#!/bin/sh ## ## GNU shtool -- The GNU Portable Shell Tool ## Copyright (c) 1994-1999 Ralf S. Engelschall ## ## See http://www.gnu.org/software/shtool/ for more information. ## See ftp://ftp.gnu.org/gnu/shtool/ for latest version. ## ## Version 1.4.5 (28-Jul-1999) ## Ingredients: 3/17 available modules ## ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ## USA, or contact Ralf S. Engelschall . ## ## Notice: Given that you include this file verbatim into your own ## source tree, you are justified in saying that it remains separate ## from your package, and that this way you are simply just using GNU ## shtool. So, in this situation, there is no requirement that your ## package itself is licensed under the GNU General Public License in ## order to take advantage of GNU shtool. ## ## ## Usage: shtool [] [ [] []] ## ## Available commands: ## install Install a program, script or datafile ## mkdir Make one or more directories ## mkshadow Make a shadow tree ## ## Not available commands (because module was not built-in): ## echo Print string with optional construct expansion ## mdate Pretty-print modification time of a file or dir ## table Pretty print a field-separated list as a table ## prop Display progress with a running propeller ## move Move files with simultan substitution ## mkln Make link with calculation of relative paths ## fixperm Fix file permissions inside a source tree ## tarball Roll distribution tarballs ## guessos Simple OS/platform guesser ## arx Extended archive command ## slo Separate linker options by library class ## scpp Sharing C Pre-Processor ## version Generate and maintain a version information file ## path Deal with program paths ## if [ $# -eq 0 ]; then echo "$0:Error: invalid command line" 1>&2 echo "$0:Hint: run \`$0 -h' for usage" 1>&2 exit 1 fi if [ ".$1" = ".-h" -o ".$1" = ".--help" ]; then echo "This is GNU shtool, version 1.4.5 (28-Jul-1999)" echo "Copyright (c) 1994-1999 Ralf S. Engelschall " echo "Report bugs to " echo '' echo "Usage: shtool [] [ [] []]" echo '' echo 'Available global :' echo ' -v, --version display shtool version information' echo ' -h, --help display shtool usage help page (this one)' echo ' -d, --debug display shell trace information' echo '' echo 'Available [] []:' echo ' install [-v] [-t] [-c] [-C] [-s] [-m] [-o] [-g]' echo ' [-e] ' echo ' mkdir [-t] [-f] [-p] [-m] [ ...]' echo ' mkshadow [-v] [-t] [-a] ' echo '' echo 'Not available (because module was not built-in):' echo ' echo [-n] [-e] [ ...]' echo ' mdate [-n] [-z] [-s] [-d] [-f] [-o] ' echo ' table [-F] [-w] [-c] [-s] ...' echo ' prop [-p]' echo ' move [-v] [-t] [-e] [-p] ' echo ' mkln [-t] [-f] [-s] [ ...] ' echo ' fixperm [-v] [-t] [ ...]' echo ' tarball [-t] [-v] [-o ] [-c ] [-d ] [-u' echo ' ] [-g ] [-e ] [ ...]' echo ' guessos ' echo ' arx [-t] [-C] [ ...]' echo ' slo -- -L -l [ -L -l ... ]' echo ' scpp [-v] [-p] [-o] [-t] [-M] [-D]' echo ' [-C] [ ...]' echo ' version [-l] [-n] [-p] [-s] [-i]' echo ' [-d] ' echo ' path [-s] [-r] [-d] [-b] [-m] [-p] [ ...]' echo '' exit 0 fi if [ ".$1" = ".-v" -o ".$1" = ."--version" ]; then echo "GNU shtool 1.4.5 (28-Jul-1999)" exit 0 fi if [ ".$1" = ".-d" -o ".$1" = ."--debug" ]; then shift set -x fi name=`echo "$0" | sed -e 's;.*/\([^/]*\)$;\1;' -e 's;-sh$;;' -e 's;\.sh$;;'` case "$name" in install|mkdir|mkshadow ) # implicit tool command selection tool="$name" ;; * ) # explicit tool command selection tool="$1" shift ;; esac arg_spec="" opt_spec="" gen_tmpfile=no ## ## DISPATCH INTO SCRIPT PROLOG ## case $tool in install ) str_tool="install" str_usage="[-v] [-t] [-c] [-C] [-s] [-m] [-o] [-g] [-e] " arg_spec="2" opt_spec="vtcCsm:o:g:e:" ;; mkdir ) str_tool="mkdir" str_usage="[-t] [-f] [-p] [-m] [ ...]" arg_spec="1+" opt_spec="tfpm:" ;; mkshadow ) str_tool="mkshadow" str_usage="[-v] [-t] [-a] " arg_spec="2" opt_spec="vta" ;; * ) echo "$0:Error: unknown command \`$tool'" 2>&1 echo "$0:Hint: run \`$0 -h' for usage" 2>&1 exit 1 ;; esac ## ## COMMON UTILITY CODE ## # determine name of tool if [ ".$tool" != . ]; then # inside shtool toolcmd="$0 $tool" toolcmdhelp="shtool $tool" msgprefix="shtool:$tool" else # standalone toolcmd="$0" toolcmdhelp="sh.$tool" msgprefix="$str_tool" fi # parse argument specification string eval `echo $arg_spec | sed -e 's/^\([0-9]*\)\(.*\)/arg_NUMS="\1"; arg_MODE="\2"/'` test ".$arg_MODE" = . && arg_MODE="=" # parse option specification string for opt in `echo "h$opt_spec" | sed -e 's/\([a-zA-Z0-9][!:+]*\)/\1 /g'`; do opt_MODE="."; opt_INIT="." eval `echo $opt |\ sed -e 's/^\([a-zA-Z0-9]\)/opt_THIS="\1";/' \ -e 's/";\([:+]\)/"; opt_MODE="\1";/' \ -e 's/";\(!\)/"; opt_INIT="\1"/'` eval "opt_MODE_${opt_THIS}=${opt_MODE}" if [ ".$opt_INIT" != ".!" ]; then case "$opt_MODE" in "." ) eval "opt_${opt_THIS}=no" ;; ":"|"+" ) eval "opt_${opt_THIS}=\"\"" ;; esac fi done # interate over argument line opt_PREV='' while [ $# -gt 0 ]; do # special option stops processing if [ ".$1" = ".--" ]; then shift break fi # determine option and argument opt_ARG_OK=no if [ ".$opt_PREV" != . ]; then # merge previous seen option with argument opt_OPT="$opt_PREV" opt_ARG="$1" opt_ARG_OK=yes opt_PREV="" else # split argument into option and argument case "$1" in -[a-zA-Z0-9]*) eval `echo "x$1" |\ sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \ -e 's/";\(.*\)$/"; opt_ARG="\1"/'` ;; -[a-zA-Z0-9]) opt_OPT=`awk 'BEGIN { printf("%s", substr(OPT, 2)); }' \ "OPT=$1" &2 echo "$msgprefix:Hint: run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2 exit 1 ;; esac done if [ ".$opt_PREV" != . ]; then echo "$msgprefix:Error: missing argument to option \`-$opt_PREV'" 1>&2 echo "$msgprefix:Hint: run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2 exit 1 fi # process help option if [ .$opt_h = .yes ]; then echo "Usage: $toolcmdhelp $str_usage" exit 0 fi # complain about incorrect number of arguments case $arg_MODE in "=" ) if [ $# -ne $arg_NUMS ]; then echo "$msgprefix:Error: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2 echo "$msgprefix:Hint: run \`$toolcmd -h' or \`man shtool' for details" 1>&2 exit 1 fi ;; "+" ) if [ $# -lt $arg_NUMS ]; then echo "$msgprefix:Error: invalid number of arguments (at least $arg_NUMS expected)" 1>&2 echo "$msgprefix:Hint: run \`$toolcmd -h' or \`man shtool' for details" 1>&2 exit 1 fi ;; esac # establish a temporary file on request if [ ".$gen_tmpfile" = .yes ]; then tmpdir="/tmp" if [ ".$TMPDIR" != . ]; then tmpdir="$TMPDIR" else if [ ".$TEMPDIR" != . ]; then tmpdir="$TEMPDIR" fi fi tmpfile="$tmpdir/.shtool.$$" rm -f $tmpfile >/dev/null 2>&1 touch $tmpfile fi ## ## DISPATCH INTO SCRIPT BODY ## case $tool in install ) ## ## install -- Install a program, script or datafile ## Copyright (c) 1997-1999 Ralf S. Engelschall ## Originally written for shtool ## src="$1" dst="$2" # If destination is a directory, append the input filename if [ -d $dst ]; then dst=`echo "$dst" | sed -e 's:/$::'` dstfile=`echo "$src" | sed -e 's;.*/\([^/]*\)$;\1;'` dst="$dst/$dstfile" fi # Add a possible extension to src and dst if [ ".$opt_e" != . ]; then src="$src$opt_e" dst="$dst$opt_e" fi # Check for correct arguments if [ ".$src" = ".$dst" ]; then echo "$msgprefix:Error: source and destination are the same" 1>&2 exit 1 fi # Make a temp file name in the destination directory dstdir=`echo $dst | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;'` dsttmp="$dstdir/#INST@$$#" # Verbosity if [ ".$opt_v" = .yes ]; then echo "$src -> $dst" 1>&2 fi # Copy or move the file name to the temp name # (because we might be not allowed to change the source) if [ ".$opt_C" = .yes ]; then opt_c=yes fi if [ ".$opt_c" = .yes ]; then if [ ".$opt_t" = .yes ]; then echo "cp $src $dsttmp" 1>&2 fi cp $src $dsttmp || exit $? else if [ ".$opt_t" = .yes ]; then echo "mv $src $dsttmp" 1>&2 fi mv $src $dsttmp || exit $? fi # Adjust the target file # (we do chmod last to preserve setuid bits) if [ ".$opt_s" = .yes ]; then if [ ".$opt_t" = .yes ]; then echo "strip $dsttmp" 1>&2 fi strip $dsttmp || exit $? fi if [ ".$opt_o" != . ]; then if [ ".$opt_t" = .yes ]; then echo "chown $opt_o $dsttmp" 1>&2 fi chown $opt_o $dsttmp || exit $? fi if [ ".$opt_g" != . ]; then if [ ".$opt_t" = .yes ]; then echo "chgrp $opt_g $dsttmp" 1>&2 fi chgrp $opt_g $dsttmp || exit $? fi if [ ".$opt_m" != . ]; then if [ ".$opt_t" = .yes ]; then echo "chmod $opt_m $dsttmp" 1>&2 fi chmod $opt_m $dsttmp || exit $? fi # Determine whether to do a quick install # (has to be done _after_ the strip was already done) quick=no if [ ".$opt_C" = .yes ]; then if [ -r $dst ]; then if cmp -s $src $dst; then quick=yes fi fi fi # Finally install the file to the real destination if [ $quick = yes ]; then if [ ".$opt_t" = .yes ]; then echo "rm -f $dsttmp" 1>&2 fi rm -f $dsttmp else if [ ".$opt_t" = .yes ]; then echo "rm -f $dst && mv $dsttmp $dst" 1>&2 fi rm -f $dst && mv $dsttmp $dst fi ;; mkdir ) ## ## mkdir -- Make one or more directories ## Copyright (c) 1996-1999 Ralf S. Engelschall ## Originally written for public domain by Noah Friedman ## Cleaned up and enhanced for shtool ## errstatus=0 for p in ${1+"$@"}; do # when the directory already exists... if [ -d "$p" ]; then if [ ".$opt_f" = .no ]; then echo "$msgprefix:Error: file exists: $p" 1>&2 errstatus=1 break else continue fi fi # when the directory has to be created if [ ".$opt_p" = .no ]; then if [ ".$opt_t" = .yes ]; then echo "mkdir $p" 1>&2 fi mkdir $p || errstatus=$? else # the smart situation set fnord `echo ":$p" |\ sed -e 's/^:\//%/' \ -e 's/^://' \ -e 's/\// /g' \ -e 's/^%/\//'` shift pathcomp= for d in ${1+"$@"}; do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp="./$pathcomp" ;; esac if [ ! -d "$pathcomp" ]; then if [ ".$opt_t" = .yes ]; then echo "mkdir $pathcomp" 1>&2 fi mkdir $pathcomp || errstatus=$? if [ ".$opt_m" != . ]; then if [ ".$opt_t" = .yes ]; then echo "chmod $opt_m $pathcomp" 1>&2 fi chmod $opt_m $pathcomp || errstatus=$? fi fi pathcomp="$pathcomp/" done fi done exit $errstatus ;; mkshadow ) ## ## mkshadow -- Make a shadow tree ## Copyright (c) 1998-1999 Ralf S. Engelschall ## Originally written for Apache ## # source and destination directory src=`echo "$1" | sed -e 's:/$::'` dst=`echo "$2" | sed -e 's:/$::'` # check whether source exists if [ ! -d $src ]; then echo "$msgprefix:Error: source directory not found: \`$src'" 1>&2 exit 1 fi # determine if one of the paths is an absolute path, # because then we have to use an absolute symlink oneisabs=0 case $src in /* ) oneisabs=1 ;; esac case $dst in /* ) oneisabs=1 ;; esac # determine reverse directory for destination directory dstrevdir='' if [ $oneisabs = 0 ]; then # (inlined fp2rp) OIFS="$IFS"; IFS='/' for pe in $dst; do dstrevdir="../$dstrevdir" done IFS="$OIFS" else src="`cd $src; pwd`"; fi # create directory tree at destination if [ ! -d $dst ]; then if [ ".$opt_t" = .yes ]; then echo "mkdir $dst" 1>&2 fi mkdir $dst fi if [ ".$opt_a" = .yes ]; then DIRS=`cd $src; find . -type d -print |\ sed -e '/^\.$/d' -e 's:^\./::'` else DIRS=`cd $src; find . -type d -print |\ sed -e '/\/CVS/d' -e '/^\.$/d' -e 's:^\./::'` fi for dir in $DIRS; do if [ ".$opt_t" = .yes ]; then echo "mkdir $dst/$dir" 1>&2 fi mkdir $dst/$dir done # fill directory tree with symlinks to files if [ ".$opt_a" = .yes ]; then FILES="`cd $src; find . -depth -print |\ sed -e 's/^\.\///'`" else FILES="`cd $src; find . -depth -print |\ sed -e '/\.o$/d' -e '/\.a$/d' -e '/\.so$/d' \ -e '/\.cvsignore$/d' -e '/\/CVS/d' \ -e '/\/\.#/d' -e '/\.orig$/d' \ -e 's/^\.\///'`" fi for file in $FILES; do # don't use `-type f' above for find because of symlinks if [ -d "$src/$file" ]; then continue fi basename=`echo $file | sed -e 's:^.*/::'` dir=`echo $file | sed -e 's:[^/]*$::' -e 's:/$::' -e 's:$:/:' -e 's:^/$::'` from=`echo "$src/$file" | sed -e 's/^\.\///'` to="$dst/$dir$basename" if [ $oneisabs = 0 ]; then if [ ".$dir" != . ]; then subdir=`echo $dir | sed -e 's:/$::'` # (inlined fp2rp) revdir='' OIFS="$IFS"; IFS='/' for pe in $subdir; do revdir="../$revdir" done IFS="$OIFS" # finalize from from="$revdir$from" fi from="$dstrevdir$from" fi if [ ".$opt_v" = .yes ]; then echo " $to" 1>&2 fi if [ ".$opt_t" = .yes ]; then echo "ln -s $from $to" 1>&2 fi ln -s $from $to done ;; esac exit 0 ##EOF##