mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-05 03:10:50 +02:00
Imported from ../bash-2.0.tar.gz.
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Convert Csh aliases to Bash aliases. Adapted from a similar program
|
||||
# supplied with zsh.
|
||||
#
|
||||
# This is a quick script to convert csh aliases to Bash aliases/functions.
|
||||
# Pipe the output of csh's alias command through this; it will generate
|
||||
# a series of alias/function definitions on stdout, suitable for
|
||||
# processing by bash.
|
||||
#
|
||||
# This is not perfect, but it gets most common aliases; it should manage to
|
||||
# cut down a lot of the busy work.
|
||||
#
|
||||
sed -e 's/ (\(.*\))/ \1/' >/tmp/cz$$.1
|
||||
grep ! /tmp/cz$$.1 >/tmp/cz$$.2
|
||||
grep -v ! /tmp/cz$$.1 >/tmp/cz$$.3
|
||||
sed -e "s/'/'"\\\\"''"/g -e 's/^\([^ ]*\) \(.*\)$/alias \1='"'\2'/" \
|
||||
/tmp/cz$$.3
|
||||
sed -e 's/![:#]*/$/g' -e 's/^\([^ ]*\) \(.*\)$/\1 () { \2 }/' /tmp/cz$$.2
|
||||
rm /tmp/cz$$.?
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,27 @@
|
||||
From mikel@ora.com Tue Aug 1 12:13:20 1995
|
||||
Flags: 10
|
||||
Return-Path: mikel@ora.com
|
||||
Received: from ruby.ora.com (ruby.ora.com [198.112.208.25]) by odin.INS.CWRU.Edu with ESMTP (8.6.12+cwru/CWRU-2.1-ins)
|
||||
id MAA01565; Tue, 1 Aug 1995 12:13:18 -0400 (from mikel@ora.com for <chet@odin.INS.CWRU.Edu>)
|
||||
Received: (from fax@localhost) by ruby.ora.com (8.6.12/8.6.11) with UUCP id MAA23251; Tue, 1 Aug 1995 12:07:51 -0400
|
||||
Received: by los.ora.com (4.1/Spike-2.1)
|
||||
id AA00672; Tue, 1 Aug 95 08:57:32 EDT
|
||||
Date: Tue, 1 Aug 95 08:57:32 EDT
|
||||
From: mikel@ora.com (Michael Loukides)
|
||||
Message-Id: <9508011257.AA00672@los.ora.com>
|
||||
Subject: Re: Ksh debugger from Rosenblatt's book [for bash]
|
||||
To: Chet Ramey <chet@odin.INS.CWRU.Edu>
|
||||
Cc: cmarie@ora.com, cam@iinet.com.au, brosenblatt@tm.com
|
||||
In-Reply-To: Chet Ramey <chet@odin.INS.CWRU.Edu>, Mon, 31 Jul 1995 16:22:48 -0400
|
||||
|
||||
I've modified a (modified) version of Bill Rosenblatt's ksh debugger
|
||||
to work with bash-2.0. Does ORA have any problem with me distributing
|
||||
it with bash-2.0?
|
||||
|
||||
That's great!
|
||||
|
||||
Go ahead and circulate it; in fact, we should probably grab it and
|
||||
stick it in our ftp archive, and put a reference to it in the book.
|
||||
(Too late to actually discuss the thing, at least for this edition).
|
||||
-------
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
This is a modified version of the Korn Shell debugger from Bill
|
||||
Rosenblatt's `Learning the Korn Shell', published by O'Reilly
|
||||
and Associates (ISBN 1-56592-054-6).
|
||||
|
||||
The original `kshdb' is available for anonymous FTP with the URL
|
||||
|
||||
ftp://ftp.uu.net/published/oreilly/nutshell/ksh/ksh.tar.Z
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# kshdb - Korn Shell Debugger main file
|
||||
# adapted from 'Learning the Korn Shell' by Bill Rosenblatt (O'Reilly)
|
||||
# by Cigy Cyriac (cigy@felix.tulblr.unisys.com)
|
||||
# Main driver: constructs full script (with preamble) and runs it
|
||||
|
||||
echo 'Bourne-Again Shell Debugger version 0.1'
|
||||
|
||||
_pname=${0##*/}
|
||||
|
||||
[ $# -eq 0 ] && {
|
||||
echo "${_pname}: usage: ${_pname} <script_file>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
_guineapig=$1
|
||||
|
||||
[ -r $_guineapig ] || {
|
||||
echo "${_pname}: cannot read $_guineapig." >&2
|
||||
exit 1
|
||||
}
|
||||
shift
|
||||
|
||||
_tmpdir=/tmp
|
||||
_libdir=.
|
||||
_dbgfile=$_tmpdir/bashdb$$ #temp file for script being debugged
|
||||
|
||||
cat $_libdir/bashdb.pre $_guineapig > $_dbgfile
|
||||
exec bash $_dbgfile $_guineapig $_tmpdir $_libdir "$@"
|
||||
# end of bashdb
|
||||
@@ -0,0 +1,235 @@
|
||||
# bashdb.fns - Bourne-Again Shell Debugger functions
|
||||
|
||||
_BUFSIZ=100
|
||||
|
||||
# Here after each statement in script being debugged.
|
||||
# Handle single-step and breakpoints.
|
||||
_steptrap() {
|
||||
let _curline=$1-1 # no. of line that just ran
|
||||
let "$_curline < 1" && let _curline=1
|
||||
|
||||
let "$_curline > $_firstline+$_BUFSIZ" && _readin $_curline
|
||||
|
||||
let " $_trace" &&
|
||||
_msg "$PS4, line $_curline: ${_lines[$(($_curline-$_firstline+1))]}"
|
||||
|
||||
# if in step mode, decrement counter
|
||||
let " $_steps >= 0" && let _steps="$_steps - 1"
|
||||
|
||||
# first check if line num or string brkpt. reached
|
||||
if _at_linenumbp || _at_stringbp; then
|
||||
_msg "Reached breakpoint at line $_curline"
|
||||
_cmdloop # enter debugger
|
||||
|
||||
# if not, check whether break condition exists and is true
|
||||
elif [ -n "$_brcond" ] && eval $_brcond; then
|
||||
_msg "Break condition $_brcond true at line $_curline"
|
||||
_cmdloop # enter debugger
|
||||
|
||||
# next, check if step mode and no. of steps is up
|
||||
elif let "$_steps == 0"; then
|
||||
_msg "Stopped at line $_curline"
|
||||
_cmdloop # enter debugger
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Debugger command loop.
|
||||
# Here at start of debugger session, when brkpt. reached, or after single-step.
|
||||
_cmdloop() {
|
||||
local cmd args
|
||||
|
||||
# added support for default command (last one entered)
|
||||
|
||||
while read -e -p "bashdb> [$lastcmd $lastargs] " cmd args; do
|
||||
if [ -z "$cmd" ]; then
|
||||
cmd=$lastcmd
|
||||
args=$lastargs
|
||||
fi
|
||||
|
||||
lastcmd="$cmd"
|
||||
lastargs=$args
|
||||
|
||||
# made commands to be debugger commands by default, no need for '*' prefix
|
||||
|
||||
case $cmd in
|
||||
bp ) _setbp $args ;; #set brkpt at line num or string
|
||||
|
||||
bc ) _setbc $args ;; # set break condition
|
||||
|
||||
cb ) _clearbp ;; # clear all brkpts.
|
||||
|
||||
g ) return ;; # start/resume execution
|
||||
|
||||
s ) let _steps=${args:-1}
|
||||
return ;; # single-step N times(default 1)
|
||||
|
||||
x ) _xtrace ;; # toggle execution trace
|
||||
|
||||
pr ) _print $args ;; # print lines in file
|
||||
|
||||
\? | h | help ) _menu ;; # print command menu
|
||||
|
||||
hi ) history ;; # show command history
|
||||
|
||||
q ) _cleanup; exit ;; # quit
|
||||
|
||||
\! ) eval $args ;; # run shell command
|
||||
|
||||
* ) _msg "Invalid command: $cmd" ; _menu ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# see if next line no. is a brkpt.
|
||||
_at_linenumbp() {
|
||||
if [ -z "${_linebp}" ]; then
|
||||
return 1
|
||||
fi
|
||||
echo "${curline}" | egrep -s "(${linebp%\|})" >/dev/null 2>&1
|
||||
return $?
|
||||
}
|
||||
|
||||
|
||||
# search string brkpts to see if next line in script matches.
|
||||
_at_stringbp() {
|
||||
local l;
|
||||
if [ -z "$_stringbp" ]; then
|
||||
return 1;
|
||||
fi
|
||||
l=${_lines[$_curline-$_firstline+1]}
|
||||
echo "${l} | egrep -s "*(${stringbp%\|})*" >/dev/null 2>&1
|
||||
return $?
|
||||
}
|
||||
|
||||
|
||||
# print message to stderr
|
||||
_msg() {
|
||||
echo -e "$@" >&2
|
||||
}
|
||||
|
||||
|
||||
# set brkpt(s) at given line numbers and/or strings
|
||||
# by appending lines to brkpt file
|
||||
_setbp() {
|
||||
declare -i n
|
||||
case "$1" in
|
||||
"") _listbp ;;
|
||||
[0-9]*) #number, set brkpt at that line
|
||||
n=$1
|
||||
_linebp="${_linebp}$n|"
|
||||
_msg "Breakpoint at line " $1
|
||||
;;
|
||||
*) #string, set brkpt at next line w/string
|
||||
_stringbp="${_stringbp}$@|"
|
||||
_msg "Breakpoint at next line containing $@."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
# list brkpts and break condition.
|
||||
_listbp() {
|
||||
_msg "Breakpoints at lines:"
|
||||
_msg "$(echo $_linebp | tr '|' ' ')"
|
||||
_msg "Breakpoints at strings:"
|
||||
_msg "$(echo $_stringbp | tr '|' ' ')"
|
||||
_msg "Break on condition:"
|
||||
_msg "$_brcond"
|
||||
}
|
||||
|
||||
|
||||
# set or clear break condition
|
||||
_setbc() {
|
||||
if [ -n "$@" ] ; then
|
||||
_brcond=$args
|
||||
_msg "Break when true: $_brcond"
|
||||
else
|
||||
_brcond=
|
||||
_msg "Break condition cleared"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# clear all brkpts
|
||||
_clearbp() {
|
||||
_linebp=
|
||||
_stringbp=
|
||||
_msg "All breakpoints cleared"
|
||||
}
|
||||
|
||||
|
||||
# toggle execution trace feature
|
||||
_xtrace() {
|
||||
let _trace="! $_trace"
|
||||
|
||||
_msg "Execution trace \c"
|
||||
let " $_trace" && _msg "on." || _msg "off."
|
||||
}
|
||||
|
||||
|
||||
# print command menu
|
||||
_menu() {
|
||||
|
||||
# made commands to be debugger commands by default, no need for '*' prefix
|
||||
|
||||
_msg 'bashdb commands:
|
||||
bp N set breakpoint at line N
|
||||
bp string set breakpoint at next line containing "string"
|
||||
bp list breakpoints and break condition
|
||||
bc string set break condition to "string"
|
||||
bc clear break condition
|
||||
cb clear all breakpoints
|
||||
g start/resume execution
|
||||
s [N] execute N statements (default 1)
|
||||
x toggle execution trace on/off (default on)
|
||||
pr [start|.] [cnt] print "cnt" lines from line no. "start"
|
||||
?, h, help print this menu
|
||||
hi show command history
|
||||
q quit
|
||||
|
||||
! cmd [args] execute command "cmd" with "args"
|
||||
|
||||
default: last command (in "[ ]" at the prompt)
|
||||
|
||||
Readline command line editing (emacs/vi mode) is available'
|
||||
}
|
||||
|
||||
|
||||
# erase temp files before exiting
|
||||
_cleanup() {
|
||||
rm $_dbgfile 2>/dev/null
|
||||
}
|
||||
|
||||
|
||||
# read $_BUFSIZ lines from $_guineapig into _lines array, starting from line $1
|
||||
# save number of first line read in _firstline
|
||||
_readin() {
|
||||
declare -i _i=1
|
||||
let _firstline=$1
|
||||
|
||||
SEDCMD="$_firstline,$(($_firstline+$_BUFSIZ))p"
|
||||
|
||||
sed -n "$SEDCMD" $_guineapig > /tmp/_script.$$
|
||||
while read -r _lines[$_i]; do
|
||||
_i=_i+1
|
||||
done < /tmp/_script.$$
|
||||
rm -f /tmp/_script.$$ 2>/dev/null
|
||||
}
|
||||
|
||||
_print() {
|
||||
typeset _start _cnt
|
||||
|
||||
if [ -z "$1" ] || [ "$1" = . ]; then
|
||||
_start=$_curline
|
||||
else
|
||||
_start=$1
|
||||
fi
|
||||
|
||||
_cnt=${2:-9}
|
||||
|
||||
SEDCMD="$_start,$(($_start+$_cnt))p"
|
||||
|
||||
pr -tn $_guineapig | sed -n "$SEDCMD"
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# bashdb.pre - Bourne-Again Shell Debugger preamble file
|
||||
# prepended to script being ddebugged
|
||||
#arguments:
|
||||
# $1 = name of original guineapig script
|
||||
# $2 = dir where temp files are stored
|
||||
# $3 = dir where bashdb.pre and bashdb.fns are stored
|
||||
|
||||
# separate history file for bashdb
|
||||
HISTFILE=~/.bashdb_history
|
||||
set -o history
|
||||
set +H
|
||||
|
||||
# prompt for trace line
|
||||
PS4=$1
|
||||
|
||||
_dbgfile=$0
|
||||
_guineapig=$1
|
||||
_tmpdir=$2
|
||||
_libdir=$3
|
||||
shift 3 #move user's args into place
|
||||
|
||||
. $_libdir/bashdb.fns #read in the debugger functions
|
||||
|
||||
_linebp=
|
||||
_stringbp=
|
||||
let _trace=1 #init execution trace flag to on
|
||||
|
||||
#read guineapig file into _lines array
|
||||
_readin 1
|
||||
|
||||
trap _cleanup EXIT #erase files before exiting
|
||||
|
||||
let _steps=1 #no. of statements to run after setting trap
|
||||
#set LINENO, gets incremented to 1
|
||||
LINENO=0
|
||||
trap '_steptrap $LINENO' DEBUG
|
||||
:
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
aload()
|
||||
{
|
||||
eval $1 '() { . '$2' ; '$1' "$@" ; return $?; }'
|
||||
eval $1 '() { . '$2' ; '$1' "$@" ; return $? ; }'
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
#
|
||||
# An almost ksh-compatible `autoload'. A function declared as `autoload' will
|
||||
# be read in from a file the same name as the function found by searching the
|
||||
# $FPATH (which works the same as $PATH), then that definition will be run.
|
||||
#
|
||||
# To do this without source support, we define a dummy function that, when
|
||||
# executed, will load the file (thereby re-defining the function), then
|
||||
# execute that newly-redefined function with the original arguments.
|
||||
#
|
||||
# It's not identical to ksh because ksh apparently does lazy evaluation
|
||||
# and looks for the file to load from only when the function is referenced.
|
||||
# This one requires that the file exist when the function is declared as
|
||||
# `autoload'.
|
||||
#
|
||||
# usage: autoload [-pu] [func ...]
|
||||
#
|
||||
# options:
|
||||
# -p print in a format that can be reused as input
|
||||
# -u unset each function and remove it from the autoload list
|
||||
#
|
||||
# The first cut of this was by Bill Trost, trost@reed.bitnet
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@ins.CWRU.Edu
|
||||
|
||||
unset _AUTOLOADS
|
||||
_aindex=0
|
||||
|
||||
#
|
||||
# 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
|
||||
# the arguments given to this `fake' function. The autoload function defined
|
||||
# by the file and the file itself *must* be named identically.
|
||||
#
|
||||
|
||||
_aload()
|
||||
{
|
||||
eval $1 '() { . '$2' ; '$1' "$@" ; return $? ; }'
|
||||
_autoload_addlist "$1"
|
||||
}
|
||||
|
||||
_autoload_addlist()
|
||||
{
|
||||
local i=0
|
||||
|
||||
while (( i < $_aindex )); do
|
||||
case "${_AUTOLOADS[i]}" in
|
||||
"$1") return 1 ;;
|
||||
esac
|
||||
(( i += 1 ))
|
||||
done
|
||||
_AUTOLOADS[_aindex]="$1"
|
||||
(( _aindex += 1 ))
|
||||
return 0
|
||||
}
|
||||
|
||||
_autoload_dump()
|
||||
{
|
||||
local func
|
||||
|
||||
for func in ${_AUTOLOADS[@]}; do
|
||||
[ -n "$1" ] && echo -n "autoload "
|
||||
echo "$func"
|
||||
done
|
||||
}
|
||||
|
||||
# Remove $1 from the list of autoloaded functions
|
||||
_autoload_remove_one()
|
||||
{
|
||||
local i=0 nnl=0
|
||||
local -a nlist
|
||||
|
||||
while (( i < _aindex )); do
|
||||
case "${_AUTOLOADS[i]}" in
|
||||
"$1") ;;
|
||||
*) nlist[nnl]="${_AUTOLOADS[i]}" ; (( nnl += 1 ));;
|
||||
esac
|
||||
(( i += 1 ))
|
||||
done
|
||||
unset _AUTOLOADS _aindex
|
||||
eval _AUTOLOADS=( ${nlist[@]} )
|
||||
_aindex=$nnl
|
||||
}
|
||||
|
||||
# Remove all function arguments from the list of autoloaded functions
|
||||
_autoload_remove()
|
||||
{
|
||||
local func i es=0
|
||||
|
||||
# first unset the autoloaded functions
|
||||
for func; do
|
||||
i=0
|
||||
while (( i < _aindex )); do
|
||||
case "${_AUTOLOADS[i]}" in
|
||||
"$func") unset -f $func ; break ;;
|
||||
esac
|
||||
(( i += 1 ))
|
||||
done
|
||||
if (( i == _aindex )); then
|
||||
echo "autoload: $func: not an autoloaded function" >&2
|
||||
es=1
|
||||
fi
|
||||
done
|
||||
|
||||
# then rebuild the list of autoloaded functions
|
||||
for func ; do
|
||||
_autoload_remove_one "$func"
|
||||
done
|
||||
|
||||
return $es
|
||||
}
|
||||
|
||||
#
|
||||
# Search $FPATH for a file the same name as the function given as $1, and
|
||||
# autoload the function from that file. There is no default $FPATH.
|
||||
#
|
||||
|
||||
autoload()
|
||||
{
|
||||
local -a fp
|
||||
local _autoload_unset nfp i
|
||||
|
||||
if (( $# == 0 )) ; then
|
||||
_autoload_dump
|
||||
return 0
|
||||
fi
|
||||
|
||||
OPTIND=1
|
||||
while getopts pu opt
|
||||
do
|
||||
case "$opt" in
|
||||
p) _autoload_dump printable; return 0;;
|
||||
u) _autoload_unset=y ;;
|
||||
*) echo "autoload: usage: autoload [-pu] [function ...]" >&2
|
||||
return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(( $OPTIND - 1 ))
|
||||
|
||||
if [ -n "$_autoload_unset" ]; then
|
||||
_autoload_remove "$@"
|
||||
return $?
|
||||
fi
|
||||
|
||||
#
|
||||
# If there is no $FPATH, there is no work to be done
|
||||
#
|
||||
|
||||
if [ -z "$FPATH" ] ; then
|
||||
echo "autoload: FPATH not set or null" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
#
|
||||
# This treats FPATH exactly like PATH: a null field anywhere in the
|
||||
# FPATH is treated the same as the current directory.
|
||||
#
|
||||
# This turns $FPATH into an array, substituting `.' for `'
|
||||
#
|
||||
eval fp=( $(
|
||||
IFS=':'
|
||||
set -- ${FPATH}
|
||||
for p in "$@" ; do echo -n "${p:-.} "; done
|
||||
)
|
||||
)
|
||||
|
||||
nfp=${#fp[@]}
|
||||
|
||||
for FUNC ; do
|
||||
i=0;
|
||||
while (( i < nfp )) ; do
|
||||
if [ -f ${fp[i]}/$FUNC ] ; then
|
||||
break # found it!
|
||||
fi
|
||||
(( i += 1 ))
|
||||
done
|
||||
|
||||
if (( i == nfp )) ; then
|
||||
echo "autoload: $FUNC: autoload function not found" >&2
|
||||
es=1
|
||||
continue
|
||||
fi
|
||||
|
||||
# echo auto-loading $FUNC from ${fp[i]}/$FUNC
|
||||
_aload $FUNC ${fp[i]}/$FUNC
|
||||
es=0
|
||||
done
|
||||
|
||||
return $es
|
||||
}
|
||||
@@ -1,27 +1,15 @@
|
||||
# C-shell compatabilty package.
|
||||
# setenv VAR VALUE
|
||||
function setenv () {
|
||||
function setenv ()
|
||||
{
|
||||
export $1="$2"
|
||||
}
|
||||
|
||||
function unsetenv () {
|
||||
function unsetenv ()
|
||||
{
|
||||
unset $1
|
||||
}
|
||||
|
||||
function alias () {
|
||||
local name=$1
|
||||
shift
|
||||
local value="$*"
|
||||
|
||||
if [ "$name" = "" ]; then
|
||||
builtin alias
|
||||
elif [ "$value" = "" ]; then
|
||||
builtin alias $name
|
||||
else
|
||||
builtin alias $name="$value"
|
||||
fi
|
||||
}
|
||||
|
||||
# Can't write foreach yet. Need pattern matching, and a few extras.
|
||||
function foreach () {
|
||||
echo 'Can'\''t do `foreach'\'' yet. Type "help for".'
|
||||
@@ -31,6 +19,29 @@ echo 'Can'\''t do `foreach'\'' yet. Type "help for".'
|
||||
#set () {
|
||||
#}
|
||||
|
||||
chdir () {
|
||||
builtin cd $*
|
||||
}
|
||||
chdir ()
|
||||
{
|
||||
builtin cd "$@"
|
||||
}
|
||||
|
||||
# alias - convert csh alias commands to bash functions
|
||||
# from Mohit Aron <aron@cs.rice.edu>
|
||||
# posted to usenet as <4i5p17$bnu@larry.rice.edu>
|
||||
function alias ()
|
||||
{
|
||||
if [ "x$2" = "x" ]
|
||||
then
|
||||
declare -f $1
|
||||
else
|
||||
echo $2 | egrep -s '(\!|#)' 2>/dev/null
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
comm=$(echo $2 | sed 's/\\!\*/\"$\@\"/g
|
||||
s/\\!:\([1-9]\)/\"$\1\"/g
|
||||
s/#/\\#/g')
|
||||
else
|
||||
comm="$2 \"\$@\""
|
||||
fi
|
||||
eval function $1 \(\) "{" command "$comm" "; }"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ function check_exit_status ()
|
||||
if [ ${status} -ne 0 -a ${status} != 128 ]; then
|
||||
# If process exited by a signal, determine name of signal.
|
||||
if [ ${status} -gt 128 ]; then
|
||||
signal="$(builtin kill -l $[${status} - 128] 2>/dev/null)"
|
||||
signal="$(builtin kill -l $((${status} - 128)) 2>/dev/null)"
|
||||
if [ "$signal" ]; then signal="($signal)"; fi
|
||||
fi
|
||||
echo "[Exit ${status} ${signal}]" 1>&2
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
inpath()
|
||||
{
|
||||
path=$(echo $PATH | sed 's/^:/.:/
|
||||
s/::/:.:/g
|
||||
s/:$/:./
|
||||
s/:/ /g')
|
||||
|
||||
for x in $path
|
||||
do
|
||||
[ -x $x/$1 ] && { PROG=$x/$1; break; }
|
||||
done
|
||||
[ -z "$PROG" ]
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# From: Seth Chaiklin <psykseth@aau.dk>
|
||||
# To: chet@ins.CWRU.Edu
|
||||
# Subject: bash functions (sorta)
|
||||
|
||||
#
|
||||
# keep:
|
||||
# usage: keep program
|
||||
# declare the a program should be "kept". i.e. try to fg a stopped one
|
||||
# and only when that fails start a fresh program.
|
||||
#
|
||||
|
||||
keep()
|
||||
{
|
||||
case $# in
|
||||
1|2) ;;
|
||||
*) echo "usage: keep [alias] program" 1>&2 ; return 1;;
|
||||
esac
|
||||
|
||||
# progname
|
||||
pn=${1##*/}
|
||||
|
||||
# set up an alias for the kept program
|
||||
if [ $# = 1 ]; then
|
||||
alias "$pn=fg $1 2>/dev/null || $1"
|
||||
else
|
||||
alias "$1=fg $2 2>/dev/null || $2"
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# unkeep:
|
||||
# usage: unkeep program
|
||||
# unset the alias set up by the keep function
|
||||
#
|
||||
|
||||
unkeep()
|
||||
{
|
||||
if [ $# != 1 ]; then
|
||||
echo "usage: unkeep program"
|
||||
return 2
|
||||
fi
|
||||
|
||||
# unset the alias for the kept program
|
||||
unalias "${1##*/}"
|
||||
}
|
||||
|
||||
#
|
||||
# kept:
|
||||
# lists all kept programs in 'alias: program' form
|
||||
#
|
||||
|
||||
kept()
|
||||
{
|
||||
alias | grep "fg.*2>" | sed "s/alias \(.*\)='fg.*||\(.*\)'$/\1:\2/"
|
||||
}
|
||||
|
||||
|
||||
# some things that should be kept
|
||||
#keep /usr/local/bin/emacs
|
||||
#keep e ${EDITOR:-/usr/local/bin/emacs}
|
||||
#keep edit ${EDITOR:-/usr/local/bin/emacs}
|
||||
#keep /usr/local/bin/emm
|
||||
+20
-27
@@ -39,13 +39,9 @@ whence()
|
||||
return 1
|
||||
fi
|
||||
case "$1" in
|
||||
-v) vflag=1
|
||||
shift 1
|
||||
;;
|
||||
-*) echo "whence: bad option: $1"
|
||||
return 1
|
||||
;;
|
||||
*) ;;
|
||||
-v) vflag=1 ; shift 1 ;;
|
||||
-*) echo "whence: bad option: $1" ; return 1 ;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
if [ "$#" = "0" ] ; then
|
||||
@@ -63,15 +59,12 @@ whence()
|
||||
echo $path
|
||||
else
|
||||
case "$cmd" in
|
||||
/*) echo ""
|
||||
;;
|
||||
*) case "$(builtin type -type $cmd)" in
|
||||
"") echo ""
|
||||
;;
|
||||
*) echo "$cmd"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
/*) echo "" ;;
|
||||
*) case "$(builtin type -type $cmd)" in
|
||||
"") echo "" ;;
|
||||
*) echo "$cmd" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
@@ -117,7 +110,7 @@ cd()
|
||||
# -n do not add trailing newline
|
||||
# -p no-op (no coprocesses)
|
||||
# -r no escapes
|
||||
# -s no-op (print to the history file)
|
||||
# -s print to the history file
|
||||
# -u n redirect output to fd n
|
||||
#
|
||||
|
||||
@@ -131,20 +124,20 @@ print()
|
||||
while getopts "Rnprsu:" c
|
||||
do
|
||||
case $c in
|
||||
R) eflag=
|
||||
;;
|
||||
r) eflag=
|
||||
;;
|
||||
n) nflag=-n
|
||||
;;
|
||||
u) fd=$OPTARG
|
||||
;;
|
||||
p|s) ;;
|
||||
R) eflag= ;;
|
||||
r) eflag= ;;
|
||||
n) nflag=-n ;;
|
||||
s) sflag=y ;;
|
||||
u) fd=$OPTARG ;;
|
||||
p) ;;
|
||||
esac
|
||||
done
|
||||
shift $[ $OPTIND - 1 ]
|
||||
|
||||
builtin echo $eflag $nflag "$@" >&$fd
|
||||
case "$sflag" in
|
||||
y) builtin history -s "$*" ;;
|
||||
*) builtin echo $eflag $nflag "$@" >&$fd
|
||||
esac
|
||||
}
|
||||
|
||||
# substring function
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# replace the `login' and `newgrp' builtins in old bourne shells
|
||||
|
||||
login()
|
||||
{
|
||||
exec login "$@"
|
||||
}
|
||||
|
||||
newgrp()
|
||||
{
|
||||
exec newgrp "$@"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from
|
||||
# @(#) lowercase.ksh 1.0 92/10/08
|
||||
# 92/10/08 john h. dubois iii (john@armory.com)
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
lowercase()
|
||||
{
|
||||
for file; do
|
||||
filename=${file##*/}
|
||||
case "$filename" in
|
||||
*/*) dirname=${file%/*} ;;
|
||||
*) dirname=.;;
|
||||
esac
|
||||
nf=$(echo $filename | tr A-Z a-z)
|
||||
newname="${dirname}/${nf}"
|
||||
if [ "$nf" != "$filename" ]; then
|
||||
mv "$file" "$newname"
|
||||
echo "$0: $file -> $newname"
|
||||
else
|
||||
echo "$0: $file not changed."
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# To: chet@ins.CWRU.Edu
|
||||
# Subject: Bash functions
|
||||
# From: Sandeep Mehta <sxm@philabs.Philips.Com>
|
||||
|
||||
# print MH folders, useful only because folders(1) doesn't print
|
||||
# mod date/times
|
||||
|
||||
mhfold()
|
||||
{
|
||||
list=`folders | tail +2 | awk '{print $1}'`
|
||||
/bin/ls -lag ~/Mail > /tmp/fold$$
|
||||
for i in $list; do
|
||||
grep $i /tmp/fold$$
|
||||
done
|
||||
/bin/rm -f /tmp/fold$$
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
# To: chet@ins.CWRU.Edu
|
||||
# Subject: Bash functions
|
||||
# From: Sandeep Mehta <sxm@philabs.Philips.Com>
|
||||
|
||||
##########################################
|
||||
#
|
||||
# repeat - clone of C shell builtin `repeat'
|
||||
#
|
||||
# usage: repeat <count> <command>
|
||||
#
|
||||
# It has been tested inside other functions and in conditionals like
|
||||
# if [ "`repeat <count> <command>`" ]; then COMMANDS [ else COMMANDS ] fi
|
||||
# Please send me fixes/enhancements.
|
||||
#
|
||||
# Sandeep Mehta <sxm@philabs.Philips.Com>
|
||||
##########################################
|
||||
repeat()
|
||||
{
|
||||
local rcount=$1
|
||||
|
||||
if [ $# -le 1 ] || [ -z "$rcount" ]; then
|
||||
echo "usage: repeat <count> <command>" 1>&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
shift
|
||||
|
||||
local acmd=("$@")
|
||||
|
||||
if [ $rcount -le 0 ]; then
|
||||
echo "count must be greater than 0"
|
||||
echo "usage: repeat <count> <command>" 1>&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
st=0
|
||||
while [ $rcount -gt 0 ]; do
|
||||
eval "${acmd[@]}"
|
||||
st=$?
|
||||
rcount=$((rcount - 1))
|
||||
done
|
||||
return $st
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# Generate a sequence from m to n, m defaults to 1.
|
||||
|
||||
seq ()
|
||||
{
|
||||
declare -i lo hi i # makes local
|
||||
local _SEQ
|
||||
|
||||
case $# in
|
||||
1) seq 1 "$1" ; return $? ;;
|
||||
2) lo=$1 hi=$2
|
||||
i=$lo _SEQ=""
|
||||
while let "i <= hi"; do
|
||||
_SEQ="${_SEQ}$i "
|
||||
let i+=1
|
||||
done
|
||||
echo "${_SEQ# }"
|
||||
return 0 ;;
|
||||
*) echo seq: usage: seq [low] high 1>&2 ; return 2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# like the APL `iota' function (or at least how I remember it :-)
|
||||
iota()
|
||||
{
|
||||
case $# in
|
||||
1) seq 1 "$1"; return $?;;
|
||||
*) echo "iota: usage: iota high" 1>&2; return 2;;
|
||||
esac
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
shcat()
|
||||
{
|
||||
while read line
|
||||
while read -r line
|
||||
do
|
||||
echo "$line"
|
||||
done
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#
|
||||
# Simple makefile for the sample loadable builtins
|
||||
#
|
||||
CC = cc
|
||||
|
||||
# SunOS 4
|
||||
PICFLAG = -pic
|
||||
# Some versions of gcc, esp. on NetBSD and FreeBSD
|
||||
#PICFLAG = -fpic
|
||||
# Linux -- could also be -fpic
|
||||
#PICFLAG = -fPIC
|
||||
# SunOS 5
|
||||
#PICFLAG = -K pic
|
||||
# SVR4, SVR4.2, Irix
|
||||
#PICFLAG = -K PIC
|
||||
# BSD/OS 2.1
|
||||
#PICFLAG =
|
||||
# AIX 4.2
|
||||
#PICFLAG = -K
|
||||
|
||||
# SunOS 4, BSD/OS 2.1, SVR4.2, SVR4, Linux, AIX 4.2, etc.
|
||||
LD = ld
|
||||
# SunOS 5, Linux
|
||||
#LD = cc
|
||||
|
||||
# SunOS 4
|
||||
LDOPT = -assert pure-text
|
||||
# OSF/1, Digital UNIX
|
||||
#LDOPT = -shared -soname $@ -expect_unresolved '*'
|
||||
# SunOS 5
|
||||
#LDOPT = -dy -z text -G -i -h $@
|
||||
# SVR4, SVR4.2
|
||||
#LDOPT = -dy -z text -G -h $@
|
||||
# NetBSD, FreeBSD -- might also need -r
|
||||
#LDOPT = -x -Bshareable
|
||||
# Linux
|
||||
#LDOPT = -shared
|
||||
# BSD/OS 2.1
|
||||
#LDOPT = -r
|
||||
# AIX 4.2
|
||||
#LDOPT = -bdynamic -bnoentry -bexpall -G
|
||||
|
||||
# other libraries to link the shared object against
|
||||
# BSD/OS 2.1
|
||||
#LDLIBS = -lc_s.2.1.0
|
||||
|
||||
srcdir = ../..
|
||||
INC= -I$(srcdir) -I$(srcdir)/builtins -I$(srcdir)/lib
|
||||
|
||||
.c.o:
|
||||
$(CC) $(PICFLAG) $(CFLAGS) $(INC) -c -o $@ $<
|
||||
|
||||
all: printf print truefalse sleep pushd finfo logname basename dirname \
|
||||
tty pathchk tee head rmdir sprintf
|
||||
others: necho getconf hello cat
|
||||
|
||||
printf: printf.o
|
||||
$(LD) $(LDOPT) -o $@ printf.o $(LDLIBS)
|
||||
|
||||
sprintf: sprintf.o
|
||||
$(LD) $(LDOPT) -o $@ sprintf.o $(LDLIBS)
|
||||
|
||||
print: print.o
|
||||
$(LD) $(LDOPT) -o $@ print.o $(LDLIBS)
|
||||
|
||||
necho: necho.o
|
||||
$(LD) $(LDOPT) -o $@ necho.o $(LDLIBS)
|
||||
|
||||
getconf: getconf.o
|
||||
$(LD) $(LDOPT) -o $@ getconf.o $(LDLIBS)
|
||||
|
||||
hello: hello.o
|
||||
$(LD) $(LDOPT) -o $@ hello.o $(LDLIBS)
|
||||
|
||||
truefalse: truefalse.o
|
||||
$(LD) $(LDOPT) -o $@ truefalse.o $(LDLIBS)
|
||||
|
||||
sleep: sleep.o
|
||||
$(LD) $(LDOPT) -o $@ sleep.o $(LDLIBS)
|
||||
|
||||
pushd: pushd.o
|
||||
$(LD) $(LDOPT) -o $@ pushd.o $(LDLIBS)
|
||||
|
||||
finfo: finfo.o
|
||||
$(LD) $(LDOPT) -o $@ finfo.o $(LDLIBS)
|
||||
|
||||
cat: cat.o
|
||||
$(LD) $(LDOPT) -o $@ cat.o $(LDLIBS)
|
||||
|
||||
logname: logname.o
|
||||
$(LD) $(LDOPT) -o $@ logname.o $(LDLIBS)
|
||||
|
||||
basename: basename.o
|
||||
$(LD) $(LDOPT) -o $@ basename.o $(LDLIBS)
|
||||
|
||||
dirname: dirname.o
|
||||
$(LD) $(LDOPT) -o $@ dirname.o $(LDLIBS)
|
||||
|
||||
tty: tty.o
|
||||
$(LD) $(LDOPT) -o $@ tty.o $(LDLIBS)
|
||||
|
||||
pathchk: pathchk.o
|
||||
$(LD) $(LDOPT) -o $@ pathchk.o $(LDLIBS)
|
||||
|
||||
tee: tee.o
|
||||
$(LD) $(LDOPT) -o $@ tee.o $(LDLIBS)
|
||||
|
||||
rmdir: rmdir.o
|
||||
$(LD) $(LDOPT) -o $@ rmdir.o $(LDLIBS)
|
||||
|
||||
head: head.o
|
||||
$(LD) $(LDOPT) -o $@ head.o $(LDLIBS)
|
||||
@@ -0,0 +1,27 @@
|
||||
Some examples of ready-to-dynamic-load builtins. Most of the
|
||||
examples given are reimplementations of standard commands whose
|
||||
execution time is dominated by process startup time. The
|
||||
exceptions are sleep, which allows you to sleep for fractions
|
||||
of a second, finfo, which provides access to the rest of the
|
||||
elements of the `stat' structure that `test' doesn't let you
|
||||
see, and pushd/popd/dirs, which allows you to compile them out
|
||||
of the shell.
|
||||
|
||||
All of the new builtins in ksh93 that bash didn't already have
|
||||
are included here, as is the ksh `print' builtin.
|
||||
|
||||
Compile with cc and whatever pic options you need (look in the
|
||||
Makefile for a few common settings)
|
||||
|
||||
load with ld and whatever shared object options you need (again,
|
||||
look in the Makefile)
|
||||
|
||||
then enable -f filename builtin-name
|
||||
|
||||
enable uses a simple reference-counting scheme to avoid unloading a
|
||||
shared object that implements more than one loadable builtin before
|
||||
all loadable builtins implemented in the object are removed.
|
||||
|
||||
Many of the details needed by builtin writers are found in hello.c,
|
||||
the canonical example. There is no real `builtin writers' programming
|
||||
guide'.
|
||||
@@ -0,0 +1,108 @@
|
||||
/* basename - return nondirectory portion of pathname */
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
|
||||
basename_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int slen, sufflen, off;
|
||||
char *string, *suffix, *fn;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
if (no_options (list))
|
||||
return (EX_USAGE);
|
||||
|
||||
string = list->word->word;
|
||||
suffix = (char *)NULL;
|
||||
if (list->next)
|
||||
{
|
||||
list = list->next;
|
||||
suffix = list->word->word;
|
||||
}
|
||||
|
||||
if (list->next)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
slen = strlen (string);
|
||||
|
||||
/* Strip trailing slashes */
|
||||
while (slen > 0 && string[slen - 1] == '/')
|
||||
slen--;
|
||||
|
||||
/* (2) If string consists entirely of slash characters, string shall be
|
||||
set to a single slash character. In this case, skip steps (3)
|
||||
through (5). */
|
||||
if (slen == 0)
|
||||
{
|
||||
fputs ("/\n", stdout);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* (3) If there are any trailing slash characters in string, they
|
||||
shall be removed. */
|
||||
string[slen] = '\0';
|
||||
|
||||
/* (4) If there are any slash characters remaining in string, the prefix
|
||||
of string up to an including the last slash character in string
|
||||
shall be removed. */
|
||||
while (--slen >= 0)
|
||||
if (string[slen] == '/')
|
||||
break;
|
||||
|
||||
fn = string + slen + 1;
|
||||
|
||||
/* (5) If the suffix operand is present, is not identical to the
|
||||
characters remaining in string, and is identical to a suffix
|
||||
of the characters remaining in string, the suffix suffix
|
||||
shall be removed from string. Otherwise, string shall not be
|
||||
modified by this step. */
|
||||
if (suffix)
|
||||
{
|
||||
sufflen = strlen (suffix);
|
||||
slen = strlen (fn);
|
||||
if (sufflen < slen)
|
||||
{
|
||||
off = slen - sufflen;
|
||||
if (strcmp (fn + off, suffix) == 0)
|
||||
fn[off] = '\0';
|
||||
}
|
||||
}
|
||||
printf ("%s\n", fn);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
char *basename_doc[] = {
|
||||
"The STRING is converted to a filename corresponding to the last",
|
||||
"pathname component in STRING. If the suffix string SUFFIX is",
|
||||
"supplied, it is removed.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
/* The standard structure describing a builtin command. bash keeps an array
|
||||
of these structures. */
|
||||
struct builtin basename_struct = {
|
||||
"basename", /* builtin name */
|
||||
basename_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
basename_doc, /* array of long documentation strings. */
|
||||
"basename string [suffix]", /* usage synopsis */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* cat replacement
|
||||
*
|
||||
* no options - the way cat was intended
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern char *strerror ();
|
||||
extern char **make_builtin_argv ();
|
||||
|
||||
static int
|
||||
fcopy(fd)
|
||||
int fd;
|
||||
{
|
||||
char buf[1024], *s;
|
||||
int n, w, e;
|
||||
|
||||
while (n = read(fd, buf, sizeof (buf))) {
|
||||
w = write(1, buf, n);
|
||||
if (w != n) {
|
||||
e = errno;
|
||||
write(2, "cat: write error: ", 18);
|
||||
s = strerror(e);
|
||||
write(2, s, strlen(s));
|
||||
write(2, "\n", 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
cat_main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int i, fd, r;
|
||||
char *s;
|
||||
|
||||
if (argc == 1)
|
||||
return (fcopy(0));
|
||||
|
||||
for (i = r = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '-' && argv[i][1] == '\0')
|
||||
fd = 0;
|
||||
else {
|
||||
fd = open(argv[i], O_RDONLY, 0666);
|
||||
if (fd < 0) {
|
||||
s = strerror(errno);
|
||||
write(2, "cat: cannot open ", 17);
|
||||
write(2, argv[i], strlen(argv[i]));
|
||||
write(2, ": ", 2);
|
||||
write(2, s, strlen(s));
|
||||
write(2, "\n", 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
r = fcopy(fd);
|
||||
if (fd != 0)
|
||||
close(fd);
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
cat_builtin(list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char **v;
|
||||
int c, r;
|
||||
|
||||
v = make_builtin_argv(list, &c);
|
||||
r = cat_main(c, v);
|
||||
free(v);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
char *cat_doc[] = {
|
||||
"Read each FILE and display it on the standard output. If any",
|
||||
"FILE is `-' or if no FILE argument is given, the standard input",
|
||||
"is read.",
|
||||
(char *)0
|
||||
};
|
||||
|
||||
struct builtin cat_struct = {
|
||||
"cat",
|
||||
cat_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
cat_doc,
|
||||
"cat [-] [file ...]",
|
||||
0
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
/* dirname - return directory portion of pathname */
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
|
||||
dirname_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int slen;
|
||||
char *string;
|
||||
|
||||
if (list == 0 || list->next)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
if (no_options (list))
|
||||
return (EX_USAGE);
|
||||
|
||||
string = list->word->word;
|
||||
slen = strlen (string);
|
||||
|
||||
/* Strip trailing slashes */
|
||||
while (slen > 0 && string[slen - 1] == '/')
|
||||
slen--;
|
||||
|
||||
/* (2) If string consists entirely of slash characters, string shall be
|
||||
set to a single slash character. In this case, skip steps (3)
|
||||
through (8). */
|
||||
if (slen == 0)
|
||||
{
|
||||
fputs ("/\n", stdout);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* (3) If there are any trailing slash characters in string, they
|
||||
shall be removed. */
|
||||
string[slen] = '\0';
|
||||
|
||||
/* (4) If there are no slash characters remaining in string, string
|
||||
shall be set to a single period character. In this case, skip
|
||||
steps (5) through (8).
|
||||
|
||||
(5) If there are any trailing nonslash characters in string,
|
||||
they shall be removed. */
|
||||
|
||||
while (--slen >= 0)
|
||||
if (string[slen] == '/')
|
||||
break;
|
||||
|
||||
if (slen >= 0)
|
||||
{
|
||||
fputs (".\n", stdout);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* (7) If there are any trailing slash characters in string, they
|
||||
shall be removed. */
|
||||
while (--slen >= 0)
|
||||
if (string[slen] != '/')
|
||||
break;
|
||||
string[++slen] = '\0';
|
||||
|
||||
/* (8) If the remaining string is empty, string shall be set to a single
|
||||
slash character. */
|
||||
printf ("%s\n", (slen == 0) ? "/" : string);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
char *dirname_doc[] = {
|
||||
"The STRING is converted to the name of the directory containing",
|
||||
"the filename corresponding to the last pathname component in STRING.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
/* The standard structure describing a builtin command. bash keeps an array
|
||||
of these structures. */
|
||||
struct builtin dirname_struct = {
|
||||
"dirname", /* builtin name */
|
||||
dirname_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
dirname_doc, /* array of long documentation strings. */
|
||||
"dirname string", /* usage synopsis */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* finfo - print file info
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "posixstat.h"
|
||||
#include <stdio.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern char *strrchr();
|
||||
extern char **make_builtin_argv ();
|
||||
|
||||
static int printst();
|
||||
static int printsome();
|
||||
static int printfinfo();
|
||||
static int finfo_main();
|
||||
|
||||
extern int sh_optind;
|
||||
extern char *sh_optarg;
|
||||
extern char *this_command_name;
|
||||
|
||||
static char *prog;
|
||||
static int pmask;
|
||||
|
||||
#define OPT_UID 0x00001
|
||||
#define OPT_GID 0x00002
|
||||
#define OPT_DEV 0x00004
|
||||
#define OPT_INO 0x00008
|
||||
#define OPT_PERM 0x00010
|
||||
#define OPT_LNKNAM 0x00020
|
||||
#define OPT_FID 0x00040
|
||||
#define OPT_NLINK 0x00080
|
||||
#define OPT_RDEV 0x00100
|
||||
#define OPT_SIZE 0x00200
|
||||
#define OPT_ATIME 0x00400
|
||||
#define OPT_MTIME 0x00800
|
||||
#define OPT_CTIME 0x01000
|
||||
#define OPT_BLKSIZE 0x02000
|
||||
#define OPT_BLKS 0x04000
|
||||
#define OPT_FTYPE 0x08000
|
||||
#define OPT_PMASK 0x10000
|
||||
#define OPT_OPERM 0x20000
|
||||
|
||||
#define OPT_ASCII 0x1000000
|
||||
|
||||
#define OPTIONS "acdgiflmnopsuACGMP:U"
|
||||
|
||||
static int
|
||||
octal(s)
|
||||
char *s;
|
||||
{
|
||||
int r;
|
||||
|
||||
r = *s - '0';
|
||||
while (*++s >= '0' && *s <= '7')
|
||||
r = (r * 8) + (*s - '0');
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
finfo_main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register int i;
|
||||
int mode, flags, opt;
|
||||
|
||||
sh_optind = 0; /* XXX */
|
||||
prog = base_pathname(argv[0]);
|
||||
if (argc == 1) {
|
||||
builtin_usage();
|
||||
return(1);
|
||||
}
|
||||
flags = 0;
|
||||
while ((opt = sh_getopt(argc, argv, OPTIONS)) != EOF) {
|
||||
switch(opt) {
|
||||
case 'a': flags |= OPT_ATIME; break;
|
||||
case 'A': flags |= OPT_ATIME|OPT_ASCII; break;
|
||||
case 'c': flags |= OPT_CTIME; break;
|
||||
case 'C': flags |= OPT_CTIME|OPT_ASCII; break;
|
||||
case 'd': flags |= OPT_DEV; break;
|
||||
case 'i': flags |= OPT_INO; break;
|
||||
case 'f': flags |= OPT_FID; break;
|
||||
case 'g': flags |= OPT_GID; break;
|
||||
case 'G': flags |= OPT_GID|OPT_ASCII; break;
|
||||
case 'l': flags |= OPT_LNKNAM; break;
|
||||
case 'm': flags |= OPT_MTIME; break;
|
||||
case 'M': flags |= OPT_MTIME|OPT_ASCII; break;
|
||||
case 'n': flags |= OPT_NLINK; break;
|
||||
case 'o': flags |= OPT_OPERM; break;
|
||||
case 'p': flags |= OPT_PERM; break;
|
||||
case 'P': flags |= OPT_PMASK; pmask = octal(sh_optarg); break;
|
||||
case 's': flags |= OPT_SIZE; break;
|
||||
case 'u': flags |= OPT_UID; break;
|
||||
case 'U': flags |= OPT_UID|OPT_ASCII; break;
|
||||
default: builtin_usage (); return(1);
|
||||
}
|
||||
}
|
||||
|
||||
argc -= sh_optind;
|
||||
argv += sh_optind;
|
||||
|
||||
if (argc == 0) {
|
||||
builtin_usage();
|
||||
return(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
opt = flags ? printsome (argv[i], flags) : printfinfo(argv[i]);
|
||||
|
||||
return(opt);
|
||||
}
|
||||
|
||||
static struct stat *
|
||||
getstat(f)
|
||||
char *f;
|
||||
{
|
||||
static struct stat st;
|
||||
int fd, r;
|
||||
long lfd;
|
||||
|
||||
if (strncmp(f, "/dev/fd/", 8) == 0) {
|
||||
if (legal_number(f + 8, &lfd) == 0) {
|
||||
builtin_error("%s: invalid fd", f + 8);
|
||||
return ((struct stat *)0);
|
||||
}
|
||||
fd = lfd;
|
||||
r = fstat(fd, &st);
|
||||
} else
|
||||
r = stat(f, &st);
|
||||
if (r < 0) {
|
||||
builtin_error("%s: cannot stat: %s", f, strerror(errno));
|
||||
return ((struct stat *)0);
|
||||
}
|
||||
return (&st);
|
||||
}
|
||||
|
||||
static int
|
||||
printfinfo(f)
|
||||
char *f;
|
||||
{
|
||||
struct stat *st;
|
||||
|
||||
st = getstat(f);
|
||||
return (st ? printst(st) : 1);
|
||||
}
|
||||
|
||||
static int
|
||||
getperm(m)
|
||||
int m;
|
||||
{
|
||||
return (m & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID));
|
||||
}
|
||||
|
||||
static int
|
||||
perms(m)
|
||||
int m;
|
||||
{
|
||||
char ubits[4], gbits[4], obits[4]; /* u=rwx,g=rwx,o=rwx */
|
||||
int i;
|
||||
|
||||
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';
|
||||
|
||||
printf ("u=%s,g=%s,o=%s", ubits, gbits, obits);
|
||||
}
|
||||
|
||||
static int
|
||||
printmode(mode)
|
||||
int mode;
|
||||
{
|
||||
if (S_ISBLK(mode))
|
||||
printf("S_IFBLK ");
|
||||
if (S_ISCHR(mode))
|
||||
printf("S_IFCHR ");
|
||||
if (S_ISDIR(mode))
|
||||
printf("S_IFDIR ");
|
||||
if (S_ISREG(mode))
|
||||
printf("S_IFREG ");
|
||||
if (S_ISFIFO(mode))
|
||||
printf("S_IFIFO ");
|
||||
if (S_ISLNK(mode))
|
||||
printf("S_IFLNK ");
|
||||
if (S_ISSOCK(mode))
|
||||
printf("S_IFSOCK ");
|
||||
perms(getperm(mode));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int
|
||||
printst(st)
|
||||
struct stat *st;
|
||||
{
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
char *owner;
|
||||
|
||||
printf("Device (major/minor): %d (%d/%d)\n", (int) (st->st_dev & 0xFF),
|
||||
(int) major (st->st_dev),
|
||||
(int) minor (st->st_dev));
|
||||
printf("Inode: %d\n", (int) st->st_ino);
|
||||
printf("Mode: (%o) ", (int) st->st_mode);
|
||||
printmode((int) st->st_mode);
|
||||
printf("Link count: %d\n", (int) st->st_nlink);
|
||||
pw = getpwuid(st->st_uid);
|
||||
owner = pw ? pw->pw_name : "unknown";
|
||||
printf("Uid of owner: %d (%s)\n", (int) st->st_uid, owner);
|
||||
gr = getgrgid(st->st_gid);
|
||||
owner = gr ? gr->gr_name : "unknown";
|
||||
printf("Gid of owner: %d (%s)\n", (int) st->st_gid, owner);
|
||||
printf("Device type: %d\n", (int) st->st_rdev);
|
||||
printf("File size: %ld\n", (long) st->st_size);
|
||||
printf("File last access time: %s", ctime (&st->st_atime));
|
||||
printf("File last modify time: %s", ctime (&st->st_mtime));
|
||||
printf("File last status change time: %s", ctime (&st->st_ctime));
|
||||
fflush(stdout);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
printsome(f, flags)
|
||||
char *f;
|
||||
int flags;
|
||||
{
|
||||
struct stat *st;
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
int p;
|
||||
char *b;
|
||||
|
||||
st = getstat(f);
|
||||
if (st == NULL)
|
||||
return (1);
|
||||
|
||||
/* Print requested info */
|
||||
if (flags & OPT_ATIME) {
|
||||
if (flags & OPT_ASCII)
|
||||
printf("%s", ctime(&st->st_atime));
|
||||
else
|
||||
printf("%ld\n", st->st_atime);
|
||||
} else if (flags & OPT_MTIME) {
|
||||
if (flags & OPT_ASCII)
|
||||
printf("%s", ctime(&st->st_mtime));
|
||||
else
|
||||
printf("%ld\n", st->st_mtime);
|
||||
} else if (flags & OPT_CTIME) {
|
||||
if (flags & OPT_ASCII)
|
||||
printf("%s", ctime(&st->st_ctime));
|
||||
else
|
||||
printf("%ld\n", st->st_ctime);
|
||||
} else if (flags & OPT_DEV)
|
||||
printf("%d\n", st->st_dev);
|
||||
else if (flags & OPT_INO)
|
||||
printf("%d\n", st->st_ino);
|
||||
else if (flags & OPT_FID)
|
||||
printf("%d:%ld\n", st->st_dev, st->st_ino);
|
||||
else if (flags & OPT_NLINK)
|
||||
printf("%d\n", st->st_nlink);
|
||||
else if (flags & OPT_LNKNAM) {
|
||||
#ifdef S_ISLNK
|
||||
b = xmalloc(4096);
|
||||
p = readlink(f, b, 4096);
|
||||
if (p >= 0 && p < 4096)
|
||||
b[p] = '\0';
|
||||
else {
|
||||
p = errno;
|
||||
strcpy(b, prog);
|
||||
strcat(b, ": ");
|
||||
strcat(b, strerror(p));
|
||||
}
|
||||
printf("%s\n", b);
|
||||
free(b);
|
||||
#else
|
||||
printf("%s\n", f);
|
||||
#endif
|
||||
} else if (flags & OPT_PERM) {
|
||||
perms(st->st_mode);
|
||||
printf("\n");
|
||||
} else if (flags & OPT_OPERM)
|
||||
printf("%o\n", getperm(st->st_mode));
|
||||
else if (flags & OPT_PMASK)
|
||||
printf("%o\n", getperm(st->st_mode) & pmask);
|
||||
else if (flags & OPT_UID) {
|
||||
pw = getpwuid(st->st_uid);
|
||||
if (flags & OPT_ASCII)
|
||||
printf("%s\n", pw ? pw->pw_name : "unknown");
|
||||
else
|
||||
printf("%d\n", st->st_uid);
|
||||
} else if (flags & OPT_GID) {
|
||||
gr = getgrgid(st->st_gid);
|
||||
if (flags & OPT_ASCII)
|
||||
printf("%s\n", gr ? gr->gr_name : "unknown");
|
||||
else
|
||||
printf("%d\n", st->st_gid);
|
||||
} else if (flags & OPT_SIZE)
|
||||
printf("%ld\n", st->st_size);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifndef NOBUILTIN
|
||||
finfo_builtin(list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int c, r;
|
||||
char **v;
|
||||
WORD_LIST *l;
|
||||
|
||||
v = make_builtin_argv (list, &c);
|
||||
r = finfo_main (c, v);
|
||||
free (v);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static char *finfo_doc[] = {
|
||||
"Display information about each FILE. Only single operators should",
|
||||
"be supplied. If no options are supplied, a summary of the info",
|
||||
"available about each FILE is printed. If FILE is of the form",
|
||||
"/dev/fd/XX, file descriptor XX is described. Operators, if supplied,",
|
||||
"have the following meanings:",
|
||||
"",
|
||||
" -a last file access time",
|
||||
" -A last file access time in ctime format",
|
||||
" -c last file status change time",
|
||||
" -C last file status change time in ctime format",
|
||||
" -m last file modification time",
|
||||
" -M last file modification time in ctime format",
|
||||
" -d device",
|
||||
" -i inode",
|
||||
" -f composite file identifier (device:inode)",
|
||||
" -g gid of owner",
|
||||
" -G group name of owner",
|
||||
" -l name of file pointed to by symlink",
|
||||
" -n link count",
|
||||
" -o permissions in octal",
|
||||
" -p permissions in ascii",
|
||||
" -P mask permissions ANDed with MASK (like with umask)",
|
||||
" -s file size in bytes",
|
||||
" -u uid of owner",
|
||||
" -U user name of owner",
|
||||
(char *)0
|
||||
};
|
||||
|
||||
struct builtin finfo_struct = {
|
||||
"finfo",
|
||||
finfo_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
finfo_doc,
|
||||
"finfo [-acdgiflmnopsuACGMPU] file [file...]",
|
||||
0
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef NOBUILTIN
|
||||
#if defined (PREFER_STDARG)
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# if defined (PREFER_VARARGS)
|
||||
# include <varargs.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
char *this_command_name;
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
this_command_name = argv[0];
|
||||
exit(finfo_main(argc, argv));
|
||||
}
|
||||
|
||||
void
|
||||
builtin_usage()
|
||||
{
|
||||
fprintf(stderr, "%s: usage: %s [-%s] [file ...]\n", prog, OPTIONS);
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
char *
|
||||
strerror(e)
|
||||
int e;
|
||||
{
|
||||
static char ebuf[40];
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
|
||||
if (e < 0 || e > sys_nerr) {
|
||||
sprintf(ebuf,"Unknown error code %d", e);
|
||||
return (&ebuf[0]);
|
||||
}
|
||||
return (sys_errlist[e]);
|
||||
}
|
||||
#endif
|
||||
|
||||
char *
|
||||
xmalloc(s)
|
||||
size_t s;
|
||||
{
|
||||
char *ret;
|
||||
extern char *malloc();
|
||||
|
||||
ret = malloc(s);
|
||||
if (ret)
|
||||
return (ret);
|
||||
fprintf(stderr, "%s: cannot malloc %d bytes\n", prog, s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *
|
||||
base_pathname(p)
|
||||
char *p;
|
||||
{
|
||||
char *t;
|
||||
|
||||
if (t = strrchr(p, '/'))
|
||||
return(++t);
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
legal_number (string, result)
|
||||
char *string;
|
||||
long *result;
|
||||
{
|
||||
int sign;
|
||||
long value;
|
||||
|
||||
sign = 1;
|
||||
value = 0;
|
||||
|
||||
if (result)
|
||||
*result = 0;
|
||||
|
||||
/* Skip leading whitespace characters. */
|
||||
while (whitespace (*string))
|
||||
string++;
|
||||
|
||||
if (!*string)
|
||||
return (0);
|
||||
|
||||
/* We allow leading `-' or `+'. */
|
||||
if (*string == '-' || *string == '+')
|
||||
{
|
||||
if (!digit (string[1]))
|
||||
return (0);
|
||||
|
||||
if (*string == '-')
|
||||
sign = -1;
|
||||
|
||||
string++;
|
||||
}
|
||||
|
||||
while (digit (*string))
|
||||
{
|
||||
if (result)
|
||||
value = (value * 10) + digit_value (*string);
|
||||
string++;
|
||||
}
|
||||
|
||||
/* Skip trailing whitespace, if any. */
|
||||
while (whitespace (*string))
|
||||
string++;
|
||||
|
||||
/* Error if not at end of string. */
|
||||
if (*string)
|
||||
return (0);
|
||||
|
||||
if (result)
|
||||
*result = value * sign;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int sh_optind;
|
||||
char *sh_optarg;
|
||||
int sh_opterr;
|
||||
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
int
|
||||
sh_getopt(c, v, o)
|
||||
int c;
|
||||
char **v, *o;
|
||||
{
|
||||
int r;
|
||||
|
||||
r = getopt(c, v, o);
|
||||
sh_optind = optind;
|
||||
sh_optarg = optarg;
|
||||
return r;
|
||||
}
|
||||
|
||||
#if defined (USE_VARARGS)
|
||||
void
|
||||
#if defined (PREFER_STDARG)
|
||||
builtin_error (const char *format, ...)
|
||||
#else
|
||||
builtin_error (format, va_alist)
|
||||
const char *format;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (this_command_name && *this_command_name)
|
||||
fprintf (stderr, "%s: ", this_command_name);
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
#endif
|
||||
|
||||
vfprintf (stderr, format, args);
|
||||
va_end (args);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
#else
|
||||
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 /* !USE_VARARGS */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (c) 1994 Winning Strategies, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Winning Strategies, Inc.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* POSIX.2 getconf utility
|
||||
*
|
||||
* Written by:
|
||||
* J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id: getconf.c,v 1.2 1994/05/10 00:04:12 jtc Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "stdc.h"
|
||||
|
||||
|
||||
struct conf_variable
|
||||
{
|
||||
const char *name;
|
||||
enum { SYSCONF, CONFSTR, PATHCONF, CONSTANT } type;
|
||||
long value;
|
||||
};
|
||||
|
||||
/* BSD/OS does not define this; use Posix.2 recommended minimum value. */
|
||||
#ifndef _POSIX2_COLL_WEIGHTS_MAX
|
||||
#define _POSIX2_COLL_WEIGHTS_MAX 2
|
||||
#endif
|
||||
|
||||
static const struct conf_variable conf_table[] =
|
||||
{
|
||||
{ "PATH", CONFSTR, _CS_PATH },
|
||||
|
||||
/* Utility Limit Minimum Values */
|
||||
{ "POSIX2_BC_BASE_MAX", CONSTANT, _POSIX2_BC_BASE_MAX },
|
||||
{ "POSIX2_BC_DIM_MAX", CONSTANT, _POSIX2_BC_DIM_MAX },
|
||||
{ "POSIX2_BC_SCALE_MAX", CONSTANT, _POSIX2_BC_SCALE_MAX },
|
||||
{ "POSIX2_BC_STRING_MAX", CONSTANT, _POSIX2_BC_STRING_MAX },
|
||||
{ "POSIX2_COLL_WEIGHTS_MAX", CONSTANT, _POSIX2_COLL_WEIGHTS_MAX },
|
||||
{ "POSIX2_EXPR_NEST_MAX", CONSTANT, _POSIX2_EXPR_NEST_MAX },
|
||||
{ "POSIX2_LINE_MAX", CONSTANT, _POSIX2_LINE_MAX },
|
||||
{ "POSIX2_RE_DUP_MAX", CONSTANT, _POSIX2_RE_DUP_MAX },
|
||||
{ "POSIX2_VERSION", CONSTANT, _POSIX2_VERSION },
|
||||
|
||||
/* POSIX.1 Minimum Values */
|
||||
{ "_POSIX_ARG_MAX", CONSTANT, _POSIX_ARG_MAX },
|
||||
{ "_POSIX_CHILD_MAX", CONSTANT, _POSIX_CHILD_MAX },
|
||||
{ "_POSIX_LINK_MAX", CONSTANT, _POSIX_LINK_MAX },
|
||||
{ "_POSIX_MAX_CANON", CONSTANT, _POSIX_MAX_CANON },
|
||||
{ "_POSIX_MAX_INPUT", CONSTANT, _POSIX_MAX_INPUT },
|
||||
{ "_POSIX_NAME_MAX", CONSTANT, _POSIX_NAME_MAX },
|
||||
{ "_POSIX_NGROUPS_MAX", CONSTANT, _POSIX_NGROUPS_MAX },
|
||||
{ "_POSIX_OPEN_MAX", CONSTANT, _POSIX_OPEN_MAX },
|
||||
{ "_POSIX_PATH_MAX", CONSTANT, _POSIX_PIPE_BUF },
|
||||
{ "_POSIX_PIPE_BUF", CONSTANT, _POSIX_PIPE_BUF },
|
||||
{ "_POSIX_SSIZE_MAX", CONSTANT, _POSIX_SSIZE_MAX },
|
||||
{ "_POSIX_STREAM_MAX", CONSTANT, _POSIX_STREAM_MAX },
|
||||
{ "_POSIX_TZNAME_MAX", CONSTANT, _POSIX_TZNAME_MAX },
|
||||
|
||||
/* Symbolic Utility Limits */
|
||||
{ "BC_BASE_MAX", SYSCONF, _SC_BC_BASE_MAX },
|
||||
{ "BC_DIM_MAX", SYSCONF, _SC_BC_DIM_MAX },
|
||||
{ "BC_SCALE_MAX", SYSCONF, _SC_BC_SCALE_MAX },
|
||||
{ "BC_STRING_MAX", SYSCONF, _SC_BC_STRING_MAX },
|
||||
{ "COLL_WEIGHTS_MAX", SYSCONF, _SC_COLL_WEIGHTS_MAX },
|
||||
{ "EXPR_NEST_MAX", SYSCONF, _SC_EXPR_NEST_MAX },
|
||||
{ "LINE_MAX", SYSCONF, _SC_LINE_MAX },
|
||||
{ "RE_DUP_MAX", SYSCONF, _SC_RE_DUP_MAX },
|
||||
|
||||
/* Optional Facility Configuration Values */
|
||||
{ "POSIX2_C_BIND", SYSCONF, _SC_2_C_BIND },
|
||||
{ "POSIX2_C_DEV", SYSCONF, _SC_2_C_DEV },
|
||||
{ "POSIX2_CHAR_TERM", SYSCONF, _SC_2_CHAR_TERM },
|
||||
{ "POSIX2_FORT_DEV", SYSCONF, _SC_2_FORT_DEV },
|
||||
{ "POSIX2_FORT_RUN", SYSCONF, _SC_2_FORT_RUN },
|
||||
{ "POSIX2_LOCALEDEF", SYSCONF, _SC_2_LOCALEDEF },
|
||||
{ "POSIX2_SW_DEV", SYSCONF, _SC_2_SW_DEV },
|
||||
{ "POSIX2_UPE", SYSCONF, _SC_2_UPE },
|
||||
|
||||
/* POSIX.1 Configurable System Variables */
|
||||
{ "ARG_MAX", SYSCONF, _SC_ARG_MAX },
|
||||
{ "CHILD_MAX", SYSCONF, _SC_CHILD_MAX },
|
||||
{ "CLK_TCK", SYSCONF, _SC_CLK_TCK },
|
||||
{ "NGROUPS_MAX", SYSCONF, _SC_NGROUPS_MAX },
|
||||
{ "OPEN_MAX", SYSCONF, _SC_OPEN_MAX },
|
||||
{ "STREAM_MAX", SYSCONF, _SC_STREAM_MAX },
|
||||
{ "TZNAME_MAX", SYSCONF, _SC_TZNAME_MAX },
|
||||
{ "_POSIX_JOB_CONTROL", SYSCONF, _SC_JOB_CONTROL },
|
||||
{ "_POSIX_SAVED_IDS", SYSCONF, _SC_SAVED_IDS },
|
||||
{ "_POSIX_VERSION", SYSCONF, _SC_VERSION },
|
||||
|
||||
{ "LINK_MAX", PATHCONF, _PC_LINK_MAX },
|
||||
{ "MAX_CANON", PATHCONF, _PC_MAX_CANON },
|
||||
{ "MAX_INPUT", PATHCONF, _PC_MAX_INPUT },
|
||||
{ "NAME_MAX", PATHCONF, _PC_NAME_MAX },
|
||||
{ "PATH_MAX", PATHCONF, _PC_PATH_MAX },
|
||||
{ "PIPE_BUF", PATHCONF, _PC_PIPE_BUF },
|
||||
{ "_POSIX_CHOWN_RESTRICTED", PATHCONF, _PC_CHOWN_RESTRICTED },
|
||||
{ "_POSIX_NO_TRUNC", PATHCONF, _PC_NO_TRUNC },
|
||||
{ "_POSIX_VDISABLE", PATHCONF, _PC_VDISABLE },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
extern char *this_command_name;
|
||||
extern char *xmalloc ();
|
||||
extern char **make_builtin_argv ();
|
||||
static int getconf_main ();
|
||||
|
||||
int
|
||||
getconf_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int c, r;
|
||||
char **v;
|
||||
WORD_LIST *l;
|
||||
|
||||
v = make_builtin_argv (list, &c);
|
||||
r = getconf_main (c, v);
|
||||
free (v);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
getconf_main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int ch;
|
||||
const struct conf_variable *cp;
|
||||
|
||||
long val;
|
||||
size_t slen;
|
||||
char *sval;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != -1) {
|
||||
switch (ch) {
|
||||
case '?':
|
||||
default:
|
||||
builtin_usage();
|
||||
return(EX_USAGE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1 || argc > 2) {
|
||||
builtin_usage();
|
||||
return(EX_USAGE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
for (cp = conf_table; cp->name != NULL; cp++) {
|
||||
if (strcmp(*argv, cp->name) == 0)
|
||||
break;
|
||||
}
|
||||
if (cp->name == NULL) {
|
||||
builtin_error ("%s: unknown variable", *argv);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (cp->type == PATHCONF) {
|
||||
if (argc != 2) {
|
||||
builtin_usage();
|
||||
return(EX_USAGE);
|
||||
}
|
||||
} else {
|
||||
if (argc != 1) {
|
||||
builtin_usage();
|
||||
return(EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
switch (cp->type) {
|
||||
case CONSTANT:
|
||||
printf("%ld\n", cp->value);
|
||||
break;
|
||||
|
||||
case CONFSTR:
|
||||
slen = confstr (cp->value, (char *) 0, (size_t) 0);
|
||||
|
||||
sval = xmalloc(slen);
|
||||
|
||||
confstr(cp->value, sval, slen);
|
||||
printf("%s\n", sval);
|
||||
break;
|
||||
|
||||
case SYSCONF:
|
||||
errno = 0;
|
||||
if ((val = sysconf(cp->value)) == -1) {
|
||||
if (errno != 0) {
|
||||
builtin_error ("%s", strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
printf ("undefined\n");
|
||||
} else {
|
||||
printf("%ld\n", val);
|
||||
}
|
||||
break;
|
||||
|
||||
case PATHCONF:
|
||||
errno = 0;
|
||||
if ((val = pathconf(argv[1], cp->value)) == -1) {
|
||||
if (errno != 0) {
|
||||
builtin_error ("%s: %s", argv[1], strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
printf ("undefined\n");
|
||||
} else {
|
||||
printf ("%ld\n", val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (ferror(stdout) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
static char *getconf_doc[] = {
|
||||
"getconf writes the current value of a configurable system limit or",
|
||||
"option variable to the standard output.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin getconf_struct = {
|
||||
"getconf",
|
||||
getconf_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
getconf_doc,
|
||||
"getconf sysvar or getconf pathvar pathname",
|
||||
0
|
||||
};
|
||||
@@ -0,0 +1,143 @@
|
||||
/* head - copy first part of files. */
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "bashtypes.h"
|
||||
#include "posixstat.h"
|
||||
#include "filecntl.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
static void
|
||||
munge_list (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
WORD_LIST *l, *nl;
|
||||
WORD_DESC *wd;
|
||||
char *arg;
|
||||
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
arg = l->word->word;
|
||||
if (arg[0] != '-' || arg[1] == '-' || (isdigit(arg[1]) == 0))
|
||||
return;
|
||||
/* We have -[0-9]* */
|
||||
wd = make_bare_word (arg+1);
|
||||
nl = make_word_list (wd, l->next);
|
||||
l->word->word[1] = 'n';
|
||||
l->word->word[2] = '\0';
|
||||
l->next = nl;
|
||||
l = nl; /* skip over new argument */
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
file_head (fp, cnt)
|
||||
FILE *fp;
|
||||
int cnt;
|
||||
{
|
||||
int ch;
|
||||
|
||||
while (cnt--)
|
||||
{
|
||||
while ((ch = getc (fp)) != EOF)
|
||||
{
|
||||
if (putchar (ch) == EOF)
|
||||
{
|
||||
builtin_error ("write error: %s", strerror (errno));
|
||||
return EXECUTION_FAILURE;
|
||||
}
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
head_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int nline, opt, rval;
|
||||
WORD_LIST *l;
|
||||
FILE *fp;
|
||||
|
||||
char *t;
|
||||
|
||||
munge_list (list); /* change -num into -n num */
|
||||
|
||||
reset_internal_getopt ();
|
||||
nline = 10;
|
||||
while ((opt = internal_getopt (list, "n:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'n':
|
||||
nline = atoi (list_optarg);
|
||||
if (nline <= 0)
|
||||
{
|
||||
builtin_error ("bad line count: %s", list_optarg);
|
||||
return (EX_USAGE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
if (list == 0)
|
||||
return (file_head (stdin, nline));
|
||||
|
||||
for (rval = EXECUTION_SUCCESS, opt = 1, l = list; l; l = l->next)
|
||||
{
|
||||
fp = fopen (l->word->word, "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
builtin_error ("%s: %s", l->word->word, strerror (errno));
|
||||
continue;
|
||||
}
|
||||
if (list->next) /* more than one file */
|
||||
{
|
||||
printf ("%s==> %s <==\n", opt ? "" : "\n", l->word->word);
|
||||
opt = 0;
|
||||
}
|
||||
rval = file_head (fp, nline);
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
char *head_doc[] = {
|
||||
"Copy the first N lines from the input files to the standard output.",
|
||||
"N is supplied as an argument to the `-n' option. If N is not given,",
|
||||
"the first ten lines are copied.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin head_struct = {
|
||||
"head", /* builtin name */
|
||||
head_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
head_doc, /* array of long documentation strings. */
|
||||
"head [-n num] [file ...]", /* usage synopsis; becomes short_doc */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
/* Sample builtin to be dynamically loaded with enable -f and create a new
|
||||
builtin. */
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
|
||||
/* A builtin `xxx' is normally implemented with an `xxx_builtin' function.
|
||||
If you're converting a command that uses the normal Unix argc/argv
|
||||
calling convention, use argv = word_list_to_argv (list, &argc) and call
|
||||
the original `main' something like `xxx_main'. Look at cat.c for an
|
||||
example.
|
||||
|
||||
Builtins should use internal_getopt to parse options. It is the same as
|
||||
getopt(3), but it takes a WORD_LIST *. Look at print.c for an example
|
||||
of its use.
|
||||
|
||||
If the builtin takes no options, call no_options(list) before doing
|
||||
anything else. If it returns a non-zero value, your builtin should
|
||||
immediately return EX_USAGE. Look at logname.c for an example.
|
||||
|
||||
A builtin command returns EXECUTION_SUCCESS for success and
|
||||
EXECUTION_FAILURE to indicate failure. */
|
||||
hello_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
printf("hello world\n");
|
||||
fflush (stdout);
|
||||
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. */
|
||||
char *hello_doc[] = {
|
||||
"this is the long doc for the sample hello builtin",
|
||||
"which is a bare-bones echo",
|
||||
(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 hello_struct = {
|
||||
"hello", /* builtin name */
|
||||
hello_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
hello_doc, /* array of long documentation strings. */
|
||||
"hello [args]", /* usage synopsis; becomes short_doc */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/* logname - print login name of current user */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
logname_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char *np;
|
||||
|
||||
if (no_options (list))
|
||||
return (EX_USAGE);
|
||||
|
||||
np = getlogin ();
|
||||
if (np == 0)
|
||||
{
|
||||
builtin_error ("cannot find username: %s", strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
printf ("%s\n", np);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
char *logname_doc[] = {
|
||||
"write the current user's login name to the standard output",
|
||||
"and exit. logname ignores the LOGNAME and USER variables.",
|
||||
"logname ignores any non-option arguments.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin logname_struct = {
|
||||
"logname",
|
||||
logname_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
logname_doc,
|
||||
"logname",
|
||||
0
|
||||
};
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/* necho - echo without options or argument interpretation */
|
||||
|
||||
/* Sample builtin to be dynamically loaded with enable -f and replace an
|
||||
existing builtin. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
|
||||
necho_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
print_word_list (list, " ");
|
||||
printf("\n");
|
||||
fflush (stdout);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
char *necho_doc[] = {
|
||||
"Print the arguments to the standard ouput separated",
|
||||
"by space characters and terminated with a newline.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin echo_struct = {
|
||||
"echo",
|
||||
necho_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
necho_doc,
|
||||
"echo [args]",
|
||||
0
|
||||
};
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
/* pathchk - check pathnames for validity and portability */
|
||||
|
||||
/* Usage: pathchk [-p] path ...
|
||||
|
||||
For each PATH, print a message if any of these conditions are false:
|
||||
* all existing leading directories in PATH have search (execute) permission
|
||||
* strlen (PATH) <= PATH_MAX
|
||||
* strlen (each_directory_in_PATH) <= NAME_MAX
|
||||
|
||||
Exit status:
|
||||
0 All PATH names passed all of the tests.
|
||||
1 An error occurred.
|
||||
|
||||
Options:
|
||||
-p Instead of performing length checks on the
|
||||
underlying filesystem, test the length of the
|
||||
pathname and its components against the POSIX.1
|
||||
minimum limits for portability, _POSIX_NAME_MAX
|
||||
and _POSIX_PATH_MAX in 2.9.2. Also check that
|
||||
the pathname contains no character not in the
|
||||
portable filename character set. */
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "posixstat.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LIMITS_H)
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "stdc.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "maxpath.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if !defined (_POSIX_PATH_MAX)
|
||||
# define _POSIX_PATH_MAX 255
|
||||
#endif
|
||||
#if !defined (_POSIX_NAME_MAX)
|
||||
# define _POSIX_NAME_MAX 14
|
||||
#endif
|
||||
|
||||
/* How do we get PATH_MAX? */
|
||||
#if defined (_POSIX_VERSION) && !defined (PATH_MAX)
|
||||
# define PATH_MAX_FOR(p) pathconf ((p), _PC_PATH_MAX)
|
||||
#endif
|
||||
|
||||
/* How do we get NAME_MAX? */
|
||||
#if defined (_POSIX_VERSION) && !defined (NAME_MAX)
|
||||
# define NAME_MAX_FOR(p) pathconf ((p), _PC_NAME_MAX)
|
||||
#endif
|
||||
|
||||
#if !defined (PATH_MAX_FOR)
|
||||
# define PATH_MAX_FOR(p) PATH_MAX
|
||||
#endif
|
||||
|
||||
#if !defined (NAME_MAX_FOR)
|
||||
# define NAME_MAX_FOR(p) NAME_MAX
|
||||
#endif
|
||||
|
||||
extern char *strerror ();
|
||||
|
||||
static int validate_path ();
|
||||
|
||||
pathchk_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int retval, pflag, opt;
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "p")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
for (retval = 0; list; list = list->next)
|
||||
retval |= validate_path (list->word->word, pflag);
|
||||
|
||||
return (retval ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
char *pathchk_doc[] = {
|
||||
"Check each pathname argument for validity (i.e., it may be used to",
|
||||
"create or access a file without casuing 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
|
||||
};
|
||||
|
||||
/* The standard structure describing a builtin command. bash keeps an array
|
||||
of these structures. */
|
||||
struct builtin pathchk_struct = {
|
||||
"pathchk", /* builtin name */
|
||||
pathchk_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
pathchk_doc, /* array of long documentation strings. */
|
||||
"pathchk [-p] pathname ...", /* usage synopsis */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
|
||||
/* The remainder of this file is stolen shamelessly from `pathchk.c' in
|
||||
the sh-utils-1.12 distribution, by
|
||||
|
||||
David MacKenzie <djm@gnu.ai.mit.edu>
|
||||
and Jim Meyering <meyering@cs.utexas.edu> */
|
||||
|
||||
/* Each element is nonzero if the corresponding ASCII character is
|
||||
in the POSIX portable character set, and zero if it is not.
|
||||
In addition, the entry for `/' is nonzero to simplify checking. */
|
||||
static char const portable_chars[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-15 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-31 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, /* 32-47 */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 48-63 */
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64-79 */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 80-95 */
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 96-111 */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 112-127 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* If PATH contains only portable characters, return 1, else 0. */
|
||||
|
||||
static int
|
||||
portable_chars_only (path)
|
||||
const char *path;
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for (p = path; *p; ++p)
|
||||
if (portable_chars[(const unsigned char) *p] == 0)
|
||||
{
|
||||
error (0, 0, "path `%s' contains nonportable character `%c'",
|
||||
path, *p);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* On some systems, stat can return EINTR. */
|
||||
|
||||
#ifndef EINTR
|
||||
# define SAFE_STAT(name, buf) stat (name, buf)
|
||||
#else
|
||||
# define SAFE_STAT(name, buf) safe_stat (name, buf)
|
||||
static inline int
|
||||
safe_stat (name, buf)
|
||||
const char *name;
|
||||
struct stat *buf;
|
||||
{
|
||||
int ret;
|
||||
|
||||
do
|
||||
ret = stat (name, buf);
|
||||
while (ret < 0 && errno == EINTR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return 1 if PATH is a usable leading directory, 0 if not,
|
||||
2 if it doesn't exist. */
|
||||
|
||||
static int
|
||||
dir_ok (path)
|
||||
const char *path;
|
||||
{
|
||||
struct stat stats;
|
||||
|
||||
if (SAFE_STAT (path, &stats))
|
||||
return 2;
|
||||
|
||||
if (!S_ISDIR (stats.st_mode))
|
||||
{
|
||||
error (0, 0, "`%s' is not a directory", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use access to test for search permission because
|
||||
testing permission bits of st_mode can lose with new
|
||||
access control mechanisms. Of course, access loses if you're
|
||||
running setuid. */
|
||||
if (access (path, X_OK) != 0)
|
||||
{
|
||||
if (errno == EACCES)
|
||||
builtin_error ("directory `%s' is not searchable", path);
|
||||
else
|
||||
builtin_error ("%s: %s", path, strerror (errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *
|
||||
xstrdup (s)
|
||||
char *s;
|
||||
{
|
||||
return (savestring (s));
|
||||
}
|
||||
|
||||
/* Make sure that
|
||||
strlen (PATH) <= PATH_MAX
|
||||
&& strlen (each-existing-directory-in-PATH) <= NAME_MAX
|
||||
|
||||
If PORTABILITY is nonzero, compare against _POSIX_PATH_MAX and
|
||||
_POSIX_NAME_MAX instead, and make sure that PATH contains no
|
||||
characters not in the POSIX portable filename character set, which
|
||||
consists of A-Z, a-z, 0-9, ., _, -.
|
||||
|
||||
Make sure that all leading directories along PATH that exist have
|
||||
`x' permission.
|
||||
|
||||
Return 0 if all of these tests are successful, 1 if any fail. */
|
||||
|
||||
static int
|
||||
validate_path (path, portability)
|
||||
char *path;
|
||||
int portability;
|
||||
{
|
||||
int path_max;
|
||||
int last_elem; /* Nonzero if checking last element of path. */
|
||||
int exists; /* 2 if the path element exists. */
|
||||
char *slash;
|
||||
char *parent; /* Last existing leading directory so far. */
|
||||
|
||||
if (portability && !portable_chars_only (path))
|
||||
return 1;
|
||||
|
||||
if (*path == '\0')
|
||||
return 0;
|
||||
|
||||
#ifdef lint
|
||||
/* Suppress `used before initialized' warning. */
|
||||
exists = 0;
|
||||
#endif
|
||||
|
||||
/* Figure out the parent of the first element in PATH. */
|
||||
parent = xstrdup (*path == '/' ? "/" : ".");
|
||||
|
||||
slash = path;
|
||||
last_elem = 0;
|
||||
while (1)
|
||||
{
|
||||
int name_max;
|
||||
int length; /* Length of partial path being checked. */
|
||||
char *start; /* Start of path element being checked. */
|
||||
|
||||
/* Find the end of this element of the path.
|
||||
Then chop off the rest of the path after this element. */
|
||||
while (*slash == '/')
|
||||
slash++;
|
||||
start = slash;
|
||||
slash = strchr (slash, '/');
|
||||
if (slash != NULL)
|
||||
*slash = '\0';
|
||||
else
|
||||
{
|
||||
last_elem = 1;
|
||||
slash = strchr (start, '\0');
|
||||
}
|
||||
|
||||
if (!last_elem)
|
||||
{
|
||||
exists = dir_ok (path);
|
||||
if (dir_ok == 0)
|
||||
{
|
||||
free (parent);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
length = slash - start;
|
||||
/* Since we know that `parent' is a directory, it's ok to call
|
||||
pathconf with it as the argument. (If `parent' isn't a directory
|
||||
or doesn't exist, the behavior of pathconf is undefined.)
|
||||
But if `parent' is a directory and is on a remote file system,
|
||||
it's likely that pathconf can't give us a reasonable value
|
||||
and will return -1. (NFS and tempfs are not POSIX . . .)
|
||||
In that case, we have no choice but to assume the pessimal
|
||||
POSIX minimums. */
|
||||
name_max = portability ? _POSIX_NAME_MAX : NAME_MAX_FOR (parent);
|
||||
if (name_max < 0)
|
||||
name_max = _POSIX_NAME_MAX;
|
||||
if (length > name_max)
|
||||
{
|
||||
error (0, 0, "name `%s' has length %d; exceeds limit of %d",
|
||||
start, length, name_max);
|
||||
free (parent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (last_elem)
|
||||
break;
|
||||
|
||||
if (exists == 1)
|
||||
{
|
||||
free (parent);
|
||||
parent = xstrdup (path);
|
||||
}
|
||||
|
||||
*slash++ = '/';
|
||||
}
|
||||
|
||||
/* `parent' is now the last existing leading directory in the whole path,
|
||||
so it's ok to call pathconf with it as the argument. */
|
||||
path_max = portability ? _POSIX_PATH_MAX : PATH_MAX_FOR (parent);
|
||||
if (path_max < 0)
|
||||
path_max = _POSIX_PATH_MAX;
|
||||
free (parent);
|
||||
if (strlen (path) > path_max)
|
||||
{
|
||||
error (0, 0, "path `%s' has length %d; exceeds limit of %d",
|
||||
path, strlen (path), path_max);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "stdc.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#define PF(f, func) { \
|
||||
if (fieldwidth) \
|
||||
if (precision) \
|
||||
(void)fprintf(ofp, f, fieldwidth, precision, func); \
|
||||
else \
|
||||
(void)fprintf(ofp, f, fieldwidth, func); \
|
||||
else if (precision) \
|
||||
(void)fprintf(ofp, f, precision, func); \
|
||||
else \
|
||||
(void)fprintf(ofp, f, func); \
|
||||
}
|
||||
|
||||
static int asciicode __P((void));
|
||||
static void escape __P((char *));
|
||||
static int getchr __P((void));
|
||||
static double getdouble __P((void));
|
||||
static int getint __P((int *));
|
||||
static int getlong __P((long *));
|
||||
static char *getstr __P((void));
|
||||
static char *mklong __P((char *, int));
|
||||
static void usage __P((void));
|
||||
|
||||
static char **gargv;
|
||||
|
||||
int print_builtin ();
|
||||
static int printf_main ();
|
||||
static int printargs ();
|
||||
|
||||
static FILE *ofp;
|
||||
|
||||
extern char *ansicstr ();
|
||||
extern char *single_quote ();
|
||||
extern char **make_builtin_argv ();
|
||||
|
||||
extern char *this_command_name;
|
||||
|
||||
extern int optind;
|
||||
|
||||
static char *print_doc[] = {
|
||||
"Output the arguments. The -f option means to use the argument as a",
|
||||
"format string as would be supplied to printf(1). The rest of the",
|
||||
"options are as in ksh.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin print_struct = {
|
||||
"print",
|
||||
print_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
print_doc,
|
||||
"print [-Rnprs] [-u unit] [-f format] [arguments]",
|
||||
(char *)0
|
||||
};
|
||||
|
||||
#ifndef ISOPTION
|
||||
#define ISOPTION(s, c) (s[0] == '-' && s[2] == '\0' && s[1] == c)
|
||||
#endif
|
||||
|
||||
int
|
||||
print_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int c, r, nflag, raw, ofd, sflag;
|
||||
char **v, *pfmt, *arg;
|
||||
WORD_LIST *l;
|
||||
|
||||
nflag = raw = sflag = 0;
|
||||
ofd = 1;
|
||||
pfmt = 0;
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((c = internal_getopt (list, "Rnprsu:f:")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'R':
|
||||
raw = 2;
|
||||
loptend = lcurrent;
|
||||
if (loptend && ISOPTION (loptend->word->word, 'n'))
|
||||
{
|
||||
loptend = loptend->next;
|
||||
nflag = 1;
|
||||
}
|
||||
goto opt_end;
|
||||
case 'r':
|
||||
raw = 1;
|
||||
break;
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
case 'p':
|
||||
break; /* NOP */
|
||||
case 'u':
|
||||
if (all_digits (list_optarg))
|
||||
ofd = atoi (list_optarg);
|
||||
else
|
||||
{
|
||||
for (l = list; l->next && l->next != lcurrent; l = l->next);
|
||||
lcurrent = loptend = l;
|
||||
goto opt_end;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
pfmt = list_optarg;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
opt_end:
|
||||
list = loptend;
|
||||
|
||||
ofp = (ofd == 1) ? stdout : fdopen (dup (ofd), "w");
|
||||
|
||||
if (pfmt)
|
||||
{
|
||||
v = word_list_to_argv (list, 0, 2, &c);
|
||||
v[0] = this_command_name;
|
||||
v[1] = pfmt;
|
||||
r = printf_main (c, v);
|
||||
free (v);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (raw)
|
||||
{
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
fprintf (ofp, "%s", l->word->word);
|
||||
if (l->next)
|
||||
fprintf (ofp, " ");
|
||||
}
|
||||
if (nflag == 0)
|
||||
fprintf (ofp, "\n");
|
||||
fflush (ofp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
r = printargs (list, ofp);
|
||||
if (r && nflag == 0)
|
||||
fprintf (ofp, "\n");
|
||||
if (ofd != 1)
|
||||
fclose (ofp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int printargs (list, ofp)
|
||||
WORD_LIST *list;
|
||||
FILE *ofp;
|
||||
{
|
||||
WORD_LIST *l;
|
||||
char *ostr;
|
||||
int sawc;
|
||||
|
||||
for (sawc = 0, l = list; l; l = l->next)
|
||||
{
|
||||
ostr = ansicstr (l->word->word, strlen (l->word->word), &sawc);
|
||||
fprintf (ofp, "%s", ostr);
|
||||
free (ostr);
|
||||
if (sawc)
|
||||
return (0);
|
||||
if (l->next)
|
||||
fprintf (ofp, " ");
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
printf_main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
static char *skip1, *skip2;
|
||||
int ch, end, fieldwidth, precision;
|
||||
char convch, nextch, *format, *fmt, *start;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch (ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic algorithm is to scan the format string for conversion
|
||||
* specifications -- once one is found, find out if the field
|
||||
* width or precision is a '*'; if it is, gather up value. Note,
|
||||
* format strings are reused as necessary to use up the provided
|
||||
* arguments, arguments of zero/null string are provided to use
|
||||
* up the format string.
|
||||
*/
|
||||
skip1 = "#-+ 0";
|
||||
skip2 = "*0123456789";
|
||||
|
||||
escape(fmt = format = *argv); /* backslash interpretation */
|
||||
gargv = ++argv;
|
||||
for (;;) {
|
||||
end = 0;
|
||||
/* find next format specification */
|
||||
next: for (start = fmt;; ++fmt) {
|
||||
if (!*fmt) {
|
||||
/* avoid infinite loop */
|
||||
if (end == 1) {
|
||||
warnx("missing format character",
|
||||
NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
end = 1;
|
||||
if (fmt > start)
|
||||
(void)printf("%s", start);
|
||||
if (!*gargv)
|
||||
return (0);
|
||||
fmt = format;
|
||||
goto next;
|
||||
}
|
||||
/* %% prints a % */
|
||||
if (*fmt == '%') {
|
||||
if (*++fmt != '%')
|
||||
break;
|
||||
*fmt++ = '\0';
|
||||
(void)printf("%s", start);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip to field width */
|
||||
for (; strchr(skip1, *fmt); ++fmt);
|
||||
if (*fmt == '*') {
|
||||
if (getint(&fieldwidth))
|
||||
return (1);
|
||||
} else
|
||||
fieldwidth = 0;
|
||||
|
||||
/* skip to possible '.', get following precision */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (*fmt == '.')
|
||||
++fmt;
|
||||
if (*fmt == '*') {
|
||||
if (getint(&precision))
|
||||
return (1);
|
||||
} else
|
||||
precision = 0;
|
||||
|
||||
/* skip to conversion char */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (!*fmt) {
|
||||
warnx("missing format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
|
||||
convch = *fmt;
|
||||
nextch = *++fmt;
|
||||
*fmt = '\0';
|
||||
switch(convch) {
|
||||
case 'c': {
|
||||
char p;
|
||||
|
||||
p = getchr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 'b': { /* expand escapes in argument */
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
escape(p);
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 'q': { /* print with shell single quoting */
|
||||
char *p, *p2;
|
||||
|
||||
p = getstr();
|
||||
p2 = single_quote(p);
|
||||
PF(start, p2);
|
||||
free(p2);
|
||||
break;
|
||||
}
|
||||
case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
|
||||
long p;
|
||||
char *f;
|
||||
|
||||
if ((f = mklong(start, convch)) == NULL)
|
||||
return (1);
|
||||
if (getlong(&p))
|
||||
return (1);
|
||||
PF(f, p);
|
||||
break;
|
||||
}
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G': {
|
||||
double p;
|
||||
|
||||
p = getdouble();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warnx("illegal format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
*fmt = nextch;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static char *
|
||||
mklong(str, ch)
|
||||
char *str;
|
||||
int ch;
|
||||
{
|
||||
static char copy[64];
|
||||
int len;
|
||||
|
||||
len = strlen(str) + 2;
|
||||
memmove(copy, str, len - 3);
|
||||
copy[len - 3] = 'l';
|
||||
copy[len - 2] = ch;
|
||||
copy[len - 1] = '\0';
|
||||
return (copy);
|
||||
}
|
||||
|
||||
static void
|
||||
escape(fmt)
|
||||
register char *fmt;
|
||||
{
|
||||
register char *store;
|
||||
register int value, c;
|
||||
|
||||
for (store = fmt; c = *fmt; ++fmt, ++store) {
|
||||
if (c != '\\') {
|
||||
*store = c;
|
||||
continue;
|
||||
}
|
||||
switch (*++fmt) {
|
||||
case '\0': /* EOS, user error */
|
||||
*store = '\\';
|
||||
*++store = '\0';
|
||||
return;
|
||||
case '\\': /* backslash */
|
||||
case '\'': /* single quote */
|
||||
*store = *fmt;
|
||||
break;
|
||||
case 'a': /* bell/alert */
|
||||
*store = '\7';
|
||||
break;
|
||||
case 'b': /* backspace */
|
||||
*store = '\b';
|
||||
break;
|
||||
case 'c':
|
||||
return;
|
||||
case 'e':
|
||||
case 'E':
|
||||
*store = '\033';
|
||||
break;
|
||||
case 'f': /* form-feed */
|
||||
*store = '\f';
|
||||
break;
|
||||
case 'n': /* newline */
|
||||
*store = '\n';
|
||||
break;
|
||||
case 'r': /* carriage-return */
|
||||
*store = '\r';
|
||||
break;
|
||||
case 't': /* horizontal tab */
|
||||
*store = '\t';
|
||||
break;
|
||||
case 'v': /* vertical tab */
|
||||
*store = '\13';
|
||||
break;
|
||||
/* octal constant */
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
for (c = 3, value = 0;
|
||||
c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
|
||||
value <<= 3;
|
||||
value += *fmt - '0';
|
||||
}
|
||||
--fmt;
|
||||
*store = value;
|
||||
break;
|
||||
default:
|
||||
*store = *fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*store = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
getchr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ('\0');
|
||||
return ((int)**gargv++);
|
||||
}
|
||||
|
||||
static char *
|
||||
getstr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ("");
|
||||
return (*gargv++);
|
||||
}
|
||||
|
||||
static char *Number = "+-.0123456789";
|
||||
static int
|
||||
getint(ip)
|
||||
int *ip;
|
||||
{
|
||||
long val;
|
||||
|
||||
if (getlong(&val))
|
||||
return (1);
|
||||
if (val > INT_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
*ip = val;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getlong(lp)
|
||||
long *lp;
|
||||
{
|
||||
long val;
|
||||
char *ep;
|
||||
|
||||
if (!*gargv) {
|
||||
*lp = 0;
|
||||
return (0);
|
||||
}
|
||||
if (strchr(Number, **gargv)) {
|
||||
errno = 0;
|
||||
val = strtol(*gargv, &ep, 0);
|
||||
if (*ep != '\0') {
|
||||
warnx("%s: illegal number", *gargv, NULL);
|
||||
return (1);
|
||||
}
|
||||
if (errno == ERANGE)
|
||||
if (val == LONG_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
if (val == LONG_MIN) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
|
||||
*lp = val;
|
||||
++gargv;
|
||||
return (0);
|
||||
}
|
||||
*lp = (long)asciicode();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static double
|
||||
getdouble()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ((double)0);
|
||||
if (strchr(Number, **gargv))
|
||||
return (atof(*gargv++));
|
||||
return ((double)asciicode());
|
||||
}
|
||||
|
||||
static int
|
||||
asciicode()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
ch = **gargv;
|
||||
if (ch == '\'' || ch == '"')
|
||||
ch = (*gargv)[1];
|
||||
++gargv;
|
||||
return (ch);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: print [-Rnprs] [-u unit] [-f format] [arg ...]\n");
|
||||
}
|
||||
@@ -0,0 +1,460 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(BUILTIN) && !defined(SHELL)
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "stdc.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#define PF(f, func) { \
|
||||
if (fieldwidth) \
|
||||
if (precision) \
|
||||
(void)printf(f, fieldwidth, precision, func); \
|
||||
else \
|
||||
(void)printf(f, fieldwidth, func); \
|
||||
else if (precision) \
|
||||
(void)printf(f, precision, func); \
|
||||
else \
|
||||
(void)printf(f, func); \
|
||||
}
|
||||
|
||||
static int asciicode __P((void));
|
||||
static void escape __P((char *));
|
||||
static int getchr __P((void));
|
||||
static double getdouble __P((void));
|
||||
static int getint __P((int *));
|
||||
static int getlong __P((long *));
|
||||
static char *getstr __P((void));
|
||||
static char *mklong __P((char *, int));
|
||||
static void usage __P((void));
|
||||
|
||||
static char **gargv;
|
||||
|
||||
int printf_builtin ();
|
||||
static int printf_main ();
|
||||
extern char *this_command_name;
|
||||
extern char *single_quote ();
|
||||
extern char **make_builtin_argv ();
|
||||
|
||||
static char *printf_doc[] = {
|
||||
"printf formats and prints its arguments, after the first, under control",
|
||||
"of the format. The format is a character string which contains three",
|
||||
"types of objects: plain characters, which are simply copied to standard",
|
||||
"output, character escape sequences which are converted and copied to the",
|
||||
"standard output, and format specifications, each of which causes printing",
|
||||
"of the next successive argument. In addition to the standard printf(1)",
|
||||
"formats, %%b means to expand escapes in the corresponding argument, and",
|
||||
"%%q means to quote the argument in a way that can be reused as shell input.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin printf_struct = {
|
||||
"printf",
|
||||
printf_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
printf_doc,
|
||||
"printf format [arguments]",
|
||||
(char *)0
|
||||
};
|
||||
|
||||
int
|
||||
printf_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int c, r;
|
||||
char **v;
|
||||
WORD_LIST *l;
|
||||
|
||||
v = make_builtin_argv (list, &c);
|
||||
r = printf_main (c, v);
|
||||
free (v);
|
||||
fflush(stdout);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
printf_main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern int optind;
|
||||
static char *skip1, *skip2;
|
||||
int ch, end, fieldwidth, precision;
|
||||
char convch, nextch, *format, *fmt, *start;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch (ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic algorithm is to scan the format string for conversion
|
||||
* specifications -- once one is found, find out if the field
|
||||
* width or precision is a '*'; if it is, gather up value. Note,
|
||||
* format strings are reused as necessary to use up the provided
|
||||
* arguments, arguments of zero/null string are provided to use
|
||||
* up the format string.
|
||||
*/
|
||||
skip1 = "#-+ 0";
|
||||
skip2 = "*0123456789";
|
||||
|
||||
escape(fmt = format = *argv); /* backslash interpretation */
|
||||
gargv = ++argv;
|
||||
for (;;) {
|
||||
end = 0;
|
||||
/* find next format specification */
|
||||
next: for (start = fmt;; ++fmt) {
|
||||
if (!*fmt) {
|
||||
/* avoid infinite loop */
|
||||
if (end == 1) {
|
||||
warnx("missing format character",
|
||||
NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
end = 1;
|
||||
if (fmt > start)
|
||||
(void)printf("%s", start);
|
||||
if (!*gargv)
|
||||
return (0);
|
||||
fmt = format;
|
||||
goto next;
|
||||
}
|
||||
/* %% prints a % */
|
||||
if (*fmt == '%') {
|
||||
if (*++fmt != '%')
|
||||
break;
|
||||
*fmt++ = '\0';
|
||||
(void)printf("%s", start);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip to field width */
|
||||
for (; strchr(skip1, *fmt); ++fmt);
|
||||
if (*fmt == '*') {
|
||||
if (getint(&fieldwidth))
|
||||
return (1);
|
||||
} else
|
||||
fieldwidth = 0;
|
||||
|
||||
/* skip to possible '.', get following precision */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (*fmt == '.')
|
||||
++fmt;
|
||||
if (*fmt == '*') {
|
||||
if (getint(&precision))
|
||||
return (1);
|
||||
} else
|
||||
precision = 0;
|
||||
|
||||
/* skip to conversion char */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (!*fmt) {
|
||||
warnx("missing format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
|
||||
convch = *fmt;
|
||||
nextch = *++fmt;
|
||||
*fmt = '\0';
|
||||
switch(convch) {
|
||||
case 'c': {
|
||||
char p;
|
||||
|
||||
p = getchr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 'b': { /* expand escapes in argument */
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
escape(p);
|
||||
PF("%s", p);
|
||||
break;
|
||||
}
|
||||
case 'q': { /* print with shell single quoting */
|
||||
char *p, *p2;
|
||||
|
||||
p = getstr();
|
||||
p2 = single_quote(p);
|
||||
PF("%s", p2);
|
||||
free(p2);
|
||||
break;
|
||||
}
|
||||
case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
|
||||
long p;
|
||||
char *f;
|
||||
|
||||
if ((f = mklong(start, convch)) == NULL)
|
||||
return (1);
|
||||
if (getlong(&p))
|
||||
return (1);
|
||||
PF(f, p);
|
||||
break;
|
||||
}
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G': {
|
||||
double p;
|
||||
|
||||
p = getdouble();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warnx("illegal format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
*fmt = nextch;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static char *
|
||||
mklong(str, ch)
|
||||
char *str;
|
||||
int ch;
|
||||
{
|
||||
static char copy[64];
|
||||
int len;
|
||||
|
||||
len = strlen(str) + 2;
|
||||
memmove(copy, str, len - 3);
|
||||
copy[len - 3] = 'l';
|
||||
copy[len - 2] = ch;
|
||||
copy[len - 1] = '\0';
|
||||
return (copy);
|
||||
}
|
||||
|
||||
static void
|
||||
escape(fmt)
|
||||
register char *fmt;
|
||||
{
|
||||
register char *store;
|
||||
register int value, c;
|
||||
|
||||
for (store = fmt; c = *fmt; ++fmt, ++store) {
|
||||
if (c != '\\') {
|
||||
*store = c;
|
||||
continue;
|
||||
}
|
||||
switch (*++fmt) {
|
||||
case '\0': /* EOS, user error */
|
||||
*store = '\\';
|
||||
*++store = '\0';
|
||||
return;
|
||||
case '\\': /* backslash */
|
||||
case '\'': /* single quote */
|
||||
*store = *fmt;
|
||||
break;
|
||||
case 'a': /* bell/alert */
|
||||
*store = '\7';
|
||||
break;
|
||||
case 'b': /* backspace */
|
||||
*store = '\b';
|
||||
break;
|
||||
case 'c':
|
||||
return;
|
||||
case 'e':
|
||||
case 'E':
|
||||
*store = '\033';
|
||||
break;
|
||||
case 'f': /* form-feed */
|
||||
*store = '\f';
|
||||
break;
|
||||
case 'n': /* newline */
|
||||
*store = '\n';
|
||||
break;
|
||||
case 'r': /* carriage-return */
|
||||
*store = '\r';
|
||||
break;
|
||||
case 't': /* horizontal tab */
|
||||
*store = '\t';
|
||||
break;
|
||||
case 'v': /* vertical tab */
|
||||
*store = '\13';
|
||||
break;
|
||||
/* octal constant */
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
for (c = 3, value = 0;
|
||||
c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
|
||||
value <<= 3;
|
||||
value += *fmt - '0';
|
||||
}
|
||||
--fmt;
|
||||
*store = value;
|
||||
break;
|
||||
default:
|
||||
*store = *fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*store = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
getchr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ('\0');
|
||||
return ((int)**gargv++);
|
||||
}
|
||||
|
||||
static char *
|
||||
getstr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ("");
|
||||
return (*gargv++);
|
||||
}
|
||||
|
||||
static char *Number = "+-.0123456789";
|
||||
static int
|
||||
getint(ip)
|
||||
int *ip;
|
||||
{
|
||||
long val;
|
||||
|
||||
if (getlong(&val))
|
||||
return (1);
|
||||
if (val > INT_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
*ip = val;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getlong(lp)
|
||||
long *lp;
|
||||
{
|
||||
long val;
|
||||
char *ep;
|
||||
|
||||
if (!*gargv) {
|
||||
*lp = 0;
|
||||
return (0);
|
||||
}
|
||||
if (strchr(Number, **gargv)) {
|
||||
errno = 0;
|
||||
val = strtol(*gargv, &ep, 0);
|
||||
if (*ep != '\0') {
|
||||
warnx("%s: illegal number", *gargv, NULL);
|
||||
return (1);
|
||||
}
|
||||
if (errno == ERANGE)
|
||||
if (val == LONG_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
if (val == LONG_MIN) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
|
||||
*lp = val;
|
||||
++gargv;
|
||||
return (0);
|
||||
}
|
||||
*lp = (long)asciicode();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static double
|
||||
getdouble()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ((double)0);
|
||||
if (strchr(Number, **gargv))
|
||||
return (atof(*gargv++));
|
||||
return ((double)asciicode());
|
||||
}
|
||||
|
||||
static int
|
||||
asciicode()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
ch = **gargv;
|
||||
if (ch == '\'' || ch == '"')
|
||||
ch = (*gargv)[1];
|
||||
++gargv;
|
||||
return (ch);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: printf format [arg ...]\n");
|
||||
}
|
||||
@@ -0,0 +1,601 @@
|
||||
/* pushd.c, created from pushd.def. */
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <tilde/tilde.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "maxpath.h"
|
||||
#include "common.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
static char *m_badarg = "%s: bad argument";
|
||||
|
||||
/* The list of remembered directories. */
|
||||
static char **pushd_directory_list = (char **)NULL;
|
||||
|
||||
/* Number of existing slots in this list. */
|
||||
static int directory_list_size;
|
||||
|
||||
/* Offset to the end of the list. */
|
||||
static int directory_list_offset;
|
||||
|
||||
static void pushd_error ();
|
||||
static void clear_directory_stack ();
|
||||
static int cd_to_string ();
|
||||
static int change_to_temp ();
|
||||
static int get_dirstack_index ();
|
||||
static void add_dirstack_element ();
|
||||
|
||||
#define NOCD 0x01
|
||||
#define ROTATE 0x02
|
||||
#define LONGFORM 0x04
|
||||
#define CLEARSTAK 0x08
|
||||
|
||||
int
|
||||
pushd_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char *temp, *current_directory, *top;
|
||||
int j, flags;
|
||||
long num;
|
||||
char direction;
|
||||
|
||||
/* If there is no argument list then switch current and
|
||||
top of list. */
|
||||
if (list == 0)
|
||||
{
|
||||
if (directory_list_offset == 0)
|
||||
{
|
||||
builtin_error ("no other directory");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
current_directory = get_working_directory ("pushd");
|
||||
if (current_directory == 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
|
||||
j = directory_list_offset - 1;
|
||||
temp = pushd_directory_list[j];
|
||||
pushd_directory_list[j] = current_directory;
|
||||
j = change_to_temp (temp);
|
||||
free (temp);
|
||||
return j;
|
||||
}
|
||||
|
||||
for (flags = 0; list; list = list->next)
|
||||
{
|
||||
if (ISOPTION (list->word->word, 'n'))
|
||||
{
|
||||
flags |= NOCD;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, '-'))
|
||||
{
|
||||
list = list->next;
|
||||
break;
|
||||
}
|
||||
else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
|
||||
/* Let `pushd -' work like it used to. */
|
||||
break;
|
||||
else if (((direction = list->word->word[0]) == '+') || direction == '-')
|
||||
{
|
||||
if (legal_number (list->word->word + 1, &num) == 0)
|
||||
{
|
||||
builtin_error (m_badarg, list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (direction == '-')
|
||||
num = directory_list_offset - num;
|
||||
|
||||
if (num > directory_list_offset || num < 0)
|
||||
{
|
||||
pushd_error (directory_list_offset, list->word->word);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
flags |= ROTATE;
|
||||
}
|
||||
else if (*list->word->word == '-')
|
||||
{
|
||||
bad_option (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & ROTATE)
|
||||
{
|
||||
/* Rotate the stack num times. Remember, the current
|
||||
directory acts like it is part of the stack. */
|
||||
temp = get_working_directory ("pushd");
|
||||
|
||||
if (num == 0)
|
||||
{
|
||||
j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS;
|
||||
free (temp);
|
||||
return j;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
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);
|
||||
|
||||
j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS;
|
||||
free (temp);
|
||||
return j;
|
||||
}
|
||||
|
||||
if (list == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
|
||||
/* 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 == 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
|
||||
j = ((flags & NOCD) == 0) ? cd_builtin (list) : EXECUTION_SUCCESS;
|
||||
if (j == EXECUTION_SUCCESS)
|
||||
{
|
||||
add_dirstack_element ((flags & NOCD) ? savestring (list->word->word) : current_directory);
|
||||
dirs_builtin ((WORD_LIST *)NULL);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
free (current_directory);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
int
|
||||
popd_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
register int i;
|
||||
long which;
|
||||
int flags;
|
||||
char direction;
|
||||
|
||||
for (flags = 0, which = 0L, direction = '+'; list; list = list->next)
|
||||
{
|
||||
if (ISOPTION (list->word->word, 'n'))
|
||||
{
|
||||
flags |= NOCD;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, '-'))
|
||||
{
|
||||
list = list->next;
|
||||
break;
|
||||
}
|
||||
else if (((direction = list->word->word[0]) == '+') || direction == '-')
|
||||
{
|
||||
if (legal_number (list->word->word + 1, &which) == 0)
|
||||
{
|
||||
builtin_error (m_badarg, list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
else if (*list->word->word == '-')
|
||||
{
|
||||
bad_option (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (which > directory_list_offset || (directory_list_offset == 0 && which == 0))
|
||||
{
|
||||
pushd_error (directory_list_offset, list ? list->word->word : "");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
/* Handle case of no specification, or top of stack specification. */
|
||||
if ((direction == '+' && which == 0) ||
|
||||
(direction == '-' && which == directory_list_offset))
|
||||
{
|
||||
i = ((flags & NOCD) == 0) ? cd_to_string (pushd_directory_list[directory_list_offset - 1])
|
||||
: EXECUTION_SUCCESS;
|
||||
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. */
|
||||
i = (direction == '+') ? directory_list_offset - which : 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);
|
||||
}
|
||||
|
||||
/* Print the current list of directories on the directory stack. */
|
||||
int
|
||||
dirs_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int flags, desired_index, index_flag, vflag;
|
||||
long i;
|
||||
char *temp, *w;
|
||||
|
||||
for (flags = vflag = index_flag = 0, desired_index = -1, w = ""; list; list = list->next)
|
||||
{
|
||||
if (ISOPTION (list->word->word, 'l'))
|
||||
{
|
||||
flags |= LONGFORM;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, 'c'))
|
||||
{
|
||||
flags |= CLEARSTAK;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, 'v'))
|
||||
{
|
||||
vflag |= 2;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, 'p'))
|
||||
{
|
||||
vflag |= 1;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, '-'))
|
||||
{
|
||||
list = list->next;
|
||||
break;
|
||||
}
|
||||
else if (*list->word->word == '+' || *list->word->word == '-')
|
||||
{
|
||||
int sign;
|
||||
if (legal_number (w = list->word->word + 1, &i) == 0)
|
||||
{
|
||||
builtin_error (m_badarg, list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
sign = (*list->word->word == '+') ? 1 : -1;
|
||||
desired_index = get_dirstack_index (i, sign, &index_flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
bad_option (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & CLEARSTAK)
|
||||
{
|
||||
clear_directory_stack ();
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
if (index_flag && (desired_index < 0 || desired_index > directory_list_offset))
|
||||
{
|
||||
pushd_error (directory_list_offset, w);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
#define DIRSTACK_FORMAT(temp) \
|
||||
(flags & LONGFORM) ? temp : polite_directory_format (temp)
|
||||
|
||||
/* The first directory printed is always the current working directory. */
|
||||
if (index_flag == 0 || (index_flag == 1 && desired_index == 0))
|
||||
{
|
||||
temp = get_working_directory ("dirs");
|
||||
if (temp == 0)
|
||||
temp = savestring ("<no current directory>");
|
||||
if (vflag & 2)
|
||||
printf ("%2d %s", 0, DIRSTACK_FORMAT (temp));
|
||||
else
|
||||
printf ("%s", DIRSTACK_FORMAT (temp));
|
||||
free (temp);
|
||||
if (index_flag)
|
||||
{
|
||||
putchar ('\n');
|
||||
return EXECUTION_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
#define DIRSTACK_ENTRY(i) \
|
||||
(flags & LONGFORM) ? pushd_directory_list[i] \
|
||||
: polite_directory_format (pushd_directory_list[i])
|
||||
|
||||
/* Now print the requested directory stack entries. */
|
||||
if (index_flag)
|
||||
{
|
||||
if (vflag & 2)
|
||||
printf ("%2d %s", directory_list_offset - desired_index,
|
||||
DIRSTACK_ENTRY (desired_index));
|
||||
else
|
||||
printf ("%s", DIRSTACK_ENTRY (desired_index));
|
||||
}
|
||||
else
|
||||
for (i = directory_list_offset - 1; i >= 0; i--)
|
||||
if (vflag >= 2)
|
||||
printf ("\n%2d %s", directory_list_offset - (int)i, DIRSTACK_ENTRY (i));
|
||||
else
|
||||
printf ("%s%s", (vflag & 1) ? "\n" : " ", DIRSTACK_ENTRY (i));
|
||||
|
||||
putchar ('\n');
|
||||
fflush (stdout);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
pushd_error (offset, arg)
|
||||
int offset;
|
||||
char *arg;
|
||||
{
|
||||
if (offset == 0)
|
||||
builtin_error ("directory stack empty");
|
||||
else if (arg)
|
||||
builtin_error ("%s: bad directory stack index", arg);
|
||||
else
|
||||
builtin_error ("bad directory stack index");
|
||||
}
|
||||
|
||||
static void
|
||||
clear_directory_stack ()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < directory_list_offset; i++)
|
||||
free (pushd_directory_list[i]);
|
||||
directory_list_offset = 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int result;
|
||||
|
||||
tlist = make_word_list (make_word (name), NULL);
|
||||
result = cd_builtin (tlist);
|
||||
dispose_words (tlist);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
change_to_temp (temp)
|
||||
char *temp;
|
||||
{
|
||||
int tt;
|
||||
|
||||
tt = temp ? cd_to_string (temp) : EXECUTION_FAILURE;
|
||||
|
||||
if (tt == EXECUTION_SUCCESS)
|
||||
dirs_builtin ((WORD_LIST *)NULL);
|
||||
|
||||
return (tt);
|
||||
}
|
||||
|
||||
static void
|
||||
add_dirstack_element (dir)
|
||||
char *dir;
|
||||
{
|
||||
int j;
|
||||
|
||||
if (directory_list_offset == directory_list_size)
|
||||
{
|
||||
j = (directory_list_size += 10) * sizeof (char *);
|
||||
pushd_directory_list = (char **)xrealloc (pushd_directory_list, j);
|
||||
}
|
||||
pushd_directory_list[directory_list_offset++] = dir;
|
||||
}
|
||||
|
||||
static int
|
||||
get_dirstack_index (ind, sign, indexp)
|
||||
int ind, sign, *indexp;
|
||||
{
|
||||
if (indexp)
|
||||
*indexp = sign > 0 ? 1 : 2;
|
||||
|
||||
/* dirs +0 prints the current working directory. */
|
||||
/* dirs -0 prints last element in directory stack */
|
||||
if (ind == 0 && sign > 0)
|
||||
return 0;
|
||||
else if (ind == directory_list_offset)
|
||||
{
|
||||
if (indexp)
|
||||
*indexp = sign > 0 ? 2 : 1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return (sign > 0 ? directory_list_offset - ind : ind);
|
||||
}
|
||||
|
||||
char *
|
||||
get_dirstack_element (ind, sign)
|
||||
int ind, sign;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = get_dirstack_index (ind, sign, (int *)NULL);
|
||||
return (i < 0 || i > directory_list_offset) ? (char *)NULL
|
||||
: pushd_directory_list[i];
|
||||
}
|
||||
|
||||
void
|
||||
set_dirstack_element (ind, sign, value)
|
||||
int ind, sign;
|
||||
char *value;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = get_dirstack_index (ind, sign, (int *)NULL);
|
||||
if (ind == 0 || i < 0 || i > directory_list_offset)
|
||||
return;
|
||||
free (pushd_directory_list[i]);
|
||||
pushd_directory_list[i] = savestring (value);
|
||||
}
|
||||
|
||||
WORD_LIST *
|
||||
get_directory_stack ()
|
||||
{
|
||||
register int i;
|
||||
WORD_LIST *ret;
|
||||
char *d, *t;
|
||||
|
||||
for (ret = (WORD_LIST *)NULL, i = 0; i < directory_list_offset; i++)
|
||||
{
|
||||
d = polite_directory_format (pushd_directory_list[i]);
|
||||
ret = make_word_list (make_word (d), ret);
|
||||
}
|
||||
/* Now the current directory. */
|
||||
d = get_working_directory ("dirstack");
|
||||
i = 0; /* sentinel to decide whether or not to free d */
|
||||
if (d == 0)
|
||||
d = ".";
|
||||
else
|
||||
{
|
||||
t = polite_directory_format (d);
|
||||
/* polite_directory_format sometimes returns its argument unchanged.
|
||||
If it does not, we can free d right away. If it does, we need to
|
||||
mark d to be deleted later. */
|
||||
if (t != d)
|
||||
{
|
||||
free (d);
|
||||
d = t;
|
||||
}
|
||||
else /* t == d, so d is what we want */
|
||||
i = 1;
|
||||
}
|
||||
ret = make_word_list (make_word (d), ret);
|
||||
if (i)
|
||||
free (d);
|
||||
return ret; /* was (REVERSE_LIST (ret, (WORD_LIST *)); */
|
||||
}
|
||||
|
||||
static char *dirs_doc[] = {
|
||||
"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'. The -v flag",
|
||||
"causes `dirs' to print the directory stack with one entry per line,",
|
||||
"prepending the directory name with its position in the stack. The -p",
|
||||
"flag does the same thing, but the stack position is not prepended.",
|
||||
"The -c flag clears the directory stack by deleting all of the elements.",
|
||||
"",
|
||||
"+N displays the Nth entry counting from the left of the list shown by",
|
||||
" dirs when invoked without options, starting with zero.",
|
||||
"",
|
||||
"-N displays the Nth entry counting from the right of the list shown by",
|
||||
" dirs when invoked without options, starting with zero.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
static char *pushd_doc[] = {
|
||||
"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.",
|
||||
"",
|
||||
"-n suppress the normal change of directory when adding directories",
|
||||
" to the stack, so only the stack is manipulated.",
|
||||
"",
|
||||
"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.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
static char *popd_doc[] = {
|
||||
"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.",
|
||||
"",
|
||||
"-n suppress the normal change of directory when removing directories",
|
||||
" from the stack, so only the stack is manipulated.",
|
||||
"",
|
||||
"You can see the directory stack with the `dirs' command.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin pushd_struct = {
|
||||
"pushd",
|
||||
pushd_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
pushd_doc,
|
||||
"pushd [+N | -N] [-n] [dir]",
|
||||
0
|
||||
};
|
||||
|
||||
struct builtin popd_struct = {
|
||||
"popd",
|
||||
popd_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
popd_doc,
|
||||
"popd [+N | -N] [-n]",
|
||||
0
|
||||
};
|
||||
|
||||
struct builtin dirs_struct = {
|
||||
"dirs",
|
||||
dirs_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
dirs_doc,
|
||||
"dirs [-clpv] [+N] [-N]",
|
||||
0
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
/* rmdir - remove directory */
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
rmdir_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int rval;
|
||||
WORD_LIST *l;
|
||||
|
||||
if (no_options (list))
|
||||
return (EX_USAGE);
|
||||
|
||||
for (rval = EXECUTION_SUCCESS, l = list; l; l = l->next)
|
||||
if (rmdir (l->word->word) < 0)
|
||||
{
|
||||
builtin_error ("%s: %s", l->word->word, strerror (errno));
|
||||
rval = EXECUTION_FAILURE;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
char *rmdir_doc[] = {
|
||||
"rmdir removes the directory entry specified by each argument,",
|
||||
"provided the directory is empty.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
/* The standard structure describing a builtin command. bash keeps an array
|
||||
of these structures. */
|
||||
struct builtin rmdir_struct = {
|
||||
"rmdir", /* builtin name */
|
||||
rmdir_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
rmdir_doc, /* array of long documentation strings. */
|
||||
"rmdir directory ...", /* usage synopsis; becomes short_doc */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* sleep -- sleep for fractions of a second
|
||||
*
|
||||
* usage: sleep seconds[.fraction]
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "bashtypes.h"
|
||||
|
||||
#if defined (TIME_WITH_SYS_TIME)
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
#else
|
||||
# if defined (HAVE_SYS_TIME_H)
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
|
||||
#define RETURN(x) \
|
||||
do { \
|
||||
if (sp) *sp = sec; \
|
||||
if (usp) *usp = usec; \
|
||||
return (x); \
|
||||
} while (0)
|
||||
|
||||
#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
|
||||
static int
|
||||
fsleep(sec, usec)
|
||||
long sec, usec;
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = sec;
|
||||
tv.tv_usec = usec;
|
||||
|
||||
return select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
|
||||
}
|
||||
#else /* !HAVE_TIMEVAL || !HAVE_SELECT */
|
||||
static int
|
||||
fsleep(sec, usec)
|
||||
long sec, usec;
|
||||
{
|
||||
if (usec >= 500000) /* round */
|
||||
sec++;
|
||||
return (sleep(sec));
|
||||
}
|
||||
#endif /* !HAVE_TIMEVAL || !HAVE_SELECT */
|
||||
|
||||
/*
|
||||
* An incredibly simplistic floating point converter.
|
||||
*/
|
||||
static int
|
||||
convert(s, sp, usp)
|
||||
char *s;
|
||||
long *sp, *usp;
|
||||
{
|
||||
int n;
|
||||
long sec, usec;
|
||||
char *p;
|
||||
|
||||
sec = usec = 0;
|
||||
|
||||
#define DECIMAL '.'
|
||||
|
||||
for (p = s; p && *p; p++) {
|
||||
if (*p == DECIMAL) /* decimal point */
|
||||
break;
|
||||
if (isdigit(*p) == 0)
|
||||
RETURN(0);
|
||||
sec = (sec * 10) + (*p - '0');
|
||||
}
|
||||
|
||||
if (*p == 0)
|
||||
RETURN(1);
|
||||
|
||||
if (*p == DECIMAL)
|
||||
p++;
|
||||
|
||||
/* Look for up to six digits past a decimal point. */
|
||||
for (n = 0; n < 6 && p[n]; n++) {
|
||||
if (isdigit(p[n]) == 0)
|
||||
RETURN(0);
|
||||
usec = (usec * 10) + (p[n] - '0');
|
||||
}
|
||||
|
||||
/* Now convert to millionths */
|
||||
if (n == 1)
|
||||
usec *= 100000;
|
||||
else if (n == 2)
|
||||
usec *= 10000;
|
||||
else if (n == 3)
|
||||
usec *= 1000;
|
||||
else if (n == 4)
|
||||
usec *= 100;
|
||||
else if (n == 5)
|
||||
usec *= 10;
|
||||
else if (n == 6 && p[6] && isdigit(p[6]) && p[6] >= '5')
|
||||
usec++; /* round up 1 */
|
||||
RETURN(1);
|
||||
}
|
||||
|
||||
int
|
||||
sleep_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
long sec, usec;
|
||||
|
||||
if (list == 0) {
|
||||
builtin_usage();
|
||||
return(EX_USAGE);
|
||||
}
|
||||
|
||||
if (*list->word->word == '-' || list->next) {
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
if (convert(list->word->word, &sec, &usec)) {
|
||||
fsleep(sec, usec);
|
||||
return(EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
builtin_error("%s: bad sleep interval", list->word->word);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
static char *sleep_doc[] = {
|
||||
"sleep suspends execution for a minimum of SECONDS[.FRACTION] seconds.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin sleep_struct = {
|
||||
"sleep",
|
||||
sleep_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
sleep_doc,
|
||||
"sleep seconds[.fraction]",
|
||||
0
|
||||
};
|
||||
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(BUILTIN) && !defined(SHELL)
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "stdc.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
static char sbuf[1024];
|
||||
static int sblen;
|
||||
|
||||
/* Gee, I wish sprintf could be reliably counted upon to return the
|
||||
number of characters written :-( */
|
||||
#define PF(f, func) \
|
||||
do { \
|
||||
if (fieldwidth) \
|
||||
if (precision) \
|
||||
sprintf(sbuf, f, fieldwidth, precision, func); \
|
||||
else \
|
||||
sprintf(sbuf, f, fieldwidth, func); \
|
||||
else if (precision) \
|
||||
sprintf(sbuf, f, precision, func); \
|
||||
else \
|
||||
sprintf(sbuf, f, func); \
|
||||
spaddstr (sbuf, strlen (sbuf)); \
|
||||
} while (0)
|
||||
|
||||
static int asciicode __P((void));
|
||||
static void escape __P((char *));
|
||||
static int getchr __P((void));
|
||||
static double getdouble __P((void));
|
||||
static int getint __P((int *));
|
||||
static int getlong __P((long *));
|
||||
static char *getstr __P((void));
|
||||
static char *mklong __P((char *, int));
|
||||
static void usage __P((void));
|
||||
|
||||
static char **gargv;
|
||||
|
||||
static char *outstr;
|
||||
static int outsize;
|
||||
static int outind;
|
||||
|
||||
int sprintf_builtin ();
|
||||
static int sprintf_main ();
|
||||
static void spaddstr ();
|
||||
|
||||
extern char *this_command_name;
|
||||
extern char *single_quote ();
|
||||
extern char **make_builtin_argv ();
|
||||
|
||||
static char *sprintf_doc[] = {
|
||||
"sprintf formats and outputs its arguments, after the second, under control",
|
||||
"of the format and assigns the result to the variable named by its first",
|
||||
"argument. The format is a character string which contains three types",
|
||||
"of objects: plain characters, which are simply copied to the output string,",
|
||||
"character escape sequences which are converted and copied to the output",
|
||||
"string, and format specifications, each of which causes printing of the",
|
||||
"next successive argument. In addition to the standard sprintf(3) formats,",
|
||||
"%b means to expand escapes in the corresponding argument, and %q means",
|
||||
"to quote the argument in a way that can be reused as shell input. Each",
|
||||
"one of the format specifications must not expand to more than 1024",
|
||||
"characters, though there is no limit on the total size of the output",
|
||||
"string.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin sprintf_struct = {
|
||||
"sprintf",
|
||||
sprintf_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
sprintf_doc,
|
||||
"sprintf var format [arguments]",
|
||||
(char *)0
|
||||
};
|
||||
|
||||
int
|
||||
sprintf_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int c, r;
|
||||
char **v, *varname;
|
||||
WORD_LIST *l;
|
||||
SHELL_VAR *var;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
varname = list->word->word;
|
||||
list = list->next;
|
||||
|
||||
if (legal_identifier (varname) == 0)
|
||||
{
|
||||
builtin_error ("%s: not a legal variable name", varname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
outind = 0;
|
||||
if (outstr == 0)
|
||||
outstr = xmalloc (outsize = 64);
|
||||
outstr[0] = '\0';
|
||||
|
||||
v = make_builtin_argv (list, &c);
|
||||
r = sprintf_main (c, v);
|
||||
free (v);
|
||||
|
||||
var = bind_variable (varname, outstr);
|
||||
if (readonly_p (var))
|
||||
{
|
||||
builtin_error ("%s: readonly variable", varname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
spaddstr(str, len)
|
||||
char *str;
|
||||
int len;
|
||||
{
|
||||
RESIZE_MALLOCED_BUFFER (outstr, outind, len, outsize, 64);
|
||||
strcpy (outstr + outind, str);
|
||||
outind += len;
|
||||
}
|
||||
|
||||
static int
|
||||
sprintf_main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern int optind;
|
||||
static char *skip1, *skip2;
|
||||
int ch, end, fieldwidth, precision;
|
||||
char convch, nextch, *format, *fmt, *start;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch (ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic algorithm is to scan the format string for conversion
|
||||
* specifications -- once one is found, find out if the field
|
||||
* width or precision is a '*'; if it is, gather up value. Note,
|
||||
* format strings are reused as necessary to use up the provided
|
||||
* arguments, arguments of zero/null string are provided to use
|
||||
* up the format string.
|
||||
*/
|
||||
skip1 = "#-+ 0";
|
||||
skip2 = "*0123456789";
|
||||
|
||||
escape(fmt = format = *argv); /* backslash interpretation */
|
||||
gargv = ++argv;
|
||||
for (;;) {
|
||||
end = 0;
|
||||
/* find next format specification */
|
||||
next: for (start = fmt;; ++fmt) {
|
||||
if (!*fmt) {
|
||||
/* avoid infinite loop */
|
||||
if (end == 1) {
|
||||
warnx("missing format character",
|
||||
NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
end = 1;
|
||||
if (fmt > start)
|
||||
(void)printf("%s", start);
|
||||
if (!*gargv)
|
||||
return (0);
|
||||
fmt = format;
|
||||
goto next;
|
||||
}
|
||||
/* %% prints a % */
|
||||
if (*fmt == '%') {
|
||||
if (*++fmt != '%')
|
||||
break;
|
||||
*fmt++ = '\0';
|
||||
(void)printf("%s", start);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip to field width */
|
||||
for (; strchr(skip1, *fmt); ++fmt);
|
||||
if (*fmt == '*') {
|
||||
if (getint(&fieldwidth))
|
||||
return (1);
|
||||
} else
|
||||
fieldwidth = 0;
|
||||
|
||||
/* skip to possible '.', get following precision */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (*fmt == '.')
|
||||
++fmt;
|
||||
if (*fmt == '*') {
|
||||
if (getint(&precision))
|
||||
return (1);
|
||||
} else
|
||||
precision = 0;
|
||||
|
||||
/* skip to conversion char */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (!*fmt) {
|
||||
warnx("missing format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
|
||||
convch = *fmt;
|
||||
nextch = *++fmt;
|
||||
*fmt = '\0';
|
||||
switch(convch) {
|
||||
case 'c': {
|
||||
char p;
|
||||
|
||||
p = getchr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 'b': { /* expand escapes in argument */
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
escape(p);
|
||||
PF("%s", p);
|
||||
break;
|
||||
}
|
||||
case 'q': { /* print with shell single quoting */
|
||||
char *p, *p2;
|
||||
|
||||
p = getstr();
|
||||
p2 = single_quote(p);
|
||||
PF("%s", p2);
|
||||
free(p2);
|
||||
break;
|
||||
}
|
||||
case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
|
||||
long p;
|
||||
char *f;
|
||||
|
||||
if ((f = mklong(start, convch)) == NULL)
|
||||
return (1);
|
||||
if (getlong(&p))
|
||||
return (1);
|
||||
PF(f, p);
|
||||
break;
|
||||
}
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G': {
|
||||
double p;
|
||||
|
||||
p = getdouble();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warnx("illegal format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
*fmt = nextch;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static char *
|
||||
mklong(str, ch)
|
||||
char *str;
|
||||
int ch;
|
||||
{
|
||||
static char copy[64];
|
||||
int len;
|
||||
|
||||
len = strlen(str) + 2;
|
||||
memmove(copy, str, len - 3);
|
||||
copy[len - 3] = 'l';
|
||||
copy[len - 2] = ch;
|
||||
copy[len - 1] = '\0';
|
||||
return (copy);
|
||||
}
|
||||
|
||||
static void
|
||||
escape(fmt)
|
||||
register char *fmt;
|
||||
{
|
||||
register char *store;
|
||||
register int value, c;
|
||||
|
||||
for (store = fmt; c = *fmt; ++fmt, ++store) {
|
||||
if (c != '\\') {
|
||||
*store = c;
|
||||
continue;
|
||||
}
|
||||
switch (*++fmt) {
|
||||
case '\0': /* EOS, user error */
|
||||
*store = '\\';
|
||||
*++store = '\0';
|
||||
return;
|
||||
case '\\': /* backslash */
|
||||
case '\'': /* single quote */
|
||||
*store = *fmt;
|
||||
break;
|
||||
case 'a': /* bell/alert */
|
||||
*store = '\7';
|
||||
break;
|
||||
case 'b': /* backspace */
|
||||
*store = '\b';
|
||||
break;
|
||||
case 'c':
|
||||
return;
|
||||
case 'e':
|
||||
case 'E':
|
||||
*store = '\033';
|
||||
break;
|
||||
case 'f': /* form-feed */
|
||||
*store = '\f';
|
||||
break;
|
||||
case 'n': /* newline */
|
||||
*store = '\n';
|
||||
break;
|
||||
case 'r': /* carriage-return */
|
||||
*store = '\r';
|
||||
break;
|
||||
case 't': /* horizontal tab */
|
||||
*store = '\t';
|
||||
break;
|
||||
case 'v': /* vertical tab */
|
||||
*store = '\13';
|
||||
break;
|
||||
/* octal constant */
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
for (c = 3, value = 0;
|
||||
c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
|
||||
value <<= 3;
|
||||
value += *fmt - '0';
|
||||
}
|
||||
--fmt;
|
||||
*store = value;
|
||||
break;
|
||||
default:
|
||||
*store = *fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*store = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
getchr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ('\0');
|
||||
return ((int)**gargv++);
|
||||
}
|
||||
|
||||
static char *
|
||||
getstr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ("");
|
||||
return (*gargv++);
|
||||
}
|
||||
|
||||
static char *Number = "+-.0123456789";
|
||||
static int
|
||||
getint(ip)
|
||||
int *ip;
|
||||
{
|
||||
long val;
|
||||
|
||||
if (getlong(&val))
|
||||
return (1);
|
||||
if (val > INT_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
*ip = val;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getlong(lp)
|
||||
long *lp;
|
||||
{
|
||||
long val;
|
||||
char *ep;
|
||||
|
||||
if (!*gargv) {
|
||||
*lp = 0;
|
||||
return (0);
|
||||
}
|
||||
if (strchr(Number, **gargv)) {
|
||||
errno = 0;
|
||||
val = strtol(*gargv, &ep, 0);
|
||||
if (*ep != '\0') {
|
||||
warnx("%s: illegal number", *gargv, NULL);
|
||||
return (1);
|
||||
}
|
||||
if (errno == ERANGE)
|
||||
if (val == LONG_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
if (val == LONG_MIN) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
|
||||
*lp = val;
|
||||
++gargv;
|
||||
return (0);
|
||||
}
|
||||
*lp = (long)asciicode();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static double
|
||||
getdouble()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ((double)0);
|
||||
if (strchr(Number, **gargv))
|
||||
return (atof(*gargv++));
|
||||
return ((double)asciicode());
|
||||
}
|
||||
|
||||
static int
|
||||
asciicode()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
ch = **gargv;
|
||||
if (ch == '\'' || ch == '"')
|
||||
ch = (*gargv)[1];
|
||||
++gargv;
|
||||
return (ch);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: printf format [arg ...]\n");
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/* tee - duplicate standard input */
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "bashtypes.h"
|
||||
#include "posixstat.h"
|
||||
#include "filecntl.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
typedef struct flist {
|
||||
struct flist *next;
|
||||
int fd;
|
||||
char *fname;
|
||||
} FLIST;
|
||||
|
||||
static FLIST *tee_flist;
|
||||
|
||||
#define TEE_BUFSIZE 8192
|
||||
|
||||
extern int interrupt_immediately;
|
||||
|
||||
extern char *strerror ();
|
||||
|
||||
tee_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int opt, append, nointr, rval, fd, fflags;
|
||||
int n, nr, nw;
|
||||
FLIST *fl;
|
||||
char *buf, *bp;
|
||||
|
||||
char *t;
|
||||
|
||||
reset_internal_getopt ();
|
||||
append = nointr = 0;
|
||||
tee_flist = (FLIST *)NULL;
|
||||
while ((opt = internal_getopt (list, "ai")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'a':
|
||||
append = 1;
|
||||
break;
|
||||
case 'i':
|
||||
nointr = 1;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
if (nointr == 0)
|
||||
interrupt_immediately++;
|
||||
|
||||
buf = xmalloc (TEE_BUFSIZE);
|
||||
|
||||
/* Initialize output file list. */
|
||||
fl = tee_flist = (FLIST *)xmalloc (sizeof(FLIST));
|
||||
tee_flist->fd = 1;
|
||||
tee_flist->fname = "stdout";
|
||||
tee_flist->next = (FLIST *)NULL;
|
||||
|
||||
/* Add file arguments to list of output files. */
|
||||
fflags = append ? O_WRONLY|O_CREAT|O_APPEND : O_WRONLY|O_CREAT|O_TRUNC;
|
||||
for (rval = EXECUTION_SUCCESS; list; list = list->next)
|
||||
{
|
||||
fd = open (list->word->word, fflags, 0666);
|
||||
if (fd < 0)
|
||||
{
|
||||
builtin_error ("%s: cannot open: %s", list->word->word, strerror (errno));
|
||||
rval = EXECUTION_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fl->next = (FLIST *)xmalloc (sizeof(FLIST));
|
||||
fl->next->fd = fd;
|
||||
fl->next->fname = list->word->word;
|
||||
fl = fl->next;
|
||||
fl->next = (FLIST *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
while ((nr = read(0, buf, TEE_BUFSIZE)) > 0)
|
||||
for (fl = tee_flist; fl; fl = fl->next)
|
||||
{
|
||||
n = nr;
|
||||
bp = buf;
|
||||
do
|
||||
{
|
||||
if ((nw = write (fl->fd, bp, n)) == -1)
|
||||
{
|
||||
builtin_error ("%s: write error: %s", fl->fname, strerror (errno));
|
||||
rval = EXECUTION_FAILURE;
|
||||
break;
|
||||
}
|
||||
bp += nw;
|
||||
}
|
||||
while (n -= nw);
|
||||
}
|
||||
if (nr < 0)
|
||||
builtin_error ("read error: %s", strerror (errno));
|
||||
|
||||
/* Deallocate resources -- this is a builtin command. */
|
||||
tee_flist = tee_flist->next; /* skip bogus close of stdout */
|
||||
while (tee_flist)
|
||||
{
|
||||
fl = tee_flist;
|
||||
if (close (fl->fd) < 0)
|
||||
{
|
||||
builtin_error ("%s: close_error: %s", fl->fname, strerror (errno));
|
||||
rval = EXECUTION_FAILURE;
|
||||
}
|
||||
tee_flist = tee_flist->next;
|
||||
free (fl);
|
||||
}
|
||||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
char *tee_doc[] = {
|
||||
"Copy standard input to standard output, making a copy in each",
|
||||
"filename argument. If the `-a' option is gived, the specified",
|
||||
"files are appended to, otherwise they are overwritten. If the",
|
||||
"`-i' option is supplied, tee ignores interrupts.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin tee_struct = {
|
||||
"tee", /* builtin name */
|
||||
tee_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
tee_doc, /* array of long documentation strings. */
|
||||
"tee [-ai] [file ...]", /* usage synopsis; becomes short_doc */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/* true and false builtins */
|
||||
|
||||
#include "bashtypes.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
|
||||
true_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
return EXECUTION_SUCCESS;
|
||||
}
|
||||
|
||||
false_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
return EXECUTION_FAILURE;
|
||||
}
|
||||
|
||||
static char *true_doc[] = {
|
||||
"Return a successful result.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
static char *false_doc[] = {
|
||||
"Return an unsuccessful result.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin true_struct = {
|
||||
"true",
|
||||
true_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
true_doc,
|
||||
"true",
|
||||
0
|
||||
};
|
||||
|
||||
struct builtin false_struct = {
|
||||
"false",
|
||||
false_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
false_doc,
|
||||
"false",
|
||||
0
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
/* tty - return terminal name */
|
||||
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "builtins.h"
|
||||
#include "shell.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
extern char *ttyname ();
|
||||
|
||||
tty_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int opt, sflag;
|
||||
char *t;
|
||||
|
||||
reset_internal_getopt ();
|
||||
sflag = 0;
|
||||
while ((opt = internal_getopt (list, "s")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
t = ttyname (0);
|
||||
if (sflag == 0)
|
||||
puts (t ? t : "not a tty");
|
||||
return (t ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
char *tty_doc[] = {
|
||||
"tty writes the name of the terminal that is opened for standard",
|
||||
"input to standard output. If the `-s' option is supplied, nothing",
|
||||
"is written; the exit status determines whether or not the standard",
|
||||
"input is connected to a tty.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
/* The standard structure describing a builtin command. bash keeps an array
|
||||
of these structures. */
|
||||
struct builtin tty_struct = {
|
||||
"tty", /* builtin name */
|
||||
tty_builtin, /* function implementing the builtin */
|
||||
BUILTIN_ENABLED, /* initial flags for builtin */
|
||||
tty_doc, /* array of long documentation strings. */
|
||||
"tty [-s]", /* usage synopsis; becomes short_doc */
|
||||
0 /* reserved for internal use */
|
||||
};
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# alias-conv.sh - convert csh aliases to bash aliases and functions
|
||||
#
|
||||
# usage: alias-conv.sh
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@po.cwru.edu
|
||||
#
|
||||
trap 'rm -f /tmp/cb$$.?' 0 1 2 3 6 15
|
||||
|
||||
T=$'\t'
|
||||
|
||||
cat << \EOF >/tmp/cb$$.1
|
||||
mkalias ()
|
||||
{
|
||||
if [ "x$2" = "x" ]; then
|
||||
echo alias ${1}="''"
|
||||
elif echo "$2" | egrep -s '(\!|#)' >/dev/null 2>&1; then
|
||||
comm=$(echo $2 | sed 's/\!\*/"$\@"/g
|
||||
s/\!:\([1-9]\)/"$\1"/g
|
||||
s/#/\#/g')
|
||||
echo $1 \(\) "{" command "$comm" "; }"
|
||||
else
|
||||
echo alias ${1}=\'$(echo "${2}" | sed "s:':'\\\\'':")\'
|
||||
fi
|
||||
}
|
||||
EOF
|
||||
|
||||
sed "s/^\([a-zA-Z0-9_-]*\)$T\(.*\)$/mkalias \1 '\2'/" >>/tmp/cb$$.1
|
||||
|
||||
$BASH /tmp/cb$$.1 | sed -e 's/\$cwd/\$PWD/g' \
|
||||
-e 's/\$term/\$TERM/g' \
|
||||
-e 's/\$home/\$HOME/g' \
|
||||
-e 's/\$user/\$USER/g' \
|
||||
-e 's/\$prompt/\$PS1/g'
|
||||
|
||||
exit 0
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# alias-conv.sh - convert csh aliases to bash aliases and functions
|
||||
#
|
||||
# usage: alias-conv.sh
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@po.cwru.edu
|
||||
#
|
||||
trap 'rm -f /tmp/cb$$.?' 0 1 2 3 6 15
|
||||
|
||||
T=' '
|
||||
|
||||
cat << \EOF >/tmp/cb$$.1
|
||||
mkalias ()
|
||||
{
|
||||
if [ "x$2" = "x" ]; then
|
||||
echo alias ${1}="''"
|
||||
elif echo "$2" | egrep -s '(\!|#)' >/dev/null 2>&1; then
|
||||
comm=`echo $2 | sed 's/\\!\*/"$\@"/g
|
||||
s/\\!:\([1-9]\)/"$\1"/g
|
||||
s/#/\#/g'`
|
||||
echo $1 \(\) "{" command "$comm" "; }"
|
||||
else
|
||||
echo alias ${1}=\'`echo "${2}" | sed "s:':'\\\\\\\\'':"`\'
|
||||
fi
|
||||
}
|
||||
EOF
|
||||
|
||||
sed "s/^\([a-zA-Z0-9_-]*\)$T\(.*\)$/mkalias \1 '\2'/" >>/tmp/cb$$.1
|
||||
|
||||
sh /tmp/cb$$.1 | sed -e 's/\$cwd/\$PWD/g' \
|
||||
-e 's/\$term/\$TERM/g' \
|
||||
-e 's/\$home/\$HOME/g' \
|
||||
-e 's/\$user/\$USER/g' \
|
||||
-e 's/\$prompt/\$PS1/g'
|
||||
|
||||
exit 0
|
||||
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# cshtobash - convert csh aliases, environment variables, and variables to
|
||||
# bash equivalents
|
||||
#
|
||||
# usage: cshtobash [filename]
|
||||
#
|
||||
# If filename is given, that file is sourced. Note that csh always
|
||||
# sources .cshrc. To recreate your csh login environment, run
|
||||
# `cshtobash ~/.login'.
|
||||
#
|
||||
# Inspired by (and some borrowed from) a similar program distributed with
|
||||
# zsh-3.0.
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@po.cwru.edu
|
||||
#
|
||||
trap 'rm -f /tmp/cb$$.? cshout cshin' 0 1 2 3 6 15
|
||||
|
||||
T=$'\t'
|
||||
|
||||
SOURCE="${1:+source $1}"
|
||||
|
||||
cat << EOF >cshin
|
||||
$SOURCE
|
||||
alias >! /tmp/cb$$.a
|
||||
setenv >! /tmp/cb$$.e
|
||||
set >! /tmp/cb$$.v
|
||||
EOF
|
||||
|
||||
# give csh a minimal environment, similar to what login would provide
|
||||
/usr/bin/env - USER=$USER HOME=$HOME PATH=/usr/bin:/bin:/usr/ucb:. TERM=$TERM SHELL=$SHELL /bin/csh -i < ./cshin > cshout 2>&1
|
||||
|
||||
# First convert aliases
|
||||
|
||||
cat << \EOF >/tmp/cb$$.1
|
||||
mkalias ()
|
||||
{
|
||||
if [ -z "$2" ]; then
|
||||
echo alias ${1}="''"
|
||||
elif echo "$2" | egrep -s '(\!|#)' >/dev/null 2>&1; then
|
||||
comm=$(echo $2 | sed 's/\!\*/"$\@"/g
|
||||
s/\!:\([1-9]\)/"$\1"/g
|
||||
s/#/\#/g')
|
||||
echo $1 \(\) "{" command "$comm" "; }"
|
||||
else
|
||||
echo alias ${1}=\'$(echo "${2}" | sed "s:':'\\\\'':")\'
|
||||
fi
|
||||
}
|
||||
EOF
|
||||
|
||||
sed "s/^\([a-zA-Z0-9_]*\)$T\(.*\)$/mkalias \1 '\2'/" < /tmp/cb$$.a >>/tmp/cb$$.1
|
||||
|
||||
echo '# csh aliases'
|
||||
echo
|
||||
|
||||
$BASH /tmp/cb$$.1 | sed -e 's/\$cwd/\$PWD/g' \
|
||||
-e 's/\$term/\$TERM/g' \
|
||||
-e 's/\$home/\$HOME/g' \
|
||||
-e 's/\$user/\$USER/g' \
|
||||
-e 's/\$prompt/\$PS1/g'
|
||||
|
||||
# Next, convert environment variables
|
||||
echo
|
||||
echo '# csh environment variables'
|
||||
echo
|
||||
|
||||
# Would be nice to deal with embedded newlines, e.g. in TERMCAP, but ...
|
||||
sed -e '/^SHLVL/d' \
|
||||
-e '/^PWD/d' \
|
||||
-e "s/'/'"\\\\"''"/g \
|
||||
-e "s/^\([A-Za-z0-9_]*=\)/export \1'/" \
|
||||
-e "s/$/'/" < /tmp/cb$$.e
|
||||
|
||||
# Finally, convert local variables
|
||||
echo
|
||||
echo '# csh variables'
|
||||
echo
|
||||
|
||||
sed -e 's/'"$T"'/=/' \
|
||||
-e "s/'/'"\\\\"''"/g \
|
||||
-e '/^[A-Za-z0-9_]*=[^(]/{
|
||||
s/=/='"'/"'
|
||||
s/$/'"'/"'
|
||||
}' < /tmp/cb$$.v |
|
||||
sed -e '/^argv=/d' -e '/^cwd=/d' -e '/^filec=/d' -e '/^status=/d' \
|
||||
-e '/^verbose=/d' \
|
||||
-e '/^term=/d' \
|
||||
-e '/^home=/d' \
|
||||
-e '/^path=/d' \
|
||||
-e '/^user=/d' \
|
||||
-e '/^shell=/d' \
|
||||
-e '/^cdpath=/d' \
|
||||
-e '/^mail=/d' \
|
||||
-e '/^home=/s//HOME=/' \
|
||||
-e '/^prompt=/s//PS1=/' \
|
||||
-e '/^histfile=/s//HISTFILE=/' \
|
||||
-e '/^history=/s//HISTSIZE=/' \
|
||||
-e '/^savehist=$/s//HISTFILESIZE=${HISTSIZE-500}/' \
|
||||
-e '/^savehist=/s//HISTFILESIZE=/' \
|
||||
-e '/^ignoreeof=$/s/^.*$/set -o ignoreeof # ignoreeof/' \
|
||||
-e '/^ignoreeof=/s//IGNOREEOF=/' \
|
||||
-e '/^noclobber=/s/^.*$/set -C # noclobber/' \
|
||||
-e '/^notify=/s/^.*$/set -b # notify/' \
|
||||
-e '/^noglob=/s/^.*$/set -f # noglob/' \
|
||||
|
||||
|
||||
# now some special csh variables converted to bash equivalents
|
||||
echo
|
||||
echo '# special csh variables converted to bash equivalents'
|
||||
echo
|
||||
|
||||
sed -e 's/'"$T"'/=/' < /tmp/cb$$.v |
|
||||
grep "^cdpath=" |
|
||||
sed 's/(//
|
||||
s/ /:/g
|
||||
s/)//
|
||||
s/cdpath=/CDPATH=/'
|
||||
|
||||
|
||||
sed -e 's/'"$T"'/=/' < /tmp/cb$$.v |
|
||||
grep "^mail=" |
|
||||
sed 's/(//
|
||||
s/ /:/g
|
||||
s/)//
|
||||
s/mail=/MAILPATH=/' |
|
||||
sed -e 's/MAILPATH=\([0-9][0-9][^:]*\)$/MAILCHECK=\1/' \
|
||||
-e 's/MAILPATH=\([0-9][0-9][^:]*\):\(.*\)/MAILCHECK=\1 MAILPATH=\2/'
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,29 @@
|
||||
From friedman@cli.com Thu May 25 12:19:06 1995
|
||||
Flags: 10
|
||||
Return-Path: friedman@cli.com
|
||||
Received: from po.cwru.edu (root@po.CWRU.Edu [129.22.4.2]) by odin.INS.CWRU.Edu with ESMTP (8.6.10+cwru/CWRU-2.1-ins)
|
||||
id MAA08685; Thu, 25 May 1995 12:19:05 -0400 (from friedman@cli.com for <chet@odin.INS.CWRU.Edu>)
|
||||
Received: from cli.com (cli.com [192.31.85.1]) by po.cwru.edu with SMTP (8.6.10+cwru/CWRU-2.3)
|
||||
id MAA11299; Thu, 25 May 1995 12:19:00 -0400 (from friedman@cli.com for <chet@po.cwru.edu>)
|
||||
Received: from tepui.cli.com by cli.com (4.1/SMI-4.1)
|
||||
id AA27213; Thu, 25 May 95 11:18:25 CDT
|
||||
Received: by tepui.cli.com (4.1) id AA16031; Thu, 25 May 95 11:18:23 CDT
|
||||
Message-Id: <9505251618.AA16031@tepui.cli.com>
|
||||
From: friedman@gnu.ai.mit.edu (Noah Friedman)
|
||||
To: chet@po.cwru.edu
|
||||
Subject: Bash scripts
|
||||
Reply-To: friedman@gnu.ai.mit.edu
|
||||
In-Reply-To: <chet@odin.ins.cwru.edu> Thu, 25 May 1995 11:19:59 -0400
|
||||
References: <9505251519.AA06424.SM@odin.INS.CWRU.Edu>
|
||||
Date: Thu, 25 May 95 11:18:21 CST
|
||||
|
||||
>Hi. I snagged some of your bash functions from your home directory on
|
||||
>the FSF machines (naughty, I know), and I was wondering if you'd let
|
||||
>me distribute them with bash-2.0. Thanks.
|
||||
|
||||
Sure. I think there's a later copy in
|
||||
~ftp/friedman/shell-inits/init-4.89.tar.gz. There are also some elisp and
|
||||
es frobs in that file.
|
||||
|
||||
It should serve as a pretty good example of how to get carried away. :-)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
This collection of scripts was originally written for older versions
|
||||
of bash by Noah Friedman (friedman@gnu.ai.mit.edu). The conversion
|
||||
to bash v2 syntax was done by Chet Ramey.
|
||||
|
||||
These scripts are as-is; there is no copyright associated with
|
||||
any of them. They exist simply as examples of bash scripting.
|
||||
|
||||
Here's a description of what's in this directory:
|
||||
|
||||
aref.bash pseudo-arrays and substring indexing examples
|
||||
bash.sub.bash library functions used by require.bash
|
||||
bash_version.bash a function to slice up $BASH_VERSION
|
||||
meta.bash enable and disable eight-bit readline input
|
||||
mktmp.bash make a temporary file with a unique name
|
||||
number.bash a fun hack to translate numerals into english
|
||||
prompt.bash a way to set PS1 to some predefined strings
|
||||
remap_keys.bash a front end to `bind' to redo readline bindings
|
||||
require.bash lisp-like require/provide library functions for bash
|
||||
send_mail.bash replacement smtp client written in bash
|
||||
shcat.bash bash replacement for `cat'
|
||||
source.bash replacement for source that uses current directory
|
||||
string.bash the string(3) functions at the shell level
|
||||
stty.bash front-end to stty that changes readline bindings too
|
||||
y_or_n_p.bash prompt for a yes/no/quit answer
|
||||
@@ -0,0 +1,44 @@
|
||||
# aref.bash --- pseudo-array manipulating routines
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created 1992-07-01
|
||||
# Last modified: 1993-02-03
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring aref:
|
||||
# Usage: aref NAME INDEX
|
||||
#
|
||||
# In array NAME, access element INDEX (0-origin)
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function aref ()
|
||||
{
|
||||
local name="$1"
|
||||
local index="$2"
|
||||
|
||||
set -- ${!name}
|
||||
[ $index -ge 1 ] && shift $index
|
||||
echo $1
|
||||
}
|
||||
|
||||
#:docstring string_aref:
|
||||
# Usage: aref STRING INDEX
|
||||
#
|
||||
# Echo the INDEXth character in STRING (0-origin) on stdout.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function string_aref ()
|
||||
{
|
||||
local stuff=${1:$2}
|
||||
echo ${stuff:0:1}
|
||||
}
|
||||
|
||||
provide aref
|
||||
|
||||
# aref.bash ends here
|
||||
@@ -0,0 +1,28 @@
|
||||
# bash.sub.bash --- stub for standalone shell scripts using bash library
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-07-13
|
||||
# Last modified: 1993-09-29
|
||||
# Public domain
|
||||
|
||||
#:docstring bash.sub:
|
||||
# Standard subroutines for bash scripts wishing to use "require" to load
|
||||
# libraries.
|
||||
#
|
||||
# Usage: In each directory where a bash script that uses this script
|
||||
# exists, place a copy of this script. Then, at the top of such scripts,
|
||||
# put the command
|
||||
#
|
||||
# source ${0%/*}/bash.sub || exit 1
|
||||
#
|
||||
# Then you can use `require' to load packages.
|
||||
#
|
||||
#:end docstring:
|
||||
|
||||
default_FPATH="~friedman/etc/init/bash/functions/lib"
|
||||
|
||||
source "${default_FPATH}/feature"
|
||||
REQUIRE_FAILURE_FATAL=t
|
||||
|
||||
FPATH="${FPATH-${default_FPATH}}"
|
||||
|
||||
# bash.sub.bash ends here
|
||||
@@ -0,0 +1,42 @@
|
||||
# bash_version.bash --- get major and minor components of bash version number
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-01-26
|
||||
# Last modified: 1993-01-26
|
||||
# Public domain
|
||||
|
||||
# Converted to bash v2 syntax by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring bash_version:
|
||||
# Usage: bash_version {major|minor}
|
||||
#
|
||||
# Echo the major or minor number of this version of bash on stdout, or
|
||||
# just echo $BASH_VERSION if no argument is given.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function bash_version ()
|
||||
{
|
||||
local major minor
|
||||
|
||||
case "$1" in
|
||||
major) echo "${BASH_VERSION/.*/}" ;;
|
||||
minor) major="${BASH_VERSION/.*/}"
|
||||
minor="${BASH_VERSION#${major}.}"
|
||||
echo "${minor%%.*}" ;;
|
||||
patchlevel) minor="${BASH_VERSION#*.*.}"
|
||||
echo "${minor%(*}" ;;
|
||||
version) minor=${BASH_VERSION/#*.*./}
|
||||
echo ${BASH_VERSION/%.$minor/} ;;
|
||||
release) echo ${BASH_VERSION%(*} ;;
|
||||
build) minor="${BASH_VERSION#*.*.*(}"
|
||||
echo ${minor%)} ;;
|
||||
*) echo "${BASH_VERSION}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
provide bash_version
|
||||
|
||||
# bash_version.bash ends here
|
||||
@@ -0,0 +1,37 @@
|
||||
# meta.bash --- meta key frobnications
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-06-28
|
||||
# Last modified: 1993-01-26
|
||||
# Public domain
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring meta:
|
||||
# Usage: meta [on|off]
|
||||
#
|
||||
# An argument of "on" will make bash use the 8th bit of any input from
|
||||
# a terminal as a "meta" bit, i.e bash will be able to use a real meta
|
||||
# key.
|
||||
#
|
||||
# An argument of "off" causes bash to disregard the 8th bit, which is
|
||||
# assumed to be used for parity instead.
|
||||
#:end docstring:
|
||||
|
||||
function meta ()
|
||||
{
|
||||
case "$1" in
|
||||
on) bind 'set input-meta On'
|
||||
bind 'set output-meta on'
|
||||
bind 'set convert-meta off' ;;
|
||||
off) bind 'set input-meta Off'
|
||||
bind 'set output-meta off'
|
||||
bind 'set convert-meta on' ;;
|
||||
*) echo "Usage: meta [on|off]" 1>&2 ; return 1 ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
provide meta
|
||||
|
||||
# meta.bash ends here
|
||||
@@ -0,0 +1,66 @@
|
||||
# mktmp.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-02-03
|
||||
# Last modified: 1993-02-03
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring mktmp:
|
||||
# Usage: mktmp [template] {createp}
|
||||
#
|
||||
# Generate a unique filename from TEMPLATE by appending a random number to
|
||||
# the end.
|
||||
#
|
||||
# If optional 2nd arg CREATEP is non-null, file will be created atomically
|
||||
# before returning. This is to avoid the race condition that in between
|
||||
# the time that the temporary name is returned and the caller uses it,
|
||||
# someone else creates the file.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function mktmp ()
|
||||
{
|
||||
local template="$1"
|
||||
local tmpfile="${template}${RANDOM}"
|
||||
local createp="$2"
|
||||
local noclobber_status
|
||||
|
||||
case "$-" in
|
||||
*C*) noclobber_status=set;;
|
||||
esac
|
||||
|
||||
if [ "${createp:+set}" = "set" ]; then
|
||||
# Version which creates file atomically through noclobber test.
|
||||
set -o noclobber
|
||||
(> "${tmpfile}") 2> /dev/null
|
||||
while [ $? -ne 0 ] ; do
|
||||
# Detect whether file really exists or creation lost because of
|
||||
# some other permissions problem. If the latter, we don't want
|
||||
# to loop forever.
|
||||
if [ ! -e "${tmpfile}" ]; then
|
||||
# Trying to create file again creates stderr message.
|
||||
echo -n "mktmp: " 1>&2
|
||||
> "${tmpfile}"
|
||||
return 1
|
||||
fi
|
||||
tmpfile="${template}${RANDOM}"
|
||||
(> "${tmpfile}") 2> /dev/null
|
||||
done
|
||||
test "${noclobber_status}" != "set" && set +o noclobber
|
||||
else
|
||||
# Doesn't create file, so it introduces race condition for caller.
|
||||
while [ -e "${tmpfile}" ]; do
|
||||
tmpfile="${template}${RANDOM}"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "${tmpfile}"
|
||||
}
|
||||
|
||||
provide mktmp
|
||||
|
||||
# mktmp.bash ends here
|
||||
@@ -0,0 +1,185 @@
|
||||
# number.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-02-22
|
||||
# Last modified: 1993-04-01
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring number:
|
||||
# Usage: number [number]
|
||||
#
|
||||
# Converts decimal integers to english notation. Spaces and commas are
|
||||
# optional. Numbers 67 digits and larger will overflow this script.
|
||||
#
|
||||
# E.g: number 99,000,000,000,000,454
|
||||
# => ninety-nine quadrillion four hundred fifty-four
|
||||
#
|
||||
#:end docstring:
|
||||
|
||||
function number ()
|
||||
{
|
||||
local result
|
||||
local val1
|
||||
local val2
|
||||
local val3
|
||||
local d1
|
||||
local d2
|
||||
local d3
|
||||
|
||||
case "$*" in
|
||||
*[!0-9,.]* )
|
||||
echo "number: invalid character in argument." 1>&2
|
||||
return 1
|
||||
;;
|
||||
*.* )
|
||||
echo "number: fractions not supported (yet)." 1>&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
result=''
|
||||
|
||||
eval set - "`echo ${1+\"$@\"} | sed -n -e '
|
||||
s/[, ]//g;s/^00*/0/g;s/\(.\)\(.\)\(.\)$/\"\1 \2 \3\"/;
|
||||
:l
|
||||
/[0-9][0-9][0-9]/{
|
||||
s/\([^\" ][^\" ]*\)\([^\" ]\)\([^\" ]\)\([^\" ]\)/\1\"\2 \3 \4\"/g;
|
||||
t l
|
||||
}
|
||||
/^[0-9][0-9][0-9]/s/\([^\" ]\)\([^\" ]\)\([^\" ]\)/\"\1 \2 \3\"/;
|
||||
/^[0-9][0-9]/s/\([^\" ]\)\([^\" ]\)/\"\1 \2\"/;
|
||||
/^[0-9]/s/^\([^\" ][^\" ]*\)/\"\1\"/g;s/\"\"/\" \"/g;p;'`"
|
||||
|
||||
while test $# -ne 0 ; do
|
||||
eval `set - $1;
|
||||
d3='' d2='' d1=''
|
||||
case $# in
|
||||
1 ) d1=$1 ;;
|
||||
2 ) d2=$1 d1=$2 ;;
|
||||
3 ) d3=$1 d2=$2 d1=$3 ;;
|
||||
esac
|
||||
echo "d3=\"${d3}\" d2=\"${d2}\" d1=\"${d1}\""`
|
||||
|
||||
val1='' val2='' val3=''
|
||||
|
||||
case "${d3}" in
|
||||
'1' ) val3='one' ;;
|
||||
'2' ) val3='two' ;;
|
||||
'3' ) val3='three' ;;
|
||||
'4' ) val3='four' ;;
|
||||
'5' ) val3='five' ;;
|
||||
'6' ) val3='six' ;;
|
||||
'7' ) val3='seven' ;;
|
||||
'8' ) val3='eight' ;;
|
||||
'9' ) val3='nine' ;;
|
||||
esac
|
||||
|
||||
case "${d2}" in
|
||||
'1' ) val2='teen' ;;
|
||||
'2' ) val2='twenty' ;;
|
||||
'3' ) val2='thirty' ;;
|
||||
'4' ) val2='forty' ;;
|
||||
'5' ) val2='fifty' ;;
|
||||
'6' ) val2='sixty' ;;
|
||||
'7' ) val2='seventy' ;;
|
||||
'8' ) val2='eighty' ;;
|
||||
'9' ) val2='ninety' ;;
|
||||
esac
|
||||
|
||||
case "${val2}" in
|
||||
'teen')
|
||||
val2=''
|
||||
case "${d1}" in
|
||||
'0') val1='ten' ;;
|
||||
'1') val1='eleven' ;;
|
||||
'2') val1='twelve' ;;
|
||||
'3') val1='thirteen' ;;
|
||||
'4') val1='fourteen' ;;
|
||||
'5') val1='fifteen' ;;
|
||||
'6') val1='sixteen' ;;
|
||||
'7') val1='seventeen' ;;
|
||||
'8') val1='eighteen' ;;
|
||||
'9') val1='nineteen' ;;
|
||||
esac
|
||||
;;
|
||||
0 ) : ;;
|
||||
* )
|
||||
if test ".${val2}" != '.' -a ".${d1}" != '.0' ; then
|
||||
val2="${val2}-"
|
||||
fi
|
||||
case "${d1}" in
|
||||
'0') val2="${val2} " ;;
|
||||
'1') val1='one' ;;
|
||||
'2') val1='two' ;;
|
||||
'3') val1='three' ;;
|
||||
'4') val1='four' ;;
|
||||
'5') val1='five' ;;
|
||||
'6') val1='six' ;;
|
||||
'7') val1='seven' ;;
|
||||
'8') val1='eight' ;;
|
||||
'9') val1='nine' ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
if test ".${val3}" != '.' ; then
|
||||
result="${result}${val3} hundred "
|
||||
fi
|
||||
|
||||
if test ".${val2}" != '.' ; then
|
||||
result="${result}${val2}"
|
||||
fi
|
||||
|
||||
if test ".${val1}" != '.' ; then
|
||||
result="${result}${val1} "
|
||||
fi
|
||||
|
||||
if test ".${d1}${d2}${d3}" != '.000' ; then
|
||||
case $# in
|
||||
0 | 1 ) ;;
|
||||
2 ) result="${result}thousand " ;;
|
||||
3 ) result="${result}million " ;;
|
||||
4 ) result="${result}billion " ;;
|
||||
5 ) result="${result}trillion " ;;
|
||||
6 ) result="${result}quadrillion " ;;
|
||||
7 ) result="${result}quintillion " ;;
|
||||
8 ) result="${result}sextillion " ;;
|
||||
9 ) result="${result}septillion " ;;
|
||||
10 ) result="${result}octillion " ;;
|
||||
11 ) result="${result}nonillion " ;;
|
||||
12 ) result="${result}decillion " ;;
|
||||
13 ) result="${result}undecillion " ;;
|
||||
14 ) result="${result}duodecillion " ;;
|
||||
15 ) result="${result}tredecillion " ;;
|
||||
16 ) result="${result}quattuordecillion " ;;
|
||||
17 ) result="${result}quindecillion " ;;
|
||||
18 ) result="${result}sexdecillion " ;;
|
||||
19 ) result="${result}septendecillion " ;;
|
||||
20 ) result="${result}octodecillion " ;;
|
||||
21 ) result="${result}novemdecillion " ;;
|
||||
22 ) result="${result}vigintillion " ;;
|
||||
* )
|
||||
echo "Error: number too large (66 digits max)." 1>&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
set - ${result}
|
||||
case "$*" in
|
||||
'') set - 'zero' ;;
|
||||
esac
|
||||
|
||||
echo ${1+"$@"}
|
||||
}
|
||||
|
||||
provide number
|
||||
|
||||
# number.bash ends here
|
||||
@@ -0,0 +1,40 @@
|
||||
# prompt.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-01-15
|
||||
# Public domain
|
||||
|
||||
# $Id: prompt.bash,v 1.2 1994/10/18 16:34:35 friedman Exp $
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring prompt:
|
||||
# Usage: prompt [chars]
|
||||
#
|
||||
# Various preformatted prompt strings selected by argument. For a
|
||||
# list of available arguments and corresponding formats, do
|
||||
# `type prompt'.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function prompt ()
|
||||
{
|
||||
case "$1" in
|
||||
d) PS1='$(dirs) \$ ' ;;
|
||||
n) PS1='\$ ' ;;
|
||||
hsw) PS1='\h[$SHLVL]: \w \$ ' ;;
|
||||
hw) PS1='\h: \w \$ ' ;;
|
||||
sh) PS1='[$SHLVL] \h\$ ' ;;
|
||||
sw) PS1='[$SHLVL] \w \$ ' ;;
|
||||
uh) PS1='\u@\h\$ ' ;;
|
||||
uhsHw) PS1='\u@\h[$SHLVL]:\#: \w \$ ' ;;
|
||||
uhsw) PS1='\u@\h[$SHLVL]: \w \$ ' ;;
|
||||
uhw) PS1='\u@\h: \w \$ ' ;;
|
||||
uw) PS1='(\u) \w \$ ' ;;
|
||||
w) PS1='\w \$ ' ;;
|
||||
esac
|
||||
}
|
||||
|
||||
provide prompt
|
||||
|
||||
# prompt.bash ends here
|
||||
@@ -0,0 +1,71 @@
|
||||
# remap_keybindings.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-01-11
|
||||
# Last modified: 1993-02-03
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring remap_keybindings:
|
||||
# Usage: remap_keybindings old_function new_function
|
||||
#
|
||||
# Clear all readline keybindings associated with OLD_FUNCTION (a Readline
|
||||
# function) rebinding them to NEW_FUNCTION (`self-insert' by default)
|
||||
#
|
||||
# This requires bash version 1.10 or newer, since previous versions did not
|
||||
# implement the `bind' builtin.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function remap_keybindings ()
|
||||
{
|
||||
local unbind_function="$1"
|
||||
local bind_function="${2:-'self-insert'}"
|
||||
local bind_output
|
||||
local arg
|
||||
|
||||
# If they're the same thing, the work has already been done. :-)
|
||||
if [ "${unbind_function}" = "${bind_function}" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
while : ; do
|
||||
bind_output="$(bind -q ${unbind_function} 2> /dev/null)"
|
||||
|
||||
case "${bind_output}" in
|
||||
"${unbind_function} can be invoked via"* ) ;;
|
||||
"" ) return 1 ;; # probably bad argument to bind
|
||||
*) return 0 ;; # unbound
|
||||
esac
|
||||
|
||||
# Format of bind_output is like:
|
||||
# 'quoted-insert can be invoked via "\C-q", "\C-v".'
|
||||
# 'self-insert can be invoked via " ", "!", """, "$", "%", ...'
|
||||
set -- ${bind_output}
|
||||
shift 5
|
||||
|
||||
for arg in "$@" ; do
|
||||
# strip off trailing `.' or `,'
|
||||
arg=${arg%.};
|
||||
arg=${arg%,};
|
||||
|
||||
case ${arg} in
|
||||
..)
|
||||
# bind -q didn't provide whole list of key bindings; jump
|
||||
# to top loop to get more
|
||||
continue 2 ;
|
||||
;;
|
||||
*)
|
||||
bind "${arg}: ${bind_function}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
provide remap_keybindings
|
||||
|
||||
# remap_keybindings.bash ends here
|
||||
@@ -0,0 +1,182 @@
|
||||
# require.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-07-08
|
||||
# Last modified: 1993-09-29
|
||||
# Public domain
|
||||
|
||||
# Commentary:
|
||||
|
||||
# These functions provide an interface based on the lisp implementation for
|
||||
# loading libraries when they are needed and eliminating redundant loading.
|
||||
# The basic idea is that each "package" (or set of routines, even if it is
|
||||
# only one function) registers itself with a symbol that marks a "feature"
|
||||
# as being "provided". If later you "require" a given feature, you save
|
||||
# yourself the trouble of explicitly loading it again.
|
||||
#
|
||||
# At the bottom of each package, put a "provide foobar", so when another
|
||||
# package has a "require foobar", it gets loaded and registered as a
|
||||
# "feature" that won't need to get loaded again. (See warning below for
|
||||
# reasons why provide should be put at the end.)
|
||||
#
|
||||
# The list of provided features are kept in the `FEATURES' variable, which
|
||||
# is not exported. Care should be taken not to munge this in the shell.
|
||||
# The search path comes from a colon-separated `FPATH' variable. It has no
|
||||
# default value and must be set by the user.
|
||||
#
|
||||
# Require uses `fpath_search', which works by scanning all of FPATH for a
|
||||
# file named the same as the required symbol but with a `.bash' appended to
|
||||
# the name. If that is found, it is loaded. If it is not, FPATH is
|
||||
# searched again for a file name the same as the feature (i.e. without any
|
||||
# extension). Fpath_search may be useful for doing library filename
|
||||
# lookups in other functions (such as a `load' or `autoload' function).
|
||||
#
|
||||
# Warning: Because require ultimately uses the builtin `source' command to
|
||||
# read in files, it has no way of undoing the commands contained in the
|
||||
# file if there is an error or if no provide statement appeared (this
|
||||
# differs from the lisp implementation of require, which normally undoes
|
||||
# most of the forms that were loaded if the require fails). Therefore, to
|
||||
# minize the number of problems caused by requiring a faulty package (such
|
||||
# as syntax errors in the source file) it is better to put the provide at
|
||||
# the end of the file, rather than at the beginning.
|
||||
|
||||
# Code:
|
||||
|
||||
# Exporting this variable would cause considerable lossage, since none of
|
||||
# the functions are exported (or at least, they're not guaranteed to be)
|
||||
export -n FEATURES
|
||||
|
||||
#:docstring :
|
||||
# Null function. Provided only so that one can put page breaks in source
|
||||
# files without any ill effects.
|
||||
#:end docstring:
|
||||
#
|
||||
# (\\014 == C-l)
|
||||
eval "function $(echo -e \\014) () { : }"
|
||||
|
||||
|
||||
#:docstring featurep:
|
||||
# Usage: featurep argument
|
||||
#
|
||||
# Returns 0 (true) if argument is a provided feature. Returns 1 (false)
|
||||
# otherwise.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function featurep ()
|
||||
{
|
||||
local feature="$1"
|
||||
|
||||
case " ${FEATURES} " in
|
||||
*" ${feature} "* ) return 0 ;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
#:docstring provide:
|
||||
# Usage: provide symbol ...
|
||||
#
|
||||
# Register a list of symbols as provided features
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function provide ()
|
||||
{
|
||||
local feature
|
||||
|
||||
for feature in "$@" ; do
|
||||
if ! featurep "${feature}" ; then
|
||||
FEATURES="${FEATURES} ${feature}"
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
#:docstring require:
|
||||
# Usage: require feature {file}
|
||||
#
|
||||
# Load FEATURE if it is not already provided. Note that require does not
|
||||
# call `provide' to register features. The loaded file must do that
|
||||
# itself. If the package does not explicitly do a `provide' after being
|
||||
# loaded, require will complain about the feature not being provided on
|
||||
# stderr.
|
||||
#
|
||||
# Optional argument FILE means to try to load FEATURE from FILE. If no
|
||||
# file argument is given, require searches through FPATH (see fpath_search)
|
||||
# for the appropriate file.
|
||||
#
|
||||
# If the variable REQUIRE_FAILURE_FATAL is set, require will cause the
|
||||
# current shell invocation to exit, rather than merely return. This may be
|
||||
# useful for a shell script that vitally depends on a package.
|
||||
#
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function require ()
|
||||
{
|
||||
local feature="$1"
|
||||
local path="$2"
|
||||
local file
|
||||
|
||||
if ! featurep "${feature}" ; then
|
||||
file=$(fpath_search "${feature}" "${path}") && source "${file}"
|
||||
|
||||
if ! featurep "${feature}" ; then
|
||||
echo "require: ${feature}: feature was not provided." 1>&2
|
||||
if [ "${REQUIRE_FAILURE_FATAL+set}" = "set" ]; then
|
||||
exit 1
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
#:docstring fpath_search:
|
||||
# Usage: fpath_search filename {path ...}
|
||||
#
|
||||
# Search $FPATH for `filename' or, if `path' (a list) is specified, search
|
||||
# those directories instead of $FPATH. First the path is searched for an
|
||||
# occurrence of `filename.bash, then a second search is made for just
|
||||
# `filename'.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function fpath_search ()
|
||||
{
|
||||
local name="$1"
|
||||
local path="$2"
|
||||
local suffix=".bash"
|
||||
local file
|
||||
|
||||
if [ -z "${path}" ]; then path="${FPATH}"; fi
|
||||
|
||||
for file in "${name}${suffix}" "${name}" ; do
|
||||
set -- $(IFS=':'
|
||||
set -- ${path}
|
||||
for p in "$@" ; do
|
||||
echo -n "${p:-.} "
|
||||
done)
|
||||
|
||||
while [ $# -ne 0 ]; do
|
||||
test -f "${1}/${file}" && { file="${1}/${file}"; break 2 }
|
||||
shift
|
||||
done
|
||||
done
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "fpath_search: ${name}: file not found in fpath" 1>&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "${file}"
|
||||
return 0
|
||||
}
|
||||
|
||||
provide require
|
||||
|
||||
# require.bash ends here
|
||||
@@ -0,0 +1,140 @@
|
||||
# send_mail.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-07-02
|
||||
# Public domain
|
||||
|
||||
# Commentary:
|
||||
|
||||
# TODO: implement Fcc headers (see emacs manual)
|
||||
|
||||
# Code:
|
||||
|
||||
#:docstring send_mail:
|
||||
# Usage: send_mail
|
||||
#
|
||||
# This function serves as a simple replacement for sendmail as a client
|
||||
# interface on those systems where it is not available. It does assume
|
||||
# that one can talk to an SMTP mailer on port 25 either on the local host
|
||||
# or on the host specified by the MAILHOST environment variable. If you
|
||||
# have access to sendmail, it's better to use 'sendmail -t' instead of this
|
||||
# script (which probably isn't as robust).
|
||||
#
|
||||
# Message is read from stdin, and headers are parsed to determine
|
||||
# recipients.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function send_mail ()
|
||||
{
|
||||
# Need gawk, since several extensions are taken advantage of (like
|
||||
# IGNORECASE for regexps).
|
||||
local awk="${GAWK_LOCATION:-gawk}"
|
||||
local DefaultFrom="${USER:-${LOGNAME}}"
|
||||
local From
|
||||
local To
|
||||
local Cc
|
||||
local Bcc
|
||||
local tmpfile="/tmp/send_mail$$"
|
||||
|
||||
while [ -e "${tmpfile}" ]; do
|
||||
tmpfile="/tmp/send_mail${RANDOM}"
|
||||
done
|
||||
|
||||
# Lines consisting only of dots need one more dot appended. SMTP
|
||||
# servers eat one of the dots (and if only 1 dot appears, it signifies
|
||||
# the end of the message).
|
||||
sed '/^\.\.*/s/^\(\.\.*\)$/\1./' > "${tmpfile}"
|
||||
|
||||
# Parse mail headers in message to extract recipients list.
|
||||
# This doesn't affect what the user sees---it's only used to generate
|
||||
# the rcpt-to lines for SMTP.
|
||||
eval $(${awk} -f - "${tmpfile}" <<- '__EOF__'
|
||||
# Try to extract email address from amidst random data
|
||||
function parse_address (data)
|
||||
{
|
||||
# From: "real name" <foobar@host>
|
||||
# From: "" <foobar@host>
|
||||
if (match(data, /^\"[^\"]*\"[ \t]*<.*>/)) {
|
||||
data_idx = match(data, /^\"[^\"]*\"[ \t]*</)
|
||||
data = substr(data, RSTART + RLENGTH);
|
||||
if (data_idx = match(data, ">.*"))
|
||||
data = substr(data, 1, RSTART - 1);
|
||||
return data
|
||||
}
|
||||
# From: real name <foobar@host>
|
||||
if (match(data, /<.*>/)) {
|
||||
data_idx = match(data, /</)
|
||||
data = substr(data, RSTART + RLENGTH);
|
||||
if (data_idx = match(data, ">"))
|
||||
data = substr(data, 1, RSTART - 1);
|
||||
return data
|
||||
}
|
||||
# From: foobar@host (real name)
|
||||
if (match(data, /\(.*\)/)) {
|
||||
data_idx = match(data, /\(/);
|
||||
data = substr(data, 1, RSTART - 1);
|
||||
return data
|
||||
}
|
||||
# (hopefully) From: foobar@host
|
||||
return data
|
||||
}
|
||||
|
||||
BEGIN { IGNORECASE = 1; }
|
||||
|
||||
# Blank line signifies end of headers, so we can stop looking.
|
||||
/^$/ { exit(0) }
|
||||
|
||||
/^from:|^to:|^cc:|^bcc:/ {
|
||||
header_idx = match($0, /^[^:]*:/)
|
||||
if (header_idx) {
|
||||
# Capitalize header name
|
||||
header_firstchar = toupper(substr($0, RSTART, 1));
|
||||
header_rest = tolower(substr($0, RSTART + 1, RLENGTH - 2));
|
||||
header = header_firstchar header_rest
|
||||
|
||||
$0 = substr($0, RSTART + RLENGTH + 1);
|
||||
addresses = ""
|
||||
# parse addresses
|
||||
while ($0) {
|
||||
# Strip leading whitespace
|
||||
if (idx = match($0, /[ \t]*/))
|
||||
$0 = substr($0, RSTART + RLENGTH);
|
||||
|
||||
# Find everything up to a nonquoted comma
|
||||
# FIXME: doesnt handle quoting yet
|
||||
if (idx = match($0, /,/)) {
|
||||
data = substr($0, 1, RSTART);
|
||||
$0 = substr($0, RSTART + 1);
|
||||
} else {
|
||||
data = $0
|
||||
$0 = ""
|
||||
}
|
||||
addresses = addresses " " parse_address(data)
|
||||
}
|
||||
|
||||
printf("%s='%s'\n", header, addresses);
|
||||
}
|
||||
}
|
||||
__EOF__)
|
||||
|
||||
# Not sure if an address is *required* after the HELO.. every sendmail
|
||||
# I tried talking to didn't seem to care. Some sendmails don't care
|
||||
# if there's a HELO at all.
|
||||
cat <<- __EOF__ | telnet ${MAILHOST:-localhost} 25 > /dev/null 2>&1
|
||||
HELO
|
||||
mail from: ${From:-${DefaultFrom}}
|
||||
$(for name in ${To} ${Cc} ${Bcc} ; do
|
||||
echo "rcpt to: ${name}"
|
||||
done)
|
||||
data
|
||||
$(cat "${tmpfile}")
|
||||
.
|
||||
quit
|
||||
__EOF__
|
||||
|
||||
rm -f "${tmpfile}"
|
||||
}
|
||||
|
||||
provide send_mail
|
||||
|
||||
# send_mail.bash ends here
|
||||
@@ -0,0 +1,49 @@
|
||||
# shcat.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-07-17
|
||||
# Last modified: 1993-09-29
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring shcat:
|
||||
# Usage: shcat {file1} {file2} {...}
|
||||
#
|
||||
# Like `cat', only this is all inline bash.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function shcat ()
|
||||
{
|
||||
local IFS=""
|
||||
local line
|
||||
local file
|
||||
local exitstat=0
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
while read -r line; do
|
||||
echo "${line}"
|
||||
done
|
||||
return 0
|
||||
else
|
||||
for file in "$@" ; do
|
||||
if [ -r "${file}" ]; then
|
||||
while read -r line; do
|
||||
echo "${line}"
|
||||
done < "${file}"
|
||||
else
|
||||
# This will cause the error to be printed on stderr
|
||||
< "${file}"
|
||||
exitstat=1
|
||||
fi
|
||||
done
|
||||
return ${exitstat}
|
||||
fi
|
||||
}
|
||||
|
||||
provide shcat
|
||||
|
||||
# shcat.bash ends here
|
||||
@@ -0,0 +1,63 @@
|
||||
# source.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-05-17
|
||||
# Last modified: 1993-09-29
|
||||
# Public domain
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring source:
|
||||
# Usage: source file ...
|
||||
#
|
||||
# Source forces file arguments to be considered in the current directory
|
||||
# only, unless there is an absolute path starting with `/'. I think it's
|
||||
# bad that the builtin "source" searches PATH, because PATH normally
|
||||
# contains directories with binary files that aren't useful for bash to
|
||||
# read and most people don't put "." first in their path.
|
||||
#
|
||||
# This "source" is capable of reading more than one file at a time. Return
|
||||
# value is number of failed source attempts.
|
||||
#:end docstring:
|
||||
|
||||
# This function is not hygienic, but there's not much we can do about
|
||||
# variable name conflicts here.
|
||||
|
||||
###;;;autoload
|
||||
function source ()
|
||||
{
|
||||
local -i _source_failure_count=0
|
||||
local _source_file
|
||||
|
||||
for _source_file ; do
|
||||
# Check first part of each filename. If it's not `/', `./', or
|
||||
# `../' then prepend "./" to the path to force the builtin `source'
|
||||
# not to go searching through PATH to find the file.
|
||||
case "${_source_file}" in
|
||||
/*|./*|../* ) ;;
|
||||
* ) _source_file="./${_source_file}" ;;
|
||||
esac
|
||||
|
||||
builtin source "${_source_file}" ||
|
||||
_source_failure_count="_source_failure_count + 1"
|
||||
|
||||
done
|
||||
|
||||
return ${_source_failure_count}
|
||||
}
|
||||
|
||||
#:docstring .:
|
||||
# See "source"
|
||||
#:end docstring:
|
||||
|
||||
# So that `.' will call function definition of `source' instead of builtin
|
||||
|
||||
###;;;autoload
|
||||
function . ()
|
||||
{
|
||||
source "$@"
|
||||
}
|
||||
|
||||
provide source
|
||||
|
||||
# source.bash ends here
|
||||
@@ -0,0 +1,226 @@
|
||||
# string.bash --- bash emulation of string(3) library routines
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-07-01
|
||||
# Last modified: 1993-09-29
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring strcat:
|
||||
# Usage: strcat s1 s2
|
||||
#
|
||||
# Strcat appends the value of variable s2 to variable s1.
|
||||
#
|
||||
# Example:
|
||||
# a="foo"
|
||||
# b="bar"
|
||||
# strcat a b
|
||||
# echo $a
|
||||
# => foobar
|
||||
#
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function strcat ()
|
||||
{
|
||||
local s1_val s2_val
|
||||
|
||||
s1_val=${!1} # indirect variable expansion
|
||||
s2_val=${!2}
|
||||
eval "$1"=\'"${s1_val}${s2_val}"\'
|
||||
}
|
||||
|
||||
#:docstring strncat:
|
||||
# Usage: strncat s1 s2 $n
|
||||
#
|
||||
# Line strcat, but strncat appends a maximum of n characters from the value
|
||||
# of variable s2. It copies fewer if the value of variabl s2 is shorter
|
||||
# than n characters. Echoes result on stdout.
|
||||
#
|
||||
# Example:
|
||||
# a=foo
|
||||
# b=barbaz
|
||||
# strncat a b 3
|
||||
# echo $a
|
||||
# => foobar
|
||||
#
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function strncat ()
|
||||
{
|
||||
local s1="$1"
|
||||
local s2="$2"
|
||||
local -i n="$3"
|
||||
local s1_val s2_val
|
||||
|
||||
s1_val=${!s1} # indirect variable expansion
|
||||
s2_val=${!s2}
|
||||
|
||||
if [ ${#s2_val} -gt ${n} ]; then
|
||||
s2_val=${s2_val:0:$n} # substring extraction
|
||||
fi
|
||||
|
||||
eval "$s1"=\'"${s1_val}${s2_val}"\'
|
||||
}
|
||||
|
||||
#:docstring strcmp:
|
||||
# Usage: strcmp $s1 $s2
|
||||
#
|
||||
# Strcmp compares its arguments and returns an integer less than, equal to,
|
||||
# or greater than zero, depending on whether string s1 is lexicographically
|
||||
# less than, equal to, or greater than string s2.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function strcmp ()
|
||||
{
|
||||
[ "$1" = "$2" ] && return 0
|
||||
|
||||
[ "${1}" '<' "${2}" ] > /dev/null && return -1
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
#:docstring strncmp:
|
||||
# Usage: strncmp $s1 $s2 $n
|
||||
#
|
||||
# Like strcmp, but makes the comparison by examining a maximum of n
|
||||
# characters (n less than or equal to zero yields equality).
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function strncmp ()
|
||||
{
|
||||
if [ -z "${3}" -o "${3}" -le "0" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ ${3} -ge ${#1} -a ${3} -ge ${#2} ]; then
|
||||
strcmp "$1" "$2"
|
||||
return $?
|
||||
else
|
||||
s1=${1:0:$3}
|
||||
s2=${2:0:$3}
|
||||
strcmp $s1 $s2
|
||||
return $?
|
||||
fi
|
||||
}
|
||||
|
||||
#:docstring strlen:
|
||||
# Usage: strlen s
|
||||
#
|
||||
# Strlen returns the number of characters in string literal s.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function strlen ()
|
||||
{
|
||||
eval echo "\${#${1}}"
|
||||
}
|
||||
|
||||
#:docstring strspn:
|
||||
# Usage: strspn $s1 $s2
|
||||
#
|
||||
# Strspn returns the length of the maximum initial segment of string s1,
|
||||
# which consists entirely of characters from string s2.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function strspn ()
|
||||
{
|
||||
# Unsetting IFS allows whitespace to be handled as normal chars.
|
||||
local IFS=
|
||||
local result="${1%%[!${2}]*}"
|
||||
|
||||
echo ${#result}
|
||||
}
|
||||
|
||||
#:docstring strcspn:
|
||||
# Usage: strcspn $s1 $s2
|
||||
#
|
||||
# Strcspn returns the length of the maximum initial segment of string s1,
|
||||
# which consists entirely of characters not from string s2.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function strcspn ()
|
||||
{
|
||||
# Unsetting IFS allows whitspace to be handled as normal chars.
|
||||
local IFS=
|
||||
local result="${1%%[${2}]*}"
|
||||
|
||||
echo ${#result}
|
||||
}
|
||||
|
||||
#:docstring strstr:
|
||||
# Usage: strstr s1 s2
|
||||
#
|
||||
# Strstr echoes a substring starting at the first occurrence of string s2 in
|
||||
# string s1, or nothing if s2 does not occur in the string. If s2 points to
|
||||
# a string of zero length, strstr echoes s1.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function strstr ()
|
||||
{
|
||||
# if s2 points to a string of zero length, strstr echoes s1
|
||||
[ ${#2} -eq 0 ] && { echo "$1" ; return 0; }
|
||||
|
||||
# strstr echoes nothing if s2 does not occur in s1
|
||||
case "$1" in
|
||||
*$2*) ;;
|
||||
*) return 1;;
|
||||
esac
|
||||
|
||||
# use the pattern matching code to strip off the match and everything
|
||||
# following it
|
||||
first=${1/$2*/}
|
||||
|
||||
# then strip off the first unmatched portion of the string
|
||||
echo "${1##$first}"
|
||||
}
|
||||
|
||||
#:docstring strtok:
|
||||
# Usage: strtok s1 s2
|
||||
#
|
||||
# Strtok considers the string s1 to consist of a sequence of zero or more
|
||||
# text tokens separated by spans of one or more characters from the
|
||||
# separator string s2. The first call (with a non-empty string s1
|
||||
# specified) echoes a string consisting of the first token on stdout. The
|
||||
# function keeps track of its position in the string s1 between separate
|
||||
# calls, so that subsequent calls made with the first argument an empty
|
||||
# string will work through the string immediately following that token. In
|
||||
# this way subsequent calls will work through the string s1 until no tokens
|
||||
# remain. The separator string s2 may be different from call to call.
|
||||
# When no token remains in s1, an empty value is echoed on stdout.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function strtok ()
|
||||
{
|
||||
:
|
||||
}
|
||||
|
||||
#:docstring strtrunc:
|
||||
# Usage: strtrunc $n $s1 {$s2} {$...}
|
||||
#
|
||||
# Used by many functions like strncmp to truncate arguments for comparison.
|
||||
# Echoes the first n characters of each string s1 s2 ... on stdout.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function strtrunc ()
|
||||
{
|
||||
n=$1 ; shift
|
||||
for z; do
|
||||
echo "${z:0:$n}"
|
||||
done
|
||||
}
|
||||
|
||||
provide string
|
||||
|
||||
# string.bash ends here
|
||||
@@ -0,0 +1,64 @@
|
||||
# stty.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-01-11
|
||||
# Last modified: 1993-09-29
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
require remap_keybindings
|
||||
|
||||
#:docstring stty:
|
||||
# Track changes to certain keybindings with stty, and make those changes
|
||||
# reflect in bash's readline bindings as well.
|
||||
#
|
||||
# This requires bash version 1.10 or newer, since previous versions did not
|
||||
# implement the `bind' builtin.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function stty ()
|
||||
{
|
||||
local erase="backward-delete-char"
|
||||
local kill="unix-line-discard"
|
||||
local werase="backward-kill-word"
|
||||
local lnext="quoted-insert"
|
||||
local readline_function=""
|
||||
local key=""
|
||||
local stty_command=""
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
erase | kill | werase | lnext )
|
||||
key=$(echo "${2}" | cat -v | sed 's/\^/\\C-/')
|
||||
readline_function=$(eval echo \$${1})
|
||||
|
||||
# Get rid of any current bindings; the whole point of this
|
||||
# function is to make the distinction between readline
|
||||
# bindings and particular cbreak characters transparent; old
|
||||
# readline keybindings shouldn't hang around.
|
||||
# could use bind -r here instead of binding to self-insert
|
||||
remap_keybindings "${readline_function}" "self-insert"
|
||||
|
||||
# Bind new key to appropriate readline function
|
||||
bind "\"${key}\": ${readline_function}"
|
||||
|
||||
stty_command="${stty_command} ${1} ${2}"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
stty_command="${stty_command} ${1}"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
command stty ${stty_command}
|
||||
}
|
||||
|
||||
provide stty
|
||||
|
||||
# stty.bash ends here
|
||||
@@ -0,0 +1,78 @@
|
||||
# y_or_n_p.bash
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1992-06-18
|
||||
# Last modified: 1993-03-01
|
||||
# Public domain
|
||||
|
||||
# Conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# Commentary:
|
||||
# Code:
|
||||
|
||||
#:docstring y_or_n_p:
|
||||
# Usage: y_or_n_p QUERY
|
||||
#
|
||||
# Print QUERY on stderr, then read stdin for a y-or-n response. Actually,
|
||||
# user may type anything they like, but first character must be a `y', `n',
|
||||
# `q', or `!', otherwise the question is repeated until such an answer is
|
||||
# obtained.
|
||||
#
|
||||
# If user typed `y', y_or_n_p returns 0.
|
||||
#
|
||||
# If user typed `n', y_or_n_p returns 1.
|
||||
#
|
||||
# If user typed `!', y_or_n_p returns 2. This is an indication to the
|
||||
# caller that no more queries should be made. Assume `y' for all the rest.
|
||||
#
|
||||
# If user typed `q', y_or_n_p returns 3. This is an indication to the
|
||||
# caller that no more queries should be made. Assume `n' for all the rest.
|
||||
#
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function y_or_n_p ()
|
||||
{
|
||||
local ans
|
||||
|
||||
[ ! -t 0 ] && return 1
|
||||
|
||||
while read -p "$*" -e ans ; do
|
||||
case "${ans}" in
|
||||
y* | Y* ) return 0 ;;
|
||||
n* | N* ) return 1 ;;
|
||||
\! ) return 2 ;;
|
||||
q* | Q* ) return 3 ;;
|
||||
*) echo "Please answer one of \`y', \`n', \`q', or \`"\!"'" 1>&2 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
#:docstring yes_or_no_p:
|
||||
# Usage: yes_or_no_p QUERY
|
||||
#
|
||||
# Like y_or_n_p, but require a full `yes', `no', `yes!', or `quit' response.
|
||||
#:end docstring:
|
||||
|
||||
###;;;autoload
|
||||
function yes_or_no_p ()
|
||||
{
|
||||
local ans
|
||||
|
||||
[ ! -t 0 ] && return 3
|
||||
|
||||
while read -p "$*" -e ans; do
|
||||
ans="$(echo ${ans} | tr '[A-Z]' '[a-z]')"
|
||||
|
||||
case "${ans}" in
|
||||
yes ) return 0 ;;
|
||||
no ) return 1 ;;
|
||||
yes\! ) return 2 ;;
|
||||
quit ) return 3 ;;
|
||||
*) echo "Please answer \`yes', \`no', \`yes"\!"', or \`quit'" 1>&2 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
provide y_or_n_p
|
||||
|
||||
# y_or_n_p.bash ends here
|
||||
@@ -0,0 +1,59 @@
|
||||
From spcecdt@armory.com Wed May 10 10:21:11 1995
|
||||
Flags: 10
|
||||
Return-Path: spcecdt@armory.com
|
||||
Received: from po.cwru.edu (root@po.CWRU.Edu [129.22.4.2]) by odin.INS.CWRU.Edu with ESMTP (8.6.10+cwru/CWRU-2.1-ins)
|
||||
id KAA22876; Wed, 10 May 1995 10:21:10 -0400 (from spcecdt@armory.com for <chet@odin.INS.CWRU.Edu>)
|
||||
Received: from deepthought.armory.com (mmdf@deepthought.armory.com [192.122.209.42]) by po.cwru.edu with SMTP (8.6.10+cwru/CWRU-2.3)
|
||||
id BAA16354; Wed, 10 May 1995 01:33:22 -0400 (from spcecdt@armory.com for <chet@po.cwru.edu>)
|
||||
From: John DuBois <spcecdt@armory.com>
|
||||
Date: Tue, 9 May 1995 22:33:12 -0700
|
||||
In-Reply-To: Chet Ramey <chet@odin.ins.cwru.edu>
|
||||
"ksh scripts" (May 9, 1:36pm)
|
||||
X-Www: http://www.armory.com/~spcecdt/
|
||||
X-Mailer: Mail User's Shell (7.2.5 10/14/92)
|
||||
To: chet@po.cwru.edu
|
||||
Subject: Re: ksh scripts
|
||||
Message-ID: <9505092233.aa13001@deepthought.armory.com>
|
||||
|
||||
Sure. The canonical versions are available on ftp.armory.com; you might
|
||||
want to pick up the latest versions before modifying them.
|
||||
|
||||
John
|
||||
|
||||
On May 9, 1:36pm, Chet Ramey wrote:
|
||||
} Subject: ksh scripts
|
||||
} From odin.ins.cwru.edu!chet Tue May 9 10:39:51 1995
|
||||
} Received: from odin.INS.CWRU.Edu by deepthought.armory.com id aa22336;
|
||||
} 9 May 95 10:39 PDT
|
||||
} Received: (chet@localhost) by odin.INS.CWRU.Edu (8.6.10+cwru/CWRU-2.1-ins)
|
||||
} id NAA20487; Tue, 9 May 1995 13:39:24 -0400 (from chet)
|
||||
} Date: Tue, 9 May 1995 13:36:54 -0400
|
||||
} From: Chet Ramey <chet@odin.ins.cwru.edu>
|
||||
} To: john@armory.com
|
||||
} Subject: ksh scripts
|
||||
} Cc: chet@odin.ins.cwru.edu
|
||||
} Reply-To: chet@po.cwru.edu
|
||||
} Message-ID: <9505091736.AA20411.SM@odin.INS.CWRU.Edu>
|
||||
} Read-Receipt-To: chet@po.CWRU.Edu
|
||||
} MIME-Version: 1.0
|
||||
} Content-Type: text/plain; charset=us-ascii
|
||||
} Status: OR
|
||||
}
|
||||
} Hi. I'm the maintainer of bash (the GNU `Bourne Again shell') for
|
||||
} the FSF.
|
||||
}
|
||||
} I picked up a tar file of ksh scripts you wrote from an anon FTP site
|
||||
} a while back. I'd like your permission to include modified versions
|
||||
} of some of them in the next major bash distribution (with proper credit
|
||||
} given, of course). Is it OK if I do that?
|
||||
}
|
||||
} Chet Ramey
|
||||
}
|
||||
} --
|
||||
} ``The lyf so short, the craft so long to lerne.'' - Chaucer
|
||||
}
|
||||
} Chet Ramey, Case Western Reserve University Internet: chet@po.CWRU.Edu
|
||||
}-- End of excerpt from Chet Ramey
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
This collection of scripts was originally written for ksh-88 by
|
||||
John DuBois <spcecdt@armory.com>. The conversion to bash v2
|
||||
syntax was done by Chet Ramey.
|
||||
|
||||
These scripts are as-is; there is no copyright associated with
|
||||
any of them. They exist simply as examples of bash scripting.
|
||||
|
||||
Here's a description of what's in this directory:
|
||||
|
||||
arc2tarz Convert an "arc" archive to a compressed tar archive.
|
||||
corename Tell what produced a core file.
|
||||
fman Fast man replacement.
|
||||
frcp Copy files using ftp but with rcp-type command line syntax.
|
||||
lowercase Change filenames to lower case.
|
||||
ncp A nicer front end for cp (has -i, etc.).
|
||||
newext Change the extension of a group of files.
|
||||
nmv A nicer front end for mv (has -i, etc.).
|
||||
pages Print specified pages from files.
|
||||
pf A pager front end that handles compressed files.
|
||||
rename Change the names of files that match a pattern.
|
||||
repeat Execute a command multiple times.
|
||||
untar Unarchive a (possibly compressed) tarfile into a directory.
|
||||
uudec Carefully uudecode multiple files.
|
||||
uuenc uuencode multiple files.
|
||||
vtree Print a visual display of a directory tree.
|
||||
where Show where commands that match a pattern are.
|
||||
|
||||
The following scripts were written or converted by Chet Ramey:
|
||||
|
||||
bashrand Random number generator with upper and lower bounds and optional seed
|
||||
cdhist cd replacement with a directory stack added
|
||||
pmtop Poor man's `top' for SunOS 4.x and BSD/OS
|
||||
shprof Line profiler for bash scripts
|
||||
@@ -0,0 +1,85 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# arc2tarz: convert arced file to tarred, compressed form.
|
||||
# @(#) arc2tarz.ksh 1.0 92/02/16
|
||||
# 91/03/28 john h. dubois iii (john@armory.com)
|
||||
# 92/02/16 added -h option for help
|
||||
#
|
||||
# conversion to bash v2 syntax by Chet Ramey
|
||||
|
||||
unset ENV
|
||||
Usage="Usage: $0 arcfile [-hcg] [ tarzfile ]"
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo "$Usage
|
||||
arcfile is the name of an arc file to convert to tarred, compressed form.
|
||||
The file must have a .arc extension, but only the base name needs to be
|
||||
given. If no output file name is given, it will be created in the current
|
||||
directory with the name being the arcfile basename followed by .tar.EXT.
|
||||
If the -c option is given, compress will be used, and EXT will be Z.
|
||||
The default (also available with -g) is to use gzip, in which case EXT
|
||||
is gz. If the basename is too long the extension may be truncated. All
|
||||
uppercase letters in the names of files in the archive are moved to lowercase."
|
||||
}
|
||||
|
||||
compress=gzip
|
||||
ext=gz
|
||||
|
||||
while getopts "hcg" opt; do
|
||||
case "$opt" in
|
||||
h) phelp; exit 0;;
|
||||
c) compress=compress; ext=Z;;
|
||||
g) compress=gzip ; ext=gz ;;
|
||||
*) echo "$Usage" 1>&2 ; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [ $# = 0 ]; then
|
||||
phelp
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ -z "$TMP" ] && tmpdir=/tmp/arc2tarz.$$ || tmpdir=$TMP/arc2tarz.$$
|
||||
|
||||
case "$1" in
|
||||
*.arc) arcfile=$1 ;;
|
||||
*) arcfile=$1.arc ;;
|
||||
esac
|
||||
|
||||
if [ ! -f $arcfile ] || [ ! -r $arcfile ]; then
|
||||
echo "Could not open arc file \"$arcfile\"."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$arcfile" in
|
||||
/*) ;;
|
||||
*) arcfile=$PWD/$arcfile ;;
|
||||
esac
|
||||
|
||||
basename=${arcfile%.arc}
|
||||
basename=${basename##*/}
|
||||
[ $# -lt 2 ] && tarzname=$PWD/$basename.tar.$ext || tarzname=$2
|
||||
|
||||
trap 'rm -rf $tmpdir $tarzname' 1 2 3 6 15
|
||||
|
||||
mkdir $tmpdir
|
||||
cd $tmpdir
|
||||
echo "unarcing files..."
|
||||
arc -ie $arcfile
|
||||
|
||||
# lowercase
|
||||
for f in *; do
|
||||
new=$(echo $f | tr A-Z a-z)
|
||||
if [ "$f" != "$new" ]; then
|
||||
mv $f $new
|
||||
fi
|
||||
done
|
||||
|
||||
echo "tarring/compressing files..."
|
||||
tar cf - * | $compress > $tarzname
|
||||
cd -
|
||||
rm -rf $tmpdir
|
||||
@@ -0,0 +1,76 @@
|
||||
#! /bin/bash
|
||||
# bashrand - generate a random number in a specified range with an
|
||||
# optionally specified ``seed'' value.
|
||||
#
|
||||
# Original Author: Peter Turnbull, May 1993
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "$PROG: usage: $PROG [-s seed] lower-limit upper-limit" >&2
|
||||
}
|
||||
|
||||
PROG=${0##*/}
|
||||
|
||||
SEED=$$ # Initialize random-number seed value with PID
|
||||
|
||||
while getopts s: opt
|
||||
do
|
||||
case "$opt" in
|
||||
s) SEED=$OPTARG ;;
|
||||
*) usage ; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
# Process command-line arguments:
|
||||
case $# in
|
||||
2) Lower=$1; Upper=$2 ;;
|
||||
*) usage ; exit 2 ;;
|
||||
esac
|
||||
|
||||
# Check that specified values are integers:
|
||||
expr "$Lower" + 0 >/dev/null 2>&1 || {
|
||||
echo "$PROG: lower ($Lower) not an integer" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
expr "$Upper" + 0 >/dev/null 2>&1 || {
|
||||
echo "$PROG: upper ($Upper) not an integer" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
expr "$SEED" + 0 >/dev/null 2>&1 || {
|
||||
echo "$PROG: seed ($SEED) not an integer" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check that values are in the correct range:
|
||||
(( $Lower < 0 )) || [ `expr "$Lower" : '.*'` -gt 5 ] && {
|
||||
echo "$PROG: Lower limit ($Lower) out of range" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
(( $Upper > 32767 )) || [ `expr "$Upper" : '.*'` -gt 5 ] && {
|
||||
echo "$PROG: Upper limit ($Upper) out of range" >&2;
|
||||
exit 1
|
||||
}
|
||||
|
||||
(( $SEED < 0 )) || (( $SEED > 32767 )) || [ `expr "$SEED" : '.*'` -gt 5 ] && {
|
||||
echo "$PROG: Seed value ($SEED) out of range (0 to 32767)" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
(( $Upper <= $Lower )) && {
|
||||
echo "$PROG: upper ($Upper) <= lower value ($Lower)" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Seed the random-number generator:
|
||||
RANDOM=$SEED
|
||||
|
||||
# Compute value, scaled within range:
|
||||
let rand="$RANDOM % ($Upper - $Lower + 1) + $Lower"
|
||||
|
||||
# Report result:
|
||||
echo $rand
|
||||
@@ -0,0 +1,176 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# cdhist - cd replacement with a directory stack like pushd/popd
|
||||
#
|
||||
# usage: cd [-l] [-n] [-] [dir]
|
||||
#
|
||||
# options:
|
||||
# -l print the cd directory stack, one entry per line
|
||||
# - equivalent to $OLDPWD
|
||||
# -n cd to nth directory in cd directory stack
|
||||
# -s cd to first directory in stack matching (substring) `s'
|
||||
#
|
||||
# arguments:
|
||||
# dir cd to dir and push dir onto the cd directory stack
|
||||
#
|
||||
# If the new directory is a directory in the stack and the options selected
|
||||
# it (-n, -s), the new working directory is printed
|
||||
#
|
||||
# If the variable CDHISTFILE is set, the cd directory stack is loaded from
|
||||
# and written to $CDHISTFILE every time `cd' is executed.
|
||||
#
|
||||
# Note: I got this off the net somewhere; I don't know the original author
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@po.cwru.edu
|
||||
|
||||
_cd_print()
|
||||
{
|
||||
echo -e "$@"
|
||||
}
|
||||
|
||||
cd()
|
||||
{
|
||||
typeset -i cdlen i
|
||||
typeset t
|
||||
|
||||
if [ $# -eq 0 ]
|
||||
then
|
||||
set -- $HOME
|
||||
fi
|
||||
|
||||
if [ "$CDHISTFILE" -a -r "$CDHISTFILE" ] # if directory history exists
|
||||
then
|
||||
typeset CDHIST
|
||||
i=-1
|
||||
while read -r t # read directory history file
|
||||
do
|
||||
CDHIST[i=i+1]=$t
|
||||
done <$CDHISTFILE
|
||||
fi
|
||||
|
||||
if [ "${CDHIST[0]}" != "$PWD" -a "$PWD" != "" ]
|
||||
then
|
||||
_cdins # insert $PWD into cd history
|
||||
fi
|
||||
|
||||
cdlen=${#CDHIST[*]} # number of elements in history
|
||||
|
||||
case "$@" in
|
||||
-) # cd to new dir
|
||||
if [ "$OLDPWD" = "" ] && ((cdlen>1))
|
||||
then
|
||||
'_cdprint' ${CDHIST[1]}
|
||||
builtin cd ${CDHIST[1]}
|
||||
pwd
|
||||
else
|
||||
builtin cd "$@"
|
||||
# pwd
|
||||
fi
|
||||
;;
|
||||
-l) # _cdprint directory list
|
||||
((i=cdlen))
|
||||
while (((i=i-1)>=0))
|
||||
do
|
||||
num=$i
|
||||
'_cdprint' "$num ${CDHIST[i]}"
|
||||
done
|
||||
return
|
||||
;;
|
||||
-[0-9]|-[0-9][0-9]) # cd to dir in list
|
||||
if (((i=${1#-})<cdlen))
|
||||
then
|
||||
'_cdprint' ${CDHIST[i]}
|
||||
builtin cd ${CDHIST[i]}
|
||||
pwd
|
||||
else
|
||||
builtin cd $@
|
||||
# pwd
|
||||
fi
|
||||
;;
|
||||
-*) # cd to matched dir in list
|
||||
t=${1#-}
|
||||
i=1
|
||||
while ((i<cdlen))
|
||||
do
|
||||
case ${CDHIST[i]} in
|
||||
*$t*)
|
||||
'_cdprint' ${CDHIST[i]}
|
||||
builtin cd ${CDHIST[i]}
|
||||
pwd
|
||||
break
|
||||
;;
|
||||
esac
|
||||
((i=i+1))
|
||||
done
|
||||
if ((i>=cdlen))
|
||||
then
|
||||
builtin cd $@
|
||||
# pwd
|
||||
fi
|
||||
;;
|
||||
*) # cd to new dir
|
||||
builtin cd $@
|
||||
# pwd
|
||||
;;
|
||||
esac
|
||||
|
||||
_cdins # insert $PWD into cd history
|
||||
|
||||
if [ "$CDHISTFILE" ]
|
||||
then
|
||||
cdlen=${#CDHIST[*]} # number of elements in history
|
||||
|
||||
i=0
|
||||
while ((i<cdlen))
|
||||
do
|
||||
echo ${CDHIST[i]} # update directory history
|
||||
((i=i+1))
|
||||
done >$CDHISTFILE
|
||||
fi
|
||||
}
|
||||
|
||||
_cdins() # insert $PWD into cd history
|
||||
{ # meant to be called only by cd
|
||||
typeset -i i
|
||||
|
||||
i=0
|
||||
|
||||
while (( i < ${#CDHIST[*]} )) # see if dir is already in list
|
||||
do
|
||||
if [ "${CDHIST[$i]}" = "$PWD" ]
|
||||
then
|
||||
break
|
||||
fi
|
||||
((i=i+1))
|
||||
done
|
||||
|
||||
if (( i>22 )) # limit max size of list
|
||||
then
|
||||
i=22
|
||||
fi
|
||||
|
||||
while (((i=i-1)>=0)) # bump old dirs in list
|
||||
do
|
||||
CDHIST[i+1]=${CDHIST[i]}
|
||||
done
|
||||
|
||||
CDHIST[0]=$PWD # insert new directory in list
|
||||
}
|
||||
|
||||
# examples
|
||||
shopt -s expand_aliases
|
||||
|
||||
# go to known place before doing anything
|
||||
cd /
|
||||
|
||||
echo CDHIST: "${CDHIST[@]}"
|
||||
for dir in /tmp /bin - -2 -l
|
||||
do
|
||||
cd $dir
|
||||
echo CDHIST: "${CDHIST[@]}"
|
||||
echo PWD: $PWD
|
||||
|
||||
done
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,43 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# @(#) corename.ksh 1.0 93/04/01
|
||||
# 92/11/11 john h. dubois iii (john@armory.com)
|
||||
# 92/02/16 Added help option.
|
||||
# 92/02/22 Added cd to origdir to fix prob w/multiple relative paths.
|
||||
# 93/04/01 Added check for whether file exists.
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
# inspired by belal's equivalent utility
|
||||
|
||||
if [ "$1" = -h ]; then
|
||||
echo \
|
||||
"$0: print the names of executables that dumped core.
|
||||
Usage: $0 [corename ...]
|
||||
If no corename is given, \"core\" is assumed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[ $# = 0 ] && set core
|
||||
origdir=$PWD
|
||||
for i; do
|
||||
cd $origdir
|
||||
file=${i##*/}
|
||||
dir=${i%$file}
|
||||
[ -z "$dir" ] && dir=$origdir/
|
||||
if [ ! -f $dir$file ]; then
|
||||
echo "$dir$file: No such file."
|
||||
continue
|
||||
fi
|
||||
if [ ! -r $dir$file ]; then
|
||||
echo "$dir$file: Cannot open."
|
||||
continue
|
||||
fi
|
||||
cd $dir
|
||||
|
||||
# the adb output syntax is highly variable. this works on SunOS 4.x
|
||||
set -- $(adb $file < /dev/null 2>&1 | sed 1q)
|
||||
name=${7#??}
|
||||
echo "$i: ${name%??}"
|
||||
done
|
||||
@@ -0,0 +1,281 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# fman: new man program
|
||||
# @(#) fman.ksh 1.5 94/04/16
|
||||
# 91/07/03 john h. dubois iii (john@armory.com)
|
||||
# 91/07/11 made it unpack man pages if neccessary
|
||||
# 91/07/16 fixed test for whether man file pattern was expanded
|
||||
# 92/01/21 made it read /etc/default/man to get section order,
|
||||
# and only display the first section found.
|
||||
# 92/02/06 changed name to fman
|
||||
# 92/02/07 fixed bug in notfound
|
||||
# 92/02/13 incorporated changes from DOS version
|
||||
# 92/03/11 changed to use MANPATH from environment if set,
|
||||
# and search all directories given in MANPATH
|
||||
# 92/03/15 exec pager or man w/o forking
|
||||
# 92/05/31 try using index if one exists
|
||||
# 92/10/01 Added "See also <other sections>"
|
||||
# 92/10/18 If PAGER is less, search for name of man page to make it easier
|
||||
# to find information in man pages for multiple items
|
||||
# 92/11/11 Make it work for compressed files not listed in index;
|
||||
# deal with man pages listed in index that don't exist.
|
||||
# 93/03/30 Fixed bug in MANPATH processing
|
||||
# 93/06/17 Include paths in "See also:" message if they would be needed
|
||||
# to get to a man page. Allow MANPATH spec on command line.
|
||||
# 93/07/09 Added -h and -e options.
|
||||
# 94/04/16 Added x option.
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
istrue()
|
||||
{
|
||||
test 0 -ne "$1"
|
||||
}
|
||||
|
||||
isfalse()
|
||||
{
|
||||
test 0 -eq "$1"
|
||||
}
|
||||
|
||||
# Finds all sections that man page $1 is in and puts them in the the
|
||||
# global array Sections[].
|
||||
# The filename of each page is put in FileNames[] with the same index.
|
||||
# Global vars used:
|
||||
# patharr[] MANPATH directories.
|
||||
|
||||
FindSectionsInIndex ()
|
||||
{
|
||||
typeset index indexes section mpath page=$1
|
||||
typeset -i i=0 NIndex=0
|
||||
|
||||
for mpath in "${patharr[@]}"; do
|
||||
if [ -r $mpath/index ]; then
|
||||
indexes="$indexes $mpath/index"
|
||||
let NIndex+=1
|
||||
fi
|
||||
done
|
||||
[ -z "$indexes" ] && return
|
||||
# Make egrep give filename
|
||||
[ NIndex -lt 2 ] && indexes="$indexes /dev/null"
|
||||
# set positional parameters to
|
||||
# indexfile:searchname pagename section ...
|
||||
# e.g.
|
||||
# /usr/man/index:FP_OFF Routines DOS
|
||||
set -- `egrep "^$page[ ]" $indexes`
|
||||
while [ $# -gt 2 ]; do
|
||||
FileNames[i]=${1%%index*}cat$3/$2.$3
|
||||
Sections[i]=$3
|
||||
shift 3
|
||||
let i+=1
|
||||
done
|
||||
}
|
||||
|
||||
# Finds all sections that man page $1 is in by searching each man directory
|
||||
# in the order given in patharr[],
|
||||
# and puts them in the the global array Sections[].
|
||||
# The filename of each page is put in FileNames[] with the same index.
|
||||
# Global vars used:
|
||||
# patharr[] MANPATH directories.
|
||||
FindSectionsInDirs ()
|
||||
{
|
||||
local page=$1 mpath AllPaths Path
|
||||
typeset -i i
|
||||
|
||||
for mpath in "${patharr[@]}"; do
|
||||
AllPaths="$AllPaths $mpath/cat[0-9]*/$page.* $mpath/man[0-9]*/$page.*"
|
||||
done
|
||||
|
||||
i=0
|
||||
for Path in $AllPaths; do
|
||||
istrue $debug && echo Path = $Path
|
||||
case "$Path" in
|
||||
*\*) ;;
|
||||
*)
|
||||
# Remove compressed-file suffix to make FileNames be the same
|
||||
# as it is when built by FindSectionsInIndex()
|
||||
FileNames[i]=${Path%.[zZ]}
|
||||
Path=${Path%/*}
|
||||
Sections[i]=${Path##*/*.}
|
||||
let i+=1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# FindSection: display man page.
|
||||
# Uses ordarr[] (built from $ORDER) to display the version of the man
|
||||
# page that occurs first in $ORDER.
|
||||
# Sections[] gives the sections that a man page was found in.
|
||||
# If the global variable "exist" is set to 1, nothing is displayed;
|
||||
# the function instead returns zero if a page is found, nonzero if not.
|
||||
# The filename of each page is in FileNames[] with the same index.
|
||||
# Global vars used:
|
||||
# Sections[], FileNames[], ordarr[]
|
||||
FindSection ()
|
||||
{
|
||||
typeset -i NumPages i foundsec
|
||||
local section OtherSec filename NPAGER=$PAGER POpt page=$1 Pat
|
||||
local PageFile
|
||||
|
||||
NumPages=${#Sections[*]} # Number of versions of man page found.
|
||||
isfalse $NumPages && return 1
|
||||
case "$PAGER" in
|
||||
*less) Popt="-p$page" ;;
|
||||
esac
|
||||
|
||||
# For each section in ORDER, determine if any man page was found in
|
||||
# that section
|
||||
for section in "${ordarr[@]}"; do
|
||||
i=0
|
||||
foundsec=0
|
||||
while [ $i -lt $NumPages ]; do
|
||||
if [ "${Sections[i]}" = $section ]; then
|
||||
# Found a man page from this section of ORDER
|
||||
filename=${FileNames[i]}
|
||||
if [ -z "$PageFile" ]; then
|
||||
PageFile=$filename
|
||||
else
|
||||
if istrue $foundsec; then
|
||||
OtherSec="$OtherSec$page(${filename%/*/*} $section) "
|
||||
else
|
||||
OtherSec="$OtherSec$page($section) "
|
||||
fi
|
||||
fi
|
||||
foundsec=1
|
||||
istrue $exist && return
|
||||
fi
|
||||
let i+=1
|
||||
done
|
||||
done
|
||||
# No pages with the specified section found.
|
||||
[ -z "$PageFile" ] && return 1
|
||||
# Return if all we want to know is whether the man page exists.
|
||||
[ "$exist" = 1 ] && return 0
|
||||
if [ -z "$OtherSec" ]; then
|
||||
NPAGER="exec $PAGER"
|
||||
fi
|
||||
if [ -r $PageFile ]; then
|
||||
$NPAGER $POpt $PageFile
|
||||
elif [ -r $PageFile.z ]; then
|
||||
pcat $PageFile.z | $NPAGER $POpt
|
||||
elif [ -r $PageFile.Z ]; then
|
||||
zcat $PageFile.Z | $NPAGER $POpt
|
||||
elif [ -f $PageFile.gz ]; then
|
||||
gzip -dc $PageFile.gz | $NPAGER $POpt
|
||||
else
|
||||
echo "$PageFile: cannot open." 1>&2
|
||||
OtherSec=
|
||||
unset Sections[i]
|
||||
let i+=1
|
||||
continue
|
||||
fi
|
||||
echo "See also $OtherSec"
|
||||
exit 0
|
||||
}
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo "$name: print man pages.
|
||||
$name locates and prints the specified manual pages from the online UNIX
|
||||
documentation.
|
||||
$Usage
|
||||
Options:
|
||||
-e: Determine whether the specified man page exists. Nothing is printed;
|
||||
$0 exits with a zero status if the page exists and a nonzero status if
|
||||
it does not.
|
||||
-h: Print this help."
|
||||
}
|
||||
|
||||
# main program
|
||||
|
||||
typeset -i exist=0 debug=0
|
||||
|
||||
name=${0##*/}
|
||||
Usage="Usage: $name [-eh] [[manpath] section] command-name"
|
||||
|
||||
while getopts :hex opt; do
|
||||
case $opt in
|
||||
h) phelp; exit 0;;
|
||||
e) exist=1 ;;
|
||||
x) debug=1 ;;
|
||||
+?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
|
||||
?)
|
||||
echo "$name: $OPTARG: bad option. Use -h for help." 1>&2 ; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# remove args that were options
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
echo -e "$Usage\nUse -h for help." 1>&2
|
||||
exit
|
||||
fi
|
||||
|
||||
P=$PAGER
|
||||
O=1:n:l:6:8:2:3:4:5:7:p:o
|
||||
T=$TERM
|
||||
M=${MANPATH:-/usr/local/man:/usr/man}
|
||||
[ -f /etc/default/man ] && . /etc/default/man
|
||||
[ -n "$P" ] && PAGER=$P
|
||||
[ -n "$O" ] && ORDER=$O
|
||||
[ -n "$T" ] && TERM=$T
|
||||
[ -n "$M" ] && MANPATH=$M
|
||||
|
||||
case $# in
|
||||
0) echo "No man page specified." ; exit 1;;
|
||||
1) page=$1;;
|
||||
2) ORDER=$(echo $1 | tr a-z A-Z) ; page=$2;;
|
||||
3) MANPATH=$1
|
||||
[ -n "$2" ] && ORDER=$(echo $2 | tr a-z A-Z)
|
||||
page=$3;;
|
||||
*) echo "Too many arguments."; exit 1;;
|
||||
esac
|
||||
|
||||
aargs=("$@")
|
||||
[ ! -t 0 ] && PAGER=cat
|
||||
|
||||
OIFS=$IFS
|
||||
IFS=:
|
||||
patharr=($MANPATH)
|
||||
i=0
|
||||
for d in $MANPATH; do
|
||||
for sec in $ORDER; do
|
||||
ordarr[i]=$d/cat${sec}
|
||||
let i+=1
|
||||
ordarr[i]=$d/man${sec}
|
||||
let i+=1
|
||||
done
|
||||
done
|
||||
IFS=$OIFS
|
||||
|
||||
istrue $debug && echo patharr = "${patharr[@]}"
|
||||
|
||||
# if less or more is being used, remove multiple blank lines
|
||||
export LESS="-s $LESS"
|
||||
export MORE="-s $MORE"
|
||||
|
||||
# Try using index
|
||||
FindSectionsInIndex "$page"
|
||||
# Exit 0 if a page was found and we're just testing for existence.
|
||||
FindSection "$page" && exit 0
|
||||
|
||||
# Try searching directories
|
||||
unset Sections[*]
|
||||
FindSectionsInDirs "$page"
|
||||
FindSection "$page" && exit 0
|
||||
|
||||
istrue $exist && exit 1
|
||||
|
||||
# Try using man
|
||||
# If using more or less, make man run faster by letting more or less compress
|
||||
# multiple blank lines instead of rmb
|
||||
#case "$PAGER" in
|
||||
#*more|*less) manopt=-b;;
|
||||
#esac
|
||||
|
||||
#cmd=(man $manopt -p$PAGER "${aargs[@]}")
|
||||
export PAGER
|
||||
cmd=(man $manopt "${aargs[@]}")
|
||||
istrue $debug && echo "$name: running ${cmd[*]}" 1>&2
|
||||
exec "${cmd[@]}"
|
||||
Executable
+288
@@ -0,0 +1,288 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
#
|
||||
# @(#) frcp.ksh 2.2 93/11/14
|
||||
# 92/06/29 john h. dubois iii (john@armory.com)
|
||||
# 92/10/14 Cleaned up, improved, added -d and -r options
|
||||
# 92/11/11 Made work with a dest of '.'
|
||||
# 93/07/09 Added -l and -n options, & login as anonymous if no .netrc entry
|
||||
# 93/11/14 Use either passwd or password in .netrc, since ftp does.
|
||||
#
|
||||
# conversion to bash v2 syntax by Chet Ramey
|
||||
#
|
||||
# frcp: ftp front end with rcp-like syntax.
|
||||
# Note: requires any machine names given to be listed with
|
||||
# user and password in .netrc. If not, anonymous FTP is
|
||||
# done.
|
||||
#
|
||||
# full path to ftp binary
|
||||
if [ -x /usr/bin/ftp ]; then
|
||||
FTP=/usr/bin/ftp;
|
||||
elif [ -x /usr/ucb/ftp ]; then
|
||||
FTP=/usr/ucb/ftp
|
||||
else
|
||||
FTP=ftp
|
||||
fi
|
||||
|
||||
istrue()
|
||||
{
|
||||
test 0 -ne "$1"
|
||||
}
|
||||
isfalse()
|
||||
{
|
||||
test 0 -eq "$1"
|
||||
}
|
||||
|
||||
# For each filename given, put the filename in filename[n]
|
||||
# and the machine it is on in machine[n].
|
||||
function SplitNames {
|
||||
typeset file
|
||||
typeset -i i=1
|
||||
|
||||
unset filename[*] machine[*]
|
||||
for file; do
|
||||
case "$file" in
|
||||
*:*) machine[i]=${file%%:*} ;;
|
||||
*) machine[i]=$LocalMach ;;
|
||||
esac
|
||||
filename[i]=${file#*:}
|
||||
let i+=1
|
||||
done
|
||||
}
|
||||
|
||||
function verboseprint {
|
||||
echo "$@"
|
||||
echo "$@" 1>&2
|
||||
}
|
||||
|
||||
function MakeDir {
|
||||
OFS=$IFS
|
||||
local IFS=/ dir component
|
||||
|
||||
case "$1" in
|
||||
/*) ;;
|
||||
*) dir=.
|
||||
esac
|
||||
set -- $1
|
||||
IFS=$OFS
|
||||
for component; do
|
||||
dir=$dir/$component
|
||||
if [ ! -d "$dir" ]; then
|
||||
if mkdir "$dir"; then :; else
|
||||
echo "Could not make directory $dir." >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
lastisdot ()
|
||||
{
|
||||
case "$1" in
|
||||
*/.|*/..) return 0;;
|
||||
*) return 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
# CopyFiles: issue ftp(TC) commands to copy files.
|
||||
# Usage: CopyFiles [sourcemachine:]sourcepath ... [destmachine:]destpath
|
||||
# Global vars:
|
||||
# Uses LocalMach (should be name of local machine)
|
||||
# Sets global arrs machine[]/filename[]
|
||||
function CopyFiles {
|
||||
unset machine[*] filename[*]
|
||||
|
||||
SplitNames "$@" # split names into filename[1..n] and machine[1..n]
|
||||
|
||||
local DestMach=${machine[$#]} # Machine to copy files to
|
||||
local DestPath=${filename[$#]} # Destination file/dir
|
||||
|
||||
unset machine[$#] filename[$#]
|
||||
|
||||
[ -z "$DestPath" ] && DestPath=. # dest was given as machine:
|
||||
|
||||
# Try to determine if destination should be a directory
|
||||
# so that it can be forced to be a directory.
|
||||
|
||||
case "$DestPath" in
|
||||
*/) ;; # don't add / if trailing / already present
|
||||
*) if [ $# -gt 2 ] || # if more than two args given, last must be a dir
|
||||
# If dest in on local machine, check whether it is a directory
|
||||
[ $DestMach = $LocalMach -a -d $DestPath ] ||
|
||||
# If dest ends with . or .., it is a directory
|
||||
lastisdot "$DestPath"
|
||||
then
|
||||
DestPath=$DestPath/
|
||||
fi ;;
|
||||
esac
|
||||
|
||||
# If one of the above tests made us think dest is a directory,
|
||||
# but it isn't, complain
|
||||
case "$DestPath" in
|
||||
*/) if [ "$DestMach" = "$LocalMach" ] && [ ! -d "$DestPath" ]; then
|
||||
echo "Destination is not a directory." 1>&2
|
||||
exit 1
|
||||
fi ;;
|
||||
esac
|
||||
|
||||
DoCopy "$DestMach" "$DestPath"
|
||||
}
|
||||
|
||||
# Usage: OpenMachine machine-name
|
||||
# Emits login sequence or doesn't, depending on .netrc file and global
|
||||
# variables anon and noanon
|
||||
OpenMachine ()
|
||||
{
|
||||
local machine=$1 netrc=$HOME/.netrc user= password=
|
||||
|
||||
if isfalse $anon && [ -r $netrc ]; then
|
||||
set -- $(gawk '
|
||||
/machine (.* )?'"$machine"'($| )/,/^ *$/ {
|
||||
Fields[$1] = $2
|
||||
if ("passwd" in Fields)
|
||||
Fields["password"] = Fields["passwd"]
|
||||
if ("login" in Fields && "password" in Fields) {
|
||||
print Fields["login"] " " Fields["password"]
|
||||
exit
|
||||
}
|
||||
}
|
||||
' $netrc )
|
||||
user=$1
|
||||
password=$2
|
||||
fi
|
||||
if [ -z "$password" ]; then
|
||||
if istrue $noanon; then
|
||||
echo "No .netrc entry for machine $machine" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
user=anonymous
|
||||
password=$USER@$LocalMach
|
||||
fi
|
||||
verboseprint open $machine
|
||||
echo user $user "*******" 1>&2
|
||||
echo user $user $password
|
||||
}
|
||||
|
||||
# Usage: DoCopy destination-machine destination-path
|
||||
# Copies the files in global arrs machine[]/filename[] to the given dest
|
||||
# Global vars:
|
||||
# Uses machine[], filename[], LocalMach, check
|
||||
DoCopy ()
|
||||
{
|
||||
local DestMach=$1
|
||||
local DestPath=$2
|
||||
local OpenMach # Machine that connection is currently open to
|
||||
local OWD=$PWD SourceMach SourceFile
|
||||
local FileName
|
||||
typeset -i i=1
|
||||
|
||||
while [ $i -le ${#machine[*]} ]; do
|
||||
istrue $check && verboseprint "runique"
|
||||
|
||||
SourceMach=${machine[i]}
|
||||
SourceFile=${filename[i]}
|
||||
|
||||
DestFile=$DestPath
|
||||
# if DestPath is a dir,
|
||||
# add source filename to it without source path
|
||||
case "$DestFile" in
|
||||
*/) DestFile=$DestFile${SourceFile##*/} ;;
|
||||
esac
|
||||
|
||||
if [ $SourceMach = $LocalMach ]; then
|
||||
if [ $DestMach != "$OpenMach" ]; then
|
||||
OpenMachine $DestMach
|
||||
OpenMach=$DestMach
|
||||
fi
|
||||
verboseprint put $SourceFile $DestFile
|
||||
elif [ $DestMach = $LocalMach ]; then
|
||||
if istrue $check && [ -f "$DestFile" ]; then
|
||||
echo "$DestFile already exists." 1>&2
|
||||
continue
|
||||
fi
|
||||
# If destination is on local machine,
|
||||
# the dest will be a full dir/filename
|
||||
if istrue $createdirs; then
|
||||
MakeDir "${DestFile%/*}" || continue
|
||||
fi
|
||||
if [ $SourceMach != "$OpenMach" ]; then
|
||||
OpenMachine $SourceMach
|
||||
OpenMach=$SourceMach
|
||||
fi
|
||||
# If source filename has wildcards ([, ], *, ?) do an mget
|
||||
case "$SourceFile" in
|
||||
\[*\]|*\**|*\?*)
|
||||
verboseprint lcd "$DestFile"
|
||||
verboseprint mget "$SourceFile"
|
||||
verboseprint lcd $OWD ;;
|
||||
*) verboseprint get "$SourceFile" "$DestFile" ;;
|
||||
esac
|
||||
else
|
||||
echo "Neither source machine \"$SourceMach\" "\
|
||||
"nor destination machine \"$DestMach\" is local." 1>&2
|
||||
fi
|
||||
let i+=1
|
||||
done
|
||||
}
|
||||
|
||||
# Start of main program
|
||||
name=${0##*/}
|
||||
|
||||
if [ "$1" = -h ]; then
|
||||
echo \
|
||||
"$name: do ftp transfers using rcp-style parameters.
|
||||
Usage: $name <source> <destpath> or $name <source> [<source> ...] <destdir>
|
||||
At least one of <source> and <destpath> must be the local system.
|
||||
A remote filename is given as machinename:filename
|
||||
If remote filenames contain wildcards, they will be globbed on the remote
|
||||
machine. Make sure they are quoted when $name is invoked.
|
||||
If the invoking user's .netrc file (see ftp(TC)) contains an entry for the
|
||||
remote system with a login and password supplied, $name will log in using
|
||||
the given login and password. If not, $name will login in as user
|
||||
anonymous and with the user@localsystem as the password.
|
||||
Options:
|
||||
-c: check: do not overwrite files.
|
||||
-d: create directories as needed.
|
||||
-f: force: overwrite files (default).
|
||||
-h: print this help.
|
||||
-l: fail if there is no entry with login and password for the remote system,
|
||||
instead of logging in as anonymous.
|
||||
-n: log in as anonymous even if there is an entry for the remote system in
|
||||
the user's .netrc file.
|
||||
-r: read source/dest filename pairs from the standard input,
|
||||
one pair per line, and copy files accordingly."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
typeset -i check=0 createdirs=0 readinput=0 anon=0 noanon=0
|
||||
|
||||
while getopts :cdflnr Option
|
||||
do
|
||||
case "$Option" in
|
||||
c) check=1;;
|
||||
d) createdirs=1;;
|
||||
f) check=0;;
|
||||
l) noanon=1;;
|
||||
n) anon=1;;
|
||||
r) readinput=1;;
|
||||
\?) echo "$OPTARG: invalid option."; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1))
|
||||
|
||||
LocalMach=`hostname`
|
||||
|
||||
if istrue $readinput; then
|
||||
while read line; do
|
||||
CopyFiles $line
|
||||
done | $FTP -nv
|
||||
else
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "$name: Not enough arguments. Use -h for help." 1>&2
|
||||
exit
|
||||
fi
|
||||
CopyFiles "$@" | $FTP -nv
|
||||
fi
|
||||
@@ -0,0 +1,44 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from
|
||||
# @(#) lowercase.ksh 1.0 92/10/08
|
||||
# 92/10/08 john h. dubois iii (john@armory.com)
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
Usage="Usage: $name file ..."
|
||||
phelp()
|
||||
{
|
||||
echo "$name: change filenames to lower case.
|
||||
$Usage
|
||||
Each file is moved to a name with the same directory component, if any,
|
||||
and with a filename component that is the same as the original but with
|
||||
any upper case letters changed to lower case."
|
||||
}
|
||||
|
||||
name=${0##*/}
|
||||
|
||||
while getopts "h" opt; do
|
||||
case "$opt" in
|
||||
h) phelp; exit 0;;
|
||||
*) echo "$Usage" 1>&2; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
for file; do
|
||||
filename=${file##*/}
|
||||
case "$file" in
|
||||
*/*) dirname=${file%/*} ;;
|
||||
*) dirname=. ;;
|
||||
esac
|
||||
nf=$(echo $filename | tr A-Z a-z)
|
||||
newname="${dirname}/${nf}"
|
||||
if [ "$nf" != "$filename" ]; then
|
||||
mv "$file" "$newname"
|
||||
echo "$0: $file -> $newname"
|
||||
else
|
||||
echo "$0: $file not changed."
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,187 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# @(#) ncp.ksh,nmv.ksh 1.1 94/07/23
|
||||
# 92/01/18 john h. dubois iii (john@armory.com)
|
||||
# 92/01/31 added check for no args left after shifts
|
||||
# 92/02/17 added help
|
||||
# 92/02/25 remove path component from filename before tacking it onto dest.
|
||||
# 92/03/15 exec mv or cp
|
||||
# 93/07/13 Added -i
|
||||
# 93/09/29 Made abort if file exists optional.
|
||||
# 93/11/19 Exit before invoking mv if no files to move
|
||||
# 94/01/03 Added o option
|
||||
# 94/04/13 Added x option.
|
||||
# Fixed appending of source filename, broken by earlier change.
|
||||
# 94/07/23 Append only the filename part of the source path.
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
false()
|
||||
{
|
||||
return 1
|
||||
}
|
||||
|
||||
true()
|
||||
{
|
||||
return 0
|
||||
}
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo "$name: do a $cmd with extra checking and options.
|
||||
$Usage
|
||||
$name is used as a front end for $cmd to get the [icfo] options, and so
|
||||
that a trailing / will force the last component of the path to be
|
||||
interpreted as a directory, so that $name foo bar/ will fail if bar is
|
||||
not an existing directory, instead of changing the name of foo to bar.
|
||||
Effectively, $name foo bar/ is short for $name foo bar/foo
|
||||
Options:
|
||||
-h prints this help.
|
||||
-c checks first for the existence of each file, and fails if it exists.
|
||||
-i is like -c except that if the file exists and stdin and stdout are a
|
||||
tty, a query is printed and a reply is read; a file is overwritten only
|
||||
if the reply begins with 'y'.
|
||||
-f unsets -c and -i (in case $cmd is aliased to $name).
|
||||
-o (overwrite only) checks that the named file(s) exist and fails for any
|
||||
that do not. It is the complement of the -c option.
|
||||
Whichever of [cifo] comes later on the command line determines the behaviour.
|
||||
Any of these options must come before any standard $cmd options."
|
||||
}
|
||||
|
||||
# interactive: Attempt to overwrite file should result in interactive
|
||||
# query rather than automatic failure.
|
||||
# noover: Do not overwrite files (if interactive is true, query, else fail)
|
||||
# overwrite: Only overwriting is allowed, not creation of new files.
|
||||
# debug: Print debugging info.
|
||||
typeset interactive=false noover=false overwrite=false debug=false
|
||||
name=${0##*/}
|
||||
|
||||
case "$name" in
|
||||
ncp|nmv) cmd=/bin/${name#?} ;;
|
||||
*) echo "$name: Must be invoked as ncp or nmv." 1>&2 ; exit 2;;
|
||||
esac
|
||||
|
||||
Usage="Usage: $name [-cfhio] $cmd-cmd-line"
|
||||
|
||||
while getopts :cfhiox opt; do
|
||||
case $opt in
|
||||
h) phelp; exit 0;;
|
||||
x) debug=true ;;
|
||||
c) noover=true ;;
|
||||
i) noover=true ; interactive=true ;;
|
||||
f) noover=false ; interactive=false ;;
|
||||
o) overwrite=true ; noover=false ; interactive=false;;
|
||||
+?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
|
||||
?) echo "$name: $OPTARG: bad option. Use -h for help." 1>&2 ; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
# remove args that were options
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo -e "$Usage\nUse -h for help."
|
||||
exit
|
||||
fi
|
||||
|
||||
Check()
|
||||
{
|
||||
if [ ! -f "$1" ] && $overwrite; then
|
||||
echo "$name: $1: File does not exist." 1>&2
|
||||
return 1
|
||||
elif [ -f "$1" ] && $noover; then
|
||||
if [ $interactive = false ] || [ ! -t 0 ] || [ ! -t 1 ]; then
|
||||
echo "$name: $1: File exists." 1>&2
|
||||
return 1
|
||||
else
|
||||
while :; do
|
||||
echo -n \
|
||||
"$name: $1: File exists. Overwrite? (y)es/(n)o/(a)bort/(Y)es for all: " 1>&2
|
||||
read reply
|
||||
case "$reply" in
|
||||
y*)
|
||||
echo "$name: Overwriting $1."
|
||||
return 0
|
||||
;;
|
||||
Y*)
|
||||
echo "$name: Overwriting $1."
|
||||
interactive=false
|
||||
noover=false
|
||||
return 0
|
||||
;;
|
||||
[nN]*)
|
||||
echo "$name: Skipping $2."
|
||||
return 1
|
||||
;;
|
||||
[aA]*)
|
||||
echo "$name: Aborting."
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "$name: Invalid response." 1>&2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# i is the index of the filename being examined
|
||||
# lastarg is the index of the last filename before the dest directory name
|
||||
typeset -i i=0 lastarg=$(($#-1))
|
||||
|
||||
# Sets argv[0..$#-1]
|
||||
argv=("$@")
|
||||
$debug && echo argv = "${argv[@]}" 1>&2
|
||||
dest=${argv[lastarg]}
|
||||
|
||||
if $debug; then
|
||||
echo \
|
||||
"interactive=$interactive noover=$noover overwrite=$overwrite debug=$debug
|
||||
lastarg=$lastarg dest=$dest name=$name cmd=$cmd
|
||||
files=$*" 1>&2
|
||||
fi
|
||||
|
||||
if $noover || $overwrite; then
|
||||
$debug && echo "checking for existance of directories..." 1>&2
|
||||
# If the destination is not intended to be a directory...
|
||||
if [ $# -eq 2 ] && [ ! -d "$dest" ]; then
|
||||
Check "$dest" "$1" || exit 0 # No files to copy
|
||||
else
|
||||
while [ $i -lt $lastarg ]; do
|
||||
Check "$dest/${argv[i]##*/}" "${argv[i]}" || unset argv[i]
|
||||
let i+=1
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
[ ${#argv[@]} -lt 2 ] && exit 0
|
||||
|
||||
# If only 2 args are given, mv/cp will not insist that the destination
|
||||
# be a directory, which we want if the destination ends in "/" or if
|
||||
# the original number of args was >2.
|
||||
# $# is still the original number of args.
|
||||
# Tack the file name onto the destination to force this behaviour.
|
||||
|
||||
lastisslash()
|
||||
{
|
||||
case "$1" in
|
||||
*/) return 0;;
|
||||
*) return 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
if [ ${#argv[@]} = 2 ] && { lastisslash "$2" || [ $# -gt 2 ]; }; then
|
||||
$debug && echo "Appending filename." 1>&2
|
||||
# Don't know which element of argv[] holds the source filename,
|
||||
# since may have started with more than 1 source file & had some unset.
|
||||
# So, compact args to make it easy to find the set one.
|
||||
argv=("${argv[@]}")
|
||||
argv[1]="${argv[1]}/${argv[0]##*/}"
|
||||
fi
|
||||
|
||||
$debug && echo "Executing command: $cmd ${argv[@]}" 1>&2
|
||||
exec $cmd "${argv[@]}"
|
||||
@@ -0,0 +1,64 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# newext: change filename extension
|
||||
# @(#) newext.sh 1.1 93/04/13
|
||||
# 90/06/06 john h. dubois iii (john@armory.com)
|
||||
# 90/11/14 changed ksh-specific code to hybrid: if running under Bourne,
|
||||
# uses expr instead of ksh builtin ops. Removed SYSV specific code.
|
||||
# 91/08/06 added -t option
|
||||
# 92/11/06 made earlier code actually work!
|
||||
# 93/04/13 If no filenames given, act on files in current dir
|
||||
#
|
||||
# conversion to bash v2 syntax by Chet Ramey
|
||||
|
||||
usage="Usage: newext [-th] <oldext> <newext> [filename ...]"
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo "$usage
|
||||
Rename all given files that end in oldext with newext replacing oldext.
|
||||
If no filenames are given, all files in the current directory that end
|
||||
in oldext are acted on (no filename is equivalent to '*').
|
||||
Options:
|
||||
-h: Print this help.
|
||||
-t: Test: No action is taken except to print the mv commands that would
|
||||
be executed if -t was not given."
|
||||
}
|
||||
|
||||
while getopts "th" opt; do
|
||||
case "$opt" in
|
||||
t) echo=echo;;
|
||||
h) phelp; exit 0;;
|
||||
*) echo "$usage" 1>&2; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
oldext=$1
|
||||
newext=$2
|
||||
|
||||
case $# in
|
||||
[01]) echo -e "$usage\nUse -h for help." 1>&2; exit 2;;
|
||||
2) shift ; shift; set -- *;;
|
||||
*) shift ; shift;;
|
||||
esac
|
||||
|
||||
found=
|
||||
|
||||
for file
|
||||
do
|
||||
case "$file" in
|
||||
*$oldext)
|
||||
newname="${file%$oldext}$newext"
|
||||
$echo mv "$file" "$newname"
|
||||
found=true;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$found" ]; then
|
||||
echo "No files ending in \"$oldext\"."
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
@@ -0,0 +1,187 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# @(#) ncp.ksh,nmv.ksh 1.1 94/07/23
|
||||
# 92/01/18 john h. dubois iii (john@armory.com)
|
||||
# 92/01/31 added check for no args left after shifts
|
||||
# 92/02/17 added help
|
||||
# 92/02/25 remove path component from filename before tacking it onto dest.
|
||||
# 92/03/15 exec mv or cp
|
||||
# 93/07/13 Added -i
|
||||
# 93/09/29 Made abort if file exists optional.
|
||||
# 93/11/19 Exit before invoking mv if no files to move
|
||||
# 94/01/03 Added o option
|
||||
# 94/04/13 Added x option.
|
||||
# Fixed appending of source filename, broken by earlier change.
|
||||
# 94/07/23 Append only the filename part of the source path.
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
false()
|
||||
{
|
||||
return 1
|
||||
}
|
||||
|
||||
true()
|
||||
{
|
||||
return 0
|
||||
}
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo "$name: do a $cmd with extra checking and options.
|
||||
$Usage
|
||||
$name is used as a front end for $cmd to get the [icfo] options, and so
|
||||
that a trailing / will force the last component of the path to be
|
||||
interpreted as a directory, so that $name foo bar/ will fail if bar is
|
||||
not an existing directory, instead of changing the name of foo to bar.
|
||||
Effectively, $name foo bar/ is short for $name foo bar/foo
|
||||
Options:
|
||||
-h prints this help.
|
||||
-c checks first for the existence of each file, and fails if it exists.
|
||||
-i is like -c except that if the file exists and stdin and stdout are a
|
||||
tty, a query is printed and a reply is read; a file is overwritten only
|
||||
if the reply begins with 'y'.
|
||||
-f unsets -c and -i (in case $cmd is aliased to $name).
|
||||
-o (overwrite only) checks that the named file(s) exist and fails for any
|
||||
that do not. It is the complement of the -c option.
|
||||
Whichever of [cifo] comes later on the command line determines the behaviour.
|
||||
Any of these options must come before any standard $cmd options."
|
||||
}
|
||||
|
||||
# interactive: Attempt to overwrite file should result in interactive
|
||||
# query rather than automatic failure.
|
||||
# noover: Do not overwrite files (if interactive is true, query, else fail)
|
||||
# overwrite: Only overwriting is allowed, not creation of new files.
|
||||
# debug: Print debugging info.
|
||||
typeset interactive=false noover=false overwrite=false debug=false
|
||||
name=${0##*/}
|
||||
|
||||
case "$name" in
|
||||
ncp|nmv) cmd=/bin/${name#?} ;;
|
||||
*) echo "$name: Must be invoked as ncp or nmv." 1>&2 ; exit 2;;
|
||||
esac
|
||||
|
||||
Usage="Usage: $name [-cfhio] $cmd-cmd-line"
|
||||
|
||||
while getopts :cfhiox opt; do
|
||||
case $opt in
|
||||
h) phelp; exit 0;;
|
||||
x) debug=true ;;
|
||||
c) noover=true ;;
|
||||
i) noover=true ; interactive=true ;;
|
||||
f) noover=false ; interactive=false ;;
|
||||
o) overwrite=true ; noover=false ; interactive=false;;
|
||||
+?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
|
||||
?) echo "$name: $OPTARG: bad option. Use -h for help." 1>&2 ; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
# remove args that were options
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo -e "$Usage\nUse -h for help."
|
||||
exit
|
||||
fi
|
||||
|
||||
Check()
|
||||
{
|
||||
if [ ! -f "$1" ] && $overwrite; then
|
||||
echo "$name: $1: File does not exist." 1>&2
|
||||
return 1
|
||||
elif [ -f "$1" ] && $noover; then
|
||||
if [ $interactive = false ] || [ ! -t 0 ] || [ ! -t 1 ]; then
|
||||
echo "$name: $1: File exists." 1>&2
|
||||
return 1
|
||||
else
|
||||
while :; do
|
||||
echo -n \
|
||||
"$name: $1: File exists. Overwrite? (y)es/(n)o/(a)bort/(Y)es for all: " 1>&2
|
||||
read reply
|
||||
case "$reply" in
|
||||
y*)
|
||||
echo "$name: Overwriting $1."
|
||||
return 0
|
||||
;;
|
||||
Y*)
|
||||
echo "$name: Overwriting $1."
|
||||
interactive=false
|
||||
noover=false
|
||||
return 0
|
||||
;;
|
||||
[nN]*)
|
||||
echo "$name: Skipping $2."
|
||||
return 1
|
||||
;;
|
||||
[aA]*)
|
||||
echo "$name: Aborting."
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "$name: Invalid response." 1>&2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# i is the index of the filename being examined
|
||||
# lastarg is the index of the last filename before the dest directory name
|
||||
typeset -i i=0 lastarg=$(($#-1))
|
||||
|
||||
# Sets argv[0..$#-1]
|
||||
argv=("$@")
|
||||
$debug && echo argv = "${argv[@]}" 1>&2
|
||||
dest=${argv[lastarg]}
|
||||
|
||||
if $debug; then
|
||||
echo \
|
||||
"interactive=$interactive noover=$noover overwrite=$overwrite debug=$debug
|
||||
lastarg=$lastarg dest=$dest name=$name cmd=$cmd
|
||||
files=$*" 1>&2
|
||||
fi
|
||||
|
||||
if $noover || $overwrite; then
|
||||
$debug && echo "checking for existance of directories..." 1>&2
|
||||
# If the destination is not intended to be a directory...
|
||||
if [ $# -eq 2 ] && [ ! -d "$dest" ]; then
|
||||
Check "$dest" "$1" || exit 0 # No files to copy
|
||||
else
|
||||
while [ $i -lt $lastarg ]; do
|
||||
Check "$dest/${argv[i]##*/}" "${argv[i]}" || unset argv[i]
|
||||
let i+=1
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
[ ${#argv[@]} -lt 2 ] && exit 0
|
||||
|
||||
# If only 2 args are given, mv/cp will not insist that the destination
|
||||
# be a directory, which we want if the destination ends in "/" or if
|
||||
# the original number of args was >2.
|
||||
# $# is still the original number of args.
|
||||
# Tack the file name onto the destination to force this behaviour.
|
||||
|
||||
lastisslash()
|
||||
{
|
||||
case "$1" in
|
||||
*/) return 0;;
|
||||
*) return 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
if [ ${#argv[@]} = 2 ] && { lastisslash "$2" || [ $# -gt 2 ]; }; then
|
||||
$debug && echo "Appending filename." 1>&2
|
||||
# Don't know which element of argv[] holds the source filename,
|
||||
# since may have started with more than 1 source file & had some unset.
|
||||
# So, compact args to make it easy to find the set one.
|
||||
argv=("${argv[@]}")
|
||||
argv[1]="${argv[1]}/${argv[0]##*/}"
|
||||
fi
|
||||
|
||||
$debug && echo "Executing command: $cmd ${argv[@]}" 1>&2
|
||||
exec $cmd "${argv[@]}"
|
||||
@@ -0,0 +1,187 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# @(#) pages.sh 1.0 92/09/26
|
||||
# 92/09/05 John H. DuBois III (jhdiii@armory.com)
|
||||
# 92/09/26 Added help
|
||||
#
|
||||
# conversion to bash v2 syntax by Chet Ramey
|
||||
|
||||
Usage="$0 [-h] [-n lines/page] page-ranges [file ...]"
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "$Usage" 1>&2
|
||||
}
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo "$0: print selected pages.
|
||||
Usage: $Usage
|
||||
|
||||
If no file names are given, the standard input is read.
|
||||
|
||||
The input is grouped into pages and a selected subset of them is printed.
|
||||
Formfeeds are acted on correctly.
|
||||
|
||||
If the output device does automatic line wrap, lines that longer than
|
||||
the width of the output device will result in incorrect output.
|
||||
The first non-option argument is a list of pages to print.
|
||||
|
||||
Pages are given as a list of ranges separated by commas.
|
||||
A range is either one number, two numbers separted by a dash,
|
||||
or one number followed by a dash. A range consisting of one
|
||||
number followed by a dash extends to the end of the document.
|
||||
|
||||
Options:
|
||||
-n sets the number of lines per page to n. The default is 66."
|
||||
}
|
||||
|
||||
while getopts "n:h" opt; do
|
||||
case "$opt" in
|
||||
n) LinesPerPage=$OPTARG;;
|
||||
h) phelp; exit 0;;
|
||||
*) usage; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $(($OPTIND - 1))
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo $0: no page ranges given. 1>&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PageList=$1
|
||||
shift
|
||||
|
||||
gawk "
|
||||
BEGIN {
|
||||
PageList = \"$PageList\"; LinesPerPage = \"$LinesPerPage\""'
|
||||
if (LinesPerPage == "")
|
||||
LinesPerPage = 66
|
||||
else
|
||||
if (LinesPerPage !~ "[1-9][0-9]*")
|
||||
ErrExit("Bad value for lines per page: " LinesPerPage)
|
||||
LinesPerPage += 0
|
||||
NumRanges = split(PageList,Ranges,",")
|
||||
for (i = 1; i <= NumRanges; i++) {
|
||||
if ((StartRange = EndRange = Ranges[i]) !~ "^[0-9]+(-([0-9]+)?)?$")
|
||||
ErrExit("Bad range \"" StartRange "\"")
|
||||
sub("-.*","",StartRange)
|
||||
sub(".*-","",EndRange)
|
||||
if (EndRange == "")
|
||||
EndRange = 2 ^ 30
|
||||
# Force StartRange and EndRange to be numeric values
|
||||
if ((StartRange += 0) == 0 || (EndRange += 0) == 0)
|
||||
ErrExit("Invalid page number \"0\" in range " Ranges[i])
|
||||
if (StartRange > EndRange)
|
||||
ErrExit("Start page comes after end page in range " Ranges[i])
|
||||
TmpRangeStarts[i] = StartRange
|
||||
TmpRangeEnds[i] = EndRange
|
||||
}
|
||||
|
||||
# Sort ranges
|
||||
qsort(TmpRangeStarts,k)
|
||||
RangeEnds[0] = 0
|
||||
for (i = 1; i <= NumRanges; i++) {
|
||||
RangeEnds[i] = TmpRangeEnds[k[i]]
|
||||
if ((RangeStarts[i] = TmpRangeStarts[k[i]]) <= RangeEnds[i - 1])
|
||||
ErrExit("Overlapping ranges: " Ranges[k[i]] "," Ranges[k[i - 1]])
|
||||
}
|
||||
|
||||
RangeNum = LineNum = PageNum = 1
|
||||
InRange = In(PageNum,RangeStarts[RangeNum],RangeEnds[RangeNum])
|
||||
FS = "\014"
|
||||
}
|
||||
|
||||
{
|
||||
if (LineNum > LinesPerPage)
|
||||
NewPage()
|
||||
if (InRange)
|
||||
printf "%s",$1
|
||||
# Deal with formfeeds
|
||||
for (i = 2; i <= NF; i++) {
|
||||
if (InRange)
|
||||
printf "\014"
|
||||
NewPage()
|
||||
if (InRange)
|
||||
printf "%s",$i
|
||||
}
|
||||
if (InRange)
|
||||
print ""
|
||||
LineNum++
|
||||
}
|
||||
|
||||
function NewPage() {
|
||||
PageNum++
|
||||
LineNum = 1
|
||||
# At the start of each page, check whether we are in a print range
|
||||
WereInRange = InRange
|
||||
InRange = In(PageNum,RangeStarts[RangeNum],RangeEnds[RangeNum])
|
||||
# If last page was in range and we no longer are, move to next range
|
||||
if (WereInRange && !InRange && ++RangeNum > NumRanges)
|
||||
exit
|
||||
}
|
||||
|
||||
function In(a,Min,Max) {
|
||||
return (Min <= a && a <= Max)
|
||||
}
|
||||
|
||||
function ErrExit(S) {
|
||||
print S > "/dev/stderr"
|
||||
Err = 1
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Arr is an array of values with arbitrary indices.
|
||||
# Array k is returned with numeric indices 1..n.
|
||||
# The values in k are the indices of array arr,
|
||||
# ordered so that if array arr is stepped through
|
||||
# in the order arr[k[1]] .. arr[k[n]], it will be stepped
|
||||
# through in order of the values of its elements.
|
||||
# The return value is the number of elements in the array (n).
|
||||
function qsort(arr,k, ArrInd,end) {
|
||||
end = 0
|
||||
for (ArrInd in arr)
|
||||
k[++end] = ArrInd;
|
||||
qsortseg(arr,k,1,end);
|
||||
return end
|
||||
}
|
||||
|
||||
function qsortseg(arr,k,start,end, left,right,sepval,tmp,tmpe,tmps) {
|
||||
# handle two-element case explicitely for a tiny speedup
|
||||
if ((end - start) == 1) {
|
||||
if (arr[tmps = k[start]] > arr[tmpe = k[end]]) {
|
||||
k[start] = tmpe
|
||||
k[end] = tmps
|
||||
}
|
||||
return
|
||||
}
|
||||
left = start;
|
||||
right = end;
|
||||
sepval = arr[k[int((left + right) / 2)]]
|
||||
# Make every element <= sepval be to the left of every element > sepval
|
||||
while (left < right) {
|
||||
while (arr[k[left]] < sepval)
|
||||
left++
|
||||
while (arr[k[right]] > sepval)
|
||||
right--
|
||||
if (left < right) {
|
||||
tmp = k[left]
|
||||
k[left++] = k[right]
|
||||
k[right--] = tmp
|
||||
}
|
||||
}
|
||||
if (left == right)
|
||||
if (arr[k[left]] < sepval)
|
||||
left++
|
||||
else
|
||||
right--
|
||||
if (start < right)
|
||||
qsortseg(arr,k,start,right)
|
||||
if (left < end)
|
||||
qsortseg(arr,k,left,end)
|
||||
}
|
||||
' "$@"
|
||||
@@ -0,0 +1,127 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
#
|
||||
# @(#) p.ksh 1.1 93/11/09
|
||||
# p: page compressed & plain files in the order given
|
||||
# 92/01/23 john h. dubois iii (john@armory.com)
|
||||
# 92/02/14 changed incorrect zpack to pcat
|
||||
# 92/02/16 added help
|
||||
# 92/10/11 search for file.Z and file.z if file not found
|
||||
# 92/10/18 pass options to pager
|
||||
# 93/11/09 Understand gzipped files too
|
||||
# Wait after printing message about unreadable files
|
||||
# Make less prompt include name of file being uncompressed
|
||||
#
|
||||
# conversion to bash v2 by Chet Ramey; renamed to pf
|
||||
#
|
||||
DefPager=/local/bin/less
|
||||
|
||||
istrue()
|
||||
{
|
||||
test 0 -ne "$1"
|
||||
}
|
||||
|
||||
warn()
|
||||
{
|
||||
echo "$@" 1>&2
|
||||
}
|
||||
|
||||
if [ "$1" = -h ]; then
|
||||
echo \
|
||||
"$0: page a file.
|
||||
Usage: $0 [pager-option ...] [filename ...]
|
||||
Files are paged by the program specified in the user's PAGER
|
||||
environment variable, or by $DefPager if PAGER is not set.
|
||||
If no filename is given, text to page is read from the standard input.
|
||||
If filenames are given, they are either paged directly, or unpacked/
|
||||
uncompressed and then paged. Files are assumed to be in packed, compressed,
|
||||
or gzipped format if the filename ends in .Z, .z, or .gz respectively.
|
||||
If a filename that does not end in .Z, .z, or .gz is not found, it is
|
||||
searched for with one of those extensions attached.
|
||||
Each group of plain files is paged by a single instance of the pager.
|
||||
Each packed or compressed file is paged by a separate instance of the
|
||||
pager.
|
||||
Initial arguments beginning with + or - are taken to be pager options and
|
||||
are passed to each instance of the pager.
|
||||
If a pager option takes a value it should be given with the option as a
|
||||
single argument (with no space between the option and the value)."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get pager options
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-*|+*) Opts="$Opts $1" ; shift;;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -z "$PAGER" ] && PAGER=$DefPager
|
||||
|
||||
# Read from stdin
|
||||
[ $# = 0 ] && exec $PAGER $Opts
|
||||
|
||||
typeset -i filenum=0 badfile=0
|
||||
|
||||
for file; do
|
||||
if [ ! -r "$file" ]; then
|
||||
case "$file" in
|
||||
*.[Zz]|*.gz)
|
||||
# Check if user specified a compressed file without giving its extension
|
||||
for ext in Z z gz; do
|
||||
if [ -r "$file.$ext" ]; then
|
||||
file="$file.$ext"
|
||||
break
|
||||
fi
|
||||
done;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -r "$file" ]; then
|
||||
warn "$file: cannot read."
|
||||
badfile=1
|
||||
else
|
||||
files[filenum]=$file
|
||||
let filenum+=1
|
||||
fi
|
||||
done
|
||||
|
||||
if istrue $badfile && [ $filenum -gt 0 ]; then
|
||||
echo -n "Press return to continue..." 1>&2
|
||||
read
|
||||
fi
|
||||
|
||||
unset plain
|
||||
|
||||
for file in "${files[@]}"; do
|
||||
case "$file" in
|
||||
*.[zZ]|*.gz)
|
||||
set -- Z zcat z pcat gz gzcat
|
||||
# Find correct uncompression program
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$file" in
|
||||
*.$1)
|
||||
# Page any uncompressed files so that they will be read
|
||||
# in the correct order
|
||||
[ ${#plain[@]} -gt 0 ] && $PAGER $Opts "${plain[@]}"
|
||||
unset plain[*]
|
||||
# If page is less, set the prompt to include the name of
|
||||
# the file being uncompressed. Escape the . in the extension
|
||||
# because less treats is specially in prompts (other dots
|
||||
# in filenames will still be mucked with).
|
||||
case "$PAGER" in
|
||||
*less) Prompt="-P[${file%.$1}\\.$1] (%pb\\%)" ;;
|
||||
*) unset Prompt ;;
|
||||
esac
|
||||
$2 "$file" | $PAGER "$Prompt" $Opts
|
||||
break
|
||||
esac
|
||||
shift 2
|
||||
done
|
||||
;;
|
||||
*) plain[${#plain[@]}]=$file;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Page any uncompressed files that haven't been paged yet
|
||||
[ ${#plain[@]} -gt 0 ] && exec $PAGER $Opts "${plain[@]}"
|
||||
@@ -0,0 +1,25 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# pmtop - poor man's `top' for SunOS 4.x
|
||||
#
|
||||
|
||||
CLEAR=clear # could also be 'tput clear'
|
||||
HEADER="USER PID %CPU %MEM SZ RSS TT STAT START TIME COMMAND"
|
||||
|
||||
if [ -n "$LINES" ]; then
|
||||
SS=$(( $LINES - 2 ))
|
||||
else
|
||||
SS=20
|
||||
fi
|
||||
|
||||
while :
|
||||
do
|
||||
$CLEAR
|
||||
echo "$HEADER"
|
||||
ps -aux | sort -nr +2 | sed ${SS}q
|
||||
sleep 5
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# @(#) rename.ksh 1.1 94/05/10
|
||||
# 90/06/01 John DuBois (spcecdt@armory.com)
|
||||
# 91/02/25 Improved help info
|
||||
# 92/06/07 remove quotes from around shell pattern as required by new ksh
|
||||
# 94/05/10 Exit if no globbing chars given.
|
||||
#
|
||||
# conversion to bash v2 syntax by Chet Ramey
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo "$usage
|
||||
All files that match oldpattern will be renamed with the
|
||||
filename components that match the constant parts of oldpattern
|
||||
changed to the corresponding constant parts of newpattern.
|
||||
The components of the filename that match variable parts of
|
||||
oldpattern will be preserved. Variable parts in oldpattern
|
||||
must occur in the same order in newpattern. Variables parts
|
||||
can be '?' and '*'.
|
||||
Example:
|
||||
rename \"/tmp/foo*.ba.?\" \"/tmp/new*x?\"
|
||||
All files in /tmp that match foo*.ba.? will have the \"foo\" part
|
||||
replaced by \"new\" and the \".ba.\" part replaced by \"x\"."
|
||||
}
|
||||
|
||||
usage="usage: $name [-htv] oldpattern newpattern"
|
||||
name=${0##/}
|
||||
|
||||
while getopts "htv" opt; do
|
||||
case "$opt" in
|
||||
t) tell=true;;
|
||||
v) verbose=true;;
|
||||
h) phelp; exit 0;;
|
||||
*) echo "$name: $usage" 1>&2; exit 2;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
phelp
|
||||
exit 2
|
||||
fi
|
||||
|
||||
oldpat=$1
|
||||
newpat=$2
|
||||
|
||||
set $1
|
||||
if [ ! -a "$1" ]; then
|
||||
echo "$name: no files match $oldpat."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
typeset -i i=1 j
|
||||
|
||||
# Example oldpat: foo*.a
|
||||
# Example newpat: bar*.b
|
||||
|
||||
# Examples given for first iteration (in the example, the only interation)
|
||||
while :; do
|
||||
case "$oldpat" in
|
||||
*[\*\?]*) ;;
|
||||
*) break;;
|
||||
esac
|
||||
|
||||
# Get leftmost globbing pattern in oldpat
|
||||
pat=${oldpat#*[\*\?]} # pat=.a
|
||||
pat=${oldpat%%"$pat"} # pat=foo*
|
||||
pat=${pat##*[!\?\*]} # pat=*
|
||||
# Find parts before & after pattern
|
||||
oldpre[i]=${oldpat%%"$pat"*} # oldpre[1]=foo
|
||||
oldsuf[i]=${oldpat#*"$pat"} # oldsuf[1]=.a
|
||||
newpre[i]=${newpat%%"$pat"*} # newpre[1]=bar
|
||||
# Get rid of processed part of patterns
|
||||
oldpat=${oldpat#${oldpre[i]}"$pat"} # oldpat=.a
|
||||
newpat=${newpat#${newpre[i]}"$pat"} # newpat=.b
|
||||
let i=i+1
|
||||
done
|
||||
|
||||
if [ $i -eq 1 ]; then
|
||||
print -u2 "No globbing chars in pattern."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
oldpre[i]=${oldpat%%"$pat"*} # oldpre[2]=.a
|
||||
oldsuf[i]=${oldpat#*"$pat"} # oldsuf[2]=.a
|
||||
newpre[i]=${newpat%%"$pat"*} # newpre[2]=.b
|
||||
|
||||
if [ -n "$verbose" ]; then
|
||||
j=1
|
||||
while let "j < i"; do
|
||||
echo \
|
||||
"Old prefix: ${oldpre[j]} Old suffix: ${oldsuf[j]} New prefix: ${newpre[j]}"
|
||||
let j=j+1
|
||||
done
|
||||
fi
|
||||
|
||||
# Example file: foox.a
|
||||
|
||||
for file; do
|
||||
j=1
|
||||
origname=$file # origname=foox.a
|
||||
newfile=
|
||||
while let "j <= i"; do
|
||||
# Peel off a prefix interation 1 2
|
||||
file=${file#${oldpre[j]}} # file=x.a file=
|
||||
# Save the part of this prefix that is to be retained
|
||||
const=${file%${oldsuf[j]}} # const=x const=
|
||||
newfile=$newfile${newpre[j]}$const # newfile=barx newfile=barx.b
|
||||
file=${file#$const} # file=.a file=.a
|
||||
let j=j+1
|
||||
done
|
||||
if [ -n "$tell" ]; then
|
||||
echo "Would move \"$origname\" to \"$newfile\"."
|
||||
else
|
||||
if [ -n "$verbose" ]; then
|
||||
echo "Moving \"$origname\" to \"$newfile\"."
|
||||
fi
|
||||
mv $origname $newfile
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,119 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# repeat: repeat a command.
|
||||
# @(#) repeat.ksh 1.1 93/06/03
|
||||
# 90/05 john h. dubois iii (john@armory.com)
|
||||
# 90/11 added help
|
||||
# 93/06/03 Added s, h, p, and v options
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
istrue()
|
||||
{
|
||||
test 0 -ne "$1"
|
||||
}
|
||||
|
||||
isfalse()
|
||||
{
|
||||
test 0 -eq "$1"
|
||||
}
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo "$name: repeatedly execute a command line.
|
||||
$Usage
|
||||
commandline is executed once for each integer from startcount through endcount
|
||||
inclusive. The default for startcount is 1 if a positive endcount or no
|
||||
endcount is given, and -1 if a negative endcount is given. A count
|
||||
parameter consisting of a single number is taken to be an endcount. If
|
||||
only an endcount is given and it is positive, commandline is executed
|
||||
endcount times. endcount may be less than startcount. If no endcount is
|
||||
given (e.g. a count parameter of \"10-\"), commandline execution repeats
|
||||
indefinitely with the iteration variable incrementing in a positive
|
||||
direction. A count parameter of consisting of \"-\" will repeat
|
||||
indefinitely starting with 1.
|
||||
|
||||
Note that quoting and variables in commandline are interpreted twice, once
|
||||
when it is passed to the repeat command, and once when it is actually executed.
|
||||
|
||||
The iteration variable is \"count\". If \$count is used in commandline, make
|
||||
sure it is quoted with ' or \.
|
||||
|
||||
Options:
|
||||
-h: Print this help.
|
||||
-p: Print value of iteration variable on stderr before each iteration.
|
||||
-s <sec>: sleep for <sec> seconds after each iteration except the last.
|
||||
-v: Print start and end values before beginning."
|
||||
}
|
||||
|
||||
name=${0##*/}
|
||||
Usage="Usage: repeat [-hpv] [-s <sec>] [[startcount]-][endcount] command [arg ...]"
|
||||
|
||||
typeset -i count=1 forever=0 sleep=0 print=0 verbose=0
|
||||
|
||||
while getopts :0123456789hpvs: opt; do
|
||||
case $opt in
|
||||
h) phelp; exit 0;;
|
||||
s) sleep=$OPTARG || exit 1;;
|
||||
p) print=1;;
|
||||
v)verbose=1;;
|
||||
[0-9]) break;;
|
||||
+?) echo "$name: options should not be preceded by a '+'." 1>&2; exit 2;;
|
||||
?) echo "$name: $OPTARG: bad option. Use -h for help." 1>&2; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
# remove args that were options
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo -e "$Usage\nUse -h for help." 1>&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
-[0-9]*-|[0-9]*-)
|
||||
# Start value only
|
||||
count=${1%-}
|
||||
forever=1
|
||||
;;
|
||||
-[0-9]*-[0-9]*|[0-9]*-[0-9]*)
|
||||
# Start and end value
|
||||
s=${1%-}
|
||||
end=${s##[0-9]*-}
|
||||
count=${s%-$end}
|
||||
;;
|
||||
-[0-9]*|[0-9]*)
|
||||
end=$1
|
||||
case "$end" in
|
||||
-\*) count=-1;;
|
||||
esac
|
||||
;;
|
||||
-)
|
||||
forever=1
|
||||
;;
|
||||
*)
|
||||
echo "$name: bad count parameter: $1" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
|
||||
[ -z "$end" -o $count -le "$end" ] && increment=1 || increment=-1
|
||||
|
||||
istrue $verbose && echo "start=$count end=$end" 1>&2
|
||||
|
||||
# Need to do this here so that up to this point, -0 will keep the leading -
|
||||
# and end will not be 0 if no value assigned
|
||||
typeset -i end
|
||||
|
||||
let end+=increment # make loop inclusive of original endcount
|
||||
|
||||
while istrue $forever || [ $count -ne $end ]; do
|
||||
istrue $print && echo $count 1>&2
|
||||
eval "$@"
|
||||
istrue $sleep && sleep $sleep
|
||||
let count+=increment
|
||||
done
|
||||
@@ -0,0 +1,66 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# shprof - a line profiler for shell scripts
|
||||
#
|
||||
# adapted from a similar program included in `The New KornShell' by
|
||||
# Bolsky and Korn and posted to usenet by bsh20858@challenger.fhda.edu
|
||||
#
|
||||
# converted to bash v2 syntax by Chet Ramey
|
||||
#
|
||||
TMPFILE=${TMP:-/tmp}/shprof$$
|
||||
|
||||
trap 'rm -f $TMPFILE' EXIT
|
||||
|
||||
errexit()
|
||||
{
|
||||
echo $0: "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# create script with profiling enabled
|
||||
cat > $TMPFILE <<- \_EOF_
|
||||
declare -a _line
|
||||
_profend()
|
||||
{
|
||||
case "$1" in
|
||||
/*|./*) file="$1" ;;
|
||||
*) file=$(type -path "$1") ;;
|
||||
esac
|
||||
|
||||
echo "*** line profile for $file ***"
|
||||
i=1;
|
||||
while read -r && [ $i -le $NLINE ]; do
|
||||
count=${_line[$i]}
|
||||
if [ "$count" -gt 0 ]; then
|
||||
echo "[$count] $i: $REPLY"
|
||||
fi
|
||||
i=$((i + 1))
|
||||
done <$file
|
||||
_EOF_
|
||||
# make the profiling script remove itself after printing line stats
|
||||
echo "rm -f $TMPFILE" >> $TMPFILE
|
||||
cat >> $TMPFILE <<- \_EOF_
|
||||
}
|
||||
_command=$1
|
||||
shift
|
||||
i=1
|
||||
NLINE=$(wc -l < "$_command")
|
||||
while [ $i -le $NLINE ]; do
|
||||
_line[$i]=0
|
||||
i=$((i + 1))
|
||||
done
|
||||
unset i
|
||||
trap "_profend ${_command}" EXIT
|
||||
trap '_line[$LINENO]=$((${_line[$LINENO]} + 1))' DEBUG
|
||||
LINENO=0
|
||||
_EOF_
|
||||
|
||||
case "$1" in
|
||||
/*|./*) file=$1 ;;
|
||||
*) file=$((type -path "$1")) ;;
|
||||
esac
|
||||
|
||||
cat "${file-$1}" >> $TMPFILE || errexit "${1}: cannot open"
|
||||
chmod +x $TMPFILE
|
||||
|
||||
exec -a "$file" $TMPFILE "$@"
|
||||
@@ -0,0 +1,80 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# @(#) untar.ksh 1.0 93/11/10
|
||||
# 92/10/08 john h. dubois iii (john@armory.com)
|
||||
# 92/10/31 make it actually work if archive isn't in current dir!
|
||||
# 93/11/10 Added pack and gzip archive support
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo \
|
||||
"$name: extract tar archives into directories, uncompressing if neccessary.
|
||||
Usage: $name archive[.tar[.[Z|gz]]] ..
|
||||
If an archive name given does not end in .tar, .tar.Z, or .tar.gz, it is
|
||||
searched for first with .tar added, then .tar.Z, and then .tar.gz added.
|
||||
The real filename must end in either .tar, .tar.Z, or .tar.gz. A
|
||||
directory with the name of the archive is created in the current directory
|
||||
(not necessarily the directory that the archive is in) if it does not
|
||||
exist, and the the contents of the archive are extracted into it.
|
||||
Absolute pathnames in tarfiles are suppressed."
|
||||
}
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
phelp
|
||||
exit 1
|
||||
fi
|
||||
|
||||
name=${0##/}
|
||||
OWD=$PWD
|
||||
|
||||
for file; do
|
||||
cd $OWD
|
||||
case "$file" in
|
||||
*.tar.Z) ArchiveName=${file%%.tar.Z} zcat=zcat;;
|
||||
*.tar.z) ArchiveName=${file%%.tar.z} zcat=pcat;;
|
||||
*.tar.gz) ArchiveName=${file%%.tar.gz} zcat=gzcat;;
|
||||
*) ArchiveName=$file
|
||||
for ext in "" .Z .z .gz; do
|
||||
if [ -f "$file.tar$ext" ]; then
|
||||
file="$file.tar$ext"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "$file: cannot find archive." 1>&2
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if [ ! -r "$file" ]; then
|
||||
echo "$file: cannot read." >&2
|
||||
continue
|
||||
fi
|
||||
DirName=${ArchiveName##*/}
|
||||
[ -d "$DirName" ] || {
|
||||
mkdir "$DirName" || {
|
||||
echo "$DirName: could not make archive directory." 1>&2
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
cd $DirName || {
|
||||
echo "$name: cannot cd to $DirName" 1>&2
|
||||
continue
|
||||
}
|
||||
|
||||
case "$file" in
|
||||
/*) ;;
|
||||
*) file=$OWD/$file ;;
|
||||
esac
|
||||
|
||||
echo "Extracting archive $file into directory $DirName..."
|
||||
case "$file" in
|
||||
*.tar.Z|*.tar.z|*.tar.gz) $zcat $file | tar xvf -;;
|
||||
*.tar) tar xvf $file;;
|
||||
esac
|
||||
echo "Done extracting archive $file into directory $DirName."
|
||||
done
|
||||
@@ -0,0 +1,45 @@
|
||||
:
|
||||
# @(#) uudec.sh 1.0 93/11/22
|
||||
# 92/08/04 john@armory.com (John H. DuBois III)
|
||||
# 93/11/22 Added help.
|
||||
|
||||
isfalse()
|
||||
{
|
||||
test 0 -eq "$1"
|
||||
}
|
||||
|
||||
phelp()
|
||||
{
|
||||
"$name: process uuencoded files.
|
||||
Usage: uudec [-h] filename ...
|
||||
Options:
|
||||
-h: Print this help."
|
||||
}
|
||||
|
||||
name=${0##*/}
|
||||
|
||||
typeset -i force=0
|
||||
|
||||
while getopts "hf" opt; do
|
||||
case "$opt" in
|
||||
h) phelp; exit 0;;
|
||||
f) force=1;;
|
||||
*) echo "$Usage" 1>&2; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
for file; do
|
||||
echo "$file"
|
||||
while read b mode filename && [ "$b" != begin ]; do :; done < "$file"
|
||||
if [ "$b" = begin ]; then
|
||||
if [ -f "$filename" ] && isfalse $force; then
|
||||
echo "Output file \"$filename\" exists. Not written."
|
||||
else
|
||||
uudecode "$file"
|
||||
fi
|
||||
else
|
||||
echo "No begin line."
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,69 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# @(#) uuenc.ksh 1.0 93/09/18
|
||||
# 93/09/18 john h. dubois iii (john@armory.com)
|
||||
#
|
||||
# conversion to bash v2 syntax by Chet Ramey
|
||||
|
||||
istrue()
|
||||
{
|
||||
test 0 -ne "$1"
|
||||
}
|
||||
|
||||
isfalse()
|
||||
{
|
||||
test 0 -eq "$1"
|
||||
}
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo "$name: uuencode files.
|
||||
$Usage
|
||||
For each filename given, $name uuencodes the file, using the final
|
||||
component of the file's path as the stored filename in the uuencoded
|
||||
archive and, with a .${SUF} appended, as the name to store the archive in.
|
||||
Example:
|
||||
$name /tmp/foo
|
||||
The file /tmp/foo is uuencoded, with \"foo\" stored as the name to uudecode
|
||||
the file into, and the output is stored in a file in the current directory
|
||||
with the name \"foo.${SUF}\".
|
||||
Options:
|
||||
-f: Normally, if the file the output would be stored in already exists,
|
||||
it is not overwritten and an error message is printed. If -f (force)
|
||||
is given, it is silently overwritten.
|
||||
-h: Print this help."
|
||||
}
|
||||
|
||||
name=${0##*/}
|
||||
Usage="Usage: $name [-hf] <filename> ..."
|
||||
typeset -i force=0
|
||||
|
||||
SUF=uu
|
||||
|
||||
while getopts :hf opt; do
|
||||
case $opt in
|
||||
h) phelp; exit 0;;
|
||||
f) force=1;;
|
||||
+?) echo "$name: options should not be preceded by a '+'." 1>&2 ; exit 2;;
|
||||
?) echo "$name: $OPTARG: bad option. Use -h for help." 1>&2 ; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
# remove args that were options
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "$Usage\nUse -h for help." 1>&2
|
||||
exit
|
||||
fi
|
||||
|
||||
for file; do
|
||||
tail=${file##*/}
|
||||
out="$tail.${SUF}"
|
||||
if isfalse $force && [ -a "$out" ]; then
|
||||
echo "$name: $out: file exists. Use -f to overwrite." 1>&2
|
||||
else
|
||||
uuencode $file $tail > $out
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,137 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# vtree: visual directory tree
|
||||
# @(#) vtree.sh 1.1 91/07/01
|
||||
# 90/04 john h. dubois iii (john@armory.com)
|
||||
# 91/07/01 fixed bug that caused problems when dir given on command line,
|
||||
# added some info to help, changed to 4-space indenting
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
#
|
||||
help=\
|
||||
"Syntax: vtree [startdir] [namelen=#] [linelen=#]
|
||||
If startdir is not specified, tree will start at current dir.
|
||||
|
||||
namelen specifies the minimum number of characters of a directory name that
|
||||
are guaranteed to be printed.
|
||||
This is a tradeoff between the number of tree levels that can fit on a
|
||||
screen line and the number of chars of each dir name that can be printed.
|
||||
In most cases it will be possible to print more than namelen characters of
|
||||
the name (a name up to namelen+1 chars will always be printed in full),
|
||||
but in some cases truncation down to namelen chars will occur.
|
||||
If truncation occurs, a '>' is printed at the end of the name.
|
||||
namelen=8 (the default) typically causes about 5 dirs/1000 to be truncated.
|
||||
namelen=7 typically causes about 10 dirs/1000 to be truncated.
|
||||
namelen=8 will allow 6 full length dirs to be printed in 79 columns.
|
||||
namelen=7 will allow 7 full length dirs to be printed in 79 columns;
|
||||
|
||||
linelen specifies the maximum number of characters to print on one screen
|
||||
line. All characters beyond this are truncated. The default is 1024.
|
||||
To avoid line wrap on an 80 column terminal with autowrap, use linelen=79.
|
||||
"
|
||||
|
||||
for i in "$@"; do
|
||||
case $i in
|
||||
-h) echo "$help"; exit;;
|
||||
*=*)
|
||||
vars="$vars $i"
|
||||
;;
|
||||
*)
|
||||
if [ ! -x $i -o ! -d $i ]; then # arg must be a dir and executable
|
||||
echo "$i: directory not accessible."
|
||||
exit
|
||||
fi
|
||||
cd $i
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
pwd # print path of root of tree
|
||||
|
||||
# find all directories depth first; ignore permission errors
|
||||
find . -type d -print 2> /dev/null | \
|
||||
gawk -F/ '
|
||||
|
||||
# Do this block for NR == 1 instead of BEGIN because command line var
|
||||
# assignments are not done until after BEGIN block is executed.
|
||||
NR == 1 {
|
||||
if (namelen)
|
||||
MaxLen = namelen;
|
||||
else
|
||||
MaxLen = 8;
|
||||
if (!linelen)
|
||||
linelen = 1024
|
||||
HSpace = substr(" ",1,MaxLen); # used to indent tree
|
||||
n = 0; # number of dirs found on one major branch
|
||||
}
|
||||
|
||||
$0 != "." { # do for every line produced by find except tree root dir
|
||||
if (NF == 2 && n > 0) # print major branch whenever a new one starts
|
||||
list();
|
||||
Depth[n] = NF - 1; # record depth and name of dir
|
||||
Name[n++] = $NF;
|
||||
}
|
||||
|
||||
END {
|
||||
list() # print last major branch
|
||||
}
|
||||
|
||||
function list() {
|
||||
Line = Name[0]; # initialize first line of branch to be branch base
|
||||
for (i = 1; i < n; i++) { # for each name in major branch
|
||||
if (Depth[i] == Depth[i-1] + 1)
|
||||
AddHLink(); # if moving deeper into branch, use same line
|
||||
else {
|
||||
print substr(Line,1,linelen); # last line is done; print it
|
||||
Line = ""; # start new line
|
||||
# print indentation, vert links, and vert/horiz links
|
||||
for (d = 1; d < Depth[i] - 1; d++) # for each level of indentation
|
||||
# if a vert. link has been established for this level
|
||||
if (VLink[d])
|
||||
Line = Line HSpace " | ";
|
||||
else # print empty indentation
|
||||
Line = Line HSpace " ";
|
||||
# Print last part of vert. link
|
||||
if (VLink[d] == i) {
|
||||
VLink[d] = 0; # mark level for no vert link
|
||||
Line = Line HSpace " \\--";
|
||||
}
|
||||
else
|
||||
Line = Line HSpace " |--";
|
||||
}
|
||||
Line = Line Name[i]; # Add dir name to line
|
||||
}
|
||||
print substr(Line,1,linelen); # print last line of major branch
|
||||
n = 0; # reset name counter
|
||||
}
|
||||
|
||||
function AddHLink() {
|
||||
NDepth = Depth[i]; # Depth of this name
|
||||
VLink[NDepth - 1] = 0;
|
||||
# search until a name found at a level less than this one
|
||||
for (j = i + 1; j < n && Depth[j] >= NDepth; j++)
|
||||
# keep track of last name that VLink should connect to
|
||||
if (Depth[j] == NDepth)
|
||||
VLink[NDepth - 1] = j;
|
||||
if (VLink[NDepth - 1]) {
|
||||
NLine = substr(Line,1,(NDepth - 2) * (MaxLen + 4) + MaxLen + 1);
|
||||
if (length(NLine) < length(Line))
|
||||
Line = substr(NLine,1,length(NLine) - 1) ">"
|
||||
else
|
||||
Line = NLine;
|
||||
Line = Line substr("--------------+--",
|
||||
18 - ((NDepth - 1) * (MaxLen + 4) - length(Line)));
|
||||
}
|
||||
else {
|
||||
NLine = substr(Line,1,(NDepth - 2) * (MaxLen + 4) + MaxLen + 3);
|
||||
if (length(NLine) < length(Line))
|
||||
Line = substr(NLine,1,length(NLine) - 1) ">"
|
||||
else
|
||||
Line = NLine;
|
||||
Line = Line substr("-----------------",
|
||||
1,(NDepth - 1) * (MaxLen + 4) - length(Line));
|
||||
}
|
||||
}
|
||||
' $vars
|
||||
@@ -0,0 +1,111 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# original from:
|
||||
# @(#) where.ksh 1.1 94/07/11
|
||||
# 91/01/12 john h. dubois iii (john@armory.com)
|
||||
# 92/08/10 Only print executable *files*.
|
||||
# 92/10/06 Print err msg if no match found.
|
||||
# 92/11/27 Added implicit *
|
||||
# 93/07/23 Print help only if -h is given.
|
||||
# 94/01/01 Added -x option
|
||||
# 94/07/11 Don't bother with eval
|
||||
#
|
||||
# conversion to bash v2 syntax done by Chet Ramey
|
||||
|
||||
name=${0##*/}
|
||||
Usage="Usage: $name [-hx] 'pattern' ..."
|
||||
typeset -i exact=0
|
||||
|
||||
phelp()
|
||||
{
|
||||
echo "$name: find executable files in PATH that match patterns.
|
||||
$Usage
|
||||
$name searches each directory specified in the PATH environment variable
|
||||
for executable files that match the specified patterns. Patterns are
|
||||
given as Korn shell filename patterns. They are surrounded by implicit
|
||||
'*' characters, so that \"foo\" will match any executble file whose name
|
||||
contains contains \"foo\". This can be overridden by using '^' and '$' to
|
||||
force a match to start at the beginning and end at the end of a filename
|
||||
respectively. Characters that are special to the shell must generally
|
||||
be protected from the shell by surrounding them with quotes.
|
||||
Examples:
|
||||
$name foo
|
||||
lists all executable files in PATH that contain foo.
|
||||
$name '^b*sh$'
|
||||
lists all executable files in PATH that start with b and end with sh.
|
||||
An error message is printed if a no matching file is found for a pattern.
|
||||
Options:
|
||||
-h: Print this help.
|
||||
-x: Find exact matches only; equivalent to putting ^ and $ at the start
|
||||
and end of each pattern."
|
||||
}
|
||||
|
||||
istrue()
|
||||
{
|
||||
test 0 -ne "$1"
|
||||
}
|
||||
|
||||
isfalse()
|
||||
{
|
||||
test 0 -eq "$1"
|
||||
}
|
||||
|
||||
while getopts "xh" opt; do
|
||||
case "$opt" in
|
||||
x) exact=1;;
|
||||
h) phelp ; exit 0;;
|
||||
*) echo -e "$Usage\nUse -h for help." 1>&2; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1))
|
||||
|
||||
set +f # make sure filename globbing is on
|
||||
Args=("$@") # save args
|
||||
|
||||
OIFS=$IFS
|
||||
IFS=: # Make PATH be split on :
|
||||
Paths=($PATH)
|
||||
IFS=$OIFS
|
||||
|
||||
for arg in "${Args[@]}"; do
|
||||
|
||||
# get rid of leading ^
|
||||
if istrue $exact; then
|
||||
arg=${arg}
|
||||
else
|
||||
case "$arg" in
|
||||
^*) arg=${arg#?};;
|
||||
*) arg="*$arg" ;; # Pattern is not anchored at start
|
||||
esac
|
||||
fi
|
||||
|
||||
# get rid of trailing $
|
||||
if istrue $exact; then
|
||||
arg="$arg"
|
||||
else
|
||||
case "$arg" in
|
||||
*\$) arg=${arg%?} ;;
|
||||
*) arg="$arg*" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
found=0 # Pattern not found yet
|
||||
Patterns=
|
||||
# Make a pattern for each element of PATH
|
||||
for PathElem in "${Paths[@]}"; do
|
||||
[ -z "$PathElem" ] && PathElem=.
|
||||
Patterns="$Patterns $PathElem/$arg"
|
||||
done
|
||||
|
||||
# Find all pattern matches that are executable regular files.
|
||||
for file in $Patterns; do
|
||||
if [ -x "$file" ] && [ -f "$file" ]; then
|
||||
echo "$file"
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
if [ $found = 0 ]; then
|
||||
echo "$arg: not found." 1>&2
|
||||
fi
|
||||
done
|
||||
Regular → Executable
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Search $PATH for a file the same name as $1; return TRUE if found.
|
||||
#
|
||||
|
||||
command=$1
|
||||
[ -n "$command" ] || exit 1
|
||||
|
||||
set `echo $PATH | sed 's/^:/.:/
|
||||
s/::/:.:/g
|
||||
s/:$/:./
|
||||
s/:/ /g'`
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
[ -f $1/$command ] && exit 0 # test -x not universal
|
||||
shift
|
||||
done
|
||||
|
||||
exit 1
|
||||
@@ -0,0 +1,51 @@
|
||||
#
|
||||
# BASH VERSION OF nohup COMMAND
|
||||
#
|
||||
ctype()
|
||||
{
|
||||
path=$(builtin type -p $cmd | sed 1q)
|
||||
if [ -n "$path" ]; then
|
||||
echo "$path"
|
||||
return 0
|
||||
else
|
||||
case "$cmd" in
|
||||
*/*) [ -x "$cmd ] && { echo "$cmd" ; return 0; } ;;
|
||||
*) case "$(builtin type -t $cmd)" in
|
||||
"") return 1;;
|
||||
*) echo "$cmd" ; return 0;;
|
||||
esac ;;
|
||||
esac
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
trap '' HUP # ignore hangup
|
||||
command=$(ctype "$1")
|
||||
oldmask=$(umask)
|
||||
umask u=rw,og= # default mode for nohup.out
|
||||
exec 0< /dev/null # disconnect input
|
||||
if [ -t 1 ]; then # redirect output if necessary
|
||||
if [ -w . ]; then
|
||||
echo 'Sending output to nohup.out'
|
||||
exec >> nohup.out
|
||||
else echo "Sending output to $HOME/nohup.out"
|
||||
exec >> $HOME/nohup.out
|
||||
fi
|
||||
fi
|
||||
|
||||
umask "$oldmask"
|
||||
|
||||
# direct unit 2 to a file
|
||||
if [ -t 2 ]; then
|
||||
exec 2>&1
|
||||
fi
|
||||
|
||||
# run the command
|
||||
case $command in
|
||||
*/*) exec "$@"
|
||||
;;
|
||||
time) eval "$@"
|
||||
;;
|
||||
*) "$@"
|
||||
;;
|
||||
esac
|
||||
Regular → Executable
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# scrollbar - display scrolling text
|
||||
#
|
||||
# usage: scrollbar args
|
||||
#
|
||||
# A cute hack originally from Heiner Steven <hs@bintec.de>
|
||||
#
|
||||
# converted from ksh syntax to bash v2 syntax by Chet Ramey
|
||||
|
||||
WIDTH=${COLUMNS:-80}
|
||||
|
||||
[ $# -lt 1 ] && set -- TESTING
|
||||
|
||||
# Posix.2 compatible printf command or bash loadable builtin
|
||||
# in examples/loadables/printf
|
||||
Text=$(printf "%-${WIDTH}s" "$*")
|
||||
Text=$(echo "$Text" | tr ' ' '_')
|
||||
|
||||
while :
|
||||
do
|
||||
printf "%-.${WIDTH}s\r" "$Text"
|
||||
LastC=$(expr "$Text" : '.*\(.\)$')
|
||||
Text=$(printf "%-.${WIDTH}s" "$LastC$Text")
|
||||
done
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# vtree - make a tree printout of the specified directory, with disk usage
|
||||
# in 1k blocks
|
||||
#
|
||||
# usage: vtree [-a] [dir]
|
||||
#
|
||||
# Original posted to Usenet sometime in February, 1996
|
||||
#
|
||||
usage()
|
||||
{
|
||||
echo "vtree: usage: vtree [-a] [dir]" >&2
|
||||
}
|
||||
|
||||
while getopts a opt
|
||||
do
|
||||
case "$opt" in
|
||||
a) andfiles=-a ;;
|
||||
*) usage ; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
export BLOCKSIZE=1k # 4.4 BSD systems need this
|
||||
|
||||
[ $# -eq 0 ] && set .
|
||||
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
cd "$1" || { shift; [ $# -ge 1 ] && echo >&2; continue; }
|
||||
echo -n "$PWD"
|
||||
|
||||
du $andfiles | sort +1f | sed \
|
||||
's/\([^ ]*\) \(.*\)/\2 (\1)/
|
||||
'"s#^$1##"'
|
||||
s#[^/]*/\([^/]*\)$#|____\1#
|
||||
s#[^/]*/#| #g'
|
||||
|
||||
[ $# -gt 1 ] && echo
|
||||
shift
|
||||
done
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# zprintf - function that calls gawk to do printf for those systems that
|
||||
# don't have a printf executable
|
||||
#
|
||||
# The format and arguments can have trailing commas, just like gawk
|
||||
#
|
||||
# example:
|
||||
# zprintf 'Eat %x %x and suck %x!\n' 57005 48879 64206
|
||||
#
|
||||
# Chet Ramey
|
||||
# chet@po.cwru.edu
|
||||
|
||||
[ $# -lt 1 ] && {
|
||||
echo "zprintf: usage: zprintf format [args ...]" >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
fmt="${1%,}"
|
||||
shift
|
||||
|
||||
for a in "$@"; do
|
||||
args="$args,\"${a%,}\""
|
||||
done
|
||||
|
||||
gawk "BEGIN { printf \"$fmt\" $args }"
|
||||
@@ -13,7 +13,6 @@ alias j="jobs -l"
|
||||
alias l="ls -l "
|
||||
alias ll="ls -l"
|
||||
alias ls="ls -F"
|
||||
alias term='set noglob; eval `tset -Q -s `'
|
||||
alias pu="pushd"
|
||||
alias po="popd"
|
||||
|
||||
@@ -53,11 +52,12 @@ seq ()
|
||||
{
|
||||
local lower upper output;
|
||||
lower=$1 upper=$2;
|
||||
|
||||
if [ $lower -ge $upper ]; then return; fi
|
||||
while [ $lower -le $upper ];
|
||||
do
|
||||
output="$output $lower";
|
||||
lower=$[ $lower + 1 ];
|
||||
done;
|
||||
echo $output
|
||||
echo -n "$lower "
|
||||
lower=$(($lower + 1))
|
||||
done
|
||||
echo "$lower"
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
#
|
||||
default_dir=/usr/local/lib/
|
||||
|
||||
if [ "$PS1" ]; then
|
||||
PS1='\u@\h(\#)$ '
|
||||
ignoreeof=3
|
||||
if [ -n "$PS1" ]; then
|
||||
PS1='\u@\h(\#)\$ '
|
||||
IGNOREEOF=3
|
||||
fi
|
||||
|
||||
LOGIN_SHELL=true
|
||||
@@ -12,9 +12,7 @@ LOGIN_SHELL=true
|
||||
# If the user has her own init file, then use that one, else use the
|
||||
# canonical one.
|
||||
if [ -f ~/.bashrc ]; then
|
||||
source ~/.bashrc
|
||||
else if [ -f ${default_dir}Bashrc ]; then
|
||||
source ${default_dir}Bashrc;
|
||||
fi
|
||||
. ~/.bashrc
|
||||
elif [ -f ${default_dir}Bashrc ]; then
|
||||
. ${default_dir}Bashrc;
|
||||
fi
|
||||
|
||||
|
||||
@@ -16,57 +16,55 @@ X11=/usr/bin/X11
|
||||
|
||||
UTIL_PATH=$GNU:$X11
|
||||
STANDARD_PATH=/usr/local/bin:/usr/ucb:/bin:/usr/bin:/usr/etc:/etc:/usr/games
|
||||
if [ "$HOSTTYPE" = "sony" ]; then STANDARD_PATH=STANDARD_PATH:/usr/sony/bin; fi
|
||||
|
||||
if [ -d $HOME/bin/$HOSTTYPE ]; then
|
||||
MY_PATH=$HOME/bin/$HOSTTYPE
|
||||
MY_PATH=$HOME/bin/$HOSTTYPE
|
||||
fi
|
||||
|
||||
if [ -d $HOME/bin ]; then
|
||||
MY_PATH=$MY_PATH:$HOME/bin
|
||||
MY_PATH=$MY_PATH:$HOME/bin
|
||||
fi
|
||||
|
||||
if [ -d /usr/hosts ]; then
|
||||
STANDARD_PATH=$STANDARD_PATH:/usr/hosts
|
||||
STANDARD_PATH=$STANDARD_PATH:/usr/hosts
|
||||
fi
|
||||
|
||||
PATH=.:$MY_PATH:$UTIL_PATH:$STANDARD_PATH
|
||||
|
||||
# If running interactively, then:
|
||||
if [ "$PS1" ]; then
|
||||
|
||||
# Set ignoreeof if you don't want EOF as the sole input to the shell to
|
||||
# immediately signal a quit condition. This only happens at the start
|
||||
# of a line if the line is empty, and you haven't just deleted a character
|
||||
# with C-d. I turn this on in ~/.bash_profile so that only login shells
|
||||
# have the right to be obnoxious.
|
||||
# ignoreeof=
|
||||
|
||||
# Set auto_resume if you want to resume on "emacs", as well as on
|
||||
# "%emacs".
|
||||
auto_resume=
|
||||
|
||||
# Set notify if you want to be asynchronously notified about background
|
||||
# job completion.
|
||||
notify=
|
||||
|
||||
# Make it so that failed `exec' commands don't flush this shell.
|
||||
no_exit_on_failed_exec=
|
||||
|
||||
if [ ! "$LOGIN_SHELL" ]; then
|
||||
PS1="\u@\h\$ "
|
||||
fi
|
||||
|
||||
HISTSIZE=256
|
||||
MAILCHECK=60
|
||||
|
||||
# A couple of default aliases.
|
||||
alias j='jobs -l'
|
||||
alias po=popd
|
||||
alias pu=pushd
|
||||
alias ls='ls -F'
|
||||
|
||||
if [ -f ~/.bash_aliases ]; then
|
||||
source ~/.bash_aliases
|
||||
fi
|
||||
# If not running interactively, then return
|
||||
if [ -z "$PS1" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Set ignoreeof if you don't want EOF as the sole input to the shell to
|
||||
# immediately signal a quit condition. This only happens at the start
|
||||
# of a line if the line is empty, and you haven't just deleted a character
|
||||
# with C-d. I turn this on in ~/.bash_profile so that only login shells
|
||||
# have the right to be obnoxious.
|
||||
# set -o ignoreeof
|
||||
|
||||
# Set auto_resume if you want to resume on "emacs", as well as on
|
||||
# "%emacs".
|
||||
auto_resume=exact
|
||||
|
||||
# Set notify if you want to be asynchronously notified about background
|
||||
# job completion.
|
||||
set -o notify
|
||||
|
||||
# Make it so that failed `exec' commands don't flush this shell.
|
||||
shopt -s execfail
|
||||
|
||||
if [ -z "$LOGIN_SHELL" ]; then
|
||||
PS1="\u@\h\$ "
|
||||
fi
|
||||
|
||||
HISTSIZE=256
|
||||
MAILCHECK=60
|
||||
|
||||
# A couple of default aliases.
|
||||
alias j='jobs -l'
|
||||
alias po=popd
|
||||
alias pu=pushd
|
||||
alias ls='ls -F'
|
||||
|
||||
[ -f ~/.bash_aliases ] && . ~/.bash_aliases
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
Some sample startup files. The ones starting with capital letters
|
||||
are originally from Brian Fox. The ones starting with lowercase
|
||||
letters are from Chet Ramey.
|
||||
|
||||
They will require changes for your environment.
|
||||
@@ -1,52 +1,37 @@
|
||||
HOME=/usr/homes/chet
|
||||
MAIL=/usr/homes/chet/mbox
|
||||
# This is the filename where your incoming mail arrives.
|
||||
MAIL=~/mbox
|
||||
MAILCHECK=30
|
||||
HISTFILE=/usr/homes/chet/.history
|
||||
|
||||
MACHINE=$(/usr/local/bin/machine)
|
||||
HOST=$(hostname)
|
||||
HISTFILE=~/.history/history.$HOSTNAME
|
||||
|
||||
PATH1=/usr/homes/chet/bin.$MACHINE:/usr/local/bin/gnu:
|
||||
PATH1=/usr/homes/chet/bin.$HOSTTYPE:/usr/local/bin/gnu:
|
||||
PATH2=/usr/local/bin:/usr/ucb:/bin:/usr/bin/X11:.
|
||||
PATH3=/usr/andrew/bin:/usr/bin:/usr/ibm:/usr/local/bin/mh:/usr/new/bin:
|
||||
PATH3=/usr/bin:/usr/new/bin:/usr/contrib/bin
|
||||
PATH=$PATH1:$PATH2:$PATH3
|
||||
|
||||
EDITOR=/usr/homes/chet/bin.$MACHINE/ce
|
||||
VISUAL=/usr/homes/chet/bin.$MACHINE/ce
|
||||
FCEDIT=/usr/homes/chet/bin.$MACHINE/ce
|
||||
EDITOR=/usr/local/bin/ce VISUAL=/usr/local/bin/ce FCEDIT=/usr/local/bin/ce
|
||||
|
||||
if [ "$BASH" ] ; then
|
||||
SHELL=$BASH
|
||||
else
|
||||
SHELL=/bin/bash
|
||||
fi
|
||||
|
||||
if [ "$MACHINE" = "ibm032" ] ; then
|
||||
stty erase ^H
|
||||
fi
|
||||
|
||||
PAGER=/usr/ucb/more
|
||||
NNTPSERVER=kiwi
|
||||
NS=/nfs/cwjcc/fs1/ns-engr/proj/netsrv/cwpub/proto/src
|
||||
SHELL=${SHELL:-${BASH:-/bin/bash}}
|
||||
|
||||
PAGER=/usr/local/bin/less
|
||||
LESS='-i -e -M -P%t?f%f :stdin .?pb%pb\%:?lbLine %lb:?bbByte %bb:-...'
|
||||
#
|
||||
# Bogus 1003.2 variables. This should really be in /etc/profile
|
||||
#
|
||||
LOGNAME=${USER-$(whoami)}
|
||||
TZ=EST5EDT
|
||||
TZ=US/Eastern
|
||||
|
||||
export HOME ENV VISUAL EDITOR MAIL SHELL PATH TERM
|
||||
export PAGER LESS TERMCAP HISTSZIE HISTFILE
|
||||
export MAIL MAILCHECK HOST HOSTNAME NNTPSERVER NS LOGNAME TZ
|
||||
export HOME VISUAL EDITOR MAIL SHELL PATH TERM
|
||||
export PAGER LESS TERMCAP HISTSIZE HISTFILE MAIL MAILCHECK LOGNAME TZ
|
||||
|
||||
PS1="${HOST}$ "
|
||||
PS1="${HOSTNAME}\$ "
|
||||
PS2='> '
|
||||
export PS1 PS2
|
||||
|
||||
umask 022
|
||||
|
||||
if [ -f /unix ] ; then
|
||||
stty intr ^c
|
||||
stty intr ^c # bogus
|
||||
fi
|
||||
|
||||
if [ -f ~/.bashrc ] ; then
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
if [ "$PS1" != "" ] ; then
|
||||
|
||||
if [ -f /unix ] ; then
|
||||
alias ls='/bin/ls -CF'
|
||||
alias ll='/bin/ls -lCF'
|
||||
alias dir='/bin/ls -bCalF'
|
||||
else
|
||||
alias ls='/bin/ls -F'
|
||||
alias ll='/bin/ls -lF'
|
||||
alias dir='/bin/ls -balF'
|
||||
if [ -z "$PS1" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# bogus
|
||||
if [ -f /unix ] ; then
|
||||
alias ls='/bin/ls -CF'
|
||||
else
|
||||
alias ls='/bin/ls -F'
|
||||
fi
|
||||
alias ll='ls -l'
|
||||
alias dir='ls -ba'
|
||||
|
||||
alias ss="ps -aux"
|
||||
alias mail=/usr/ucb/mail
|
||||
alias dot='ls .[a-zA-Z0-9]*'
|
||||
alias mroe=more
|
||||
alias pwd='echo $PWD'
|
||||
alias pdw='echo $PWD'
|
||||
alias news="xterm -g 80x45 -e rn -e &"
|
||||
alias back='cd $OLDPWD'
|
||||
alias manroff="nroff /usr/lib/tmac/tmac.an.4.3"
|
||||
alias laser="lpr -Palw2"
|
||||
alias lw="lpr -Palw2"
|
||||
alias dot='ls .[a-zA-Z0-9_]*'
|
||||
alias news="xterm -g 80x45 -e trn -e -S1 -N &"
|
||||
|
||||
alias c="clear"
|
||||
alias m="more"
|
||||
alias j="jobs"
|
||||
|
||||
# common misspellings
|
||||
alias mroe=more
|
||||
alias pdw=pwd
|
||||
|
||||
hash -p /usr/bin/mail mail
|
||||
|
||||
if [ -z "$HOST" ] ; then
|
||||
export HOST=`hostname`
|
||||
export HOST=${HOSTNAME}
|
||||
fi
|
||||
|
||||
history_control=ignoredups
|
||||
HISTIGNORE="[ ]*:&:bg:fg"
|
||||
|
||||
psgrep()
|
||||
{
|
||||
@@ -57,10 +57,14 @@ term()
|
||||
tset
|
||||
}
|
||||
|
||||
xtitle ()
|
||||
{
|
||||
echo -n -e "\033]0;$*\007"
|
||||
}
|
||||
|
||||
cd()
|
||||
{
|
||||
builtin cd $*
|
||||
xtitle $HOST: $PWD
|
||||
builtin cd "$@" && xtitle $HOST: $PWD
|
||||
}
|
||||
|
||||
bold()
|
||||
@@ -126,14 +130,3 @@ function chmog()
|
||||
chgrp $3 $4
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Source kshenv for ksh-compatibility definitions
|
||||
#
|
||||
|
||||
if [ -f ~/.kshenv ] ; then
|
||||
. ~/.kshenv
|
||||
fi
|
||||
|
||||
fi
|
||||
#end of .bashrc
|
||||
|
||||
Reference in New Issue
Block a user