bash-5.0 distribution sources and documentation

This commit is contained in:
Chet Ramey
2019-01-07 09:27:52 -05:00
parent 6444760999
commit d233b485e8
528 changed files with 84836 additions and 67099 deletions
+31 -433
View File
@@ -43,45 +43,29 @@
<td>A more ksh-compatible 'autoload' (with lazy load).</td>
<td>ksh</td>
</tr>
<tr>
<td>./functions/autoload.v3</td>
<td>An updated ksh-compatible 'autoload'.</td>
<td>ksh</td>
</tr>
<tr>
<td>./functions/basename</td>
<td>A replacement for basename(1).</td>
<td>basename</td>
</tr>
<tr>
<td>./functions/basename2</td>
<td>Fast basename(1) and dirname(1) functions for BASH/SH.</td>
<td>basename, dirname</td>
</tr>
<tr>
<td>./functions/coproc.bash</td>
<td>Start, control, and end coprocesses.</td>
</tr>
<tr>
<td>./functions/coshell.bash</td>
<td>Control shell coprocesses (see coprocess.bash).</td>
</tr>
<tr>
<td>./functions/coshell.README</td>
<td>README for coshell and coproc.</td>
</tr>
<tr>
<td>./functions/csh-compat</td>
<td>A C-shell compatibility package.</td>
<td>csh</td>
</tr>
<tr>
<td>./functions/dirfuncs</td>
<td>Directory manipulation functions from the book 'The Korn Shell'.</td>
</tr>
<tr>
<td>./functions/dirname</td>
<td>A replacement for dirname(1).</td>
<td>dirname</td>
</tr>
<tr>
<td>./functions/emptydir</td>
<td>Find out if a directory is empty.</td>
<td>./functions/dirstack</td>
<td>Directory stack functions.</td>
</tr>
<tr>
<td>./functions/exitstat</td>
@@ -100,18 +84,6 @@
<td>Front end to sync TERM changes to both stty(1) and readline 'bind'.</td>
<td>stty.bash</td>
</tr>
<tr>
<td>./functions/func</td>
<td>Print out definitions for functions named by arguments.</td>
</tr>
<tr>
<td>./functions/gethtml</td>
<td>Get a web page from a remote server (wget(1) in bash!).</td>
</tr>
<tr>
<td>./functions/getoptx.bash</td>
<td>getopt function that parses long-named options.</td>
</tr>
<tr>
<td>./functions/inetaddr</td>
<td>Internet address conversion (inet2hex & hex2inet).</td>
@@ -121,10 +93,6 @@
<td>Return zero if the argument is in the path and executable.</td>
<td>inpath</td>
</tr>
<tr>
<td>./functions/isnum.bash</td>
<td>Test user input on numeric or character value.</td>
</tr>
<tr>
<td>./functions/isnum2</td>
<td>Test user input on numeric values, with floating point.</td>
@@ -133,18 +101,6 @@
<td>./functions/isvalidip</td>
<td>Test user input for valid IP Addresses.</td>
</tr>
<tr>
<td>./functions/jdate.bash</td>
<td>Julian date conversion.</td>
</tr>
<tr>
<td>./functions/jj.bash</td>
<td>Look for running jobs.</td>
</tr>
<tr>
<td>./functions/keep</td>
<td>Try to keep some programs in the foreground and running.</td>
</tr>
<tr>
<td>./functions/ksh-cd</td>
<td>ksh-like 'cd': cd [-LP] [dir [change]].</td>
@@ -164,47 +120,14 @@
<td>./functions/login</td>
<td>Replace the 'login' and 'newgrp' builtins in old Bourne shells.</td>
</tr>
<tr>
<td>./functions/lowercase</td>
<td>Rename files to lower case.</td>
<td>rename lower</td>
</tr>
<tr>
<td>./functions/manpage</td>
<td>Find and print a manual page.</td>
<td>fman</td>
</tr>
<tr>
<td>./functions/mhfold</td>
<td>Print MH folders, useful only because folders(1) doesn't print mod date/times.</td>
</tr>
<tr>
<td>./functions/notify.bash</td>
<td>Notify when jobs change status.</td>
</tr>
<tr>
<td>./functions/pathfuncs</td>
<td>Path related functions (no_path, add_path, pre-path, del_path).</td>
<td>path</td>
</tr>
<tr>
<td>./functions/README</td>
<td>README</td>
</tr>
<tr>
<td>./functions/recurse</td>
<td>Recursive directory traverser.</td>
</tr>
<tr>
<td>./functions/repeat2</td>
<td>A clone of C shell builtin 'repeat'.</td>
<td>repeat, csh</td>
</tr>
<tr>
<td>./functions/repeat3</td>
<td>A clone of C shell builtin 'repeat'.</td>
<td>repeat, csh</td>
</tr>
<tr>
<td>./functions/seq</td>
<td>Generate a sequence from m to n, m defaults to 1.</td>
@@ -237,10 +160,6 @@
<td>A function to emulate the ancient ksh builtin.</td>
<td>ksh</td>
</tr>
<tr>
<td>./functions/term</td>
<td>A shell function to set the terminal type interactively or not.</td>
</tr>
<tr>
<td>./functions/whatis</td>
<td>An implementation of the 10th Edition Unix sh builtin 'whatis(1)' command.</td>
@@ -253,17 +172,6 @@
<td>./functions/which</td>
<td>An emulation of 'which(1)' as it appears in FreeBSD.</td>
</tr>
<tr>
<td>./functions/xalias.bash</td>
<td>Convert csh alias commands to bash functions.</td>
<td>csh, aliasconv</td>
</tr>
<tr>
<td>./functions/xfind.bash</td>
<td>A 'find(1)' clone.</td>
</tr>
<tr>
</tr>
<tr>
<td>./loadables/</td>
<td>Example loadable replacements</td>
@@ -278,27 +186,19 @@
<td>cat(1) replacement with no options - the way cat was intended.</td>
<td>cat, readline pager</td>
</tr>
<tr>
<td>./loadables/cut.c</td>
<td>cut(1) replacement.</td>
</tr>
<tr>
<td>./loadables/dirname.c</td>
<td>Return directory portion of pathname.</td>
<td>dirname</td>
</tr>
<tr>
<td>./loadables/fdflags.c</td>
<td>Display or modify file descriptor flags</td>
</tr>
<tr>
<td>./loadables/finfo.c</td>
<td>Print file info.</td>
</tr>
<tr>
<td>./loadables/getconf.c</td>
<td>POSIX.2 getconf utility.</td>
</tr>
<tr>
<td>./loadables/getconf.h</td>
<td>Replacement definitions for ones the system doesn't provide.</td>
</tr>
<tr>
<td>./loadables/head.c</td>
<td>Copy first part of files.</td>
@@ -323,10 +223,18 @@
<td>./loadables/Makefile.in</td>
<td>Simple makefile for the sample loadable builtins.</td>
</tr>
<tr>
<td>./loadables/Makefile.inc.in</td>
<td>Sample makefile to use for loadable builtin development.</td>
</tr>
<tr>
<td>./loadables/mkdir.c</td>
<td>Make directories.</td>
</tr>
<tr>
<td>./loadables/mypid.c</td>
<td>Demonstrate how a loadable builtin can create and delete shell variables.</td>
</tr>
<tr>
<td>./loadables/necho.c</td>
<td>echo without options or argument interpretation.</td>
@@ -355,14 +263,26 @@
<td>./loadables/realpath.c</td>
<td>Canonicalize pathnames, resolving symlinks.</td>
</tr>
<tr>
<td>./loadables/rm.c</td>
<td>Remove file.</td>
</tr>
<tr>
<td>./loadables/rmdir.c</td>
<td>Remove directory.</td>
</tr>
<tr>
<td>./loadables/setpgid.c</td>
<td>Set a child process's process group.
</tr>
<tr>
<td>./loadables/sleep.c</td>
<td>sleep for fractions of a second.</td>
</tr>
<tr>
<td>./loadables/stat.c</td>
<td>Load an associative array with stat information about a file.</td>
</tr>
<tr>
<td>./loadables/strftime.c</td>
<td>Loadable builtin interface to strftime(3).</td>
@@ -430,221 +350,12 @@
<td>./misc/README</td>
<td>README</td>
</tr>
<tr>
<td>./misc/suncmd.termcap</td>
<td>SunView TERMCAP string.</td>
</tr>
<tr>
</tr>
<tr>
<td>./scripts.noah</td>
<td>Noah Friedman's collection of scripts (updated to bash v2 syntax by Chet Ramey)</td>
</tr>
<tr>
<td>./scripts.noah/aref.bash</td>
<td>Pseudo-arrays and substring indexing examples.</td>
</tr>
<tr>
<td>./scripts.noah/bash.sub.bash</td>
<td>Library functions used by require.bash.</td>
</tr>
<tr>
<td>./scripts.noah/bash_version.bash</td>
<td>A function to slice up $BASH_VERSION.</td>
</tr>
<tr>
<td>./scripts.noah/meta.bash</td>
<td>Enable and disable eight-bit readline input.</td>
</tr>
<tr>
<td>./scripts.noah/mktmp.bash</td>
<td>Make a temporary file with a unique name.</td>
</tr>
<tr>
<td>./scripts.noah/number.bash</td>
<td>A fun hack to translate numerals into English.</td>
</tr>
<tr>
<td>./scripts.noah/PERMISSION</td>
<td>Permissions to use the scripts in this directory.</td>
</tr>
<tr>
<td>./scripts.noah/prompt.bash</td>
<td>A way to set PS1 to some predefined strings.</td>
</tr>
<tr>
<td>./scripts.noah/README</td>
<td>README</td>
</tr>
<tr>
<td>./scripts.noah/remap_keys.bash</td>
<td>A front end to 'bind' to redo readline bindings.</td>
</tr>
<tr>
<td>./scripts.noah/require.bash</td>
<td>Lisp-like require/provide library functions for bash.</td>
</tr>
<tr>
<td>./scripts.noah/send_mail.bash</td>
<td>Replacement SMTP client written in bash.</td>
</tr>
<tr>
<td>./scripts.noah/shcat.bash</td>
<td>Bash replacement for 'cat(1)'.</td>
<td>cat</td>
</tr>
<tr>
<td>./scripts.noah/source.bash</td>
<td>Replacement for source that uses current directory.</td>
</tr>
<tr>
<td>./scripts.noah/string.bash</td>
<td>The string(3) functions at the shell level.</td>
</tr>
<tr>
<td>./scripts.noah/stty.bash</td>
<td>Front-end to stty(1) that changes readline bindings too.</td>
<td>fstty</td>
</tr>
<tr>
<td>./scripts.noah/y_or_n_p.bash</td>
<td>Prompt for a yes/no/quit answer.</td>
<td>ask</td>
</tr>
<tr>
</tr>
<tr>
<td>./scripts.v2</td>
<td>John DuBois' ksh script collection (converted to bash v2 syntax by Chet Ramey).</td>
</tr>
<tr>
<td>./scripts.v2/arc2tarz</td>
<td>Convert an "arc" archive to a compressed tar archive.</td>
</tr>
<tr>
<td>./scripts.v2/bashrand</td>
<td>Random number generator with upper and lower bounds and optional seed.</td>
<td>random</td>
</tr>
<tr>
<td>./scripts.v2/cal2day.bash</td>
<td>Convert a day number to a name.</td>
</tr>
<tr>
<td>./scripts.v2/cdhist.bash</td>
<td>cd replacement with a directory stack added.</td>
</tr>
<tr>
<td>./scripts.v2/corename</td>
<td>Tell what produced a core file.</td>
</tr>
<tr>
<td>./scripts.v2/fman</td>
<td>Fast man(1) replacement.</td>
<td>manpage</td>
</tr>
<tr>
<td>./scripts.v2/frcp</td>
<td>Copy files using ftp(1) but with rcp-type command line syntax.</td>
</tr>
<tr>
<td>./scripts.v2/lowercase</td>
<td>Change filenames to lower case.</td>
<td>rename lower</td>
</tr>
<tr>
<td>./scripts.v2/ncp</td>
<td>A nicer front end for cp(1) (has -i, etc.).</td>
</tr>
<tr>
<td>./scripts.v2/newext</td>
<td>Change the extension of a group of files.</td>
<td>rename</td>
</tr>
<tr>
<td>./scripts.v2/nmv</td>
<td>A nicer front end for mv(1) (has -i, etc.).</td>
<td>rename</td>
</tr>
<tr>
<td>./scripts.v2/pages</td>
<td>Print specified pages from files.</td>
</tr>
<tr>
<td>./scripts.v2/PERMISSION</td>
<td>Permissions to use the scripts in this directory.</td>
</tr>
<tr>
<td>./scripts.v2/pf</td>
<td>A pager front end that handles compressed files.</td>
</tr>
<tr>
<td>./scripts.v2/pmtop</td>
<td>Poor man's 'top(1)' for SunOS 4.x and BSD/OS.</td>
</tr>
<tr>
<td>./scripts.v2/README</td>
<td>README</td>
</tr>
<tr>
<td>./scripts.v2/ren</td>
<td>Rename files by changing parts of filenames that match a pattern.</td>
<td>rename</td>
</tr>
<tr>
<td>./scripts.v2/rename</td>
<td>Change the names of files that match a pattern.</td>
<td>rename</td>
</tr>
<tr>
<td>./scripts.v2/repeat</td>
<td>Execute a command multiple times.</td>
<td>repeat</td>
</tr>
<tr>
<td>./scripts.v2/shprof</td>
<td>Line profiler for bash scripts.</td>
</tr>
<tr>
<td>./scripts.v2/untar</td>
<td>Unarchive a (possibly compressed) tarfile into a directory.</td>
</tr>
<tr>
<td>./scripts.v2/uudec</td>
<td>Carefully uudecode(1) multiple files.</td>
</tr>
<tr>
<td>./scripts.v2/uuenc</td>
<td>uuencode(1) multiple files.</td>
</tr>
<tr>
<td>./scripts.v2/vtree</td>
<td>Print a visual display of a directory tree.</td>
<td>tree</td>
</tr>
<tr>
<td>./scripts.v2/where</td>
<td>Show where commands that match a pattern are.</td>
</tr>
<tr>
</tr>
<tr>
<td>./scripts</td>
<td>Example scripts</td>
</tr>
<tr>
<td>./scripts/adventure.sh</td>
<td>Text adventure game in bash!</td>
</tr>
<tr>
<td>./scripts/bcsh.sh</td>
<td>Bourne shell cshell-emulator.</td>
<td>csh</td>
</tr>
<tr>
<td>./scripts/bash-hexdump.sh</td>
<td>hexdump(1) in bash</td>
<td>hexdump -C, hd</td>
<tr>
<td>./scripts/cat.sh</td>
<td>Readline-based pager.</td>
@@ -654,65 +365,15 @@
<td>./scripts/center</td>
<td>Center - center a group of lines.</td>
</tr>
<tr>
<td>./scripts/dd-ex.sh</td>
<td>Line editor using only /bin/sh, /bin/dd and /bin/rm.</td>
</tr>
<tr>
<td>./scripts/fixfiles.bash</td>
<td>Recurse a tree and fix files containing various "bad" chars.</td>
</tr>
<tr>
<td>./scripts/hanoi.bash</td>
<td>The inevitable Towers of Hanoi in bash.</td>
</tr>
<tr>
<td>./scripts/inpath</td>
<td>Search $PATH for a file the same name as $1; return TRUE if found.</td>
<td>inpath</td>
</tr>
<tr>
<td>./scripts/krand.bash</td>
<td>Produces a random number within integer limits.</td>
<td>random</td>
</tr>
<tr>
<td>./scripts/line-input.bash</td>
<td>Line input routine for GNU Bourne-Again Shell plus terminal-control primitives.</td>
</tr>
<tr>
<td>./scripts/nohup.bash</td>
<td>bash version of 'nohup' command.</td>
</tr>
<tr>
<td>./scripts/precedence</td>
<td>Test relative precedences for '&&' and '||' operators.</td>
</tr>
<tr>
<td>./scripts/randomcard.bash</td>
<td>Print a random card from a card deck.</td>
<td>random</td>
</tr>
<tr>
<td>./scripts/README</td>
<td>README</td>
</tr>
<tr>
<td>./scripts/scrollbar</td>
<td>Display scrolling text.</td>
</tr>
<tr>
<td>./scripts/scrollbar2</td>
<td>Display scrolling text.</td>
</tr>
<tr>
<td>./scripts/self-repro</td>
<td>A self-reproducing script (careful!)</td>
</tr>
<tr>
<td>./scripts/showperm.bash</td>
<td>Convert ls(1) symbolic permissions into octal mode.</td>
</tr>
<tr>
<td>./scripts/shprompt</td>
<td>Display a prompt and get an answer satisfying certain criteria.</td>
@@ -722,37 +383,6 @@
<td>./scripts/spin.bash</td>
<td>Display a 'spinning wheel' to show progress.</td>
</tr>
<tr>
<td>./scripts/timeout</td>
<td>Give rsh(1) a shorter timeout.</td>
</tr>
<tr>
<td>./scripts/timeout2</td>
<td>Execute a given command with a timeout.</td>
</tr>
<tr>
<td>./scripts/timeout3</td>
<td>Execute a given command with a timeout.</td>
</tr>
<tr>
<td>./scripts/vtree2</td>
<td>Display a tree printout of dir in 1k blocks.</td>
<td>tree</td>
</tr>
<tr>
<td>./scripts/vtree3</td>
<td>Display a graphical tree printout of dir.</td>
<td>tree</td>
</tr>
<tr>
<td>./scripts/vtree3a</td>
<td>Display a graphical tree printout of dir.</td>
<td>tree</td>
</tr>
<tr>
<td>./scripts/websrv.sh</td>
<td>A web server in bash!</td>
</tr>
<tr>
<td>./scripts/xterm_title</td>
<td>Print the contents of the xterm title bar.</td>
@@ -793,36 +423,4 @@
</tr>
<tr>
</tr>
<tr>
<td>./startup-files/apple</td>
<td>Example Start-up files for Mac OS X.</td>
</tr>
<tr>
<td>./startup-files/apple/aliases</td>
<td>Sample aliases for Mac OS X.</td>
</tr>
<tr>
<td>./startup-files/apple/bash.defaults</td>
<td>Sample User preferences file.</td>
</tr>
<tr>
<td>./startup-files/apple/environment</td>
<td>Sample Bourne Again Shell environment file.</td>
</tr>
<tr>
<td>./startup-files/apple/login</td>
<td>Sample login wrapper.</td>
</tr>
<tr>
<td>./startup-files/apple/logout</td>
<td>Sample logout wrapper.</td>
</tr>
<tr>
<td>./startup-files/apple/rc</td>
<td>Sample Bourne Again Shell config file.</td>
</tr>
<tr>
<td>./startup-files/apple/README</td>
<td>README</td>
</tr>
</table>
+8 -104
View File
@@ -9,43 +9,25 @@ Path Description X-Ref
./functions/autoload An almost ksh-compatible 'autoload' (no lazy load). ksh
./functions/autoload.v2 An almost ksh-compatible 'autoload' (no lazy load). ksh
./functions/autoload.v3 A more ksh-compatible 'autoload' (with lazy load). ksh
./functions/autoload.v4 An updated ksh-compatible 'autoload'. ksh
./functions/basename A replacement for basename(1). basename
./functions/basename2 Fast basename(1) and dirname(1) functions for BASH/SH. basename, dirname
./functions/coproc.bash Start, control, and end coprocesses.
./functions/coshell.bash Control shell coprocesses (see coprocess.bash).
./functions/coshell.README README for coshell and coproc.
./functions/csh-compat A C-shell compatibility package. csh
./functions/dirfuncs Directory manipulation functions from the book 'The Korn Shell'.
./functions/dirname A replacement for dirname(1). dirname
./functions/emptydir Find out if a directory is empty.
./functions/dirstack Directory stack functions.
./functions/exitstat Display the exit status of processes.
./functions/external Like 'command' but FORCES use of external command.
./functions/fact Recursive factorial function.
./functions/fstty Front end to sync TERM changes to both stty(1) and readline 'bind'. stty.bash
./functions/func Print out definitions for functions named by arguments.
./functions/gethtml Get a web page from a remote server (wget(1) in bash!).
./functions/getoptx.bash getopt function that parses long-named options.
./functions/inetaddr Internet address conversion (inet2hex & hex2inet).
./functions/inpath Return zero if the argument is in the path and executable. inpath
./functions/isnum.bash Test user input on numeric or character value.
./functions/isnum2 Test user input on numeric values, with floating point.
./functions/isvalidip Test user input for valid IP Addresses.
./functions/jdate.bash Julian date conversion.
./functions/jj.bash Look for running jobs.
./functions/keep Try to keep some programs in the foreground and running.
./functions/ksh-cd ksh-like 'cd': cd [-LP] [dir [change]]. ksh
./functions/ksh-compat-test ksh-like arithmetic test replacements. ksh
./functions/kshenv Functions and aliases to provide the beginnings of a ksh environment for bash. ksh
./functions/login Replace the 'login' and 'newgrp' builtins in old Bourne shells.
./functions/lowercase Rename files to lower case. rename lower
./functions/manpage Find and print a manual page. fman
./functions/mhfold Print MH folders, useful only because folders(1) doesn't print mod date/times.
./functions/notify.bash Notify when jobs change status.
./functions/pathfuncs Path related functions (no_path, add_path, pre-path, del_path). path
./functions/README README
./functions/recurse Recursive directory traverser.
./functions/repeat2 A clone of C shell builtin 'repeat'. repeat, csh
./functions/repeat3 A clone of C shell builtin 'repeat'. repeat, csh
./functions/seq Generate a sequence from m to n, m defaults to 1.
./functions/seq2 Generate a sequence from m to n, m defaults to 1.
./functions/shcat Readline-based pager. cat, readline pager
@@ -53,28 +35,25 @@ Path Description X-Ref
./functions/sort-pos-params Sort the positional parameters.
./functions/substr A function to emulate the ancient ksh builtin. ksh
./functions/substr2 A function to emulate the ancient ksh builtin. ksh
./functions/term A shell function to set the terminal type interactively or not.
./functions/whatis An implementation of the 10th Edition Unix sh builtin 'whatis(1)' command.
./functions/whence An almost-ksh compatible 'whence(1)' command.
./functions/which An emulation of 'which(1)' as it appears in FreeBSD.
./functions/xalias.bash Convert csh alias commands to bash functions. csh, aliasconv
./functions/xfind.bash A 'find(1)' clone.
./loadables/ Example loadable replacements
./loadables/basename.c Return non-directory portion of pathname. basename
./loadables/cat.c cat(1) replacement with no options - the way cat was intended. cat, readline pager
./loadables/cut.c cut(1) replacement.
./loadables/dirname.c Return directory portion of pathname. dirname
./loadables/fdflags.c Display or modify file descriptor flags
./loadables/finfo.c Print file info.
./loadables/getconf.c POSIX.2 getconf utility.
./loadables/getconf.h Replacement definitions for ones the system doesn't provide.
./loadables/head.c Copy first part of files.
./loadables/hello.c Obligatory "Hello World" / sample loadable.
./loadables/id.c POSIX.2 user identity.
./loadables/ln.c Make links.
./loadables/logname.c Print login name of current user.
./loadables/Makefile.in Simple makefile for the sample loadable builtins.
./loadables/Makefile.inc.in Sample makefile to use for loadable builtin development.
./loadables/mkdir.c Make directories.
./loadables/mypid.c Demonstrate how a loadable builtin can create and delete shell variables.
./loadables/necho.c echo without options or argument interpretation.
./loadables/pathchk.c Check pathnames for validity and portability.
./loadables/print.c Loadable ksh-93 style print builtin.
@@ -82,8 +61,11 @@ Path Description X-Ref
./loadables/push.c Anyone remember TOPS-20?
./loadables/README README
./loadables/realpath.c Canonicalize pathnames, resolving symlinks.
./loadables/rm.c Remove file.
./loadables/rmdir.c Remove directory.
./loadables/setpgid.c Set a child process's process group.
./loadables/sleep.c sleep for fractions of a second.
./loadables/stat.c Load an associative array with stat information about a file.
./loadables/strftime.c Loadable builtin interface to strftime(3).
./loadables/sync.c Sync the disks by forcing pending filesystem writes to complete.
./loadables/tee.c Duplicate standard input.
@@ -101,83 +83,13 @@ Path Description X-Ref
./misc/aliasconv.sh Convert csh aliases to bash aliases and functions. csh, xalias
./misc/cshtobash Convert csh aliases, environment variables, and variables to bash equivalents. csh, xalias
./misc/README README
./misc/suncmd.termcap SunView TERMCAP string.
./scripts.noah Noah Friedman's collection of scripts (updated to bash v2 syntax by Chet Ramey)
./scripts.noah/aref.bash Pseudo-arrays and substring indexing examples.
./scripts.noah/bash.sub.bash Library functions used by require.bash.
./scripts.noah/bash_version.bash A function to slice up $BASH_VERSION.
./scripts.noah/meta.bash Enable and disable eight-bit readline input.
./scripts.noah/mktmp.bash Make a temporary file with a unique name.
./scripts.noah/number.bash A fun hack to translate numerals into English.
./scripts.noah/PERMISSION Permissions to use the scripts in this directory.
./scripts.noah/prompt.bash A way to set PS1 to some predefined strings.
./scripts.noah/README README
./scripts.noah/remap_keys.bash A front end to 'bind' to redo readline bindings.
./scripts.noah/require.bash Lisp-like require/provide library functions for bash.
./scripts.noah/send_mail.bash Replacement SMTP client written in bash.
./scripts.noah/shcat.bash Bash replacement for 'cat(1)'. cat
./scripts.noah/source.bash Replacement for source that uses current directory.
./scripts.noah/string.bash The string(3) functions at the shell level.
./scripts.noah/stty.bash Front-end to stty(1) that changes readline bindings too. fstty
./scripts.noah/y_or_n_p.bash Prompt for a yes/no/quit answer. ask
./scripts.v2 John DuBois' ksh script collection (converted to bash v2 syntax by Chet Ramey).
./scripts.v2/arc2tarz Convert an "arc" archive to a compressed tar archive.
./scripts.v2/bashrand Random number generator with upper and lower bounds and optional seed. random
./scripts.v2/cal2day.bash Convert a day number to a name.
./scripts.v2/cdhist.bash cd replacement with a directory stack added.
./scripts.v2/corename Tell what produced a core file.
./scripts.v2/fman Fast man(1) replacement. manpage
./scripts.v2/frcp Copy files using ftp(1) but with rcp-type command line syntax.
./scripts.v2/lowercase Change filenames to lower case. rename lower
./scripts.v2/ncp A nicer front end for cp(1) (has -i, etc.).
./scripts.v2/newext Change the extension of a group of files. rename
./scripts.v2/nmv A nicer front end for mv(1) (has -i, etc.). rename
./scripts.v2/pages Print specified pages from files.
./scripts.v2/PERMISSION Permissions to use the scripts in this directory.
./scripts.v2/pf A pager front end that handles compressed files.
./scripts.v2/pmtop Poor man's 'top(1)' for SunOS 4.x and BSD/OS.
./scripts.v2/README README
./scripts.v2/ren Rename files by changing parts of filenames that match a pattern. rename
./scripts.v2/rename Change the names of files that match a pattern. rename
./scripts.v2/repeat Execute a command multiple times. repeat
./scripts.v2/shprof Line profiler for bash scripts.
./scripts.v2/untar Unarchive a (possibly compressed) tarfile into a directory.
./scripts.v2/uudec Carefully uudecode(1) multiple files.
./scripts.v2/uuenc uuencode(1) multiple files.
./scripts.v2/vtree Print a visual display of a directory tree. tree
./scripts.v2/where Show where commands that match a pattern are.
./scripts Example scripts
./scripts/adventure.sh Text adventure game in bash!
./scripts/bash-hexdump.sh hexdump(1) in bash
./scripts/bcsh.sh Bourne shell cshell-emulator. csh
./scripts/cat.sh Readline-based pager. cat, readline pager
./scripts/center Center - center a group of lines.
./scripts/dd-ex.sh Line editor using only /bin/sh, /bin/dd and /bin/rm.
./scripts/fixfiles.bash Recurse a tree and fix files containing various "bad" chars.
./scripts/hanoi.bash The inevitable Towers of Hanoi in bash.
./scripts/inpath Search $PATH for a file the same name as $1; return TRUE if found. inpath
./scripts/krand.bash Produces a random number within integer limits. random
./scripts/line-input.bash Line input routine for GNU Bourne-Again Shell plus terminal-control primitives.
./scripts/nohup.bash bash version of 'nohup' command.
./scripts/precedence Test relative precedences for '&&' and '||' operators.
./scripts/randomcard.bash Print a random card from a card deck. random
./scripts/README README
./scripts/scrollbar Display scrolling text.
./scripts/scrollbar2 Display scrolling text.
./scripts/self-repro A self-reproducing script (careful!)
./scripts/showperm.bash Convert ls(1) symbolic permissions into octal mode.
./scripts/shprompt Display a prompt and get an answer satisfying certain criteria. ask
./scripts/spin.bash Display a 'spinning wheel' to show progress.
./scripts/timeout Give rsh(1) a shorter timeout.
./scripts/timeout2 Execute a given command with a timeout.
./scripts/timeout3 Execute a given command with a timeout.
./scripts/vtree2 Display a tree printout of dir in 1k blocks. tree
./scripts/vtree3 Display a graphical tree printout of dir. tree
./scripts/vtree3a Display a graphical tree printout of dir. tree
./scripts/websrv.sh A web server in bash!
./scripts/xterm_title Print the contents of the xterm title bar.
./scripts/zprintf Emulate printf (obsolete since it's now a bash builtin).
@@ -189,11 +101,3 @@ Path Description X-Ref
./startup-files/Bashrc.bfox Sample Bourne Again SHell init file (Fox).
./startup-files/README README
./startup-files/apple Example Start-up files for Mac OS X.
./startup-files/apple/aliases Sample aliases for Mac OS X.
./startup-files/apple/bash.defaults Sample User preferences file.
./startup-files/apple/environment Sample Bourne Again Shell environment file.
./startup-files/apple/login Sample login wrapper.
./startup-files/apple/logout Sample logout wrapper.
./startup-files/apple/rc Sample Bourne Again Shell config file.
./startup-files/apple/README README
+7
View File
@@ -0,0 +1,7 @@
Master source: https://github.com/scop/bash-completion
This is the latest version of the bash-completion package, which provides
programmable completion specifications for a large number of commands.
If you are a vendor installing bash or preparing a package containing bash,
please install the latest version of bash-completion when installing bash.
Binary file not shown.
+146
View File
@@ -0,0 +1,146 @@
# arrayops.bash --- hide some of the nasty syntax for manipulating bash arrays
# Author: Noah Friedman <friedman@splode.com>
# Created: 2016-07-08
# Public domain
# $Id: arrayops.bash,v 1.3 2016/07/28 15:38:55 friedman Exp $
# Commentary:
# These functions try to tame the syntactic nightmare that is bash array
# syntax, which makes perl's almost look reasonable.
#
# For example the apush function below lets you write:
#
# apush arrayvar newval
#
# instead of
#
# ${arrayvar[${#arrayvar[@]}]}=newval
#
# Because seriously, you've got to be kidding me.
# These functions avoid the use of local variables as much as possible
# (especially wherever modification occurs) because those variable names
# might shadow the array name passed in. Dynamic scope!
# Code:
#:docstring apush:
# Usage: apush arrayname val1 {val2 {...}}
#
# Appends VAL1 and any remaining arguments to the end of the array
# ARRAYNAME as new elements.
#:end docstring:
apush()
{
eval "$1=(\"\${$1[@]}\" \"\${@:2}\")"
}
#:docstring apop:
# Usage: apop arrayname {n}
#
# Removes the last element from ARRAYNAME.
# Optional argument N means remove the last N elements.
#:end docstring:
apop()
{
eval "$1=(\"\${$1[@]:0:\${#$1[@]}-${2-1}}\")"
}
#:docstring aunshift:
# Usage: aunshift arrayname val1 {val2 {...}}
#
# Prepends VAL1 and any remaining arguments to the beginning of the array
# ARRAYNAME as new elements. The new elements will appear in the same order
# as given to this function, rather than inserting them one at a time.
#
# For example:
#
# foo=(a b c)
# aunshift foo 1 2 3
# => foo is now (1 2 3 a b c)
# but
#
# foo=(a b c)
# aunshift foo 1
# aunshift foo 2
# aunshift foo 3
# => foo is now (3 2 1 a b c)
#
#:end docstring:
aunshift()
{
eval "$1=(\"\${@:2}\" \"\${$1[@]}\")"
}
#:docstring ashift:
# Usage: ashift arrayname {n}
#
# Removes the first element from ARRAYNAME.
# Optional argument N means remove the first N elements.
#:end docstring:
ashift()
{
eval "$1=(\"\${$1[@]: -\${#$1[@]}+${2-1}}\")"
}
#:docstring aset:
# Usage: aset arrayname idx newval
#
# Assigns ARRAYNAME[IDX]=NEWVAL
#:end docstring:
aset()
{
eval "$1[\$2]=${@:3}"
}
#:docstring aref:
# Usage: aref arrayname idx {idx2 {...}}
#
# Echoes the value of ARRAYNAME at index IDX to stdout.
# If more than one IDX is specified, each one is echoed.
#
# Unfortunately bash functions cannot return arbitrary values in the usual way.
#:end docstring:
aref()
{
eval local "v=(\"\${$1[@]}\")"
local x
for x in ${@:2} ; do echo "${v[$x]}"; done
}
#:docstring aref:
# Usage: alen arrayname
#
# Echoes the length of the number of elements in ARRAYNAME.
#
# It also returns number as a numeric value, but return values are limited
# by a maximum of 255 so don't rely on this unless you know your arrays are
# relatively small.
#:end docstring:
alen()
{
eval echo "\${#$1[@]}"
eval return "\${#$1[@]}"
}
#:docstring anreverse:
# Usage: anreverse arrayname
#
# Reverse the order of the elements in ARRAYNAME.
# The array variable is altered by this operation.
#:end docstring:
anreverse()
{
eval set $1 "\"\${$1[@]}\""
eval unset $1
while [ $# -gt 1 ]; do
eval "$1=(\"$2\" \"\${$1[@]}\")"
set $1 "${@:3}"
done
}
#provide arrayops
# arrayops.bash ends here
+1 -1
View File
@@ -22,7 +22,7 @@
#
# Declare a function ($1) to be autoloaded from a file ($2) when it is first
# called. This defines a `temporary' function that will `.' the file
# containg the real function definition, then execute that new definition with
# containing the real function definition, then execute that new definition with
# the arguments given to this `fake' function. The autoload function defined
# by the file and the file itself *must* be named identically.
#
+556
View File
@@ -0,0 +1,556 @@
## -*- sh -*-
# The psuedo-ksh autoloader.
# How to use:
# o One function per file.
# o File and function name match exactly.
# o File is located in a directory that is in FPATH.
# o This script (autoload) must be sourced in as early as possible. This
# implies that any code in this script should NOT rely on any library of local
# or self-defined functions having already been loaded.
# o autoload must be called for each function before the function can be used. If
# autoloads are in directories where there are nothing but autoloads, then
# 'autoload /path/to/files/*' suffices (but see options -a and -f).
# o The call must be made in the current environment, not a subshell.
# o The command line suffices as "current environment". If you have autoload
# calls in a script, that script must be dotted into the process.
# The first cut of this was by Bill Trost, trost@reed.bitnet.
# The second cut came from Chet Ramey, chet@ins.CWRU.Edu
# The third cut came from Mark Kennedy, mtk@ny.ubs.com. 1998/08/25
# The fourth cut came from Matthew Persico, matthew.persico@gmail.com 2017/August
autoload_calc_shimsize ()
{
echo $((AUTOLOAD_SHIM_OVERHEAD + 3 * ${#1}))
}
_autoload_split_fpath ()
{
(IFS=':'; set -- ${FPATH}; echo "$@")
}
_aload()
{
local opt OPTIND
local doexport=0
local doreload=0
local doverbose=0
local doevalshim=0
local loadthese
local optimize=0
local loaded=0
local exported=0
local optimized=0
local summary=0
local dofpath=0
while getopts xrvla:oyf opt; do
case $opt in
x) doexport=1;;
r) doreload=1;;
v) doverbose=1;;
l) doevalshim=1;;
a) loadthese=$(find $OPTARG -maxdepth 1 -type f -printf '%f ');;
o) optimize=1;;
y) summary=1;;
f) loadthese=$(find $(_autoload_split_fpath) -maxdepth 1 -type f -printf '%f ');;
*) echo "_aload: usage: _aload [-xrvlyf] [-a dir] [function ...]" >&2; return;;
esac
done
shift $(($OPTIND-1))
[ -z "$loadthese" ] && loadthese="$@"
local func
for func in $loadthese; do
local exists_fn
exists_fn=$(declare -F $func)
if [ -n "$exists_fn" ] && ((doreload==0)) && ((doevalshim==0))
then
if ((doverbose))
then
echo "autoload: function '$func' already exists"
fi
else
local andevaled=''
local andexported=''
local evalstat=0
local doshim=1
local funcfile
funcfile=$(_autoload_resolve $func)
if [[ $funcfile ]] ; then
## The file was found for $func. Process it.
if ((optimize)); then
## For the first function loaded, we will not know
## AUTOLOAD_SHIM_OVERHEAD. We can only calculate it after
## we have loaded one function.
if [[ $AUTOLOAD_SHIM_OVERHEAD ]]; then
local size=$(wc -c $funcfile| sed 's/ .*//')
local shimsize=$(autoload_calc_shimsize $func)
if (( size <= shimsize)); then
doshim=0
andevaled=', optimized'
((optimized+=1))
fi
fi
fi
if ((doevalshim)); then
doshim=0
andevaled=', evaled'
fi
## 'brand' as in branding a cow with a mark. We add a local
## variable to each function we autoload so that we can tell
## later on it is an autoloaded function without having to
## maintain some bash array or hash that cannot be passed to
## and used by subshells.
local brandtext
brandtext="eval \"\$(type $func | sed -e 1d -e 4ilocal\\ AUTOLOADED=\'$func\')\""
if ((doshim)); then
## Don't bother trying to save space by shoving all the
## eval text below onto one unreadable line; new lines will
## be added at your semicolons and any indentation below
## seems to be ignored anyway if you export the function;
## look at its BASH_FUNCTION representation.
eval $func '()
{
local IS_SHIM="$func"
local file=$(_autoload_resolve '$func')
if [[ $file ]]
then
. $file
'$brandtext'
'$func' "$@"
return $?
else
return 1;
fi
}'
else
. $funcfile
eval "$brandtext"
fi
evalstat=$?
if((evalstat==0))
then
((loaded+=1))
((doexport)) && export -f $func && andexported=', exported' && ((exported+=1))
((doverbose)) && echo "$func autoloaded${andexported}${andevaled}"
if [[ ! $AUTOLOAD_SHIM_OVERHEAD ]] && ((doshim)); then
## ...we have just loaded the first function shim into
## memory. Let's calc the AUTOLOAD_SHIM_OVERHEAD size
## to use going forward. In theory, we could check
## again here to see if we should optimize and source
## in this function, now that we now the
## AUTOLOAD_SHIM_OVERHEAD. In practice, it's not worth
## duping that code or creating a function to do so for
## one function.
AUTOLOAD_SHIM_OVERHEAD=$(type $func | grep -v -E "^$1 is a function" | sed "s/$func//g"| wc -c)
export AUTOLOAD_SHIM_OVERHEAD
fi
else
echo "$func failed to load" >&2
fi
fi
fi
done
((summary)) && echo "autoload: loaded:$loaded exported:$exported optimized:$optimized overhead:$AUTOLOAD_SHIM_OVERHEAD bytes"
}
_autoload_dump()
{
local opt OPTIND
local opt_p=''
local opt_s=''
while getopts ps opt
do
case $opt in
p ) opt_p=1;;
s ) opt_s=1;;
esac
done
shift $(($OPTIND-1))
local exported=''
local executed=''
local func
for func in $(declare | grep -E 'local\\{0,1} AUTOLOADED' | sed -e "s/.*AUTOLOADED=//" -e 's/\\//g' -e 's/[");]//g' -e "s/'//g")
do
if [ -n "$opt_p" ]; then echo -n "autoload "; fi
if [ -n "$opt_s" ]
then
exported=$(declare -F | grep -E "${func}$" | sed 's/declare -f\(x\{0,1\}\).*/\1/')
[ "$exported" = 'x' ] && exported=' exported' || exported=' not exported'
executed=$(type $func | grep 'local IS_SHIM')
[ -z "$executed" ] && executed=' executed' || executed=' not executed'
fi
echo "${func}${exported}${executed}"
done
}
_autoload_resolve()
{
if [[ ! "$FPATH" ]]; then
echo "autoload: FPATH not set or null" >&2
return
fi
local p # for 'path'. The $() commands in the for loop split the FPATH
# string into its constituents so that each one may be processed.
for p in $( _autoload_split_fpath ); do
p=${p:-.}
if [ -f $p/$1 ]; then echo $p/$1; return; fi
done
echo "autoload: $1: function source file not found" >&2
}
_autoload_edit()
{
[ -z "$EDITOR" ] && echo "Error: no EDITOR defined" && return 1
local toedit
local func
for func in "$@"
do
local file=$(_autoload_resolve $func)
if [[ $file ]]
then
toedit="$toedit $file"
else
echo "$funcname not found in FPATH funcfile. Skipping."
fi
done
[ -z "$toedit" ] && return 1
local timemarker=$(mktemp)
$EDITOR $toedit
local i
for i in $toedit
do
if [ $i -nt $timemarker ]
then
local f=$(basename $i)
echo Reloading $f
autoload -r $f
fi
done
}
_autoload_page()
{
[ -z "$PAGER" ] && echo "Error: no PAGER defined" && return 1
local topage
local func
for func in "$@"
do
local file=$(_autoload_resolve $func)
if [[ $file ]]
then
topage="$topage $file"
else
echo "$funcname not found in FPATH funcfile. Skipping."
fi
done
[ -z "$topage" ] && return 1
$PAGER $topage
}
_autoload_remove()
{
unset -f "$@"
}
_autoload_help()
{
cat <<EOH
NAME
autoload
SYNOPSIS
autoload [-ps]
autoload [-xuremloyv] [function ...]
autoload -a directory [-oyv]
autoload -f [-oyv]
autoload [-h]
autoreload [function ...]
DESCRIPTION
An implementation of the 'autoload' functionality built into other
shells, of which 'ksh' is the most prominent. It allows for a keeping
the process environment small by loading small 'shim' functions into
memory that will, on first call, load the full text of the given
function and run it. Subsequent calls to the function just run the
function.
'autoreload' is a synonym for 'autoload -r'. See below.
USAGE
o Each function to be autoloaded should be defined in a single file,
named exactly the same as the function.
o In order to avoid side effects, do NOT put code other than the
function definition in the file. Unless of course you want to do some
one-time initialization. But beware that if you reload the function
for any reason, you will rerun the initialization code. Make sure
your initialization is re-entrant. Or, better yet,
*** do NOT put code other than the function definition in the file ***
o These function definition files should be placed in a directory that
is in the FPATH environment variable. Subdirectories are NOT scanned.
o The autoload script should be sourced into the current process as
early as possible in process start up. See NOTES below for
suggestions.
o The calls to the autoload function must be made in the current
process. If your calls are in their own script, that script must be
sourced in. Command line invocations are also sufficient. (But see
'-l' below.)
o The first time the function is called, the shim function that was
created by the 'autoload' call is what is executed. This function
then goes and finds the appropriate file in FPATH, sources it in and
then calls the actual function with any arguments you just passed in
to the shim function. Subsequent calls just run the function.
OPTIONS
-a Autoload (a)ll the functions found in the given directory.
-f Autoload all the functions found in all the directories on the
FPATH.
-p Print all the autoloaded functions.
-s Print all the autoloaded functions and add their export status.
-x Export the specified functions to the environment for use in
subshells.
-u Unset the function, so it can be reloaded.
-r Reload the shims of the specified functions, even if the functions
have been already been executed. This will allow you to modify the
functions' source and have the new version executed next time the
function is called.
It would be very easy to modify a function's script, run the
function and scratch your head for a long time trying to figure out
why your changes are not being executed. That's why we provide the
'-e' flag described below for modifications.
Reloads, of course, only apply in the context of the current session
and any future subshell you start from the current session. Existing
sessions will need to have the same 'autoload -r' command run in
them.
-e Find the scripts in which the specified functions are defined and
start up \$EDITOR on those scripts. Reload the ones that were
modified when you exit \$EDITOR. (Note: If you use 'autoload -e foo'
to edit function 'foo', and then in your editor you separately load
up function 'bar', 'autoload' has no way of knowing that you edited
'bar' and will NOT reload 'bar' for you.)
Reloads, of course, only apply in the context of the current session
and any future subshell you start from the current session. Existing
sessions will need to have the same 'autoload -r' command run in
them.
-m Find the scripts in which the specified functions are defined and
run \$PAGER on them ('m' is for 'more', because 'p' (page) and 'l'
(load) are already used as options in 'autoload').
-l When autoloading a function, eval the shim immediately in order to
load the true function code. See "Using '-l'" in the NOTES below for
details.
-o Optimize. When autoloading, take the time to execute
'theCharCount=\$(wc -c \$theFuncFile)'
for each funcion and
if \$theCharCount < \$AUTOLOAD_SHIM_OVERHEAD
don't shim it, just eval directly.
-y Summar(y). Print the number of loaded, exported and optimized
functions.
-v Turns up the chattiness.
NOTES
o Calling 'autoload' on a function that already exists (either shimmed
or expanded) silently ignores the request to load the shim unless it
has been previously removed (-u) or you force the reload (-r).
o Changing and reloading a function that has been exported does not
require it be re-exported; the modifications will appear in
subsequent subshells.
o Using '-1'
If you are running under set -x and/or set -v, you may see that the
shim does not appear to "work"; instead of seeing the shim first and
the real code subsequently, you may see the shim evaluated multiple
times.
This may not be an error; review your code. What is most likely
happening is that you are calling the function in subshells via
backticks or $(), or in a script that is not being sourced into the
current environment. If you have not previously called the function
in question at your command line or in a script that was sourced into
the current envirnoment, then the various subshells are going to
encounter the shim and replace with the real code before executing.
Remember, however, that environment modifications that occur in a
subshell are NOT propagated back to the calling shell or over to any
sibling shells. So, if you call an autoloaded function in a very
tight loop of very many subshells, you may want to make an 'autoload
-l' call before you start your loop. '-l' will instruct 'autoload' to
bypass the shim creation and just source in the function's file
directly. For a few calls, the overhead of repeatedly running the
shim is not expensive, but in a tight loop, it might be. Caveat
Programer.
o Although the number of functions in the environment does not change
by using 'autoload', the amount of memory they take up can be greatly
reduced, depending on the size of your functions. If you have a lot
of small functions, then it is possible that the shim text will be
larger than your actual functions, rendering the memory savings moot.
'small' in this case can be determined by calling the function
'autoload_calc_shimsize' with the name of the function to determine
its shim size.
o In order to support the -p and -s options, we need a way to determine
if a function 'func' has been autoloaded or if it was loaded
diredctly. In order to do that, we modify the function's code by
adding the text
local AUTOLOADED='func';
to the shim and to the actual function text, just after the opening
brace. Then supporting -p and -s is just a matter of grepping through
all the function text in memory. Even though grepping through the
environment may not be the most efficient way to support this, it is
the simplest to implement for -p and -s operations that are not
heavily used.
As a consquence of this (and other reasons), the AUTOLOAD* namespace
is reserved for autoloading. Make sure you check any functions that
you bring under autoload for use of variables or functions that start
with AUTOLOAD and change them.
o The easiest way to load shims for all functions on the FPATH is to run
autoload -f -x
in the profile that gets run for login shells.
When called in the profile of a login shell where no definitions
exist, -f will load all functions it can find on FPATH and -x will
export all of those functions to be available in subshells when this
is called in a login shell. Using this option will relieve you of the
need to call 'autoload' after Every Single Function Definition, nor
will you need to call it in subshells.
The only thing left to do is to load up the autoload function itself
and its helper functions. That needs to happen in your profile:
export FPATH=~/functions # or wherever you stash them
if [ -z $(declare -F autoload) ]
then
. ~/bin/autoload # or wherever you've put it
fi
The 'if' statement is used to make sure we don't reload autoload
needlessly. Sourcing in the autoload script loads the 'autoload'
function and all of its support functions. Additionally, we export
all of these functions so that they are available in subshells; you
do not have to re-source the autoload file in '.bashrc'.
o Even with all of these shenanigans, you will find cases where no
matter how hard you try, your autoloaded functions will be
unavailable to you, even if you run 'autoload -x -f'. The typical
condition for this is starting up not a subshell, but a brand new
DIFFERENT shell. And the typical example of this is git extentions.
At the time of this writing, git extentions work by taking a command
'git foo' and looking for a file 'git-foo' on the path. 'git' then
executes 'git-foo' in a new shell - it executes your command in
/bin/sh. That's not a subshell of your process. It will not get your
exported shell functions. Ballgame over.
If you find that you want your functions to be available in such
circumstances, convert them back to plain old scripts, make sure they
are 'sh' compliant and take the read/parse hit every time they are
run.
EOH
}
autoload()
{
if (( $# == 0 )) ; then _autoload_dump; return; fi
local opt OPTIND OPTARG
local passthru
local dumpopt
while getopts psuema:yxrvlohf opt
do
case $opt in
p|s) dumpopt="$dumpopt -${opt}";;
u) shift $((OPTIND-1)); _autoload_remove "$@"; return;;
e) shift $((OPTIND-1)); _autoload_edit "$@"; return;;
m) shift $((OPTIND-1)); _autoload_page "$@"; return;;
x|r|v|l|y|f|o) passthru="$passthru -$opt";;
a) passthru="$passthru -$opt $OPTARG";;
h) _autoload_help; return;;
*) echo "autoload: usage: autoload [-puUx] [function ...]" >&2; return;;
esac
done
shift $(($OPTIND-1))
if [ -n "$dumpopt" ]
then
_autoload_dump $dumpopt
else
_aload $passthru "$@"
fi
}
autoreload ()
{
autoload -r "$@"
}
## When we source in autoload, we export (but NOT autoload) the autoload
## functions so that they are available in subshells and you don't have to
## source in the autoload file in subshells.
export -f _aload \
_autoload_dump \
_autoload_edit \
_autoload_help \
_autoload_page \
_autoload_resolve \
_autoload_split_fpath \
autoload \
autoload_calc_shimsize \
autoreload
+184
View File
@@ -0,0 +1,184 @@
#!/bin/bash
workdir=$(mktemp -d)
cp autoload $workdir
cd $workdir
pwd
. ./autoload
funclist='ALTEST_func1 ALTEST_funcexport ALTEST_funcu'
for funcname in $funclist; do
cat <<EOFFUNC > $funcname
$funcname ()
{
echo this is $funcname
}
EOFFUNC
done
export FPATH=$workdir
autoload ALTEST_func1 ALTEST_funcu
autoload -x ALTEST_funcexport
ok=0
failed=0
for funcname in $funclist; do
testname="$funcname loaded"
got=$(type $funcname 2>&1)
if [[ $got =~ "$funcname: not found" ]]; then
echo "## Failed $testname"
((failed+=1))
else
echo "ok - $testname"
((ok+=1))
testname="$funcname is a shim"
if [[ ! $got =~ "IS_SHIM" ]]; then
echo "## Failed $testname"
((failed+=1))
else
echo "ok - $testname"
((ok+=1))
testname="$funcname shim executed"
$funcname > /dev/null
got=$(type $funcname 2>&1)
if [[ $got =~ "IS_SHIM" ]]; then
echo "## Failed $testname"
((failed+=1))
else
echo "ok - $testname"
((ok+=1))
fi
fi
fi
done
funcname=ALTEST_func1
testname="$funcname shim reloaded"
autoload -r $funcname
got=$(type $funcname 2>&1)
if [[ ! $got =~ "IS_SHIM" ]]; then
echo "## Failed $testname"
((failed+=1))
else
echo "ok - $testname"
((ok+=1))
fi
funcname=ALTEST_funcu
testname="$funcname shim unloaded"
autoload -u $funcname
got=$(type $funcname 2>&1)
if [[ ! $got =~ "$funcname: not found" ]]; then
echo "## Failed $testname"
((failed+=1))
else
echo "ok - $testname"
((ok+=1))
fi
testname="autoload -p"
got=$(autoload -p | grep ALTEST)
if [[ ! $got =~ "autoload ALTEST_func1" ]] || \
[[ ! $got =~ "autoload ALTEST_funcexport" ]] ; then
echo "## Failed $testname"
((failed+=1))
else
echo "ok - $testname"
((ok+=1))
fi
testname="autoload -s"
echo "Executing $testname, could take a long time..."
got=$(autoload -s | grep ALTEST)
if [[ ! $got =~ "ALTEST_func1 not exported not executed" ]] || \
[[ ! $got =~ "ALTEST_funcexport exported executed" ]] ; then
echo "## Failed $testname"
echo "## got: $got"
((failed+=1))
else
echo "ok - $testname"
((ok+=1))
fi
testname="autoload -r -a $FPATH"
autoload -r -a $FPATH
localfailed=0
localok=0
for funcname in $funclist; do
got=$(type $funcname 2>&1)
if [[ $got =~ "$funcname: not found" ]]; then
echo "## Failed $testname - $funcname"
((localfailed+=1))
else
((localok+=1))
if [[ ! $got =~ "IS_SHIM" ]]; then
((localfailed+=1))
else
((localok+=1))
fi
fi
done
if ((localfailed==0)); then
echo "ok - $testname"
((ok+=1))
else
((failed+=1))
fi
testname="autoload -u $funclist"
autoload -u $funclist
localfailed=0
localok=0
for funcname in $funclist; do
got=$(type $funcname 2>&1)
if [[ ! $got =~ "$funcname: not found" ]]; then
echo "## Failed $testname - $funcname"
((localfailed+=1))
else
((localok+=1))
fi
done
if ((localfailed==0)); then
echo "ok - $testname"
((ok+=1))
else
((failed+=1))
fi
testname="autoload -r -f"
autoload -r -f
localfailed=0
localok=0
for funcname in $funclist; do
got=$(type $funcname 2>&1)
if [[ $got =~ "$funcname: not found" ]]; then
echo "## Failed $testname - $funcname"
((localfailed+=1))
else
((localok+=1))
if [[ ! $got =~ "IS_SHIM" ]]; then
((localfailed+=1))
else
((localok+=1))
fi
fi
done
if ((localfailed==0)); then
echo "ok - $testname"
((ok+=1))
else
((failed+=1))
fi
echo $ok passed, $failed failed
exit $failed
+20 -5
View File
@@ -100,10 +100,10 @@ INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins -I${srcdir} \
$(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $<
ALLPROG = print truefalse sleep finfo logname basename dirname \
ALLPROG = print truefalse sleep finfo logname basename dirname fdflags \
tty pathchk tee head mkdir rmdir printenv id whoami \
uname sync push ln unlink realpath strftime mypid setpgid
OTHERPROG = necho hello cat pushd
uname sync push ln unlink realpath strftime mypid setpgid seq
OTHERPROG = necho hello cat pushd stat rm
all: $(SHOBJ_STATUS)
@@ -142,6 +142,15 @@ finfo: finfo.o
cat: cat.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS)
rm: rm.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rm.o $(SHOBJ_LIBS)
fdflags: fdflags.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ fdflags.o $(SHOBJ_LIBS)
seq: seq.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ seq.o $(SHOBJ_LIBS)
logname: logname.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS)
@@ -202,10 +211,12 @@ strftime: strftime.o
mypid: mypid.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mypid.o $(SHOBJ_LIBS)
setpgid: setpgid.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ setpgid.o $(SHOBJ_LIBS)
stat: stat.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ stat.o $(SHOBJ_LIBS)
# pushd is a special case. We use the same source that the builtin version
# uses, with special compilation options.
#
@@ -236,6 +247,7 @@ installdirs:
install-dev: installdirs
@$(INSTALL_DATA) Makefile.inc $(DESTDIR)$(loadablesdir)/Makefile.inc
@$(INSTALL_DATA) $(srcdir)/loadables.h $(DESTDIR)$(loadablesdir)/loadables.h
@( cd $(BUILD_DIR) && ${MAKE} ${MFLAGS} DESTDIR="$(DESTDIR)" install-headers)
install-supported: all installdirs install-dev
@@ -246,7 +258,7 @@ install-supported: all installdirs install-dev
done
uninstall-dev:
-$(RM) $(DESTDIR)$(loadablesdir)/Makefile.inc
-$(RM) $(DESTDIR)$(loadablesdir)/Makefile.inc $(DESTDIR)$(loadablesdir)/loadables.h
-( cd $(BUILD_DIR) && ${MAKE} ${MFLAGS} DESTDIR="$(DESTDIR)" uninstall-headers)
uninstall-supported: uninstall-dev
@@ -283,3 +295,6 @@ mkdir.o: mkdir.c
realpath.o: realpath.c
strftime.o: strftime.c
setpgid.o: setpgid.c
stat.o: stat.c
fdflags.o: fdflags.c
seq.o: seq.c
+14 -3
View File
@@ -32,28 +32,39 @@ the canonical example. There is no real `builtin writers' programming
guide'. The file template.c provides a template to use for creating
new loadable builtins.
The file "Makefile.inc" is created using the same values that configure
writes into Makefile.in, and is installed in the same directory as the
rest of the example builtins. It's intended to be a start at something
that can be modified or included to help you build your own loadables
without having to search for the right CFLAGS and LDFLAGS.
basename.c Return non-directory portion of pathname.
cat.c cat(1) replacement with no options - the way cat was intended.
dirname.c Return directory portion of pathname.
fdflags.c Change the flag associated with one of bash's open file desriptors.
finfo.c Print file info.
head.c Copy first part of files.
hello.c Obligatory "Hello World" / sample loadable.
id.c POSIX.2 user identity.
ln.c Make links.
loadables.h Start at a file loadable builtins can include for shell definitions
loadables.h File loadable builtins can include for shell definitions.
logname.c Print login name of current user.
Makefile.in Simple makefile for the sample loadable builtins.
Makefile.inc.in Sample makefile to use for loadable builtin development.
mkdir.c Make directories.
mypid.c Add $MYPID variable, demonstrate use of unload hook function
mypid.c Add $MYPID variable, demonstrate use of unload hook functio.n
necho.c echo without options or argument interpretation.
pathchk.c Check pathnames for validity and portability.
print.c Loadable ksh-93 style print builtin.
printenv.c Minimal builtin clone of BSD printenv(1).
push.c Anyone remember TOPS-20?
README README
realpath.c Canonicalize pathnames, resolving symlinks.
rm.c Remove files and directories.
rmdir.c Remove directory.
seq.c Print a sequence of decimal or floating point numbers.
setpgid.c Set a process's pgrp; example of how to wrap a system call.
sleep.c sleep for fractions of a second.
stat.c populate an associative array with information about a file
strftime.c Loadable builtin interface to strftime(3).
sync.c Sync the disks by forcing pending filesystem writes to complete.
tee.c Duplicate standard input.
+2
View File
@@ -30,6 +30,7 @@
#include "builtins.h"
#include "shell.h"
#include "common.h"
#include "bashgetopt.h"
int
basename_builtin (list)
@@ -46,6 +47,7 @@ basename_builtin (list)
if (no_options (list))
return (EX_USAGE);
list = loptend;
string = list->word->word;
suffix = (char *)NULL;
+2
View File
@@ -56,6 +56,7 @@ int fd;
return 0;
}
int
cat_main (argc, argv)
int argc;
char **argv;
@@ -88,6 +89,7 @@ char **argv;
return (r);
}
int
cat_builtin(list)
WORD_LIST *list;
{
+5 -3
View File
@@ -30,6 +30,7 @@
#include "builtins.h"
#include "shell.h"
#include "common.h"
#include "bashgetopt.h"
int
dirname_builtin (list)
@@ -38,15 +39,16 @@ dirname_builtin (list)
int slen;
char *string;
if (no_options (list))
return (EX_USAGE);
list = loptend;
if (list == 0 || list->next)
{
builtin_usage ();
return (EX_USAGE);
}
if (no_options (list))
return (EX_USAGE);
string = list->word->word;
slen = strlen (string);
+336
View File
@@ -0,0 +1,336 @@
/* Loadable builtin to get and set file descriptor flags. */
/* See Makefile for compilation details. */
/*
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <fcntl.h>
#include <errno.h>
#include "bashansi.h"
#include <stdio.h>
#include "loadables.h"
static const struct
{
const char *name;
int value;
} file_flags[] =
{
#ifdef O_APPEND
{ "append", O_APPEND },
#endif
#ifdef O_ASYNC
{ "async", O_ASYNC },
#endif
#ifdef O_SYNC
{ "sync", O_SYNC },
#endif
#ifdef O_NONBLOCK
{ "nonblock", O_NONBLOCK },
#endif
#ifdef O_FSYNC
{ "fsync", O_FSYNC },
#endif
#ifdef O_DSYNC
{ "dsync", O_DSYNC },
#endif
#ifdef O_RSYNC
{ "rsync", O_RSYNC },
#endif
#ifdef O_ALT_IO
{ "altio", O_ALT_IO },
#endif
#ifdef O_DIRECT
{ "direct", O_DIRECT },
#endif
#ifdef O_NOATIME
{ "noatime", O_NOATIME },
#endif
#ifdef O_NOSIGPIPE
{ "nosigpipe", O_NOSIGPIPE },
#endif
#ifdef O_CLOEXEC
{ "cloexec", O_CLOEXEC },
#endif
};
#define N_FLAGS (sizeof (file_flags) / sizeof (file_flags[0]))
#ifndef errno
extern int errno;
#endif
/* FIX THIS */
static int
getallflags ()
{
int i, allflags;
for (i = allflags = 0; i < N_FLAGS; i++)
allflags |= file_flags[i].value;
return allflags;
}
static int
getflags(int fd, int p)
{
int c, f;
int allflags;
if ((c = fcntl(fd, F_GETFD)) == -1)
{
if (p)
builtin_error("can't get status for fd %d: %s", fd, strerror(errno));
return -1;
}
if ((f = fcntl(fd, F_GETFL)) == -1)
{
if (p)
builtin_error("Can't get flags for fd %d: %s", fd, strerror(errno));
return -1;
}
if (c)
f |= O_CLOEXEC;
return f & getallflags();
}
static void
printone(int fd, int p, int verbose)
{
int f;
size_t i;
if ((f = getflags(fd, p)) == -1)
return;
printf ("%d:", fd);
for (i = 0; i < N_FLAGS; i++)
{
if (f & file_flags[i].value)
{
printf ("%s%s", verbose ? "+" : "", file_flags[i].name);
f &= ~file_flags[i].value;
}
else if (verbose)
printf ( "-%s", file_flags[i].name);
else
continue;
if (f || (verbose && i != N_FLAGS - 1))
putchar (',');
}
printf ("\n");
}
static int
parseflags(char *s, int *p, int *n)
{
int f, *v;
size_t i;
f = 0;
*p = *n = 0;
for (s = strtok(s, ","); s; s = strtok(NULL, ","))
{
switch (*s)
{
case '+':
v = p;
s++;
break;
case '-':
v = n;
s++;
break;
default:
v = &f;
break;
}
for (i = 0; i < N_FLAGS; i++)
if (strcmp(s, file_flags[i].name) == 0)
{
*v |= file_flags[i].value;
break;
}
if (i == N_FLAGS)
builtin_error("invalid flag `%s'", s);
}
return f;
}
static void
setone(int fd, char *v, int verbose)
{
int f, n, pos, neg, cloexec;
f = getflags(fd, 1);
if (f == -1)
return;
parseflags(v, &pos, &neg);
cloexec = -1;
if ((pos & O_CLOEXEC) && (f & O_CLOEXEC) == 0)
cloexec = FD_CLOEXEC;
if ((neg & O_CLOEXEC) && (f & O_CLOEXEC))
cloexec = 0;
if (cloexec != -1 && fcntl(fd, F_SETFD, cloexec) == -1)
builtin_error("can't set status for fd %d: %s", fd, strerror(errno));
pos &= ~O_CLOEXEC;
neg &= ~O_CLOEXEC;
f &= ~O_CLOEXEC;
n = f;
n |= pos;
n &= ~neg;
if (n != f && fcntl(fd, F_SETFL, n) == -1)
builtin_error("can't set flags for fd %d: %s", fd, strerror(errno));
}
static int
getmaxfd ()
{
int maxfd, ignore;
#ifdef F_MAXFD
maxfd = fcntl (0, F_MAXFD);
if (maxfd > 0)
return maxfd;
#endif
maxfd = getdtablesize ();
if (maxfd <= 0)
maxfd = HIGH_FD_MAX;
for (maxfd--; maxfd > 0; maxfd--)
if (fcntl (maxfd, F_GETFD, &ignore) != -1)
break;
return maxfd;
}
int
fdflags_builtin (WORD_LIST *list)
{
int opt, maxfd, i, num, verbose, setflag;
char *setspec;
WORD_LIST *l;
intmax_t inum;
setflag = verbose = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "s:v")) != -1)
{
switch (opt)
{
case 's':
setflag = 1;
setspec = list_optarg;
break;
case 'v':
verbose = 1;
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
/* Maybe we could provide some default here, but we don't yet. */
if (list == 0 && setflag)
return (EXECUTION_SUCCESS);
if (list == 0)
{
maxfd = getmaxfd ();
if (maxfd < 0)
{
builtin_error ("can't get max fd: %s", strerror (errno));
return (EXECUTION_FAILURE);
}
for (i = 0; i < maxfd; i++)
printone (i, 0, verbose);
return (EXECUTION_SUCCESS);
}
opt = EXECUTION_SUCCESS;
for (l = list; l; l = l->next)
{
if (legal_number (l->word->word, &inum) == 0 || inum < 0)
{
builtin_error ("%s: invalid file descriptor", l->word->word);
opt = EXECUTION_FAILURE;
continue;
}
num = inum; /* truncate to int */
if (setflag)
setone (num, setspec, verbose);
else
printone (num, 1, verbose);
}
return (opt);
}
char *fdflags_doc[] =
{
"Display and modify file descriptor flags.",
"",
"Display or, if the -s option is supplied, set flags for each file",
"descriptor supplied as an argument. If the -v option is supplied,",
"the display is verbose, including each settable option name in the",
"form of a string such as that accepted by the -s option.",
"",
"The -s option accepts a string with a list of flag names, each preceded",
"by a `+' (set) or `-' (unset). Those changes are applied to each file",
"descriptor supplied as an argument.",
"",
"If no file descriptor arguments are supplied, the displayed information",
"consists of the status of flags for each of the shell's open files.",
(char *)NULL
};
/* The standard structure describing a builtin command. bash keeps an array
of these structures. The flags must include BUILTIN_ENABLED so the
builtin can be used. */
struct builtin fdflags_struct = {
"fdflags", /* builtin name */
fdflags_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
fdflags_doc, /* array of long documentation strings. */
"fdflags [-v] [-s flags_string] [fd ...]", /* usage synopsis; becomes short_doc */
0 /* reserved for internal use */
};
+2 -2
View File
@@ -336,9 +336,9 @@ int flags;
} else if (flags & OPT_DEV)
printf("%d\n", st->st_dev);
else if (flags & OPT_INO)
printf("%d\n", st->st_ino);
printf("%lu\n", (unsigned long)st->st_ino);
else if (flags & OPT_FID)
printf("%d:%ld\n", st->st_dev, st->st_ino);
printf("%d:%lu\n", st->st_dev, (unsigned long)st->st_ino);
else if (flags & OPT_NLINK)
printf("%d\n", st->st_nlink);
else if (flags & OPT_LNKNAM) {
+1
View File
@@ -117,6 +117,7 @@ head_builtin (list)
return (EX_USAGE);
}
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+1
View File
@@ -91,6 +91,7 @@ id_builtin (list)
case 'n': id_flags |= ID_USENAME; break;
case 'r': id_flags |= ID_USEREAL; break;
case 'u': id_flags |= ID_USERONLY; break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+1
View File
@@ -76,6 +76,7 @@ ln_builtin (list)
case 'n':
flags |= LN_NOFOLLOW;
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+16 -6
View File
@@ -52,12 +52,12 @@ int
mkdir_builtin (list)
WORD_LIST *list;
{
int opt, pflag, omode, rval, nmode, parent_mode;
int opt, pflag, mflag, omode, rval, nmode, parent_mode;
char *mode;
WORD_LIST *l;
reset_internal_getopt ();
pflag = 0;
pflag = mflag = 0;
mode = (char *)NULL;
while ((opt = internal_getopt(list, "m:p")) != -1)
switch (opt)
@@ -66,8 +66,10 @@ mkdir_builtin (list)
pflag = 1;
break;
case 'm':
mflag = 1;
mode = list_optarg;
break;
CASE_HELPOPT;
default:
builtin_usage();
return (EX_USAGE);
@@ -114,7 +116,7 @@ mkdir_builtin (list)
for (rval = EXECUTION_SUCCESS, l = list; l; l = l->next)
{
if (pflag && make_path (l->word->word, nmode, parent_mode))
if (pflag && make_path (l->word->word, mflag, nmode, parent_mode))
{
rval = EXECUTION_FAILURE;
continue;
@@ -132,8 +134,9 @@ mkdir_builtin (list)
this changes the process's umask; make sure that all paths leading to a
return reset it to ORIGINAL_UMASK */
static int
make_path (path, nmode, parent_mode)
make_path (path, user_mode, nmode, parent_mode)
char *path;
int user_mode;
int nmode, parent_mode;
{
int oumask;
@@ -148,7 +151,7 @@ make_path (path, nmode, parent_mode)
return 1;
}
if (chmod (path, nmode))
if (user_mode && chmod (path, nmode))
{
builtin_error ("%s: %s", path, strerror (errno));
return 1;
@@ -172,13 +175,20 @@ make_path (path, nmode, parent_mode)
*p = '\0';
if (stat (npath, &sb) != 0)
{
if (mkdir (npath, parent_mode))
if (mkdir (npath, 0))
{
builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
umask (original_umask);
free (npath);
return 1;
}
if (chmod (npath, parent_mode) != 0)
{
builtin_error ("cannot chmod directory `%s': %s", npath, strerror (errno));
umask (original_umask);
free (npath);
return 1;
}
}
else if (S_ISDIR (sb.st_mode) == 0)
{
+1 -1
View File
@@ -38,7 +38,7 @@ WORD_LIST *list;
char *necho_doc[] = {
"Display arguments.",
"",
"Print the arguments to the standard ouput separated",
"Print the arguments to the standard output separated",
"by space characters and terminated with a newline.",
(char *)NULL
};
+2 -1
View File
@@ -112,6 +112,7 @@ pathchk_builtin (list)
case 'p':
pflag = 1;
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
@@ -135,7 +136,7 @@ char *pathchk_doc[] = {
"Check pathnames for validity.",
"",
"Check each pathname argument for validity (i.e., it may be used to",
"create or access a file without casuing syntax errors) and portability",
"create or access a file without causing syntax errors) and portability",
"(i.e., no filename truncation will result). If the `-p' option is",
"supplied, more extensive portability checks are performed.",
(char *)NULL
+1
View File
@@ -122,6 +122,7 @@ print_builtin (list)
case 'f':
pfmt = list_optarg;
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+1
View File
@@ -46,6 +46,7 @@ printenv_builtin (list)
{
switch (opt)
{
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+1
View File
@@ -51,6 +51,7 @@ push_builtin (list)
{
switch (opt)
{
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+5 -1
View File
@@ -86,15 +86,19 @@ WORD_LIST *list;
case 'v':
vflag = 1;
break;
CASE_HELPOPT;
default:
builtin_usage();
return (EX_USAGE);
}
}
list = loptend;
if (list == 0)
if (list == 0) {
builtin_usage();
return (EX_USAGE);
}
for (es = EXECUTION_SUCCESS; list; list = list->next) {
p = list->word->word;
+177
View File
@@ -0,0 +1,177 @@
/* rm - remove files and directories with -r */
/* See Makefile for compilation details. */
/*
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdio.h>
#include <errno.h>
#include <dirent.h>
#include "builtins.h"
#include "shell.h"
#include "common.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif
static int rm_file(const char *fname);
static int force, recursive;
static int
_remove_directory(const char *dirname)
{
DIR *dir;
struct dirent *dp;
size_t dirlen;
int err;
dirlen = strlen (dirname);
err = 0;
if ((dir = opendir(dirname)))
{
while ((dp = readdir(dir)))
{
#ifdef __GNUC__
char fname[dirlen + 1 + strlen (dp->d_name) + 1];
#else
char *fname;
int fnsize;
#endif
if (*dp->d_name == '.' && (dp->d_name[1] == 0 || (dp->d_name[1] == '.' && dp->d_name[2] == 0)))
continue;
#ifdef __GNUC__
snprintf(fname, sizeof (fname), "%s/%s", dirname, dp->d_name);
#else
fnsize = dirlen + 1 + strlen (dp->d_name) + 1;
fname = xmalloc (fnsize);
snprintf(fname, fnsize, "%s/%s", dirname, dp->d_name);
#endif
if (rm_file (fname) && force == 0)
err = 1;
#ifndef __GNUC__
free (fname);
#endif
}
closedir(dir);
if (err == 0 && rmdir (dirname) && force == 0)
err = 1;
}
else if (force == 0)
err = 1;
if (err)
builtin_error ("%s: %s", dirname, strerror (errno));
return err;
}
static int
rm_file(const char *fname)
{
if (unlink (fname) == 0)
return 0;
/* If FNAME is a directory glibc returns EISDIR but correct POSIX value
would be EPERM. If we get that error and FNAME is a directory and -r
was supplied, recursively remove the directory and its contents */
if ((errno == EISDIR || errno == EPERM) && recursive && file_isdir (fname))
return _remove_directory(fname);
else if (force)
return 0;
builtin_error ("%s: %s", fname, strerror (errno));
return 1;
}
int
rm_builtin (list)
WORD_LIST *list;
{
const char *name;
WORD_LIST *l;
int rval, opt;
recursive = force = 0;
rval = EXECUTION_SUCCESS;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "Rrfi")) != -1)
{
switch (opt)
{
case 'R':
case 'r':
recursive = 1;
break;
case 'f':
force = 1;
break;
case 'i':
return (EX_DISKFALLBACK);
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (list == 0)
{
builtin_usage ();
return (EXECUTION_FAILURE);
}
for (l = list; l; l = l->next)
{
if (rm_file(l->word->word) && force == 0)
rval = EXECUTION_FAILURE;
}
return rval;
}
char *rm_doc[] = {
"Remove files.",
"",
"rm removes the files specified as arguments.",
(char *)NULL
};
/* The standard structure describing a builtin command. bash keeps an array
of these structures. */
struct builtin rm_struct = {
"rm", /* builtin name */
rm_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
rm_doc, /* array of long documentation strings. */
"rm [-rf] file ...", /* usage synopsis; becomes short_doc */
0 /* reserved for internal use */
};
+490
View File
@@ -0,0 +1,490 @@
/* seq - print sequence of numbers to standard output.
Copyright (C) 2018 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 3 of the License, 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, see <https://www.gnu.org/licenses/>. */
/* Written as bash builtin by Chet Ramey. Portions from seq.c by Ulrich Drepper. */
#include <config.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdio.h>
#include <errno.h>
#include "bashansi.h"
#include "loadables.h"
#include "bashintl.h"
#ifndef errno
extern int errno;
#endif
#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
typedef long double floatmax_t;
# define FLOATMAX_CONV "L"
# define strtofltmax strtold
# define FLOATMAX_FMT "%Lg"
# define FLOATMAX_WFMT "%0.Lf"
# define USE_LONG_DOUBLE
#else
typedef double floatmax_t;
# define FLOATMAX_CONV ""
# define strtofltmax strtod
# define FLOATMAX_FMT "%g"
# define FLOATMAX_WFMT "%0.f"
#endif
static floatmax_t getfloatmax __P((const char *));
static char *genformat __P((floatmax_t, floatmax_t, floatmax_t));
#define MAX(a, b) (((a) < (b))? (b) : (a))
static int conversion_error = 0;
/* If true print all number with equal width. */
static int equal_width;
/* The string used to separate two numbers. */
static char const *separator;
/* The string output after all numbers have been output. */
static char const terminator[] = "\n";
static char decimal_point;
/* Pretty much the same as the version in builtins/printf.def */
static floatmax_t
getfloatmax (arg)
const char *arg;
{
floatmax_t ret;
char *ep;
errno = 0;
ret = strtofltmax (arg, &ep);
if (*ep)
{
sh_invalidnum ((char *)arg);
conversion_error = 1;
}
else if (errno == ERANGE)
{
builtin_error ("warning: %s: %s", arg, strerror(ERANGE));
conversion_error = 1;
}
if (ret == -0.0)
ret = 0.0;
return (ret);
}
/* If FORMAT is a valid printf format for a double argument, return
its long double equivalent, allocated from dynamic storage. This
was written by Ulrich Drepper, taken from coreutils:seq.c */
static char *
long_double_format (char const *fmt)
{
size_t i;
size_t length_modifier_offset;
int has_L;
for (i = 0; ! (fmt[i] == '%' && fmt[i + 1] != '%'); i += (fmt[i] == '%') + 1)
{
if (!fmt[i])
{
builtin_error ("format %s has no %% directive", fmt);
return 0;
}
}
i++;
i += strspn (fmt + i, "-+#0 '"); /* zero or more flags */
i += strspn (fmt + i, "0123456789"); /* optional minimum field width */
if (fmt[i] == '.') /* optional precision */
{
i++;
i += strspn (fmt + i, "0123456789");
}
length_modifier_offset = i; /* optional length modifier */
/* we could ignore an 'l' length modifier here */
has_L = (fmt[i] == 'L');
i += has_L;
switch (fmt[i])
{
case '\0':
builtin_error ("format %s ends in %%", fmt);
return 0;
case 'A':
case 'a':
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
break;
default:
builtin_error ("format %s has unknown `%%%c' directive", fmt, fmt[i]);
return 0;
}
for (i++; ; i += (fmt[i] == '%') + 1)
if (fmt[i] == '%' && fmt[i + 1] != '%')
{
builtin_error ("format %s has too many %% directives", fmt);
return 0;
}
else if (fmt[i] == 0)
{
size_t format_size = i + 1;
char *ldfmt = xmalloc (format_size + 1);
memcpy (ldfmt, fmt, length_modifier_offset);
#ifdef USE_LONG_DOUBLE
ldfmt[length_modifier_offset] = 'L';
strcpy (ldfmt + length_modifier_offset + 1,
fmt + length_modifier_offset + has_L);
#else
strcpy (ldfmt + length_modifier_offset, fmt + length_modifier_offset);
#endif
return ldfmt;
}
}
/* Return the number of digits following the decimal point in NUMBUF */
static int
getprec (numbuf)
const char *numbuf;
{
int p;
char *dp;
if (dp = strchr (numbuf, decimal_point))
dp++; /* skip over decimal point */
for (p = 0; dp && *dp && ISDIGIT (*dp); dp++)
p++;
return p;
}
/* Return the default format given FIRST, INCR, and LAST. */
static char *
genformat (first, incr, last)
floatmax_t first, incr, last;
{
static char buf[6 + 2 * INT_STRLEN_BOUND (int)];
int wfirst, wlast, width;
int iprec, fprec, lprec, prec;
if (equal_width == 0)
return (FLOATMAX_FMT);
/* OK, we have to figure out the largest number of decimal places. This is
a little more expensive than using the original strings. */
snprintf (buf, sizeof (buf), FLOATMAX_FMT, incr);
iprec = getprec (buf);
wfirst = snprintf (buf, sizeof (buf), FLOATMAX_FMT, first);
fprec = getprec (buf);
prec = MAX (fprec, iprec);
wlast = snprintf (buf, sizeof (buf), FLOATMAX_FMT, last);
lprec = getprec (buf);
/* increase first width by any increased precision in increment */
wfirst += (prec - fprec);
/* adjust last width to use precision from first/incr */
wlast += (prec - lprec);
if (lprec && prec == 0)
wlast--; /* no decimal point */
if (lprec == 0 && prec)
wlast++; /* include decimal point */
if (fprec == 0 && prec)
wfirst++; /* include decimal point */
width = MAX (wfirst, wlast);
if (width)
sprintf (buf, "%%0%d.%d%sf", width, prec, FLOATMAX_CONV);
else
sprintf (buf, "%%.%d%sf", prec, FLOATMAX_CONV);
return buf;
}
int
print_fltseq (fmt, first, last, incr)
const char *fmt;
floatmax_t first, last, incr;
{
int n;
floatmax_t next;
const char *s;
n = 0; /* interation counter */
s = "";
for (next = first; incr >= 0 ? (next <= last) : (next >= last); next = first + n * incr)
{
QUIT;
if (*s && fputs (s, stdout) == EOF)
return (sh_chkwrite (EXECUTION_FAILURE));
if (printf (fmt, next) < 0)
return (sh_chkwrite (EXECUTION_FAILURE));
s = separator;
n++;
}
if (n > 0 && fputs (terminator, stdout) == EOF)
return (sh_chkwrite (EXECUTION_FAILURE));
return (sh_chkwrite (EXECUTION_SUCCESS));
}
/* must be <= INT_STRLEN_BOUND(intmax_t) */
int
width_needed (num)
intmax_t num;
{
int ret;
ret = num < 0; /* sign */
if (ret)
num = -num;
do
ret++;
while (num /= 10);
return ret;
}
int
print_intseq (ifirst, ilast, iincr)
intmax_t ifirst, ilast, iincr;
{
char intwfmt[6 + INT_STRLEN_BOUND(int) + sizeof (PRIdMAX)];
const char *s;
intmax_t i, next;
/* compute integer format string */
if (equal_width) /* -w supplied */
{
int wfirst, wlast, width;
wfirst = width_needed (ifirst);
wlast = width_needed (ilast);
width = MAX(wfirst, wlast);
/* The leading %s is for the separator */
snprintf (intwfmt, sizeof (intwfmt), "%%s%%0%u" PRIdMAX, width);
}
/* We could use braces.c:mkseq here but that allocates lots of memory */
s = "";
for (i = ifirst; (ifirst <= ilast) ? (i <= ilast) : (i >= ilast); i = next)
{
QUIT;
/* The leading %s is for the separator */
if (printf (equal_width ? intwfmt : "%s%" PRIdMAX, s, i) < 0)
return (sh_chkwrite (EXECUTION_FAILURE));
s = separator;
next = i + iincr;
}
if (fputs (terminator, stdout) == EOF)
return (sh_chkwrite (EXECUTION_FAILURE));
return (sh_chkwrite (EXECUTION_SUCCESS));
}
int
seq_builtin (list)
WORD_LIST *list;
{
floatmax_t first, last, incr;
intmax_t ifirst, ilast, iincr;
WORD_LIST *l;
int opt, nargs, intseq, freefmt;
char *first_str, *incr_str, *last_str;
char const *fmtstr; /* The printf(3) format used for output. */
equal_width = 0;
separator = "\n";
fmtstr = NULL;
first = 1.0;
last = 0.0;
incr = 0.0; /* set later */
ifirst = ilast = iincr = 0;
first_str = incr_str = last_str = 0;
intseq = freefmt = 0;
opt = 0;
reset_internal_getopt ();
while (opt != -1)
{
l = lcurrent ? lcurrent : list;
if (l && l->word && l->word->word && l->word->word[0] == '-' &&
(l->word->word[1] == '.' || DIGIT (l->word->word[1])))
{
loptend = l;
break; /* negative number */
}
if ((opt = internal_getopt (list, "f:s:w")) == -1)
break;
switch (opt)
{
case 'f':
fmtstr = list_optarg;
break;
case 's':
separator = list_optarg;
break;
case 'w':
equal_width = 1;
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (list == 0)
{
builtin_usage ();
return (EXECUTION_FAILURE);
}
for (nargs = 1, l = list; l->next; l = l->next)
nargs++;
if (nargs > 3)
{
builtin_usage ();
return (EXECUTION_FAILURE);
}
/* LAST */
conversion_error = 0;
last = getfloatmax (last_str = l->word->word);
if (conversion_error)
return (EXECUTION_FAILURE);
/* FIRST LAST */
if (nargs > 1)
{
conversion_error = 0;
first = getfloatmax (first_str = list->word->word);
if (conversion_error)
return (EXECUTION_FAILURE);
}
/* FIRST INCR LAST */
if (nargs > 2)
{
conversion_error = 0;
incr = getfloatmax (incr_str = list->next->word->word);
if (conversion_error)
return (EXECUTION_FAILURE);
if (incr == 0.0)
{
builtin_error ("zero %screment", (first < last) ? "in" : "de");
return (EXECUTION_FAILURE);
}
}
/* Sanitize arguments */
if (incr == 0.0)
incr = (first <= last) ? 1.0 : -1.0;
if ((incr < 0.0 && first < last) || (incr > 0 && first > last))
{
builtin_error ("incorrect %screment", (first < last) ? "in" : "de");
return (EXECUTION_FAILURE);
}
/* validate format here */
if (fmtstr)
{
fmtstr = long_double_format (fmtstr);
freefmt = 1;
if (fmtstr == 0)
return (EXECUTION_FAILURE);
}
if (fmtstr != NULL && equal_width)
{
builtin_warning ("-w ignored when the format string is specified");
equal_width = 0;
}
/* Placeholder for later additional conditions */
if (last_str && all_digits (last_str) &&
(first_str == 0 || all_digits (first_str)) &&
(incr_str == 0 || all_digits (incr_str)) &&
fmtstr == NULL)
intseq = 1;
if (intseq)
{
ifirst = (intmax_t)first; /* truncation */
ilast = (intmax_t)last;
iincr = (intmax_t)incr;
return (print_intseq (ifirst, ilast, iincr));
}
decimal_point = locale_decpoint ();
if (fmtstr == NULL)
fmtstr = genformat (first, incr, last);
print_fltseq (fmtstr, first, last, incr);
if (freefmt)
free ((void *)fmtstr);
return sh_chkwrite (EXECUTION_SUCCESS);
}
/* Taken largely from GNU seq. */
char *seq_doc[] = {
"Print numbers from FIRST to LAST, in steps of INCREMENT.",
"",
"-f FORMAT use printf style floating-point FORMAT",
"-s STRING use STRING to separate numbers (default: \\n)",
"-w equalize width by padding with leading zeroes",
"",
"If FIRST or INCREMENT is omitted, it defaults to 1. However, an",
"omitted INCREMENT defaults to -1 when LAST is smaller than FIRST.",
"The sequence of numbers ends when the sum of the current number and",
"INCREMENT would become greater than LAST.",
"FIRST, INCREMENT, and LAST are interpreted as floating point values.",
"",
"FORMAT must be suitable for printing one argument of type 'double';",
"it defaults to %.PRECf if FIRST, INCREMENT, and LAST are all fixed point",
"decimal numbers with maximum precision PREC, and to %g otherwise.",
(char *)NULL
};
struct builtin seq_struct = {
"seq",
seq_builtin,
BUILTIN_ENABLED,
seq_doc,
"seq [-f format] [-s separator] [-w] [FIRST [INCR]] LAST",
0
};
-7
View File
@@ -48,13 +48,6 @@
#include "builtins.h"
#include "common.h"
#define RETURN(x) \
do { \
if (sp) *sp = sec; \
if (usp) *usp = usec; \
return (x); \
} while (0)
int
sleep_builtin (list)
WORD_LIST *list;
+430
View File
@@ -0,0 +1,430 @@
/* stat - load up an associative array with stat information about a file */
/* See Makefile for compilation details. */
/*
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include "posixstat.h"
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include "posixtime.h"
#include "bashansi.h"
#include "shell.h"
#include "builtins.h"
#include "common.h"
#include "bashgetopt.h"
#ifndef errno
extern int errno;
#endif
#define ST_NAME 0
#define ST_DEV 1
#define ST_INO 2
#define ST_MODE 3
#define ST_NLINK 4
#define ST_UID 5
#define ST_GID 6
#define ST_RDEV 7
#define ST_SIZE 8
#define ST_ATIME 9
#define ST_MTIME 10
#define ST_CTIME 11
#define ST_BLKSIZE 12
#define ST_BLOCKS 13
#define ST_CHASELINK 14
#define ST_PERMS 15
#define ST_END 16
static char *arraysubs[] =
{
"name", "device", "inode", "type", "nlink", "uid", "gid", "rdev",
"size", "atime", "mtime", "ctime", "blksize", "blocks", "link", "perms",
0
};
static int
getstat (fname, flags, sp)
const char *fname;
int flags;
struct stat *sp;
{
intmax_t lfd;
int fd, r;
if (strncmp (fname, "/dev/fd/", 8) == 0)
{
if ((legal_number(fname + 8, &lfd) == 0) || (int)lfd != lfd)
{
errno = EINVAL;
return -1;
}
fd = lfd;
r = fstat(fd, sp);
}
#ifdef HAVE_LSTAT
else if (flags & 1)
r = lstat(fname, sp);
#endif
else
r = stat(fname, sp);
return r;
}
static char *
statlink (fname, sp)
char *fname;
struct stat *sp;
{
#if defined (HAVE_READLINK)
char linkbuf[PATH_MAX];
int n;
if (fname && S_ISLNK (sp->st_mode) && (n = readlink (fname, linkbuf, PATH_MAX)) > 0)
{
linkbuf[n] = '\0';
return (savestring (linkbuf));
}
else
#endif
return (savestring (fname));
}
static char *
octalperms (m)
int m;
{
int operms;
char *ret;
operms = 0;
if (m & S_IRUSR)
operms |= 0400;
if (m & S_IWUSR)
operms |= 0200;
if (m & S_IXUSR)
operms |= 0100;
if (m & S_IRGRP)
operms |= 0040;
if (m & S_IWGRP)
operms |= 0020;
if (m & S_IXGRP)
operms |= 0010;
if (m & S_IROTH)
operms |= 0004;
if (m & S_IWOTH)
operms |= 0002;
if (m & S_IXOTH)
operms |= 0001;
if (m & S_ISUID)
operms |= 04000;
if (m & S_ISGID)
operms |= 02000;
if (m & S_ISVTX)
operms |= 01000;
ret = (char *)xmalloc (16);
snprintf (ret, 16, "%04o", operms);
return ret;
}
static char *
statperms (m)
int m;
{
char ubits[4], gbits[4], obits[4]; /* u=rwx,g=rwx,o=rwx */
int i;
char *ret;
i = 0;
if (m & S_IRUSR)
ubits[i++] = 'r';
if (m & S_IWUSR)
ubits[i++] = 'w';
if (m & S_IXUSR)
ubits[i++] = 'x';
ubits[i] = '\0';
i = 0;
if (m & S_IRGRP)
gbits[i++] = 'r';
if (m & S_IWGRP)
gbits[i++] = 'w';
if (m & S_IXGRP)
gbits[i++] = 'x';
gbits[i] = '\0';
i = 0;
if (m & S_IROTH)
obits[i++] = 'r';
if (m & S_IWOTH)
obits[i++] = 'w';
if (m & S_IXOTH)
obits[i++] = 'x';
obits[i] = '\0';
if (m & S_ISUID)
ubits[2] = (m & S_IXUSR) ? 's' : 'S';
if (m & S_ISGID)
gbits[2] = (m & S_IXGRP) ? 's' : 'S';
if (m & S_ISVTX)
obits[2] = (m & S_IXOTH) ? 't' : 'T';
ret = (char *)xmalloc (32);
snprintf (ret, 32, "u=%s,g=%s,o=%s", ubits, gbits, obits);
return ret;
}
static char *
statmode(mode)
int mode;
{
char *modestr, *m;
modestr = m = (char *)xmalloc (8);
if (S_ISBLK (mode))
*m++ = 'b';
if (S_ISCHR (mode))
*m++ = 'c';
if (S_ISDIR (mode))
*m++ = 'd';
if (S_ISREG(mode))
*m++ = '-';
if (S_ISFIFO(mode))
*m++ = 'p';
if (S_ISLNK(mode))
*m++ = 'l';
if (S_ISSOCK(mode))
*m++ = 's';
#ifdef S_ISDOOR
if (S_ISDOOR (mode))
*m++ = 'D';
#endif
#ifdef S_ISWHT
if (S_ISWHT(mode))
*m++ = 'W';
#endif
#ifdef S_ISNWK
if (S_ISNWK(mode))
*m++ = 'n';
#endif
#ifdef S_ISMPC
if (S_ISMPC (mode))
*m++ = 'm';
#endif
*m = '\0';
return (modestr);
}
static char *
stattime (t)
time_t t;
{
char *tbuf, *ret;
size_t tlen;
tbuf = ctime (&t);
tlen = strlen (tbuf);
ret = savestring (tbuf);
ret[tlen-1] = '\0';
return ret;
}
static char *
statval (which, fname, flags, sp)
int which;
char *fname;
int flags;
struct stat *sp;
{
int temp;
switch (which)
{
case ST_NAME:
return savestring (fname);
case ST_DEV:
return itos (sp->st_dev);
case ST_INO:
return itos (sp->st_ino);
case ST_MODE:
return (statmode (sp->st_mode));
case ST_NLINK:
return itos (sp->st_nlink);
case ST_UID:
return itos (sp->st_uid);
case ST_GID:
return itos (sp->st_gid);
case ST_RDEV:
return itos (sp->st_rdev);
case ST_SIZE:
return itos (sp->st_size);
case ST_ATIME:
return ((flags & 2) ? stattime (sp->st_atime) : itos (sp->st_atime));
case ST_MTIME:
return ((flags & 2) ? stattime (sp->st_mtime) : itos (sp->st_mtime));
case ST_CTIME:
return ((flags & 2) ? stattime (sp->st_ctime) : itos (sp->st_ctime));
case ST_BLKSIZE:
return itos (sp->st_blksize);
case ST_BLOCKS:
return itos (sp->st_blocks);
case ST_CHASELINK:
return (statlink (fname, sp));
case ST_PERMS:
temp = sp->st_mode & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID);
return (flags & 2) ? statperms (temp) : octalperms (temp);
default:
return savestring ("42");
}
}
static int
loadstat (vname, var, fname, flags, sp)
char *vname;
SHELL_VAR *var;
char *fname;
int flags;
struct stat *sp;
{
int i;
char *key, *value;
SHELL_VAR *v;
for (i = 0; arraysubs[i]; i++)
{
key = savestring (arraysubs[i]);
value = statval (i, fname, flags, sp);
v = bind_assoc_variable (var, vname, key, value, ASS_FORCE);
}
return 0;
}
int
stat_builtin (list)
WORD_LIST *list;
{
int opt, flags;
char *aname, *fname;
struct stat st;
SHELL_VAR *v;
aname = "STAT";
flags = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "A:Ll")) != -1)
{
switch (opt)
{
case 'A':
aname = list_optarg;
break;
case 'L':
flags |= 1; /* operate on links rather than resolving them */
break;
case 'l':
flags |= 2;
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
fname = list->word->word;
if (getstat (fname, flags, &st) < 0)
{
builtin_error ("%s: cannot stat: %s", fname, strerror (errno));
return (EXECUTION_FAILURE);
}
unbind_variable (aname);
v = make_new_assoc_variable (aname);
if (v == 0)
{
builtin_error ("%s: cannot create variable", aname);
return (EXECUTION_FAILURE);
}
if (loadstat (aname, v, fname, flags, &st) < 0)
{
builtin_error ("%s: cannot assign file status information", aname);
unbind_variable (aname);
return (EXECUTION_FAILURE);
}
return (EXECUTION_SUCCESS);
}
/* An array of strings forming the `long' documentation for a builtin xxx,
which is printed by `help xxx'. It must end with a NULL. By convention,
the first line is a short description. */
char *stat_doc[] = {
"Load an associative array with file status information.",
"",
"Take a filename and load the status information returned by a",
"stat(2) call on that file into the associative array specified",
"by the -A option. The default array name is STAT. If the -L",
"option is supplied, stat does not resolve symbolic links and",
"reports information about the link itself. The -l option results",
"in longer-form listings for some of the fields. The exit status is 0",
"unless the stat fails or assigning the array is unsuccessful.",
(char *)NULL
};
/* The standard structure describing a builtin command. bash keeps an array
of these structures. The flags must include BUILTIN_ENABLED so the
builtin can be used. */
struct builtin stat_struct = {
"stat", /* builtin name */
stat_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
stat_doc, /* array of long documentation strings. */
"stat [-lL] [-A aname] file", /* usage synopsis; becomes short_doc */
0 /* reserved for internal use */
};
+1
View File
@@ -84,6 +84,7 @@ tee_builtin (list)
case 'i':
nointr = 1;
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+1
View File
@@ -31,6 +31,7 @@ template_builtin (list)
{
switch (opt)
{
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+1
View File
@@ -46,6 +46,7 @@ tty_builtin (list)
case 's':
sflag = 1;
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+1
View File
@@ -95,6 +95,7 @@ uname_builtin (list)
case 'v':
uname_flags |= FLAG_VERSION;
break;
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);
+1
View File
@@ -39,6 +39,7 @@ whoami_builtin (list)
{
switch (opt)
{
CASE_HELPOPT;
default:
builtin_usage ();
return (EX_USAGE);