: # @(#)shipout (ulysses!{dgk,gsf}) 01/31/91 # # 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 # -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 # *%compress generates compressed cpio archive on stdout # *%list generates shipment file list # *%pull generates sh script with datakit pull's # *%push generates sh script with datakit push's # # 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" SHIPMENT=*[0-9][0-9][0-9][0-9][0-9][0-9] SHIPPER=${SHIPPER:-${USER:-${LOGNAME:-${HOME##*/}}}} SHIPSPOOL=${SHIPSPOOL:-/usr/spool/uucppublic} CRATEFILES="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 { db_done rm -f $TMP.? exit $1 } db_data= db_db= db_key_base= db_key_delta= db_status= db_style= # # send request to dbm server # status returned in db_status # data returned in db_data # function db_request # request { 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 { case $db_debug in grep) db_style=grep ;; esac case $db_style in "") if (shipdbm) </dev/null >/dev/null 2>&1 then db_style=dbm logfile=$SHIPSLOG/log shipdbm |& db_request om$logfile || db_request oc$logfile || errexit $logfile: cannot access log db_db=$db_data else db_style=grep fi ;; esac case $db_style in dbm) first_time=0 db_request s$db_db db_check - $1 $2 shipin "*" base || first_time=1 ;; grep) typeset -L2 dir=$1 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/$1/$2 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/$1" then mkdir "$SHIPSLOG/$dir/$1" || logfile=$SHIPSLOG/log fi ;; esac fi ;; esac } # # end db interaction # function db_done # { case $noexec in "") case $db_style in dbm) case $db_db in ?*) db_request c$db_db && db_request q ;; esac ;; 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 $first_time:$force in 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_style in dbm) if db_request g$db_db$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:$nocheck in :*|*:1) ;; *) continue ;; esac case $3 in $undo) continue ;; *) ;; 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 $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_style in dbm) db_request p$db_db$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) 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 -- $tool.000 always created # function package { typeset tool=$1 integer nblocks=${2-20} integer size i=0 skip=0 integer chunksize=nblocks*8*1024 typeset -RZ3 suffix typeset fsize print packaging $tool rm -f "$tool".??? fsize=$(wc -c $tool) size=${fsize%$tool} if ((size <= chunksize)) then ln "$tool" "$tool".000 else while (( size > 0)) do suffix=$i dd if="$tool" of="$tool.$suffix" bs=8k skip=$skip count=$nblocks 2> /dev/null let i=i+1 skip=skip+nblocks size=size-chunksize done fi set -- "$tool".??? case $1 in *.\?\?\?) errexit "$tool: cannot package" ;; esac } function gencontrol # tool { typeset tool=${1%/*} typeset format=${1#$tool/} typeset init if test -f $1 then if test $1 -nt $1.000 then package $1 fi set -- $1.??? else # $SHIPFILES print - "cp $date.$SHIPPER/${tool%/*} \$INSTALLROOT/ship" >> $TMP.u return fi tooldir=${tool%%/*} { cat <<-! if test ! -f "\$INSTALLROOT/ship/$tooldir/items" then ! case $format in base) init= ;; *) init=$basetoo ;; esac case $init in "") cat <<-! if test ! -d "\$INSTALLROOT/ship/$tooldir" then mkdir "\$INSTALLROOT/ship/$tooldir" fi rm -rf "\$INSTALLROOT/ship/$tool" mkdir "\$INSTALLROOT/ship/$tool" ! ;; esac cat <<-! if cat $tool/$format.??? > \$INSTALLROOT/ship/$tool/$format then rm -f $tool/$format.??? fi ! 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 "" = "$shipper" -a -s $tool/owner then owner=$(<$tool/owner) else owner=$SHIPPER fi case ${TOSYS##*!} in ${owner%%!*}) owner=${TOSYS%!*}!$owner ;; *) owner=$TOSYS!$owner ;; esac print - "echo \"$owner\" > \$INSTALLROOT/ship/$tool/owner" ;; esac cat <<-! fi ! } >> $TMP.u } 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 <<!EOF!" print "Subject: software shipment" if test -f ship.body then print cat ship.body else f=${name#*,} l=${name%,*} case $f in $l) ;; *) print "\ Dear ${name#*,} ${name%,*}:" ;; esac if test -f ship.head then cat ship.head print fi if db_check $1 $2 shipin "*" base then no_shipin=0 else no_shipin=1 fi if ((first_time||no_shipin)) then print "\ As a first time recipient: (1) Wait for a \\\`copy succeeded' message from uucp for the file: \$user/$FROMSYS/$date.$SHIPPER/manifest (2) For safety do not run as root. If you are not running as \$user then: RECIPIENT=\$user export RECIPIENT (3) Create a shipment root directory under which all source and binaries will be generated. This should not be a final installation directory. INSTALLROOT=<shipment-root-directory> test -d \\\$INSTALLROOT || mkdir \\\$INSTALLROOT cd \\\$INSTALLROOT test -d ship || mkdir ship (4) Name the uucp shipment spool directory: SHIPSPOOL=$uuspool/\$user/$FROMSYS however if $uuspool/\$user/$FROMSYS was copied to \\\$SPOOLROOT then: SHIPSPOOL=\\\$SPOOLROOT (5) 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. You can set the C compiler name and/or flags by: CC='hackcc -systype bsd43' CCFLAGS='-g' # just an example # export CC CCFLAGS (6) Execute the following commands to unpack and install the shipment: export SHIPSPOOL cp \\\$SHIPSPOOL/$date.$SHIPPER/shipin ship/shipin chmod 0755 ship/shipin nohup ship/shipin & (7) Use shipout within \\\$INSTALLROOT/ship to ship to other machines. \\\$INSTALLROOT/ship/README contains more detailed information. " else print "\ As a repeat recipient: (1) Wait for a \\\`copy succeeded' message from uucp for the file: \$user/$FROMSYS/$date.$SHIPPER/manifest (2) For safety do not run as root. If you are not running as \$user then: RECIPIENT=\$user export RECIPIENT (3) Name the directory under which previous shipments were installed: INSTALLROOT=<shipment-root-directory> (4) If $uuspool/\$user/$FROMSYS was copied to \\\$SPOOLROOT then: SHIPSPOOL=\\\$SPOOLROOT export SHIPSPOOL (5) 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. You can set the C compiler name and/or flags by: CC='hackcc -systype bsd43' CCFLAGS='-g' # just an example # export CC CCFLAGS (6) Execute the following commands to unpack and install the shipment: cd \\\$INSTALLROOT nohup ship/shipin & (7) Use shipout within \\\$INSTALLROOT/ship to ship to other machines. \\\$INSTALLROOT/ship/README contains more detailed information. " fi fi typeset -L n='tool ' d='release ' t='type' print "\ This distribution contains: $n$d$t" n=---- d=------- t=---- print "\ $n$d$t" for tool in "${ship_list[@]}" do format=${tool##*/} tool=${tool%/$format} test -r $tool && eval _notes_${tool%%/*}=0 n=${tool%%/*} d=${tool##*/} case $format in base) t="base" ;; $SHIPMENT) t="$format delta" delta=1 ;; *) 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 <<!EOF!"' print "cat $tfile" print 'echo !EOF!' ;; esac } > $mscript ;; esac } function tosys # machine { # construct return mail address typeset IFS=! TOSYS= for i in $@ do TOSYS=$i!$TOSYS 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 for file in $SHIPFILES do if test ! -r "$file" then continue fi v=$(shipstamp $file) if db_check $machine $user $file $v base then continue fi ship_list[i]=$file/$v/base i=i+1 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 ?*) 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 ;; *) case $noexec in "") db_note $machine $user $n $t base $name ;; esac ;; esac elif test -f "$n/$v/base" then if db_check $machine $user $n $v base then case $basetoo in "") continue ;; esac else ship_list[i]=$n/$v/base i=i+1 case $basetoo in "") continue ;; esac fi 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 continue fi ship_list[i]=$tool eval clean_$n= i=i+1 done case $missing in ?*) exit 1 ;; esac if ((j>=i)) then case $total in "") print -u2 "$mail is up to date" ;; *) print -u2 "\n$mail: up to date" ;; esac return 0 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 case $total in ?*) print -u2 "\n$mail:" PS3='' select i in ${ship_list[*]} do : done </dev/null return 0 ;; esac fi return 1 } function sendcontrol # machine user { # $transport the control file to <user> on given <machine> 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 buildscript $machine $user dtime=0 for tool in "${ship_list[@]}" do for i in $tool.??? do case $i in *.\?\?\?) d=50 if test -f $tool then i=$tool j=$tool.000 else # here for $SHIPFILES i=${tool%%/*}; j=$date.$SHIPPER/$i fi;; *.000) j=$i d=50;; *) j=$i d=100;; 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 <recipient> in database and transport software to them # if <open> is given, the database is re-opened addr=$1 case $addr in *:*) transport=rcp mail=$1 host=${addr%:*} machine=$host dir=${addr#*:} user=${dir%%/*} case $user in '~'*) user=${user#~} ;; *) user=$SHIPPER ;; esac ;; *!*) name=${1##*!} transport=uucp ;; *@*) name=${1%%@*} transport=uucp ;; *%compress|*%list|*%pull|*%push) mail=$addr transport=${addr##*'%'} machine=%$transport user=${addr%$machine} dir=. ;; *) 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 compress|list|push) ;; *) print - "umask 02" ;; 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 compress|list) 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 compress|list|push) 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 compress|list|push) print - "$dir/$i/$f" ;; *) print - "> $dir/$i/$f" ;; esac fi done case $transport in compress|list|push) if test -s $i/owner then print - "$dir/$i/owner" fi ;; *) 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 print - "echo \"$owner\" > $dir/$i/owner" ;; esac fi done case $transport in list|push) ;; *) print - "rm -f $dir/ship.$date" ;; esac } | case $transport:$noexec in compress:) cat ;; compress:*) print - "(pax -wv | compress${mail:+" > $mail"}) <<!" 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-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 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 compress) print -u2 "oops: $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 ;; esac fi i=${tool#*/} i=${i%/*} case $user:$noexec in ?*:) db_note $machine $user ${tool%%/*} $i ${tool##*/} $name ;; esac done case $transport in push) print - '!' ;; 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 continue fi case $closure in "") items=$item ;; *) items=$(<$item/$release/items)" $item" ;; esac 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= 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 ;; -C) shift; CRATEFILES="$CRATEFILES $1" ;; -D) shift; delay=$1 ;; +D) delay=0 ;; -F) force=1 ;; +F) force= ;; -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] [-C crate-file] [-D delay] [-S support-file] [recipient ...] [tool ...]"; exit 2 ;; *) break ;; esac shift done case $date in $SHIPMENT) ;; *) date=$(shipstamp) ;; esac 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:*) ;; *) 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 "$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 if test -f shipop.c -a -x shipop then SHIPID=$FROMSYS!$SHIPPER case $SHIPFILES in ?*) SHIPFILES="$SHIPFILES shipop.c" ;; esac else SHIPID= fi 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