Imported from ../bash-1.14.7.tar.gz.

This commit is contained in:
Jari Aalto 1996-08-26 18:22:31 +00:00
commit 726f63884d
402 changed files with 150297 additions and 0 deletions

1
.distribution Normal file
View file

@ -0,0 +1 @@
1.14

1
.patchlevel Normal file
View file

@ -0,0 +1 @@
7

257
COPYING Normal file
View file

@ -0,0 +1,257 @@
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
The Free Software Foundation has exempted Bash from the requirement of
Paragraph 2c of the General Public License. This is to say, there is
no requirement for Bash to print a notice when it is started
interactively in the usual way. We made this exception because users
and standards expect shells not to print such messages. This
exception applies to any program that serves as a shell and that is
based primarily on Bash as opposed to other GNU software.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
that there is no warranty (or else, saying that you provide a
warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this General
Public License.
d) You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
That's all there is to it!

18
CWRU/PLATFORMS Normal file
View file

@ -0,0 +1,18 @@
The version of bash in this directory has been compiled on the
following systems:
Sun 690 SunOS 4.1.2
Sparcstation SunOS 5.3
Sparcstation NetBSD 0.9a
386 BSDI BSD/386 1.0, 1.1
NeXTstation NeXT OS 2.1
IBM RT IBM/4.3 (AOS)
Motorola Delta 88K SVR3.2
Decstation 3100 Ultrix 4.3
Dec 4000 Alpha AXP DEC OSF/1 V1.3
386 ISC UNIX 3.0.1
386 FreeBSD 1.1
IBM RS/6000 AIX 3.2
Amiga Amiga UNIX 2.1
Sony NEWS 841 NEWS OS
HP 9000/834 HP/UX 7.0

63
CWRU/POSIX.NOTES Normal file
View file

@ -0,0 +1,63 @@
Starting bash with the `-posix' command-line option or setting the variable
POSIXLY_CORRECT while bash is running will cause bash to conform more
closely to the Posix.2 standard by changing the behavior to match that
specified by Posix.2 in areas where the bash default differs.
The following list is what's changed when `posixly_correct' is enabled:
1. When a command in the hash table no longer exists, bash will re-search
$PATH to find the new location.
2. The >& redirection does not redirect stdout and stderr.
3. The message printed by the job control code and builtins when a job
exits with a non-zero status is `Done(status)'.
4. The <> redirection does not open a file for both stdin and stdout, but
rather opens it for read-write on fd 0.
5. Reserved words may not be aliased.
6. The Posix.2 PS1 and PS2 expansions of `!' -> history number and `!!' -> `!'
are enabled.
7. Interactive comments are enabled by default. (Note that this version has
them on by default anyway.)
8. The Posix.2 startup files are executed ($ENV) rather than the normal bash
files.
9. Tilde expansion is only performed on assignments preceding a command name,
rather than on all assignment statements on the line.
10. The default history file is ~/.sh_history (default value of $HISTFILE).
11. The output of `kill -l' prints all the signal names on a single line,
separated by spaces.
12. Non-interactive shells exit if `file' in `. file' is not found.
13. Redirection operators do not perform pathname expansion on the word
in the redirection unless the shell is interactive
14. Function names must be valid shell identifiers. That is, they may not
contain characters other than letters, digits, and underscores, and
may not start with a digit
There is other Posix.2 behavior that bash does not implement. Specifically:
1. There are no `special builtins' and `regular builtins'. All builtins
are equivalent. This means that:
o assignment statements affect the execution environment of all
builtins, not just special ones
o temporary assignments do not persist after Posix.2 special
builtins complete
o Functions are found before Posix.2 special builtins
o The shell does not exit upon errors while executing Posix.2
special builtins
2. $LINENO does not represent the line number of a command within a function
3. The arithmetic evaluator does not implement the `e ? e1 : e2' conditional
expression

26
CWRU/README Normal file
View file

@ -0,0 +1,26 @@
Notes:
ISC 386 machines must compile test.c without -O. The resultant shell dumps
core when test is invoked.
There have been reports that SCO 3.2v4.2 requires -DPRGP_PIPE in SCO_CFLAGS,
and that it has too many -D defines for SCO's cc (rcc works).
Contents of this directory:
CWRU.chlog - my change log since the last release
KSH.README - list of similarities with ksh. Slightly out of date
PLATFORMS.113 - list of platforms I have built this release on
POSIX.NOTES - list of what changes for `posix mode'
README - this file
RSH.README - explanation of the bash `restricted shell' mode
misc - directory with some useful tools
OS-BUGS - directory with messages detailing some OS bugs and
the bash workarounds

786
CWRU/changelog Normal file
View file

@ -0,0 +1,786 @@
6/2
---
lib/readline/readline.c
- fixed an off-by-one error in the kill ring reallocation code
in rl_kill_text
Makefile
- replaced instances of /bin/sh with $(SHELL)
Makefile, cpp-Makefile, documentation/Makefile
- added a working `uninstall' target
[1.14.0 FCS release made available for FTP]
6/3
---
README
- added note about building with gcc, same as in Makefile
documentation/Makefile
- some versions of make don't understand `$*' in a regular recipe;
replace with features.dvi in the recipe for features.ps
6/4
---
subst.c
- fix up the calls to string_extract_double_quoted and
string_extract_single_quoted in char_is_quoted so the initial
value of the index is *after* the opening quote character
- make sure we only return 1 from char_is_quoted if the index
into the string after a call to string_extract_double_quoted or
string_extract_single_quoted is *greater than* `eindex'
lib/readline/complete.c
- change the order and sense of the quoting tests in
rl_complete_internal so that the expensive char_is_quoted
is only called if `scan' actually is a word break character
shell.c
- fixed a typo in the test for a restricted shell
builtins/exec.def
- need to include flags.h
6/6
---
make_cmd.c
- make sure that we don't try to walk down a null command tree
in connect_async_list (tickled by `(command &) &')
- if a command has the CMD_WANT_SUBSHELL bit set in its flags,
don't even try to walk the command tree and move the `&';
just connect the command with a null command using `&'
execute_cmd.c
- make sure we don't try to reference a command struct without
first checking it (case '&')
6/7
---
machines.h
- fix a typo in the NeXT/i386 description; change the NeXT description
to #define HAVE_RESOURCE if not already defined rather than putting
-DHAVE_RESOURCE into the SYSDEP_CFLAGS
6/9
---
Makefile
- make sure all of the rules that reinvoke `make' have the
`-f bash-Makefile' before the assignment statements; some
versions of make like it that way
variables.c
- make sure that `interactive' is set to 0 before evaluating the
string containing an exported function obtained from the
environment, so that it does not try to execute PROMPT_COMMAND
(this may not be the best fix)
6/13
----
documentation/Makefile
- make sure all of the directories exist before trying to install
doc files into them
lib/readline/history.c
- add a missing O_TRUNC to the open call for writing in
history_truncate_file
trap.c
- run_interrupt_trap should only try to run the trap command if
the value is not IMPOSSIBLE_TRAP_HANDLER
Makefile
- add `realclean'
lib/readline/complete.c
- do the same kind of double-quoting a replacement string if the
user supplies the opening double quote as we would if we were
adding both quotes ourselves
variables.c
- fixed the variable initialization so that history_control/HISTCONTROL
can be inherited from a parent shell
INSTALL, README, cpp-Makefile, documentation/bash.1, documentation/readline.3
- ai.mit.edu -> prep.ai.mit.edu
shell.c
- fixed a problem with setting no_line_editing to the result of the
check for running inside emacs, thereby losing any value
initialized by the `-nolineediting' flag
cpp-Makefile
- `make distclean' will now remove the `installed-bash' link
print_cmd.c
- fixed a problem with undefined variables when HAVE_VARARGS_H is
not defined
6/14
----
lib/readline/history.c
- fixed an error in the csh history expansion code so that the
`-y' word designator now expands to `0-y' rather than `1-y'
lib/readline/isearch.c
- changed an absolute check for a character falling within the
ASCII 32-126 range (printable chars) with checks for CTRL_P
and META_CHAR and a check against the value RUBOUT
- changed a `break' to a `continue' so that the first non-matching
character in the search string does not cause the search to
end abruptly
- initialize prev_line_found to 0 at the top of rl_search_history
to avoid duplicate history lines being saved across searches
lib/readline/rltty.c
- consolidated repeated code for setting special characters into
`SET_SPECIAL' defines
lib/readline/readline.c
- include <sys/ioctl.h> if VSTATUS is defined
- add bindable command rl_tty_status (unbound by default)
lib/readline/funmap.c
- assign bindable command name `tty-status' to rl_tty_status
INSTALL
- add note about compiling with gcc, same text as README
lib/readline/display.c
- many changes and tweaks to make redisplay work better when the
prompt has invisible characters. These changes are non-optimal
in that the prompt is redrawn more than it needs to be, but
things are a hell of a lot better than they were
6/15
----
documentation/Makefile
- make a variable NROFF that people can set to `groff -Tascii' if
they don't have real nroff
- changed the suffix rules to use $<
support/bashbug.sh
- if rmail doesn't exist or fails, save the bug report in
~/dead.bashbug
execute_cmd.c
- in setup_async_signals, only ignore SIGINT and SIGQUIT if job
control is not active. If it is active and the job is restarted,
SIGINT remains ignored, and the now-foregrounded job is not
interruptible
subst.c
- fixed up a problem with char_is_quoted that caused backslash-
escaped characters to cause incorrect results
tests/run-dollars, tests/dollar-at.sh, tests/dollar-star.sh
- since the error messages produced by `cat' vary, changed `cat'
to `recho' and updated the correct answers file
machines.h
- fixes to CRAY_STACKSEG_END definitions for different versions of
Unicos on the YMP (from Bill Jones)
- Motorola SVR4 machines have getcwd() and should not undef
HAVE_GETCWD
- on hpux 9.x, don't try to link with -lPW if compiling with gcc
(for alloca)
parse.y
- an ugly fix for a compiler problem with structure assignment on
the cray
6/16
----
builtins/wait.def
- replaced a call to sscanf with a validity check using all_digits()
and a call to atoi, since a pid_t is not necessarily an int, and
the sscanf clobbered the stack frame on systems where it is shorter
than an int (e.g., SCO)
lib/readline/display.c
- since META_CHAR and the other macros only work with unsigned
chars, make rl_character_len convert its argument to an unsigned
char before testing it
documentation/Makefile
- use $(INSTALL_DATA) instead of $(CP) to install the man pages and
info files
cpp-Makefile
- use INSTALL_PROGRAM and INSTALL_DATA to install binaries and
documentation; pass both values to installs in subdirectories
6/18
----
builtins/ulimit.def
- compensate for systems which define RLIMIT_OFILE instead of
RLIMIT_NOFILE, or don't provide such a compatibility define
themselves
shell.c
- make maybe_execute_file check for directories and print an
appropriate error message, since it's doing an fstat anyway
support/mksysdefs
- added support for a `-s srcdir' option so it can find
cpp-Makefile if ansi-Makefile is to be created
Makefile
- call mksysdefs with -s $(srcdir)
jobs.c
- add the magic #undef lines to avoid redefinition warnings on
SunOS 4 only
6/20
----
cpp-Makefile
- install `bashbug' with `make install'
trap.c
- make sure that `interactive' is set to 0 when running trap
commands
builtins/umask.c
- fixed typo in usage error message
subst.c
- fix process_substitute to set subshell_environment
jobs.c, nojobs.c
- only mess with the terminal settings for an interactive shell
that is not in a subshell environment
6/21
----
lib/readline/history.h
- add extern declaration of history_get
builtins/fc.def
- make history replacement when using `r' or `fc -s' obey the
setting of HISTCONTROL
general.c
- in canonicalize_pathname, preserve a double // at the start
of an absolute pathname, since that means something special
for the network directory system
README, INSTALL
- updated information about submitting bug reports
lib/readline/vi_mode.c, lib/readline/isearch.c
- make sure unistd.h is included before rldefs.h, if
HAVE_UNISTD_H is defined
6/24
----
lib/readline/complete.c
- add `#' to the list of characters which cause a completed filename
to be quoted
execute_cmd.c
- be more careful about closing pipe file descriptors in do_piping;
don't want to have `dup2(i, i); close(i);' problem
lib/readline/{keymaps,readline}.h
- include local copies of include files if READLINE_LIBRARY is
defined, otherwise include the `official, installed' versions
using #include <readline/xxx.h>
lib/readline/*.c
- define READLINE_LIBRARY before including any files
- include only `local' copies of include files using #include "xxx.h"
rather than #include <readline/xxx.h>
6/26
----
execute_cmd.c
- check for clobbering the bash input stream before closing a file
descriptor due to an r_close_this redirection
lib/readline/history.c
- made history_expand inhibit history expansion if the history
expansion char is set to 0
lib/readline/chardefs.h
- moved savestring() definition to rldefs.h
- changed lowercase_p, uppercase_p, to_lower, to_upper defines to
use <ctype.h> macros rather than assume ASCII
lib/readline/bind.c, general.c, general.h
- use strcasecmp, strncasecmp instead of str[n]icmp if
HAVE_STRCASECMP is defined
cpp-Makefile
- pass -DHAVE_STRCASECMP to builds in the libraries, primarily
readline
machines.h
- add HAVE_STRCASECMP to the entries for BSD/386, NetBSD, FreeBSD,
and 4.4 BSD
builtins/hash.def
- add a fourth parameter to remember_filename, the initial value
of times_found (0 if we're just looking it up for `hash', 1
for the command execution code)
execute_cmd.c
- call remember_filename with an initial value of 1 for times_found
builtins/wait.def
- handle a null argument with an error message
builtins/common.c
- parse_and_execute now takes a third parameter: the value for
`interactive' while it is executing commands
bashline.c, jobs.c, parse.y, shell.c, subst.c, trap.c, variables.c
- set the new third argument to parse_and_execute appropriately
builtins/eval.def, builtins/fc.def, builtins/source.def
- set the new third argument to parse_and_execute appropriately
builtins/help.def
- changed a call to strnicmp to strncmp when trying to find what
to give help on; it seems more correct
6/27
----
machines.h
- cleaned up the SunOS section so it no longer relies on
HAVE_SHARED_LIBS being defined; it uses SunOS4 and SunOS5
instead
support/mksysdefs
- define SYSDEF to be SunOS4 or SunOS5 depending on the output
of uname rather than looking for ld.so
6/29
----
machines.h
- minor change to the ardent titan machine description
- move the ardent and stardent descriptions before the
mips riscos description
print_cmd.c
- ardent machines also need the extern declaration for printf
make_cmd.c
- connect_async_list should do its work only if the lists to be
backgrounded are connected with `;'. This makes `;' bind tighter
than `&', so only the last job in the list is backgrounded. All
other lists should have the entire thing put in the background
parse.y
- added a function `print_prompt' to take care of displaying the
prompt string if readline is not being used. This fixes problems
with the prompt being displayed before the status of completed
jobs is printed
6/30
----
builtins/fg_bg.def
- `fg' and `bg' now print error messages if invoked when job control
is disabled
lib/readline/rltty.c
- if not compiled into the shell, make get_tty_settings get and set
the window size. This noop stops the process if it is started in
the background
lib/readline/readline.c
- provide a function version of savestring, if not being compiled
into the shell, since the macro has been removed from the
`public' header files
lib/readline/readline.h
- provide all extern function declarations without checking whether
VI_MODE or PAREN_MATCHING are defined. It does not hurt to define
them if they are not used and not in the library, and other
applications using readline can't tell whether or not VI_MODE was
defined when the library was compiled anyway
7/1
---
machines.h
- add #undef HAVE_DIRENT_H to the ardent titan description
7/2
---
lib/readline/chardefs.h
- removed META_P define, renamed CTRL_P to CTRL_CHAR
lib/readline/bind.c, lib/readline/isearch.c
- changed instances of CTRL_P to CTRL_CHAR
lib/readline/search.c
- include <unistd.h> before rldefs.h, if HAVE_UNISTD_H is defined
lib/readline/readline.c
- declare PC, UP, and BC as extern rather than `local' to the
readline library
7/5
---
bashline.c
- implement command word completion inside of command substitution
with a new function: `command_subst_completion_function'
subst.c
- new function to help with command subst completion: unclosed_pair
lib/readline/complete.c
- new variable rl_filename_quoting_desired, which can be set to 0
to inhibit the quoting of filenames after completion
lib/readline/readline.h
- declare rl_filename_completion_desired and
rl_filename_quoting_desired
builtins/bind.def
- don't save the old value of rl_outstream before initializing
readline -- it saves garbage values and screws up readline
parse.y
- don't have private state telling whether or not readline has
been initialized -- use bash_readline_initialized like other
functions in bashline.c
lib/readline/readline.c
- make the default 8-bit behavior be based on whether LC_CTYPE is
defined and its value (accept iso-8859-1 or iso_8859_1)
7/6
---
variables.c
- fix up the declaration of getenv() for convex machines
7/7
---
lib/readline/readline.c
- fixed up typos in the declaration of `savestring'
lib/readline/history.c
- fixed an off-by-one error in the ADD_CHAR macro which caused one
extra character to be overwritten, causing the gnu malloc to abort
when that one character was at the end of an allocated block
- changed the ADD_STRING macro to avoid some unnecessary xreallocs
lib/readline/display.c
- fixed a problem with move_cursor_relative -- function now returns
immediately if it has nothing to do
- fixed another problem with displaying prompts with invisible chars
lib/readline/chardefs.h
- fixed the CTRL macro to be right (agree with the BSD kernel, for
example)
cpp-Makefile
- fixed typo in the `install' recipe
7/8
---
support/srcdir
- fixed to handle srcdir when it begins with ./ or ../ to handle
$(srcdir) being a relative path better
cpp-Makefile
- changed some include paths to $(BUILTIN_ABSSRC) when building in
`builtins' to handle $(srcdir) being a relative path
- change the `chmod' on bashbug to turn on read and execute for all
- added a couple of definitions to make it easier for a later
`configure' program
support/mksysdefs
- added a -i option to specify an alternate set of directories to
search for include files
lib/readline/bind.c
- in rl_read_init_file, when skipping whitespace at the start of
the line, decrement `i' so that we don't jump past the start
of the next line
machines.h
- SCOv4 has a `robust' opendir that checks that you're actually
opening a directory
7/11
----
lib/readline/complete.c
- make sure a word break character is unquoted before using it to
separate out the current word for completing
machines.h
- new machine description: NetBSD on motorola m68k machines like
the hp300
- undef HAVE_GETWD in the generic svr4 machine description, like
other svr4 descriptions
lib/readline/rltty.c
- make sure to fflush (rl_outstream) after toggling the setting
of the keypad and meta key
portbash/libc.sh
- add a test for OPENDIR_NOT_ROBUST
support/getcppsyms.c
- output __svr4__ if we find __uxps__ (this makes the Fujitsu port of
SVR4 to the sparc build OK)
7/12
----
lib/readline/display.c
- more display-related fixes when the prompt has invisible chars;
this time for screen updates when moving between screen lines
lib/readline/readline.c, lib/readline/display.c
- changes to make readline work with terminals that have auto-wrap
from Per Bothner (new function _rl_update_final, term_xn changes,
some efficiency speedups, new function space_to_eol)
7/13
----
lib/readline/display.c
- after moving up screen lines using term_up in _rl_move_vert, if
the new screen line is 0, _rl_last_c_pos needs to be adjusted
to take invisible characters into account. This was the source
of many bugs
7/14
----
documentation/Makefile
- change instances of `groff' to `${GROFF}', GROFF is set to
`groff' by default
general.c, variables.c
- moved `qsort_string_compare' from variables.c to general.c
general.h, variables.h
- moved declaration of `qsort_string_compare' from variables.h
to general.h
alias.c, lib/readline/funmap.c
- moved qsort auxiliary functions after their use and added
forward declarations to avoid warnings from ANSI C compilers
memalloc.h
- hpux_9 needs alloca declared as `extern void *' if __STDC__
is defined
support/mksysdefs
- removed HAVE_SHARED_LIBS entirely
- make a call to /bin/uname -X for SCO machines to avoid running
a different uname from the $PATH
machines.h
- new descriptions: Intel i860 running SVR4, Tahoe running 4.3 BSD
- changed descriptions: Mips/RiscOS, DG AViiON, unknown machine
jobs.c
- changes to how the shell handles foreground jobs dying of SIGINT:
an interactive shell using job control will no longer
act as if it received a SIGINT if the foreground job
dies from a SIGINT
a non-interactive shell or shell without job control tries
to differentiate between SIGINTs it has seen (in
wait_sigint_handler) and a foreground job dying of a SIGINT
not sent from the keyboard, and runs the normal SIGINT code
only in the former case
7/15
----
support/mksysdefs
- check for ${UNAME}${RELEASE} expanding to `SunOS4*' or `SunOS5*'
to set SYSDEF to SunOS4 or SunOS5, respectively. Apparently
this does not work for Solbourne
7/18
----
lib/readline/rltty.c
- if output is being flushed on termios systems, loop until the
FLUSHO bit is no longer set in the termios struct
support/mksysdefs
- added a -A flag to force creation of ansi-Makefile
machines.h
- new entry for Tandem machines running SVR3
7/19
----
lib/readline/rldefs.h
- include <termcap.h> if HAVE_TERMCAP_H is defined
- use <termio.h> stuff if HAVE_TERMIO_H is defined and _POSIX_VERSION
is not defined
lib/readline/rldefs.h, lib/readline/history.c
- include "config.h" if HAVE_CONFIG_H is defined
lib/readline/{rldefs.h,signals.c,readline.c}
- WINSIZE_IN_IOCTL_H -> GWINSZ_IN_SYS_IOCTL for compatibility with
other GNU programs
lib/readline/doc/Makefile
- fixed up to create the readline and history manuals in dvi and
ps format
lib/readline/Makefile
- changes inspired by the standalone readline-2.0 distribution
7/20
----
lib/readline/history.c
- new function, history_is_stifled (), returns history_stifled
- set history_state flags member in the history state functions
lib/readline/history.h
- reorganized the function declarations, added missing declarations
- history_stifled is no longer exported by the library
- added a `flags' member to the HISTORY_STATE structure
bashline.c
- use history_is_stifled () instead of history_stifled
lib/readline/readline.c, lib/readline/vi_mode.c
- filled in correct argument declarations for functions called via
keymaps (count, key)
lib/readline/complete.c
- efficiency improvement for compare_strings
7/21
----
examples/dirfuncs
- new directory functions from ksh book, contributed by
Ken Konecki (kenk@wfg.com)
machines.h
- hpux_8 and hpux_9 should both #undef HAVE_ALLOCA unless gcc is
being used
7/22
----
bashline.c
- fixed up command_word_completion_function so that filenames with
leading tildes are completed correctly
7/26
----
builtins/read.def
- if -r not given, make sure CTLESC is removed from input string
when reading \<newline>
lib/readline/readline.c
- new function bind_arrow_keys, which binds vt100/ansi arrow key
escape sequences after reading the termcap definition and the
inputrc file
- new function rl_yank_last_arg, which does what insert-last-arg
does in bash
lib/readline/emacs_keymap.c
- remove default bindings to rl_arrow_keys for M-[ and M-O
- rl_yank_last_arg is now bound to `M-.' and `M-_' in
emacs_meta_keymap
subst.c
- when performing process substitution on systems with /dev/fd,
make sure the child clears the slot in dev_fd_list it gets
from its parent so the file descriptor does not get closed
inappropriately if reallocated by, e.g., pipe(2)
bashline.c
- removed insert_last_arg and the calls to bind in to `M-.' and `M-_'.
`insert-last-argument' is now bound to rl_yank_last_arg for
backwards compatibility
lib/readline/funmap.c
- `yank-last-arg' is now a named command for rl_yank_last_arg
documentation/bash.1, documentation/readline.3
- add description of yank-last-arg as one of the readline user
commands
lib/readline/doc/rluser.texinfo
- added description of yank-last-arg
builtins/getopts.def
- fixed a typo in the int-to-string code computing the value to set
OPTIND to: had '\0' instead of '0'
- made getopts handle the case where there are more than 9 dollar
variables (where rest_of_args is non-null) correctly
7/28
----
lib/readline/display.c
- fixes to the display code for single-line-display in the presence
of prompts containing invisible characters
lib/readline/readline.c
- if we are using horizontal scrolling and we have term_xn, decrement
the screenwidth by 1, since we won't be doing any line wrapping
7/31
----
jobs.c
- new variable `freeze_jobs_list' to set when changes to the jobs
list or status of jobs in the list (other than calling something
like `jobs -n') are undesirable. This is set when execuing traps
on SIGCHLD
8/1
---
subst.c
- check that `~' is unquoted before performing tilde expansion in
an assignment statement
8/3
---
bracecomp.c
- keep brace completion from dumping core if there is only one
match
lib/readline/chardefs.h
- add a define for digit_p, which returns the value of isdigit()
lib/readline/readline.c
- added function equivalents for uppercase_p, lowercase_p, to_upper,
to_lower, pure_alphabetic, digit_p, and digit_value
- replaced calls to numeric () with calls to digit_p, removed
definition of numeric ()
lib/readline/history.c
- digit -> digit_p
lib/readline/vi_mode.c
- replaced uses of the `isletter' define to use pure_alphabetic
from chartypes.h
- replaced uses of `numeric' with calls to digit_p
- added do...while(0) to `exchange' define
8/4
---
execute_cmd.c
- make sure execute_function saves and restores the current loop
count with unwind_protect_int
documentation/features.texi
- change the `Shell Command Line Options' section to `Invoking
Bash' to be closer to the GNU coding standards
8/5
---
builtins/read.def
- fixed up a memory leak and made behavior correct when no
variables given and backslash escaped at least one input char
- if we added CTLESC anywhere while reading the input string,
make sure we call dequote_string on each word of the input
before calling bind_variable with that string
subst.c
- made an efficiency improvement to dequote_string -- don't
do anything when we see CTLESC, just `continue' the loop

20
CWRU/misc/aux-mach-desc Normal file
View file

@ -0,0 +1,20 @@
/* ************************ */
/* */
/* A/UX 3.0 System */
/* */
/* ************************ */
#if defined (mc68k32) && !defined (M_MACHINE)
# define M_MACHINE "Macintosh"
# define M_OS "AUX"
# define SYSDEP_CFLAGS -ZP -DUSG -DHAVE_BCOPY -DHAVE_UID_T -DNSIG=32 \
-DHAVE_GETDTABLESIZE
# define SYSDEP_LDFLAGS -ZP
# define HAVE_DIRENT
# define HAVE_POSIX_SIGNALS
# define HAVE_VFPRINTF
# define VOID_SIGHANDLER
# define HAVE_GETGROUPS
# undef HAVE_RESOURCE
# undef HAVE_ALLOCA
# define REQUIRED_LIBRARIES -lc_s
#endif /* A/UX */

7
CWRU/misc/bison Executable file
View file

@ -0,0 +1,7 @@
#! /bin/sh
if [ "$1" = '-y' ]; then
shift
fi
exec /usr/bin/yacc ${1+"$@"}

16
CWRU/misc/open-files.c Normal file
View file

@ -0,0 +1,16 @@
#include <sys/types.h>
#include <fcntl.h>
#include <sys/file.h>
#include <stdio.h>
main()
{
register int i;
for (i = 0; i < getdtablesize(); i++) {
if (fcntl(i, F_GETFD, 0) != -1)
fprintf(stderr, "fd %d: open\n", i);
}
exit(0);
}

7
CWRU/misc/pid.c Normal file
View file

@ -0,0 +1,7 @@
#include <stdio.h>
main()
{
fprintf(stderr, "%d\n", getpid());
exit(0);
}

27
CWRU/misc/sigs.c Normal file
View file

@ -0,0 +1,27 @@
#include <signal.h>
#include <stdio.h>
extern char *sys_siglist[];
typedef void sighandler();
main(argc, argv)
int argc;
char **argv;
{
register int i;
sighandler *h;
for (i = 1; i < NSIG; i++) {
h = signal(i, SIG_DFL);
if (h != SIG_DFL) {
if (h == SIG_IGN)
fprintf(stderr, "%d: ignored (%s)\n", i, sys_siglist[i]);
else
fprintf(stderr, "%d: caught (%s)\n", i, sys_siglist[i]);
}
}
exit(0);
}

206
CWRU/misc/sigstat.c Normal file
View file

@ -0,0 +1,206 @@
/*
* sigstat - print out useful information about signal arguments
*
*/
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
extern char *strrchr();
static char *signames[NSIG];
char *progname;
void sigstat();
main(argc, argv)
int argc;
char **argv;
{
register int i;
char *t;
if (t = strrchr(argv[0], '/'))
progname = ++t;
else
progname = argv[0];
init_signames();
if (argc == 1) {
for (i = 1; i < NSIG; i++)
sigstat(i);
exit(0);
}
for (i = 1; i < argc; i++)
sigstat(atoi(argv[i]));
exit(0);
}
void
sigstat(sig)
int sig;
{
struct sigaction oact;
char *signame;
sigset_t set, oset;
int blocked;
if (sig < 0 || sig >= NSIG) {
fprintf(stderr, "%s: %d: signal out of range\n", progname, sig);
return;
}
signame = signames[sig];
sigemptyset(&oset);
sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &oset);
if (sigismember(&oset, sig))
printf("%s: signal is blocked\n", signame);
sigaction(sig, (struct sigaction *)NULL, &oact);
if (oact.sa_handler == SIG_IGN)
printf("%s: signal is ignored\n", signame);
else if (oact.sa_handler == SIG_DFL)
printf("%s: signal is defaulted\n", signame);
else
printf("%s: signal is trapped (?)\n", signame);
}
init_signames()
{
register int i;
bzero(signames, sizeof(signames));
#if defined (SIGHUP) /* hangup */
signames[SIGHUP] = "SIGHUP";
#endif
#if defined (SIGINT) /* interrupt */
signames[SIGINT] = "SIGINT";
#endif
#if defined (SIGQUIT) /* quit */
signames[SIGQUIT] = "SIGQUIT";
#endif
#if defined (SIGILL) /* illegal instruction (not reset when caught) */
signames[SIGILL] = "SIGILL";
#endif
#if defined (SIGTRAP) /* trace trap (not reset when caught) */
signames[SIGTRAP] = "SIGTRAP";
#endif
#if defined (SIGABRT) /* */
signames[SIGABRT] = "SIGABRT";
#endif
#if defined (SIGIOT) /* IOT instruction */
signames[SIGIOT] = "SIGIOT";
#endif
#if defined (SIGEMT) /* EMT instruction */
signames[SIGEMT] = "SIGEMT";
#endif
#if defined (SIGFPE) /* floating point exception */
signames[SIGFPE] = "SIGFPE";
#endif
#if defined (SIGKILL) /* kill (cannot be caught or ignored) */
signames[SIGKILL] = "SIGKILL";
#endif
#if defined (SIGBUS) /* bus error */
signames[SIGBUS] = "SIGBUS";
#endif
#if defined (SIGSEGV) /* segmentation violation */
signames[SIGSEGV] = "SIGSEGV";
#endif
#if defined (SIGSYS) /* bad argument to system call */
signames[SIGSYS] = "SIGSYS";
#endif
#if defined (SIGPIPE) /* write on a pipe with no one to read it */
signames[SIGPIPE] = "SIGPIPE";
#endif
#if defined (SIGALRM) /* alarm clock */
signames[SIGALRM] = "SIGALRM";
#endif
#if defined (SIGTERM) /* software termination signal from kill */
signames[SIGTERM] = "SIGTERM";
#endif
#if defined (SIGCLD) /* Like SIGCHLD. */
signames[SIGCLD] = "SIGCLD";
#endif
#if defined (SIGPWR) /* Magic thing for some machines. */
signames[SIGPWR] = "SIGPWR";
#endif
#if defined (SIGPOLL) /* For keyboard input? */
signames[SIGPOLL] = "SIGPOLL";
#endif
#if defined (SIGURG) /* urgent condition on IO channel */
signames[SIGURG] = "SIGURG";
#endif
#if defined (SIGSTOP) /* sendable stop signal not from tty */
signames[SIGSTOP] = "SIGSTOP";
#endif
#if defined (SIGTSTP) /* stop signal from tty */
signames[SIGTSTP] = "SIGTSTP";
#endif
#if defined (SIGCONT) /* continue a stopped process */
signames[SIGCONT] = "SIGCONT";
#endif
#if defined (SIGCHLD) /* to parent on child stop or exit */
signames[SIGCHLD] = "SIGCHLD";
#endif
#if defined (SIGTTIN) /* to readers pgrp upon background tty read */
signames[SIGTTIN] = "SIGTTIN";
#endif
#if defined (SIGTTOU) /* like TTIN for output if (tp->t_local&LTOSTOP) */
signames[SIGTTOU] = "SIGTTOU";
#endif
#if defined (SIGIO) /* input/output possible signal */
signames[SIGIO] = "SIGIO";
#endif
#if defined (SIGXCPU) /* exceeded CPU time limit */
signames[SIGXCPU] = "SIGXCPU";
#endif
#if defined (SIGXFSZ) /* exceeded file size limit */
signames[SIGXFSZ] = "SIGXFSZ";
#endif
#if defined (SIGVTALRM) /* virtual time alarm */
signames[SIGVTALRM] = "SIGVTALRM";
#endif
#if defined (SIGPROF) /* profiling time alarm */
signames[SIGPROF] = "SIGPROF";
#endif
#if defined (SIGWINCH) /* window changed */
signames[SIGWINCH] = "SIGWINCH";
#endif
#if defined (SIGLOST) /* resource lost (eg, record-lock lost) */
signames[SIGLOST] = "SIGLOST";
#endif
#if defined (SIGUSR1) /* user defined signal 1 */
signames[SIGUSR1] = "SIGUSR1";
#endif
#if defined (SIGUSR2) /* user defined signal 2 */
signames[SIGUSR2] = "SIGUSR2";
#endif
#if defined (SIGMSG) /* HFT input data pending */
signames[SIGMSG] = "SIGMSG";
#endif
#if defined (SIGPWR) /* power failure imminent (save your data) */
signames[SIGPWR] = "SIGPWR";
#endif
#if defined (SIGDANGER) /* system crash imminent */
signames[SIGDANGER] = "SIGDANGER";
#endif
#if defined (SIGMIGRATE) /* migrate process to another CPU */
signames[SIGMIGRATE] = "SIGMIGRATE";
#endif
#if defined (SIGPRE) /* programming error */
signames[SIGPRE] = "SIGPRE";
#endif
#if defined (SIGGRANT) /* HFT monitor mode granted */
signames[SIGGRANT] = "SIGGRANT";
#endif
#if defined (SIGRETRACT) /* HFT monitor mode retracted */
signames[SIGRETRACT] = "SIGRETRACT";
#endif
#if defined (SIGSOUND) /* HFT sound sequence has completed */
signames[SIGSOUND] = "SIGSOUND";
#endif
for (i = 0; i < NSIG; i++)
if (signames[i] == (char *)NULL) {
signames[i] = (char *)malloc (16);;
sprintf (signames[i], "signal %d", i);
}
}

15
CWRU/sh-redir-hack Normal file
View file

@ -0,0 +1,15 @@
Add to `subshell' production in parse.y and recompile -DREDIRECTION_HACK to
get `< xx (command)' sh compatibility.
| redirections '(' list ')'
{
#if defined (REDIRECTION_HACK)
/* XXX - C News sh compatibility hack - XXX */
$3->redirects = $1;
$3->flags |= CMD_WANT_SUBSHELL;
$$ = $3;
#else
yyerror ();
YYABORT;
#endif
}

212
INSTALL Normal file
View file

@ -0,0 +1,212 @@
File: bash.info, Node: Install, Next: Invoke, Prev: Built-in, Up: Top
Installing BASH
***************
To install BASH you simply type `make'. The BASH `Makefile' tries
to dynamically figure out what kind of machine and operating system
you are using. It makes an educated guess based on the information
it finds.
During the `make' process, a message is displayed describing what
machine and operating system has been chosen for you. This
information is also saved in the file `.machine' so you can look at
it later.
Therefore, for most machines, simply follow this simple checklist
to install BASH:
1. Type `make'. If you want to use GCC to compile bash, type
`make CC=gcc CPPNAME='$(CC) -E''.
2. Wait for the compilation to finish.
3. Type `./bash' to see if the compile worked.
4. Type `make install prefix=/usr/gnu/' (or the appropriate root
of your local GNU software installation tree) to copy bash to
your binaries directory, assumed to be ${prefix}/bin. This will
also attempt to install the manual pages under ${prefix}/man
and the info file under ${prefix}/info.
* Menu:
* Problems:: What to do if BASH doesn't install quite so easily.
* Files:: Files used in the `make' process.
* Porting:: Porting BASH to a new machine.
* Bugs:: What to do if you Discover Bugs in BASH.
File: bash.info, Node: Problems, Next: Files, Prev: Install, Up: Install
What if it Doesn't Install so Easily?
=====================================
Sometimes BASH gets confused and will make the wrong assumptions
about your machine or operating system. If the displayed
information (also found in `.machine') is incorrect, you will have
to edit the file `machines.h' and provide the appropriate
information so that BASH can be installed correctly. The complete
instructions for doing this are located in the `machines.h' file.
However, if BASH says that your machine type is an
"UNKNOWN_MACHINE", or BASH thought it knew something about your
machine but was wrong, then reading the next few sections could
be of use to you (*note Files::., and *note Porting::., for more
information).
On the MIPSEB with the BSD universe, you must:
1) Place /bsd43/bin in your PATH before /bin
2) Use $(CC) -E instead of /lib/cpp to build cpp-Makefile.
On SCO Xenix 386, you must:
1) Use $(CC) -E instead of /lib/cpp to build cpp-Makefile.
On Interactive Unix version 3 or 4, you must:
1) Edit cpp-Makefile to remove either -O or -g from DEBUG_FLAGS
File: bash.info, Node: Files, Next: Porting, Prev: Problems, Up: Install
Files Used in the `make' Process.
=================================
The following files are used during the installation of BASH, in
the `make' process:
`Makefile'
This is responsible for making the actual `Makefile' that is
used to create Bash. It runs the C preprocessor (usually
located in `/lib/cpp') on the file `cpp-Makefile', producing
the output file `bash-Makefile'.
`cpp-Makefile'
This is a file of C comments and text. It contains a
reasonable number of `ifdefs' which control what files get
compiled and which flags are passed to the various C files
comprising BASH. It includes files named `machines.h',
`sysdefs.h', and `config.h'.
`machines.h'
This file contains the basic compilation parameters for all of
the machines to which BASH has been ported. This file
consists of a series of conditional blocks, one per machine
type.
These conditional blocks are depend upon the unique identifier
that `cpp' has predefined for this machine. In some cases,
additional information can be passed from `Makefile'. It is
possible to pass information such as whether or not a
particular file is available on this system, and so on.
`sysdefs.h'
This file is dynamically made at build time by running the shell
script `support/mksydefs'. If there appears to be something wrong
in this file, then edit the `mksysdefs' script, and mail the
changes that you make to bash-maintainers@prep.ai.mit.edu.
`bash-Makefile'
This is the output from the initial stage of `make'. It is a
stripped down version of `cpp-Makefile' which is tailor-made
for your machine and operating system. All subsequent `makes'
use this file.
File: bash.info, Node: Porting, Next: Bugs, Prev: Files, Up: Install
What if You Have to Port to a New Machine?
==========================================
Sometimes you may want to port BASH to a new, previously
unsupported machine. To do so you need to create a block in
`machines.h' which is conditional based on a unique identifier
present in your version of the C preprocessor.
If you don't know what that symbol is, you might try the following
simple test:
echo "main () { }" > foo.c
cc -v foo.c
You are looking for `-DMACHINE', where `MACHINE' is an identifier
for your machine. If you are very unlucky and your machine's C
preprocessor doesn't have a unique identifier, you will have to
define the identifier in Makefile manually.
Let's say you have a machine from Yoyodyne Industries, called the
YoYo. It runs a version of BSD, so it is reasonably compatible.
However, the `cpp' on this YoYo machine doesn't define any unique
identifiers. You should change the `Makefile' line for `CPPFLAGS'
to:
CPPFLAGS = -P -DYoYo
Then, in `machines.h', you copy the block for `UNKNOWN_MACHINE',
and change the conditional to;
#if defined (YoYo)
Inside of the YoYo block you define `M_MACHINE="YoYo"', and
`M_OS=Bsd'. You also modify the existing defines to match your
machine's software.
If BASH still won't compile, perhaps because of missing code that
is required for your YoYo machine, you will have to write that code
and place it within a conditional block based on YoYo.
Most machines aren't that difficult; simply redefining a few of the
default values is sufficient. If you do run across a difficult
machine, please send all fixes and changes to
bash-maintainers@prep.ai.mit.edu in the form of context diffs:
diff -c orig-machines.h machines.h >machines.diffs
Please include information about which version of the shell you have.
For those machines which prove more difficult, or if you are not
sure about where to start, the scripts in the `portbash' directory
may prove helpful.
File: bash.info, Node: Bugs, Prev: Porting, Up: Install
Reporting Bugs
==============
If you find a bug in bash, you should report it. But first you
should make sure that it really is a bug and that it appears in the
latest version of BASH that is available.
Once you have ascertained that a bug really exists, you are welcome
to mail in a bug report. If you have a fix, please mail that too!
The program `bashbug' is used to submit bug reports.
Suggestions and "philosophical" bug reports should be mailed to
bug-bash@ai.mit.edu. Genuine bug reports should be mailed to the
same place, or to bash-maintainers@prep.ai.mit.edu. The `bashbug'
script sends its messages to bug-bash@prep.ai.mit.edu.
*All* bug reports should include:
* The version number of BASH.
* The hardware and operating system used.
* The compiler used to compile BASH.
* A description of the bug's behavior.
* A short script or "recipe" which demonstrates the bug.
The `bashbug' program includes much of this information
automatically. Without this information, it is generally not
possible to successfully debug BASH. Usually, without this
information, the bug won't manifest itself!
Discussion and questions about BASH in general (including
questions about this documentation) can be sent to
bash-maintainers@prep.ai.mit.edu.

421
MANIFEST Normal file
View file

@ -0,0 +1,421 @@
#
# Master distribution manifest for bash
#
#
# Filename type
#
CWRU d
CWRU/misc d
builtins d
documentation d
examples d
examples/functions d
examples/scripts d
examples/startup-files d
lib d
lib/doc-support d
lib/glob d
lib/glob/doc d
lib/malloc d
lib/malloclib d
lib/posixheaders d
lib/readline d
lib/readline/doc d
lib/readline/examples d
lib/termcap d
lib/termcap/grot d
lib/tilde d
lib/tilde/doc d
portbash d
support d
tests d
tests/misc d
README f
RELEASE f
INSTALL f
COPYING f
MANIFEST f
configure f
Makefile f
cpp-Makefile f
print_cmd.c f
general.c f
variables.c f
make_cmd.c f
copy_cmd.c f
unwind_prot.c f
dispose_cmd.c f
getcwd.c f
bashhist.c f
hash.c f
parse.y f
subst.c f
shell.c f
trap.c f
siglist.c f
version.c f
flags.c f
jobs.c f
newversion.c f
input.c f
mailcheck.c f
test.c f
expr.c f
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
signames.c f
endian.c f
alias.h f
config.h f
config.h.mini f
builtins.h f
parser.h f
variables.h f
machines.h f
jobs.h f
maxpath.h f
filecntl.h f
hash.h f
quit.h f
flags.h f
shell.h f
trap.h f
general.h f
unwind_prot.h f
input.h f
error.h f
command.h f
externs.h f
siglist.h f
subst.h f
dispose_cmd.h f
bashansi.h f
make_cmd.h f
bashhist.h f
execute_cmd.h f
bashtypes.h f
y.tab.c f
y.tab.h f
posixstat.h f
stdc.h f
ansi_stdlib.h f
memalloc.h f
parser-built f
builtins/ChangeLog f
builtins/Makefile f
builtins/alias.def f
builtins/bind.def f
builtins/break.def f
builtins/builtin.def f
builtins/cd.def f
builtins/colon.def f
builtins/command.def f
builtins/common.c f
builtins/declare.def f
builtins/echo.def f
builtins/enable.def f
builtins/eval.def f
builtins/exec.def f
builtins/exit.def f
builtins/fc.def f
builtins/fg_bg.def f
builtins/getopt.c f
builtins/getopt.h f
builtins/getopts.def f
builtins/hash.def f
builtins/hashcom.h f
builtins/help.def f
builtins/let.def f
builtins/history.def f
builtins/jobs.def f
builtins/kill.def f
builtins/mkbuiltins.c f
builtins/read.def f
builtins/reserved.def f
builtins/return.def f
builtins/set.def f
builtins/setattr.def f
builtins/shift.def f
builtins/source.def f
builtins/suspend.def f
builtins/test.def f
builtins/times.def f
builtins/trap.def f
builtins/type.def f
builtins/ulimit.def f
builtins/umask.def f
builtins/wait.def f
builtins/psize.c f
builtins/psize.sh f
builtins/inlib.def f
builtins/bashgetopt.c f
builtins/common.h f
builtins/bashgetopt.h f
lib/doc-support/texindex.c f
lib/doc-support/getopt.h f
lib/doc-support/Makefile f
lib/glob/ChangeLog f
lib/glob/Makefile f
lib/glob/fnmatch.c f
lib/glob/fnmatch.h f
lib/glob/glob.c f
lib/glob/doc/Makefile f
lib/glob/doc/glob.texi f
lib/glob/ndir.h f
lib/malloc/Makefile f
lib/malloc/alloca.c f
lib/malloc/getpagesize.h f
lib/malloc/i386-alloca.s f
lib/malloc/malloc.c f
lib/malloc/x386-alloca.s f
lib/malloc/xmalloc.c f
lib/malloclib/Makefile f
lib/malloclib/alloca.c f
lib/malloclib/i386-alloca.s f
lib/malloclib/calloc.c f
lib/malloclib/cfree.c f
lib/malloclib/x386-alloca.s f
lib/malloclib/morecore.c f
lib/malloclib/free.c f
lib/malloclib/getpagesize.h f
lib/malloclib/malloc.c f
lib/malloclib/malloc.h f
lib/malloclib/xmalloc.c f
lib/malloclib/mcheck.c f
lib/malloclib/memalign.c f
lib/malloclib/mstats.c f
lib/malloclib/mtrace.awk f
lib/malloclib/mtrace.c f
lib/malloclib/realloc.c f
lib/malloclib/valloc.c f
lib/posixheaders/posixstat.h f
lib/posixheaders/ansi_stdlib.h f
lib/posixheaders/stdc.h f
lib/posixheaders/memalloc.h f
lib/posixheaders/filecntl.h f
lib/readline/COPYING f
lib/readline/readline.c f
lib/readline/readline.h f
lib/readline/ChangeLog f
lib/readline/vi_mode.c f
lib/readline/history.h f
lib/readline/Makefile f
lib/readline/chardefs.h f
lib/readline/emacs_keymap.c f
lib/readline/keymaps.h f
lib/readline/vi_keymap.c f
lib/readline/history.c f
lib/readline/funmap.c f
lib/readline/keymaps.c f
lib/readline/xmalloc.c f
lib/readline/doc/Makefile f
lib/readline/doc/rlman.texinfo f
lib/readline/doc/rltech.texinfo f
lib/readline/doc/rluser.texinfo f
lib/readline/doc/hist.texinfo f
lib/readline/doc/hstech.texinfo f
lib/readline/doc/hsuser.texinfo f
lib/readline/examples/Makefile f
lib/readline/examples/fileman.c f
lib/readline/examples/manexamp.c f
lib/readline/examples/histexamp.c f
lib/readline/examples/Inputrc f
lib/readline/README f
lib/readline/STANDALONE f
lib/readline/search.c f
lib/readline/isearch.c f
lib/readline/rldefs.h f
lib/readline/rlconf.h f
lib/readline/parens.c f
lib/readline/rltty.c f
lib/readline/complete.c f
lib/readline/bind.c f
lib/readline/display.c f
lib/readline/signals.c f
lib/readline/doc/texindex.c f
lib/readline/tilde.c f
lib/readline/tilde.h f
lib/readline/posixstat.h f
lib/readline/ansi_stdlib.h f
lib/readline/memalloc.h f
lib/termcap/Makefile f
lib/termcap/termcap.c f
lib/termcap/termcap.h f
lib/termcap/tparam.c f
lib/termcap/version.c f
lib/termcap/grot/termcap.info f
lib/termcap/grot/termcap.info-1 f
lib/termcap/grot/termcap.info-2 f
lib/termcap/grot/termcap.info-3 f
lib/termcap/grot/termcap.info-4 f
lib/termcap/grot/NEWS f
lib/termcap/grot/INSTALL f
lib/termcap/grot/ChangeLog f
lib/termcap/grot/texinfo.tex f
lib/termcap/grot/termcap.texi f
lib/termcap/grot/Makefile.in f
lib/termcap/grot/configure f
lib/termcap/grot/configure.in f
lib/termcap/grot/COPYING f
lib/termcap/grot/README f
lib/tilde/ChangeLog f
lib/tilde/Makefile f
lib/tilde/doc/tilde.texi f
lib/tilde/doc/Makefile f
lib/tilde/tilde.c f
lib/tilde/tilde.h f
lib/tilde/memalloc.h f
CWRU/misc/open-files.c f
CWRU/misc/sigs.c f
CWRU/misc/pid.c f
CWRU/misc/sigstat.c f
CWRU/misc/bison f
CWRU/misc/aux-mach-desc f
CWRU/PLATFORMS f
CWRU/README f
CWRU/POSIX.NOTES f
CWRU/changelog f
CWRU/sh-redirection-hack f
documentation/Makefile f
documentation/bash.1 f
documentation/bash.ps f
documentation/bash.txt f
documentation/README f
documentation/readline.3 f
documentation/readline.ps f
documentation/readline.txt f
documentation/texinfo.tex f
documentation/features.texi f
documentation/features.info f
documentation/features.dvi f
documentation/features.ps f
documentation/builtins.1 f
documentation/builtins.ps f
documentation/builtins.txt f
documentation/article.ms f
documentation/article.ps f
documentation/article.txt f
support/cat-s f
support/mksysdefs f
support/printenv f
support/getcppsyms.c f
support/cppmagic f
support/bash.xbm f
support/FAQ f
support/PORTING f
support/mklinks f
support/mkdirs f
support/clone-bash f
support/bashbug.sh f
support/mkmachtype f
support/recho.c f
support/srcdir f
support/SYMLINKS f
support/fixlinks f
examples/functions/substr f
examples/functions/kshenv f
examples/functions/autoload 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/scripts/shprompt f
examples/scripts/adventure.sh f
examples/scripts/precedence f
examples/scripts/bcsh.sh f
examples/startup-files/Bashrc f
examples/startup-files/Bash_aliases f
examples/startup-files/Bash_profile f
examples/startup-files/bash-profile f
examples/startup-files/bashrc f
examples/suncmd.termcap f
examples/alias-conv.sh f
tests/README f
tests/dollar-at.sh f
tests/dollar-star.sh f
tests/dollar.right f
tests/exp-tests f
tests/exp.right f
tests/glob-test f
tests/glob.right 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/minus-e f
tests/minus-e.right f
tests/new-exp.tests f
tests/new-exp.right f
tests/prec.right f
tests/precedence f
tests/run-all f
tests/run-dollars f
tests/run-exp-tests f
tests/run-glob-test f
tests/run-ifs-tests f
tests/run-input-test f
tests/run-minus-e f
tests/run-new-exp f
tests/run-precedence f
tests/run-set-e-test f
tests/run-strip f
tests/run-varenv f
tests/set-e-test f
tests/set-e.right f
tests/strip.tests f
tests/strip.right f
tests/tilde-tests f
tests/tilde.right f
tests/varenv.right f
tests/varenv.sh f
tests/misc/chld-trap.sh f
tests/misc/dot-test-1.sh f
tests/misc/dot-test-1.sub f
tests/misc/gotest f
tests/misc/perf-script f
tests/misc/redir.t1.sh f
tests/misc/redir.t2.sh f
tests/misc/redir.t3.sh f
tests/misc/redir.t3.sub f
tests/misc/redir.t4.sh f
tests/misc/run.r1.sh f
tests/misc/run.r2.sh f
tests/misc/run.r3.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
portbash/signals.sh f
portbash/stdio.sh f
portbash/libc.sh f
portbash/mkdesc.sh f
portbash/README f
portbash/strings.sh f
portbash/syscalls.sh f
portbash/pgrp.c f

115
Makefile Normal file
View file

@ -0,0 +1,115 @@
# Hey Emacs, this Makefile is in -*- makefile -*- mode!
#
# Makefile for Bash.
# If your cpp doesn't like -P, just get rid of it (the -P, not cpp).
# If you wish to use Gcc, then type `make CC=gcc CPPNAME='$(CC) -E''.
# If you wish to use GNU's Make, then change `MAKE'.
# If you don't like the destination, then change `bindir'.
# The file that you most likely want to look at is cpp-Makefile.
#
# If you haven't read README, now might be a good time.
# Include some boilerplate Gnu makefile definitions.
prefix = /usr/local
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
srcdir = .
VPATH = $(srcdir)
# MAKE = make
RM = rm -f
SHELL = /bin/sh
GAWK = awk
# GAWK = gawk
# Force CPPNAME to be the name of your C preprocesor if Bash can't
# find it. For instance, `CPPNAME=/usr/libexec/cpp' on 4.4 BSD.
# If all else fails, set CPPNAME=$(CC) -E
CPPNAME =
CPP = `$(SHELL) $(CPPMAGIC) $(GETCPPSYMS) "$(CPPNAME)"` -P
CPP_MAKEFILE = $(srcdir)/cpp-Makefile
ANSI_MAKEFILE = ansi-Makefile
# CPPFLAGS = $(SYSTEM) $(CPP_DEFINES)
CPPFLAGS = $(CPP_DEFINES) -I. -I$(srcdir)
CPP_ARGS = -DCPP_CC="$(CC)"
SUPPORTDIR = ./support/
SUPPORTSRC = $(srcdir)/support/
MKSYSDEFS = $(SUPPORTSRC)mksysdefs
CPPMAGIC = $(SUPPORTSRC)cppmagic
CAT_S = $(SUPPORTSRC)cat-s
GETCPPSYMS = $(SUPPORTDIR)getcppsyms
GETCPPSYMS_SRC = $(SUPPORTSRC)getcppsyms.c
# Here is a command which compresses runs of multiple blank lines to a
# single blank line. "cat -s" works for BSD systems, but not for USG
# systems. You can use an awk script if you like. If you have too
# much trouble with this, just forget it. It is for making
# bash-Makefile pretty and readable; something that isn't strictly
# necessary.
# SQUASH_BLANKS = cat -s
#
SQUASH_BLANKS = $(GAWK) -f $(CAT_S)
all: .notified bash-Makefile
$(MAKE) -f bash-Makefile $(MFLAGS) $(MAKEARGS) srcdir=$(srcdir)
bash-Makefile: $(CPP_MAKEFILE) Makefile machines.h sysdefs.h config.h
@-if [ -f ansi-Makefile ]; then \
echo "cp ansi-Makefile tmp-Makefile.c"; \
cp ansi-Makefile tmp-Makefile.c; else \
echo "cp $(CPP_MAKEFILE) tmp-Makefile.c"; \
cp $(CPP_MAKEFILE) tmp-Makefile.c; \
fi
$(RM) $(GETCPPSYMS)
$(SHELL) $(SUPPORTSRC)mkdirs support
$(CC) -o $(GETCPPSYMS) $(GETCPPSYMS_SRC)
rm -f bash-Makefile
@$(SHELL) -c 'echo $(CPP) $(CPPFLAGS) $(CPP_ARGS) tmp-Makefile.c \| $(SQUASH_BLANKS) \> bash-Makefile'
@$(SHELL) -c '$(CPP) $(CPPFLAGS) $(CPP_ARGS) tmp-Makefile.c | $(SQUASH_BLANKS) >bash-Makefile'
rm -f tmp-Makefile.c
@test -s bash-Makefile || { rm -f bash-Makefile ; exit 1; }
sysdefs.h: $(MKSYSDEFS)
$(SHELL) $(MKSYSDEFS) -s $(srcdir)
# This is also performed by support/mksysdefs, but there's no way to change
# it if cpp-Makefile is changed without changing anything else, since there
# are no dependencies. This lets you run `make ansi-Makefile'.
ansi-Makefile: $(CPP_MAKEFILE)
grep -v '/\*\*/' $(CPP_MAKEFILE) > $@
# Subsequent lines contain targets that are correctly handled by an
# existing bash-Makefile.
install uninstall newversion architecture: bash-Makefile
$(MAKE) -f bash-Makefile $(MFLAGS) $(MAKEARGS) bindir=$(bindir) \
prefix=$(prefix) $@
tests DEFINES tags documentation: bash-Makefile directory-frob
$(MAKE) -f bash-Makefile $(MFLAGS) $(MAKEARGS) $@
clean distclean realclean mostlyclean maintainer-clean: bash-Makefile directory-frob
rm -f .notified
$(MAKE) -f bash-Makefile $(MFLAGS) $(MAKEARGS) $@
directory-frob:
.NOEXPORT:
.notified:
@echo ""
@echo " You are about to make this version of GNU Bash for"
@echo " this architecture for the first time. If you haven't"
@echo " yet read the README file, you may want to do so. If"
@echo " you wish to report a bug in Bash, or in the installation"
@echo " procedure, please run the bashbug script and include:"
@echo ""
@echo " * a description of the bug,"
@echo " * a recipe for recreating the bug reliably,"
@echo " * a fix for the bug if you have one!"
@echo ""
@touch .notified

10
NEWS Normal file
View file

@ -0,0 +1,10 @@
This file documents the bugs fixed between this release, bash-1.14.7,
and the last public bash release, 1.14.6.
1. Bugs fixed in Bash
a. A memory leak that caused long-running scripts to eventually consume
all available memory was fixed.
b. A sign-extension bug that caused a security hole for non-interactive
shells was fixed.

52
README Normal file
View file

@ -0,0 +1,52 @@
This README file is in -*- text -*- mode, because Emacs likes it that way.
This is GNU Bash, version 1.14. Bash is the GNU Project's Bourne
Again SHell, an interactive shell with Bourne shell syntax (/bin/sh);
but also with interactive command line editing, job control on
architectures that support it, Csh-like history features and brace
expansion, and a slew of other stuff. For more information on the
features of Bash that are new to this type of shell, see the file
`documentation/features.texi'. There is also a DVI file there, as
well as a large man page.
To compile it, try typing `make'. Bash auto-configures the build
process, so no intervention should be necessary. If you want to
use gcc, type `make CC=gcc CPPNAME='$(CC) -E''.
You may want to read the file INSTALL in this directory for more
information if the make fails.
If you are a csh user and wish to convert your csh aliases to Bash
aliases, you may wish to use the script in examples/alias-conv.sh
as a starting point.
Bug reports for 1.14 should be sent to:
bug-bash@prep.ai.mit.edu
using the `bashbug' program that is built and installed at the same
time as bash.
The discussion list "bug-bash@prep.ai.mit.edu" often contains information
about new ports of Bash, or discussions of new features or behavior
changes that people would like. This mailing list is also available
as a usenet newsgroup: gnu.bash.bug.
When you send a bug report to bash-maintainers@prep.ai.mit.edu, please
include:
* the version number of Bash
* the machine and OS that it is running on (see .machine or .made)
* a description of the bug
* a recipe for recreating the bug reliably
* a fix for the bug if you have one!
The `bashbug' program includes much of this automatically.
While the Bash maintainers do not promise to fix all bugs, we would
like this shell to be the best that we can make it.
Enjoy!
Chet Ramey
chet@po.cwru.edu

269
RELEASE Normal file
View file

@ -0,0 +1,269 @@
This file details the changes between the previous release of bash (1.13.5)
and this release (1.14.0).
1. New Features in Bash
a. The source has been reorganized: nearly all extern function
declarations have been moved to header files, function prototypes
have been added to most header files, function declarations have
been moved to file scope, dead code has been removed, the
bash history code has been isolated in bashhist.[ch], and several
new header files have been created
b. `set -o posix' puts bash into Posix.2 mode
c. If $POSIX_PEDANTIC exists in the initial environment or is assigned
a value, bash enters Posix.2 mode
d. Bash sets $OSTYPE to a string describing the UNIX version
e. The features.info file was completely rewritten and now reflects
the current state of things
f. A manual page for readline is in documentation/readline.{3,ps}
g. The test builtin emulates /dev/fd/x for systems without /dev/fd
h. `dirs' has -n and +n options to access members of the directory stack
i. Prompt string expansion handles invisible characters in the prompt;
\[ and \] are used (and required) to start and end sequences of
invisible chars
j. NO_PROMPT_VARS has been removed
k. New machine descriptions have been added: IBM AIX/ESA, NEC EWS, NetBSD,
FreeBSD, QNX 4.2, concurrent, MIPS SVR4.2, Lynx 2.1
l. RESTRICTED_SHELL is no longer defined by default in config.h
m. The version string in $BASH_VERSION has changed to dist.patch(build)
n. $history_control has been renamed to $HISTCONTROL and now takes the
value `ignoreboth' ($history_control is still accepted for backwards
compatibility)
o. There is a new program `bashbug' for reporting bugs. Eventually I will
probably switch to gnats.
p. auto_resume can take the values `exact' and `substring'
q. `set -P' (`set -o physical') enables the same physical view of the
file system that `nolinks' enables (`nolinks' will remain for one
more release)
r. There is a `mkmachtype' program to generate a GNU-style machine type
string (e.g., `sparc-sun-sunos4.1.2') suitable for assigning to
$MACHTYPE
s. The variable $HISTCMD returns the current history number
t. Variables in directory names are now expanded while doing completion
u. The test suite has been expanded and is runnable as a regression test
with `make tests'
v. `bye' is no longer a builtin synonym for `exit'
w. The ksh `select' control construct has been implemented
x. The `ignoreeof' attribute can be inherited if $IGNOREEOF is exported
y. The `USG-style' echo is now a configuration option. Define
DEFAULT_ECHO_TO_USG for default \-interpretation without the -e flag
z. There is a copy of an article I wrote about bash for the Linux
Journal in documentation/article.{ms,ps}
aa. The `pwd' builtin now obeys the setting of `set -o physical' (`nolinks')
bb. Process substitution is no longer performed when the shell is in
`posix mode'
cc. Users may change the debugging and optimization flags to cc by specifying
CFLAGS to make
2. New Features in Readline
a. Readline now understands sequences of invisible characters in the prompt
string, as long as they are escaped (e.g., by the bash \[ and \] escapes)
b. A `set keymap' variable assignment
c. A `bell-style' variable that can be set to `visible', `audio', or `none'
d. A `show-all-if-ambiguous' variable, which causes non-unique completion
to immediately list the possible completions
e. An `output-meta' variable to make readline directly output chars
with the eighth bit set
f. New bindable readline commands: kill-whole-line, tilde-expand,
vi-redo, vi-tilde-expand, emacs-editing-mode,
non-incremental-forward-search-history-again,
non-incremental-reverse-search-history-again
g. New history-search-forward and history-search-backward to search for
the characters between the start of the current line and point
h. Readline takes the name of the startup file from the INPUTRC variable
before defaulting to ~/.inputrc
i. isearch no longer finds identical lines multiple times in succession
j. M-C-H bound to backward-kill-word in emacs mode
k. M-~ bound to tilde-expand in emacs mode
l. History expansion is now fully csh-compatible: missing modifiers and
substitutions have been added, and bugs fixed
m. When asking whether or not to display the possible completions, readline
now accepts space as equivalent to `y' and rubout for `n'
n. Readline now attempts to find and bind the arrow keys into the vi mode
movement keymap
3. Bugs fixed in Bash
a. Portability fixes: `index' and `rindex' are gone completely, many
OS-specific defines have been replaced with feature-test macros,
the use of alloca has been reduced, and other platform-specific fixes
(e.g. cray) have been made
b. The man page has been fixed up and brought up to date
c. Speed improvements: here documents, variable expansion, history
expansion, command substitution
d. If history is stifled, the history list replaces the history file at
exit
e. Asynchronous jobs re-run with fc -s now print the job number
f. Output redirections do not perform filename expansion in Posix.2 mode
when the shell is not interactive
g. operate_and_get_next now works on the most recent line even if the
history is unstifled
h. $PROMPT_COMMAND execution no longer causes recursive invocations
of yyparse()
i. An error message is printed if job control initialization fails
j. A command found in $PATH from the temporary environment is not hashed
k. Errors display the name of the script if the shell is not interactive
l. Fixed expression evaluation so blank expressions return 0
m. Fixed a bug that caused SIGINT and SIGQUIT not to be ignored in some
asynchronous children
n. Pipes used for /dev/fd process substitution are now closed on errors
o. Fixed /dev/null redirection so that ( list ) subshells inherit the
`stdin-has-been-redirected' flag as in sh
p. Process substitution now works only when unquoted
q. Fixed a bug where the async flag was added inappropriately in a command
like `a;b;c;d &'
r. Fixed off-by-one bug which caused negative history offsets in `fc' to
be wrong
s. Shell now remembers mail dates at startup on all systems
t. Posix systems without job control no longer create so many zombies
u. $ENV is now sourced by shells forked to execute scripts without a
leading `#!' line
v. Non-root users can now use the `unlimited' argument to ulimit and have
the resource value set to the hard limit
w. Made bash more sh-compatible by assigning the first argument after
`-c command' to $0
x. Fixed mail checking bug to note that *new* mail has arrived
y. Fixed off-by-one error in mailcheck.c:free_mail_files()
z. Fixed a bug where command strings passed to `bash -c' would be truncated
after executing the first disk command in the string
aa. Fixed a bug which caused redirections passed to executable commands with
input or output pipes to be closed before the command was executed
bb. Fixed a bug which caused bash to search for files supplied on the command
line in the $PATH if the initial open failed, even if the names contained
a slash
cc. The initial argument parsing was fixed up so that other options can
be supplied with -c (that is, `sh -ec command' now works as make
intends), and so `bash -o' lists all the shell options at startup.
dd. Error messages are consistently prefixed with the name of the shell
or shell script when non-interactive.
ee. Fixed up a problem with the `read' builtin that occurred when more
variables than arguments were supplied.
ff. Unset the variables passed to `read' as arguments when EOF is
read from stdin (sh, Posix.2 compatibility).
gg. Fixes to the command printing code to make the output of `type'
available as legal shell input.
ii. Fixes so that command completion is attempted after all of the shell
command separator characters.
jj. Fixes to the shell completion code so that it handles quoted characters
and substrings better.
kk. Bash no longer looks through $PATH for a shell script passed as an
argument if the name contains slashes.
ll. Bash now checks that the `name' in a `name[=value]' argument to `declare'
(and thus `typeset', `export', and `readonly') is a legal shell variable
name.
4. Bugs fixed in Readline
a. The ^W and ^U bindings in non-incremental search mode have been changed
to be closer to what Posix specifies
b. Tries to initialize the keypad to enable the arrow keys
c. Multiple words are now killed and yanked in the right order
d. rl_read_init_file now reads filenames in a more regular order: the last
one read, $INPUTRC, then ~/.inputrc
e. yank_nth_arg inserts a space in the right place in vi mode
f. Fixed a bug in the history library that tried to write to a file opened
O_RDONLY
g. Binding of `0' in vi command mode is now right
h. The VISIBLE_STATS completion listing code now follows symlinks
i. Memory allocated with alloca() is no longer passed to other functions
j. Error messages are now printed for unrecognized history modifiers
k. Fixed a problem with history library and `!#'; now it is more csh-like.
l. Fixed a csh incompatibility in the history library: now only an end of
line or `?' terminates a ?string history search string.
m. Fixed a problem with readline completion that sometimes caused possible
matches to be listed one per line when `show-all-if-ambiguous' was set.
n. Fixed a problem in the readline display code that caused divide-by-zero
errors.
o. Fixed an off-by-one error in the kill ring reallocation code.

535
alias.c Normal file
View file

@ -0,0 +1,535 @@
/* alias.c -- Not a full alias, but just the kind that we use in the
shell. Csh style alias is somewhere else (`over there, in a box'). */
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Bash is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with Bash; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "bashansi.h"
#include "config.h"
#include "command.h"
#include "general.h"
#include "hash.h"
#include "alias.h"
static int qsort_alias_compare ();
/* Non-zero means expand all words on the line. Otherwise, expand
after first expansion if the expansion ends in a space. */
int alias_expand_all = 0;
/* The list of aliases that we have. */
HASH_TABLE *aliases = (HASH_TABLE *)NULL;
void
initialize_aliases ()
{
if (!aliases)
aliases = make_hash_table (0);
}
/* Scan the list of aliases looking for one with NAME. Return NULL
if the alias doesn't exist, else a pointer to the assoc. */
ASSOC *
find_alias (name)
char *name;
{
BUCKET_CONTENTS *al;
if (!aliases)
return ((ASSOC *)NULL);
else
al = find_hash_item (name, aliases);
if (al)
return ((ASSOC *)al->data);
else
return ((ASSOC *)NULL);
}
/* Return the value of the alias for NAME, or NULL if there is none. */
char *
get_alias_value (name)
char *name;
{
ASSOC *alias = find_alias (name);
if (alias)
return (alias->value);
else
return ((char *)NULL);
}
/* Make a new alias from NAME and VALUE. If NAME can be found,
then replace its value. */
void
add_alias (name, value)
char *name, *value;
{
ASSOC *temp = (ASSOC *)NULL;
if (!aliases)
initialize_aliases ();
else
temp = find_alias (name);
if (temp)
{
free (temp->value);
temp->value = savestring (value);
}
else
{
BUCKET_CONTENTS *elt;
temp = (ASSOC *)xmalloc (sizeof (ASSOC));
temp->name = savestring (name);
temp->value = savestring (value);
elt = add_hash_item (savestring (name), aliases);
elt->data = (char *)temp;
}
}
/* Remove the alias with name NAME from the alias table. Returns
the number of aliases left in the table, or -1 if the alias didn't
exist. */
int
remove_alias (name)
char *name;
{
BUCKET_CONTENTS *elt;
if (!aliases)
return (-1);
elt = remove_hash_item (name, aliases);
if (elt)
{
ASSOC *t;
t = (ASSOC *)elt->data;
free (t->name);
free (t->value);
free (elt->key); /* alias name */
free (t);
return (aliases->nentries);
}
return (-1);
}
/* Delete a hash bucket chain of aliases. */
static void
delete_alias_list (alias_list)
BUCKET_CONTENTS *alias_list;
{
register BUCKET_CONTENTS *bp, *temp;
register ASSOC *a;
for (bp = alias_list; bp; )
{
temp = bp->next;
a = (ASSOC *)bp->data;
free (a->value);
free (a->name);
free (bp->data);
free (bp->key);
free (bp);
bp = temp;
}
}
/* Delete all aliases. */
void
delete_all_aliases ()
{
register int i;
if (!aliases)
return;
for (i = 0; i < aliases->nbuckets; i++)
{
register BUCKET_CONTENTS *bp;
bp = get_hash_bucket (i, aliases);
delete_alias_list (bp);
}
free (aliases);
aliases = (HASH_TABLE *)NULL;
}
/* Return an array of aliases that satisfy the conditions tested by FUNCTION.
If FUNCTION is NULL, return all aliases. */
static ASSOC **
map_over_aliases (function)
Function *function;
{
register int i;
register BUCKET_CONTENTS *tlist;
ASSOC *alias, **list = (ASSOC **)NULL;
int list_index = 0, list_size = 0;
for (i = 0; i < aliases->nbuckets; i++)
{
tlist = get_hash_bucket (i, aliases);
while (tlist)
{
alias = (ASSOC *)tlist->data;
if (!function || (*function) (alias))
{
if (list_index + 1 >= list_size)
list = (ASSOC **)
xrealloc ((char *)list, (list_size += 20) * sizeof (ASSOC *));
list[list_index++] = alias;
list[list_index] = (ASSOC *)NULL;
}
tlist = tlist->next;
}
}
return (list);
}
static void
sort_aliases (array)
ASSOC **array;
{
qsort (array, array_len ((char **)array), sizeof (ASSOC *), qsort_alias_compare);
}
static int
qsort_alias_compare (as1, as2)
ASSOC **as1, **as2;
{
int result;
if ((result = (*as1)->name[0] - (*as2)->name[0]) == 0)
result = strcmp ((*as1)->name, (*as2)->name);
return (result);
}
/* Return a sorted list of all defined aliases */
ASSOC **
all_aliases ()
{
ASSOC **list;
if (!aliases)
return ((ASSOC **)NULL);
list = map_over_aliases ((Function *)NULL);
if (list)
sort_aliases (list);
return (list);
}
char *
alias_expand_word (s)
char *s;
{
ASSOC *r = find_alias (s);
if (r)
return (savestring (r->value));
else
return ((char *)NULL);
}
/* Return non-zero if CHARACTER is a member of the class of characters
that are self-delimiting in the shell (this really means that these
characters delimit tokens). */
#define self_delimiting(character) (member ((character), " \t\n\r;|&()"))
/* Return non-zero if CHARACTER is a member of the class of characters
that delimit commands in the shell. */
#define command_separator(character) (member ((character), "\r\n;|&("))
/* If this is 1, we are checking the next token read for alias expansion
because it is the first word in a command. */
static int command_word;
/* This is for skipping quoted strings in alias expansions. */
#define quote_char(c) (((c) == '\'') || ((c) == '"'))
/* Consume a quoted string from STRING, starting at string[START] (so
string[START] is the opening quote character), and return the index
of the closing quote character matching the opening quote character.
This handles single matching pairs of unquoted quotes; it could afford
to be a little smarter... This skips words between balanced pairs of
quotes, words where the first character is quoted with a `\', and other
backslash-escaped characters. */
static int
skipquotes (string, start)
char *string;
int start;
{
register int i;
int delimiter = string[start];
/* i starts at START + 1 because string[START] is the opening quote
character. */
for (i = start + 1 ; string[i] ; i++)
{
if (string[i] == '\\')
{
i++; /* skip backslash-quoted quote characters, too */
continue;
}
if (string[i] == delimiter)
return i;
}
return (i);
}
/* Skip the white space and any quoted characters in STRING, starting at
START. Return the new index into STRING, after zero or more characters
have been skipped. */
static int
skipws (string, start)
char *string;
int start;
{
register int i = 0;
int pass_next, backslash_quoted_word, peekc;
/* skip quoted strings, in ' or ", and words in which a character is quoted
with a `\'. */
backslash_quoted_word = pass_next = 0;
/* Skip leading whitespace (or separator characters), and quoted words.
But save it in the output. */
for (i = start; string[i]; i++)
{
if (pass_next)
{
pass_next = 0;
continue;
}
if (whitespace (string[i]))
{
backslash_quoted_word = 0; /* we are no longer in a backslash-quoted word */
continue;
}
if (string[i] == '\\')
{
peekc = string[i+1];
if (isletter (peekc))
backslash_quoted_word++; /* this is a backslash-quoted word */
else
pass_next++;
continue;
}
/* This only handles single pairs of non-escaped quotes. This
overloads backslash_quoted_word to also mean that a word like
""f is being scanned, so that the quotes will inhibit any expansion
of the word. */
if (quote_char(string[i]))
{
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;
peekc = string[i + 1];
if (isletter (peekc))
backslash_quoted_word++;
continue;
}
/* If we're in the middle of some kind of quoted word, let it
pass through. */
if (backslash_quoted_word)
continue;
/* If this character is a shell command separator, then set a hint for
alias_expand that the next token is the first word in a command. */
if (command_separator (string[i]))
{
command_word++;
continue;
}
break;
}
return (i);
}
/* Characters that may appear in a token. Basically, anything except white
space and a token separator. */
#define token_char(c) (!((whitespace (string[i]) || self_delimiting (string[i]))))
/* Read from START in STRING until the next separator character, and return
the index of that separator. Skip backslash-quoted characters. Call
skipquotes () for quoted strings in the middle or at the end of tokens,
so all characters show up (e.g. foo'' and foo""bar) */
static int
rd_token (string, start)
char *string;
int start;
{
register int i;
/* From here to next separator character is a token. */
for (i = start; string[i] && token_char (string[i]); i++)
{
if (string[i] == '\\')
{
i++; /* skip backslash-escaped character */
continue;
}
/* If this character is a quote character, we want to call skipquotes
to get the whole quoted portion as part of this word. That word
will not generally match an alias, even if te unquoted word would
have. The presence of the quotes in the token serves then to
inhibit expansion. */
if (quote_char (string[i]))
{
i = skipquotes (string, i);
/* Now string[i] is the matching quote character, and the
quoted portion of the token has been scanned. */
continue;
}
}
return (i);
}
/* Return a new line, with any aliases substituted. */
char *
alias_expand (string)
char *string;
{
int line_len = 1 + strlen (string);
char *line = (char *)xmalloc (line_len);
register int i, j, start;
char *token = xmalloc (line_len);
int tl, real_start, expand_next, expand_this_token;
ASSOC *alias;
line[0] = i = 0;
expand_next = 0;
command_word = 1; /* initialized to expand the first word on the line */
/* Each time through the loop we find the next word in line. If it
has an alias, substitute
the alias value. If the value ends in ` ', then try again
with the next word. Else, if there is no value, or if
the value does not end in space, we are done. */
for (;;)
{
token[0] = 0;
start = i;
/* Skip white space and quoted characters */
i = skipws (string, start);
if (start == i && string[i] == '\0')
{
free (token);
return (line);
}
/* copy the just-skipped characters into the output string,
expanding it if there is not enough room. */
j = strlen (line);
tl = i - start; /* number of characters just skipped */
if (1 + j + tl >= line_len)
line = (char *)xrealloc (line, line_len += (50 + tl));
strncpy (line + j, string + start, tl);
line[j + tl] = '\0';
real_start = i;
command_word = command_word || (command_separator (string[i]));
expand_this_token = (command_word || expand_next);
expand_next = 0;
/* Read the next token, and copy it into TOKEN. */
start = i;
i = rd_token (string, start);
tl = i - start; /* token length */
/* If tl == 0, but we're not at the end of the string, then we have a
single-character token, probably a delimiter */
if (tl == 0 && string[i] != '\0')
{
tl = 1;
i++; /* move past it */
}
strncpy (token, string + start, tl);
token [tl] = '\0';
/* If there is a backslash-escaped character quoted in TOKEN,
then we don't do alias expansion. This should check for all
other quoting characters, too. */
if (strchr (token, '\\'))
expand_this_token = 0;
/* If we should be expanding here, if we are expanding all words, or if
we are in a location in the string where an expansion is supposed to
take place, see if this word has a substitution. If it does, then do
the expansion. Note that we defer the alias value lookup until we
are sure we are expanding this token. */
if ((token[0]) &&
(expand_this_token || alias_expand_all) &&
(alias = find_alias (token)))
{
char *v = alias->value;
int l = strlen (v);
/* +3 because we possibly add one more character below. */
if ((l + 3) > line_len - (int)strlen (line))
line = (char *)xrealloc (line, line_len += (50 + l));
strcat (line, v);
if ((expand_this_token && l && whitespace (v[l - 1])) ||
alias_expand_all)
expand_next = 1;
}
else
{
int ll = strlen (line);
int tlen = i - real_start; /* tlen == strlen(token) */
if (ll + tlen + 2 > line_len)
line = (char *)xrealloc (line, line_len += 50 + ll + tlen);
strncpy (line + ll, string + real_start, tlen);
line[ll + tlen] = '\0';
}
command_word = 0;
}
}

75
alias.h Normal file
View file

@ -0,0 +1,75 @@
/* alias.h -- structure definitions. */
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Bash is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with Bash; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (_ALIAS_)
#define _ALIAS_
#include "hash.h"
extern char *xmalloc ();
#if !defined (whitespace)
# define whitespace(c) (((c) == ' ') || ((c) == '\t'))
#endif /* !whitespace */
#if !defined (savestring)
# define savestring(x) (char *)strcpy (xmalloc (1 + strlen (x)), (x))
#endif /* !savestring */
#if !defined (NULL)
# if defined (__STDC__)
# define NULL ((void *) 0)
# else
# define NULL 0x0
# endif /* !__STDC__ */
#endif /* !NULL */
typedef struct {
char *name;
char *value;
} ASSOC;
/* The list of known aliases. */
extern HASH_TABLE *aliases;
extern void initialize_aliases ();
/* Scan the list of aliases looking for one with NAME. Return NULL
if the alias doesn't exist, else a pointer to the assoc. */
extern ASSOC *find_alias ();
/* Return the value of the alias for NAME, or NULL if there is none. */
extern char *get_alias_value ();
/* Make a new alias from NAME and VALUE. If NAME can be found,
then replace its value. */
extern void add_alias ();
/* Remove the alias with name NAME from the alias list. Returns
the index of the removed alias, or -1 if the alias didn't exist. */
extern int remove_alias ();
/* Return a new line, with any aliases expanded. */
extern char *alias_expand ();
/* Return an array of all defined aliases. */
extern ASSOC **all_aliases ();
#endif /* _ALIAS_ */

41
ansi_stdlib.h Normal file
View file

@ -0,0 +1,41 @@
/* ansi_stdlib.h -- An ANSI Standard stdlib.h. */
/* A minimal stdlib.h containing extern declarations for those functions
that bash uses. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (_STDLIB_H_)
#define _STDLIB_H_ 1
/* String conversion functions. */
extern int atoi ();
extern long int atol ();
/* Memory allocation functions. */
extern char *malloc ();
extern char *realloc ();
extern void free ();
/* Other miscellaneous functions. */
extern void abort ();
extern void exit ();
extern char *getenv ();
extern void qsort ();
#endif /* _STDLIB_H */

36
bashansi.h Normal file
View file

@ -0,0 +1,36 @@
/* bashansi.h -- Typically included information required by picky compilers. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (_BASHANSI_H_)
#define _BASHANSI_H_
#if defined (HAVE_STRING_H)
# include <string.h>
#else
# include <strings.h>
#endif /* !HAVE_STRING_H */
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
#else
# include "ansi_stdlib.h"
#endif /* !HAVE_STDLIB_H */
#endif /* !_BASHANSI_H_ */

390
bashhist.c Normal file
View file

@ -0,0 +1,390 @@
/* bashhist.c -- bash interface to the GNU history library. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include "bashansi.h"
#include "posixstat.h"
#include "filecntl.h"
#include "shell.h"
#include "flags.h"
#include <readline/history.h>
/* Declarations of bash history variables. */
/* Non-zero means to remember lines typed to the shell on the history
list. This is different than the user-controlled behaviour; this
becomes zero when we read lines from a file, for example. */
int remember_on_history = 1;
/* The number of lines that Bash has added to this history session. */
int history_lines_this_session = 0;
/* The number of lines that Bash has read from the history file. */
int history_lines_in_file = 0;
/* Non-zero means do no history expansion on this line, regardless
of what history_expansion says. */
int history_expansion_inhibited = 0;
/* By default, every line is saved in the history individually. I.e.,
if the user enters:
bash$ for i in a b c
> do
> echo $i
> done
Each line will be individually saved in the history.
bash$ history
10 for i in a b c
11 do
12 echo $i
13 done
14 history
If the variable command_oriented_history is set, multiple lines
which form one command will be saved as one history entry.
bash$ for i in a b c
> do
> echo $i
> done
bash$ history
10 for i in a b c
do
echo $i
done
11 history
The user can then recall the whole command all at once instead
of just being able to recall one line at a time.
*/
int command_oriented_history = 0;
/* A nit for picking at history saving.
Value of 0 means save all lines parsed by the shell on the history.
Value of 1 means save all lines that do not start with a space.
Value of 2 means save all lines that do not match the last line saved. */
int history_control = 0;
/* Variables declared in other files used here. */
extern int interactive;
extern int current_command_line_count;
extern int delimiter_depth;
extern char *history_delimiting_chars ();
extern void maybe_add_history (); /* forward declaration */
static void bash_add_history ();
/* Load the history list from the history file. */
void
load_history ()
{
char *hf;
/* Truncate history file for interactive shells which desire it.
Note that the history file is automatically truncated to the
size of HISTSIZE if the user does not explicitly set the size
differently. */
set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE"));
stupidly_hack_special_variables ("HISTFILESIZE");
/* Read the history in HISTFILE into the history list. */
hf = get_string_value ("HISTFILE");
if (hf && *hf)
{
struct stat buf;
if (stat (hf, &buf) == 0)
{
read_history (hf);
using_history ();
history_lines_in_file = where_history ();
}
}
}
/* Write the existing history out to the history file. */
void
save_history ()
{
char *hf = get_string_value ("HISTFILE");
if (hf && *hf)
{
struct stat buf;
if (stat (hf, &buf) == 0)
{
/* Append only the lines that occurred this session to
the history file. */
using_history ();
if (history_lines_this_session < where_history ())
append_history (history_lines_this_session, hf);
else
write_history (hf);
}
}
}
/* If this is an interactive shell, then append the lines executed
this session to the history file. */
int
maybe_save_shell_history ()
{
int result = 0;
if (history_lines_this_session)
{
char *hf = get_string_value ("HISTFILE");
if (hf && *hf)
{
struct stat buf;
/* If the file doesn't exist, then create it. */
if (stat (hf, &buf) == -1)
{
int file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0666);
if (file != -1)
close (file);
}
/* Now actually append the lines if the history hasn't been
stifled. If the history has been stifled, rewrite the
history file. */
using_history ();
if (history_lines_this_session <= where_history ())
{
result = append_history (history_lines_this_session, hf);
history_lines_in_file += history_lines_this_session;
}
else
{
result = write_history (hf);
history_lines_in_file = history_lines_this_session;
}
history_lines_this_session = 0;
}
}
return (result);
}
#if defined (HISTORY_REEDITING)
/* Tell readline () that we have some text for it to edit. */
static void
re_edit (text)
char *text;
{
#if defined (READLINE)
if (strcmp (bash_input.name, "readline stdin") == 0)
bash_re_edit (text);
#endif /* READLINE */
}
#endif /* HISTORY_REEDITING */
/* Do pre-processing on LINE. If PRINT_CHANGES is non-zero, then
print the results of expanding the line if there were any changes.
If there is an error, return NULL, otherwise the expanded line is
returned. If ADDIT is non-zero the line is added to the history
list after history expansion. ADDIT is just a suggestion;
REMEMBER_ON_HISTORY can veto, and does.
Right now this does history expansion. */
char *
pre_process_line (line, print_changes, addit)
char *line;
int print_changes, addit;
{
char *history_value;
char *return_value;
int expanded = 0;
return_value = line;
# if defined (BANG_HISTORY)
/* History expand the line. If this results in no errors, then
add that line to the history if ADDIT is non-zero. */
if (!history_expansion_inhibited && history_expansion)
{
expanded = history_expand (line, &history_value);
if (expanded)
{
if (print_changes)
{
if (expanded < 0)
internal_error (history_value);
else
fprintf (stderr, "%s\n", history_value);
}
/* If there was an error, return NULL. */
if (expanded < 0 || expanded == 2) /* 2 == print only */
{
free (history_value);
# if defined (HISTORY_REEDITING)
/* New hack. We can allow the user to edit the
failed history expansion. */
re_edit (line);
# endif /* HISTORY_REEDITING */
return ((char *)NULL);
}
}
/* Let other expansions know that return_value can be free'ed,
and that a line has been added to the history list. Note
that we only add lines that have something in them. */
expanded = 1;
return_value = history_value;
}
# endif /* BANG_HISTORY */
if (addit && remember_on_history && *return_value)
maybe_add_history (return_value);
if (!expanded)
return_value = savestring (line);
return (return_value);
}
/* Add LINE to the history list depending on the value of HISTORY_CONTROL. */
void
maybe_add_history (line)
char *line;
{
int h;
/* 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)
h = 0;
else
h = history_control;
switch (h)
{
case 0:
bash_add_history (line);
break;
case 1:
if (*line != ' ')
bash_add_history (line);
break;
case 3:
if (*line == ' ')
break;
/* FALLTHROUGH if case == 3 (`ignoreboth') */
case 2:
{
HIST_ENTRY *temp;
using_history ();
temp = previous_history ();
if (!temp || (STREQ (temp->line, line) == 0))
bash_add_history (line);
using_history ();
}
break;
}
}
/* Add a line to the history list.
The variable COMMAND_ORIENTED_HISTORY controls the style of history
remembering; when non-zero, and LINE is not the first line of a
complete parser construct, append LINE to the last history line instead
of adding it as a new line. */
static void
bash_add_history (line)
char *line;
{
int add_it = 1;
if (command_oriented_history && current_command_line_count > 1)
{
register int offset;
register HIST_ENTRY *current, *old;
char *chars_to_add, *new_line;
chars_to_add = history_delimiting_chars ();
using_history ();
current = previous_history ();
if (current)
{
/* If the previous line ended with an escaped newline (escaped
with backslash, but otherwise unquoted), then remove the quoted
newline, since that is what happens when the line is parsed. */
int curlen;
curlen = strlen (current->line);
if (!delimiter_depth && current->line[curlen - 1] == '\\' &&
current->line[curlen - 2] != '\\')
{
current->line[curlen - 1] = '\0';
curlen--;
chars_to_add = "";
}
offset = where_history ();
new_line = (char *) xmalloc (1
+ curlen
+ strlen (line)
+ strlen (chars_to_add));
sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
old = replace_history_entry (offset, new_line, current->data);
free (new_line);
if (old)
{
/* Note that the old data is not freed, since it was simply
copied to the new history entry. */
if (old->line)
free (old->line);
free (old);
}
add_it = 0;
}
}
if (add_it)
{
add_history (line);
history_lines_this_session++;
}
using_history ();
}
int
history_number ()
{
using_history ();
if (get_string_value ("HISTSIZE"))
return (history_base + where_history ());
else
return (1); /* default to command number 1 */
}

42
bashhist.h Normal file
View file

@ -0,0 +1,42 @@
/* bashhist.h -- interface to the bash history functions in bashhist.c. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (__BASHHIST_H__)
#define __BASHHIST_H__
extern int remember_on_history;
extern int history_lines_this_session;
extern int history_lines_in_file;
extern int history_expansion;
extern int history_control;
extern int command_oriented_history;
# if defined (BANG_HISTORY)
extern int history_expansion_inhibited;
# endif /* BANG_HISTORY */
extern void load_history ();
extern void save_history ();
extern int maybe_save_shell_history ();
extern char *pre_process_line ();
extern int history_number ();
extern void maybe_add_history ();
#endif /* __BASHHIST_H__ */

1797
bashline.c Normal file

File diff suppressed because it is too large Load diff

34
bashtypes.h Normal file
View file

@ -0,0 +1,34 @@
/* bashtypes.h -- <sys/types.h> with special handling for crays. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (__BASHTYPES_H)
# define __BASHTYPES_H
#if defined (CRAY)
# define word __word
#endif
#include <sys/types.h>
#if defined (CRAY)
# undef word
#endif
#endif /* __BASHTYPES_H */

166
bracecomp.c Normal file
View file

@ -0,0 +1,166 @@
/* bracecomp.c -- Complete a filename with the possible completions enclosed
in csh-style braces such that the list of completions is available to the
shell. */
/* Original version by tromey@cns.caltech.edu, Fri Feb 7 1992. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "shell.h"
#include <readline/readline.h>
/* Find greatest common prefix of two strings. */
static int
string_gcd (s1, s2)
char *s1, *s2;
{
register int i;
if (s1 == NULL || s2 == NULL)
return (0);
for (i = 0; *s1 && *s2; ++s1, ++s2, ++i)
{
if (*s1 != *s2)
break;
}
return (i);
}
static char *
really_munge_braces (array, real_start, real_end, gcd_zero)
char **array;
int real_start, real_end, gcd_zero;
{
int start, end, gcd;
char *result, *subterm;
int result_size, flag;
flag = 0;
if (real_start == real_end)
{
if (array[real_start])
return (savestring (array[real_start] + gcd_zero));
else
return (savestring (array[0]));
}
result = (char *) xmalloc (result_size = 1);
*result = '\0';
for (start = real_start; start < real_end; start = end + 1)
{
gcd = strlen (array[start]);
for (end = start + 1; end < real_end; end++)
{
int temp;
temp = string_gcd (array[start], array[end]);
if (temp <= gcd_zero)
break;
gcd = temp;
}
end--;
if (gcd_zero == 0 && start == real_start && end != (real_end - 1))
{
/* In this case, add in a leading '{', because we are at
top level, and there isn't a consistent prefix. */
result_size += 1;
result = (char *) xrealloc (result, result_size);
strcpy (result, "{");
flag++;
}
if (start == end)
subterm = savestring (array[start] + gcd_zero);
else
{
/* If there is more than one element in the subarray,
insert the prefix and an opening brace. */
result_size += gcd - gcd_zero + 1;
result = (char *) xrealloc (result, result_size);
strncat (result, array[start] + gcd_zero, gcd - gcd_zero);
strcat (result, "{");
subterm = really_munge_braces (array, start, end + 1, gcd);
subterm[strlen (subterm) - 1] = '}';
}
result_size += strlen (subterm) + 1;
result = (char *) xrealloc (result, result_size);
strcat (result, subterm);
strcat (result, ",");
free (subterm);
}
if (gcd_zero == 0)
result[strlen (result) - 1] = flag ? '}' : '\0';
return (result);
}
static void
hack_braces_completion (names)
char **names;
{
register int i;
char *temp;
temp = really_munge_braces (names, 1, array_len (names), 0);
for (i = 0; names[i]; ++i)
{
free (names[i]);
names[i] = NULL;
}
names[0] = temp;
}
void
bash_brace_completion ()
{
Function *orig_ignore_func;
Function *orig_entry_func;
CPPFunction *orig_attempt_func;
orig_ignore_func = rl_ignore_some_completions_function;
orig_attempt_func = rl_attempted_completion_function;
orig_entry_func = rl_completion_entry_function;
rl_completion_entry_function = (Function *) filename_completion_function;
rl_attempted_completion_function = NULL;
rl_ignore_some_completions_function = (Function *) hack_braces_completion;
rl_complete_internal (TAB);
rl_ignore_some_completions_function = orig_ignore_func;
rl_attempted_completion_function = orig_attempt_func;
rl_completion_entry_function = orig_entry_func;
}

371
braces.c Normal file
View file

@ -0,0 +1,371 @@
/* braces.c -- code for doing word expansion in curly braces. */
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Bash is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with Bash; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Stuff in curly braces gets expanded after variable and command
substitution, but before filename globbing.
(Actually, this should be true for the sake of efficiency, but it
isn't because of quoting hacks. Once I rebuild quoting it will be
true. */
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#if defined (SHELL)
#include "shell.h"
#endif /* SHELL */
#include "general.h"
#define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
/* Basic idea:
Segregate the text into 3 sections: preamble (stuff before an open brace),
postamble (stuff after the matching close brace) and amble (stuff after
preamble, and before postamble). Expand amble, and then tack on the
expansions to preamble. Expand postamble, and tack on the expansions to
the result so far.
*/
/* The character which is used to separate arguments. */
int brace_arg_separator = ',';
static int brace_gobbler ();
static char **expand_amble (), **array_concat ();
/* Return an array of strings; the brace expansion of TEXT. */
char **
brace_expand (text)
char *text;
{
register int start;
char *preamble, *postamble, *amble;
char **tack, **result;
int i, c;
/* Find the text of the preamble. */
i = 0;
c = brace_gobbler (text, &i, '{');
preamble = (char *)xmalloc (i + 1);
strncpy (preamble, text, i);
preamble[i] = '\0';
result = (char **)xmalloc (2 * sizeof (char *));
result[0] = preamble;
result[1] = (char *)NULL;
/* Special case. If we never found an exciting character, then
the preamble is all of the text, so just return that. */
if (c != '{')
return (result);
/* Find the amble. This is the stuff inside this set of braces. */
start = ++i;
c = brace_gobbler (text, &i, '}');
/* What if there isn't a matching close brace? */
if (!c)
{
#if defined (NOTDEF)
register int j;
/* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
and I, then this should be an error. Otherwise, it isn't. */
for (j = start; j < i; j++)
{
if (text[j] == '\\')
{
j++;
continue;
}
if (text[j] == brace_arg_separator)
{
free_array (result);
report_error ("Missing `}'");
throw_to_top_level ();
}
}
#endif
free (preamble); /* Same as result[0]; see initialization. */
result[0] = savestring (text);
return (result);
}
amble = (char *)xmalloc (1 + (i - start));
strncpy (amble, &text[start], (i - start));
amble[i - start] = '\0';
#if defined (SHELL)
/* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
just return without doing any expansion. */
{
register int j;
for (j = 0; amble[j]; j++)
{
if (amble[j] == '\\')
{
j++;
continue;
}
if (amble[j] == brace_arg_separator)
break;
}
if (!amble[j])
{
free (amble);
free (preamble);
result[0] = savestring (text);
return (result);
}
}
#endif /* SHELL */
postamble = &text[i + 1];
tack = expand_amble (amble);
result = array_concat (result, tack);
free (amble);
free_array (tack);
tack = brace_expand (postamble);
result = array_concat (result, tack);
free_array (tack);
return (result);
}
/* Expand the text found inside of braces. We simply try to split the
text at BRACE_ARG_SEPARATORs into separate strings. We then brace
expand each slot which needs it, until there are no more slots which
need it. */
static char **
expand_amble (text)
char *text;
{
char **result, **partial;
char *tem;
int start, i, c;
result = (char **)NULL;
for (start = 0, i = 0, c = 1; c; start = ++i)
{
c = brace_gobbler (text, &i, brace_arg_separator);
tem = (char *)xmalloc (1 + (i - start));
strncpy (tem, &text[start], (i - start));
tem[i- start] = '\0';
partial = brace_expand (tem);
if (!result)
result = partial;
else
{
register int lr = array_len (result);
register int lp = array_len (partial);
register int j;
result = (char **)xrealloc (result, (1 + lp + lr) * sizeof (char *));
for (j = 0; j < lp; j++)
result[lr + j] = partial[j];
result[lr + j] = (char *)NULL;
free (partial);
}
free (tem);
}
return (result);
}
/* Start at INDEX, and skip characters in TEXT. Set INDEX to the
index of the character matching SATISFY. This understands about
quoting. Return the character that caused us to stop searching;
this is either the same as SATISFY, or 0. */
static int
brace_gobbler (text, indx, satisfy)
char *text;
int *indx;
int satisfy;
{
register int i, c, quoted, level, pass_next;
level = quoted = pass_next = 0;
for (i = *indx; c = text[i]; i++)
{
if (pass_next)
{
pass_next = 0;
continue;
}
/* A backslash escapes the next character. This allows backslash to
escape the quote character in a double-quoted string. */
if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
{
pass_next = 1;
continue;
}
if (quoted)
{
if (c == quoted)
quoted = 0;
continue;
}
if (c == '"' || c == '\'' || c == '`')
{
quoted = c;
continue;
}
if (c == satisfy && !level && !quoted)
{
/* We ignore an open brace surrounded by whitespace, and also
an open brace followed immediately by a close brace, that
was preceded with whitespace. */
if (c == '{' &&
((!i || brace_whitespace (text[i - 1])) &&
(brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
continue;
#if defined (SHELL)
/* If this is being compiled as part of bash, ignore the `{'
in a `${}' construct */
if ((c != '{') || !i || (text[i - 1] != '$'))
#else /* !SHELL */
if ((c != '{') || !i)
#endif /* !SHELL */
break;
}
if (c == '{')
level++;
else if (c == '}' && level)
level--;
}
*indx = i;
return (c);
}
/* Return a new array of strings which is the result of appending each
string in ARR2 to each string in ARR1. The resultant array is
len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
is returned. */
static char **
array_concat (arr1, arr2)
char **arr1, **arr2;
{
register int i, j, len, len1, len2;
register char **result;
if (!arr1)
return (copy_array (arr2));
if (!arr2)
return (copy_array (arr1));
len1 = array_len (arr1);
len2 = array_len (arr2);
result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
len = 0;
for (i = 0; i < len1; i++)
{
int strlen_1 = strlen (arr1[i]);
for (j = 0; j < len2; j++)
{
result[len] =
(char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
strcpy (result[len], arr1[i]);
strcpy (result[len] + strlen_1, arr2[j]);
len++;
}
free (arr1[i]);
}
free (arr1);
result[len] = (char *)NULL;
return (result);
}
#if defined (TEST)
#include <stdio.h>
fatal_error (format, arg1, arg2)
char *format, *arg1, *arg2;
{
report_error (format, arg1, arg2);
exit (1);
}
report_error (format, arg1, arg2)
char *format, *arg1, *arg2;
{
fprintf (stderr, format, arg1, arg2);
fprintf (stderr, "\n");
}
main ()
{
char example[256];
for (;;)
{
char **result;
int i;
fprintf (stderr, "brace_expand> ");
if ((!fgets (example, 256, stdin)) ||
(strncmp (example, "quit", 4) == 0))
break;
if (strlen (example))
example[strlen (example) - 1] = '\0';
result = brace_expand (example);
for (i = 0; result[i]; i++)
printf ("%s\n", result[i]);
free_array (result);
}
}
/*
* Local variables:
* compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
* end:
*/
#endif /* TEST */

45
builtins.h Normal file
View file

@ -0,0 +1,45 @@
/* builtins.h -- What a builtin looks like, and where to find them. */
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Bash is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with Bash; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "command.h"
#include "general.h"
#if defined (ALIAS)
#include "alias.h"
#endif
/* Flags describing various things about a builtin. */
#define BUILTIN_ENABLED 0x1 /* This builtin is enabled. */
#define STATIC_BUILTIN 0x2 /* This builtin is not dynamically loaded. */
#define SPECIAL_BUILTIN 0x4 /* This is a Posix `special' builtin. */
/* The thing that we build the array of builtins out of. */
struct builtin {
char *name; /* The name that the user types. */
Function *function; /* The address of the invoked function. */
int flags; /* One of the #defines above. */
char **long_doc; /* NULL terminated array of strings. */
char *short_doc; /* Short version of documenation. */
};
/* Found in builtins.c, created by builtins/mkbuiltins. */
extern int num_shell_builtins; /* Number of shell builtins. */
extern struct builtin shell_builtins[];

0
builtins/ChangeLog Normal file
View file

267
builtins/Makefile Normal file
View file

@ -0,0 +1,267 @@
# This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
#
MKBUILTINS = mkbuiltins
RANLIB = /usr/bin/ranlib
CFLAGS = -g -I.. -I.
SHELL = /bin/sh
# CC = cc
AR = ar
RM = rm -f
CP = cp
srcdir = .
VPATH = .:$(srcdir)
.SUFFIXES:
.SUFFIXES: .def .c .o
# How to make a .o file from a .def file.
.def.o:
$(RM) $@
./$(MKBUILTINS) $(DIRECTDEFINE) $<
$(CC) -c $(CFLAGS) $(CPPFLAGS) $*.c || ( $(RM) $*.c ; exit 1 )
$(RM) $*.c
# How to make a .c file from a .def file.
.def.c:
$(RM) $@
./$(MKBUILTINS) $(DIRECTDEFINE) $<
# Here is a rule for making .o files from .c files that does not
# force the type of the machine (like -M_MACHINE) into the flags.
.c.o:
$(RM) $@
$(CC) -c $(CFLAGS) $(CPPFLAGS) $<
DEFS = $(srcdir)/alias.def $(srcdir)/bind.def $(srcdir)/break.def \
$(srcdir)/builtin.def $(srcdir)/cd.def $(srcdir)/colon.def \
$(srcdir)/command.def $(srcdir)/declare.def $(srcdir)/echo.def \
$(srcdir)/enable.def $(srcdir)/eval.def $(srcdir)/getopts.def \
$(srcdir)/exec.def $(srcdir)/exit.def $(srcdir)/fc.def \
$(srcdir)/fg_bg.def $(srcdir)/hash.def $(srcdir)/help.def \
$(srcdir)/history.def $(srcdir)/jobs.def $(srcdir)/kill.def \
$(srcdir)/let.def $(srcdir)/read.def $(srcdir)/return.def \
$(srcdir)/set.def $(srcdir)/setattr.def $(srcdir)/shift.def \
$(srcdir)/source.def $(srcdir)/suspend.def $(srcdir)/test.def \
$(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \
$(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \
$(srcdir)/reserved.def
STATIC_SOURCE = common.c getopt.c bashgetopt.c getopt.h
OFILES = builtins.o \
alias.o bind.o break.o builtin.o cd.o colon.o command.o \
common.o declare.o echo.o enable.o eval.o exec.o exit.o \
fc.o fg_bg.o hash.o help.o history.o jobs.o kill.o \
let.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 getopt.o bashgetopt.o
THINGS_TO_TAR = $(DEFS) $(STATIC_SOURCE) Makefile ChangeLog
CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h
all: $(MKBUILTINS) libbuiltins.a
libbuiltins.a: $(MKBUILTINS) $(OFILES)
$(RM) $@
$(AR) cq $@ $(OFILES)
-$(RANLIB) $@
builtext.h builtins.c: $(MKBUILTINS) $(DEFS)
$(RM) builtext.h builtins.c
./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \
-noproduction $(DIRECTDEFINE) $(DEFS)
mkbuiltins: $(srcdir)/mkbuiltins.c ../config.h
$(CC) $(CFLAGS) -o $(MKBUILTINS) $(srcdir)/mkbuiltins.c
ulimit.o: ulimit.def pipesize.h
pipesize.h: psize.aux
$(SHELL) $(srcdir)/psize.sh > pipesize.h
psize.aux: psize.c
$(CC) $(CFLAGS) -o $@ $(srcdir)/psize.c
documentation: builtins.texi
$(OFILES): $(MKBUILTINS) ../config.h
builtins.texi: $(MKBUILTINS)
./$(MKBUILTINS) -documentonly $(DEFS)
clean:
$(RM) $(OFILES) $(CREATED_FILES) $(MKBUILTINS)
mostlyclean:
$(RM) $(OFILES) libbuiltins.a
distclean realclean maintainer-clean: clean
$(RM) libbuiltins.a
alias.o: alias.def
bind.o: bind.def
break.o: break.def
builtin.o: builtin.def
cd.o: cd.def
colon.o: colon.def
command.o: command.def
declare.o: declare.def
echo.o: echo.def
enable.o: enable.def
eval.o: eval.def
exec.o: exec.def
exit.o: exit.def
fc.o: fc.def
fg_bg.o: fg_bg.def
hash.o: hash.def
help.o: help.def
history.o: history.def
jobs.o: jobs.def
kill.o: kill.def
let.o: let.def
read.o: read.def
return.o: return.def
set.o: set.def
setattr.o: setattr.def
shift.o: shift.def
source.o: source.def
suspend.o: suspend.def
test.o: test.def
times.o: times.def
trap.o: trap.def
type.o: type.def
umask.o: umask.def
wait.o: wait.def
getopts.o: getopts.def
reserved.o: reserved.def
common.o: ../shell.h ../command.h ../config.h ../memalloc.h ../general.h
common.o: ../variables.h ../input.h hashcom.h ../bashhist.h
common.o: ../quit.h ../unwind_prot.h ../maxpath.h ../jobs.h ../builtins.h
common.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
common.o: ../execute_cmd.h ../error.h
alias.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
alias.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
alias.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../maxpath.h
bind.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
bind.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
bind.o: ../maxpath.h
bind.o: ../shell.h ../unwind_prot.h ../variables.h bashgetopt.h
break.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
break.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
break.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
builtin.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
builtin.o: ../quit.h common.h ../maxpath.h
builtin.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
builtin.o: ../shell.h ../unwind_prot.h ../variables.h
cd.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
cd.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
cd.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../maxpath.h
command.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
command.o: ../quit.h bashgetopt.h ../maxpath.h
command.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
command.o: ../shell.h ../unwind_prot.h ../variables.h
declare.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
declare.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
declare.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
echo.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
echo.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
echo.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
enable.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
enable.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
enable.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
eval.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
eval.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
eval.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
exec.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
exec.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
exec.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../execute_cmd.h
exec.o: ../maxpath.h ../flags.h
exit.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
exit.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
exit.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
fc.o: ../builtins.h ../command.h bashgetopt.h ../bashhist.h
fc.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
fc.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
fc.o: ../flags.h ../unwind_prot.h ../variables.h ../shell.h ../maxpath.h
fg_bg.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
fg_bg.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
fg_bg.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
getopts.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
getopts.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
getopts.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
hash.o: ../builtins.h ../command.h ../quit.h ../execute_cmd.h
hash.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
hash.o: ../shell.h ../unwind_prot.h ../variables.h common.h ../maxpath.h
help.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
help.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
help.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
history.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
history.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
history.o: ../filecntl.h ../shell.h ../unwind_prot.h ../variables.h
history.o: ../bashhist.h ../maxpath.h
inlib.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
inlib.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
inlib.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
jobs.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
jobs.o: ../quit.h bashgetopt.h ../maxpath.h
jobs.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
jobs.o: ../shell.h ../unwind_prot.h ../variables.h
kill.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
kill.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
kill.o: ../shell.h ../trap.h ../unwind_prot.h ../variables.h ../maxpath.h
let.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
let.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
let.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
read.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
read.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
read.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
return.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
return.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
return.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
set.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
set.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
set.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
setattr.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
setattr.o: ../quit.h common.h bashgetopt.h ../maxpath.h
setattr.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
setattr.o: ../shell.h ../unwind_prot.h ../variables.h
shift.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
shift.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
shift.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
source.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
source.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
source.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
suspend.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
suspend.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
suspend.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
test.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
test.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
test.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
times.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
times.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
times.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
trap.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
trap.o: ../quit.h common.h ../maxpath.h
trap.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
trap.o: ../shell.h ../unwind_prot.h ../variables.h ../execute_cmd.h
type.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
type.o: ../quit.h common.h ../maxpath.h
type.o: ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
type.o: ../shell.h ../unwind_prot.h ../variables.h
ulimit.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
ulimit.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
ulimit.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
umask.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
umask.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
umask.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
wait.o: ../command.h ../config.h ../memalloc.h ../error.h ../general.h
wait.o: ../quit.h ../dispose_cmd.h ../make_cmd.h ../subst.h ../externs.h
wait.o: ../shell.h ../unwind_prot.h ../variables.h ../maxpath.h
bashgetopt.o: ../bashansi.h ../ansi_stdlib.h
mkbuiltins.o: ../bashansi.h ../ansi_stdlib.h
fc.o: ../bashansi.h ../ansi_stdlib.h
#bind.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h

180
builtins/alias.def Normal file
View file

@ -0,0 +1,180 @@
This file is alias.def, from which is created alias.c
It implements the builtins "alias" and "unalias" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$BUILTIN alias
$FUNCTION alias_builtin
$DEPENDS_ON ALIAS
$PRODUCES alias.c
$SHORT_DOC alias [ name[=value] ... ]
`alias' with no arguments prints the list of aliases in the form
NAME=VALUE on standard output. An alias is defined for each NAME
whose VALUE is given. A trailing space in VALUE causes the next
word to be checked for alias substitution. Alias returns true
unless a NAME is given for which no alias has been defined.
$END
#include "../config.h"
#if defined (ALIAS)
# include <stdio.h>
# include "../shell.h"
# include "../alias.h"
# include "common.h"
extern int interactive;
static void print_alias ();
/* Hack the alias command in a Korn shell way. */
alias_builtin (list)
WORD_LIST *list;
{
int any_failed = 0;
if (!list)
{
register int i;
ASSOC **alias_list;
if (!aliases)
return (EXECUTION_FAILURE);
alias_list = all_aliases ();
if (!alias_list)
return (EXECUTION_FAILURE);
for (i = 0; alias_list[i]; i++)
print_alias (alias_list[i]);
free (alias_list); /* XXX - Do not free the strings. */
}
else
{
while (list)
{
register char *value, *name = list->word->word;
register int offset;
for (offset = 0; name[offset] && name[offset] != '='; offset++)
;
if (offset && name[offset] == '=')
{
name[offset] = '\0';
value = name + offset + 1;
add_alias (name, value);
}
else
{
ASSOC *t = find_alias (name);
if (t)
print_alias (t);
else
{
if (interactive)
builtin_error ("`%s' not found", name);
any_failed++;
}
}
list = list->next;
}
}
if (any_failed)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
}
#endif /* ALIAS */
$BUILTIN unalias
$FUNCTION unalias_builtin
$DEPENDS_ON ALIAS
$SHORT_DOC unalias [-a] [name ...]
Remove NAMEs from the list of defined aliases. If the -a option is given,
then remove all alias definitions.
$END
#if defined (ALIAS)
/* Remove aliases named in LIST from the aliases database. */
unalias_builtin (list)
register WORD_LIST *list;
{
register ASSOC *alias;
int any_failed = 0;
while (list && *list->word->word == '-')
{
register char *word = list->word->word;
if (ISOPTION (word, 'a'))
{
delete_all_aliases ();
list = list->next;
}
else if (ISOPTION (word, '-'))
{
list = list->next;
break;
}
else
{
bad_option (word);
return (EXECUTION_FAILURE);
}
}
while (list)
{
alias = find_alias (list->word->word);
if (alias)
remove_alias (alias->name);
else
{
if (interactive)
builtin_error ("`%s' not an alias", list->word->word);
any_failed++;
}
list = list->next;
}
if (any_failed)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
}
/* Output ALIAS in such a way as to allow it to be read back in. */
static void
print_alias (alias)
ASSOC *alias;
{
char *value = single_quote (alias->value);
printf ("alias %s=%s\n", alias->name, value);
free (value);
fflush (stdout);
}
#endif /* ALIAS */

136
builtins/bashgetopt.c Normal file
View file

@ -0,0 +1,136 @@
/* bashgetopt.c -- `getopt' for use by the builtins. */
/* Copyright (C) 1992 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 <errno.h>
#include "shell.h"
#include "bashansi.h"
#define ERR(S, C) builtin_error("%s%c", (S), (C))
static int sp;
char *list_optarg;
int list_optopt;
static WORD_LIST *lhead = (WORD_LIST *)NULL;
WORD_LIST *lcurrent = (WORD_LIST *)NULL;
WORD_LIST *loptend; /* Points to the first non-option argument in the list */
int
internal_getopt(list, opts)
WORD_LIST *list;
char *opts;
{
register int c;
register char *cp;
if (!list) {
list_optarg = (char *)NULL;
loptend = (WORD_LIST *)NULL; /* No non-option arguments */
return -1;
}
if (list != lhead || !lhead) {
/* Hmmm.... called with a different word list. Reset. */
sp = 1;
lcurrent = lhead = list;
loptend = (WORD_LIST *)NULL;
}
if (sp == 1) {
if (!lcurrent ||
(lcurrent->word->word[0] != '-' || lcurrent->word->word[1] == '\0')) {
lhead = (WORD_LIST *)NULL;
loptend = lcurrent;
return(-1);
} else if (lcurrent->word->word[0] == '-' &&
lcurrent->word->word[1] == '-' &&
lcurrent->word->word[2] == 0) {
lhead = (WORD_LIST *)NULL;
loptend = lcurrent->next;
return(-1);
}
}
list_optopt = c = lcurrent->word->word[sp];
if (c == ':' || (cp = strchr(opts, c)) == NULL) {
ERR("illegal option: -", c);
if (lcurrent->word->word[++sp] == '\0') {
lcurrent = lcurrent->next;
sp = 1;
}
list_optarg = NULL;
if (lcurrent)
loptend = lcurrent->next;
return('?');
}
if (*++cp == ':') {
/* Option requires an argument. */
/* We allow -l2 as equivalent to -l 2 */
if (lcurrent->word->word[sp+1] != '\0') {
list_optarg = &(lcurrent->word->word[sp+1]);
lcurrent = lcurrent->next;
} else if (lcurrent->next == NULL) {
ERR("option requires an argument: -", c);
sp = 1;
list_optarg = (char *)NULL;
return('?');
} else {
lcurrent = lcurrent->next;
list_optarg = lcurrent->word->word;
lcurrent = lcurrent->next;
}
sp = 1;
} else {
/* No argument, just return the option. */
if (lcurrent->word->word[++sp] == '\0') {
sp = 1;
lcurrent = lcurrent->next;
}
list_optarg = (char *)NULL;
}
return(c);
}
/*
* reset_internal_getopt -- force the in[ft]ernal getopt to reset
*/
void
reset_internal_getopt ()
{
lhead = lcurrent = loptend = (WORD_LIST *)NULL;
sp = 1;
}
void
report_bad_option ()
{
char s[3];
s[0] = '-';
s[1] = list_optopt;
s[2] = '\0';
bad_option (s);
}

37
builtins/bashgetopt.h Normal file
View file

@ -0,0 +1,37 @@
/* bashgetopt.h -- extern declarations for stuff defined in bashgetopt.c. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* See getopt.h for the explanation of these variables. */
#if !defined (__BASH_GETOPT_H)
# define __BASH_GETOPT_H
extern char *list_optarg;
extern int list_optopt;
extern WORD_LIST *lcurrent;
extern WORD_LIST *loptend;
extern int internal_getopt ();
extern void reset_internal_getopt ();
extern void report_bad_option ();
#endif /* !__BASH_GETOPT_H */

219
builtins/bind.def Normal file
View file

@ -0,0 +1,219 @@
This file is bind.def, from which is created bind.c.
It implements the builtin "bind" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES bind.c
$BUILTIN bind
$DEPENDS_ON READLINE
$FUNCTION bind_builtin
$SHORT_DOC bind [-lvd] [-m keymap] [-f filename] [-q name] [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
passed as a single argument: bind '"\C-x\C-r": re-read-init-file'.
Arguments we accept:
-m keymap Use `keymap' as the keymap for the duration of this
command. Acceptable keymap names are emacs,
emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
vi-command, and vi-insert.
-l List names of functions.
-v List function names and bindings.
-d Dump functions and bindings such that they
can be read back in.
-f filename Read key bindings from FILENAME.
-q function-name Query about which keys invoke the named function.
$END
#include <stdio.h>
#include "../shell.h"
#if defined (READLINE)
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#include <readline/readline.h>
#include <readline/history.h>
#include "bashgetopt.h"
static int query_bindings ();
extern int bash_readline_initialized;
extern int no_line_editing;
#define BIND_RETURN(x) do { return_code = x; goto bind_exit; } while (0)
#define USAGE "usage: bind [-lvd] [-m keymap] [-f filename] [-q name] [keyseq:readline_func]"
int
bind_builtin (list)
WORD_LIST *list;
{
int return_code = EXECUTION_SUCCESS;
FILE *old_rl_outstream;
Keymap kmap, saved_keymap;
int lflag, dflag, fflag, vflag, qflag, mflag, opt;
char *initfile, *map_name, *fun_name;
if (no_line_editing)
return (EXECUTION_FAILURE);
kmap = saved_keymap = (Keymap) NULL;
lflag = dflag = vflag = fflag = qflag = mflag = 0;
initfile = map_name = fun_name = (char *)NULL;
if (!bash_readline_initialized)
initialize_readline ();
/* Cannot use unwind_protect_pointer () on "FILE *", it is only
guaranteed to work for strings. */
/* XXX -- see if we can use unwind_protect here */
old_rl_outstream = rl_outstream;
rl_outstream = stdout;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "lvdf:q:m:")) != EOF)
{
switch (opt)
{
case 'l':
lflag++;
break;
case 'v':
vflag++;
break;
case 'd':
dflag++;
break;
case 'f':
fflag++;
initfile = list_optarg;
break;
case 'm':
mflag++;
map_name = list_optarg;
break;
case 'q':
qflag++;
fun_name = list_optarg;
break;
default:
builtin_error (USAGE);
BIND_RETURN (EX_USAGE);
}
}
list = loptend;
/* First, see if we need to install a special keymap for this
command. Then start on the arguments. */
if (mflag && map_name)
{
kmap = rl_get_keymap_by_name (map_name);
if (!kmap)
{
builtin_error ("`%s': illegal keymap name", map_name);
BIND_RETURN (EXECUTION_FAILURE);
}
}
if (kmap)
{
saved_keymap = rl_get_keymap ();
rl_set_keymap (kmap);
}
/* XXX - we need to add exclusive use tests here. It doesn't make sense
to use some of these options together. */
/* Now hack the option arguments */
if (lflag)
rl_list_funmap_names (0);
if (vflag)
rl_function_dumper (0);
if (dflag)
rl_function_dumper (1);
if (fflag && initfile)
{
if (rl_read_init_file (initfile) != 0)
{
builtin_error ("cannot read %s: %s", initfile, strerror (errno));
BIND_RETURN (EXECUTION_FAILURE);
}
}
if (qflag && fun_name)
return_code = query_bindings (fun_name);
/* Process the rest of the arguments as binding specifications. */
while (list)
{
rl_parse_and_bind (list->word->word);
list = list->next;
}
bind_exit:
if (saved_keymap)
rl_set_keymap (saved_keymap);
rl_outstream = old_rl_outstream;
return (return_code);
}
static int
query_bindings (name)
char *name;
{
Function *function;
char **keyseqs;
int j;
function = rl_named_function (name);
if (!function)
{
builtin_error ("unknown function name `%s'", name);
return EXECUTION_FAILURE;
}
keyseqs = rl_invoking_keyseqs (function);
if (!keyseqs)
{
printf ("%s is not bound to any keys.\n", name);
return EXECUTION_FAILURE;
}
printf ("%s can be invoked via ", name);
for (j = 0; j < 5 && keyseqs[j]; j++)
printf ("\"%s\"%s", keyseqs[j], keyseqs[j + 1] ? ", " : ".\n");
if (keyseqs[j])
printf ("...\n");
free_array (keyseqs);
return EXECUTION_SUCCESS;
}
#endif /* READLINE */

110
builtins/break.def Normal file
View file

@ -0,0 +1,110 @@
This file is break.def, from which is created break.c.
It implements the builtins "break" and "continue" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES break.c
$BUILTIN break
$FUNCTION break_builtin
$SHORT_DOC break [n]
Exit from within a FOR, WHILE or UNTIL loop. If N is specified,
break N levels.
$END
#include "../shell.h"
extern char *this_command_name;
static int check_loop_level ();
/* The depth of while's and until's. */
int loop_level = 0;
/* Non-zero when a "break" instruction is encountered. */
int breaking = 0;
/* Non-zero when we have encountered a continue instruction. */
int continuing = 0;
/* Set up to break x levels, where x defaults to 1, but can be specified
as the first argument. */
break_builtin (list)
WORD_LIST *list;
{
int newbreak;
if (!check_loop_level ())
return (EXECUTION_FAILURE);
newbreak = get_numeric_arg (list);
if (newbreak <= 0)
return (EXECUTION_FAILURE);
if (newbreak > loop_level)
newbreak = loop_level;
breaking = newbreak;
return (EXECUTION_SUCCESS);
}
$BUILTIN continue
$FUNCTION continue_builtin
$SHORT_DOC continue [n]
Resume the next iteration of the enclosing FOR, WHILE or UNTIL loop.
If N is specified, resume at the N-th enclosing loop.
$END
/* Set up to continue x levels, where x defaults to 1, but can be specified
as the first argument. */
continue_builtin (list)
WORD_LIST *list;
{
int newcont;
if (!check_loop_level ())
return (EXECUTION_FAILURE);
newcont = get_numeric_arg (list);
if (newcont <= 0)
return (EXECUTION_FAILURE);
if (newcont > loop_level)
newcont = loop_level;
continuing = newcont;
return (EXECUTION_SUCCESS);
}
/* Return non-zero if a break or continue command would be okay.
Print an error message if break or continue is meaningless here. */
static int
check_loop_level ()
{
#if defined (BREAK_COMPLAINS)
if (!loop_level)
builtin_error ("Only meaningful in a `for', `while', or `until' loop");
#endif /* BREAK_COMPLAINS */
return (loop_level);
}

67
builtins/builtin.def Normal file
View file

@ -0,0 +1,67 @@
This file is builtin.def, from which is created builtin.c.
It implements the builtin "builtin" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES builtin.c
$BUILTIN builtin
$FUNCTION builtin_builtin
$SHORT_DOC builtin [shell-builtin [arg ...]]
Run a shell builtin. This is useful when you wish to rename a
shell builtin to be a function, but need the functionality of the
builtin within the function itself.
$END
#include "../shell.h"
#include "common.h"
extern char *this_command_name;
/* Run the command mentioned in list directly, without going through the
normal alias/function/builtin/filename lookup process. */
builtin_builtin (list)
WORD_LIST *list;
{
Function *function;
register char *command;
if (!list)
return (EXECUTION_SUCCESS);
command = (list->word->word);
#if defined (DISABLED_BUILTINS)
function = builtin_address (command);
#else /* !DISABLED_BUILTINS */
function = find_shell_builtin (command);
#endif /* !DISABLED_BUILTINS */
if (!function)
{
builtin_error ("%s: not a shell builtin", command);
return (EXECUTION_FAILURE);
}
else
{
this_command_name = command;
list = list->next;
return ((*function) (list));
}
}

689
builtins/cd.def Normal file
View file

@ -0,0 +1,689 @@
This file is cd.def, from which is created cd.c. It implements the
builtins "cd", "pwd", "pushd", "popd", and "dirs" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES cd.c
#include <stdio.h>
#include <sys/param.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include <errno.h>
#include <tilde/tilde.h>
#include "../shell.h"
#include "../flags.h"
#include "../maxpath.h"
#include "common.h"
#if !defined (errno)
extern int errno;
#endif /* !errno */
static int change_to_directory (), cd_to_string ();
$BUILTIN cd
$FUNCTION cd_builtin
$SHORT_DOC cd [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 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 variable `cdable_vars' exists, then try the word as a variable
name. If that variable has a value, then cd to the value of that
variable.
$END
/* This builtin is ultimately the way that all user-visible commands should
change the current working directory. It is called by cd_to_string (),
so the programming interface is simple, and it handles errors and
restrictions properly. */
int
cd_builtin (list)
WORD_LIST *list;
{
char *dirname;
#if defined (RESTRICTED_SHELL)
if (restricted)
{
builtin_error ("restricted");
return (EXECUTION_FAILURE);
}
#endif /* RESTRICTED_SHELL */
if (list)
{
char *extract_colon_unit ();
char *path_string = get_string_value ("CDPATH");
char *path;
int path_index = 0, dirlen, pathlen;
dirname = list->word->word;
if (path_string && !absolute_pathname (dirname))
{
while ((path = extract_colon_unit (path_string, &path_index)))
{
char *dir;
if (*path == '~')
{
char *te_string = tilde_expand (path);
free (path);
path = te_string;
}
if (!*path)
{
free (path);
path = xmalloc (2);
path[0] = '.'; /* by definition. */
path[1] = '\0';
}
dirlen = strlen (dirname);
pathlen = strlen (path);
dir = xmalloc (2 + dirlen + pathlen);
strcpy (dir, path);
if (path[pathlen - 1] != '/')
{
dir[pathlen++] = '/';
dir[pathlen] = '\0';
}
strcpy (dir + pathlen, dirname);
free (path);
if (change_to_directory (dir))
{
/* replaces (strncmp (dir, "./", 2) != 0) */
if (dir[0] != '.' || dir[1] != '/')
printf ("%s\n", dir);
free (dir);
goto bind_and_exit;
}
else
free (dir);
}
}
if (!change_to_directory (dirname))
{
/* Maybe this is `cd -', equivalent to `cd $OLDPWD' */
if (dirname[0] == '-' && dirname[1] == '\0')
{
char *t = get_string_value ("OLDPWD");
if (t && change_to_directory (t))
goto bind_and_exit;
}
/* If the user requests it, then perhaps this is the name of
a shell variable, whose value contains the directory to
change to. If that is the case, then change to that
directory. */
if (find_variable ("cdable_vars"))
{
char *t = get_string_value (dirname);
if (t && change_to_directory (t))
{
printf ("%s\n", t);
goto bind_and_exit;
}
}
file_error (dirname);
return (EXECUTION_FAILURE);
}
goto bind_and_exit;
}
else
{
dirname = get_string_value ("HOME");
if (!dirname)
return (EXECUTION_FAILURE);
if (!change_to_directory (dirname))
{
file_error (dirname);
return (EXECUTION_FAILURE);
}
bind_and_exit:
{
char *directory;
directory = get_working_directory ("cd");
bind_variable ("OLDPWD", get_string_value ("PWD"));
bind_variable ("PWD", directory);
FREE (directory);
}
return (EXECUTION_SUCCESS);
}
}
$BUILTIN pwd
$FUNCTION pwd_builtin
$SHORT_DOC pwd
Print the current working directory.
$END
/* Non-zero means that pwd always give verbatim directory, regardless of
symbolic link following. */
static int verbatim_pwd;
/* Print the name of the current working directory. */
pwd_builtin (list)
WORD_LIST *list;
{
char *directory, *s;
#if 0
no_args (list);
#else
verbatim_pwd = no_symbolic_links;
if (list && (s = list->word->word) && s[0] == '-' && s[1] == 'P' && !s[2])
verbatim_pwd = 1;
#endif
if (verbatim_pwd)
{
char *buffer = xmalloc (MAXPATHLEN);
directory = getwd (buffer);
if (!directory)
{
builtin_error ("%s", buffer);
free (buffer);
}
}
else
directory = get_working_directory ("pwd");
if (directory)
{
printf ("%s\n", directory);
fflush (stdout);
free (directory);
return (EXECUTION_SUCCESS);
}
else
return (EXECUTION_FAILURE);
}
$BUILTIN pushd
$FUNCTION pushd_builtin
$DEPENDS_ON PUSHD_AND_POPD
$SHORT_DOC pushd [dir | +n | -n]
Adds a directory to the top of the directory stack, or rotates
the stack, making the new top of the stack the current working
directory. With no arguments, exchanges the top two directories.
+n Rotates the stack so that the Nth directory (counting
from the left of the list shown by `dirs') is at the top.
-n Rotates the stack so that the Nth directory (counting
from the right) is at the top.
dir adds DIR to the directory stack at the top, making it the
new current working directory.
You can see the directory stack with the `dirs' command.
$END
#if defined (PUSHD_AND_POPD)
/* Some useful commands whose behaviour has been observed in Csh. */
/* The list of remembered directories. */
static char **pushd_directory_list = (char **)NULL;
/* Number of existing slots in this list. */
static int directory_list_size = 0;
/* Offset to the end of the list. */
static int directory_list_offset = 0;
pushd_builtin (list)
WORD_LIST *list;
{
char *temp, *current_directory;
int j = directory_list_offset - 1;
char direction = '+';
/* If there is no argument list then switch current and
top of list. */
if (!list)
{
if (!directory_list_offset)
{
builtin_error ("No other directory");
return (EXECUTION_FAILURE);
}
current_directory = get_working_directory ("pushd");
if (!current_directory)
return (EXECUTION_FAILURE);
temp = pushd_directory_list[j];
pushd_directory_list[j] = current_directory;
goto change_to_temp;
}
else
{
direction = *(list->word->word);
if (direction == '+' || direction == '-')
{
int num;
if (1 == sscanf (&(list->word->word)[1], "%d", &num))
{
if (direction == '-')
num = directory_list_offset - num;
if (num > directory_list_offset || num < 0)
{
if (!directory_list_offset)
builtin_error ("Directory stack empty");
else
builtin_error ("Stack contains only %d directories",
directory_list_offset + 1);
return (EXECUTION_FAILURE);
}
else
{
/* Rotate the stack num times. Remember, the
current directory acts like it is part of the
stack. */
temp = get_working_directory ("pushd");
if (!num)
goto change_to_temp;
do
{
char *top =
pushd_directory_list[directory_list_offset - 1];
for (j = directory_list_offset - 2; j > -1; j--)
pushd_directory_list[j + 1] = pushd_directory_list[j];
pushd_directory_list[j + 1] = temp;
temp = top;
num--;
}
while (num);
temp = savestring (temp);
change_to_temp:
{
int tt = EXECUTION_FAILURE;
if (temp)
{
tt = cd_to_string (temp);
free (temp);
}
if ((tt == EXECUTION_SUCCESS))
dirs_builtin ((WORD_LIST *)NULL);
return (tt);
}
}
}
}
/* Change to the directory in list->word->word. Save the current
directory on the top of the stack. */
current_directory = get_working_directory ("pushd");
if (!current_directory)
return (EXECUTION_FAILURE);
if (cd_builtin (list) == EXECUTION_SUCCESS)
{
if (directory_list_offset == directory_list_size)
{
pushd_directory_list = (char **)
xrealloc (pushd_directory_list,
(directory_list_size += 10) * sizeof (char *));
}
pushd_directory_list[directory_list_offset++] = current_directory;
dirs_builtin ((WORD_LIST *)NULL);
return (EXECUTION_SUCCESS);
}
else
{
free (current_directory);
return (EXECUTION_FAILURE);
}
}
}
#endif /* PUSHD_AND_POPD */
$BUILTIN dirs
$FUNCTION dirs_builtin
$DEPENDS_ON PUSHD_AND_POPD
$SHORT_DOC dirs [-l]
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.
The -l flag specifies that `dirs' should not print shorthand versions
of directories which are relative to your home directory. This means
that `~/bin' might be displayed as `/homes/bfox/bin'.
$END
#if defined (PUSHD_AND_POPD)
/* Print the current list of directories on the directory stack. */
dirs_builtin (list)
WORD_LIST *list;
{
int i, format, desired_index, index_flag;
char *temp, *w;
format = index_flag = 0;
desired_index = -1;
/* Maybe do long form or print specific dir stack entry? */
while (list)
{
if (strcmp (list->word->word, "-l") == 0)
{
format++;
list = list->next;
}
else if (*list->word->word == '+' && all_digits (list->word->word + 1))
{
w = list->word->word + 1;
index_flag = 1;
i = atoi (w);
/* dirs +0 prints the current working directory. */
if (i == 0)
desired_index = i;
else if (i == directory_list_offset)
{
desired_index = 0;
index_flag = 2;
}
else
desired_index = directory_list_offset - i;
list = list->next;
}
else if (*list->word->word == '-' && all_digits (list->word->word + 1))
{
w = list->word->word + 1;
i = atoi (w);
index_flag = 2;
/* dirs -X where X is directory_list_offset prints the current
working directory. */
if (i == directory_list_offset)
{
index_flag = 1;
desired_index = 0;
}
else
desired_index = i;
list = list->next;
}
else
{
bad_option (list->word->word);
return (EXECUTION_FAILURE);
}
}
if (index_flag && (desired_index < 0 || desired_index > directory_list_offset))
{
if (directory_list_offset == 0)
builtin_error ("directory stack empty");
else
builtin_error ("%s: bad directory stack index", w);
return (EXECUTION_FAILURE);
}
/* The first directory printed is always the current working directory. */
if (!index_flag || (index_flag == 1 && desired_index == 0))
{
temp = get_working_directory ("dirs");
if (!temp)
temp = savestring ("<no directory>");
printf ("%s", format ? temp : polite_directory_format (temp));
free (temp);
if (index_flag)
{
putchar ('\n');
return EXECUTION_SUCCESS;
}
}
#define DIRSTACK_ENTRY(i) \
format ? pushd_directory_list[i] \
: polite_directory_format (pushd_directory_list[i])
/* Now print the requested directory stack entries. */
if (index_flag)
printf ("%s", DIRSTACK_ENTRY (desired_index));
else
for (i = (directory_list_offset - 1); i > -1; i--)
printf (" %s", DIRSTACK_ENTRY (i));
putchar ('\n');
fflush (stdout);
return (EXECUTION_SUCCESS);
}
#endif /* PUSHD_AND_POPD */
$BUILTIN popd
$FUNCTION popd_builtin
$DEPENDS_ON PUSHD_AND_POPD
$SHORT_DOC popd [+n | -n]
Removes entries from the directory stack. With no arguments,
removes the top directory from the stack, and cd's to the new
top directory.
+n removes the Nth entry counting from the left of the list
shown by `dirs', starting with zero. For example: `popd +0'
removes the first directory, `popd +1' the second.
-n removes the Nth entry counting from the right of the list
shown by `dirs', starting with zero. For example: `popd -0'
removes the last directory, `popd -1' the next to last.
You can see the directory stack with the `dirs' command.
$END
#if defined (PUSHD_AND_POPD)
/* Pop the directory stack, and then change to the new top of the stack.
If LIST is non-null it should consist of a word +N or -N, which says
what element to delete from the stack. The default is the top one. */
popd_builtin (list)
WORD_LIST *list;
{
register int i;
int which = 0;
char direction = '+';
if (list)
{
direction = *(list->word->word);
if ((direction != '+' && direction != '-') ||
(1 != sscanf (&((list->word->word)[1]), "%d", &which)))
{
builtin_error ("bad arg `%s'", list->word->word);
return (EXECUTION_FAILURE);
}
}
if (which > directory_list_offset || (!directory_list_offset && !which))
{
if (!directory_list_offset)
builtin_error ("Directory stack empty");
else
builtin_error ("Stack contains only %d directories",
directory_list_offset + 1);
return (EXECUTION_FAILURE);
}
/* Handle case of no specification, or top of stack specification. */
if ((direction == '+' && which == 0) ||
(direction == '-' && which == directory_list_offset))
{
i = cd_to_string (pushd_directory_list[directory_list_offset - 1]);
if (i != EXECUTION_SUCCESS)
return (i);
free (pushd_directory_list[--directory_list_offset]);
}
else
{
/* Since an offset other than the top directory was specified,
remove that directory from the list and shift the remainder
of the list into place. */
if (direction == '+')
i = directory_list_offset - which;
else
i = which;
free (pushd_directory_list[i]);
directory_list_offset--;
/* Shift the remainder of the list into place. */
for (; i < directory_list_offset; i++)
pushd_directory_list[i] = pushd_directory_list[i + 1];
}
dirs_builtin ((WORD_LIST *)NULL);
return (EXECUTION_SUCCESS);
}
#endif /* PUSHD_AND_POPD */
/* Do the work of changing to the directory NEWDIR. Handle symbolic
link following, etc. */
static int
change_to_directory (newdir)
char *newdir;
{
char *t;
if (!no_symbolic_links)
{
int chdir_return = 0;
char *tdir = (char *)NULL;
if (!the_current_working_directory)
{
t = get_working_directory ("cd_links");
FREE (t);
}
if (the_current_working_directory)
t = make_absolute (newdir, the_current_working_directory);
else
t = savestring (newdir);
/* TDIR is the canonicalized absolute pathname of the NEWDIR. */
tdir = canonicalize_pathname (t);
/* Use the canonicalized version of NEWDIR, or, if canonicalization
failed, use the non-canonical form. */
if (tdir && *tdir)
free (t);
else
{
FREE (tdir);
tdir = t;
}
if (chdir (tdir) < 0)
{
int err;
chdir_return = 0;
free (tdir);
err = errno;
/* We failed changing to the canonicalized directory name. Try
what the user passed verbatim. If we succeed, reinitialize
the_current_working_directory. */
if (chdir (newdir) == 0)
{
chdir_return = 1;
if (the_current_working_directory)
{
free (the_current_working_directory);
the_current_working_directory = (char *)NULL;
}
tdir = get_working_directory ("cd");
FREE (tdir);
}
else
errno = err;
}
else
{
chdir_return = 1;
FREE (the_current_working_directory);
the_current_working_directory = tdir;
}
return (chdir_return);
}
else
{
if (chdir (newdir) < 0)
return (0);
else
return (1);
}
}
/* Switch to the directory in NAME. This uses the cd_builtin to do the work,
so if the result is EXECUTION_FAILURE then an error message has already
been printed. */
static int
cd_to_string (name)
char *name;
{
WORD_LIST *tlist = make_word_list (make_word (name), NULL);
int result = (cd_builtin (tlist));
dispose_words (tlist);
return (result);
}

37
builtins/colon.def Normal file
View file

@ -0,0 +1,37 @@
This file is colon.def, from which is created colon.c.
It implements the builtin ":" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES colon.c
$BUILTIN :
$DOCNAME colon_builtin
$FUNCTION colon_builtin
$SHORT_DOC :
No effect; the command does nothing. A zero exit code is returned.
$END
/* Do nothing. This command is a no-op. */
int
colon_builtin (ignore)
char *ignore;
{
return (0);
}

177
builtins/command.def Normal file
View file

@ -0,0 +1,177 @@
This file is command.def, from which is created command.c.
It implements the builtin "command" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES command.c
$BUILTIN command
$FUNCTION command_builtin
$SHORT_DOC command [-pVv] [command [arg ...]]
Runs COMMAND with ARGS ignoring shell functions. If you have a shell
function called `ls', and you wish to call the command `ls', you can
say "command ls". If the -p option is given, a default value is used
for PATH that is guaranteed to find all of the standard utilities. If
the -V or -v option is given, a string is printed describing COMMAND.
The -V option produces a more verbose description.
$END
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "../shell.h"
#include "bashgetopt.h"
extern int subshell_environment;
static void restore_path ();
static char *get_standard_path ();
/* Run the commands mentioned in LIST without paying attention to shell
functions. */
int
command_builtin (list)
WORD_LIST *list;
{
int result, verbose = 0, use_standard_path = 0, opt;
char *old_path;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "pvV")) != -1)
{
switch (opt)
{
case 'p':
use_standard_path = 1;
break;
case 'V':
verbose = 2;
break;
case 'v':
verbose = 4;
break;
default:
report_bad_option ();
builtin_error ("usage: command [-pvV] [command [arg...]]");
return (EX_USAGE);
}
}
list = loptend;
if (!list)
return (EXECUTION_SUCCESS);
if (verbose)
{
int found, any_found = 0;
while (list)
{
found = describe_command (list->word->word, verbose, 0);
if (!found)
builtin_error ("%s: not found", list->word->word);
any_found += found;
list = list->next;
}
return (any_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
begin_unwind_frame ("command_builtin");
/* We don't want this to be reparsed (consider command echo 'foo &'), so
just make a simple_command structure and call execute_command with it. */
{
COMMAND *command;
if (use_standard_path)
{
char *standard_path;
old_path = get_string_value ("PATH");
if (old_path)
old_path = savestring (old_path);
else
old_path = savestring ("");
add_unwind_protect ((Function *)restore_path, old_path);
standard_path = get_standard_path ();
bind_variable ("PATH", standard_path);
free (standard_path);
}
command = make_bare_simple_command ();
command->value.Simple->words = (WORD_LIST *)copy_word_list (list);
command->value.Simple->redirects = (REDIRECT *)NULL;
command->flags |= (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION);
command->value.Simple->flags |= (CMD_NO_FUNCTIONS | CMD_INHIBIT_EXPANSION);
/* If we're in a subshell, see if we can get away without forking
again, since we've already forked to run this builtin. */
if (subshell_environment)
{
command->flags |= CMD_NO_FORK;
command->value.Simple->flags |= CMD_NO_FORK;
}
add_unwind_protect ((char *)dispose_command, command);
result = execute_command (command);
}
run_unwind_frame ("command_builtin");
return (result);
}
/* Restore the value of the $PATH variable after replacing it when
executing `command -p'. */
static void
restore_path (var)
char *var;
{
bind_variable ("PATH", var);
free (var);
}
/* Return a value for PATH that is guaranteed to find all of the standard
utilities. This uses Posix.2 configuration variables, if present. It
uses a value defined in config.h as a last resort. */
static char *
get_standard_path ()
{
#if defined (_CS_PATH) && !defined (hpux_7) && !defined (NetBSD)
char *p;
size_t len;
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 || hpux_7 || NetBSD */
# if defined (CS_PATH)
return (savestring (CS_PATH));
# else
return (savestring (STANDARD_UTILS_PATH));
# endif /* !CS_PATH */
#endif /* !_CS_PATH || hpux_7 */
}

829
builtins/common.c Normal file
View file

@ -0,0 +1,829 @@
/* Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <sys/types.h>
#include "../posixstat.h"
#if defined (HAVE_VFPRINTF)
#include <varargs.h>
#endif /* VFPRINTF */
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "../shell.h"
#include "../unwind_prot.h"
#include "../maxpath.h"
#include "../jobs.h"
#include "../builtins.h"
#include "../input.h"
#include "../execute_cmd.h"
#include "hashcom.h"
#include "common.h"
#include <tilde/tilde.h>
#if defined (HISTORY)
# include "../bashhist.h"
#endif
extern int no_symbolic_links, interactive, interactive_shell;
extern int indirection_level, startup_state;
extern int last_command_exit_value;
extern int hashing_disabled;
extern int variable_context;
extern char *this_command_name, *shell_name;
extern COMMAND *global_command;
extern HASH_TABLE *hashed_filenames;
/* Read a numeric arg for this_command_name, the name of the shell builtin
that wants it. LIST is the word list that the arg is to come from. */
int
get_numeric_arg (list)
WORD_LIST *list;
{
int count = 1;
if (list)
{
register char *arg;
int sign = 1;
arg = list->word->word;
if (!arg)
goto bad_number;
/* Skip optional leading white space. */
while (whitespace (*arg))
arg++;
if (!*arg)
goto bad_number;
/* We allow leading `-' or `+'. */
if (*arg == '-' || *arg == '+')
{
if (!digit (arg[1]))
goto bad_number;
if (*arg == '-')
sign = -1;
arg++;
}
for (count = 0; digit (*arg); arg++)
count = (count * 10) + digit_value (*arg);
/* Skip trailing whitespace, if any. */
while (whitespace (*arg))
arg++;
if (!*arg)
count = count * sign;
else
{
bad_number:
builtin_error ("bad non-numeric arg `%s'", list->word->word);
throw_to_top_level ();
}
no_args (list->next);
}
return (count);
}
/* This is a lot like report_error (), but it is for shell builtins
instead of shell control structures, and it won't ever exit the
shell. */
#if defined (HAVE_VFPRINTF)
void
builtin_error (va_alist)
va_dcl
{
char *format;
va_list args;
if (this_command_name && *this_command_name)
fprintf (stderr, "%s: ", this_command_name);
va_start (args);
format = va_arg (args, char *);
vfprintf (stderr, format, args);
va_end (args);
fprintf (stderr, "\n");
}
#else /* !HAVE_VFPRINTF */
void
builtin_error (format, arg1, arg2, arg3, arg4, arg5)
char *format, *arg1, *arg2, *arg3, *arg4, *arg5;
{
if (this_command_name && *this_command_name)
fprintf (stderr, "%s: ", this_command_name);
fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
fprintf (stderr, "\n");
fflush (stderr);
}
#endif /* !HAVE_VFPRINTF */
/* Remember LIST in $0 ... $9, and REST_OF_ARGS. If DESTRUCTIVE is
non-zero, then discard whatever the existing arguments are, else
only discard the ones that are to be replaced. */
void
remember_args (list, destructive)
WORD_LIST *list;
int destructive;
{
register int i;
for (i = 1; i < 10; i++)
{
if (destructive && dollar_vars[i])
{
free (dollar_vars[i]);
dollar_vars[i] = (char *)NULL;
}
if (list)
{
if (!destructive && dollar_vars[i])
free (dollar_vars[i]);
dollar_vars[i] = savestring (list->word->word);
list = list->next;
}
}
/* If arguments remain, assign them to REST_OF_ARGS.
Note that copy_word_list (NULL) returns NULL, and
that dispose_words (NULL) does nothing. */
if (destructive || list)
{
dispose_words (rest_of_args);
rest_of_args = copy_word_list (list);
}
if (destructive)
set_dollar_vars_changed ();
}
/* Return if LIST is NULL else barf and jump to top_level. */
void
no_args (list)
WORD_LIST *list;
{
if (list)
{
builtin_error ("extra arguments");
longjmp (top_level, DISCARD);
}
}
/* Return the octal number parsed from STRING, or -1 to indicate
that the string contained a bad number. */
int
read_octal (string)
char *string;
{
int result = 0;
int digits = 0;
while (*string && *string >= '0' && *string < '8')
{
digits++;
result = (result * 8) + *string++ - '0';
}
if (!digits || result > 0777 || *string)
result = -1;
return (result);
}
/* Temporary static. */
static char *dotted_filename = (char *)NULL;
/* Return the full pathname that FILENAME hashes to. If FILENAME
is hashed, but data->check_dot is non-zero, check ./FILENAME
and return that if it is executable. */
char *
find_hashed_filename (filename)
char *filename;
{
register BUCKET_CONTENTS *item;
if (hashing_disabled)
return ((char *)NULL);
item = find_hash_item (filename, hashed_filenames);
if (item)
{
/* If this filename is hashed, but `.' comes before it in the path,
then see if `./filename' is an executable. */
if (pathdata(item)->check_dot)
{
if (dotted_filename)
free (dotted_filename);
dotted_filename = (char *)xmalloc (3 + strlen (filename));
strcpy (dotted_filename, "./");
strcat (dotted_filename, filename);
if (executable_file (dotted_filename))
return (dotted_filename);
/* Watch out. If this file was hashed to "./filename", and
"./filename" is not executable, then return NULL. */
/* Since we already know "./filename" is not executable, what
we're really interested in is whether or not the `path'
portion of the hashed filename is equivalent to the current
directory, but only if it starts with a `.'. (This catches
./. and so on.) same_file () is in execute_cmd.c; it tests
general Unix file equivalence -- same device and inode. */
{
char *path = pathdata (item)->path;
if (*path == '.')
{
int same = 0;
char *tail;
tail = (char *) strrchr (path, '/');
if (tail)
{
*tail = '\0';
same = same_file
(".", path, (struct stat *)NULL, (struct stat *)NULL);
*tail = '/';
}
if (same)
return ((char *)NULL);
}
}
}
return (pathdata (item)->path);
}
else
return ((char *)NULL);
}
/* Remove FILENAME from the table of hashed commands. */
void
remove_hashed_filename (filename)
char *filename;
{
register BUCKET_CONTENTS *item;
if (hashing_disabled)
return;
item = remove_hash_item (filename, hashed_filenames);
if (item)
{
if (item->data)
{
free (pathdata(item)->path);
free (item->data);
}
if (item->key)
free (item->key);
free (item);
}
}
/* **************************************************************** */
/* */
/* Pushing and Popping a Context */
/* */
/* **************************************************************** */
static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
static int dollar_arg_stack_slots = 0;
static int dollar_arg_stack_index = 0;
void
push_context ()
{
push_dollar_vars ();
variable_context++;
}
void
pop_context ()
{
pop_dollar_vars ();
kill_all_local_variables ();
variable_context--;
}
/* Save the existing positional parameters on a stack. */
void
push_dollar_vars ()
{
if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
{
dollar_arg_stack = (WORD_LIST **)
xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
* sizeof (WORD_LIST **));
}
dollar_arg_stack[dollar_arg_stack_index] = list_rest_of_args ();
dollar_arg_stack[++dollar_arg_stack_index] = (WORD_LIST *)NULL;
}
/* Restore the positional parameters from our stack. */
void
pop_dollar_vars ()
{
if (!dollar_arg_stack || !dollar_arg_stack_index)
return;
remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
}
void
dispose_saved_dollar_vars ()
{
if (!dollar_arg_stack || !dollar_arg_stack_index)
return;
dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
}
static int changed_dollar_vars = 0;
/* Have the dollar variables been reset to new values since we last
checked? */
dollar_vars_changed ()
{
return (changed_dollar_vars);
}
void
set_dollar_vars_unchanged ()
{
changed_dollar_vars = 0;
}
void
set_dollar_vars_changed ()
{
changed_dollar_vars = 1;
}
/* Function called when one of the builtin commands detects a bad
option. */
void
bad_option (s)
char *s;
{
builtin_error ("unknown option: %s", s);
}
/* Return a consed string which is the current working directory.
FOR_WHOM is the name of the caller for error printing. */
char *the_current_working_directory = (char *)NULL;
char *
get_working_directory (for_whom)
char *for_whom;
{
if (no_symbolic_links)
{
if (the_current_working_directory)
free (the_current_working_directory);
the_current_working_directory = (char *)NULL;
}
if (!the_current_working_directory)
{
char *directory;
the_current_working_directory = xmalloc (MAXPATHLEN);
directory = getwd (the_current_working_directory);
if (!directory)
{
if (for_whom && *for_whom)
fprintf (stderr, "%s: ", for_whom);
else
fprintf (stderr, "%s: ", get_name_for_error ());
fprintf (stderr, "could not get current directory: %s\n",
the_current_working_directory);
free (the_current_working_directory);
the_current_working_directory = (char *)NULL;
return (char *)NULL;
}
}
return (savestring (the_current_working_directory));
}
/* Make NAME our internal idea of the current working directory. */
void
set_working_directory (name)
char *name;
{
if (the_current_working_directory)
free (the_current_working_directory);
the_current_working_directory = savestring (name);
}
#if defined (JOB_CONTROL)
/* Return the job spec found in LIST. */
get_job_spec (list)
WORD_LIST *list;
{
register char *word;
int job = NO_JOB;
int substring = 0;
if (!list)
return (current_job);
word = list->word->word;
if (!*word)
return (current_job);
if (*word == '%')
word++;
if (digit (*word) && (sscanf (word, "%d", &job) == 1))
return (job - 1);
switch (*word)
{
case 0:
case '%':
case '+':
return (current_job);
case '-':
return (previous_job);
case '?': /* Substring search requested. */
substring++;
word++;
goto find_string;
default:
find_string:
{
register int i, wl = strlen (word);
for (i = 0; i < job_slots; i++)
{
if (jobs[i])
{
register PROCESS *p = jobs[i]->pipe;
do
{
if ((substring && strindex (p->command, word)) ||
(strncmp (p->command, word, wl) == 0))
if (job != NO_JOB)
{
builtin_error ("ambigious job spec: %s", word);
return (DUP_JOB);
}
else
job = i;
p = p->next;
}
while (p != jobs[i]->pipe);
}
}
return (job);
}
}
}
#endif /* JOB_CONTROL */
int parse_and_execute_level = 0;
/* How to force parse_and_execute () to clean up after itself. */
void
parse_and_execute_cleanup ()
{
run_unwind_frame ("parse_and_execute_top");
}
/* Parse and execute the commands in STRING. Returns whatever
execute_command () returns. This frees STRING. INTERACT is
the new value for `interactive' while the commands are being
executed. A value of -1 means don't change it. */
int
parse_and_execute (string, from_file, interact)
char *string;
char *from_file;
int interact;
{
int last_result = EXECUTION_SUCCESS;
int code = 0, jump_to_top_level = 0;
char *orig_string = string;
/* Unwind protect this invocation of parse_and_execute (). */
begin_unwind_frame ("parse_and_execute_top");
unwind_protect_int (parse_and_execute_level);
unwind_protect_jmp_buf (top_level);
unwind_protect_int (indirection_level);
if (interact != -1 && interactive != interact)
unwind_protect_int (interactive);
#if defined (HISTORY)
if (interactive_shell)
{
unwind_protect_int (remember_on_history);
# if defined (BANG_HISTORY)
unwind_protect_int (history_expansion_inhibited);
# endif /* BANG_HISTORY */
}
#endif /* HISTORY */
add_unwind_protect (pop_stream, (char *)NULL);
if (orig_string)
add_unwind_protect (xfree, orig_string);
end_unwind_frame ();
parse_and_execute_level++;
push_stream ();
indirection_level++;
if (interact != -1)
interactive = interact;
#if defined (HISTORY)
/* We don't remember text read by the shell this way on
the history list, and we don't use !$ in shell scripts. */
remember_on_history = 0;
# if defined (BANG_HISTORY)
history_expansion_inhibited = 1;
# endif /* BANG_HISTORY */
#endif /* HISTORY */
with_input_from_string (string, from_file);
{
COMMAND *command;
while (*(bash_input.location.string))
{
if (interrupt_state)
{
last_result = EXECUTION_FAILURE;
break;
}
/* Provide a location for functions which `longjmp (top_level)' to
jump to. This prevents errors in substitution from restarting
the reader loop directly, for example. */
code = setjmp (top_level);
if (code)
{
jump_to_top_level = 0;
switch (code)
{
case FORCE_EOF:
case EXITPROG:
run_unwind_frame ("pe_dispose");
/* Remember to call longjmp (top_level) after the old
value for it is restored. */
jump_to_top_level = 1;
goto out;
case DISCARD:
dispose_command (command);
run_unwind_frame ("pe_dispose");
last_command_exit_value = 1;
continue;
default:
programming_error ("bad jump to top_level: %d", code);
break;
}
}
if (parse_command () == 0)
{
if ((command = global_command) != (COMMAND *)NULL)
{
struct fd_bitmap *bitmap;
bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
begin_unwind_frame ("pe_dispose");
add_unwind_protect (dispose_fd_bitmap, bitmap);
global_command = (COMMAND *)NULL;
#if defined (ONESHOT)
if (startup_state == 2 && *bash_input.location.string == '\0' &&
command->type == cm_simple && !command->redirects &&
!command->value.Simple->redirects)
{
command->flags |= CMD_NO_FORK;
command->value.Simple->flags |= CMD_NO_FORK;
}
#endif /* ONESHOT */
last_result = execute_command_internal
(command, 0, NO_PIPE, NO_PIPE, bitmap);
dispose_command (command);
run_unwind_frame ("pe_dispose");
}
}
else
{
last_result = EXECUTION_FAILURE;
/* Since we are shell compatible, syntax errors in a script
abort the execution of the script. Right? */
break;
}
}
}
out:
run_unwind_frame ("parse_and_execute_top");
if (interrupt_state && parse_and_execute_level == 0)
{
/* An interrupt during non-interactive execution in an
interactive shell (e.g. via $PROMPT_COMMAND) should
not cause the shell to exit. */
interactive = interactive_shell;
throw_to_top_level ();
}
if (jump_to_top_level)
longjmp (top_level, code);
return (last_result);
}
/* Return the address of the builtin named NAME.
DISABLED_OKAY means find it even if the builtin is disabled. */
static Function *
builtin_address_internal (name, disabled_okay)
char *name;
int disabled_okay;
{
int hi, lo, mid, j;
hi = num_shell_builtins - 1;
lo = 0;
while (lo <= hi)
{
mid = (lo + hi) / 2;
j = shell_builtins[mid].name[0] - name[0];
if (j == 0)
j = strcmp (shell_builtins[mid].name, name);
if (j == 0)
{
/* It must have a function pointer. It must be enabled, or we
must have explicitly allowed disabled functions to be found. */
if (shell_builtins[mid].function &&
((shell_builtins[mid].flags & BUILTIN_ENABLED) || disabled_okay))
return (shell_builtins[mid].function);
else
return ((Function *)NULL);
}
if (j > 0)
hi = mid - 1;
else
lo = mid + 1;
}
return ((Function *)NULL);
}
/* Perform a binary search and return the address of the builtin function
whose name is NAME. If the function couldn't be found, or the builtin
is disabled or has no function associated with it, return NULL. */
Function *
find_shell_builtin (name)
char *name;
{
return (builtin_address_internal (name, 0));
}
/* Return the address of builtin with NAME, irregardless of its state of
enableness. */
Function *
builtin_address (name)
char *name;
{
return (builtin_address_internal (name, 1));
}
static int
shell_builtin_compare (sbp1, sbp2)
struct builtin *sbp1, *sbp2;
{
int result;
if ((result = sbp1->name[0] - sbp2->name[0]) == 0)
result = strcmp (sbp1->name, sbp2->name);
return (result);
}
/* Sort the table of shell builtins so that the binary search will work
in find_shell_builtin. */
void
initialize_shell_builtins ()
{
qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin),
shell_builtin_compare);
}
/* Return a new string which is the quoted version of STRING. This is used
by alias and trap. */
char *
single_quote (string)
char *string;
{
register int i, j, c;
char *result;
result = (char *)xmalloc (3 + (3 * strlen (string)));
result[0] = '\'';
for (i = 0, j = 1; string && (c = string[i]); i++)
{
result[j++] = c;
if (c == '\'')
{
result[j++] = '\\'; /* insert escaped single quote */
result[j++] = '\'';
result[j++] = '\''; /* start new quoted string */
}
}
result[j++] = '\'';
result[j] = '\0';
return (result);
}
char *
double_quote (string)
char *string;
{
register int i, j, c;
char *result;
result = (char *)xmalloc (3 + (3 * strlen (string)));
result[0] = '"';
for (i = 0, j = 1; string && (c = string[i]); i++)
{
switch (c)
{
case '"':
case '$':
case '`':
case '\\':
result[j++] = '\\';
default:
result[j++] = c;
break;
}
}
result[j++] = '"';
result[j] = '\0';
return (result);
}

69
builtins/common.h Normal file
View file

@ -0,0 +1,69 @@
/* common.h -- extern declarations for functions defined in common.c. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (__COMMON_H)
# define __COMMON_H
#define ISOPTION(s, c) (s[0] == '-' && !s[2] && s[1] == c)
extern void builtin_error ();
extern void bad_option ();
extern int get_numeric_arg ();
extern void remember_args ();
extern void no_args ();
extern int read_octal ();
extern char *find_hashed_filename ();
extern void remove_hashed_filename ();
extern void remember_filename ();
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 parse_and_execute ();
extern void parse_and_execute_cleanup ();
extern void initialize_shell_builtins ();
/* It's OK to declare a function as returning a Function * without
providing a definition of what a `Function' is. */
extern Function *find_shell_builtin ();
extern Function *builtin_address ();
extern char *single_quote ();
extern char *double_quote ();
#endif /* !__COMMON_H */

290
builtins/declare.def Normal file
View file

@ -0,0 +1,290 @@
This file is declare.def, from which is created declare.c.
It implements the builtins "declare" and "local" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES declare.c
$BUILTIN declare
$FUNCTION declare_builtin
$SHORT_DOC declare [-[frxi]] name[=value] ...
Declare variables and/or give them attributes. If no NAMEs are
given, then display the values of variables instead.
The flags are:
-f to select from among function names only,
-r to make NAMEs readonly,
-x to make NAMEs export,
-i to make NAMEs have the `integer' attribute set.
Variables with the integer attribute have arithmetic evaluation (see
`let') done when the variable is assigned to.
Using `+' instead of `-' turns off the given attribute instead. When
used in a function, makes NAMEs local, as with the `local' command.
$END
$BUILTIN typeset
$FUNCTION declare_builtin
$SHORT_DOC typeset [-[frxi]] name[=value] ...
Obsolete. See `declare'.
$END
#include <stdio.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "../shell.h"
extern int variable_context, array_needs_making;
static int declare_internal ();
/* Declare or change variable attributes. */
int
declare_builtin (list)
register WORD_LIST *list;
{
return (declare_internal (list, 0));
}
$BUILTIN local
$FUNCTION local_builtin
$SHORT_DOC local name[=value] ...
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.
$END
int
local_builtin (list)
register WORD_LIST *list;
{
if (variable_context)
return (declare_internal (list, 1));
else
{
builtin_error ("Can only be used in a function");
return (EXECUTION_FAILURE);
}
}
/* The workhorse function. */
static int
declare_internal (list, local_var)
register WORD_LIST *list;
int local_var;
{
int flags_on = 0, flags_off = 0;
int any_failed = 0;
while (list)
{
register char *t = list->word->word;
int *flags;
if (t[0] == '-' && t[1] == '-' && t[2] == '\0')
{
list = list->next;
break;
}
if (*t != '+' && *t != '-')
break;
if (*t == '+')
flags = &flags_off;
else
flags = &flags_on;
t++;
while (*t)
{
if (*t == 'f')
*flags |= att_function, t++;
else if (*t == 'x')
*flags |= att_exported, t++, array_needs_making = 1;
else if (*t == 'r')
*flags |= att_readonly, t++;
else if (*t == 'i')
*flags |= att_integer, t++;
else
{
builtin_error ("unknown option: `-%c'", *t);
return (EX_USAGE);
}
}
list = list->next;
}
/* If there are no more arguments left, then we just want to show
some variables. */
if (!list)
{
/* Show local variables defined at this context level if this is
the `local' builtin. */
if (local_var)
{
register SHELL_VAR **vlist;
register int i;
vlist = map_over (variable_in_context, shell_variables);
if (vlist)
{
for (i = 0; vlist[i]; i++)
print_assignment (vlist[i]);
free (vlist);
}
}
else
{
if (!flags_on)
set_builtin ((WORD_LIST *)NULL);
else
set_or_show_attributes ((WORD_LIST *)NULL, flags_on);
}
fflush (stdout);
return (EXECUTION_SUCCESS);
}
#define NEXT_VARIABLE() free (name); list = list->next; continue
/* There are arguments left, so we are making variables. */
while (list)
{
char *value, *name = savestring (list->word->word);
int offset = assignment (name);
if (offset)
{
name[offset] = '\0';
value = name + offset + 1;
}
else
value = "";
if (legal_identifier (name) == 0)
{
builtin_error ("%s: not a legal variable name", name);
any_failed++;
NEXT_VARIABLE ();
}
/* If VARIABLE_CONTEXT has a non-zero value, then we are executing
inside of a function. This means we should make local variables,
not global ones. */
if (variable_context)
make_local_variable (name);
/* If we are declaring a function, then complain about it in some way.
We don't let people make functions by saying `typeset -f foo=bar'. */
/* There should be a way, however, to let people look at a particular
function definition by saying `typeset -f foo'. */
if (flags_on & att_function)
{
if (offset)
{
builtin_error ("Can't use `-f' to make functions");
return (EXECUTION_FAILURE);
}
else
{
SHELL_VAR *find_function (), *funvar;
funvar = find_function (name);
if (funvar)
{
if (readonly_p (funvar) && (flags_off & att_readonly))
{
builtin_error ("%s: readonly function", name);
any_failed++;
NEXT_VARIABLE ();
}
if (flags_on == att_function && flags_off == 0)
{
char *result = named_function_string
(name, (COMMAND *)function_cell (funvar), 1);
printf ("%s\n", result);
}
else
{
funvar->attributes |= flags_on;
funvar->attributes &= ~flags_off;
}
}
else
any_failed++;
NEXT_VARIABLE ();
}
}
else
{
SHELL_VAR *var;
var = find_variable (name);
if (!var)
var = bind_variable (name, "");
if (readonly_p (var) && (flags_off & att_readonly))
{
builtin_error ("%s: readonly variable", name);
any_failed++;
NEXT_VARIABLE ();
}
var->attributes |= flags_on;
var->attributes &= ~flags_off;
if (offset)
{
free (var->value);
if (integer_p (var))
{
long val, evalexp ();
char *itos ();
val = evalexp (value);
var->value = itos ((int)val);
}
else
var->value = savestring (value);
}
}
stupidly_hack_special_variables (name);
NEXT_VARIABLE ();
}
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}

168
builtins/echo.def Normal file
View file

@ -0,0 +1,168 @@
This file is echo.def, from which is created echo.c.
It implements the builtin "echo" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES echo.c
#include <stdio.h>
#include "../shell.h"
$BUILTIN echo
$FUNCTION echo_builtin
$DEPENDS_ON V9_ECHO
$SHORT_DOC echo [-neE] [arg ...]
Output the ARGs. If -n is specified, the trailing newline is
suppressed. If the -e option is given, interpretation of the
following backslash-escaped characters is turned on:
\a alert (bell)
\b backspace
\c suppress trailing newline
\f form feed
\n new line
\r carriage return
\t horizontal tab
\v vertical tab
\\ backslash
\num the character whose ASCII code is NUM (octal).
You can explicitly turn off the interpretation of the above characters
with the -E option.
$END
$BUILTIN echo
$FUNCTION echo_builtin
$DEPENDS_ON !V9_ECHO
$SHORT_DOC echo [-n] [arg ...]
Output the ARGs. If -n is specified, the trailing newline is suppressed.
$END
#if defined (V9_ECHO)
# define VALID_ECHO_OPTIONS "neE"
#else /* !V9_ECHO */
# define VALID_ECHO_OPTIONS "n"
#endif /* !V9_ECHO */
/* Print the words in LIST to standard output. If the first word is
`-n', then don't print a trailing newline. We also support the
echo syntax from Version 9 unix systems. */
echo_builtin (list)
WORD_LIST *list;
{
int display_return = 1, do_v9 = 0;
#if defined (DEFAULT_ECHO_TO_USG)
/* System V machines already have a /bin/sh with a v9 behaviour. We
give Bash the identical behaviour for these machines so that the
existing system shells won't barf. */
do_v9 = 1;
#endif /* DEFAULT_ECHO_TO_USG */
while (list && list->word->word[0] == '-')
{
register char *temp;
register int i;
/* If it appears that we are handling options, then make sure that
all of the options specified are actually valid. Otherwise, the
string should just be echoed. */
temp = &(list->word->word[1]);
for (i = 0; temp[i]; i++)
{
if (strchr (VALID_ECHO_OPTIONS, temp[i]) == 0)
goto just_echo;
}
if (!*temp)
goto just_echo;
/* All of the options in TEMP are valid options to ECHO.
Handle them. */
while (*temp)
{
if (*temp == 'n')
display_return = 0;
#if defined (V9_ECHO)
else if (*temp == 'e')
do_v9 = 1;
else if (*temp == 'E')
do_v9 = 0;
#endif /* V9_ECHO */
else
goto just_echo;
temp++;
}
list = list->next;
}
just_echo:
if (list)
{
#if defined (V9_ECHO)
if (do_v9)
{
while (list)
{
register char *s = list->word->word;
register int c;
while (c = *s++)
{
if (c == '\\' && *s)
{
switch (c = *s++)
{
case 'a': c = '\007'; break;
case 'b': c = '\b'; break;
case 'c': display_return = 0; continue;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'v': c = (int) 0x0B; break;
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 '\\': break;
default: putchar ('\\'); break;
}
}
putchar(c);
}
list = list->next;
if (list)
putchar(' ');
}
}
else
#endif /* V9_ECHO */
print_word_list (list, " ");
}
if (display_return)
printf ("\n");
fflush (stdout);
return (EXECUTION_SUCCESS);
}

156
builtins/enable.def Normal file
View file

@ -0,0 +1,156 @@
This file is enable.def, from which is created enable.c.
It implements the builtin "enable" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES enable.c
$BUILTIN enable
$FUNCTION enable_builtin
$SHORT_DOC enable [-n] [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' found on your
path instead of the shell builtin version, you type `enable -n test'.
$END
#include "../shell.h"
#include "../builtins.h"
#include "common.h"
#define ENABLED 1
#define DISABLED 2
static int enable_shell_command ();
static void list_some_builtins ();
/* Enable/disable shell commands present in LIST. If list is not specified,
then print out a list of shell commands showing which are enabled and
which are disabled. */
enable_builtin (list)
WORD_LIST *list;
{
int result = 0, any_failed = 0;
int disable_p, all_p;
disable_p = all_p = 0;
while (list && list->word->word && list->word->word[0] == '-')
{
char *arg = list->word->word;
list = list->next;
if (ISOPTION (arg, 'n'))
disable_p = 1;
else if (arg[1] == 'a' && (arg[2] == 0 || strcmp (arg + 2, "ll") == 0))
all_p = 1;
else if (ISOPTION (arg, '-'))
break;
else
{
bad_option (arg);
return (EXECUTION_FAILURE);
}
}
if (!list)
{
int filter;
if (all_p)
filter = ENABLED | DISABLED;
else if (disable_p)
filter = DISABLED;
else
filter = ENABLED;
list_some_builtins (filter);
}
else
{
while (list)
{
result = enable_shell_command (list->word->word, disable_p);
if (!result)
{
builtin_error ("%s: not a shell builtin", list->word->word);
any_failed++;
}
list = list->next;
}
}
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
/* List some builtins.
FILTER is a mask with two slots: ENABLED and DISABLED. */
static void
list_some_builtins (filter)
int filter;
{
register int i;
for (i = 0; i < num_shell_builtins; i++)
{
if (!shell_builtins[i].function)
continue;
if ((filter & ENABLED) &&
(shell_builtins[i].flags & BUILTIN_ENABLED))
{
printf ("enable %s\n", shell_builtins[i].name);
}
else if ((filter & DISABLED) &&
((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
{
printf ("enable -n %s\n", shell_builtins[i].name);
}
}
}
/* Enable the shell command NAME. If DISABLE_P is non-zero, then
disable NAME instead. */
static int
enable_shell_command (name, disable_p)
char *name;
int disable_p;
{
register int i;
int found = 0;
for (i = 0; i < num_shell_builtins; i++)
{
if (!shell_builtins[i].function)
continue;
if (STREQ (name, shell_builtins[i].name))
{
found++;
if (disable_p)
shell_builtins[i].flags &= ~BUILTIN_ENABLED;
else
shell_builtins[i].flags |= BUILTIN_ENABLED;
}
}
return (found);
}

45
builtins/eval.def Normal file
View file

@ -0,0 +1,45 @@
This file is eval.def, from which is created eval.c.
It implements the builtin "eval" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES eval.c
$BUILTIN eval
$FUNCTION eval_builtin
$SHORT_DOC eval [arg ...]
Read ARGs as input to the shell and execute the resulting command(s).
$END
#include "../shell.h"
/* Parse the string that these words make, and execute the command found. */
int
eval_builtin (list)
WORD_LIST *list;
{
int result;
/* Note that parse_and_execute () frees the string it is passed. */
if (list)
result = parse_and_execute (string_list (list), "eval", -1);
else
result = EXECUTION_SUCCESS;
return (result);
}

163
builtins/exec.def Normal file
View file

@ -0,0 +1,163 @@
This file is exec.def, from which is created exec.c.
It implements the builtin "exec" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES exec.c
$BUILTIN exec
$FUNCTION exec_builtin
$SHORT_DOC exec [ [-] file [redirection ...]]
Exec FILE, replacing this shell with the specified program.
If FILE is not specified, the redirections take effect in this
shell. If the first argument is `-', then place a dash in the
zeroth arg passed to FILE. If the file cannot be exec'ed and
the shell is not interactive, then the shell exits, unless the
shell variable "no_exit_on_failed_exec" exists.
$END
#include "../shell.h"
#include <sys/types.h>
#include "../posixstat.h"
#include <signal.h>
#include <errno.h>
#include "../execute_cmd.h"
#include "common.h"
#include "../flags.h"
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
#if !defined (errno)
extern int errno;
#endif /* !errno */
extern int interactive, subshell_environment;
extern REDIRECT *redirection_undo_list;
int
exec_builtin (list)
WORD_LIST *list;
{
int exit_value = EXECUTION_FAILURE;
maybe_make_export_env ();
/* First, let the redirections remain. */
dispose_redirects (redirection_undo_list);
redirection_undo_list = (REDIRECT *)NULL;
if (!list)
return (EXECUTION_SUCCESS);
else
{
/* Otherwise, execve the new command with args. */
char *command, **args;
int dash_name = 0;
if (list->word->word[0] == '-' && !list->word->word[1])
{
/* The user would like to exec this command as if it was a
login command. Do so. */
list = list->next;
dash_name++;
}
if (!list)
return (EXECUTION_SUCCESS);
#if defined (RESTRICTED_SHELL)
if (restricted)
{
builtin_error ("restricted");
return (EXECUTION_FAILURE);
}
#endif /* RESTRICTED_SHELL */
args = make_word_array (list);
/* A command with a slash anywhere in its name is not looked up in
the search path. */
if (absolute_program (args[0]))
command = args[0];
else
command = find_user_command (args[0]);
if (!command)
{
builtin_error ("%s: not found", args[0]);
exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
goto failed_exec;
}
command = full_pathname (command);
/* If the user wants this to look like a login shell, then
prepend a `-' onto the first argument (argv[0]). */
if (dash_name)
{
char *new_name = xmalloc (2 + strlen (args[0]));
new_name[0] = '-';
strcpy (new_name + 1, args[0]);
free (args[0]);
args[0] = new_name;
}
/* Decrement SHLVL by 1 so a new shell started here has the same value,
preserving the appearance. After we do that, we need to change the
exported environment to include the new value. */
adjust_shell_level (-1);
maybe_make_export_env ();
#if defined (HISTORY)
maybe_save_shell_history ();
#endif /* HISTORY */
restore_original_signals ();
#if defined (JOB_CONTROL)
if (subshell_environment == 0)
end_job_control ();
#endif /* JOB_CONTROL */
shell_execve (command, args, export_env);
adjust_shell_level (1);
if (!executable_file (command))
{
builtin_error ("%s: cannot execute: %s", command, strerror (errno));
exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */
}
else
file_error (command);
failed_exec:
if (command)
free (command);
if (subshell_environment ||
(!interactive && !find_variable ("no_exit_on_failed_exec")))
exit (exit_value);
initialize_traps ();
reinitialize_signals ();
#if defined (JOB_CONTROL)
restart_job_control ();
#endif /* JOB_CONTROL */
return (exit_value);
}
}

129
builtins/exit.def Normal file
View file

@ -0,0 +1,129 @@
This file is exit.def, from which is created exit.c.
It implements the builtins "exit" and "logout" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES exit.c
$BUILTIN exit
$FUNCTION exit_builtin
$SHORT_DOC exit [n]
Exit the shell with a status of N. If N is omitted, the exit status
is that of the last command executed.
$END
#include <stdio.h>
#include <sys/types.h>
#include "../shell.h"
#include "../jobs.h"
#include "builtext.h" /* for jobs_builtin */
extern int interactive, login_shell;
extern int last_command_exit_value;
static int exit_or_logout ();
static int sourced_logout = 0;
int
exit_builtin (list)
WORD_LIST *list;
{
if (interactive)
{
fprintf (stderr, login_shell ? "logout\n" : "exit\n");
fflush (stderr);
}
return (exit_or_logout (list));
}
$BUILTIN logout
$FUNCTION logout_builtin
$SHORT_DOC logout
Logout of a login shell.
$END
/* How to logout. */
int
logout_builtin (list)
WORD_LIST *list;
{
if (!login_shell && interactive)
{
builtin_error ("Not login shell: use `exit'");
return (EXECUTION_FAILURE);
}
else
return (exit_or_logout (list));
}
/* Clean up work for exiting or logging out. */
Function *last_shell_builtin = (Function *)NULL;
Function *this_shell_builtin = (Function *)NULL;
static int
exit_or_logout (list)
WORD_LIST *list;
{
int exit_value;
#if defined (JOB_CONTROL)
int exit_immediate_okay;
exit_immediate_okay = (!interactive ||
last_shell_builtin == exit_builtin ||
last_shell_builtin == logout_builtin ||
last_shell_builtin == jobs_builtin);
/* Check for stopped jobs if the user wants to. */
if (!exit_immediate_okay)
{
register int i;
for (i = 0; i < job_slots; i++)
if (jobs[i] && (jobs[i]->state == JSTOPPED))
{
fprintf (stderr, "There are stopped jobs.\n");
/* This is NOT superfluous because EOF can get here without
going through the command parser. Set both last and this
so that either `exit', `logout', or ^D will work to exit
immediately if nothing intervenes. */
this_shell_builtin = last_shell_builtin = exit_builtin;
return (EXECUTION_FAILURE);
}
}
#endif /* JOB_CONTROL */
/* Get return value if present. This means that you can type
`logout 5' to a shell, and it returns 5. */
if (list)
exit_value = get_numeric_arg (list);
else
exit_value = last_command_exit_value;
/* Run our `~/.bash_logout' file if it exists, and this is a login shell. */
if (login_shell && sourced_logout++ == 0)
maybe_execute_file ("~/.bash_logout", 1);
last_command_exit_value = exit_value;
/* Exit the program. */
longjmp (top_level, EXITPROG);
}

691
builtins/fc.def Normal file
View file

@ -0,0 +1,691 @@
This file is fc.def, from which is created fc.c.
It implements the builtin "fc" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES fc.c
$BUILTIN fc
$FUNCTION fc_builtin
$DEPENDS_ON HISTORY
$SHORT_DOC fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd]
FIRST and LAST can be numbers specifying the range, or FIRST can be a
string, which means the most recent command beginning with that
string.
-e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
then the editor which corresponds to the current readline editing
mode, then vi.
-l means list lines instead of editing.
-n means no line numbers listed.
-r means reverse the order of the lines (making it newest listed first).
With the `fc -s [pat=rep ...] [command]' format, the command is
re-executed after the substitution OLD=NEW is performed.
A useful alias to use with this is r='fc -s', so that typing `r cc'
runs the last command beginning with `cc' and typing `r' re-executes
the last command.
$END
#include <stdio.h>
#include "../bashansi.h"
#include "../shell.h"
#if defined (HISTORY)
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <errno.h>
#include "../builtins.h"
#include "../flags.h"
#include "../maxpath.h"
#include "../bashhist.h"
#include <readline/history.h>
#include "bashgetopt.h"
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
#if !defined (errno)
extern int errno;
#endif /* !errno */
extern int echo_input_at_read;
extern int unlink ();
/* **************************************************************** */
/* */
/* The K*rn shell style fc command (Fix Command) */
/* */
/* **************************************************************** */
/* fc builtin command (fix command) for Bash for those who
like K*rn-style history better than csh-style.
fc [-e ename] [-nlr] [first] [last]
FIRST and LAST can be numbers specifying the range, or FIRST can be
a string, which means the most recent command beginning with that
string.
-e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
then the editor which corresponds to the current readline editing
mode, then vi.
-l means list lines instead of editing.
-n means no line numbers listed.
-r means reverse the order of the lines (making it newest listed first).
fc -e - [pat=rep ...] [command]
fc -s [pat=rep ...] [command]
Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
*/
static char *fc_dosubs (), *fc_replace (), *fc_gethist (), *fc_readline ();
static int fc_gethnum ();
static void fc_replhist (), fc_addhist ();
/* Data structure describing a list of global replacements to perform. */
typedef struct repl {
struct repl *next;
char *pat;
char *rep;
} REPL;
#define USAGE "usage: fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [command]"
/* Accessors for HIST_ENTRY lists that are called HLIST. */
#define histline(i) (hlist[(i)]->line)
#define histdata(i) (hlist[(i)]->data)
#define FREE_RLIST() \
do { \
for (rl = rlist; rl; ) { \
REPL *r; \
r = rl->next; \
if (rl->pat) \
free (rl->pat); \
if (rl->rep) \
free (rl->rep); \
free (rl); \
rl = r; \
} \
} while (0)
/* String to execute on a file that we want to edit. */
#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
int
fc_builtin (list)
WORD_LIST *list;
{
register int i;
register char *sep;
int numbering, reverse, listing, execute;
int histbeg, histend, last_hist, retval, first, opt;
FILE *stream;
REPL *rlist = (REPL *) NULL, *rl;
char *ename = NULL, *command, *newcom, *line;
HIST_ENTRY **hlist;
char fn[MAXPATHLEN];
numbering = 1;
reverse = listing = execute = 0;
/* Parse out the options and set which of the two forms we're in. */
while (list && *list->word->word == '-')
{
register char *s = &((list->word->word)[1]);
if (!isletter (*s))
break;
while (opt = *s++)
{
switch (opt)
{
case 'n':
numbering = 0;
break;
case 'l':
listing = 1;
break;
case 'r':
reverse = 1;
break;
case 's':
execute = 1;
break;
case 'e':
list = list->next;
if (list == NULL)
{
builtin_error (USAGE);
return (EX_USAGE);
}
ename = list->word->word;
break;
default:
builtin_error (USAGE);
return (EX_USAGE);
}
}
list = list->next;
}
if (ename && (*ename == '-') && (ename[1] == '\0'))
execute = 1;
/* The "execute" form of the command (re-run, with possible string
substitutions). */
if (execute)
{
while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
{
*sep++ = '\0';
rl = (REPL *)xmalloc (sizeof (REPL));
rl->next = (REPL *)NULL;
rl->pat = savestring (list->word->word);
rl->rep = savestring (sep);
if (rlist == NULL)
rlist = rl;
else
{
rl->next = rlist;
rlist = rl;
}
list = list->next;
}
/* If we have a list of substitutions to do, then reverse it
to get the replacements in the proper order. */
if (rlist && rlist->next)
rlist = (REPL *) reverse_list ((GENERIC_LIST *) rlist);
hlist = history_list ();
/* If we still have something in list, it is a command spec.
Otherwise, we use the most recent command in time. */
if (list)
command = fc_gethist (list->word->word, hlist);
else
command = fc_gethist ((char *) NULL, hlist);
if (command == NULL)
{
builtin_error ("no command found");
if (rlist)
FREE_RLIST ();
return (EXECUTION_FAILURE);
}
if (rlist)
{
newcom = fc_dosubs (command, rlist);
free (command);
FREE_RLIST ();
command = newcom;
}
printf ("%s\n", command);
fc_replhist (command); /* replace `fc -e -' with command */
return (parse_and_execute (command, "fc", -1));
}
/* This is the second form of the command (the list-or-edit-and-rerun
form). */
hlist = history_list ();
if (hlist == 0)
return (EXECUTION_SUCCESS);
for (i = 0; hlist[i]; i++);
/* With the Bash implementation of history, the current command line
("fc blah..." and so on) is already part of the history list by
the time we get to this point. This just skips over that command
and makes the last command that this deals with be the last command
the user entered before the fc. */
last_hist = i - 2;
if (list)
{
histbeg = fc_gethnum (list->word->word, hlist);
list = list->next;
if (list)
histend = fc_gethnum (list->word->word, hlist);
else
{
if (listing)
histend = last_hist;
else
histend = histbeg;
}
}
else
{
/* The default for listing is the last 16 history items. */
if (listing)
{
histend = last_hist;
histbeg = histend - 16;
if (histbeg < 0)
histbeg = 0;
}
else
{
/* For editing, it is the last history command. */
histbeg = histend = last_hist;
}
}
/* We print error messages for line specifications out of range. */
if ((histbeg < 0) || (histend < 0) ||
(histbeg > last_hist) || (histend > last_hist))
{
builtin_error ("history specification out of range");
return (EXECUTION_FAILURE);
}
if (histend < histbeg)
{
int t = histend;
histend = histbeg;
histbeg = t;
reverse = 1;
}
if (listing)
stream = stdout;
else
{
numbering = 0;
sprintf (fn, "/tmp/bash%d", (int)time ((long *) 0) + (int)getpid ());
stream = fopen (fn, "w");
if (!stream)
{
builtin_error ("cannot open temp file %s", fn);
return (EXECUTION_FAILURE);
}
}
if (!reverse)
{
for (i = histbeg; i <= histend; i++)
{
QUIT;
if (numbering)
fprintf (stream, "%d", i + history_base);
if (listing)
fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
fprintf (stream, "%s\n", histline (i));
}
}
else
{
for (i = histend; i >= histbeg; i--)
{
QUIT;
if (numbering)
fprintf (stream, "%d", i + history_base);
if (listing)
fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
fprintf (stream, "%s\n", histline (i));
}
}
if (listing)
return (EXECUTION_SUCCESS);
fclose (stream);
/* Now edit the file of commands. */
if (ename)
{
command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
sprintf (command, "%s %s", ename, fn);
}
else
{
command = (char *)xmalloc (3 + strlen (FC_EDIT_COMMAND) + strlen (fn));
sprintf (command, "%s %s", FC_EDIT_COMMAND, fn);
}
parse_and_execute (command, "fc", -1);
/* Now reopen the file and execute the edited commands. */
stream = fopen (fn, "r");
if (stream == NULL)
{
builtin_error ("cannot reopen temp file %s", fn);
unlink (fn);
return (EXECUTION_FAILURE);
}
retval = EXECUTION_SUCCESS;
first = 1;
/* First, write the commands to the history file. This will not happen
when we call parse_and_execute, since parse_and_execute disables
the command line history while it executes. */
while ((line = fc_readline (stream)) != NULL)
{
if (line[0] == '\n')
{
free (line);
continue; /* Skip blank lines. */
}
if (first)
{
first = 0;
fc_replhist (line);
}
else
fc_addhist (line);
free (line);
}
fclose (stream);
/* Turn on the `v' flag while maybe_execute_file runs so the commands
will be echoed as they are read by the parser. */
begin_unwind_frame ("fc builtin");
add_unwind_protect (unlink, fn);
unwind_protect_int (echo_input_at_read);
echo_input_at_read = 1;
retval = maybe_execute_file (fn, 0);
run_unwind_frame ("fc builtin");
return (retval);
}
/* Return an absolute index into HLIST which corresponds to COMMAND. If
COMMAND is a number, then it was specified in relative terms. If it
is a string, then it is the start of a command line present in HLIST. */
static int
fc_gethnum (command, hlist)
char *command;
HIST_ENTRY **hlist;
{
int sign = 1, n, clen;
register int i, j;
register char *s;
/* Count history elements. */
for (i = 0; hlist[i]; i++);
/* With the Bash implementation of history, the current command line
("fc blah..." and so on) is already part of the history list by
the time we get to this point. This just skips over that command
and makes the last command that this deals with be the last command
the user entered before the fc. */
i -= 2;
/* No specification defaults to most recent command. */
if (command == NULL)
return (i);
/* Otherwise, there is a specification. It can be a number relative to
the current position, or an absolute history number. */
s = command;
/* Handle possible leading minus sign. */
if (s && (*s == '-'))
{
sign = -1;
s++;
}
if (s && digit(*s))
{
n = atoi (s);
n *= sign;
/* Anything specified greater than the last history element that we
deal with is an error. */
if (n > i + history_base)
return (-1);
/* If the value is negative or zero, then it is an offset from
the current history item. */
if (n < 0)
return (i + n + 1);
else if (n == 0)
return (i);
else
return (n - history_base);
}
clen = strlen (command);
for (j = i; j >= 0; j--)
{
if (STREQN (command, histline (j), clen))
return (j);
}
return (-1);
}
/* Locate the most recent history line which begins with
COMMAND in HLIST, and return a malloc()'ed copy of it. */
static char *
fc_gethist (command, hlist)
char *command;
HIST_ENTRY **hlist;
{
int i;
if (!hlist)
return ((char *)NULL);
i = fc_gethnum (command, hlist);
if (i >= 0)
return (savestring (histline (i)));
else
return ((char *)NULL);
}
/* Read the edited history lines from STREAM and return them
one at a time. This can read unlimited length lines. The
caller should free the storage. */
static char *
fc_readline (stream)
FILE *stream;
{
register int c;
int line_len = 0, lindex = 0;
char *line = (char *)NULL;
while ((c = getc (stream)) != EOF)
{
if ((lindex + 2) >= line_len)
line = (char *) xrealloc (line, (line_len += 128));
if (c == '\n')
{
line[lindex++] = '\n';
line[lindex++] = '\0';
return (line);
}
else
line[lindex++] = c;
}
if (!lindex)
{
if (line)
free (line);
return ((char *)NULL);
}
if (lindex + 2 >= line_len)
line = (char *)xrealloc (line, lindex + 3);
line[lindex++] = '\n'; /* Finish with newline if none in file */
line[lindex++] = '\0';
return (line);
}
/* Perform the SUBS on COMMAND.
SUBS is a list of substitutions, and COMMAND is a simple string.
Return a pointer to a malloc'ed string which contains the substituted
command. */
static char *
fc_dosubs (command, subs)
char *command;
REPL *subs;
{
register char *new = savestring (command);
register REPL *r;
for (r = subs; r; r = r->next)
{
register char *t;
t = fc_replace (r->pat, r->rep, new);
free (new);
new = t;
}
return (new);
}
/* Replace the occurrences of PAT with REP in COMMAND.
This returns a new string; the caller should free it. */
static char *
fc_replace (pat, rep, command)
char *pat, *rep, *command;
{
register int i;
int patlen, replen, templen;
char *new, *temp;
patlen = strlen (pat);
replen = strlen (rep);
temp = savestring (command);
templen = strlen (temp);
i = 0;
for (; (i + patlen) <= templen; i++)
{
if (STREQN (temp + i, pat, patlen))
{
new = (char *) xmalloc (1 + (replen - patlen) + templen);
strncpy (new, temp, i);
strncpy (new + i, rep, replen);
strncpy (new + i + replen,
temp + i + patlen, templen - (i + patlen));
new[templen + (replen - patlen)] = '\0'; /* just in case */
free (temp);
temp = new;
i += replen;
templen = strlen (temp);
}
}
return (temp);
}
/* Use `command' to replace the last entry in the history list, which,
by this time, is `fc blah...'. The intent is that the new command
become the history entry, and that `fc' should never appear in the
history list. This way you can do `r' to your heart's content. */
static void
fc_replhist (command)
char *command;
{
register int i;
HIST_ENTRY **hlist, *histent, *discard;
char *data;
int n;
if (!command || !*command)
return;
hlist = history_list ();
if (hlist == NULL)
return;
for (i = 0; hlist[i]; i++);
i--;
/* History_get () takes a parameter that should be
offset by history_base. */
histent = history_get (history_base + i); /* Don't free this */
if (histent == NULL)
return;
n = strlen (command);
if (command[n - 1] == '\n')
command[n - 1] = '\0';
if (command && *command)
{
discard = remove_history (i);
if (discard)
{
if (discard->line)
free (discard->line);
free ((char *) discard);
}
maybe_add_history (command); /* Obeys HISTCONTROL setting. */
}
}
/* Add LINE to the history, after removing a single trailing newline. */
static void
fc_addhist (line)
char *line;
{
register int n;
n = strlen (line);
if (line[n - 1] == '\n')
line[n - 1] = '\0';
if (line && *line)
maybe_add_history (line);
}
#endif /* HISTORY */

145
builtins/fg_bg.def Normal file
View file

@ -0,0 +1,145 @@
This file is fg_bg.def, from which is created fg_bg.c.
It implements the builtins "bg" and "fg" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES fg_bg.c
$BUILTIN fg
$FUNCTION fg_builtin
$DEPENDS_ON JOB_CONTROL
$SHORT_DOC fg [job_spec]
Place JOB_SPEC in the foreground, and make it the current job. If
JOB_SPEC is not present, the shell's notion of the current job is
used.
$END
#include <sys/types.h>
#include <signal.h>
#include "../shell.h"
#include "../jobs.h"
#if defined (JOB_CONTROL)
extern char *this_command_name;
static int fg_bg ();
/* How to bring a job into the foreground. */
int
fg_builtin (list)
WORD_LIST *list;
{
int fg_bit = 1;
register WORD_LIST *t = list;
if (!job_control)
{
builtin_error ("no job control");
return (EXECUTION_FAILURE);
}
/* If the last arg on the line is '&', then start this job in the
background. Else, fg the job. */
while (t && t->next)
t = t->next;
if (t && t->word->word[0] == '&' && !t->word->word[1])
fg_bit = 0;
return (fg_bg (list, fg_bit));
}
#endif /* JOB_CONTROL */
$BUILTIN bg
$FUNCTION bg_builtin
$DEPENDS_ON JOB_CONTROL
$SHORT_DOC bg [job_spec]
Place JOB_SPEC in the background, as if it had been started with
`&'. If JOB_SPEC is not present, the shell's notion of the current
job is used.
$END
#if defined (JOB_CONTROL)
/* How to put a job into the background. */
int
bg_builtin (list)
WORD_LIST *list;
{
if (!job_control)
{
builtin_error ("no job control");
return (EXECUTION_FAILURE);
}
return (fg_bg (list, 0));
}
/* How to put a job into the foreground/background. */
static int
fg_bg (list, foreground)
WORD_LIST *list;
int foreground;
{
sigset_t set, oset;
int job, status = EXECUTION_SUCCESS, old_async_pid;
BLOCK_CHILD (set, oset);
job = get_job_spec (list);
if (job < 0 || job >= job_slots || !jobs[job])
{
if (job != DUP_JOB)
builtin_error ("No such job %s", list ? list->word->word : "");
goto failure;
}
/* Or if jobs[job]->pgrp == shell_pgrp. */
if (!(jobs[job]->flags & J_JOBCONTROL))
{
builtin_error ("job %%%d started without job control", job + 1);
goto failure;
}
if (!foreground)
{
old_async_pid = last_asynchronous_pid;
last_asynchronous_pid = jobs[job]->pgrp; /* As per Posix.2 5.4.2 */
}
status = start_job (job, foreground);
if (status >= 0)
{
/* win: */
UNBLOCK_CHILD (oset);
return (status);
}
else
{
if (!foreground)
last_asynchronous_pid = old_async_pid;
failure:
UNBLOCK_CHILD (oset);
return (EXECUTION_FAILURE);
}
}
#endif /* JOB_CONTROL */

283
builtins/getopt.c Normal file
View file

@ -0,0 +1,283 @@
/* getopt for BASH.
Copyright (C) 1993, 1994
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "../memalloc.h"
#include "../shell.h"
#include "getopt.h"
/* For communication from `sh_getopt' to the caller.
When `sh_getopt' finds an option that takes an argument,
the argument value is returned here. */
char *sh_optarg = 0;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `sh_getopt'.
On entry to `sh_getopt', zero means this is the first call; initialize.
When `sh_getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `sh_optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* XXX 1003.2 says this must be 1 before any call. */
int sh_optind = 0;
/* Index of the current argument. */
static int sh_curopt;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
static int sh_charindex;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int sh_opterr = 1;
/* Set to an option character which was unrecognized.
This must be initialized on some systems to avoid linking in the
system's own getopt implementation. */
int sh_optopt = '?';
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `sh_getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `sh_getopt' finds another option character, it returns that character,
updating `sh_optind' and `nextchar' so that the next call to `sh_getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `sh_getopt' returns `EOF'.
Then `sh_optind' is the index in ARGV of the first ARGV-element
that is not an option.
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `sh_opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `sh_optarg'. */
/* 1003.2 specifies the format of this message. */
#define BADOPT(x) fprintf (stderr, "%s: illegal option -- %c\n", argv[0], x)
#define NEEDARG(x) fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], x)
int
sh_getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
int option_index;
char c, *temp;
sh_optarg = 0;
if (sh_optind > argc || sh_optind < 0)
{
sh_optind = argc;
return (EOF);
}
/* Initialize the internal data when the first call is made.
Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
if (sh_optind == 0)
{
sh_optind = 1;
nextchar = (char *)NULL;
}
if (nextchar == 0 || *nextchar == '\0')
{
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (sh_optind == argc)
return EOF;
temp = argv[sh_optind];
/* Special ARGV-element `--' means premature end of options.
Skip it like a null option, and return EOF. */
if (temp[0] == '-' && temp[1] == '-' && temp[2] == '\0')
{
sh_optind++;
return EOF;
}
/* If we have come to a non-option, either stop the scan or describe
it to the caller and pass it by. This makes the pseudo-option
`-' mean the end of options, but does not skip over it. */
if (temp[0] != '-' || temp[1] == '\0')
return EOF;
/* We have found another option-ARGV-element.
Start decoding its characters. */
nextchar = argv[sh_curopt = sh_optind] + 1;
sh_charindex = 1;
}
/* Look at and handle the next option-character. */
c = *nextchar++; sh_charindex++;
temp = strchr (optstring, c);
/* Increment `sh_optind' when we start to process its last character. */
if (nextchar == 0 || *nextchar == '\0')
{
sh_optind++;
nextchar = (char *)NULL;
}
sh_optopt = c;
if (temp == NULL || c == ':')
{
if (sh_opterr)
BADOPT (c);
return '?';
}
if (temp[1] == ':')
{
if (nextchar && *nextchar)
{
/* This is an option that requires an argument. */
sh_optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
sh_optind++;
}
else if (sh_optind == argc)
{
if (sh_opterr)
NEEDARG (c);
sh_optopt = c;
c = (optstring[0] == ':') ? ':' : '?';
}
else
/* We already incremented `sh_optind' once;
increment it again when taking next ARGV-elt as argument. */
sh_optarg = argv[sh_optind++];
nextchar = (char *)NULL;
}
return c;
}
void
sh_getopt_restore_state (argv)
char **argv;
{
if (nextchar)
nextchar = argv[sh_curopt] + sh_charindex;
}
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `sh_getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_sh_optind = 0;
while (1)
{
int this_option_sh_optind = sh_optind ? sh_optind : 1;
c = sh_getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_sh_optind != 0 && digit_sh_optind != this_option_sh_optind)
printf ("digits occur in two different argv-elements.\n");
digit_sh_optind = this_option_sh_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", sh_optarg);
break;
case '?':
break;
default:
printf ("?? sh_getopt returned character code 0%o ??\n", c);
}
}
if (sh_optind < argc)
{
printf ("non-option ARGV-elements: ");
while (sh_optind < argc)
printf ("%s ", argv[sh_optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

57
builtins/getopt.h Normal file
View file

@ -0,0 +1,57 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* XXX THIS HAS BEEN MODIFIED FOR INCORPORATION INTO BASH XXX */
#ifndef _GETOPT_H
#define _GETOPT_H 1
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *sh_optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `sh_optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int sh_optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int sh_opterr;
/* Set to an option character which was unrecognized. */
extern int sh_optopt;
extern int sh_getopt ();
extern void sh_getopt_restore_state ();
#endif /* _GETOPT_H */

300
builtins/getopts.def Normal file
View file

@ -0,0 +1,300 @@
This file is getopts.def, from which is created getopts.c.
It implements the builtin "getopts" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES getopts.c
$BUILTIN getopts
$DEPENDS_ON GETOPTS_BUILTIN
$FUNCTION getopts_builtin
$SHORT_DOC getopts optstring name [arg]
Getopts is used by shell procedures to parse positional parameters.
OPTSTRING contains the option letters to be recognized; if a letter
is followed by a colon, the option is expected to have an argument,
which should be separated from it by white space.
Each time it is invoked, getopts will place the next option in the
shell variable $name, initializing name if it does not exist, and
the index of the next argument to be processed into the shell
variable OPTIND. OPTIND is initialized to 1 each time the shell or
a shell script is invoked. When an option requires an argument,
getopts places that argument into the shell variable OPTARG.
getopts reports errors in one of two ways. If the first character
of OPTSTRING is a colon, getopts uses silent error reporting. In
this mode, no error messages are printed. If an illegal option is
seen, getopts places the option character found into OPTARG. If a
required argument is not found, getopts places a ':' into NAME and
sets OPTARG to the option character found. If getopts is not in
silent mode, and an illegal option is seen, getopts places '?' into
NAME and unsets OPTARG. If a required option is not found, a '?'
is placed in NAME, OPTARG is unset, and a diagnostic message is
printed.
If the shell variable OPTERR has the value 0, getopts disables the
printing of error messages, even if the first character of
OPTSTRING is not a colon. OPTERR has the value 1 by default.
Getopts normally parses the positional parameters ($0 - $9), but if
more arguments are given, they are parsed instead.
$END
#include <stdio.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "../shell.h"
#if defined (GETOPTS_BUILTIN)
#include "getopt.h"
#define G_EOF (-1)
#define G_ILLEGAL_OPT (-2)
#define G_ARG_MISSING (-3)
extern char *this_command_name;
extern WORD_LIST *rest_of_args;
/* getopts_reset is magic code for when OPTIND is reset. N is the
value that has just been assigned to OPTIND. */
void
getopts_reset (newind)
int newind;
{
sh_optind = newind;
}
/* Error handling is now performed as specified by Posix.2, draft 11
(identical to that of ksh-88). The special handling is enabled if
the first character of the option string is a colon; this handling
disables diagnostic messages concerning missing option arguments
and illegal option characters. The handling is as follows.
ILLEGAL OPTIONS:
name -> "?"
if (special_error) then
OPTARG = option character found
no error output
else
OPTARG unset
diagnostic message
fi
MISSING OPTION ARGUMENT;
if (special_error) then
name -> ":"
OPTARG = option character found
else
name -> "?"
OPTARG unset
diagnostic message
fi
*/
static int
dogetopts (argc, argv)
int argc;
char **argv;
{
int ret, special_error, old_opterr = 0, i, n;
char strval[2], numval[16];
char *optstr; /* list of options */
char *name; /* variable to get flag val */
char *t;
if (argc < 3)
{
builtin_error("usage: getopts optstring name [arg]");
return (EX_USAGE);
}
/* argv[0] is "getopts". */
optstr = argv[1];
name = argv[2];
argc -= 2;
argv += 2;
special_error = optstr[0] == ':';
if (special_error)
{
old_opterr = sh_opterr;
optstr++;
sh_opterr = 0; /* suppress diagnostic messages */
}
if (argc > 1)
{
sh_getopt_restore_state (argv);
t = argv[0];
argv[0] = dollar_vars[0];
ret = sh_getopt (argc, argv, optstr);
argv[0] = t;
}
else if (rest_of_args == (WORD_LIST *)NULL)
{
register int i;
for (i = 0; i < 10 && dollar_vars[i]; i++);
ret = sh_getopt (i, dollar_vars, optstr);
}
else
{
register int i;
register WORD_LIST *words;
char **v;
for (i = 0; i < 10 && dollar_vars[i]; i++);
for (words = rest_of_args; words; words = words->next, i++);
v = (char **)xmalloc ((i + 1) * sizeof (char *));
for (i = 0; i < 10 && dollar_vars[i]; i++)
v[i] = dollar_vars[i];
for (words = rest_of_args; words; words = words->next, i++)
v[i] = words->word->word;
v[i] = (char *)NULL;
ret = sh_getopt (i, v, optstr);
free (v);
}
if (special_error)
sh_opterr = old_opterr;
/* Set the OPTIND variable in any case, to handle "--" skipping. */
if (sh_optind < 10)
{
numval[14] = sh_optind + '0';
numval[15] = '\0';
i = 14;
}
else
{
numval[i = 15] = '\0';
n = sh_optind;
do
{
numval[--i] = (n % 10) + '0';
}
while (n /= 10);
}
bind_variable ("OPTIND", numval + i);
/* If an error occurred, decide which one it is and set the return
code appropriately. In all cases, the option character in error
is in SH_OPTOPT. If an illegal option was encountered, OPTARG is
NULL. If a required option argument was missing, OPTARG points
to a NULL string (that is, optarg[0] == 0). */
if (ret == '?')
{
if (sh_optarg == NULL)
ret = G_ILLEGAL_OPT;
else if (sh_optarg[0] == '\0')
ret = G_ARG_MISSING;
}
if (ret == G_EOF)
{
bind_variable (name, "?");
return (EXECUTION_FAILURE);
}
if (ret == G_ILLEGAL_OPT)
{
/* Illegal option encountered. */
strval[0] = '?';
strval[1] = '\0';
bind_variable (name, strval);
if (special_error)
{
strval[0] = (char) sh_optopt;
strval[1] = '\0';
bind_variable ("OPTARG", strval);
}
else
makunbound ("OPTARG", shell_variables);
return (EXECUTION_SUCCESS);
}
if (ret == G_ARG_MISSING)
{
/* Required argument missing. */
if (special_error)
{
strval[0] = ':';
strval[1] = '\0';
bind_variable (name, strval);
strval[0] = (char) sh_optopt;
strval[1] = '\0';
bind_variable ("OPTARG", strval);
}
else
{
strval[0] = '?';
strval[1] = '\0';
bind_variable (name, strval);
makunbound ("OPTARG", shell_variables);
}
return (EXECUTION_SUCCESS);
}
bind_variable ("OPTARG", sh_optarg);
strval[0] = (char) ret;
strval[1] = '\0';
bind_variable (name, strval);
return (EXECUTION_SUCCESS);
}
/* The getopts builtin. Build an argv, and call dogetopts with it. */
int
getopts_builtin (list)
WORD_LIST *list;
{
register int i;
char **av;
int ac, ret;
WORD_LIST *t;
if (list == 0)
return EXECUTION_FAILURE;
for (t = list, ac = 0; t; t = t->next, ac++);
ac++;
av = (char **)xmalloc ((1 + ac) * sizeof (char *));
av[ac] = (char *) NULL;
av[0] = this_command_name;
for (t = list, i = 1; t; t = t->next, i++)
av[i] = t->word->word;
ret = dogetopts (ac, av);
free ((char *)av);
return (ret);
}
#endif /* GETOPTS_BUILTIN */

222
builtins/hash.def Normal file
View file

@ -0,0 +1,222 @@
This file is hash.def, from which is created hash.c.
It implements the builtin "hash" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES hash.c
$BUILTIN hash
$FUNCTION hash_builtin
$SHORT_DOC hash [-r] [name ...]
For each NAME, the full pathname of the command is determined and
remembered. The -r option causes the shell to forget all remembered
locations. If no arguments are given, information about remembered
commands is presented.
$END
#include <sys/types.h>
#include "../posixstat.h"
#include <stdio.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "../shell.h"
#include "../builtins.h"
#include "../flags.h"
#include "hashcom.h"
#include "common.h"
#include "../execute_cmd.h"
extern int dot_found_in_search;
void
initialize_filename_hashing ()
{
hashed_filenames = make_hash_table (FILENAME_HASH_BUCKETS);
}
/* Print statistics on the current state of hashed commands. If LIST is
not empty, then rehash (or hash in the first place) the specified
commands. */
hash_builtin (list)
WORD_LIST *list;
{
int expunge_hash_table = 0;
int any_failed = 0;
if (hashing_disabled)
{
builtin_error ("hashing disabled");
return (EXECUTION_FAILURE);
}
while (list)
{
char *arg = list->word->word;
if (ISOPTION (arg, 'r'))
{
expunge_hash_table = 1;
list = list->next;
}
else if (ISOPTION (arg, '-'))
{
list = list->next;
break;
}
else if (*arg == '-')
{
bad_option (list->word->word);
builtin_error ("usage: hash [-r] [command ...]");
return (EX_USAGE);
}
else
break;
}
/* We want hash -r to be silent, but hash -- to print hashing info. That
is the reason for the !expunge_hash_table. */
if (!list && !expunge_hash_table)
{
/* Print information about current hashed info. */
int any_printed = 0;
int bucket = 0;
register BUCKET_CONTENTS *item_list;
while (bucket < hashed_filenames->nbuckets)
{
item_list = get_hash_bucket (bucket, hashed_filenames);
if (item_list)
{
if (!any_printed)
{
printf ("hits\tcommand\n");
any_printed++;
}
while (item_list)
{
printf ("%4d\t%s\n",
item_list->times_found, pathdata(item_list)->path);
item_list = item_list->next;
}
}
bucket++;
}
if (!any_printed)
printf ("No commands in hash table.\n");
return (EXECUTION_SUCCESS);
}
if (expunge_hash_table)
{
int bucket = 0;
register BUCKET_CONTENTS *item_list, *prev;
while (bucket < hashed_filenames->nbuckets)
{
item_list = get_hash_bucket (bucket, hashed_filenames);
if (item_list)
{
while (item_list)
{
prev = item_list;
free (item_list->key);
free (pathdata(item_list)->path);
free (item_list->data);
item_list = item_list->next;
free (prev);
}
hashed_filenames->bucket_array[bucket] = (BUCKET_CONTENTS *)NULL;
}
bucket++;
}
}
while (list)
{
/* Add or rehash the specified commands. */
char *word;
char *full_path;
SHELL_VAR *var;
word = list->word->word;
if (absolute_program (word))
{
list = list->next;
continue;
}
full_path = find_user_command (word);
var = find_function (word);
if (!find_shell_builtin (word) && (!var))
{
if (full_path && executable_file (full_path))
remember_filename (word, full_path, dot_found_in_search, 0);
else
{
builtin_error ("%s: not found", word);
any_failed++;
}
}
if (full_path)
free (full_path);
list = list->next;
}
fflush (stdout);
if (any_failed)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
}
/* Place FILENAME (key) and FULL_PATHNAME (data->path) into the
hash table. CHECK_DOT if non-null is for future calls to
find_hashed_filename (). FOUND is the initial value for
times_found. */
void
remember_filename (filename, full_pathname, check_dot, found)
char *filename, *full_pathname;
int check_dot, found;
{
register BUCKET_CONTENTS *item;
if (hashing_disabled)
return;
item = add_hash_item (filename, hashed_filenames);
if (item->data)
free (pathdata(item)->path);
else
{
item->key = savestring (filename);
item->data = (char *)xmalloc (sizeof (PATH_DATA));
}
pathdata(item)->path = savestring (full_pathname);
pathdata(item)->check_dot = check_dot;
item->times_found = found;
}

32
builtins/hashcom.h Normal file
View file

@ -0,0 +1,32 @@
/* hashcom.h - Common defines for hashing filenames. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "../hash.h"
#define FILENAME_HASH_BUCKETS 631
extern HASH_TABLE *hashed_filenames;
typedef struct {
char *path; /* The full pathname of the file. */
int check_dot; /* Whether `.' appeared before this one in $PATH. */
} PATH_DATA;
#define pathdata(x) ((PATH_DATA *)(x)->data)

134
builtins/help.def Normal file
View file

@ -0,0 +1,134 @@
This file is help.def, from which is created help.c.
It implements the builtin "help" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES help.c
$BUILTIN help
$FUNCTION help_builtin
$SHORT_DOC help [pattern ...]
Display helpful information about builtin commands. If PATTERN is
specified, gives detailed help on all commands matching PATTERN,
otherwise a list of the builtins is printed.
$END
#include <stdio.h>
#include "../shell.h"
#include "../builtins.h"
#if defined (USE_GLOB_LIBRARY)
# include <glob/glob.h>
#else
# define FNM_NOMATCH 1
#endif /* USE_GLOB_LIBRARY */
/* Print out a list of the known functions in the shell, and what they do.
If LIST is supplied, print out the list which matches for each pattern
specified. */
help_builtin (list)
WORD_LIST *list;
{
if (!list)
{
register int i, j;
char blurb[256];
show_shell_version ();
printf (
"Shell commands that are defined internally. Type `help' to see this list.\n\
Type `help name' to find out more about the function `name'.\n\
Use `info bash' to find out more about the shell in general.\n\
\n\
A star (*) next to a name means that the command is disabled.\n\
\n");
for (i = 0; i < num_shell_builtins; i++)
{
QUIT;
sprintf (blurb, "%c%s",
(shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*',
shell_builtins[i].short_doc);
blurb[35] = '\0';
printf ("%s", blurb);
if (i % 2)
printf ("\n");
else
for (j = strlen (blurb); j < 35; j++)
putc (' ', stdout);
}
if (i % 2)
printf ("\n");
}
else
{
int match_found = 0;
char *pattern = "";
if (glob_pattern_p (list->word->word))
{
printf ("Shell commands matching keyword%s `",
list->next ? "s" : "");
print_word_list (list, ", ");
printf ("'\n\n");
}
while (list)
{
register int i = 0, plen;
char *name;
pattern = list->word->word;
plen = strlen (pattern);
while (name = shell_builtins[i].name)
{
int doc_index;
QUIT;
if ((strncmp (pattern, name, plen) == 0) ||
(fnmatch (pattern, name, 0) != FNM_NOMATCH))
{
printf ("%s: %s\n", name, shell_builtins[i].short_doc);
for (doc_index = 0;
shell_builtins[i].long_doc[doc_index]; doc_index++)
printf (" %s\n", shell_builtins[i].long_doc[doc_index]);
match_found++;
}
i++;
}
list = list->next;
}
if (!match_found)
{
fprintf (stderr, "No help topics match `%s'. Try `help help'.\n",
pattern);
fflush (stderr);
return (EXECUTION_FAILURE);
}
}
fflush (stdout);
return (EXECUTION_SUCCESS);
}

179
builtins/history.def Normal file
View file

@ -0,0 +1,179 @@
This file is history.def, from which is created history.c.
It implements the builtin "history" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES history.c
$BUILTIN history
$FUNCTION history_builtin
$DEPENDS_ON HISTORY
$SHORT_DOC history [n] [ [-awrn] [filename]]
Display the history list with line numbers. Lines listed with
with a `*' have been modified. Argument of N says to list only
the last N lines. Argument `-w' means to write out the current
history file; `-r' means to read it instead. Argument `-a' means
to append history lines from this session to the history file.
Argument `-n' means to read all history lines not already read
from the history file. If FILENAME is given, then use that file,
else if $HISTFILE has a value, use that, else use ~/.bash_history.
$END
#include "../shell.h"
#if defined (HISTORY)
#include <sys/types.h>
#include <sys/file.h>
#include "../filecntl.h"
#include "../posixstat.h"
#include "../bashhist.h"
#include <readline/history.h>
/* History. Arg of -w FILENAME means write file, arg of -r FILENAME
means read file. Arg of N means only display that many items. */
history_builtin (list)
WORD_LIST *list;
{
register int i;
int limited = 0, limit = 0;
HIST_ENTRY **hlist;
while (list)
{
char *arg = list->word->word;
if ((arg[0] == '-') &&
(strlen (arg) == 2) &&
(member (arg[1], "rwan")))
{
char *file;
int result = EXECUTION_SUCCESS;
if (list->next)
file = list->next->word->word;
else
file = get_string_value ("HISTFILE");
switch (arg[1])
{
case 'a': /* Append `new' lines to file. */
{
if (history_lines_this_session)
{
void using_history ();
if (history_lines_this_session < where_history ())
{
/* If the filename was supplied, then create it
if it doesn't already exist. */
if (file)
{
struct stat buf;
if (stat (file, &buf) == -1)
{
int tem;
tem = open (file, O_CREAT, 0666);
close (tem);
}
}
result =
append_history (history_lines_this_session, file);
history_lines_in_file += history_lines_this_session;
history_lines_this_session = 0;
}
}
break;
}
case 'w': /* Write entire history. */
{
result = write_history (file);
break;
}
case 'r': /* Read entire file. */
{
result = read_history (file);
break;
}
case 'n': /* Read `new' history from file. */
{
/* Read all of the lines in the file that we haven't
already read. */
using_history ();
result = read_history_range (file, history_lines_in_file, -1);
using_history ();
history_lines_in_file = where_history ();
break;
}
}
return (result ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
else if (strcmp (list->word->word, "--") == 0)
{
list = list->next;
break;
}
else if (*list->word->word == '-')
{
bad_option (list->word->word);
builtin_error ("usage: history [n] [-rwan [filename]]");
return (EX_USAGE);
}
else
break;
}
if (list)
{
limited = 1;
limit = get_numeric_arg (list);
}
hlist = history_list ();
if (hlist)
{
for (i = 0; hlist[i]; i++);
if (limit < 0)
limit = -limit;
if (!limited)
i = 0;
else
if ((i -= limit) < 0)
i = 0;
while (hlist[i])
{
QUIT;
printf ("%5d%c %s\n", i + history_base,
hlist[i]->data ? '*' : ' ', hlist[i]->line);
i++;
}
}
return (EXECUTION_SUCCESS);
}
#endif /* HISTORY */

74
builtins/inlib.def Normal file
View file

@ -0,0 +1,74 @@
This file is inlib.def, from which is created inlib.c.
It implements the Apollo-specific builtin "inlib" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES inlib.c
#include <stdio.h>
#include "../shell.h"
$BUILTIN inlib
$FUNCTION inlib_builtin
$DEPENDS_ON apollo
$SHORT_DOC inlib pathname [pathname...]
Install a user-supplied library specified by pathname in the current
shell process. The library is used to resolve external references
in programs and libraries loaded after its installation. Note
that the library is not loaded into the address space unless it is
needed to resolve an external reference. The list of inlibed
libraries is passed to all children of the current shell.
$END
#if defined (apollo)
#include <apollo/base.h>
#include <apollo/loader.h>
inlib_builtin (list)
WORD_LIST *list;
{
status_$t status;
int return_value;
short len;
if (!list)
{
builtin_error ("usage: inlib pathname [pathname...]");
return (EX_USAGE);
}
return_value = EXECUTION_SUCCESS;
while (list)
{
len = (short)strlen (list->word->word);
loader_$inlib (list->word->word, len, &status);
if (status.all != status_$ok)
{
builtin_error ("inlib failed for %s", list->word->word);
return_value = EXECUTION_FAILURE;
}
list = list->next;
}
return (return_value);
}
#endif /* apollo */

171
builtins/jobs.def Normal file
View file

@ -0,0 +1,171 @@
This file is jobs.def, from which is created jobs.c.
It implements the builtin "jobs" in Bash.
Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES jobs.c
$BUILTIN jobs
$FUNCTION jobs_builtin
$DEPENDS_ON JOB_CONTROL
$SHORT_DOC jobs [-lnp] [jobspec ...] | jobs -x command [args]
Lists the active jobs. The -l option lists process id's in addition
to the normal information; the -p option lists process id's only.
If -n is given, only processes that have changed status since the last
notification are printed. JOBSPEC restricts output to that job.
If -x is given, COMMAND is run after all job specifications that appear
in ARGS have been replaced with the process ID of that job's process group
leader.
$END
#include "../shell.h"
#if defined (JOB_CONTROL)
#include <sys/types.h>
#include <signal.h>
#include "../jobs.h"
#include "bashgetopt.h"
extern int job_control, interactive_shell;
static int execute_list_with_replacements ();
/* The `jobs' command. Prints outs a list of active jobs. If the
argument `-l' is given, then the process id's are printed also.
If the argument `-p' is given, print the process group leader's
pid only. If `-n' is given, only processes that have changed
status since the last notification are printed. If -x is given,
replace all job specs with the pid of the appropriate process
group leader and execute the command. */
int
jobs_builtin (list)
WORD_LIST *list;
{
int form = JLIST_STANDARD, execute = 0;
int opt;
int any_failed = 0;
if (!job_control && !interactive_shell)
return (EXECUTION_SUCCESS);
reset_internal_getopt ();
while ((opt = internal_getopt (list, "lpnx")) != -1)
{
switch (opt)
{
case 'l':
form = JLIST_LONG;
break;
case 'p':
form = JLIST_PID_ONLY;
break;
case 'n':
form = JLIST_CHANGED_ONLY;
break;
case 'x':
if (form != JLIST_STANDARD)
{
builtin_error ("Other options not allowed with `-x'");
return (EXECUTION_FAILURE);
}
execute++;
break;
default:
builtin_error ("usage: jobs [-lpn [jobspec]] [-x command [args]]");
return (EX_USAGE);
}
}
list = loptend;
if (execute)
return (execute_list_with_replacements (list));
if (!list)
{
list_jobs (form);
return (EXECUTION_SUCCESS);
}
while (list)
{
int job;
sigset_t set, oset;
BLOCK_CHILD (set, oset);
job = get_job_spec (list);
if ((job == NO_JOB) || !jobs || !jobs[job])
{
builtin_error ("No such job %s", list->word->word);
any_failed++;
}
else if (job != DUP_JOB)
list_one_job ((JOB *)NULL, form, 0, job);
UNBLOCK_CHILD (oset);
list = list->next;
}
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
static int
execute_list_with_replacements (list)
WORD_LIST *list;
{
register WORD_LIST *l;
int job, result;
/* First do the replacement of job specifications with pids. */
for (l = list; l; l = l->next)
{
if (l->word->word[0] == '%') /* we have a winner */
{
job = get_job_spec (l);
/* A bad job spec is not really a job spec! Pass it through. */
if (job < 0 || job >= job_slots || !jobs[job])
continue;
free (l->word->word);
l->word->word = itos (jobs[job]->pgrp);
}
}
/* Next make a new simple command and execute it. */
begin_unwind_frame ("jobs_builtin");
{
COMMAND *command = (COMMAND *)NULL;
add_unwind_protect (dispose_command, command);
command = make_bare_simple_command ();
command->value.Simple->words = copy_word_list (list);
command->value.Simple->redirects = (REDIRECT *)NULL;
command->flags |= CMD_INHIBIT_EXPANSION;
command->value.Simple->flags |= CMD_INHIBIT_EXPANSION;
result = execute_command (command);
}
run_unwind_frame ("jobs_builtin");
return (result);
}
#endif /* JOB_CONTROL */

281
builtins/kill.def Normal file
View file

@ -0,0 +1,281 @@
This file is kill.def, from which is created kill.c.
It implements the builtin "kill" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES kill.c
$BUILTIN kill
$FUNCTION kill_builtin
$DEPENDS_ON JOB_CONTROL
$SHORT_DOC kill [-s sigspec | -sigspec] [pid | job]... | -l [signum]
Send the processes named by PID (or JOB) the signal SIGSPEC. If
SIGSPEC is not present, then SIGTERM is assumed. An argument of `-l'
lists the signal names; if arguments follow `-l' they are assumed to
be signal numbers for which names should be listed. Kill is a shell
builtin for two reasons: it allows job IDs to be used instead of
process IDs, and, if you have reached the limit on processes that
you can create, you don't have to start a process to kill another one.
$END
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
#if !defined (errno)
extern int errno;
#endif /* !errno */
#include "../bashtypes.h"
#include "../shell.h"
#include "../trap.h"
#include "../jobs.h"
#include "common.h"
#include <errno.h>
#if defined (JOB_CONTROL)
extern int interactive;
extern int posixly_correct;
#if !defined (CONTINUE_AFTER_KILL_ERROR)
# define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
#else
# define CONTINUE_OR_FAIL goto continue_killing
#endif /* CONTINUE_AFTER_KILL_ERROR */
/* Here is the kill builtin. We only have it so that people can type
kill -KILL %1? No, if you fill up the process table this way you
can still kill some. */
int
kill_builtin (list)
WORD_LIST *list;
{
int signal = SIGTERM;
int any_succeeded = 0, listing = 0, saw_signal = 0;
char *sigspec = "TERM", *word;
pid_t pid;
if (!list)
return (EXECUTION_SUCCESS);
/* Process options. */
while (list)
{
word = list->word->word;
if (ISOPTION (word, 'l'))
{
listing++;
list = list->next;
}
else if (ISOPTION (word, 's'))
{
list = list->next;
if (list)
{
sigspec = list->word->word;
if (sigspec[0] == '0' && !sigspec[1])
signal = 0;
else
signal = decode_signal (sigspec);
list = list->next;
}
else
{
builtin_error ("-s requires an argument");
return (EXECUTION_FAILURE);
}
}
else if (ISOPTION (word, '-'))
{
list = list->next;
break;
}
/* If this is a signal specification then process it. We only process
the first one seen; other arguments may signify process groups (e.g,
-num == process group num). */
else if ((*word == '-') && !saw_signal)
{
sigspec = word + 1;
signal = decode_signal (sigspec);
saw_signal++;
list = list->next;
}
else
break;
}
if (listing)
{
if (!list)
{
register int i;
register int column = 0;
char *name;
for (i = 1; i < NSIG; i++)
{
name = signal_name (i);
if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
continue;
if (posixly_correct)
printf ("%s%s", name, (i == NSIG - 1) ? "" : " ");
else
{
printf ("%2d) %s", i, name);
if (++column < 4)
printf ("\t");
else
{
printf ("\n");
column = 0;
}
}
}
if (posixly_correct || column != 0)
printf ("\n");
}
else
{
/* List individual signal names. */
while (list)
{
int signum;
char *name;
if ((sscanf (list->word->word, "%d", &signum) != 1) ||
(signum <= 0))
{
list_error:
builtin_error ("bad signal number: %s", list->word->word);
list = list->next;
continue;
}
/* This is specified by Posix.2 so that exit statuses can be
mapped into signal numbers. */
if (signum > 128)
signum -= 128;
if (signum >= NSIG)
goto list_error;
name = signal_name (signum);
if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
{
list = list->next;
continue;
}
printf ("%s\n", name);
list = list->next;
}
}
return (EXECUTION_SUCCESS);
}
/* OK, we are killing processes. */
if (signal == NO_SIG)
{
builtin_error ("bad signal spec `%s'", sigspec);
return (EXECUTION_FAILURE);
}
while (list)
{
word = list->word->word;
if (*word == '-')
word++;
if (all_digits (word))
{
/* Use the entire argument in case of minus sign presence. */
pid = (pid_t) atoi (list->word->word);
if (kill_pid (pid, signal, 0) < 0)
goto signal_error;
else
any_succeeded++;
}
else if (*list->word->word != '%')
{
builtin_error ("No such pid %s", list->word->word);
CONTINUE_OR_FAIL;
}
#if 1
else if (interactive)
/* Posix.2 says you can kill without job control active (4.32.4) */
#else
else if (job_control) /* can't kill jobs if not using job control */
#endif
{ /* Must be a job spec. Check it out. */
int job;
sigset_t set, oset;
BLOCK_CHILD (set, oset);
job = get_job_spec (list);
if (job < 0 || job >= job_slots || !jobs[job])
{
if (job != DUP_JOB)
builtin_error ("No such job %s", list->word->word);
UNBLOCK_CHILD (oset);
CONTINUE_OR_FAIL;
}
/* Job spec used. Kill the process group. If the job was started
without job control, then its pgrp == shell_pgrp, so we have
to be careful. We take the pid of the first job in the pipeline
in that case. */
if (jobs[job]->flags & J_JOBCONTROL)
pid = jobs[job]->pgrp;
else
pid = jobs[job]->pipe->pid;
UNBLOCK_CHILD (oset);
if (kill_pid (pid, signal, 1) < 0)
{
signal_error:
if (errno == EPERM)
builtin_error ("(%d) - Not owner", (int)pid);
else if (errno == ESRCH)
builtin_error ("(%d) - No such pid", (int)pid);
else
builtin_error ("Invalid signal %d", signal);
CONTINUE_OR_FAIL;
}
else
any_succeeded++;
}
else
{
builtin_error ("bad process specification `%s'", list->word->word);
CONTINUE_OR_FAIL;
}
continue_killing:
list = list->next;
}
if (any_succeeded)
return (EXECUTION_SUCCESS);
else
return (EXECUTION_FAILURE);
}
#endif /* JOB_CONTROL */

77
builtins/let.def Normal file
View file

@ -0,0 +1,77 @@
This file is let.def, from which is created let.c.
It implements the builtin "let" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$BUILTIN let
$FUNCTION let_builtin
$PRODUCES let.c
$SHORT_DOC let arg [arg ...]
Each ARG is an arithmetic expression to be evaluated. 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.
- unary minus
! logical NOT
* / % multiplication, division, remainder
+ - addition, subtraction
<= >= < > comparison
== != equality inequality
= assignment
Shell variables are allowed as operands. The name of the variable
is replaced by its value (coerced to a long integer) within
an expression. The variable need not have its integer attribute
turned on to be used in an expression.
Operators are evaluated in order of precedence. Sub-expressions in
parentheses are evaluated first and may override the precedence
rules above.
If the last ARG evaluates to 0, let returns 1; 0 is returned
otherwise.
$END
#include "../shell.h"
/* Arithmetic LET function. */
let_builtin (list)
WORD_LIST *list;
{
long ret = 0L;
if (!list)
{
builtin_error ("argument (expression) expected");
return (EXECUTION_FAILURE);
}
while (list)
{
ret = evalexp (list->word->word);
list = list->next;
}
if (ret == 0L)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
}

1311
builtins/mkbuiltins.c Normal file

File diff suppressed because it is too large Load diff

63
builtins/psize.c Normal file
View file

@ -0,0 +1,63 @@
/* psize.c - Find pipe size. */
/* Copyright (C) 1987, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Bash is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with Bash; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Write output in 128-byte chunks until we get a sigpipe or write gets an
EPIPE. Then report how many bytes we wrote. We assume that this is the
pipe size. */
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#include "../command.h"
#include "../general.h"
extern int errno;
int nw;
sighandler
sigpipe (sig)
int sig;
{
fprintf (stderr, "%d\n", nw);
exit (0);
}
main (argc, argv)
int argc;
char **argv;
{
char buf[128];
register int i;
for (i = 0; i < 128; i++)
buf[i] = ' ';
signal (SIGPIPE, sigpipe);
nw = 0;
for (;;)
{
int n;
n = write (1, buf, 128);
nw += n;
}
}

24
builtins/psize.sh Executable file
View file

@ -0,0 +1,24 @@
#! /bin/sh
#
# psize.sh -- determine this system's pipe size, and write a define to
# pipesize.h so ulimit.c can use it.
echo "/*"
echo " * pipesize.h"
echo " *"
echo " * This file is automatically generated by psize.sh"
echo " * Do not edit!"
echo " */"
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

276
builtins/read.def Normal file
View file

@ -0,0 +1,276 @@
This file is read.def, from which is created read.c.
It implements the builtin "read" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES read.c
$BUILTIN read
$FUNCTION read_builtin
$SHORT_DOC read [-r] [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, etc.
with leftover words assigned to the last NAME. Only the characters
found in $IFS are recognized as word delimiters. The return code is
zero, unless end-of-file is encountered. If the -r option is given,
this signifies `raw' input, and backslash processing is disabled.
$END
#include <stdio.h>
#include "../shell.h"
#include "common.h"
#define issep(c) (strchr (ifs_chars, (c)) != (char *)0)
static int stream_close ();
extern int interrupt_immediately;
/* Read the value of the shell variables whose names follow.
The reading is done from the current input stream, whatever
that may be. Successive words of the input line are assigned
to the variables mentioned in LIST. The last variable in LIST
gets the remainder of the words on the line. If no variables
are mentioned in LIST, then the default variable is $REPLY.
S. R. Bourne's shell complains if you don't name a variable
to receive the stuff that is read. GNU's shell doesn't. This
allows you to let the user type random things. */
read_builtin (list)
WORD_LIST *list;
{
register char *varname;
int size, c, i, fildes, raw_mode, pass_next, saw_escape, retval;
char *input_string, *orig_input_string, *ifs_chars, *t;
FILE *input_stream;
SHELL_VAR *var;
i = 0; /* Index into the string that we are reading. */
raw_mode = 0; /* Not reading raw input be default. */
while (list)
{
if (ISOPTION (list->word->word, 'r'))
{
raw_mode = 1;
list = list->next;
}
else if (ISOPTION (list->word->word, '-'))
{
list = list->next;
break;
}
else if (*list->word->word == '-')
{
bad_option (list->word->word);
builtin_error ("usage: read [-r] [name ...]");
return (EX_USAGE);
}
else
break;
}
/* We need unbuffered input from stdin. So we make a new stream with
the same file descriptor as stdin, then unbuffer it. */
fildes = dup (fileno (stdin));
if (fildes == -1)
return (EXECUTION_FAILURE);
input_stream = fdopen (fildes, "r");
if (!input_stream)
{
close (fildes);
return (EXECUTION_FAILURE);
}
var = find_variable ("IFS");
ifs_chars = var ? value_cell (var) : " \t\n";
input_string = xmalloc (size = 128);
setbuf (input_stream, (char *)NULL);
begin_unwind_frame ("read_builtin");
add_unwind_protect (xfree, input_string);
add_unwind_protect (stream_close, input_stream);
interrupt_immediately++;
pass_next = 0; /* Non-zero signifies last char was backslash. */
saw_escape = 0; /* Non-zero signifies that we saw an escape char */
while ((c = getc (input_stream)) != EOF)
{
if (i + 2 >= size)
input_string = xrealloc (input_string, size += 128);
/* If the next character is to be accepted verbatim, a backslash
newline pair still disappears from the input. */
if (pass_next)
{
if (c == '\n')
i--; /* back up over the CTLESC */
else
input_string[i++] = c;
pass_next = 0;
continue;
}
if (c == '\\' && !raw_mode)
{
pass_next++;
saw_escape++;
input_string[i++] = CTLESC;
continue;
}
if (c == '\n')
break;
if (c == CTLESC || c == CTLNUL)
{
saw_escape++;
input_string[i++] = CTLESC;
}
input_string[i++] = c;
}
input_string[i] = '\0';
interrupt_immediately--;
discard_unwind_frame ("read_builtin");
fclose (input_stream);
if (c == EOF)
{
retval = EXECUTION_FAILURE;
/* input_string[0] = '\0'; */
}
else
retval = EXECUTION_SUCCESS;
if (!list)
{
if (saw_escape)
{
t = dequote_string (input_string);
var = bind_variable ("REPLY", t);
free (t);
}
else
var = bind_variable ("REPLY", input_string);
var->attributes &= ~att_invisible;
free (input_string);
}
else
{
/* This code implements the Posix.2 spec for splitting the words
read and assigning them to variables. If $IFS is unset, we
use the default value of " \t\n". */
orig_input_string = input_string;
/* Remove IFS white space at the beginning of the input string. If
$IFS is null, no field splitting is performed. */
for (t = input_string; *ifs_chars && spctabnl (*t) && issep (*t); t++)
;
input_string = t;
for (; list->next; list = list->next)
{
char *e, *t1;
varname = list->word->word;
if (legal_identifier (varname) == 0)
{
builtin_error ("%s: not a legal variable name", varname);
free (orig_input_string);
return (EXECUTION_FAILURE);
}
/* If there are more variables than words read from the input,
the remaining variables are set to the empty string. */
if (*input_string)
{
/* This call updates INPUT_STRING. */
t = get_word_from_string (&input_string, ifs_chars, &e);
if (t)
*e = '\0';
/* Don't bother to remove the CTLESC unless we added one
somewhere while reading the string. */
if (t && saw_escape)
{
t1 = dequote_string (t);
var = bind_variable (varname, t1);
free (t1);
}
else
var = bind_variable (varname, t);
}
else
{
t = (char *)0;
var = bind_variable (varname, "");
}
stupidly_hack_special_variables (varname);
var->attributes &= ~att_invisible;
if (t)
free (t);
}
if (legal_identifier (list->word->word) == 0)
{
builtin_error ("%s: not a legal variable name", list->word->word);
free (orig_input_string);
return (EXECUTION_FAILURE);
}
/* This has to be done this way rather than using string_list
and list_string because Posix.2 says that the last variable gets the
remaining words and their intervening separators. */
input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars,
saw_escape);
if (saw_escape)
{
t = dequote_string (input_string);
var = bind_variable (list->word->word, t);
free (t);
}
else
var = bind_variable (list->word->word, input_string);
stupidly_hack_special_variables (list->word->word);
var->attributes &= ~att_invisible;
free (orig_input_string);
}
return (retval);
}
/* This way I don't have to know whether fclose () is a
function or a macro. */
static int
stream_close (file)
FILE *file;
{
return (fclose (file));
}

154
builtins/reserved.def Normal file
View file

@ -0,0 +1,154 @@
This file is reserved.def, in which the shell reserved words are defined.
It has no direct C file production, but defines builtins for the Bash
builtin help command.
Copyright (C) 1987, 1989, 1991, 1992 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.
$BUILTIN for
$SHORT_DOC for NAME [in WORDS ... ;] do COMMANDS; done
The `for' loop executes a sequence of commands for each member in a
list of items. If `in WORDS ...;' is not present, then `in "$@"' is
assumed. For each element in WORDS, NAME is set to that element, and
the COMMANDS are executed.
$END
$BUILTIN select
$SHORT_DOC select NAME [in WORDS ... ;] do COMMANDS; done
The WORDS are expanded, generating a list of words. The
set of expanded words is printed on the standard error, each
preceded by a number. If `in WORDS' is not present, `in "$@"'
is assumed. The PS3 prompt is then displayed and a line read
from the standard input. If the line consists of the number
corresponding to one of the displayed words, then NAME is set
to that word. If the line is empty, WORDS and the prompt are
redisplayed. If EOF is read, the command completes. Any other
value read causes NAME to be set to null. The line read is saved
in the variable REPLY. COMMANDS are executed after each selection
until a break or return command is executed.
$END
$BUILTIN case
$SHORT_DOC case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
Selectively execute COMMANDS based upon WORD matching PATTERN. The
`|' is used to separate multiple patterns.
$END
$BUILTIN if
$SHORT_DOC if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
The if COMMANDS are executed. If the exit status is zero, then the then
COMMANDS are executed. Otherwise, each of the elif COMMANDS are executed
in turn, and if the exit status is zero, the corresponding then COMMANDS
are executed and the if command completes. Otherwise, the else COMMANDS
are executed, if present. The exit status is the exit status of the last
command executed, or zero if no condition tested true.
$END
$BUILTIN while
$SHORT_DOC while COMMANDS; do COMMANDS; done
Expand and execute COMMANDS as long as the final command in the
`while' COMMANDS has an exit status of zero.
$END
$BUILTIN until
$SHORT_DOC until COMMANDS; do COMMANDS; done
Expand and execute COMMANDS as long as the final command in the
`until' COMMANDS has an exit status which is not zero.
$END
$BUILTIN function
$SHORT_DOC function NAME { COMMANDS ; } or NAME () { COMMANDS ; }
Create a simple command invoked by NAME which runs COMMANDS.
Arguments on the command line along with NAME are passed to the
function as $0 .. $n.
$END
$BUILTIN { ... }
$DOCNAME grouping_braces
$SHORT_DOC { COMMANDS }
Run a set of commands in a group. This is one way to redirect an
entire set of commands.
$END
$BUILTIN %
$DOCNAME fg_percent
$SHORT_DOC %[DIGITS | WORD] [&]
This is similar to the `fg' command. Resume a stopped or background
job. If you specifiy DIGITS, then that job is used. If you specify
WORD, then the job whose name begins with WORD is used. Following the
job specification with a `&' places the job in the background.
$END
$BUILTIN variables
$DOCNAME variable_help
$SHORT_DOC variables - Some variable names and meanings
BASH_VERSION The version numbers of this Bash.
CDPATH A colon separated list of directories to search
when the argument to `cd' is not found in the current
directory.
#if defined (HISTORY)
HISTFILE The name of the file where your command history is stored.
HISTFILESIZE The maximum number of lines this file can contain.
HISTSIZE The maximum number of history lines that a running
shell can access.
#endif /* HISTORY */
HOME The complete pathname to your login directory.
HOSTTYPE The type of CPU this version of Bash is running under.
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 EOF characters that can be seen
in a row on an empty line before the shell will exit
(default 10). When unset, EOF signifies the end of input.
MAILCHECK How often, in seconds, Bash checks for new mail.
MAILPATH A colon-separated list of filenames which Bash checks
for new mail.
PATH A colon-separated list of directories to search when
looking for commands.
PROMPT_COMMAND A command to be executed before the printing of each
primary prompt.
PS1 The primary prompt string.
PS2 The secondary prompt string.
TERM The name of the current terminal type.
auto_resume Non-null means a command word appearing on a line by
itself is first looked for in the list of currently
stopped jobs. If found there, that job is foregrounded.
A value of `exact' means that the command word must
exactly match a command in the list of stopped jobs. A
value of `substring' means that the command word must
match a substring of the job. Any other value means that
the command must be a prefix of a stopped job.
#if defined (HISTORY)
command_oriented_history
Non-null means to save multiple-line commands together on
a single history line.
# if defined (BANG_HISTORY)
histchars Characters controlling history expansion and quick
substitution. The first character is the history
substitution character, usually `!'. The second is
the `quick substitution' character, usually `^'. The
third is the `history comment' character, usually `#'.
# endif /* BANG_HISTORY */
HISTCONTROL Set to a value of `ignorespace', it means don't enter
lines which begin with a space or tab on the history
list. Set to a value of `ignoredups', it means don't
enter lines which match the last entered line. Set to
`ignoreboth' means to combine the two options. Unset,
or set to any other value than those above means to save
all lines on the history list.
#endif /* HISTORY */
$END

57
builtins/return.def Normal file
View file

@ -0,0 +1,57 @@
This file is return.def, from which is created return.c.
It implements the builtin "return" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES return.c
$BUILTIN return
$FUNCTION return_builtin
$SHORT_DOC return [n]
Causes a function to exit with the return value specified by N. If N
is omitted, the return status is that of the last command.
$END
#include "../shell.h"
extern int last_command_exit_value;
extern int return_catch_flag, return_catch_value;
extern jmp_buf return_catch;
/* If we are executing a user-defined function then exit with the value
specified as an argument. if no argument is given, then the last
exit status is used. */
int
return_builtin (list)
WORD_LIST *list;
{
return_catch_value = get_numeric_arg (list);
if (!list)
return_catch_value = last_command_exit_value;
if (return_catch_flag)
longjmp (return_catch, 1);
else
{
builtin_error ("Can only `return' from a function");
return (EXECUTION_FAILURE);
}
}

528
builtins/set.def Normal file
View file

@ -0,0 +1,528 @@
This file is set.def, from which is created set.c.
It implements the "set" and "unset" builtins in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES set.c
#include <stdio.h>
#include "../shell.h"
#include "../flags.h"
#include "bashgetopt.h"
extern int interactive;
extern int noclobber, no_brace_expansion, posixly_correct;
#if defined (READLINE)
extern int rl_editing_mode, no_line_editing;
#endif /* READLINE */
#define USAGE_STRING "set [--abefhknotuvxldHCP] [-o option] [arg ...]"
$BUILTIN set
$FUNCTION set_builtin
$SHORT_DOC set [--abefhknotuvxldHCP] [-o option] [arg ...]
-a Mark variables which are modified or created for export.
-b Notify of job termination immediately.
-e Exit immediately if a command exits with a non-zero status.
-f Disable file name generation (globbing).
-h Locate and remember function commands as functions are
defined. Function commands are normally looked up when
the function is executed.
-i Force the shell to be an "interactive" one. Interactive shells
always read `~/.bashrc' on startup.
-k All keyword arguments are placed in the environment for a
command, not just those that precede the command name.
-m Job control is enabled.
-n Read commands but do not execute them.
-o option-name
Set the variable corresponding to option-name:
allexport same as -a
braceexpand the shell will perform brace expansion
#if defined (READLINE)
emacs use an emacs-style line editing interface
#endif /* READLINE */
errexit same as -e
#if defined (BANG_HISTORY)
histexpand same as -H
#endif /* BANG_HISTORY */
ignoreeof the shell will not exit upon reading EOF
interactive-comments
allow comments to appear in interactive commands
monitor same as -m
noclobber disallow redirection to existing files
noexec same as -n
noglob same as -f
nohash same as -d
notify save as -b
nounset same as -u
physical same as -P
posix change the behavior of bash where the default
operation differs from the 1003.2 standard to
match the standard
privileged same as -p
verbose same as -v
#if defined (READLINE)
vi use a vi-style line editing interface
#endif /* READLINE */
xtrace same as -x
-p Turned on whenever the real and effective user ids do not match.
Disables processing of the $ENV file and importing of shell
functions. Turning this option off causes the effective uid and
gid to be set to the real uid and gid.
-t Exit after reading and executing one command.
-u Treat unset variables as an error when substituting.
-v Print shell input lines as they are read.
-x Print commands and their arguments as they are executed.
-l Save and restore the binding of the NAME in a FOR command.
-d Disable the hashing of commands that are looked up for execution.
Normally, commands are remembered in a hash table, and once
found, do not have to be looked up again.
#if defined (BANG_HISTORY)
-H Enable ! style history substitution. This flag is on
by default.
#endif /* BANG_HISTORY */
-C If set, disallow existing regular files to be overwritten
by redirection of output.
-P If set, do not follow symbolic links when executing commands
such as cd which change the current directory.
Using + rather than - causes these flags to be turned off. The
flags can also be used upon invocation of the shell. The current
set of flags may be found in $-. The remaining n ARGs are positional
parameters and are assigned, in order, to $1, $2, .. $n. If no
ARGs are given, all shell variables are printed.
$END
/* An a-list used to match long options for set -o to the corresponding
option letter. */
struct {
char *name;
int letter;
} o_options[] = {
{ "allexport", 'a' },
{ "errexit", 'e' },
#if defined (BANG_HISTORY)
{ "histexpand", 'H' },
#endif /* BANG_HISTORY */
{ "monitor", 'm' },
{ "noexec", 'n' },
{ "noglob", 'f' },
{ "nohash", 'd' },
#if defined (JOB_CONTROL)
{ "notify", 'b' },
#endif /* JOB_CONTROL */
{"nounset", 'u' },
{"physical", 'P' },
{"privileged", 'p' },
{"verbose", 'v' },
{"xtrace", 'x' },
{(char *)NULL, 0},
};
#define MINUS_O_FORMAT "%-15s\t%s\n"
void
list_minus_o_opts ()
{
register int i;
char *on = "on", *off = "off";
printf (MINUS_O_FORMAT, "braceexpand", (no_brace_expansion == 0) ? on : off);
printf (MINUS_O_FORMAT, "noclobber", (noclobber == 1) ? on : off);
if (find_variable ("ignoreeof") || find_variable ("IGNOREEOF"))
printf (MINUS_O_FORMAT, "ignoreeof", on);
else
printf (MINUS_O_FORMAT, "ignoreeof", off);
printf (MINUS_O_FORMAT, "interactive-comments",
interactive_comments ? on : off);
printf (MINUS_O_FORMAT, "posix", posixly_correct ? on : off);
#if defined (READLINE)
if (no_line_editing)
{
printf (MINUS_O_FORMAT, "emacs", off);
printf (MINUS_O_FORMAT, "vi", off);
}
else
{
/* Magic. This code `knows' how readline handles rl_editing_mode. */
printf (MINUS_O_FORMAT, "emacs", (rl_editing_mode == 1) ? on : off);
printf (MINUS_O_FORMAT, "vi", (rl_editing_mode == 0) ? on : off);
}
#endif /* READLINE */
for (i = 0; o_options[i].name; i++)
{
int *on_or_off, zero = 0;
on_or_off = find_flag (o_options[i].letter);
if (on_or_off == FLAG_UNKNOWN)
on_or_off = &zero;
printf (MINUS_O_FORMAT, o_options[i].name, (*on_or_off == 1) ? on : off);
}
}
set_minus_o_option (on_or_off, option_name)
int on_or_off;
char *option_name;
{
int option_char = -1;
if (STREQ (option_name, "braceexpand"))
{
if (on_or_off == FLAG_ON)
no_brace_expansion = 0;
else
no_brace_expansion = 1;
}
else if (STREQ (option_name, "noclobber"))
{
if (on_or_off == FLAG_ON)
bind_variable ("noclobber", "");
else
unbind_variable ("noclobber");
stupidly_hack_special_variables ("noclobber");
}
else if (STREQ (option_name, "ignoreeof"))
{
unbind_variable ("ignoreeof");
unbind_variable ("IGNOREEOF");
if (on_or_off == FLAG_ON)
bind_variable ("IGNOREEOF", "10");
stupidly_hack_special_variables ("IGNOREEOF");
}
#if defined (READLINE)
else if ((STREQ (option_name, "emacs")) || (STREQ (option_name, "vi")))
{
if (on_or_off == FLAG_ON)
{
rl_variable_bind ("editing-mode", option_name);
if (interactive)
with_input_from_stdin ();
no_line_editing = 0;
}
else
{
int isemacs = (rl_editing_mode == 1);
if ((isemacs && STREQ (option_name, "emacs")) ||
(!isemacs && STREQ (option_name, "vi")))
{
if (interactive)
with_input_from_stream (stdin, "stdin");
no_line_editing = 1;
}
else
builtin_error ("not in %s editing mode", option_name);
}
}
#endif /* READLINE */
else if (STREQ (option_name, "interactive-comments"))
interactive_comments = (on_or_off == FLAG_ON);
else if (STREQ (option_name, "posix"))
{
posixly_correct = (on_or_off == FLAG_ON);
unbind_variable ("POSIXLY_CORRECT");
unbind_variable ("POSIX_PEDANTIC");
if (on_or_off == FLAG_ON)
{
bind_variable ("POSIXLY_CORRECT", "");
stupidly_hack_special_variables ("POSIXLY_CORRECT");
}
}
else
{
register int i;
for (i = 0; o_options[i].name; i++)
{
if (STREQ (option_name, o_options[i].name))
{
option_char = o_options[i].letter;
break;
}
}
if (option_char == -1)
{
builtin_error ("%s: unknown option name", option_name);
return (EXECUTION_FAILURE);
}
if (change_flag (option_char, on_or_off) == FLAG_ERROR)
{
bad_option (option_name);
return (EXECUTION_FAILURE);
}
}
return (EXECUTION_SUCCESS);
}
/* Set some flags from the word values in the input list. If LIST is empty,
then print out the values of the variables instead. If LIST contains
non-flags, then set $1 - $9 to the successive words of LIST. */
set_builtin (list)
WORD_LIST *list;
{
int on_or_off, flag_name, force_assignment = 0;
if (!list)
{
SHELL_VAR **vars;
vars = all_shell_variables ();
if (vars)
{
print_var_list (vars);
free (vars);
}
vars = all_shell_functions ();
if (vars)
{
print_var_list (vars);
free (vars);
}
return (EXECUTION_SUCCESS);
}
/* Check validity of flag arguments. */
if (*list->word->word == '-' || *list->word->word == '+')
{
register char *arg;
WORD_LIST *save_list = list;
while (list && (arg = list->word->word))
{
char c;
if (arg[0] != '-' && arg[0] != '+')
break;
/* `-' or `--' signifies end of flag arguments. */
if (arg[0] == '-' &&
(!arg[1] || (arg[1] == '-' && !arg[2])))
break;
while (c = *++arg)
{
if (find_flag (c) == FLAG_UNKNOWN && c != 'o')
{
char s[2];
s[0] = c; s[1] = '\0';
bad_option (s);
if (c == '?')
printf ("usage: %s\n", USAGE_STRING);
return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
}
list = list->next;
}
list = save_list;
}
/* Do the set command. While the list consists of words starting with
'-' or '+' treat them as flags, otherwise, start assigning them to
$1 ... $n. */
while (list)
{
char *string = list->word->word;
/* If the argument is `--' or `-' then signal the end of the list
and remember the remaining arguments. */
if (string[0] == '-' && (!string[1] || (string[1] == '-' && !string[2])))
{
list = list->next;
/* `set --' unsets the positional parameters. */
if (string[1] == '-')
force_assignment = 1;
/* Until told differently, the old shell behaviour of
`set - [arg ...]' being equivalent to `set +xv [arg ...]'
stands. Posix.2 says the behaviour is marked as obsolescent. */
else
{
change_flag ('x', '+');
change_flag ('v', '+');
}
break;
}
if ((on_or_off = *string) &&
(on_or_off == '-' || on_or_off == '+'))
{
int i = 1;
while (flag_name = string[i++])
{
if (flag_name == '?')
{
printf ("usage: %s\n", USAGE_STRING);
return (EXECUTION_SUCCESS);
}
else if (flag_name == 'o') /* -+o option-name */
{
char *option_name;
WORD_LIST *opt;
opt = list->next;
if (!opt)
{
list_minus_o_opts ();
continue;
}
option_name = opt->word->word;
if (!option_name || !*option_name || (*option_name == '-'))
{
list_minus_o_opts ();
continue;
}
list = list->next; /* Skip over option name. */
if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
return (EXECUTION_FAILURE);
}
else
{
if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
{
char opt[3];
opt[0] = on_or_off;
opt[1] = flag_name;
opt[2] = '\0';
bad_option (opt);
return (EXECUTION_FAILURE);
}
}
}
}
else
{
break;
}
list = list->next;
}
/* Assigning $1 ... $n */
if (list || force_assignment)
remember_args (list, 1);
return (EXECUTION_SUCCESS);
}
$BUILTIN unset
$FUNCTION unset_builtin
$SHORT_DOC unset [-f] [-v] [name ...]
For each NAME, remove the corresponding variable or function. Given
the `-v', unset will only act on variables. Given the `-f' flag,
unset will only act on functions. With neither flag, unset first
tries to unset a variable, and if that fails, then tries to unset a
function. Some variables (such as PATH and IFS) cannot be unset; also
see readonly.
$END
unset_builtin (list)
WORD_LIST *list;
{
int unset_function = 0, unset_variable = 0, opt;
int any_failed = 0;
char *name;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "fv")) != -1)
{
switch (opt)
{
case 'f':
unset_function = 1;
break;
case 'v':
unset_variable = 1;
break;
default:
return (EXECUTION_FAILURE);
}
}
list = loptend;
if (unset_function && unset_variable)
{
builtin_error ("cannot simultaneously unset a function and a variable");
return (EXECUTION_FAILURE);
}
while (list)
{
name = list->word->word;
if (!unset_function &&
find_name_in_list (name, non_unsettable_vars) > -1)
{
builtin_error ("%s: cannot unset", name);
any_failed++;
}
else
{
SHELL_VAR *var;
int tem;
var = unset_function ? find_function (name) : find_variable (name);
/* Posix.2 says that unsetting readonly variables is an error. */
if (var && readonly_p (var))
{
builtin_error ("%s: cannot unset: readonly %s",
name, unset_function ? "function" : "variable");
any_failed++;
list = list->next;
continue;
}
/* Unless the -f option is supplied, the name refers to a
variable. */
tem = makunbound
(name, unset_function ? shell_functions : shell_variables);
/* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
is specified, the name refers to a variable; if a variable by
that name does not exist, a function by that name, if any,
shall be unset.'' */
if ((tem == -1) && !unset_function && !unset_variable)
tem = makunbound (name, shell_functions);
if (tem == -1)
any_failed++;
else if (!unset_function)
stupidly_hack_special_variables (name);
}
list = list->next;
}
if (any_failed)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
}

253
builtins/setattr.def Normal file
View file

@ -0,0 +1,253 @@
This file is setattr.def, from which is created setattr.c.
It implements the builtins "export" and "readonly", in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES setattr.c
#include "../shell.h"
#include "common.h"
#include "bashgetopt.h"
extern int array_needs_making;
extern char *this_command_name;
$BUILTIN export
$FUNCTION export_builtin
$SHORT_DOC export [-n] [-f] [name ...] or export -p
NAMEs are marked for automatic export to the environment of
subsequently executed commands. If the -f option is given,
the NAMEs refer to functions. If no NAMEs are given, or if `-p'
is given, a list of all names that are exported in this shell is
printed. An argument of `-n' says to remove the export property
from subsequent NAMEs. An argument of `--' disables further option
processing.
$END
/* For each variable name in LIST, make that variable appear in the
environment passed to simple commands. If there is no LIST, then
print all such variables. An argument of `-n' says to remove the
exported attribute from variables named in LIST. An argument of
-f indicates that the names present in LIST refer to functions. */
export_builtin (list)
register WORD_LIST *list;
{
return (set_or_show_attributes (list, att_exported));
}
$BUILTIN readonly
$FUNCTION readonly_builtin
$SHORT_DOC readonly [-n] [-f] [name ...] or readonly -p
The given NAMEs are marked readonly and the values of these NAMEs may
not be changed by subsequent assignment. If the -f option is given,
then functions corresponding to the NAMEs are so marked. If no
arguments are given, or if `-p' is given, a list of all readonly names
is printed. An argument of `-n' says to remove the readonly property
from subsequent NAMEs. An argument of `--' disables further option
processing.
$END
/* For each variable name in LIST, make that variable readonly. Given an
empty LIST, print out all existing readonly variables. */
readonly_builtin (list)
register WORD_LIST *list;
{
return (set_or_show_attributes (list, att_readonly));
}
/* For each variable name in LIST, make that variable have the specified
ATTRIBUTE. An arg of `-n' says to remove the attribute from the the
remaining names in LIST. */
int
set_or_show_attributes (list, attribute)
register WORD_LIST *list;
int attribute;
{
register SHELL_VAR *var;
int assign, undo = 0, functions_only = 0, any_failed = 0, opt;
/* Read arguments from the front of the list. */
reset_internal_getopt ();
while ((opt = internal_getopt (list, "nfp")) != -1)
{
switch (opt)
{
case 'n':
undo = 1;
break;
case 'f':
functions_only = 1;
break;
case 'p':
break;
default:
builtin_error ("usage: %s [-nfp] [varname]", this_command_name);
return (EX_USAGE);
}
}
list = loptend;
if (list)
{
if (attribute & att_exported)
array_needs_making = 1;
/* Cannot undo readonly status. */
if (undo && (attribute & att_readonly))
attribute &= ~att_readonly;
while (list)
{
register char *name = list->word->word;
if (functions_only)
{
var = find_function (name);
if (!var)
{
builtin_error ("%s: not a function", name);
any_failed++;
}
else
{
if (undo)
var->attributes &= ~attribute;
else
var->attributes |= attribute;
}
list = list->next;
if (attribute == att_exported)
array_needs_making++;
continue;
}
assign = assignment (name);
if (assign)
name[assign] = '\0';
if (legal_identifier (name) == 0)
{
builtin_error ("%s: not a legal variable name", name);
any_failed++;
list = list->next;
continue;
}
if (assign)
{
name[assign] = '=';
/* This word has already been expanded once with command
and parameter expansion. Call do_assignment_no_expand (),
which does not do command or parameter substitution. */
do_assignment_no_expand (name);
name[assign] = '\0';
}
if (undo)
{
var = find_variable (name);
if (var)
var->attributes &= ~attribute;
}
else
{
SHELL_VAR *find_tempenv_variable (), *tv;
if (tv = find_tempenv_variable (name))
{
var = bind_variable (tv->name, tv->value);
dispose_variable (tv);
}
else
var = find_variable (name);
if (!var)
{
var = bind_variable (name, (char *)NULL);
var->attributes |= att_invisible;
}
var->attributes |= attribute;
}
array_needs_making++; /* XXX */
list = list->next;
}
}
else
{
SHELL_VAR **variable_list;
register int i;
if ((attribute & att_function) || functions_only)
{
variable_list = all_shell_functions ();
if (attribute != att_function)
attribute &= ~att_function; /* so declare -xf works, for example */
}
else
variable_list = all_shell_variables ();
if (variable_list)
{
for (i = 0; var = variable_list[i]; i++)
{
if ((var->attributes & attribute) && !invisible_p (var))
{
char flags[6];
flags[0] = '\0';
if (exported_p (var))
strcat (flags, "x");
if (readonly_p (var))
strcat (flags, "r");
if (function_p (var))
strcat (flags, "f");
if (integer_p (var))
strcat (flags, "i");
if (flags[0])
{
printf ("declare -%s ", flags);
if (!function_p (var))
{
char *x = double_quote (value_cell (var));
printf ("%s=%s\n", var->name, x);
free (x);
}
else
{
char *named_function_string ();
printf ("%s\n", named_function_string
(var->name, function_cell (var), 1));
}
}
}
}
free (variable_list);
}
}
return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}

95
builtins/shift.def Normal file
View file

@ -0,0 +1,95 @@
This file is shift.def, from which is created shift.c.
It implements the builtin "shift" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES shift.c
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "../shell.h"
$BUILTIN shift
$FUNCTION shift_builtin
$SHORT_DOC shift [n]
The positional parameters from $N+1 ... are renamed to $1 ... If N is
not given, it is assumed to be 1.
$END
/* Shift the arguments ``left''. Shift DOLLAR_VARS down then take one
off of REST_OF_ARGS and place it into DOLLAR_VARS[9]. If LIST has
anything in it, it is a number which says where to start the
shifting. Return > 0 if `times' > $#, otherwise 0. */
int
shift_builtin (list)
WORD_LIST *list;
{
int times, number;
WORD_LIST *args;
times = get_numeric_arg (list);
if (!times)
return (EXECUTION_SUCCESS);
if (times < 0)
{
builtin_error ("shift count must be >= 0");
return (EXECUTION_FAILURE);
}
args = list_rest_of_args ();
number = list_length (args);
dispose_words (args);
if (times > number)
{
builtin_error ("shift count must be <= $#");
return (EXECUTION_FAILURE);
}
while (times-- > 0)
{
register int count;
if (dollar_vars[1])
free (dollar_vars[1]);
for (count = 1; count < 9; count++)
dollar_vars[count] = dollar_vars[count + 1];
if (rest_of_args)
{
WORD_LIST *temp = rest_of_args;
dollar_vars[9] = savestring (temp->word->word);
rest_of_args = rest_of_args->next;
temp->next = (WORD_LIST *)NULL;
dispose_words (temp);
}
else
dollar_vars[9] = (char *)NULL;
}
return (EXECUTION_SUCCESS);
}

186
builtins/source.def Normal file
View file

@ -0,0 +1,186 @@
This file is source.def, from which is created source.c.
It implements the builtins "." and "source" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES source.c
$BUILTIN source
$FUNCTION source_builtin
$SHORT_DOC source filename
Read and execute commands from FILENAME and return. The pathnames
in $PATH are used to find the directory containing FILENAME.
$END
$BUILTIN .
$DOCNAME dot
$FUNCTION source_builtin
$SHORT_DOC . filename
Read and execute commands from FILENAME and return. The pathnames
in $PATH are used to find the directory containing FILENAME.
$END
/* source.c - Implements the `.' and `source' builtins. */
#include <sys/types.h>
#include <sys/file.h>
#include <errno.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "../shell.h"
#include "../posixstat.h"
#include "../filecntl.h"
#include "../execute_cmd.h"
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
#if !defined (errno)
extern int errno;
#endif /* !errno */
/* Variables used here but defined in other files. */
extern int return_catch_flag, return_catch_value;
extern jmp_buf return_catch;
extern int posixly_correct;
extern int interactive, interactive_shell, last_command_exit_value;
/* How many `levels' of sourced files we have. */
int sourcelevel = 0;
/* If this . script is supplied arguments, we save the dollar vars and
replace them with the script arguments for the duration of the script's
execution. If the script does not change the dollar vars, we restore
what we saved. If the dollar vars are changed in the script, we leave
the new values alone and free the saved values. */
static void
maybe_pop_dollar_vars ()
{
if (dollar_vars_changed ())
{
dispose_saved_dollar_vars ();
set_dollar_vars_unchanged ();
}
else
pop_dollar_vars ();
}
/* Read and execute commands from the file passed as argument. Guess what.
This cannot be done in a subshell, since things like variable assignments
take place in there. So, I open the file, place it into a large string,
close the file, and then execute the string. */
source_builtin (list)
WORD_LIST *list;
{
int result, return_val;
/* Assume the best. */
result = EXECUTION_SUCCESS;
if (list)
{
char *string, *filename;
struct stat finfo;
int fd, tt;
filename = find_path_file (list->word->word);
if (!filename)
filename = savestring (list->word->word);
if (((fd = open (filename, O_RDONLY)) < 0) || (fstat (fd, &finfo) < 0))
goto file_error_exit;
string = (char *)xmalloc (1 + (int)finfo.st_size);
tt = read (fd, string, finfo.st_size);
string[finfo.st_size] = '\0';
/* Close the open file, preserving the state of errno. */
{ int temp = errno; close (fd); errno = temp; }
if (tt != finfo.st_size)
{
free (string);
file_error_exit:
file_error (filename);
free (filename);
/* POSIX shells exit if non-interactive and file error. */
if (posixly_correct && !interactive_shell)
{
last_command_exit_value = 1;
longjmp (top_level, EXITPROG);
}
return (EXECUTION_FAILURE);
}
if (tt > 80)
tt = 80;
if (check_binary_file ((unsigned char *)string, tt))
{
free (string);
builtin_error ("%s: cannot execute binary file", filename);
free (filename);
return (EX_BINARY_FILE);
}
begin_unwind_frame ("File Sourcing");
if (list->next)
{
push_dollar_vars ();
add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL);
remember_args (list->next, 1);
}
unwind_protect_int (return_catch_flag);
unwind_protect_jmp_buf (return_catch);
unwind_protect_int (interactive);
unwind_protect_int (sourcelevel);
add_unwind_protect ((Function *)xfree, filename);
interactive = 0;
sourcelevel++;
set_dollar_vars_unchanged ();
return_catch_flag++;
return_val = setjmp (return_catch);
if (return_val)
parse_and_execute_cleanup ();
else
result = parse_and_execute (string, filename, -1);
run_unwind_frame ("File Sourcing");
/* If RETURN_VAL is non-zero, then we return the value given
to return_builtin (), since that is how we got here. */
if (return_val)
result = return_catch_value;
}
else
{
builtin_error ("filename argument required");
result = EXECUTION_FAILURE;
}
return (result);
}

86
builtins/suspend.def Normal file
View file

@ -0,0 +1,86 @@
This file is suspend.def, from which is created suspend.c.
It implements the builtin "suspend" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES suspend.c
$BUILTIN suspend
$DEPENDS_ON JOB_CONTROL
$FUNCTION suspend_builtin
$SHORT_DOC suspend [-f]
Suspend the execution of this shell until it receives a SIGCONT
signal. The `-f' if specified says not to complain about this
being a login shell if it is; just suspend anyway.
$END
#include <sys/types.h>
#include <signal.h>
#include "../shell.h"
#include "../jobs.h"
#if defined (JOB_CONTROL)
extern int job_control;
static SigHandler *old_cont, *old_tstp;
/* Continue handler. */
sighandler
suspend_continue (sig)
int sig;
{
set_signal_handler (SIGCONT, old_cont);
set_signal_handler (SIGTSTP, old_tstp);
#if !defined (VOID_SIGHANDLER)
return (0);
#endif /* !VOID_SIGHANDLER */
}
/* Suspending the shell. If -f is the arg, then do the suspend
no matter what. Otherwise, complain if a login shell. */
int
suspend_builtin (list)
WORD_LIST *list;
{
if (!job_control)
{
builtin_error ("Cannot suspend a shell without job control");
return (EXECUTION_FAILURE);
}
if (list)
if (strcmp (list->word->word, "-f") == 0)
goto do_suspend;
no_args (list);
if (login_shell)
{
builtin_error ("Can't suspend a login shell");
return (EXECUTION_FAILURE);
}
do_suspend:
old_cont = (SigHandler *)set_signal_handler (SIGCONT, suspend_continue);
old_tstp = (SigHandler *)set_signal_handler (SIGTSTP, SIG_DFL);
killpg (shell_pgrp, SIGTSTP);
return (EXECUTION_SUCCESS);
}
#endif /* JOB_CONTROL */

144
builtins/test.def Normal file
View file

@ -0,0 +1,144 @@
This file is test.def, from which is created test.c.
It implements the builtin "test" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES test.c
$BUILTIN test
$FUNCTION test_builtin
$SHORT_DOC test [expr]
Exits with a status of 0 (trueness) or 1 (falseness) depending on
the evaluation of EXPR. Expressions may be unary or binary. Unary
expressions are often used to examine the status of a file. There
are string operators as well, and numeric comparison operators.
File operators:
-b FILE True if file is block special.
-c FILE True if file is character special.
-d FILE True if file is a directory.
-e FILE True if file exists.
-f FILE True if file exists and is a regular file.
-g FILE True if file is set-group-id.
-h FILE True if file is a symbolic link. Use "-L".
-L FILE True if file is a symbolic link.
-k FILE True if file has its "sticky" bit set.
-p FILE True if file is a named pipe.
-r FILE True if file is readable by you.
-s FILE True if file is not empty.
-S FILE True if file is a socket.
-t FD True if FD is opened on a terminal.
-u FILE True if the file is set-user-id.
-w FILE True if the file is writable by you.
-x FILE True if the file is executable by you.
-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.
FILE1 -ef FILE2 True if file1 is a hard link to file2.
String operators:
-z STRING True if string is empty.
-n STRING
or STRING True if string is not empty.
STRING1 = STRING2
True if the strings are equal.
STRING1 != STRING2
True if the strings are not equal.
Other operators:
! EXPR True if expr is false.
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne,
-lt, -le, -gt, or -ge.
Arithmetic binary operators return true if ARG1 is equal, not-equal,
less-than, less-than-or-equal, greater-than, or greater-than-or-equal
than ARG2.
$END
$BUILTIN [
$DOCNAME test_bracket
$FUNCTION test_builtin
$SHORT_DOC [ arg... ]
This is a synonym for the "test" shell builtin, excepting that the
last argument must be literally `]', to match the `[' which invoked
the test.
$END
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "../shell.h"
extern char *this_command_name;
/* TEST/[ builtin. */
int
test_builtin (list)
WORD_LIST *list;
{
char **argv;
int argc, result;
WORD_LIST *t = list;
/* We let Matthew Bradburn and Kevin Braunsdorf's code do the
actual test command. So turn the list of args into an array
of strings, since that is what his code wants. */
if (!list)
{
if (this_command_name[0] == '[' && !this_command_name[1])
builtin_error ("missing `]'");
return (EXECUTION_FAILURE);
}
/* Get the length of the argument list. */
for (argc = 0; t; t = t->next, argc++);
/* Account for argv[0] being a command name. This makes our life easier. */
argc++;
argv = (char **)xmalloc ((1 + argc) * sizeof (char *));
argv[argc] = (char *)NULL;
/* this_command_name is the name of the command that invoked this
function. So you can't call test_builtin () directly from
within this code, there are too many things to worry about. */
argv[0] = savestring (this_command_name);
for (t = list, argc = 1; t; t = t->next, argc++)
argv[argc] = savestring (t->word->word);
result = test_command (argc, argv);
free_array (argv);
return (result);
}

89
builtins/times.def Normal file
View file

@ -0,0 +1,89 @@
This file is times.def, from which is created times.c.
It implements the builtin "times" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES times.c
$BUILTIN times
$FUNCTION times_builtin
$SHORT_DOC times
Print the accumulated user and system times for processes run from
the shell.
$END
#include "../shell.h"
#include <sys/types.h>
#if defined (hpux) || defined (USGr4) || defined (XD88) || defined (USGr3)
# undef HAVE_RESOURCE
#endif /* hpux || USGr4 || XD88 || USGr3 */
#if defined (_POSIX_VERSION) || !defined (HAVE_RESOURCE)
# include <sys/times.h>
#else /* !_POSIX_VERSION && HAVE_RESOURCE */
# include <sys/time.h>
# include <sys/resource.h>
#endif /* !_POSIX_VERSION && HAVE_RESOURCE */
/* Print the totals for system and user time used. The
information comes from variables in jobs.c used to keep
track of this stuff. */
times_builtin (list)
WORD_LIST *list;
{
#if !defined (_POSIX_VERSION) && defined (HAVE_RESOURCE) && defined (RUSAGE_SELF)
struct rusage self, kids;
getrusage (RUSAGE_SELF, &self);
getrusage (RUSAGE_CHILDREN, &kids); /* terminated child processes */
print_timeval (&self.ru_utime);
putchar (' ');
print_timeval (&self.ru_stime);
putchar ('\n');
print_timeval (&kids.ru_utime);
putchar (' ');
print_timeval (&kids.ru_stime);
putchar ('\n');
#else /* _POSIX_VERSION || !HAVE_RESOURCE || !RUSAGE_SELF */
# if !defined (BrainDeath)
struct tms t;
times (&t);
/* As of System V.3, HP-UX 6.5, and other ATT-like systems, this stuff is
returned in terms of clock ticks (HZ from sys/param.h). C'mon, guys.
This kind of stupid clock-dependent stuff is exactly the reason 4.2BSD
introduced the `timeval' struct. */
print_time_in_hz (t.tms_utime);
putchar (' ');
print_time_in_hz (t.tms_stime);
putchar ('\n');
print_time_in_hz (t.tms_cutime);
putchar (' ');
print_time_in_hz (t.tms_cstime);
putchar ('\n');
# endif /* BrainDeath */
#endif /* _POSIX_VERSION || !HAVE_RESOURCE || !RUSAGE_SELF */
return (EXECUTION_SUCCESS);
}

204
builtins/trap.def Normal file
View file

@ -0,0 +1,204 @@
This file is trap.def, from which is created trap.c.
It implements the builtin "trap" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES trap.c
$BUILTIN trap
$FUNCTION trap_builtin
$SHORT_DOC trap [arg] [signal_spec]
The command ARG is to be read and executed when the shell receives
signal(s) SIGNAL_SPEC. If ARG is absent all specified signals are
reset to their original values. If ARG is the null string this
signal is ignored by the shell and by the commands it invokes. If
SIGNAL_SPEC is EXIT (0) the command ARG is executed on exit from
the shell. The trap command with no arguments prints the list of
commands associated with each signal number. SIGNAL_SPEC is either
a signal name in <signal.h>, or a signal number. The syntax `trap -l'
prints a list of signal names and their corresponding numbers.
Note that a signal can be sent to the shell with "kill -signal $$".
$END
#include <sys/types.h>
#include <signal.h>
#include "../shell.h"
#include "../trap.h"
#include "common.h"
/* The trap command:
trap <arg> <signal ...>
trap <signal ...>
trap -l
trap [--]
Set things up so that ARG is executed when SIGNAL(s) N is recieved.
If ARG is the empty string, then ignore the SIGNAL(s). If there is
no ARG, then set the trap for SIGNAL(s) to its original value. Just
plain "trap" means to print out the list of commands associated with
each signal number. Single arg of "-l" means list the signal names. */
/* Possible operations to perform on the list of signals.*/
#define SET 0 /* Set this signal to first_arg. */
#define REVERT 1 /* Revert to this signals original value. */
#define IGNORE 2 /* Ignore this signal. */
extern int interactive;
trap_builtin (list)
WORD_LIST *list;
{
register int i;
int list_signal_names = 0;
while (list)
{
if (ISOPTION (list->word->word, 'l'))
{
list_signal_names++;
list = list->next;
}
else if (ISOPTION (list->word->word, '-'))
{
list = list->next;
break;
}
else if ((*list->word->word == '-') && list->word->word[1])
{
bad_option (list->word->word);
builtin_error ("usage: trap [-l] [arg] [sigspec]");
return (EX_USAGE);
}
else
break;
}
if (list_signal_names)
{
int column = 0;
for (i = 0; i < NSIG; i++)
{
printf ("%2d) %s", i, signal_name (i));
if (++column < 4)
printf ("\t");
else
{
printf ("\n");
column = 0;
}
}
if (column != 0)
printf ("\n");
return (EXECUTION_SUCCESS);
}
if (list)
{
char *first_arg = list->word->word;
int operation = SET, any_failed = 0;
if (signal_object_p (first_arg))
operation = REVERT;
else
{
list = list->next;
if (*first_arg == '\0')
operation = IGNORE;
else if (first_arg[0] == '-' && !first_arg[1])
operation = REVERT;
}
while (list)
{
int sig;
sig = decode_signal (list->word->word);
if (sig == NO_SIG)
{
builtin_error ("%s: not a signal specification",
list->word->word);
any_failed++;
}
else
{
switch (operation)
{
case SET:
set_signal (sig, first_arg);
break;
case REVERT:
restore_default_signal (sig);
/* Signals that the shell treats specially need special
handling. */
switch (sig)
{
case SIGINT:
if (interactive)
set_signal_handler (SIGINT, sigint_sighandler);
else
set_signal_handler (SIGINT, termination_unwind_protect);
break;
case SIGQUIT:
/* Always ignore SIGQUIT. */
set_signal_handler (SIGQUIT, SIG_IGN);
break;
case SIGTERM:
#if defined (JOB_CONTROL)
case SIGTTIN:
case SIGTTOU:
case SIGTSTP:
#endif /* JOB_CONTROL */
if (interactive)
set_signal_handler (sig, SIG_IGN);
break;
}
break;
case IGNORE:
ignore_signal (sig);
break;
}
}
list = list->next;
}
return ((!any_failed) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
for (i = 0; i < NSIG; i++)
{
char *t, *p;
p = trap_list[i];
if (p == (char *)DEFAULT_SIG)
continue;
t = (p == (char *)IGNORE_SIG) ? (char *)NULL : single_quote (p);
printf ("trap -- %s %s\n", t ? t : "''", signal_name (i));
if (t)
free (t);
}
return (EXECUTION_SUCCESS);
}

325
builtins/type.def Normal file
View file

@ -0,0 +1,325 @@
This file is type.def, from which is created type.c.
It implements the builtin "type" in Bash.
Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES type.c
$BUILTIN type
$FUNCTION type_builtin
$SHORT_DOC 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, 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 -path flag is used, either returns the name of the disk file
that would be exec'ed, or nothing if -type wouldn't return `file'.
If the -all flag is used, displays 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.
$END
#include <stdio.h>
#include <sys/types.h>
#include "../posixstat.h"
#include "../shell.h"
#include "../execute_cmd.h"
#if defined (ALIAS)
#include "../alias.h"
#endif /* ALIAS */
#include "common.h"
extern STRING_INT_ALIST word_token_alist[];
/* For each word in LIST, find out what the shell is going to do with
it as a simple command. i.e., which file would this shell use to
execve, or if it is a builtin command, or an alias. Possible flag
arguments:
-type Returns the "type" of the object, one of
`alias', `keyword', `function', `builtin',
or `file'.
-path Returns the pathname of the file if -type is
a file.
-all Returns all occurrences of words, whether they
be a filename in the path, alias, function,
or builtin.
Order of evaluation:
alias
keyword
function
builtin
file
*/
type_builtin (list)
WORD_LIST *list;
{
int path_only, type_only, all, verbose;
int successful_finds;
path_only = type_only = all = 0;
successful_finds = 0;
if (!list)
return (EXECUTION_SUCCESS);
while (list && *(list->word->word) == '-')
{
char *flag = &(list->word->word[1]);
if (flag[0] == 't' && (!flag[1] || strcmp (flag + 1, "ype") == 0))
{
type_only = 1;
path_only = 0;
}
else if (flag[0] == 'p' && (!flag[1] || strcmp (flag + 1, "ath") == 0))
{
path_only = 1;
type_only = 0;
}
else if (flag[0] == 'a' && (!flag[1] || strcmp (flag + 1, "ll") == 0))
{
all = 1;
}
else
{
bad_option (flag);
builtin_error ("usage: type [-all | -path | -type ] name [name ...]");
return (EX_USAGE);
}
list = list->next;
}
if (type_only)
verbose = 1;
else if (!path_only)
verbose = 2;
else if (path_only)
verbose = 3;
else
verbose = 0;
while (list)
{
int found;
found = describe_command (list->word->word, verbose, all);
if (!found && !path_only && !type_only)
builtin_error ("%s: not found", list->word->word);
successful_finds += found;
list = list->next;
}
fflush (stdout);
if (successful_finds != 0)
return (EXECUTION_SUCCESS);
else
return (EXECUTION_FAILURE);
}
/*
* Describe COMMAND as required by the type builtin.
*
* If VERBOSE == 0, don't print anything
* If VERBOSE == 1, print short description as for `type -t'
* If VERBOSE == 2, print long description as for `type' and `command -V'
* If VERBOSE == 3, print path name only for disk files
* If VERBOSE == 4, print string used to invoke COMMAND, for `command -v'
*
* ALL says whether or not to look for all occurrences of COMMAND, or
* return after finding it once.
*/
describe_command (command, verbose, all)
char *command;
int verbose, all;
{
int found = 0, i, found_file = 0;
char *full_path = (char *)NULL;
SHELL_VAR *func;
#if defined (ALIAS)
/* Command is an alias? */
ASSOC *alias = find_alias (command);
if (alias)
{
if (verbose == 1)
printf ("alias\n");
else if (verbose == 2)
printf ("%s is aliased to `%s'\n", command, alias->value);
else if (verbose == 4)
{
char *x = single_quote (alias->value);
printf ("alias %s=%s\n", command, x);
free (x);
}
found = 1;
if (!all)
return (1);
}
#endif /* ALIAS */
/* Command is a shell reserved word? */
i = find_reserved_word (command);
if (i >= 0)
{
if (verbose == 1)
printf ("keyword\n");
else if (verbose == 2)
printf ("%s is a shell keyword\n", command);
else if (verbose == 4)
printf ("%s\n", command);
found = 1;
if (!all)
return (1);
}
/* Command is a function? */
func = find_function (command);
if (func)
{
if (verbose == 1)
printf ("function\n");
else if (verbose == 2)
{
#define PRETTY_PRINT_FUNC 1
char *result;
printf ("%s is a function\n", command);
/* We're blowing away THE_PRINTED_COMMAND here... */
result = named_function_string (command,
(COMMAND *) function_cell (func),
PRETTY_PRINT_FUNC);
printf ("%s\n", result);
#undef PRETTY_PRINT_FUNC
}
else if (verbose == 4)
printf ("%s\n", command);
found = 1;
if (!all)
return (1);
}
/* Command is a builtin? */
if (find_shell_builtin (command))
{
if (verbose == 1)
printf ("builtin\n");
else if (verbose == 2)
printf ("%s is a shell builtin\n", command);
else if (verbose == 4)
printf ("%s\n", command);
found = 1;
if (!all)
return (1);
}
/* Command is a disk file? */
/* If the command name given is already an absolute command, just
check to see if it is executable. */
if (absolute_program (command))
{
int f = file_status (command);
if (f & FS_EXECABLE)
{
if (verbose == 1)
printf ("file\n");
else if (verbose == 2)
printf ("%s is %s\n", command, command);
else if (verbose == 3 || verbose == 4)
printf ("%s\n", command);
/* There's no use looking in the hash table or in $PATH,
because they're not consulted when an absolute program
name is supplied. */
return (1);
}
}
/* If the user isn't doing "-all", then we might care about
whether the file is present in our hash table. */
if (!all)
{
if ((full_path = find_hashed_filename (command)) != (char *)NULL)
{
if (verbose == 1)
printf ("file\n");
else if (verbose == 2)
printf ("%s is hashed (%s)\n", command, full_path);
else if (verbose == 3 || verbose == 4)
printf ("%s\n", full_path);
return (1);
}
}
/* Now search through $PATH. */
while (1)
{
if (!all)
full_path = find_user_command (command);
else
full_path =
user_command_matches (command, FS_EXEC_ONLY, found_file);
/* XXX - should that be FS_EXEC_PREFERRED? */
if (!full_path)
break;
found_file++;
found = 1;
if (verbose == 1)
printf ("file\n");
else if (verbose == 2)
printf ("%s is %s\n", command, full_path);
else if (verbose == 3 || verbose == 4)
printf ("%s\n", full_path);
free (full_path);
full_path = (char *)NULL;
if (!all)
break;
}
return (found);
}

731
builtins/ulimit.def Normal file
View file

@ -0,0 +1,731 @@
This file is ulimit.def, from which is created ulimit.c.
It implements the builtin "ulimit" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES ulimit.c
$BUILTIN ulimit
$FUNCTION ulimit_builtin
$DEPENDS_ON !MINIX
$SHORT_DOC ulimit [-SHacdfmstpnuv [limit]]
Ulimit provides control over the resources available to processes
started by the shell, on systems that allow such control. If an
option is given, it is interpreted as follows:
-S use the `soft' resource limit
-H use the `hard' resource limit
-a all current limits are reported
-c the maximum size of core files created
-d the maximum size of a process's data segment
-m the maximum resident set size
-s the maximum stack size
-t the maximum amount of cpu time in seconds
-f the maximum size of files created by the shell
-p the pipe buffer size
-n the maximum number of open file descriptors
-u the maximum number of user processes
-v the size of virtual memory
If LIMIT is given, it is the new value of the specified resource.
Otherwise, the current value of the specified resource is printed.
If no option is given, then -f is assumed. Values are in 1k
increments, except for -t, which is in seconds, -p, which is in
increments of 512 bytes, and -u, which is an unscaled number of
processes.
$END
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <errno.h>
#include "../shell.h"
#include "pipesize.h"
#if !defined (errno)
extern int errno;
#endif
#if defined (HAVE_RESOURCE)
# include <sys/time.h>
# include <sys/resource.h>
#else
# include <sys/times.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (HAVE_LIMITS_H)
# include <limits.h>
#endif
/* Check for the most basic symbols. If they aren't present, this
system's <sys/resource.h> isn't very useful to us. */
#if !defined (RLIMIT_FSIZE) || defined (GETRLIMIT_MISSING)
# undef HAVE_RESOURCE
#endif
#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
static void print_long ();
/* **************************************************************** */
/* */
/* Ulimit builtin and Hacks. */
/* */
/* **************************************************************** */
/* Block size for ulimit operations. */
#define ULIMIT_BLOCK_SIZE ((long)1024)
#define u_FILE_SIZE 0x001
#define u_MAX_BREAK_VAL 0x002
#define u_PIPE_SIZE 0x004
#define u_CORE_FILE_SIZE 0x008
#define u_DATA_SEG_SIZE 0x010
#define u_PHYS_MEM_SIZE 0x020
#define u_CPU_TIME_LIMIT 0x040
#define u_STACK_SIZE 0x080
#define u_NUM_OPEN_FILES 0x100
#define u_MAX_VIRTUAL_MEM 0x200
#define u_MAX_USER_PROCS 0x400
#define u_ALL_LIMITS 0x7ff
#if !defined (RLIM_INFINITY)
# define RLIM_INFINITY 0x7fffffff
#endif
/* Some systems use RLIMIT_NOFILE, others use RLIMIT_OFILE */
#if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE)
# define RLIMIT_NOFILE RLIMIT_OFILE
#endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */
#define LIMIT_HARD 0x01
#define LIMIT_SOFT 0x02
static RLIMTYPE shell_ulimit ();
static RLIMTYPE pipesize ();
static RLIMTYPE open_files ();
#if defined (HAVE_RESOURCE)
static RLIMTYPE getmaxvm ();
#endif /* HAVE_RESOURCE */
static void print_specific_limits ();
static void print_all_limits ();
static char t[2];
/* Return 1 if the limit associated with CMD can be raised from CURRENT
to NEW. This is for USG systems without HAVE_RESOURCE, most of which
do not allow any user other than root to raise limits. There are,
however, exceptions. */
#if !defined (HAVE_RESOURCE)
static int
canraise (cmd, current, new)
int cmd;
RLIMTYPE current, new;
{
# if defined (HAVE_SETDTABLESIZE)
if (cmd == u_NUM_OPEN_FILES)
return (1);
# endif /* HAVE_SETDTABLSIZE */
return ((current > new) || (current_user.uid == 0));
}
#endif /* !HAVE_RESOURCE */
/* Report or set limits associated with certain per-process resources.
See the help documentation in builtins.c for a full description.
Rewritten by Chet Ramey 6/30/91. */
int
ulimit_builtin (list)
register WORD_LIST *list;
{
register char *s;
int c, setting, cmd, mode, verbose_print, opt_eof;
int all_limits, specific_limits;
long block_factor;
RLIMTYPE current_limit, real_limit, limit;
c = mode = verbose_print = opt_eof = 0;
limit = (RLIMTYPE)-1;
do
{
cmd = setting = all_limits = specific_limits = 0;
block_factor = ULIMIT_BLOCK_SIZE;
/* read_options: */
if (list && !opt_eof && *list->word->word == '-')
{
s = &(list->word->word[1]);
list = list->next;
while (*s && (c = *s++))
{
switch (c)
{
#define ADD_CMD(x) { if (cmd) specific_limits++; cmd |= (x); }
case '-': /* ulimit -- */
opt_eof++;
break;
case 'a':
all_limits++;
break;
case 'f':
ADD_CMD (u_FILE_SIZE);
break;
#if defined (HAVE_RESOURCE)
/* -S and -H are modifiers, not real options. */
case 'S':
mode |= LIMIT_SOFT;
break;
case 'H':
mode |= LIMIT_HARD;
break;
case 'c':
ADD_CMD (u_CORE_FILE_SIZE);
break;
case 'd':
ADD_CMD (u_DATA_SEG_SIZE);
break;
#if !defined (USGr4)
case 'm':
ADD_CMD (u_PHYS_MEM_SIZE);
break;
#endif /* USGr4 */
case 't':
ADD_CMD (u_CPU_TIME_LIMIT);
block_factor = 1; /* seconds */
break;
case 's':
ADD_CMD (u_STACK_SIZE);
break;
case 'v':
ADD_CMD (u_MAX_VIRTUAL_MEM);
block_factor = 1;
break;
case 'u':
ADD_CMD (u_MAX_USER_PROCS);
block_factor = 1;
break;
#endif /* HAVE_RESOURCE */
case 'p':
ADD_CMD (u_PIPE_SIZE);
block_factor = 512;
break;
case 'n':
ADD_CMD (u_NUM_OPEN_FILES);
block_factor = 1;
break;
default: /* error_case: */
t[0] = c;
t[1] = '\0';
bad_option (t);
#if !defined (HAVE_RESOURCE)
builtin_error("usage: ulimit [-afnp] [new limit]");
#else
builtin_error("usage: ulimit [-SHacmdstfnpuv] [new limit]");
#endif
return (EX_USAGE);
}
}
}
if (all_limits)
{
print_all_limits (mode);
return (EXECUTION_SUCCESS);
}
if (specific_limits)
{
print_specific_limits (cmd, mode);
if (list)
verbose_print++;
continue;
}
if (cmd == 0)
cmd = u_FILE_SIZE;
/* If an argument was supplied for the command, then we want to
set the limit. Note that `ulimit something' means a command
of -f with argument `something'. */
if (list)
{
if (opt_eof || (*list->word->word != '-'))
{
s = list->word->word;
list = list->next;
if (STREQ (s, "unlimited"))
limit = RLIM_INFINITY;
else if (all_digits (s))
limit = string_to_rlimtype (s);
else
{
builtin_error ("bad non-numeric arg `%s'", s);
return (EXECUTION_FAILURE);
}
setting++;
}
else if (!opt_eof)
verbose_print++;
}
if (limit == RLIM_INFINITY)
block_factor = 1;
real_limit = limit * block_factor;
/* If more than one option is given, list each in a verbose format,
the same that is used for -a. */
if (!setting && verbose_print)
{
print_specific_limits (cmd, mode);
continue;
}
current_limit = shell_ulimit (cmd, real_limit, 0, mode);
if (setting)
{
#if !defined (HAVE_RESOURCE)
/* Most USG systems do not most allow limits to be raised by any
user other than root. There are, however, exceptions. */
if (canraise (cmd, current_limit, real_limit) == 0)
{
builtin_error ("cannot raise limit: %s", strerror (EPERM));
return (EXECUTION_FAILURE);
}
#endif /* !HAVE_RESOURCE */
if (shell_ulimit (cmd, real_limit, 1, mode) == (RLIMTYPE)-1)
{
builtin_error ("cannot raise limit: %s", strerror (errno));
return (EXECUTION_FAILURE);
}
continue;
}
else
{
if (current_limit < 0)
builtin_error ("cannot get limit: %s", strerror (errno));
else if (current_limit != RLIM_INFINITY)
print_rlimtype ((current_limit / block_factor), 1);
else
printf ("unlimited\n");
}
}
while (list);
return (EXECUTION_SUCCESS);
}
/* The ulimit that we call from within Bash.
WHICH says which limit to twiddle; SETTING is non-zero if NEWLIM
contains the desired new limit. Otherwise, the existing limit is
returned. If mode & LIMIT_HARD, the hard limit is used; if
mode & LIMIT_SOFT, the soft limit. Both may be set by specifying
-H and -S; if both are specified, or if neither is specified, the
soft limit will be returned.
Systems without BSD resource limits can specify only u_FILE_SIZE.
This includes most USG systems.
Chet Ramey supplied the BSD resource limit code. */
static RLIMTYPE
shell_ulimit (which, newlim, setting, mode)
int which, setting, mode;
RLIMTYPE newlim;
{
#if defined (HAVE_RESOURCE)
struct rlimit limit;
int cmd;
if (mode == 0)
mode |= LIMIT_SOFT;
#endif
switch (which)
{
#if !defined (HAVE_RESOURCE)
case u_FILE_SIZE:
if (!setting)
{
/* ulimit () returns a number that is in 512 byte blocks, thus we
must multiply it by 512 to get back to bytes. This is false
only under HP/UX 6.x. */
RLIMTYPE result;
result = ulimit (1, 0L);
# if defined (hpux) && !defined (_POSIX_VERSION)
return (result);
# else
return (result * 512);
# endif /* hpux 6.x */
}
else
return (ulimit (2, newlim / 512L));
break;
#else /* defined (HAVE_RESOURCE) */
case u_FILE_SIZE:
cmd = RLIMIT_FSIZE;
goto do_ulimit;
case u_CORE_FILE_SIZE:
cmd = RLIMIT_CORE;
goto do_ulimit;
case u_DATA_SEG_SIZE:
cmd = RLIMIT_DATA;
goto do_ulimit;
#if !defined (USGr4)
case u_PHYS_MEM_SIZE:
# if defined (RLIMIT_RSS)
cmd = RLIMIT_RSS;
# else /* !RLIMIT_RSS */
errno = EINVAL;
return ((RLIMTYPE)-1);
# endif /* !RLIMIT_RSS */
goto do_ulimit;
#endif /* USGr4 */
case u_CPU_TIME_LIMIT:
#if defined (RLIMIT_CPU)
cmd = RLIMIT_CPU;
goto do_ulimit;
#else
errno = EINVAL;
return ((RLIMTYPE)-1);
# endif /* !RLIMIT_CPU */
case u_STACK_SIZE:
cmd = RLIMIT_STACK;
do_ulimit:
if (getrlimit (cmd, &limit) != 0)
return ((RLIMTYPE)-1);
if (!setting)
{
if (mode & LIMIT_SOFT)
return (limit.rlim_cur);
else
return (limit.rlim_max);
}
else
{
if (mode & LIMIT_SOFT)
{
/* Non-root users are only allowed to raise a limit up to the
hard limit, not to infinity. */
if (current_user.euid != 0 && newlim == RLIM_INFINITY)
limit.rlim_cur = limit.rlim_max;
else
limit.rlim_cur = newlim;
}
if (mode & LIMIT_HARD)
limit.rlim_max = newlim;
return (setrlimit (cmd, &limit));
}
break;
#endif /* HAVE_RESOURCE */
/* You can't get or set the pipe size with getrlimit, so we have to
cheat. */
case u_PIPE_SIZE:
if (setting)
{
errno = EINVAL;
return ((RLIMTYPE)-1);
}
return (pipesize ());
case u_NUM_OPEN_FILES:
if (setting)
{
#if defined (HAVE_RESOURCE) && defined (RLIMIT_NOFILE)
cmd = RLIMIT_NOFILE;
goto do_ulimit;
#else
# if defined (HAVE_SETDTABLESIZE)
return (setdtablesize (newlim));
# else
errno = EINVAL;
return ((RLIMTYPE)-1);
# endif /* HAVE_SETDTABLESIZE */
#endif /* !HAVE_RESOURCE || !RLIMIT_NOFILE */
}
else
return (open_files (mode));
case u_MAX_VIRTUAL_MEM:
if (setting)
{
errno = EINVAL;
return ((RLIMTYPE)-1);
}
else
{
#if defined (HAVE_RESOURCE)
return (getmaxvm (mode));
#else /* !HAVE_RESOURCE */
errno = EINVAL;
return ((RLIMTYPE)-1);
#endif /* !HAVE_RESOURCE */
}
case u_MAX_USER_PROCS:
#if defined (HAVE_RESOURCE) && defined (RLIMIT_NPROC)
cmd = RLIMIT_NPROC;
goto do_ulimit;
#else /* !HAVE_RESOURCE || !RLIMIT_NPROC */
errno = EINVAL;
return ((RLIMTYPE)-1);
#endif /* !HAVE_RESOURCE || !RLIMIT_NPROC */
default:
errno = EINVAL;
return ((RLIMTYPE)-1);
}
}
#if defined (HAVE_RESOURCE)
static RLIMTYPE
getmaxvm (mode)
int mode;
{
struct rlimit rl;
#if defined (RLIMIT_VMEM)
if (getrlimit (RLIMIT_VMEM, &rl) < 0)
return ((RLIMTYPE)-1);
else
return (((mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max) / 1024L);
#else /* !RLIMIT_VMEM */
RLIMTYPE maxdata, maxstack;
if (getrlimit (RLIMIT_DATA, &rl) < 0)
return ((RLIMTYPE)-1);
else
maxdata = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
if (getrlimit (RLIMIT_STACK, &rl) < 0)
return ((RLIMTYPE)-1);
else
maxstack = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
/* Protect against overflow. */
return ((maxdata / 1024L) + (maxstack / 1024L));
#endif /* !RLIMIT_VMEM */
}
#endif /* HAVE_RESOURCE */
static RLIMTYPE
open_files (mode)
int mode;
{
#if !defined (RLIMIT_NOFILE)
return ((RLIMTYPE)getdtablesize ());
#else
struct rlimit rl;
getrlimit (RLIMIT_NOFILE, &rl);
if (mode & LIMIT_SOFT)
return (rl.rlim_cur);
else
return (rl.rlim_max);
#endif
}
static RLIMTYPE
pipesize ()
{
#if defined (PIPE_BUF)
/* This is defined on Posix systems. */
return ((RLIMTYPE) PIPE_BUF);
#else
# if defined (PIPESIZE)
/* This is defined by running a program from the Makefile. */
return ((RLIMTYPE) PIPESIZE);
# else
errno = EINVAL;
return ((RLIMTYPE)-1);
# endif /* PIPESIZE */
#endif /* PIPE_BUF */
}
/* ulimit(2) returns information about file size limits in terms of 512-byte
blocks. This is the factor by which to divide to turn it into information
in terms of 1024-byte blocks. Except for hpux 6.x, which returns it in
terms of bytes. */
#if !defined (hpux) || defined (_POSIX_VERSION)
# define ULIMIT_DIVISOR 2
#else
# define ULIMIT_DIVISOR 1024
#endif
#if defined (HAVE_RESOURCE)
typedef struct {
int option_cmd; /* The ulimit command for this limit. */
int parameter; /* Parameter to pass to getrlimit (). */
int block_factor; /* Blocking factor for specific limit. */
char *description; /* Descriptive string to output. */
} BSD_RESOURCE_LIMITS;
static BSD_RESOURCE_LIMITS limits[] = {
{ u_CORE_FILE_SIZE, RLIMIT_CORE, 1024, "core file size (blocks)" },
{ u_DATA_SEG_SIZE, RLIMIT_DATA, 1024, "data seg size (kbytes)" },
{ u_FILE_SIZE, RLIMIT_FSIZE, 1024, "file size (blocks)" },
#if !defined (USGr4) && defined (RLIMIT_RSS)
{ u_PHYS_MEM_SIZE, RLIMIT_RSS, 1024, "max memory size (kbytes)" },
#endif /* USGr4 && RLIMIT_RSS */
{ u_STACK_SIZE, RLIMIT_STACK, 1024, "stack size (kbytes)" },
#if defined (RLIMIT_CPU)
{ u_CPU_TIME_LIMIT, RLIMIT_CPU, 1, "cpu time (seconds)" },
#endif /* RLIMIT_CPU */
#if defined (RLIMIT_NPROC)
{ u_MAX_USER_PROCS, RLIMIT_NPROC, 1, "max user processes" },
#endif /* RLIMIT_NPROC */
{ 0, 0, 0, (char *)NULL }
};
static void
print_bsd_limit (i, mode)
int i, mode;
{
struct rlimit rl;
RLIMTYPE limit;
getrlimit (limits[i].parameter, &rl);
if (mode & LIMIT_HARD)
limit = rl.rlim_max;
else
limit = rl.rlim_cur;
printf ("%-25s", limits[i].description);
if (limit == RLIM_INFINITY)
printf ("unlimited\n");
else
print_rlimtype ((limit / limits[i].block_factor), 1);
}
static void
print_specific_bsd_limits (cmd, mode)
int cmd, mode;
{
register int i;
for (i = 0; limits[i].option_cmd; i++)
if (cmd & limits[i].option_cmd)
print_bsd_limit (i, mode);
}
#endif /* HAVE_RESOURCE */
/* Print the limits corresponding to a specific set of resources. This is
called when an option string contains more than one character (e.g. -at),
because limits may not be specified with that kind of argument. */
static void
print_specific_limits (cmd, mode)
int cmd, mode;
{
if (mode == 0)
mode = LIMIT_SOFT;
#if defined (HAVE_RESOURCE)
print_specific_bsd_limits (cmd, mode);
#else /* !HAVE_RESOURCE */
if (cmd & u_FILE_SIZE)
{
printf ("%-25s", "file size (blocks)");
print_rlimtype ((ulimit (1, 0L) / ULIMIT_DIVISOR), 1);
}
#endif /* !HAVE_RESOURCE */
if (cmd & u_PIPE_SIZE)
{
printf ("%-25s", "pipe size (512 bytes)");
print_rlimtype ((pipesize () / 512), 1);
}
if (cmd & u_NUM_OPEN_FILES)
{
printf ("%-25s", "open files");
print_rlimtype (open_files (mode), 1);
}
#if defined (HAVE_RESOURCE)
if (cmd & u_MAX_VIRTUAL_MEM)
{
printf ("%-25s", "virtual memory (kbytes)");
print_rlimtype (getmaxvm (mode), 1);
}
#endif /* HAVE_RESOURCE */
}
static void
print_all_limits (mode)
int mode;
{
if (mode == 0)
mode |= LIMIT_SOFT;
print_specific_limits (u_ALL_LIMITS, mode);
}

288
builtins/umask.def Normal file
View file

@ -0,0 +1,288 @@
This file is umask.def, from which is created umask.c.
It implements the builtin "umask" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES umask.c
$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
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include "../shell.h"
#include "../posixstat.h"
#include "common.h"
/* **************************************************************** */
/* */
/* UMASK Builtin and Helpers */
/* */
/* **************************************************************** */
static void print_symbolic_umask ();
static int symbolic_umask ();
/* Set or display the mask used by the system when creating files. Flag
of -S means display the umask in a symbolic mode. */
umask_builtin (list)
WORD_LIST *list;
{
int print_symbolically = 0;
while (list)
{
if (ISOPTION (list->word->word, 'S'))
{
list = list->next;
print_symbolically++;
continue;
}
else if (ISOPTION (list->word->word, '-'))
{
list = list->next;
break;
}
else if (*(list->word->word) == '-')
{
bad_option (list->word->word);
builtin_error ("usage: umask [-S] [mode]");
return (EX_USAGE);
}
else
break;
}
if (list)
{
int new_umask;
if (digit (*list->word->word))
{
new_umask = read_octal (list->word->word);
/* Note that other shells just let you set the umask to zero
by specifying a number out of range. This is a problem
with those shells. We don't change the umask if the input
is lousy. */
if (new_umask == -1)
{
builtin_error ("`%s' is not an octal number from 000 to 777",
list->word->word);
return (EXECUTION_FAILURE);
}
}
else
{
new_umask = symbolic_umask (list);
if (new_umask == -1)
return (EXECUTION_FAILURE);
}
umask (new_umask);
if (print_symbolically)
print_symbolic_umask (new_umask);
}
else /* Display the UMASK for this user. */
{
int old_umask;
old_umask = umask (022);
umask (old_umask);
if (print_symbolically)
print_symbolic_umask (old_umask);
else
printf ("%03o\n", old_umask);
}
fflush (stdout);
return (EXECUTION_SUCCESS);
}
/* Print the umask in a symbolic form. In the output, a letter is
printed if the corresponding bit is clear in the umask. */
static void
print_symbolic_umask (um)
int um;
{
char ubits[4], gbits[4], obits[4]; /* u=rwx,g=rwx,o=rwx */
int i;
i = 0;
if ((um & S_IRUSR) == 0)
ubits[i++] = 'r';
if ((um & S_IWUSR) == 0)
ubits[i++] = 'w';
if ((um & S_IXUSR) == 0)
ubits[i++] = 'x';
ubits[i] = '\0';
i = 0;
if ((um & S_IRGRP) == 0)
gbits[i++] = 'r';
if ((um & S_IWGRP) == 0)
gbits[i++] = 'w';
if ((um & S_IXGRP) == 0)
gbits[i++] = 'x';
gbits[i] = '\0';
i = 0;
if ((um & S_IROTH) == 0)
obits[i++] = 'r';
if ((um & S_IWOTH) == 0)
obits[i++] = 'w';
if ((um & S_IXOTH) == 0)
obits[i++] = 'x';
obits[i] = '\0';
printf ("u=%s,g=%s,o=%s\n", ubits, gbits, obits);
}
/* Set the umask from a symbolic mode string similar to that accepted
by chmod. If the -S argument is given, then print the umask in a
symbolic form. */
static int
symbolic_umask (list)
WORD_LIST *list;
{
int um, umc, c;
int who, op, perm, mask;
char *s;
/* Get the initial umask. Don't change it yet. */
um = umask (022);
umask (um);
/* All work below is done with the complement of the umask -- its
more intuitive and easier to deal with. It is complemented
again before being returned. */
umc = ~um;
s = list->word->word;
for (;;)
{
who = op = perm = mask = 0;
/* Parse the `who' portion of the symbolic mode clause. */
while (member (*s, "agou"))
{
switch (c = *s++)
{
case 'u':
who |= S_IRWXU;
continue;
case 'g':
who |= S_IRWXG;
continue;
case 'o':
who |= S_IRWXO;
continue;
case 'a':
who |= S_IRWXU | S_IRWXG | S_IRWXO;
continue;
default:
break;
}
}
/* The operation is now sitting in *s. */
op = *s++;
switch (op)
{
case '+':
case '-':
case '=':
break;
default:
builtin_error ("bad symbolic mode operator: %c", op);
return (-1);
}
/* Parse out the `perm' section of the symbolic mode clause. */
while (member (*s, "rwx"))
{
c = *s++;
switch (c)
{
case 'r':
perm |= S_IRUGO;
break;
case 'w':
perm |= S_IWUGO;
break;
case 'x':
perm |= S_IXUGO;
break;
}
}
/* Now perform the operation or return an error for a
bad permission string. */
if (!*s || *s == ',')
{
if (who)
perm &= who;
switch (op)
{
case '+':
umc |= perm;
break;
case '-':
umc &= ~perm;
break;
case '=':
umc &= ~who;
umc |= perm;
break;
default:
builtin_error ("bad operation character: %c", op);
return (-1);
}
if (!*s)
{
um = ~umc & 0777;
break;
}
else
s++; /* skip past ',' */
}
else
{
builtin_error ("bad character in symbolic mode: %c", *s);
return (-1);
}
}
return (um);
}

132
builtins/wait.def Normal file
View file

@ -0,0 +1,132 @@
This file is wait.def, from which is created wait.c.
It implements the builtin "wait" in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$BUILTIN wait
$FUNCTION wait_builtin
$DEPENDS_ON JOB_CONTROL
$PRODUCES wait.c
$SHORT_DOC wait [n]
Wait for the specified process and report its termination status. If
N is not given, all currently active child processes are waited for,
and the return code is zero. N may be a process ID or a job
specification; if a job spec is given, all processes in the job's
pipeline are waited for.
$END
$BUILTIN wait
$FUNCTION wait_builtin
$DEPENDS_ON !JOB_CONTROL
$SHORT_DOC wait [n]
Wait for the specified process and report its termination status. If
N is not given, all currently active child processes are waited for,
and the return code is zero. N is a process ID; if it is not given,
all child processes of the shell are waited for.
$END
#include <sys/types.h>
#include <signal.h>
#include "../shell.h"
#include "../jobs.h"
extern int interrupt_immediately;
/* Wait for the pid in LIST to stop or die. If no arguments are given, then
wait for all of the active background processes of the shell and return
0. If a list of pids or job specs are given, return the exit status of
the last one waited for. */
wait_builtin (list)
WORD_LIST *list;
{
int status = EXECUTION_SUCCESS;
begin_unwind_frame ("wait_builtin");
unwind_protect_int (interrupt_immediately);
interrupt_immediately++;
/* We support jobs or pids.
wait <pid-or-job> [pid-or-job ...] */
/* But wait without any arguments means to wait for all of the shell's
currently active background processes. */
if (!list)
{
wait_for_background_pids ();
status = EXECUTION_SUCCESS;
goto return_status;
}
while (list)
{
pid_t pid;
char *w;
w = list->word->word;
if (digit (*w))
{
if (all_digits (w + 1))
{
pid = (pid_t)atoi (w);
status = wait_for_single_pid (pid);
}
else
{
builtin_error ("`%s' is not a pid or legal job spec", w);
status = EXECUTION_FAILURE;
goto return_status;
}
}
#if defined (JOB_CONTROL)
else if (job_control && *w)
/* Must be a job spec. Check it out. */
{
int job;
sigset_t set, oset;
BLOCK_CHILD (set, oset);
job = get_job_spec (list);
if (job < 0 || job >= job_slots || !jobs[job])
{
if (job != DUP_JOB)
builtin_error ("No such job %s", list->word->word);
UNBLOCK_CHILD (oset);
status = 127; /* As per Posix.2, section 4.70.2 */
list = list->next;
continue;
}
/* Job spec used. Wait for the last pid in the pipeline. */
UNBLOCK_CHILD (oset);
status = wait_for_job (job);
}
#endif /* JOB_CONTROL */
else
{
builtin_error ("`%s' is not a pid or legal job spec", w);
status = EXECUTION_FAILURE;
}
list = list->next;
}
return_status:
run_unwind_frame ("wait_builtin");
return (status);
}

215
command.h Normal file
View file

@ -0,0 +1,215 @@
/* command.h -- The structures used internally to represent commands, and
the extern declarations of the functions used to create them. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (_COMMAND_H)
#define _COMMAND_H
#include "stdc.h"
/* Instructions describing what kind of thing to do for a redirection. */
enum r_instruction {
r_output_direction, r_input_direction, r_inputa_direction,
r_appending_to, r_reading_until, r_duplicating_input,
r_duplicating_output, r_deblank_reading_until, r_close_this,
r_err_and_out, r_input_output, r_output_force,
r_duplicating_input_word, r_duplicating_output_word
};
/* 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 };
/* A structure which represents a word. */
typedef struct word_desc {
char *word; /* Zero terminated string. */
int dollar_present; /* Non-zero means dollar sign present. */
int quoted; /* Non-zero means single, double, or back quote
or backslash is present. */
int assignment; /* Non-zero means that this word contains an
assignment. */
} WORD_DESC;
/* A linked list of words. */
typedef struct word_list {
struct word_list *next;
WORD_DESC *word;
} WORD_LIST;
/* **************************************************************** */
/* */
/* Shell Command Structs */
/* */
/* **************************************************************** */
/* What a redirection descriptor looks like. If FLAGS is IS_DESCRIPTOR,
then we use REDIRECTEE.DEST, else we use the file specified. */
typedef union {
long dest; /* Place to redirect REDIRECTOR to, or ... */
WORD_DESC *filename; /* filename to redirect to. */
} REDIRECTEE;
typedef struct redirect {
struct redirect *next; /* Next element, or NULL. */
int redirector; /* Descriptor to be redirected. */
int flags; /* Flag value for `open'. */
enum r_instruction instruction; /* What to do with the information. */
REDIRECTEE redirectee; /* File descriptor or filename */
char *here_doc_eof; /* The word that appeared in <<foo. */
} REDIRECT;
/* An element used in parsing. A single word or a single redirection.
This is an ephemeral construct. */
typedef struct element {
WORD_DESC *word;
REDIRECT *redirect;
} ELEMENT;
/* Possible values for command->flags. */
#define CMD_WANT_SUBSHELL 0x01 /* User wants a subshell: ( command ) */
#define CMD_FORCE_SUBSHELL 0x02 /* Shell needs to force a subshell. */
#define CMD_INVERT_RETURN 0x04 /* Invert the exit value. */
#define CMD_IGNORE_RETURN 0x08 /* Ignore the exit value. For set -e. */
#define CMD_NO_FUNCTIONS 0x10 /* Ignore functions during command lookup. */
#define CMD_INHIBIT_EXPANSION 0x20 /* Do not expand the command words. */
#define CMD_NO_FORK 0x40 /* Don't fork; just call execve */
/* What a command looks like. */
typedef struct command {
enum command_type type; /* FOR CASE WHILE IF CONNECTION or SIMPLE. */
int flags; /* Flags controlling execution environment. */
int line; /* line number the command starts on */
REDIRECT *redirects; /* Special redirects for FOR CASE, etc. */
union {
struct for_com *For;
struct case_com *Case;
struct while_com *While;
struct if_com *If;
struct connection *Connection;
struct simple_com *Simple;
struct function_def *Function_def;
struct group_com *Group;
#if defined (SELECT_COMMAND)
struct select_com *Select;
#endif
} value;
} COMMAND;
/* Structure used to represent the CONNECTION type. */
typedef struct connection {
int ignore; /* Unused; simplifies make_command (). */
COMMAND *first; /* Pointer to the first command. */
COMMAND *second; /* Pointer to the second command. */
int connector; /* What separates this command from others. */
} CONNECTION;
/* Structures used to represent the CASE command. */
/* Pattern/action structure for CASE_COM. */
typedef struct pattern_list {
struct pattern_list *next; /* Clause to try in case this one failed. */
WORD_LIST *patterns; /* Linked list of patterns to test. */
COMMAND *action; /* Thing to execute if a pattern matches. */
} PATTERN_LIST;
/* The CASE command. */
typedef struct case_com {
int flags; /* See description of CMD flags. */
WORD_DESC *word; /* The thing to test. */
PATTERN_LIST *clauses; /* The clauses to test against, or NULL. */
} CASE_COM;
/* FOR command. */
typedef struct for_com {
int flags; /* See description of CMD flags. */
WORD_DESC *name; /* The variable name to get mapped over. */
WORD_LIST *map_list; /* The things to map over. This is never NULL. */
COMMAND *action; /* The action to execute.
During execution, NAME is bound to successive
members of MAP_LIST. */
} FOR_COM;
#if defined (SELECT_COMMAND)
/* KSH SELECT command. */
typedef struct select_com {
int flags; /* See description of CMD flags. */
WORD_DESC *name; /* The variable name to get mapped over. */
WORD_LIST *map_list; /* The things to map over. This is never NULL. */
COMMAND *action; /* The action to execute.
During execution, NAME is bound to the member of
MAP_LIST chosen by the user. */
} SELECT_COM;
#endif /* SELECT_COMMAND */
/* IF command. */
typedef struct if_com {
int flags; /* See description of CMD flags. */
COMMAND *test; /* Thing to test. */
COMMAND *true_case; /* What to do if the test returned non-zero. */
COMMAND *false_case; /* What to do if the test returned zero. */
} IF_COM;
/* WHILE command. */
typedef struct while_com {
int flags; /* See description of CMD flags. */
COMMAND *test; /* Thing to test. */
COMMAND *action; /* Thing to do while test is non-zero. */
} WHILE_COM;
/* The "simple" command. Just a collection of words and redirects. */
typedef struct simple_com {
int flags; /* See description of CMD flags. */
WORD_LIST *words; /* The program name, the arguments,
variable assignments, etc. */
REDIRECT *redirects; /* Redirections to perform. */
int line; /* line number the command starts on */
} SIMPLE_COM;
/* The "function_def" command. This isn't really a command, but it is
represented as such for now. If the function def appears within
`(' `)' the parser tries to set the SUBSHELL bit of the command. That
means that FUNCTION_DEF has to be run through the executor. Maybe this
command should be defined in a subshell. Who knows or cares. */
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. */
} FUNCTION_DEF;
/* A command that is `grouped' allows pipes to take effect over
the entire command structure. */
typedef struct group_com {
int ignore; /* See description of CMD flags. */
COMMAND *command;
} GROUP_COM;
extern COMMAND *global_command;
/* Forward declarations of functions declared in copy_cmd.c. */
extern WORD_DESC *copy_word __P((WORD_DESC *));
extern WORD_LIST *copy_word_list __P((WORD_LIST *));
extern REDIRECT *copy_redirect __P((REDIRECT *));
extern REDIRECT *copy_redirects __P((REDIRECT *));
extern COMMAND *copy_command __P((COMMAND *));
#endif /* _COMMAND_H */

186
config.h Normal file
View file

@ -0,0 +1,186 @@
/* config.h -- Configuration file for bash. */
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Bash is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with Bash; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (_CONFIG_H_)
#define _CONFIG_H_
#if !defined (BUILDING_MAKEFILE)
#include "memalloc.h"
#endif
#if defined (HAVE_UNISTD_H) && !defined (BUILDING_MAKEFILE)
# ifdef CRAY
# define word __word
# endif
#include <unistd.h>
# ifdef CRAY
# undef word
# endif
#endif
/* Define JOB_CONTROL if your operating system supports
BSD-like job control. */
#define JOB_CONTROL
/* Note that vanilla System V machines don't support BSD job control,
although some do support Posix job control. */
#if defined (USG) || defined (MINIX) || defined (Minix)
# if !defined (_POSIX_JOB_CONTROL)
# undef JOB_CONTROL
# endif /* !_POSIX_JOB_CONTROL */
#endif /* USG || Minix || MINIX */
/* Define ALIAS if you want the alias features. */
#define ALIAS
/* Define PUSHD_AND_POPD if you want those commands to be compiled in.
(Also the `dirs' commands.) */
#define PUSHD_AND_POPD
/* Define BRACE_EXPANSION if you want curly brace expansion a la Csh:
foo{a,b} -> fooa foob. Even if this is compiled in (the default) you
can turn it off at shell startup with `-nobraceexpansion', or during
shell execution with `set +o braceexpand'. */
#define BRACE_EXPANSION
/* Define READLINE to get the nifty/glitzy editing features.
This is on by default. You can turn it off interactively
with the -nolineediting flag. */
#define READLINE
/* Define BANG_HISTORY if you want to have Csh style "!" history expansion.
This is unrelated to READLINE. */
#define BANG_HISTORY
/* Define HISTORY if you want to have access to previously typed commands.
If both HISTORY and READLINE are defined, you can get at the commands
with line editing commands, and you can directly manipulate the history
from the command line.
If only HISTORY is defined, the `fc' and `history' builtins are
available. */
#define HISTORY
#if defined (BANG_HISTORY) && !defined (HISTORY)
/* BANG_HISTORY requires HISTORY. */
# define HISTORY
#endif /* BANG_HISTORY && !HISTORY */
#if defined (READLINE) && !defined (HISTORY)
# define HISTORY
#endif
/* The default value of the PATH variable. */
#define DEFAULT_PATH_VALUE \
"/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:."
/* The value for PATH when invoking `command -p'. This is only used when
the Posix.2 confstr () function, or CS_PATH define are not present. */
#define STANDARD_UTILS_PATH \
"/bin:/usr/bin:/usr/ucb:/usr/sbin:/sbin:/etc:/usr/etc:/usr/lib"
/* Put system-specific default mail directories here. */
#if defined (__bsdi__) || defined (__FreeBSD__) || defined (__NetBSD__)
# define DEFAULT_MAIL_PATH "/var/mail/"
#endif
#if !defined (DEFAULT_MAIL_PATH)
#if defined (USG)
# define DEFAULT_MAIL_PATH "/usr/mail/"
#else
# define DEFAULT_MAIL_PATH "/usr/spool/mail/"
#endif
#endif
/* Define V9_ECHO if you want to give the echo builtin backslash-escape
interpretation using the -e option, in the style of the Bell Labs 9th
Edition version of echo. */
#define V9_ECHO
/* Define DEFAULT_ECHO_TO_USG if you want the echo builtin to interpret
the backslash-escape characters by default, like the System V echo.
This requires that V9_ECHO be defined. */
/* #define DEFAULT_ECHO_TO_USG */
#if !defined (V9_ECHO)
# undef DEFAULT_ECHO_TO_USG
#endif
/* Define CONTINUE_AFTER_KILL_ERROR if you want the kill command to
continue processing arguments after one of them fails. */
#define CONTINUE_AFTER_KILL_ERROR
/* Define BREAK_COMPLAINS if you want the non-standard, but useful
error messages about `break' and `continue' out of context. */
#define BREAK_COMPLAINS
/* Define GETOPTS_BUILTIN if you want the Posix.2 `getopts' shell builtin
compiled into the shell. */
#define GETOPTS_BUILTIN
/* When ALLOW_RIGID_POSIX_COMPLIANCE is defined, you can turn on strictly
Posix compliant behaviour by setting the environment variable
POSIXLY_CORRECT. */
#define ALLOW_RIGID_POSIX_COMPLIANCE
/* Define RESTRICTED_SHELL if you want the generated shell to have the
ability to be a restricted one. The shell thus generated can become
restricted by being run with the name "rbash", or by setting the -r
flag. */
/* #define RESTRICTED_SHELL */
/* Define DISABLED_BUILTINS if you want "builtin foo" to always run the
shell builtin "foo", even if it has been disabled with "enable -n foo". */
/* #define DISABLED_BUILTINS */
/* Define PROCESS_SUBSTITUTION if you want the K*rn shell-like process
substitution features "<(file)". */
/* Right now, you cannot do this on machines without fully operational
FIFO support. This currently include NeXT and Alliant. */
#if !defined (MKFIFO_MISSING) || defined (HAVE_DEV_FD)
# define PROCESS_SUBSTITUTION
#endif /* !MKFIFO_MISSING */
/* Define PROMPT_STRING_DECODE if you want the backslash-escaped special
characters in PS1 and PS2 expanded. Variable expansion will still be
performed. */
#define PROMPT_STRING_DECODE
/* Define BUFFERED_INPUT if you want the shell to do its own input
buffering. */
#define BUFFERED_INPUT
/* Define INTERACTIVE_COMMENTS if you want # comments to work by default
when the shell is interactive, as Posix.2a specifies. */
#define INTERACTIVE_COMMENTS
/* Define ONESHOT if you want sh -c 'command' to avoid forking to execute
`command' whenever possible. */
#define ONESHOT
/* Default primary and secondary prompt strings. */
#define PPROMPT "bash\\$ "
#define SPROMPT "> "
/* Define SELECT_COMMAND if you want the Korn-shell style `select' command:
select word in word_list; do command_list; done */
#define SELECT_COMMAND
#endif /* !_CONFIG_H_ */

194
config.h.mini Normal file
View file

@ -0,0 +1,194 @@
/* config.h -- Configuration file for bash. */
/* This is a `minimal' configuration file. It will create a shell without:
job control
aliases
pushd and popd
readline
history
restricted shell mode
`disabled' builtins (builtin xxx finds xxx even after enable -n xxx)
process substitution
prompt string decoding (though variable expansion is still done)
the `select' command */
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Bash is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with Bash; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (_CONFIG_H_)
#define _CONFIG_H_
#include "memalloc.h"
#if defined (HPUX) || defined (UNIXPC) || defined (Xenix)
# if !defined (USG)
# define USG
# endif
#endif
#if defined (HAVE_UNISTD_H) && !defined (BUILDING_MAKEFILE)
#include <unistd.h>
#endif
/* Define JOB_CONTROL if your operating system supports
BSD-like job control. */
/* #define JOB_CONTROL */
/* Note that vanilla System V machines don't support BSD job control,
although some do support Posix job control. */
#if defined (USG) && !defined (_POSIX_JOB_CONTROL)
# undef JOB_CONTROL
#endif /* USG && !_POSIX_JOB_CONTROL */
/* Define ALIAS if you want the alias features. */
/* #define ALIAS */
/* Define PUSHD_AND_POPD if you want those commands to be compiled in.
(Also the `dirs' commands.) */
/* #define PUSHD_AND_POPD */
/* Define BRACE_EXPANSION if you want curly brace expansion a la Csh:
foo{a,b} -> fooa foob. Even if this is compiled in (the default) you
can turn it off at shell startup with `-nobraceexpansion', or during
shell execution with `set +o braceexpand'. */
/* #define BRACE_EXPANSION */
/* Define READLINE to get the nifty/glitzy editing features.
This is on by default. You can turn it off interactively
with the -nolineediting flag. */
/* #define READLINE */
/* Define BANG_HISTORY if you want to have Csh style "!" history expansion.
This is unrelated to READLINE. */
/* #define BANG_HISTORY */
/* Define HISTORY if you want to have access to previously typed commands.
If both HISTORY and READLINE are defined, you can get at the commands
with line editing commands, and you can directly manipulate the history
from the command line.
If only HISTORY is defined, the `fc' and `history' builtins are
available. */
/* #define HISTORY */
#if defined (BANG_HISTORY) && !defined (HISTORY)
/* BANG_HISTORY requires HISTORY. */
# define HISTORY
#endif /* BANG_HISTORY && !HISTORY */
#if defined (READLINE) && !defined (HISTORY)
# define HISTORY
#endif
/* The default value of the PATH variable. */
#define DEFAULT_PATH_VALUE \
"/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:."
/* The value for PATH when invoking `command -p'. This is only used when
the Posix.2 confstr () function, or CS_PATH define are not present. */
#define STANDARD_UTILS_PATH \
"/bin:/usr/bin:/usr/ucb:/usr/sbin:/sbin:/etc:/usr/etc:/usr/lib"
/* Put system-specific default mail directories here. */
#if defined (__bsdi__) || defined (__FreeBSD__) || defined (__NetBSD__)
# define DEFAULT_MAIL_PATH "/var/mail/"
#endif
#if !defined (DEFAULT_MAIL_PATH)
#if defined (USG)
# define DEFAULT_MAIL_PATH "/usr/mail/"
#else
# define DEFAULT_MAIL_PATH "/usr/spool/mail/"
#endif
#endif
/* Define V9_ECHO if you want to give the echo builtin backslash-escape
interpretation using the -e option, in the style of the Bell Labs 9th
Edition version of echo. */
#define V9_ECHO
/* Define DEFAULT_ECHO_TO_USG if you want the echo builtin to interpret
the backslash-escape characters by default, like the System V echo.
This requires that V9_ECHO be defined. */
/* #define DEFAULT_ECHO_TO_USG */
#if !defined (V9_ECHO)
# undef DEFAULT_ECHO_TO_USG
#endif
/* Define CONTINUE_AFTER_KILL_ERROR if you want the kill command to
continue processing arguments after one of them fails. */
#define CONTINUE_AFTER_KILL_ERROR
/* Define BREAK_COMPLAINS if you want the non-standard, but useful
error messages about `break' and `continue' out of context. */
#define BREAK_COMPLAINS
/* Define GETOPTS_BUILTIN if you want the Posix.2 `getopts' shell builtin
compiled into the shell. */
#define GETOPTS_BUILTIN
/* When ALLOW_RIGID_POSIX_COMPLIANCE is defined, you can turn on strictly
Posix compliant behaviour by setting the environment variable
POSIXLY_CORRECT. */
#define ALLOW_RIGID_POSIX_COMPLIANCE
/* Define RESTRICTED_SHELL if you want the generated shell to have the
ability to be a restricted one. The shell thus generated can become
restricted by being run with the name "rbash", or by setting the -r
flag. */
/* #define RESTRICTED_SHELL */
/* Define DISABLED_BUILTINS if you want "builtin foo" to always run the
shell builtin "foo", even if it has been disabled with "enable -n foo". */
/* #define DISABLED_BUILTINS */
/* Define PROCESS_SUBSTITUTION if you want the K*rn shell-like process
substitution features "<(file)". */
/* Right now, you cannot do this on machines without fully operational
FIFO support. This currently include NeXT and Alliant. */
#if !defined (MKFIFO_MISSING)
# define PROCESS_SUBSTITUTION
#endif /* !MKFIFO_MISSING */
/* Define PROMPT_STRING_DECODE if you want the backslash-escaped special
characters in PS1 and PS2 expanded. Variable expansion will still be
performed. */
/* #define PROMPT_STRING_DECODE */
/* Define BUFFERED_INPUT if you want the shell to do its own input
buffering. */
#define BUFFERED_INPUT
/* Define INTERACTIVE_COMMENTS if you want # comments to work by default
when the shell is interactive, as Posix.2a specifies. */
#define INTERACTIVE_COMMENTS
/* Define ONESHOT if you want sh -c 'command' to avoid forking to execute
`command' whenever possible. */
#define ONESHOT
/* Default primary and secondary prompt strings. */
#define PPROMPT "bash\\$ "
#define SPROMPT "> "
/* Define SELECT_COMMAND if you want the Korn-shell style `select' command:
select word in word_list; do command_list; done */
/* #define SELECT_COMMAND */
#endif /* !_CONFIG_H_ */

8
configure vendored Executable file
View file

@ -0,0 +1,8 @@
#!/bin/sh
#
# This shell script does nothing since Bash doesn't require
# configuration to be forced on it; it auto-configures. You can
# change the location of the source directory with +srcdir.
#
echo "Bash is configured to auto configure."
exit 0

305
copy_cmd.c Normal file
View file

@ -0,0 +1,305 @@
/* copy_command.c -- copy a COMMAND structure. This is needed
primarily for making function definitions, but I'm not sure
that anyone else will need it. */
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Bash is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with Bash; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#include "shell.h"
WORD_DESC *
copy_word (word)
WORD_DESC *word;
{
WORD_DESC *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);
}
/* Copy the chain of words in LIST. Return a pointer to
the new chain. */
WORD_LIST *
copy_word_list (list)
WORD_LIST *list;
{
WORD_LIST *new_list = NULL;
while (list)
{
WORD_LIST *temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
temp->next = new_list;
new_list = temp;
new_list->word = copy_word (list->word);
list = list->next;
}
return (REVERSE_LIST (new_list, WORD_LIST *));
}
static PATTERN_LIST *
copy_case_clause (clause)
PATTERN_LIST *clause;
{
PATTERN_LIST *new_clause = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST));
new_clause->patterns = copy_word_list (clause->patterns);
new_clause->action = copy_command (clause->action);
return (new_clause);
}
static PATTERN_LIST *
copy_case_clauses (clauses)
PATTERN_LIST *clauses;
{
PATTERN_LIST *new_list = (PATTERN_LIST *)NULL;
while (clauses)
{
PATTERN_LIST *new_clause = copy_case_clause (clauses);
new_clause->next = new_list;
new_list = new_clause;
clauses = clauses->next;
}
return (REVERSE_LIST (new_list, PATTERN_LIST *));
}
/* Copy a single redirect. */
REDIRECT *
copy_redirect (redirect)
REDIRECT *redirect;
{
REDIRECT *new_redirect = (REDIRECT *)xmalloc (sizeof (REDIRECT));
FASTCOPY ((char *)redirect, (char *)new_redirect, (sizeof (REDIRECT)));
switch (redirect->instruction)
{
case r_reading_until:
case r_deblank_reading_until:
new_redirect->here_doc_eof = savestring (redirect->here_doc_eof);
/* There is NO BREAK HERE ON PURPOSE!!!! */
case r_appending_to:
case r_output_direction:
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:
new_redirect->redirectee.filename =
copy_word (redirect->redirectee.filename);
break;
}
return (new_redirect);
}
REDIRECT *
copy_redirects (list)
REDIRECT *list;
{
REDIRECT *new_list = NULL;
while (list)
{
REDIRECT *temp = copy_redirect (list);
temp->next = new_list;
new_list = temp;
list = list->next;
}
return (REVERSE_LIST (new_list, REDIRECT *));
}
static FOR_COM *
copy_for_command (com)
FOR_COM *com;
{
FOR_COM *new_for = (FOR_COM *)xmalloc (sizeof (FOR_COM));
new_for->flags = com->flags;
new_for->name = copy_word (com->name);
new_for->map_list = copy_word_list (com->map_list);
new_for->action = copy_command (com->action);
return (new_for);
}
#if defined (SELECT_COMMAND)
static SELECT_COM *
copy_select_command (com)
SELECT_COM *com;
{
SELECT_COM *new_select = (SELECT_COM *)xmalloc (sizeof (SELECT_COM));
new_select->flags = com->flags;
new_select->name = copy_word (com->name);
new_select->map_list = copy_word_list (com->map_list);
new_select->action = copy_command (com->action);
return (new_select);
}
#endif /* SELECT_COMMAND */
static GROUP_COM *
copy_group_command (com)
GROUP_COM *com;
{
GROUP_COM *new_group = (GROUP_COM *)xmalloc (sizeof (GROUP_COM));
new_group->command = copy_command (com->command);
return (new_group);
}
static CASE_COM *
copy_case_command (com)
CASE_COM *com;
{
CASE_COM *new_case = (CASE_COM *)xmalloc (sizeof (CASE_COM));
new_case->flags = com->flags;
new_case->word = copy_word (com->word);
new_case->clauses = copy_case_clauses (com->clauses);
return (new_case);
}
static WHILE_COM *
copy_while_command (com)
WHILE_COM *com;
{
WHILE_COM *new_while = (WHILE_COM *)xmalloc (sizeof (WHILE_COM));
new_while->flags = com->flags;
new_while->test = copy_command (com->test);
new_while->action = copy_command (com->action);
return (new_while);
}
static IF_COM *
copy_if_command (com)
IF_COM *com;
{
IF_COM *new_if = (IF_COM *)xmalloc (sizeof (IF_COM));
new_if->flags = com->flags;
new_if->test = copy_command (com->test);
new_if->true_case = copy_command (com->true_case);
new_if->false_case = copy_command (com->false_case);
return (new_if);
}
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);
new_simple->redirects = copy_redirects (com->redirects);
new_simple->line = com->line;
return (new_simple);
}
static FUNCTION_DEF *
copy_function_def (com)
FUNCTION_DEF *com;
{
FUNCTION_DEF *new_def = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF));
new_def->name = copy_word (com->name);
new_def->command = copy_command (com->command);
return (new_def);
}
/* Copy the command structure in COMMAND. Return a pointer to the
copy. Don't you forget to dispose_command () on this pointer
later! */
COMMAND *
copy_command (command)
COMMAND *command;
{
COMMAND *new_command = (COMMAND *)NULL;
if (command)
{
new_command = (COMMAND *)xmalloc (sizeof (COMMAND));
FASTCOPY ((char *)command, (char *)new_command, sizeof (COMMAND));
new_command->flags = command->flags;
new_command->line = command->line;
if (command->redirects)
new_command->redirects = copy_redirects (command->redirects);
switch (command->type)
{
case cm_for:
new_command->value.For = copy_for_command (command->value.For);
break;
#if defined (SELECT_COMMAND)
case cm_select:
new_command->value.Select = copy_select_command (command->value.Select);
break;
#endif
case cm_group:
new_command->value.Group = copy_group_command (command->value.Group);
break;
case cm_case:
new_command->value.Case = copy_case_command (command->value.Case);
break;
case cm_until:
case cm_while:
new_command->value.While = copy_while_command (command->value.While);
break;
case cm_if:
new_command->value.If = copy_if_command (command->value.If);
break;
case cm_simple:
new_command->value.Simple = copy_simple_command (command->value.Simple);
break;
case cm_connection:
{
CONNECTION *new_connection;
new_connection = (CONNECTION *)xmalloc (sizeof (CONNECTION));
new_connection->connector = command->value.Connection->connector;
new_connection->first =
copy_command (command->value.Connection->first);
new_connection->second =
copy_command (command->value.Connection->second);
new_command->value.Connection = new_connection;
break;
}
/* Pathological case. I'm not even sure that you can have a
function definition as part of a function definition. */
case cm_function_def:
new_command->value.Function_def =
copy_function_def (command->value.Function_def);
break;
}
}
return (new_command);
}

1553
cpp-Makefile Normal file

File diff suppressed because it is too large Load diff

207
dispose_cmd.c Normal file
View file

@ -0,0 +1,207 @@
/* dispose_command.c -- dispose of a COMMAND structure. */
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Bash is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with Bash; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "shell.h"
/* Dispose of the command structure passed. */
void
dispose_command (command)
COMMAND *command;
{
if (!command) return;
if (command->redirects)
dispose_redirects (command->redirects);
switch (command->type)
{
case cm_for:
{
register FOR_COM *c = command->value.For;
dispose_word (c->name);
dispose_words (c->map_list);
dispose_command (c->action);
free (c);
break;
}
#if defined (SELECT_COMMAND)
case cm_select:
{
register SELECT_COM *c = command->value.Select;
dispose_word (c->name);
dispose_words (c->map_list);
dispose_command (c->action);
free (c);
break;
}
#endif
case cm_group:
{
dispose_command (command->value.Group->command);
free (command->value.Group);
break;
}
case cm_case:
{
register CASE_COM *c = command->value.Case;
PATTERN_LIST *t, *p = c->clauses;
dispose_word (c->word);
while (p)
{
dispose_words (p->patterns);
dispose_command (p->action);
t = p;
p = p->next;
free (t);
}
free (c);
break;
}
case cm_until:
case cm_while:
{
register WHILE_COM *c = command->value.While;
dispose_command (c->test);
dispose_command (c->action);
free (c);
break;
}
case cm_if:
{
register IF_COM *c = command->value.If;
dispose_command (c->test);
dispose_command (c->true_case);
dispose_command (c->false_case);
free (c);
break;
}
case cm_simple:
{
register SIMPLE_COM *c = command->value.Simple;
dispose_words (c->words);
dispose_redirects (c->redirects);
free (c);
break;
}
case cm_connection:
{
register CONNECTION *c = command->value.Connection;
dispose_command (c->first);
dispose_command (c->second);
free (c);
break;
}
case cm_function_def:
{
register FUNCTION_DEF *c = command->value.Function_def;
dispose_word (c->name);
dispose_command (c->command);
free (c);
break;
}
default:
report_error ("Attempt to free unknown command type `%d'.\n", command->type);
break;
}
free (command);
}
/* How to free a WORD_DESC. */
void
dispose_word (word)
WORD_DESC *word;
{
if (word->word)
free (word->word);
free (word);
}
/* How to get rid of a linked list of words. A WORD_LIST. */
void
dispose_words (list)
WORD_LIST *list;
{
WORD_LIST *t;
while (list)
{
t = list;
list = list->next;
dispose_word (t->word);
free (t);
}
}
/* How to dispose of an array of pointers to char. */
void
dispose_word_array (array)
char **array;
{
register int count;
for (count = 0; array[count]; count++)
free (array[count]);
free (array);
}
/* How to dispose of an list of redirections. A REDIRECT. */
void
dispose_redirects (list)
REDIRECT *list;
{
register REDIRECT *t;
while (list)
{
t = list;
list = list->next;
switch (t->instruction)
{
case r_reading_until:
case r_deblank_reading_until:
free (t->here_doc_eof);
/* ... */
case r_output_direction:
case r_input_direction:
case r_inputa_direction:
case r_appending_to:
case r_err_and_out:
case r_input_output:
case r_output_force:
case r_duplicating_input_word:
case r_duplicating_output_word:
dispose_word (t->redirectee.filename);
break;
}
free (t);
}
}

32
dispose_cmd.h Normal file
View file

@ -0,0 +1,32 @@
/* dispose_cmd.h -- Functions appearing in dispose_cmd.c. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (_DISPOSE_CMD_H_)
#define _DISPOSE_CMD_H_
#include "stdc.h"
extern void dispose_command __P((COMMAND *));
extern void dispose_word __P((WORD_DESC *));
extern void dispose_words __P((WORD_LIST *));
extern void dispose_word_array __P((char **));
extern void dispose_redirects __P((REDIRECT *));
#endif /* !_DISPOSE_CMD_H_ */

795
documentation/FAQ Normal file
View file

@ -0,0 +1,795 @@
This is the Bash FAQ, version 1.2, for Bash version 1.14.6.
This document contains a set of frequently-asked questions concerning
Bash, the GNU Bourne-Again Shell. Bash is a freely-available command
interpreter with advanced features for both interactive use and shell
programming.
Another good source of basic information about shells is the collection
of FAQ articles periodically posted to comp.unix.shell.
Questions and comments concerning this document should be set to
chet@po.cwru.edu.
Contents:
1) What is it?
2) What's the latest version?
3) Where can I get it?
4) What's the `Posix 1003.2 standard'?
5) On what machines will bash run?
6) How does bash differ from sh, the Bourne shell?
7) How does bash differ from the Korn shell?
8) What is the bash `posix mode'?
9) How can I build bash with gcc?
10) Why does bash run a different version of `command' than
`which command' says it will?
11) How can I make my csh aliases work when I convert to bash?
12) Now that I've converted from ksh to bash, are there equivalents to
ksh features like autoloaded functions and the `whence' command?
13) Why is the bash builtin `test' slightly different from /bin/test?
14) Why does bash sometimes say `Broken pipe'?
15) How can I get bash to read and display eight-bit characters?
16) Why can't I use command line editing in my `cmdtool'?
17) How do I write a function `x' to replace builtin command `x', but
still invoke the command from within the function?
18) When I have terminal escape sequences in my prompt, why does bash
wrap lines at the wrong column?
19) I built bash on Solaris 2. Why do globbing expansions and filename
completion chop off the first few characters of each filename?
20) Why doesn't bash treat brace expansions exactly like csh?
21) Why does bash dump core after I interrupt username completion?
22) I'm running SVR4.2. Why is the line erased every time I type `@'?
23) How can I find the value of a shell variable whose name is the value
of another shell variable?
24) If I pipe the output of a command into `read variable', why doesn't
the output show up in $variable when the read command finishes?
25) I just changed my shell to bash, and now I can't FTP into my machine.
Why not?
26) I have a bunch of shell scripts that use backslash-escaped characters
in arguments to `echo'. Bash doesn't interpret these characters. Why
not, and how can I make it understand them?
27) Why doesn't bash have csh variable modifiers?
28) Why does bash report syntax errors when my C News scripts use a
redirection before a subshell command?
29) How do I report bugs in bash, and where should I look for fixes and
advice?
30) What kind of bash documentation is there?
31) What's coming in future versions?
32) What's on the bash `wish list'?
33) When will the next release appear?
1) What is it?
Bash is a Unix command interpreter (shell). It is an implementation of
the Posix 1003.2 shell standard, and resembles the Korn and System V
shells.
Bash contains a number of enhancements over those shells, both
for interactive use and shell programming. Features geared
toward interactive use include command line editing, command
history, job control, aliases, and prompt expansion. Programming
features include additional variable expansions, shell
arithmetic, and a number of variables and options to control
shell behavior.
Bash was originally written by Brian Fox of the Free Software
Foundation. The current developer and maintainer is Chet Ramey
of Case Western Reserve University.
2) What's the latest version?
The latest version is 1.14.6, first made available on December 19, 1995.
3) Where can I get it?
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 1.14.6:
ftp://prep.ai.mit.edu/pub/gnu/bash-1.14.6.tar.gz
ftp://slc2.ins.cwru.edu/pub/dist/bash-1.14.6.tar.gz
4) What's the `Posix 1003.2 standard'?
POSIX is a name originally coined by Richard Stallman for a
family of open system standards based on UNIX. There are a
number of aspects of UNIX under consideration for
standardization, from the basic system services at the system
call and C library level to applications and tools to system
administration and management. Each area of standardization is
assigned to a working group in the 1003 series.
The POSIX Shell and Utilities standard has been developed by IEEE
Working Group 1003.2 (POSIX.2). It concentrates on the command
interpreter interface and utility programs commonly executed from
the command line or by other programs. An initial version of the
standard has been approved and published by the IEEE, and work is
currently underway to update it.
Bash is concerned with the aspects of the shell's behavior
defined by POSIX.2. The shell command language has of course
been standardized, including the basic flow control and program
execution constructs, I/O redirection and pipelining, argument
handling, variable expansion, and quoting.
The `special' builtins, which must be implemented as part of the
shell to provide the desired functionality, are specified as
being part of the shell; examples of these are `eval' and
`export'. Other utilities appear in the sections of POSIX.2 not
devoted to the shell which are commonly (and in some cases must
be) implemented as builtin commands, such as `read' and `test'.
POSIX.2 also specifies aspects of the shell's interactive
behavior as part of the UPE, including job control and command
line editing. Only vi-style line editing commands have been
standardized; emacs editing commands were left out due to
objections.
5) On what machines will bash run?
Bash has been ported to nearly every version of UNIX. All you
should have to do to build it on a machine for which a port
exists is to type `make'. The build process will attempt to
discover the version of UNIX you have and tailor itself
accordingly, using a combination of saved definitions in the file
`machines.h' and a file `sysdefs.h' created by inspecting the
environment for various things.
More information appears in the file `INSTALL' in the distribution.
6) How does bash differ from sh, the Bourne shell?
This is a non-comprehensive list of features that differentiate bash
from the SVR4 shell. The bash manual page explains these completely.
Things bash has that sh does not:
long invocation options
`!' reserved word to invert pipeline return value
the select compound command
the $(...) form of command substitution
the ${#param} parameter value length operator
expansions to perform substring removal (${p%[%]w}, ${p#[#]w})
variables: BASH, BASH_VERSION, UID, EUID, REPLY, PPID, PWD,
OLDPWD, SHLVL, RANDOM, SECONDS, LINENO, HISTCMD,
HOSTTYPE, OSTYPE, ENV, MAIL_WARNING, PS3, PS4,
HISTSIZE, HISTFILE, HISTFILESIZE, PROMPT_COMMAND,
FCEDIT, FIGNORE, IGNOREEOF, INPUTRC, HISTCONTROL,
command_oriented_history, allow_null_glob_expansion,
glob_dot_filenames, histchars, nolinks, auto_resume,
HOSTFILE, noclobber, TMOUT, no_exit_on_failed_exec,
cdable_vars
redirections: <>, &>, >|
prompt string special char translation and variable expansion
auto-export of modified values of variables in initial environment
command search finds functions before builtins
bash return builtin will exit a file sourced with `.'
builtins: cd -, exec -, echo -e/-E, export -n/-f/-p/name=value,
pwd -P, read -r, readonly -f, trap -l, ulimit -n/-p/-u,
set -b/-m/-o option/-p/-l/-d/-C/-H/-P, unset -f/-v,
umask -S, type -all/-path/-type, suspend -f, kill -s
bash reads ~/.bashrc for interactive shells, $ENV for non-interactive
bash restricted shell mode is more extensive
bash allows functions and variables with the same name
brace expansion
tilde expansion
arithmetic expansion and `let' builtin
process substitution
aliases and alias/unalias builtins
local variables in functions and `local' builtin
readline and command-line editing
history and history/fc builtins
csh-like history expansion
other new bash builtins: bind, command, builtin, declare/typeset,
dirs, enable, fc, help, history, logout,
popd, pushd
exported functions
filename generation when using output redirection (command >a*)
Things sh has that bash does not:
uses variable SHACCT to do shell accounting
includes `stop' builtin (bash can use alias stop='kill -s STOP')
`newgrp' builtin
turns on job control if called as `jsh'
ulimit attempts to set both soft & hard limits if -S/-H not given
New things in the SVR4.2 sh:
internationalization: $LANG, $LC_CTYPE, $LC_MESSAGES, setlocale, etc.
$TIMEOUT (like bash $TMOUT)
new builtins: mldmode, priv
`read' builtin has -r
cannot trap SIGALRM or SIGCHLD
kill -s is present
Implementation differences:
redirection to/from compound commands causes sh to create a subshell
bash does not allow unbalanced quotes; sh silently inserts them at EOF
bash does not mess with signal 11
sh sets (euid, egid) to (uid, gid) if -p not supplied and uid < 100
bash splits only the results of expansions on IFS
sh does not allow MAILCHECK to be unset (?)
7) How does bash differ from the Korn shell?
Things bash has or uses that ksh does not:
long invocation options
`!' reserved word
posix mode and posix conformance
command hashing
tilde expansion for assignment statements that look like $PATH
process substitution with named pipes if /dev/fd is not available
variables: BASH, BASH_VERSION, UID, EUID, SHLVL, HISTCMD, HOSTTYPE,
OSTYPE, MAIL_WARNING, HISTFILESIZE, OPTERR,
PROMPT_COMMAND, IGNOREEOF, FIGNORE, INPUTRC, HISTCONTROL,
notify, command_oriented_history, glob_dot_filenames,
allow_null_glob_expansion, histchars, nolinks, HOSTFILE,
noclobber, auto_resume, no_exit_on_failed_exec, cdable_vars
prompt expansion with backslash escapes and command substitution
redirection: &> (stdout and stderr)
more extensive and extensible editing and completion
builtins: bind, builtin, command, declare, dirs, echo -e/-E, enable,
exec -, fc -s, export -n/-f/-p, hash, help, history,
jobs -x, kill -s, local, logout, popd, pushd,
readonly -n/-f/-p, set -o braceexpand/-o histexpand/
-o interactive-comments/-o notify/-o physical/-o posix/
-l/-d/-C/-b/-H/-P, suspend, trap -l, type, ulimit -u,
umask -S
$[...] synonym for $((...))
`!' csh-style history expansion
Things ksh has or uses that bash does not:
new version of test: [[...]]
((...)) equivalent to let "..."
time keyword to let pipelines be timed
tracked aliases
$(<file)
one-dimensional arrays and appropriate expansions
variables: ERRNO, FPATH, COLUMNS, LINES, EDITOR, VISUAL
extended pattern matching with egrep-style pattern lists
co-processes (|&, >&p, <&p)
weirdly-scoped functions
typeset +f to list all function names without definitions
text of command history kept in a file, not memory
builtins: alias -x, cd old new, fc -e -, newgrp, print,
read -p/-s/u/var?prompt, set -A/-o gmacs/-o keyword/
-o bgnice/-o markdirs/-o nolog/-o trackall/-o viraw/-s,
typeset -H/-L/-R/-A/-ft/-fu/-fx/-l/-u/-t, whence
Implementation differences:
ksh runs last command of a pipeline in parent shell context
ksh ulimit sets hard and soft limits by default
bash has brace expansion by default
bash has fixed startup file for all interactive shells; ksh reads $ENV
bash has exported functions
bash command search finds functions before builtins
8) What is the bash `posix mode'?
Although bash is an implementation of the Posix.2 shell
specification, there are areas where the bash default behavior
differs from that spec. The bash `posix mode' changes the bash
behavior in these areas so that it obeys the spec more closely.
Posix mode is entered by starting bash with the -posix option or
executing `set -o posix' after bash is running.
The specific aspects of bash which change when posix mode is
active are listed in the file CWRU/POSIX.NOTES in the bash
distribution.
9) How can I build bash with gcc?
Type
make CC=gcc CPPNAME='$(CC) -E'
10) Why does bash run a different version of `command' than
`which command' says it will?
`which' is actually a csh script that assumes you're running csh.
It reads the csh startup files from your home directory and uses
those to determine which `command' will be invoked. Since bash
doesn't use any of those startup files, there's a good chance
that your bash environment differs from your csh environment.
11) How can I make my csh aliases work when I convert to bash?
Bash uses a different syntax to support aliases than csh does.
The details can be found in the documentation. We have provided
a shell script which does most of the work of conversion for you;
this script can be found in ./examples/alias-conv.sh. Here is
how you use it:
Start csh in the normal way for you. (e.g., `csh')
Pipe the output of `alias' through `alias-conv.sh', saving the
results into `bash_aliases':
alias | alias-conv.sh >bash_aliases
Edit `bash_aliases', carefully reading through any created
functions. You will need to change the names of csh specific
variables (like $cwd) to the bash equivalents (like $PWD). You
will also need to remove recursive references to commands which
are defined as functions. For example, the csh alias:
alias cd 'cd \!*;echo $cwd'
is converted to the bash function:
cd ()
{
cd $*;
echo $cwd
}
This function contains a self-pointing reference to `cd', which
should be changed to use the `builtin' version. It also uses
the csh variable `$cwd' which has an equivalent in bash.
Precede the recursive reference with the word `builtin', and
change the name of the variable:
cd () { builtin cd $*; echo $PWD; }
Merge the edited file into your ~/.bashrc.
12) Now that I've converted from ksh to bash, are there equivalents to
ksh features like autoloaded functions and the `whence' command?
There are features in ksh-88 that do not have direct bash equivalents.
Most, however, can be emulated with very little trouble.
ksh-88 feature Bash equivalent
-------------- ---------------
[[...]] can usually use [...]; minor differences
compiled-in aliases set up aliases in .bashrc; some ksh aliases are
bash builtins (hash, history, type)
$(<file) $(cat file)
arrays no good subsitute yet
((...)) let "..."
time use external command; GNU time is particularly useful
use time bash -c '...' for complicated constructs
extended patterns no good substitute
coprocesses named pipe pairs (one for read, one for write)
typeset +f declare -f |
sed -n 's:^declare -[a-z]* \([^ ]*\).*$:\1:p'
cd, print, whence function subsitutes in examples/functions/kshenv
autoloaded functions examples/functions/autoload is the same as typeset -fu
read var?prompt [ -t 0 ] && echo -n prompt >&2; read var
13) Why is the bash builtin `test' slightly different from /bin/test?
The specific example used here is [ ! x -o x ], which is false.
Bash's builtin `test' implements the Posix.2 spec, which can be
summarized as follows (the wording is due to David Korn):
Here is the set of rules for processing test arguments.
0 Args: False
1 Arg: True iff argument is not null.
2 Args: If first arg is !, True iff second argument is null.
If first argument is unary, then true if unary test is true
Otherwise error.
3 Args: If second argument is a binary operator, do binary test of $1 $3
If first argument is !, negate two argument test of $2 $3
Otherwise error.
4 Args: If first argument is !, negate three argument test of $2 $3 $4.
Otherwise unspecified
5 or more Args: unspecified. (Historical shells would use their
current algorithm).
The operators -a and -o are considered binary operators for the purpose
of the 3 Arg case.
As you can see, the test becomes (not (x or x)), which is false.
14) Why does bash sometimes say `Broken pipe'?
If a sequence of commands appear in a pipeline, and one of the
reading commands finishes before the writer has finished, the
writer receives a SIGPIPE signal. Many other shells special-case
SIGPIPE as an exit status in the pipeline and do not report it.
For example, in:
ps -aux | head
`head' can finish before `ps' writes all of its output, and ps
will try to write on a pipe without a reader. In that case, bash
will print `Broken pipe' to stderr when ps is killed by a
SIGPIPE.
15) How can I get bash to read and display eight-bit characters?
This is a process requiring several steps.
First, you must ensure that the `physical' data path is a full eight
bits. For xterms, for example, the `vt100' resources `eightBitInput'
and `eightBitOutput' should be set to `true'.
Once you have set up an eight-bit path, you must tell the kernel and
tty driver to leave the eigth bit of characters alone when processing
keyboard input. Use `stty' to do this:
stty cs8 -istrip -parenb
For old BSD-style systems, you can use
stty pass8
You may also need
stty even odd
Finally, you need to tell readline that you will be inputting and
displaying eight-bit characters. You use readline variables to do
this. These variables can be set in your .inputrc or using the bash
`bind' builtin. Here's an example using `bind':
bash$ bind 'set convert-meta off'
bash$ bind 'set meta-flag on'
bash$ bind 'set output-meta on'
The `set' commands between the single quotes may also be placed
in ~/.inputrc.
16) Why can't I use command line editing in my `cmdtool'?
The problem is `cmdtool' and bash fighting over the input. When
scrolling is enabled in a cmdtool window, cmdtool puts the tty in
`raw mode' to permit command-line editing using the mouse for
applications that cannot do it themselves. As a result, bash and
cmdtool each try to read keyboard input immediately, with neither
getting enough of it to be useful.
This mode also causes cmdtool to not implement many of the
terminal functions and control sequences appearing in the
`sun-cmd' termcap entry. For a more complete explanation, see
that file examples/suncmd.termcap in the bash distribution.
`xterm' is a better choice, and gets along with bash much more
smoothly.
17) How do I write a function `x' to replace builtin command `x', but
still invoke the command from within the function?
This is what the `command' and `builtin' builtins are for. The
`command' builtin executes the command supplied as its first
argument, skipping over any function defined with that name. The
`builtin' builtin executes the builtin command given as its first
argument directly.
For example, to write a function to replace `cd' that writes the
hostname and current directory to an xterm title bar, use
something like the following:
cd()
{
builtin cd "$@" && xtitle $HOST: $PWD
}
This could also be written using `command' instead of `builtin';
the version above is marginally more efficient.
18) When I have terminal escape sequences in my prompt, why does bash
wrap lines at the wrong column?
Bash does not know that the terminal escape sequences do not take
up space on the screen. The redisplay code assumes, unless told
otherwise, that each character in the prompt is a `printable'
character that takes up one character position on the screen.
You can use the bash prompt expansion facility (see the PROMPTING
section in the manual page) to tell readline that sequences of
characters in the prompt strings take up no screen space.
Use the \[ escape to begin a sequence of non-printing characters,
and the \] escape to signal the end of such a sequence.
19) I built bash on Solaris 2. Why do globbing expansions and filename
completion chop off the first few characters of each filename?
This is the consequence of building bash on SunOS 5 and linking
with the libraries in /usr/ucblib, but using the definitions
and strutures from files in /usr/include.
The actual conflict is between the dirent structure in
/usr/include/dirent.h and the struct returned by the version of
`readdir' in libucb.a (a 4.3-BSD style `struct direct').
Make sure you've got /usr/ccs/bin ahead of /usr/ucb in your $PATH
when building bash. This will ensure that you use /usr/ccs/bin/cc
or acc instead of /usr/ucb/cc and that you link with libc before
libucb.
If you have installed the Sun C compiler, you may also need to
put /usr/ccs/bin and /opt/SUNWspro/bin into your $PATH before
/usr/ucb.
20) Why doesn't bash treat brace expansions exactly like csh?
The only difference between bash and csh brace expansion is that
bash requires a brace expression to contain at least on unquoted
comma if it is to be expanded. Any brace-surrounded word not
containing an unquoted comma is left unchanged by the brace
expansion code. This affords the greatest degree of sh
compatibility.
Bash, ksh, zsh, and pd-ksh all implement brace expansion this way.
21) Why does bash dump core after I interrupt username completion on a
machine running NIS?
This is a famous and long-standing bug in the SunOS YP (sorry, NIS)
client library, which is part of libc.
The YP library code keeps static state -- a pointer into the data
returned from the server. When YP initializes itself (setpwent),
it looks at this pointer and calls free on it if it's non-null.
So far, so good.
If one of the YP functions is interrupted during getpwent (the
exact function is interpretwithsave()), and returns NULL, the
pointer is freed without being reset to NULL, and the function
returns. The next time getpwent is called, it sees that this
pointer is non-null, calls free, and the bash free() blows up
because it's being asked to free freed memory.
The traditional Unix mallocs allow memory to be freed multiple
times; that's probably why this has never been fixed. You can
probably stop it by adding an #undef USE_GNU_MALLOC to the
appropriate machine description in machines.h.
22) I'm running SVR4.2. Why is the line erased every time I type `@'?
The `@' character is the default `line kill' character in most
versions of System V, including SVR4.2. You can change this
character to whatever you want using `stty'. For example, to
change the line kill character to control-u, type
stty kill ^U
where the `^' and `U' can be two separate characters.
23) How can I find the value of a shell variable whose name is the value
of another shell variable?
Use the `eval' builtin. The important thing to remember is that
`eval' expands the arguments you give it again, so you need to
quote the parts of the arguments that you want `eval' to act on.
For example, this expression prints the value of the last positional
parameter:
eval echo \$\{$#\}
The expansion of the quoted portions of this expression will be
deferred until `eval' runs, while the `$#' will be expanded
before `eval' is executed.
24) If I pipe the output of a command into `read variable', why doesn't
the output show up in $variable when the read command finishes?
This has to do with the parent-child relationship between Unix
processes.
Each element of a pipeline runs in a separate process, a child of
the shell running the pipeline. A subprocess cannot affect its
parent's environment. When the `read' command sets the variable
to the input, that variable is set only in the subshell, not the
parent shell. When the subshell exits, the value of the variable
is lost.
Many pipelines that end with `read variable' can be converted
into command substitutions, which will capture the output into a
variable:
grep ^gnu /usr/lib/news/active | wc -l | read ngroup
can be converted into
ngroup=$(grep ^gnu /usr/lib/news/active | wc -l)
This does not, unfortunately, work to split the text among
multiple variables, as read does when given multiple variable
arguments.
25) I just changed my shell to bash, and now I can't FTP into my machine.
Why not?
You must add the full pathname to bash to the file /etc/shells.
Many versions of ftpd use this file to prohibit `special' users
such as `uucp' and `news' from using FTP.
26) I have a bunch of shell scripts that use backslash-escaped characters
in arguments to `echo'. Bash doesn't interpret these characters. Why
not, and how can I make it understand them?
This is the behavior of echo on most Unix System V machines.
The bash builtin `echo' is modelled after the 9th Edition
Research Unix version of `echo'. It does not interpret
backslash-escaped characters in its argument strings by default,
but requires the use of the -e option to enable the
interpretation. The System V echo provides no way to disable the
special characters; the bash echo has a -E option to disable
them.
There is a compile-time option that will make bash behave like
the System V echo and interpret things like \t by default.
Change config.h so that DEFAULT_ECHO_TO_USG is defined, remove
builtins/libbuiltins.a and builtins/echo.o, and rebuild.
27) Why doesn't bash have csh variable modifiers?
Posix has specified a more powerful, albeit somewhat more confusing,
mechanism cribbed from ksh, and bash implements it.
${parameter%word}
Remove smallest suffix pattern. The WORD is expanded to produce
a pattern. It then expands to the value of PARAMETER, with the
smallest portion of the suffix matched by the pattern deleted.
x=file.c
echo ${x%.c}.o
-->file.o
${parameter%%word}
Remove largest suffix pattern. The WORD is expanded to produce
a pattern. It then expands to the value of PARAMETER, with the
largest portion of the suffix matched by the pattern deleted.
x=posix/src/std
echo ${x%%/*}
-->posix
${parameter#word}
Remove smallest prefix pattern. The WORD is expanded to produce
a pattern. It then expands to the value of PARAMETER, with the
smallest portion of the prefix matched by the pattern deleted.
x=$HOME/src/cmd
echo ${x#$HOME}
-->/src/cmd
${parameter##word}
Remove largest prefix pattern. The WORD is expanded to produce
a pattern. It then expands to the value of PARAMETER, with the
largest portion of the prefix matched by the pattern deleted.
x=/one/two/three
echo ${x##*/}
-->three
Given
a=/a/b/c/d
b=b.xxx
csh bash result
--- ---- ------
$a:h ${a%/*} /a/b/c
$a:t ${a##*/} d
$b:r ${b%.*} b
$b:e ${b##*.} xxx
28) Why does bash report syntax errors when my C News scripts use a
redirection before a subshell command?
The actual command in question is something like
< file ( command )
According to the grammar given in the Posix.2 standard, this construct
is, in fact, a syntax error. Redirections may only precede `simple
commands'. A subshell construct such as the above is one of the shell's
`compound commands'. A redirection may only follow a compound command.
The file CWRU/sh-redir-hack in the 1.14.6 distribution is an (unofficial)
patch to parse.y that will modify the grammar to support this construct.
Note that if you apply this, you must recompile with -DREDIRECTION_HACK.
This introduces a large number of reduce/reduce conflicts into the shell
grammar.
29) How do I report bugs in bash, and where should I look for fixes and
advice?
Use the `bashbug' script to report bugs. It is built and
installed at the same time as bash. It provides a standard
template for reporting a problem and automatically includes
information about your configuration and build environment.
`bashbug' sends its reports to bug-bash@prep.ai.mit.edu, which
is a large mailing list gatewayed to the usenet newsgroup gnu.bash.bug.
Bug fixes, answers to questions, and announcements of new releases
are all posted to gnu.bash.bug. Discussions concerning bash features
and problems also take place there.
To reach the bash maintainers directly, send mail to
bash-maintainers@prep.ai.mit.edu.
30) What kind of bash documentation is there?
First, look in the documentation directory in the bash distribution.
It should contain the following files:
bash.1 an extensive, thorough Unix-style manual page
builtins.1 a manual page covering just bash builtin commands
features.texi a Gnu-style info file overview
FAQ this file
article.ms text of an article written for The Linux Journal
readline.3 a man page describing readline
Postscript files created from the above source are also present in
the distribution.
There is additional documentation available for anonymous FTP from host
slc2.ins.cwru.edu in the `pub/bash' directory.
Cameron Newham is in the midst of writing a book on bash, to be
published by O'Reilly and Associates. Look for it sometime this
year.
31) What's coming in future versions?
There will be no new features in future releases of version 1.14.
The next major release, bash-2.0, will contain extensive changes and new
features. Here's a short list:
one-dimensional arrays with a new compound assignment statement,
appropriate expansion constructs and modifications to some
of the builtins (read, declare, etc.) to use them
new expansions to do ANSI-C string expansion, substring extraction,
pattern replacement, and indirect variable expansion
new builtins: `disown' and `shopt'
new variables: HISTIGNORE, SHELLOPTS, PIPESTATUS, DIRSTACK
special handling of many unused or redundant variables removed
dynamic loading of new builtin commands; many loadable examples provided
new prompt expansions: \e, \n, \H, \T
new readline variables: enable-keypad, mark-directories, input-meta
new readline commands to manipulate the mark and operate on the region
new readline emacs mode commands and bindings for ksh-88 compatibility
updated and extended builtins
new DEBUG trap
expanded (and now documented) restricted shell mode
implementation stuff:
autoconf-based configuration
nearly all of the bugs reported since version 1.14 have been fixed
most builtins converted to use builtin `getopt' for consistency
most builtins use -p option to display output in a reusable form
(for consistency)
grammar tighter and smaller (66 reduce-reduce conflicts gone)
lots of code now smaller and faster
test suite greatly expanded
32) What's on the bash `wish list'?
internationalization with a variable expansion to translate a string
according to a particular message catalog
Programmable completion a la zsh
menu completion a la tcsh
the ksh egrep-style extended pattern matching operators
associative arrays (not really all that hard)
breaking some of the shell functionality into embeddable libraries
a bash debugger
Much of this will not be in bash-2.0.
33) When will the next release appear?
Version 1.14.6 will probably be the last release for version 1.14.
The next version will appear sometime in 1996. Never make predictions.
This document is copyright Chester Ramey, 1995.
Permission is hereby granted, without written agreement and
without license or royalty fees, to use, copy, and distribute
this document for any purpose, provided that the above copyright
notice appears in all copies of this document and that the
contents of this document remain unaltered.

103
documentation/Makefile Normal file
View file

@ -0,0 +1,103 @@
# This Makefile is for the Bash/documentation directory -*- text -*-.
#
RM = rm -f
INSTALL_DATA = ../support/install.sh -c -m 644
# unused
TEXINDEX = texindex
TEX = tex
MAKEINFO = makeinfo
TEXI2DVI = ../support/texi2dvi
QUIETPS = #set this to -q to shut up dvips
DVIPS = dvips -D 300 $(QUIETPS) -o $@ # tricky
TEXINPUTS = ./../lib/readline/doc
# Change to groff -Tascii if you don't have nroff
NROFF = nroff
# This should be a program that converts troff to postscript
GROFF = groff
HSUSER = ./../lib/readline/doc/hsuser.texinfo
RLUSER = ./../lib/readline/doc/rluser.texinfo
.SUFFIXES: .1 .3 .ms .ps .txt .dvi
.1.ps:
$(RM) $@
${GROFF} -man $< > $@
.1.txt:
$(RM) $@
${NROFF} -man $< > $@
.ms.ps:
$(RM) $@
${GROFF} -ms $< > $@
.ms.txt:
$(RM) $@
${NROFF} -ms $< > $@
.3.ps:
$(RM) $@
${GROFF} -man $< > $@
.3.txt:
$(RM) $@
${NROFF} -man $< > $@
all: ps info dvi text
ps: bash.ps readline.ps article.ps
dvi: features.dvi features.ps
info: features.info
text: bash.txt builtins.txt readline.txt article.txt
features.dvi: features.texi $(HSUSER) $(RLUSER)
TEXINPUTS=.:$(TEXINPUTS):$$TEXINPUTS $(TEXI2DVI) features.texi
features.ps: features.dvi
$(RM) $@
$(DVIPS) features.dvi
features.info: features.texi $(HSUSER) $(RLUSER)
$(MAKEINFO) --no-split -I$(TEXINPUTS) features.texi
bash.txt: bash.1
bash.ps: bash.1
builtins.txt: builtins.1 bash.1
readline.txt: readline.3
readline.ps: readline.3
article.ps: article.ms
hsuser.texinfo: ../lib/readline/doc/hsuser.texinfo
ln -s ../lib/readline/doc/hsuser.texinfo .
rluser.texinfo: ../lib/readline/doc/rluser.texinfo
ln -s ../lib/readline/doc/rluser.texinfo .
clean:
$(RM) *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \
*.fns *.kys *.tps *.vrs *.o core rluser.texinfo hsuser.texinfo
distclean mostlyclean: clean
realclean maintainer-clean: clean
rm -f *.dvi *.info *.ps *.txt
installdirs:
-[ -d $(mandir) ] || mkdir $(mandir)
-[ -d $(man3dir) ] || mkdir $(man3dir)
-[ -d $(infodir) ] || mkdir $(infodir)
install: all installdirs
$(INSTALL_DATA) bash.1 $(mandir)
$(INSTALL_DATA) readline.3 $(man3dir)
$(INSTALL_DATA) features.info $(infodir)/bash.info
uninstall:
$(RM) $(mandir)/bash.1
$(RM) $(man3dir)/readline.3 $(infodir)/bash.info

32
documentation/README Normal file
View file

@ -0,0 +1,32 @@
This directory contains the bash documentation.
FAQ - a set of frequently-asked questions about Bash with answers
article.ms - an article I wrote about bash for The Linux Journal
bash.1 - the bash man page
builtins.1 - a man page that documents the builtins, extracted from bash.1
features.texi - the `bash features' document, suitable for an info tree
readline.3 - the readline man page
The `.ps' files are postscript versions of the above. The `.txt' versions
are ascii -- the output of `nroff'.
The rest of this file explains how to use the `builtins.1' man page.
For each command in the list of builtins create a file in man/man1 called:
${command}.1
eg.
for.1
type.1
alias.1
etc.
All these files are identical as follows:
jaws@jaws(264)$ cat alias.1
.so man1/builtins.1
jaws@jaws(265)$
Make sure you adjust the .so line in builtins.1 to reflect where you
put it.

1114
documentation/article.ms Normal file

File diff suppressed because it is too large Load diff

1368
documentation/article.ps Normal file

File diff suppressed because it is too large Load diff

1111
documentation/article.txt Normal file

File diff suppressed because it is too large Load diff

5371
documentation/bash.1 Normal file

File diff suppressed because it is too large Load diff

3959
documentation/bash.ps Normal file

File diff suppressed because it is too large Load diff

3960
documentation/bash.txt Normal file

File diff suppressed because it is too large Load diff

15
documentation/builtins.1 Normal file
View file

@ -0,0 +1,15 @@
.\" This is a hack to force bash builtins into the whatis database
.\" and to get the list of builtins to come up with the man command.
.TH BASH_BUILTINS 1 "1993 September 16" GNU
.SH NAME
bash, :, ., alias, bg, bind, break, builtin, bye, case, cd, command,
continue, declare, dirs, echo, enable, eval, exec, exit, export, fc,
fg, for, getopts, hash, help, history, if, jobs, kill, let, local,
logout, popd, pushd, pwd, read, readonly, return, set, shift, source,
suspend, test, times, trap, type, typeset, ulimit, umask, unalias,
unset, until, wait, while \- bash built-in commands, see \fBbash\fR(1)
.SH BASH BUILTIN COMMANDS
.nr zZ 1
.so bash.1
.SH SEE ALSO
bash(1), sh(1)

1367
documentation/builtins.ps Normal file

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more