Imported from ../bash-1.14.7.tar.gz.
This commit is contained in:
commit
726f63884d
402 changed files with 150297 additions and 0 deletions
1
.distribution
Normal file
1
.distribution
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
1.14
|
||||||
1
.patchlevel
Normal file
1
.patchlevel
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
7
|
||||||
257
COPYING
Normal file
257
COPYING
Normal 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
18
CWRU/PLATFORMS
Normal 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
63
CWRU/POSIX.NOTES
Normal 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
26
CWRU/README
Normal 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
786
CWRU/changelog
Normal 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
20
CWRU/misc/aux-mach-desc
Normal 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
7
CWRU/misc/bison
Executable 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
16
CWRU/misc/open-files.c
Normal 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
7
CWRU/misc/pid.c
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%d\n", getpid());
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
27
CWRU/misc/sigs.c
Normal file
27
CWRU/misc/sigs.c
Normal 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
206
CWRU/misc/sigstat.c
Normal 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<OSTOP) */
|
||||||
|
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
15
CWRU/sh-redir-hack
Normal 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
212
INSTALL
Normal 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
421
MANIFEST
Normal 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
115
Makefile
Normal 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
10
NEWS
Normal 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
52
README
Normal 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
269
RELEASE
Normal 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
535
alias.c
Normal 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
75
alias.h
Normal 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
41
ansi_stdlib.h
Normal 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
36
bashansi.h
Normal 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
390
bashhist.c
Normal 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
42
bashhist.h
Normal 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
1797
bashline.c
Normal file
File diff suppressed because it is too large
Load diff
34
bashtypes.h
Normal file
34
bashtypes.h
Normal 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
166
bracecomp.c
Normal 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
371
braces.c
Normal 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
45
builtins.h
Normal 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
0
builtins/ChangeLog
Normal file
267
builtins/Makefile
Normal file
267
builtins/Makefile
Normal 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
180
builtins/alias.def
Normal 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
136
builtins/bashgetopt.c
Normal 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
37
builtins/bashgetopt.h
Normal 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
219
builtins/bind.def
Normal 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
110
builtins/break.def
Normal 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
67
builtins/builtin.def
Normal 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
689
builtins/cd.def
Normal 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
37
builtins/colon.def
Normal 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
177
builtins/command.def
Normal 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
829
builtins/common.c
Normal 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
69
builtins/common.h
Normal 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
290
builtins/declare.def
Normal 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
168
builtins/echo.def
Normal 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
156
builtins/enable.def
Normal 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
45
builtins/eval.def
Normal 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
163
builtins/exec.def
Normal 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
129
builtins/exit.def
Normal 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
691
builtins/fc.def
Normal 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
145
builtins/fg_bg.def
Normal 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
283
builtins/getopt.c
Normal 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
57
builtins/getopt.h
Normal 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
300
builtins/getopts.def
Normal 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
222
builtins/hash.def
Normal 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
32
builtins/hashcom.h
Normal 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
134
builtins/help.def
Normal 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
179
builtins/history.def
Normal 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
74
builtins/inlib.def
Normal 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
171
builtins/jobs.def
Normal 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
281
builtins/kill.def
Normal 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
77
builtins/let.def
Normal 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
1311
builtins/mkbuiltins.c
Normal file
File diff suppressed because it is too large
Load diff
63
builtins/psize.c
Normal file
63
builtins/psize.c
Normal 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
24
builtins/psize.sh
Executable 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
276
builtins/read.def
Normal 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
154
builtins/reserved.def
Normal 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
57
builtins/return.def
Normal 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
528
builtins/set.def
Normal 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
253
builtins/setattr.def
Normal 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
95
builtins/shift.def
Normal 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
186
builtins/source.def
Normal 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
86
builtins/suspend.def
Normal 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
144
builtins/test.def
Normal 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
89
builtins/times.def
Normal 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
204
builtins/trap.def
Normal 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
325
builtins/type.def
Normal 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
731
builtins/ulimit.def
Normal 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
288
builtins/umask.def
Normal 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
132
builtins/wait.def
Normal 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
215
command.h
Normal 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
186
config.h
Normal 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
194
config.h.mini
Normal 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
8
configure
vendored
Executable 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
305
copy_cmd.c
Normal 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
1553
cpp-Makefile
Normal file
File diff suppressed because it is too large
Load diff
207
dispose_cmd.c
Normal file
207
dispose_cmd.c
Normal 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
32
dispose_cmd.h
Normal 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
795
documentation/FAQ
Normal 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
103
documentation/Makefile
Normal 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
32
documentation/README
Normal 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
1114
documentation/article.ms
Normal file
File diff suppressed because it is too large
Load diff
1368
documentation/article.ps
Normal file
1368
documentation/article.ps
Normal file
File diff suppressed because it is too large
Load diff
1111
documentation/article.txt
Normal file
1111
documentation/article.txt
Normal file
File diff suppressed because it is too large
Load diff
5371
documentation/bash.1
Normal file
5371
documentation/bash.1
Normal file
File diff suppressed because it is too large
Load diff
3959
documentation/bash.ps
Normal file
3959
documentation/bash.ps
Normal file
File diff suppressed because it is too large
Load diff
3960
documentation/bash.txt
Normal file
3960
documentation/bash.txt
Normal file
File diff suppressed because it is too large
Load diff
15
documentation/builtins.1
Normal file
15
documentation/builtins.1
Normal 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
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
Loading…
Add table
Add a link
Reference in a new issue