V10/cmd/odist/pax/ship/shipout
:
# @(#)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