: # @(#)shipout (gsf@research.att.com) 07/17/95 # # shipout [ options ... ] [ name ... ] [ tool ... ] # # ship software to recipient using system|user info in $SHIPINFO # # options -- + turns the corresponding option off # # -b ship bases with deltas # -c don't generate tool closure # -d don't ship deltas # -i list info on specified recipient(s) only # -k mark recipient(s) as having received tool(s) # -l file list of people to ship to # -m don't send shipment manifest mail message # -n show but don't execute # -o set shipment ownership to shipper # -p name next argument is a recipient to ship to # -s don't send shipment support files # -t don't execute but show total shipment # -u [[yy]mm]dd ignore db info for date pattern # -v yymmdd override current date stamp # -w shipment suitable for www # -x format pax output format and compression # -C files add to default crate file list # -D secs delay in seconds between sends # -F force db override # -S files add to default support file list # # name -- recipient address # # machine!user uucp address # host:directory rcp address # *%[beta.]bin[.arch] compressed cpio binary archive in Z/*[.arch] # *%ftp sh script with ftp get's on stdout # *%[beta.]lib[.arch] compressed cpio binary archive in Z/*[.arch] # *%list shipment file list on stdout # *%pull sh script with datakit pull's on stdout # *%push sh script with datakit push's on stdout # *%[beta.]src compressed cpio src archive in Z/* # # the message file is evaluated by the shell and the following variables # are predefined by ship: # # f list of expanded file names # name name of shipee # umask 02 PATH=:$PATH SHIPSLOG=${SHIPSLOG:-shipslog} SHIPINFO=${SHIPINFO:-$SHIPSLOG/info} SHIPFILES="README shipin shipout" SHIPAUX="shipiffe.sh shipop.c shipproto.c" SHIPMENT=*[0-9][0-9][0-9][0-9][0-9][0-9] SHIPPER=${SHIPPER:-${USER:-${LOGNAME:-${HOME##*/}}}} SHIPSPOOL=${SHIPSPOOL:-/usr/spool/uucppublic} SHIPORG=${SHIPORG:-"Software and Systems Research"} SHIPLOGO=${SHIPLOGO:-"http://www1126.research.att.com/logos/attbllogo.gif align=middle"} SHIPMM2HTML=${SHIPMM2HTML:-mm2html} CRATEFILES="copyright items message promo release report" TMP=${TMPDIR:=/tmp}/ship$$ FROMSYS=$( (uname -n || hostname || cat /etc/whoami) 2>/dev/null ) test -f shipinit && . ./shipinit function errexit { # print out an error message on unit 2 and exit print -u2 - "$command: $@" exit 1 } function warning { print -u2 - "$command: warning: $@" } function cleanup # exitcode { trap - EXIT INT TERM db_done rm -f $TMP.? exit $1 } db_access= db_data= db_disable= db_key_base= db_key_delta= db_pid= db_status= # # send request to dbm server # status returned in db_status # data returned in db_data # function db_request # op args ... { print -p "$@" read -p db_status db_data case $db_debug in ?*) print -u2 DB: "$@": $db_status $db_data ;; esac case $db_status in I) return 0 ;; E) print -u2 $logfile: $db_data; return 1 ;; *) return 1 ;; esac } # # initialize db # function db_init # machine user { typeset log=$logfile machine=$1 user=$2 i j l case $db_disable in ?*) return 0 ;; esac case $db_debug in grep) db_access=grep ;; esac case $db_access in "") case $log in "") ifs=$IFS IFS=: set -- $PATH IFS=$ifs for i do case $i in */bin) i=${i%/bin} for j in /share/ / do l=${i}${j}lib/ship/log if test -f $l.dir -a -r $l.dir -a -w $l.dir then log=$l break 2 fi done ;; esac done case $log in "") log=$SHIPSLOG/log ;; esac ;; esac case $log in /*) ;; *) log=$PWD/$log ;; esac db_access=grep if cs /dev/null 2>&1 then cs -i /dev/tcp/share/dbm/group=ship |& db_pid=$! if db_request version then db_request open $log w || errexit $log: cannot access log db_access=dbm logfile=$log fi fi ;; esac case $db_debug in ?*) print -u2 DB: init: access=$db_access logfile=$logfile ;; esac case $db_access in dbm) first_time=0 db_check - $machine $user shipin "*" base || first_time=1 ;; grep) typeset -L2 dir=$machine case $logfile in ?*) mv $logfile $SHIPSLOG/.tmp. sort -r < $SHIPSLOG/.tmp. | sort -m -u +0 -1 > $logfile rm -f $SHIPSLOG/.tmp. ;; esac logfile=$SHIPSLOG/$dir/$machine/$user if test "" = "$force" -a -r "$logfile" then first_time=0 else first_time=1 case $noexec in "") if test ! -d "$SHIPSLOG/$dir" then mkdir "$SHIPSLOG/$dir" || logfile=$SHIPSLOG/log fi if test ! -d "$SHIPSLOG/$dir/$machine" then mkdir "$SHIPSLOG/$dir/$machine" || logfile=$SHIPSLOG/log fi ;; esac fi ;; esac } # # end db interaction # function db_done # { case $db_disable in ?*) return 0 ;; esac case $noexec in "") case $db_access in dbm) db_request close db_request quit kill $db_pid ;; grep) case $logfile in ?*) mv $logfile $SHIPSLOG/.tmp. sort -r < $SHIPSLOG/.tmp. | sort -m -u +0 -1 > $logfile rm -f $SHIPSLOG/.tmp. ;; esac ;; esac ;; esac } # # check if < machine user tool version type > was sent # function db_check # [ - ] machine user tool version type { typeset k key ks sav x nocheck= case $db_disable:$first_time:$force in 1:*:*|*:1:*|*:*:1) return 1 ;; esac case $1 in -) shift; nocheck=1 ;; esac typeset a=$1!$2 n=$3 v=$4 t=$5 m case $5 in "*") ks="base delta" ;; base) ks=base ;; *) ks=delta ;; esac for k in $ks do key=$a,$n,$k eval sav=\$db_key_$k case $key in $sav) eval set -- \$db_val_$k ;; *) case $db_access in dbm) if db_request get $key then set -- $db_data else continue fi ;; grep) set -- $(grep "^$key" $logfile) case $# in 0) continue ;; esac shift ;; esac eval db_key_$k='$key' db_val_$k='$*' ;; esac case $1/$2 in $v/$t) case $undo in "") ;; *) case $nocheck in "") case $3 in $undo) continue ;; esac ;; esac ;; esac case $v in "*") return 0 ;; esac ;; *) case "$v" in "*") return 0 ;; esac continue ;; esac if test -d $n then m=$(shipop time $n/$1/$2) else m=$(shipop time $n) fi case $6 in ""|$m) return 0 ;; *) return 1 ;; esac done return 1 } # # note that < machine user tool version type > was sent # function db_note # machine user tool version type name { typeset k v m case $db_disable in ?*) return 0 ;; esac case $5 in base) k=base ;; *) k=delta ;; esac if test -d $3 then m=$(shipop time $3/$4/$5) else m=$(shipop time $3) fi v="$1!$2,$3,$k $4 $5 $date $SHIPPER $6 $m" case $db_access in dbm) db_request put $v ;; grep) print $v >> $logfile ;; esac } # # output SHIPMENT stamp for file [current date] # function shipstamp # file { typeset -Z2 day month typeset -R2 year integer mon Jan=1 Feb=2 Mar=3 Apr=4 May=5 Jun=6 \ Jul=7 Aug=8 Sep=9 Oct=10 Nov=11 Dec=12 case $# in 0) set -- $(date) shift 1 ;; *) set -- $(ls -ld $1 2>/dev/null) while : do case $# in [01]) break ;; esac case $1 in Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) case $2 in [1-9]|[0-3][0-9]) case $3 in [0-9]*) break ;; esac ;; esac ;; esac shift done ;; esac mon=$1 day=$2 month=$mon case $3 in *:*:*) year=$5 ;; *:*) set -- $(date) year=$6 if (($mon > $2)) then let year=year-1 fi ;; *) year=$3 ;; esac print $year$month$day } # # prepare $tool for shipping # function package # tool [blocks] { typeset tool=$1 integer package_blocks=${2-20} integer package_chunk=package_blocks*8*1024 integer size i=0 skip=0 typeset -RZ3 suffix typeset fsize if test $tool.000 -nt $tool then return 0 fi fsize=$(wc -c $tool) size=${fsize%$tool} if ((size <= package_chunk)) then return 1 fi print packaging $tool rm -f $tool.??? while (( size > 0)) do suffix=$i dd if=$tool of=$tool.$suffix bs=8k skip=$skip count=$package_blocks 2> /dev/null let i=i+1 skip=skip+package_blocks size=size-package_chunk done set -- $tool.??? case $1 in *.\?\?\?) errexit "$tool: cannot package" ;; esac return 0 } function gencontrol # tool { typeset tool=${1%/*} typeset format=${1#$tool/} typeset init typeset parts if test -f $1 then if package $1 then parts='.???' else parts='' fi else # $SHIPFILES print - "cp $date.$SHIPPER/${tool%/*} \$INSTALLROOT/ship" >> $TMP.u return fi tooldir=${tool%%/*} { print - "if test ! -f \$INSTALLROOT/ship/$tooldir/items" set -- $tool/$format$parts case $# in 1) print - "then if test -f $tool/$format$parts" prefix="then" ;; *) print - "then _unspool_nope= for i in $* do if test ! -f \$i then _unspool_nope=1 break fi done case \$_unspool_nope in" prefix='"")' ;; esac case $format in base|delete) init= ;; *) init=$basetoo ;; esac case $init in "") print - " $prefix if test ! -d \$INSTALLROOT/ship/$tooldir then mkdir \$INSTALLROOT/ship/$tooldir fi rm -rf \$INSTALLROOT/ship/$tool mkdir \$INSTALLROOT/ship/$tool" prefix= ;; esac print - " $prefix cat $tool/$format$parts > \$INSTALLROOT/ship/$tool/$format" print - " rm -f $tool/$format$parts" case $init in "") for i in $CRATEFILES do if test -s $tool/$i then print - " echo \"$(cat $tool/$i 2>/dev/null)\" > \$INSTALLROOT/ship/$tool/$i" elif test -f $tool/$i then print - " : > \$INSTALLROOT/ship/$tool/$i" fi done if test "" != "$www" then owner= else if test "" = "$shipper" -a -s $tool/owner then owner=$(<$tool/owner) else owner=$SHIPPER fi case ${TOSYS##*!} in ${owner%%!*}) owner=${TOSYS%!*}!$owner ;; *) owner=$TOSYS!$owner ;; esac fi print - " echo \"$owner\" > \$INSTALLROOT/ship/$tool/owner" ;; esac case $# in 1) print - " fi" ;; *) print - " ;; esac" ;; esac print - "fi" } >> $TMP.u } function instructions # first { integer item=0 first=$1 typeset tool pack packages omit main case $first in 0) print " As a repeat recipient:" case $redo in 1) print " ($((item=item+1))) This shipment includes an update to the installation support tools. Any tools that failed to build previously will be attempted again." ;; esac ;; 1) print " As a first time recipient:" ;; esac print " ($((item=item+1))) Wait for a \\\`copy succeeded' message from uucp for the file: \$user/$FROMSYS/$date.$SHIPPER/manifest" print " ($((item=item+1))) For safety do not run as root. If you are not running as \$user then: RECIPIENT=\$user export RECIPIENT" packages=$(for tool in "${ship_list[@]}" do tool=${tool%%/*} if test -f $tool/Mamfile then sed -e '/^setv PACKAGE/!d' -e 's/^setv / /' -e 's/ /=/' -e 's/\$/\\&/g' $tool/Mamfile fi done | sort -t= -u +0 -1) case $packages in ?*) omit= for tool in "${ship_list[@]}" do case $tool in lib*) tool=${tool%%/*} tool=${tool#lib} case $omit in "") omit="$tool" ;; *) omit="$omit|$tool" ;; esac ;; esac done case $omit in ?*) main=$(echo "$packages" | egrep "PACKAGE_($omit)[=_]" | sed -e 's/^ PACKAGE_\([^_=]*\).*/\1/' | sort -u) packages=$(echo "$packages" | egrep -v "PACKAGE_($omit)[=_]") ;; esac esac case $first in 0) print " ($((item=item+1))) Name the directory under which previous shipments were installed: INSTALLROOT=" ;; 1) case $main in ""|*" "*) main= ;; *) main=" A good final installation directory name would be /usr/add-on/$main." ;; esac print " ($((item=item+1))) Create a shipment root directory under which all source and binaries will be generated. This should not be a final installation directory.$main INSTALLROOT= test -d \\\$INSTALLROOT || mkdir \\\$INSTALLROOT cd \\\$INSTALLROOT test -d ship || mkdir ship" ;; esac print " ($((item=item+1))) If $uuspool/\$user/$FROMSYS was copied to \\\$SPOOLROOT then: SHIPSPOOL=\\\$SPOOLROOT export SHIPSPOOL" print " ($((item=item+1))) If your system has att and bsd/ucb universes then in general the tools will have more functionality when built in the bsd/ucb universe. The exception is on solaris where /usr/ucb/cc is fubar. Set cc by: CC='hackcc -systype bsd43' CCFLAGS='-g' # just an example # export CC CCFLAGS" case $packages in ?*) print " ($((item=item+1))) This shipment refers to some installation dependent software packages. Redefine and export any of the following definitions that are incorrect: $packages" ;; esac print " ($((item=item+1))) Execute the following commands to unpack and install the shipment: cd \\\$INSTALLROOT" case $first in 1) print "\ cp \\\${SHIPSPOOL-$uuspool/\$user/$FROMSYS}/$date.$SHIPPER/shipin ship/shipin chmod 0755 ship/shipin" ;; esac print "\ nohup ksh ship/shipin &" print " ($((item=item+1))) Use shipout within \\\$INSTALLROOT/ship to ship to other machines. \\\$INSTALLROOT/ship/README contains more detailed information." } function buildscript # machine user { # create mscript to execute as a . script typeset tool format integer delta=0 first=1 no_shipin mscript=$TMP.s tfile=$TMP.f case $message in ?*) { print "cat > $tfile </dev/null | egrep 'DELTA!!!|!PAX!D!' >/dev/null then t="$format delta" delta=1 else t="$format patch" fi ;; *) errexit "$format: invalid format" ;; esac print " $n$d$t" done print if ((delta)) then print "\ Unpacking delta shipments requires the new pax command. " fi for tool in "${ship_list[@]}" do if test ! -r $tool then continue fi format=${tool##*/} tool=${tool%/$format} if test -s "$tool/message" then item=${tool%%/*} eval x='$'_notes_$item case $x in 0) print "\ $item notes: " eval _notes_$item=1 ;; 1) if cmp -s "$tool/message" "$item/$format/message" then continue fi ;; esac cat "$tool/message" print fi done if test -f ship.tail then cat ship.tail elif test -f $HOME/.signature then cat $HOME/.signature fi print '!EOF!' case $noexec in "") print 'mail $mail < $tfile' ;; *) print 'print "mail $mail < $mscript ;; esac } function tosys # machine { # construct return mail address typeset i IFS=! TOSYS= for i in $@ do case $i in %*) ;; *) TOSYS=$i!$TOSYS ;; esac done case $TOSYS in $FROMSYS!) TOSYS= ;; esac TOSYS=$TOSYS$FROMSYS } function genshiplist # machine user mail { typeset tool file x n v t need_pax= missing= integer i=0 j=0 lclfiles= rmtfiles= db_init $1 $2 db_check - $1 $2 pax "*" base || need_pax=1 machine=$1 user=$2 mail=$3 unset ship_list redo for file in $SHIPFILES do v=$(shipstamp $file) if db_check $machine $user $file $v base then continue fi ship_list[i]=$file/$v/base i=i+1 case " $SHIPAUX " in *" $file "*) redo=1 ;; esac done j=i for tool in "${tool_list[@]}" do n=${tool%%/*} case $need_pax in "") eval t=\$type_$n case $t in pax) continue ;; esac ;; esac v=${tool#*/} v=${v%/*} t=${tool##*/} case $tool in */*/$SHIPMENT) if db_check $machine $user $n $t "*" then case $basetoo in "") case $noexec in "") db_note $machine $user $n $t base $name ;; esac ;; ?*) if db_check $machine $user $n $v base then : elif test -f $n/$v/base then ship_list[i]=$n/$v/base i=i+1 else print -u2 "$n/$v/base: missing base archive" missing=1 fi ;; esac elif test -f "$n/$v/base" then if db_check $machine $user $n $v base then : else ship_list[i]=$n/$v/base i=i+1 fi case $basetoo in "") continue ;; esac elif test -f $n/$t/base then ship_list[i]=$n/$t/base i=i+1 else print -u2 "$n/$t/base: missing base archive" missing=1 fi ;; esac if db_check $machine $user $n $v $t then : else ship_list[i]=$tool eval clean_$n= i=i+1 fi done case $missing in ?*) exit 1 ;; esac if ((j>=i)) then case $redo in "") case $total in "") print -u2 "$mail is up to date" ;; *) print -u2 "\\n$mail: up to date" ;; esac return 0 ;; esac else case $mark in ?*) case $user:$noexec in ?*:) for tool in "${ship_list[@]}" do x=${tool#*/} x=${x%/*} db_note $machine $user ${tool%%/*} $x ${tool##*/} $name done ;; esac return 0 ;; esac fi case $total in ?*) print -u2 "\\n$mail:" PS3='' select i in ${ship_list[*]} do : done on given case $transport in uucp) typeset dest=$1!$uupublic/$2/$FROMSYS/$date.$SHIPPER print "$rmtfiles $date.$SHIPPER/unspool $date.$SHIPPER/manifest" > $TMP.m print uucp -r -C $TMP.u $dest/unspool case $noexec in "") uucp -r -C $TMP.u $dest/unspool ;; esac case $SHIPID in ?*) print $date.$SHIPPER/id >> $TMP.m id="$SHIPPER SEAL $(date) $1!$2" print "$1!$SHIPID $id" > $TMP.i print uucp -r -C $TMP.i $dest/id case $noexec in "") uucp -r -C $TMP.i $dest/id ;; esac case $noexec in "") print "$id\\t$(shipop seal $lclfiles $TMP.u $TMP.m $TMP.i)" >> $SHIPSLOG/seals ;; esac ;; esac print uucp -r -C -m -n"$2" $TMP.m $dest/manifest case $noexec in "") uucp -r -C -m -n"$2" $TMP.m $dest/manifest ;; esac ;; uuto) print uuto -m $TMP.u $1!$2 case $noexec in "") uuto -m $TMP.u $1!$2 ;; esac ;; esac case $noexec in ?*) case $SHIPID in ?*) print "ID:" cat $TMP.i ;; esac print "MANIFEST:" cat $TMP.m print "UNSPOOL:" cat $TMP.u ;; esac } function doship # { # ship the files typeset i j tool file integer d case "$info" in ?*) fixedname=${name%% *} print "$fixedname $address $phone $mail $company $project $transport" return esac user=${mail##*!} machine=${mail%!*} user=${user%%@*} machine=${machine#*@} target=$machine!~/$user/$FROMSYS uuspool=$SHIPSPOOL case $transport in uucp) uupublic='~' ;; uuto) uuspool=$uuspoool/receive uupublic=$uuspool print -u2 $transport: transport not supported for $user return ;; *) print -u2 $transport: unknown transport for $user return ;; esac if genshiplist $machine $user $mail then return fi tosys $machine > $TMP.u for i in "${ship_list[@]}" do gencontrol "$i" done case $redo in ?*) for i in $tools do print - "for i in \$INSTALLROOT/ship/${i%/*}/*" print - "do if test -d \$i -a ! -f \$i/BUILT" print - " then rm -f \$i/[BEU]*" print - " fi" print - "done" done >> $TMP.u ;; esac buildscript $machine $user dtime=0 for tool in "${ship_list[@]}" do for i in $tool.??? do case $i in *.\?\?\?|*.000) d=25 if test -f $tool.001 then j=$i elif test -f $tool then i=$tool j=$tool else # here for $SHIPFILES i=${tool%%/*}; j=$date.$SHIPPER/$i fi;; *) j=$i d=50;; esac dfile=$target/$j if test -f "$i" then lclfiles="$lclfiles $i" case $rmtfiles in "") rmtfiles=$j ;; *) rmtfiles="$rmtfiles $j" ;; esac print uucp -r $nocopy $PWD/"$i" "$dfile" case $noexec in "") uucp -r $nocopy $PWD/"$i" "$dfile" dtime=dtime+d ;; esac fi done i=${tool#*/} i=${i%/*} case $noexec in "") db_note $machine $user ${tool%%/*} $i ${tool##*/} $name ;; esac done if test -r $mscript then . $mscript fi sendcontrol $machine $user } function dosend # recipient open { # lookup in database and transport software to them # if is given, the database is re-opened addr=$1 db_disable= case $addr in *%beta.*|*%bin*|*%ftp|*%lib*|*%list|*%pull|*%push|*%src) db_disable=1 mail=$addr transport=${addr##*'%'} machine=%$transport user=${addr%"$machine"} case $transport in beta.*) beta=$SHIPPER transport=${transport#beta.} ;; *) beta= ;; esac case $transport in bin*|lib*|src) dir=ship out=${user:-${transport%%.*}} view= case $transport in bin) arch=${PWD%/ship} case $arch in */arch/*) a=${arch##*/} ;; *) a=${HOSTTYPE:-$(hostinfo type)} ;; esac out=$out.$a type="$a binary" type_H=".I $a .B binary" ;; bin.*) arch=${transport#bin.} out=$out.$arch transport=bin type="$arch binary" type_H=".I $arch .B binary" view=1 ;; lib) arch=${PWD%/ship} case $arch in */arch/*) a=${arch##*/} ;; *) a=${HOSTTYPE:-$(hostinfo type)} ;; esac out=$out.$a type="$a binary and library" type_H=".I $a .B binary and .B library" ;; lib.*) arch=${transport#lib.} out=$out.$arch transport=lib type="$arch binary and library" type_H=".I $arch .B binary and .B library" view=1 ;; *) arch=.. type="source" type_H=".B source" ;; esac ccprobe= case $view in ?*) case $PWD in */arch/*) arch=${PWD%/arch/*}/arch/$arch export INSTALLROOT=$arch vpath $arch ${PWD%/arch/*} 2>/dev/null export VPATH=$arch:${PWD%/arch/*} for f in $arch/lib/probe/C/make/[!p]*bincc $arch/lib/probe/C/make/[!p]*cc $arch/lib/probe/C/make/[!p]* do if test -f $f then ccprobe=CC.PROBE=$f break fi done ;; esac ;; esac MAKE=$(whence nmake) ;; *) dir=. ;; esac ;; *:*) transport=rcp mail=$1 host=${addr%:*} dir=${addr#*:} case $host in *@*) user=${host%@*} host=${host#*@} ;; *) user=${dir%%/*} case $user in '~'*) user=${user#~} ;; *) user=$SHIPPER ;; esac ;; esac machine=$host ;; *!*) name=${1##*!} transport=uucp ;; *@*) name=${1%%@*} transport=uucp ;; *) transport=db ;; esac case $transport in uucp) address= phone= mail=$1 project= doship return 1 ;; db) typeset -l given match case $shipinfo_test in "") if test ! -f "$SHIPINFO" then errexit "$SHIPINFO: cannot find information file" fi shipinfo_test=1 ;; esac case $2 in ?*) exec 3< $SHIPINFO ;; esac given=$1 while IFS=: read -ru3 name address phone mail company project unused transport comments do match=$name case $match in \#*) ;; $given*) doship return 1 ;; esac done ;; *) typeset d i p s if genshiplist $machine $user $mail then return 1 fi tosys $machine case $transport in ftp) ftp_address=$(cs -a addr $FROMSYS 2>/dev/null || print - $FROMSYS) ;; esac exec 9>&1 case $transport in bin|lib);; *) case $transport in list|push|src) ;; *) print - "umask 02" ;; esac case $transport in ftp) print - 'case $INSTALLROOT in' print - '?*) if test -d $INSTALLROOT' print - ' then cd $INSTALLROOT' print - ' else echo "$0: $INSTALLROOT: invalid INSTALLROOT" >&2' print - ' exit 1' print - ' fi' print - ' ;;' print - 'esac' print - 'if test ! -d ship' print - 'then mkdir ship || exit 1' print - 'fi' print - 'cd ship' print - 'if test -r "$HOME/.netrc" && grep -c "machine[ ]*'$ftp_address'[ ]*" "$HOME/.netrc"' print - 'then :' print - 'else echo "machine '$ftp_address' login anonymous password '$user'" >> "$HOME/.netrc"' print - ' chmod 0600 "$HOME/.netrc"' print - 'fi' ;; esac for i in "${ship_list[@]}" do if test -f $i then d=$i/file p=${d%%/*} s=${d#${p}/} t=$p while test "$s" != file do if test "" != "$p" then case $transport in list|src) print - "$dir/$p" ;; push) ;; *) print - "if test ! -d $dir/$p" print - "then mkdir $dir/$p" print - "fi" ;; esac fi p=${p}/${s%%/*} s=${d#${p}/} done i=${i%/*} for f in $CRATEFILES do if test -s $i/$f then case $transport in list|push|src) print - "$dir/$i/$f" ;; *) print - "echo \"$(cat $i/$f 2>/dev/null)\" > $dir/$i/$f" ;; esac elif test -f $i/$f then case $transport in list|push|src) print - "$dir/$i/$f" ;; *) print - "> $dir/$i/$f" ;; esac fi done case $transport in list|push|src) if test "" = "$www" -a -s $i/owner then print - "$dir/$i/owner" fi ;; *) if test "" != "$www" then owner= else if test "" = "$shipper" -a -s $i/owner then owner=$(<$i/owner) else owner=$SHIPPER fi case ${TOSYS##*!} in ${owner%%!*}) owner=${TOSYS%!*}!$owner ;; *) owner=$TOSYS!$owner ;; esac fi print - "echo \"$owner\" > $dir/$i/owner" ;; esac fi done case $transport in list|push|src) ;; *) print - "rm -f $dir/ship.$date" ;; esac case $transport in ftp) print - '${FTP-ftp} $FTP_ADDRESS <$TMP.f cat test -d Z || mkdir Z ;; bin:*|lib:*|src:*) print - "(cd $arch; pax -w $paxformat) > Z/$out.Z <&2; exit 1 ;;' print - 'esac' print - 'FTP_ADDRESS=${1-'$ftp_address'}' print - 'FTP_INSTALLROOT=${2-.}' cat ;; list:*) cat ;; pull:*) print - ': pull shipment from remote dk host' print - 'case $# in' print - '1|2) ;;' print - '*) echo "Usage: $0 dk-address [remote-INSTALLROOT]" >&2; exit 1 ;;' print - 'esac' print - 'DK_ADDRESS=$1' print - 'DK_INSTALLROOT=${2-.}' cat ;; push:*) print - ': push shipment to remote dk host' print - 'case $# in' print - '1|2) ;;' print - '*) echo "Usage: $0 dk-address [remote-INSTALLROOT]" >&2; exit 1 ;;' print - 'esac' print - 'push $1 - ${2:+$2/}ship <<"!!!"' cat ;; *:) cat > $TMP.r rcp $TMP.r $host:$dir/ship.$date || exit rm -f $TMP.r case $rsh in "") for i in rcmd remsh do if ($i $host date) >/dev/null 2>&1 then rsh=$i break fi done case $rsh in "") rsh=rsh ;; esac ;; esac $rsh $host sh $dir/ship.$date || exit ;; *) print - "cat '" cat print - "' > ship.$date" print - "rcp ship.$date $host:$dir" print - "rm ship.$date" print - "rsh $host sh $dir/ship.$date" ;; esac chmod= items= pwd=. skip= for tool in "${ship_list[@]}" do if test ! -f $tool then i=${tool%%/*} else i=$tool fi dfile=$mail/$i if test -f "$i" then case $transport in bin|lib)case $i in */*) case $i in $tool) i=${i%/*} i=${i%/*} case $i in $skip) ;; *) ( cd $arch r=$PWD case $i in lib*) cd src/lib/$i ;; *) cd src/cmd/$i ;; esac list=list.ship case $transport in bin) list=$list.$transport ;; esac INSTALLROOT=$r $MAKE -o 'accept noexec mismatch reread silent' $list $ccprobe ) ;; esac ;; esac ;; README|shipout) print - "ship/$i" skip=${tool%%/*} ;; *) skip=${tool%%/*} ;; esac ;; ftp) case $i in */*) t=${i%/*} ;; *) t=. ;; esac case $t in $pwd) ;; *) print - cd '$FTP_INSTALLROOT'/ship/${i%/*} case $pwd in .) print - lcd $t ;; *) print - lcd ../../$t ;; esac pwd=$t ;; esac print - get ${i##*/} test -x $i && chmod="$chmod $i" ;; list|push) print - "$i" ;; pull) case $i in */*) t=${i%/*} ;; *) t=. ;; esac print - echo pull '$DK_ADDRESS' '$DK_INSTALLROOT'/ship/$i $t print - pull '$DK_ADDRESS' '$DK_INSTALLROOT'/ship/$i $t ;; rcp) print rcp "$i" "$dfile" case $noexec in "") rcp "$i" "$dfile" || exit ;; esac ;; src) print - "ship/$i" case $i in */*) ;; *) skip=${tool%%/*} ;; esac ;; esac fi i=${tool#*/} i=${i%/*} case $user:$noexec in ?*:) db_note $machine $user ${tool%%/*} $i ${tool##*/} $name ;; esac i=${tool%%/*} case $i in $skip) ;; *) skip=$i items="$items $i" ;; esac done exec 1>&9 9>&- case $transport:$noexec in bin:|lib:|src:) test "" != "$www" && { case $type in [aehiouAEHIOU]*) a=an ;; *) a=a ;; esac print - ".TL - - \"$SHIPORG\" \"$SHIPLOGO\" Software Shipment Contents This is $a $type_H shipment of .IR $out ." if test -f ship.${out%%.*}.promo then print - ".P" cat ship.${out%%.*}.promo print - ".P" fi print - "The shipment contains: .EX" case $transport in bin) ls -Cd $(ls -d $items 2>/dev/null | grep -v '^lib') 2>/dev/null ;; *) ls -Cd $items 2>/dev/null ;; esac print - ".EE" hit=" " for tool in "${ship_list[@]}" do tool=${tool%/*} case $hit in *" $tool "*) ;; *) hit="$hit$tool " if test -f $tool/promo then promo=1 cat $tool/promo else promo= fi if test -f $tool/release then case $promo in "") print - ".H 1 ${tool%/*}" ;; esac print - ".P" print - ".DS" cat $tool/release print - ".DE" fi ;; esac done print - ".H 1 If you have problems send mail to .I advsoft@attmail.att.com with .I $out in the subject field." } | $SHIPMM2HTML >Z/$out.H { print - "#" print - "# the following ${beta:+beta }$type shipment" print - "# of $out has been sent" case $beta in ?*) print - "# this beta shipment may only be interface compatible with itself" print - "# other shipments will be reconciled after beta testing" ;; esac print - "#" case $transport in bin) ls -Cd $(ls -d $items 2>/dev/null | grep -v '^lib') 2>/dev/null ;; *) ls -Cd $items 2>/dev/null ;; esac | sed 's/^/# /' print - "#" print - "# to install:" print - "#" print - "INSTALLROOT=${beta:+/beta.$beta}" print - "SHIPMENT=" print - "cd \$INSTALLROOT" print - "$paxuncompress \$SHIPMENT | $paxunformat" case $transport in bin|lib)(cd $arch; ls -ld $(<$TMP.f) 2>/dev/null) > $TMP.s for f in $(sed -e '/^-..s..s/!d' -e 's/.* //' $TMP.s) do set x $(cd $arch; ls -ld $f 2>/dev/null) n=$# g=$5 set x $(cd $arch; ls -ldg $f 2>/dev/null) n1=$# g1=$5 if test $n -lt $n1 then g=$g1 fi print - "chgrp $g $f || echo ship: $f would be more efficient if owned by group $g >&2" done sed -e '/^-..s/!d' -e 's/^-..s..s.* /chmod ug+s /' -e 's/^-..s.* /chmod u+s /' $TMP.s rm $TMP.s for f in $items do test -f $f/binary && cat $f/binary done ;; src) print - "nohup ksh ship/shipin &" ;; esac print - "#" print - "# to use:" print - "#" print - "export LD_LIBRARY_PATH=\$INSTALLROOT/lib\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}" print - "export PATH=\$INSTALLROOT/bin:\$PATH" print - "export FPATH=\$INSTALLROOT/fun\${FPATH:+:\$FPATH}" } >Z/$out.M case $transport in bin) (cd $arch; sort -u $TMP.f | egrep -v '^(include/.*|lib/lib.*\.a)$' | pax -Lw $paxformat; rm $TMP.f) > Z/$out.Z ;; *) (cd $arch; sort -u $TMP.f | pax -Lw $paxformat; rm $TMP.f) > Z/$out.Z ;; esac ;; bin:*|ftp:*|lib:*|push:*|src:*) case $transport in ftp) print - 'quit' ;; esac print - '!!!' case $chmod in ?*) print - "chmod +x$chmod" ;; esac ;; esac return 1 ;; esac print -u2 "$command: address for $1 not found" return 1 } function closure # tools { tools= for tool do if test ! -d $tool then case $original in *" ${tool%/*} "*|*" $tool "*) warning "${tool%/*}: invalid tool" ;; esac else case $tool in */?*) release=${tool#*/} tool=${tool#*/} ;; *) eval items=\"\$items_$item\" case $items in "") release= ;; *) eval release=\$release_$tool ;; esac ;; esac eval release_${tool%/*}=$release tools="$tools $tool" fi done set -- $tools # # now generate the closure of the top level tools and releases # tools= for tool do old= new=$tool while : do case $new in $old) break esac dup= for item in $new do # we assume items_* not in environment eval items=\"\$items_$item\" case $items in "") eval release=\$release_$item case $release in "") set -- $item/$SHIPMENT shift $#-1 case $1 in "$item/$SHIPMENT") continue ;; esac release=${1#*/} eval release_$item=$release esac if test ! -f $item/$release/items then if test ! -f $item/$release/delete then continue fi items=$item else case $closure in "") items=$item ;; *) items=$(<$item/$release/items)" $item" ;; esac fi eval items_$item=\"$items\" ;; esac dup="$dup $items" done old=$new new= for item in $dup do eval seen_$item= done for item in $dup do eval seen=\$seen_$item case $seen in "") eval seen_$item=1 new="$new $item" esac done done tools="$tools $new" done } function undup # tools { tools= for item do eval seen_$item= done for item do eval seen=\$seen_$item case $seen in "") eval seen_$item=1 tools="$tools $item" esac done } command=$0 integer dtime=0 i=0 nrecipient=0 first_time=1 delay=0 info= mark= list= logfile= message=1 nocopy= noexec= format=$SHIPMENT shipinfo_test= force= shipper= closure=1 undo= date= basetoo= www= paxformat= paxunformat= paxcompress= paxuncompress= while : do case $1 in -b) basetoo=1 ;; +b) basetoo= ;; -c) closure= ;; +c) closure=1 ;; -d) format=base ;; +d) format=$SHIPMENT ;; -i) info=1 delay=0 ;; -k) mark=1 delay=0 ;; -l) shift; list=$1 ;; +l) list= ;; -m) message= ;; +m) message=1 ;; -n) noexec=1 delay=0 ;; +n) noexec= ;; -o) shipper=1 ;; +o) shipper= ;; -p) shift; recipient_list[nrecipient]=$1; nrecipient=nrecipient+1 ;; +p) recipient= ;; -s) SHIPFILES= ;; -t) total=1 noexec=1 delay=0 ;; -u) shift; undo=$1 ;; +u) undo= ;; -v) shift; date=$1 ;; -w) www=1 ;; +w) www= ;; -x) shift case $1 in compress|gzip) paxcompress=$1 ;; *) paxformat=$1 ;; esac ;; -C) shift; CRATEFILES="$CRATEFILES $1" ;; -D) shift; delay=$1 ;; +D) delay=0 ;; -F) force=1 ;; +F) force= ;; -L) shift; logfile=$1 ;; -S) shift; SHIPFILES="$SHIPFILES $1" ;; *[,:!%@]*)recipient_list[nrecipient]=$1;nrecipient=nrecipient+1 ;; --) shift; break ;; -*|+*) print -u2 "Usage: $command [-bcdikmnostfF] [-l recipient-list] [-p recipient] [-u [[yy]mm]dd] [-v yymmdd] [-x format] [-C crate-file] [-D delay] [-S support-file] [recipient ...] [tool ...]"; exit 2 ;; *) break ;; esac shift done case $www in ?*) case $paxformat in "") paxformat=tar ;; esac case $paxcompress in "") paxcompress=gzip ;; esac ;; esac case $paxcompress in ""|compress) paxcompress=compress paxuncompress="zcat <" ;; gzip) paxuncompress="(gunzip || zcat) <" ;; esac case $paxformat in "") paxformat=cpio ;; esac case $paxformat in cpio) paxunformat="cpio -icdvmu" ;; tar) paxunformat="tar xvf -" ;; *) paxunformat="pax -rv" ;; esac case $paxformat in ?*) paxformat="-x $paxformat" ;; esac case $paxcompress in ?*) paxformat="-x $paxcompress $paxformat" ;; esac case $date in $SHIPMENT) ;; *) date=$(shipstamp) ;; esac ($SHIPMM2HTML) >/dev/null 2>&1 || SHIPMM2HTML=cat case $info in "") if test 0 = "$nrecipient" -a ! -f "$list" then errexit "no recipient(s)" fi trap 'cleanup $?' EXIT INT TERM # # generate the tools list # original=" $* " case $# in 0) tools= for tool in * do set -- $tool/$SHIPMENT case $1 in "$tool/$SHIPMENT") ;; *) tools="$tools $tool" ;; esac done case $tools in "") errexit "no tools" ;; esac set -- $tools ;; esac closure $* case $tools in "") errexit "no 'items' file(s)" ;; esac tools_usr=$tools tools_pax= case $closure:$format:$SHIPFILES in :*|*:|*:base:*|*:delete:*) ;; *) set -- pax/$SHIPMENT case $1 in "$tool/$SHIPMENT") ;; *) closure pax tools_pax=$tools ;; esac ;; esac undup $tools_pax $tools_usr set -- $tools for tool in $tools_pax do eval type_$tool=pax done for tool in $tools_usr do eval type_$tool=usr done set -- $tools for tool do eval tool=$tool/\$release_$tool item= for f in delete "$format" base do set -- $tool/$f if test -f "$1" then item=${1##*/} break fi done case $item in "") if test ! -d ${tool%/*} then case $original in *" ${tool%/*} "*|*" $tool "*) warning "${tool%/*}: invalid tool" ;; esac continue fi case $format in base) set -- $tool/$SHIPMENT if test -f "$1" then eval release_${tool%/*}=${1##*/} tool=${tool%/*}/${1##*/} item=base warning "${tool}: latest base not crated" else warning "${tool}: base not crated" continue fi ;; *) continue ;; esac ;; esac case $format in "$SHIPMENT"|$item) tool=$tool/$item ;; *) tool=${tool%/*}/$item/base if test ! -f $tool then errexit "${tool%/*}: $item base not crated" fi ;; esac tool_list[i]=$tool;i=i+1 done ;; *) typeset -lL16 fixedname typeset -L9 address project typeset -R12 phone typeset -L21 mail typeset -L11 company ;; esac if test ! -d $SHIPSLOG then mkdir $SHIPSLOG || errexit "$SHIPSLOG: cannot create log directory" fi SHIPID=$FROMSYS!$SHIPPER case $SHIPFILES in ?*) SHIPFILES="$SHIPFILES $SHIPAUX" for file in $SHIPFILES do if test ! -r $file then print -u2 "$file: cannot read"; exit 1 fi done ;; esac while : do case $undo in ""|??????*) break ;; *) undo="?$undo" ;; esac done nocopy=${nocopy+-c} flag=1 case $list in "") set -s -- "${recipient_list[@]}" ;; ?*) if test ! -r "$list" then errexit "$list: cannot read" else set -s -- "${recipient_list[@]}" $(sed -e '/^#/d' -e 's/[: ].*//' $list) fi ;; esac for recipient do if ((dtime)) then sleep $dtime fi if dosend "$recipient" $flag then flag= case $noexec$info in "") print "$name" >> ${tool%/*}/list ;; esac else flag=1 fi if ((delay > dtime)) then dtime=delay fi done exit 0