#!/bin/sh

# need tape devices, /dev/null, /dev/tty, /tmp, /var
#
# dopackage  $Usage
#
# -t	tapenum		which tape is currently in drive
# -f	tapename	[hostname:]device	 $TAPE or  /dev/nrst0
# -c	client		hostname of client	
# -i	info file directory			/var/packages
# -F	force ``space'' ``command'' ``save'' ``defaults'' 
#	or all [keyword ``all''] multiple -F allowed
#		ie don't check disk space 
#		continue even with 
#		{Pre,Post}command errors 
#		or errors saving old files
#		use defaults from PDF, don't prompt for dirs/vars
#						off
# -R	/root/path
#	Path to prefix to all directories that we're to extract files
#	into.
#
# NOTE:	functions are expected to print errors and return non-zero
# status
# directory names can be /dev/null to stop file installation.
# NOTE:  this is dangerous if pre/post commands use that dir 
# 
# assumptions:  
#	always run on server, client name specified with -c
#
# log and error report in $Idir/$Ppartnum.{Errors,Log}
#	
#

PATH=/usr/etc/packages:/bin:/usr/bin:/usr/ucb:/etc:/usr/etc:`pwd`

#
# Global variables
#


Myname=`basename "$0"`
Usage="[-f [host:]tape] [-c client] [-i info-file-dir] [-F {space,command,save,defaults,all}] [-t tapenum] [-R /root/path] PDF-base ..."

Here=`pwd`

Force=
Client=

Host=`hostname`
if [ "$Host" = "" ]; then Host=localhost ; fi

Rootpath=
Rhost=
Idir=/var/packages
Elog=/tmp/Errors		# in case no partnumber found
Log=/tmp/Log			# in case no partnumber found
Cpio=/tmp/cpio$$		# for dir saving
Toc=/tmp/toc$$
Pdfs=
Local=n				# if `y', then don't go to tape for toc/pdfs
Error=
From_Disk=0			# `1' if installing from a disk package

OldStty=/tmp/stty$$

				# files removed on exit

main()
{
Files="$Toc $Cpio"
trap "rm -f $Files; quit 1" 1 2 15
	#
	# handle ^c correctly, even in single user mode
	#
	# in 4.0.*, stty output to stderr, but in 4.1 it goes
	# to stdout.  gratuitous changes....
	#
	stty -g > $OldStty
	if [ -t 1 ]
	then
		stty isig
	fi

	Tnum=32767
	fullname=$0
	while getopts f:c:i:F:t:R: arg
	do
		case "$arg" in
		R)
			Rootpath="$OPTARG"
			;;
		t)
			Tnum="$OPTARG"
			;;
		f)
			Tape="$OPTARG"
			#
			# parse Tape to /dev/n<sometapename>, sets Rhost
			#
			parsetape
			if [ $? -ne 0 ]
			then
				quit 1
			fi
			;;
		c)
			Client="$OPTARG"
			;;
		i)
			Idir="$OPTARG"
			if [ ! -d $Idir ]
			then
				usage
			fi
			;;
		F)
			case $OPTARG in
			space | command | save | defaults)
				Force="$Force $OPTARG"
				;;
			all)
				Force="space command save defaults"
				;;
			*)
				usage
				;;
			esac
			;;
		esac
	done
	shift `expr $OPTIND - 1`

	if [ $# -eq 0 ]
	then
		usage
	fi

	Pdfs="$*"

	#
	# check to make sure i can write to
	#

	if [ ! -w . ]
	then
		error "must have write permissions for `pwd`"
		quit 1
	fi

	#
	# if -f wasn't specified
	# use environment var if set, else default 
	#
	if [ "$Tape" = "" ]
	then 
		if [ "`printenv TAPE`" = "" ] 
		then
			Tape=/dev/nrst0
			echo "Using default tape /dev/nrst0"
		else
			Tape=$TAPE
			echo "Using environment variable TAPE ($Tape)"
			parsetape $Tape
			if [ $? -ne 0 ]
			then
				quit 1
			fi
		fi
	fi


	if [ ! -d $Idir ]
	then
		mkdir -p $Idir
		if [ $? -ne 0 ]
		then
			error "unable to create $Idir"
			quit 1
		fi
	fi

	rm -f $Idir/Bogon-list

	if [ $From_Disk -eq 1 ]
	then
		map_files
	fi

	for i in $Pdfs
	do
		#
		# initialize the world
		#
		PDF=$i

		VarList=$PDF.varlist
		TarList=$PDF.tarlist
		PreCmdFile=$PDF.precmd
		PostCmdFile=$PDF.postcmd
		NoteFile=$PDF.notelist
		NewDirs=$PDF.newdirs
		DelModRepAddFile=$PDF.delmodrepadd
		AdminList=$PDF.admin

		IdFile=$PDF.id

		. $IdFile

		sed < $VarList -e 's/client _X-X-X_ //' \
		    -e 's/\([^ ]*\) \(.*\)/\1=\2; export \1/' > /tmp/sed.$$
		. /tmp/sed.$$
		rm -f /tmp/sed.$$

		Elog=$Ifile.Errors
		Log=$Ifile.Log

		Files="$PreCmdFile $PostCmdFile $VarList $TarList $Toc"
		Files="$Files $NoteFile $NewDirs $Cpio $DelModRepAddFile"
		Files="$Files $AdminList $IdFile"

		trap "rm -f $Files; quit 1" 1 2 15

		echo "Installing $Pname"
		echo ""

		if [ -f $Elog ]
		then
			cat $Elog >> $Elog- 2>/dev/null
			if [ $? -ne 0 ]
			then
				error "Cannot append to $Elog-, previous error messages lost"
			fi
			rm -f $Elog
		fi

		if [ -f $Log ]
		then
			cat $Log >> $Log- 2>/dev/null
			if [ $? -ne 0 ]
			then
				error "Cannot append to $Log-, previous log messages lost"
			fi
			rm -f $Log
		fi

		Touched=0	# true once i start pre commands or tars
		DidPre=0
		DidPost=0
		TrustMe=1	# used for error reports
		AnyToSave=0
		if [ -s $DelModRepAddFile ]
		then
			AnyToSave=1
		fi

		installpkg

		if [ X$Error = X3 ]
		then
			echo log $Log >> $Idir/Bogon-list
			echo err $Elog >> $Idir/Bogon-list
		fi
	done

	quit $Error

}

installpkg()
{
	trap "backout 9" 1 2 15
	
	#
	# do precommands from the pdf
	#
	if [ -s $PreCmdFile ]
	then
		DidPre=1
		commands Pre $PreCmdFile
		if [ $? -ne 0 ]
		then
			Error=3
			case "$Force" in
			*command*)
				error "continuing due to -F flag"
				TrustMe=0
				;;
			*)
				backout
				return
			esac
		fi
	fi

	# 
	# save the 'modified,replaced,deleted' files
	#
	if [ $Save -eq 1 -a $AnyToSave -eq 1 ]
	then
		Touched=1
		save
		if [ $? -ne 0 ]
		then
			Error=3
			case "$Force" in
			*save*)
				error "continuing due to -F flag"
				echo "continuing due to -F flag" >>$Elog
				;;
			*)
				backout
				return
				;;
			esac
		fi
	fi

	#
	# everything looks good, extract the package from the tape
	#
#	export Tapeid
	exec 3<$TarList
	while read dir tnum loc size varname 0<&3
	do
		case "`eval echo $dir`" in
		/dev/null*)
			echo "###" >> $Log
			echo "###	$varname files skipped" >> $Log
			echo "###	`date '+%h %d %T'`" >> $Log
			echo "###" >> $Log
			echo "	Skipping $varname files"
			;;
		*)
			Touched=1
			if [ $tnum -ne $Tnum ]
			then
				Tnum=$tnum
				gettape `expr $tnum + 1`
				if [ $? -ne 0 ]
				then
					backout
					quit 1
				fi
				echo 
			fi
			eval dotar $dir $loc $varname
			;;
		esac

		if [ $? -ne 0 ]
		then
			Error=3
			backout
			return
		fi
	done

	echo 

	#
	# do the deleted files
	#
	if [ -s $DelModRepAddFile ]
	then
		echo "	Removing obsolete files"
		echo "###"	>> $Log
		echo "###	Removing obsolete files" >>$Log
		echo "###"	>> $Log
		exec 3<$DelModRepAddFile
		while read cmd name 0<&3
		do
			case "$cmd" in
			del*)
				eval echo "deleted	$name" >> $Log
				eval rm -rf $name
				;;
			*)
				;;
			esac
		done
	fi

	#
	# do the postcommands from the pdf
	#
	if [ -s $PostCmdFile ]
	then
		DidPost=1
		commands Post $PostCmdFile
		if [ $? -ne 0 ]
		then
			echo "	Post Commands Failed" 2>&1
			TrustMe=0
		fi
	fi

	infofile
	s=$?

	#
	# display Note messages if necessary
	#
	if [ -s $NoteFile ]
	then
		notes
	fi

	if [ $TrustMe -eq 0 ]
	then
		error "errors encountered, package $Pname only partially installed"
		echo "errors encountered, package $Pname only partially installed" >>$Elog
		Error=3
	elif [ "$s" != 0 ]
	then
		error "package $Pname installed, $Ifile not complete"
		echo "package $Pname installed, $Ifile not complete" >>$Elog
	else
		echo "Package $Pname successfully installed"
	fi	

	rm -f $Files

	return 0
}
   
# 
# parsetape()
# get hostname: from tape, ensure norewind device
#
parsetape()
{
	if [ "`expr \"$Tape\" : '.*\(:\)'`" = ":" ]
	then
		Rhost="`expr \"$Tape\" : '\(.*\):'`"
		Tape="`expr \"$Tape\" : '.*:\(.*\)'`"
	fi

	case "$Tape" in
	/dev*/nr*)
		;;
	/dev*/r*)
		Tape="/dev/n`expr \"$Tape\" : '\/dev\/\(.*\)'`"
		;;
	/dev*/*)
		Tape="/dev/nr`expr \"$Tape\" : '\/dev\/\(.*\)'`"
		;;
	*)
	#	error "'$Tape' illegal, tape must be explicit (/dev/...)"
	#	return 1
	#	;;
		if [ -d $Tape -a -f $Tape/TOC -a "X$Rhost" = X ]
		then
			From_Disk=1
		else
			error "'$Tape' is not valid"
			return 1
		fi
	esac
	
}

# 
# notes()
# print notes.  notes are printed if variable or directory are other
# than default.
#
# The rigamarole with the ``echo | while read ...'' is to duplicate
# the special-character-stripping and quoting and such performed in
# the original dopackage.  Apparently read is the only way to strip
# out a single set of backslashes, and you can't just ``echo xxx |
# read''.  This doesn't seem particularly elegant, but it works.
#
notes()
{
	echo "###" >> $Log
	echo "###" >> $Log
	echo "###	Installation Notes" >> $Log
	echo "###" >> $Log

	exec 3<$NoteFile
	while read name key junk def rest 0<&3
	do
		real=`eval echo $"$name"`
		case "$key" in
		a)
			default=$def
			echo "###" >> $Log
			echo -n "###	Note relevant to $name" >> $Log
			if [ X$real = X/dev/null ]
			then
				echo -n " (not installed)" >> $Log
			fi
			echo >> $Log
			echo "###" >> $Log
			echo
			echo NOTE
			echo
			;;
		note)
			if [ ! "$real" = "$default" ]
			then
				echo $def $rest | while read def1 rest1
				do
					echo -n "    "
					eval echo $def1 $rest1
					echo -n "	" >> $Log
					eval echo $def1 $rest1 >> $Log
				done
			fi
			;;
		esac
	done
	echo 
	echo "###" >> $Log
	echo "###	End of Installation Notes" >> $Log
	echo "###" >> $Log
}

#
# checktape()
# make sure a tape is in the drive get the toc 
# make sure toc says its tape $1 unless $1 = first
# then just read the first file and return
#
# silently return 2 on tape number error 
#
checktape()
{
	echo "Checking tape: ${Rhost:+$Rhost:}$Tape"

	s=1
	while [ $s -ne 0 ]
	do
		position_tape rew
		s=$?
		if [ "$s" != 0 ]
		then
			error "${Rhost:+$Rhost:}$Tape: cannot rewind, tape in drive?"
			echo "${Rhost:+$Rhost:}$Tape: cannot rewind, tape in drive?" >>$Elog
			echo
			if [ $1 = first ]
			then
				echo "Insert tape number 1 in ${Rhost:+$Rhost:}$Tape " >/dev/tty
			else
				echo "Insert tape number $1 in ${Rhost:+$Rhost:}$Tape " >/dev/tty
			fi
			echo -n "			then press carriage return " >/dev/tty
			read foo
		fi
	done

	#
	# get toc
	# errors checked by looking at $Toc
	#
	if [ "$Rhost" = "" ]
	then
		if [ $From_Disk -eq 1 ]
		then
			cp $Tape/TOC $Toc
		else
			dd if=$Tape of=$Toc 2>/dev/null
		fi
	else
		rsh -n $Rhost "/bin/sh -c 'dd if=$Tape 2>/dev/null'" | dd of=$Toc 2>/dev/null
	fi

	if [ ! -f $Toc ]
	then
		error "dd failed: cannot read table of contents from ${Rhost:+$Rhost}$Tape"
		echo "dd failed: cannot read table of contents from ${Rhost:+$Rhost}$Tape" >>$Elog
		return 1
	fi

	if [ "$1" = first ]
	then
		echo \"checktape first\" occurred
		return 0
	fi

	#
	# Look for package name in toc.  If found, check partnumber.
	#
	echo "Checking table of contents from ${Rhost:+$Rhost:}$Tape"

	Tapeid=`egrep "^tapeid" $Toc`
	if [ "$Tapeid" = "" ]
	then
		error "$Toc: not a Table of Contents "
		echo "$Toc: not a Table of Contents " >>$Elog
		return 3
	fi

	Tapenum=`echo $Tapeid | awk '{n=split($2,a,"-");t=a[n-1]+1; print t}'`
	if [ "$Tapenum" -ne $1 ]
	then
		return 2
	fi

	exec 4<$Toc

	found=0
	while read key name 0<&4
	do
		case "$key" in
		package)
			if [ "$name" = "$Pname" ]
			then
				found=1
			fi
			;;
		partnumber)
			if [ $found -eq 1 ]
			then
				if [ "$name" != "$Partnum" ]
				then
					error "expected partnumber '$Partnum', found '$name'"
					echo "expected partnumber '$Partnum', found '$name'" >>$Elog
					return 1
				else
					return 0
				fi
			fi
			;;
		*)
			;;
		esac
	done

	#
	# if i get here i didn't find Pname in toc
	#
	error "did not find package $Pname in table of contents from ${Rhost:+$Rhost:}$Tape"
	echo "did not find package $Pname in table of contents from ${Rhost:+$Rhost:}$Tape" >>$Elog

	return 1
}

#
# gettape()
# ask for $1 tape in package
# try to be a bit smart - if asking for tape 1 check it first.
#
gettape()
{
	if [ $From_Disk -eq 1 ]
	then
		return 0
	fi

	# if asking for tape 1 check it first - it is probably already
	# in the drive
	if [ $1 -eq 1 ]
	then
		checktape 1 1>/dev/null
		s=$?
		if [ $s -eq 0 ]
		then
			return
		elif [ $s -ne 2 ]	# 2 means i didn't find tape $1
		then
			return $s
		fi
	else
		# rewind the last tape before asking for new one
		position_tape rew
	fi

	s=2
	while [ $s -eq 2 ]
	do
		echo
		echo "Insert tape number $1 in ${Rhost:+$Rhost:}$Tape " >/dev/tty
			echo -n "			then press carriage return " >/dev/tty
		read foo

		#
		# check that tape is what i expect 
		#
		checktape $1
		s=$?
		if [ $s -eq 2 ]
		then
			error "${Rhost:+$Rhost:}$Tape has tape number $Tapenum"
		fi
	done
	return $s
}

#
# dotar()
#
dotar()
{
	# echo "	Stubbing installation of $3 files"
	# return 0

	echo "###"	>> $Log
	echo "###	$3 files installed in $1" >> $Log
	echo "###	`date '+%h %d %T'`" >> $Log
	echo "###"	>> $Log

	if [ $From_Disk -eq 1 ]
	then
		if [ "X$Map_file" = X ]
		then
			error "No mapping file defined"
			return 1
		fi

		From_file=`egrep "^$2 " $Map_file | awk '{print $2}' | head -1`
		if [ "X$From_file" = X ]
		then
			error "Could not get path for $3 archive"
			return 1
		fi

		echo "  Extracting $3 files from $From_file"
	else
		echo "	Positioning tape to beginning of $3 files"

		s=1
		while [ $s -ne 0 ]
		do
			position_tape $2
			s=$?
			if [ $s -ne 0 ]
			then
				error "${Rhost:+$Rhost:}$Tape unable to access file $2"
				echo "${Rhost:+$Rhost:}$Tape unable to access file $2" >>$Elog
				gettape `expr $Tnum + 1`
			fi
		done
	fi

	if [ "x$Rootpath" != x ]
	then
		echo "	Installing $3 files in" `echo $1 | sed "s@$Rootpath@@"`
	else
		echo "	Installing $3 files in $1"
	fi

	cd $1
	if [ "$Rhost" = "" ]
	then
		if [ $From_Disk -eq 1 ]
		then
			tar xepbf 16 $From_file >> $Log 2>> $Elog
			s=$?
		else
			tar xepbf 16 $Tape >> $Log 2>> $Elog
			s=$?
		fi

		if [ $s -ne 0 ]
		then
			error "tar of $1 files failed"
			echo "tar of $1 files failed" >>$Elog
			cd $Here
			return 1
		fi
	else
		rsh -n $Rhost dd if=$Tape bs=8192 2>/dev/null \
			| (tar xepBf - >> $Log 2>> $Elog || exit 1; \
			   dd of=/dev/null bs=8192 2>/dev/null)
		if [ $? -ne 0 ]
		then
			error "tar failed: $3 files into $1"
			echo "tar failed: $3 files into $1" >>$Elog
			cd $Here
			return 1
		fi
	fi

	cd $Here
	return 0
}

#
# commands()
# do variable subsitution then execute the {Pre,Post}commands found in pdf
# $1 is type of commands, pre or post, $2 is name of commands file
#
commands()
{
	echo "	Executing $1 Commands"
	File=$2
	err=0

	echo "###" >> $Log
	echo "###	$1 Commands Executed"  >> $Log
	echo "###	`date '+%h %d %T'`" >> $Log
	echo "###" >> $Log

	exec 3<$File
	while read line 0<&3
	do
		eval echo '$line' >> $Log
		echo -n "###	command: " >> $Elog
		eval echo '$line' >> $Elog
		eval sh -ec '"$line"' 2>> $Elog
		if [ $? -ne 0 ]
		then
			error failed executing $1 command 
		#	eval echo `date '+%h %d %T'` " :: executing :: " '$line' >> $Elog
			echo "###	command FAILED" >> $Elog
			err=1
		fi
	done
			
	return $err
}

# 
# save()
# save deleted, modified, or replaced files
#
save()
{
	echo "  Looking for files to preserve"

	err=0
	export err
	exec 3<$DelModRepAddFile

	while read cmd name 0<&3
	do
		case $cmd in
		del* | mod* | rep* )
			files=`eval echo $name`
			for i in $files 
			do
				if [ -d $i -a ! -d $i.last ]
				then
					echo $i | cpio -o > $Cpio 2>/dev/null
					mv $i $i.last
					if [ $? -ne 0 ]
					then
						error "cannot save $i"
						echo "cannot save $i" >>$Elog
						err=1
					else
						cpio -id < $Cpio 2>/dev/null
					fi
				elif [ -r $i -a ! -r $i.last ]
				then
					cp -p $i $i.last
					if [ $? -ne 0 ]
					then
						error "cannot save $i"
						echo "cannot save $i" >>$Elog
						err=1
					fi
				fi
			done
			;;
		*)
			;;
		esac
	done

	echo "  File preservation complete"
	return $err
}

#
# backout()
# attempt clean backout
# tell usr to see log and error files if anything was touched
#
# if called from trap $1 == 9 so quit after cleanup instead of return
#
backout()
{
trap "echo; echo 'Interrupts disabled' " 1 2 15

	echo 
	#
	# check for $Touched in case called from trap
	#
	if [ $Touched -eq 0 ]
	then
		echo "Package $Pname not installed"
		cleanup 1
		if [ "$1" -eq 9 ]
		then
			quit 1
		else
			return
		fi
	fi

	if [ $Save -eq 0 ]
	then
		error "Package $Pname partially installed"
		error "Previous version not saved, so cannot backout"
		echo "Package $Pname partially installed" >>$Elog
		echo "Previous version not saved, so cannot backout" >>$Elog
		if [ -f $Elog ]
		then
			echo "See error report $Elog"
		fi
		if [ -f $Log ]
		then
			echo "See log file $Log"
		fi
		cleanup 2
		if [ "$1" -eq 9 ]
		then
			quit 1
		else
			return
		fi
	fi

	echo "Backing out of package $Pname "
	echo 
	exec 3<$DelModRepAddFile
	while read cmd name 0<& 3
	do
		case "$cmd" in
		add*)
			eval rm -f $name
			;;
		del* | rep* | mod*)
			files=`eval echo $name`
			for i in $files 
			do
				if [ -r $i.last ]
				then
					mv -f $i.last $i
				fi
			done
			;;
		*)
			;;
		esac
	done

	if [ $DidPre -eq 1 ]
	then
		dolog Pre $PreCmdFile
	fi
	
	if [ $DidPost -eq 1 ]
	then
		dolog Post $PostCmdFile
	fi

	if [ -f $Elog ]
	then
		echo "See error report $Elog"
	fi

	if [ -f $Log ]
	then
		echo "See log file $Log"
	fi

	cleanup 2
	if [ "$1" -eq 9 ]
	then
		quit 1
	else
		return
	fi
}

#
# dolog()
# prints {Pre,Post}commands to Elog, called by backout()
#
dolog()
{
	if [ -f $2 ]
	then
		echo "###" >> $Elog
		echo "###	$1 Commands Executed, not recovered" >> $Elog
		echo "###	`date '+%h %d %T'`" >> $Elog
		echo "###"	>> $Elog
		cat $2 >> $Elog
	fi
}

#
# infofile()
# create or add to an info file for this package
#
infofile()
{
trap "return 1" 1 2 15

	echo 
	echo "	Writing Info File: $Ifile"
	if [ "$Client" = "" ]
	then
		Client=$Host
	fi

	if [ ! -f $Ifile ]
	then
		echo "dopackage" > $Ifile
		egrep '^id|^package|^release|^version|^patch|^partnumber' \
			$AdminList >> $Ifile

		if [ $? -ne 0 ]
		then
			error "error creating $Ifile"
			echo "error creating $Ifile" >>$Elog
			return 1
		fi
	fi

	echo "$Tapeid" >> $Ifile

	#
	# add the dir and var lines
	# 
	sed -e s,_X-X-X_,$Client, $VarList >> $Ifile

	echo "updated $Client `date +%y%m%d`" >> $Ifile

	#
	# do a checksum for addpackage, showpackage
	# so they will have checkpoints
	#
	echo "sum `sum $Ifile`" >> $Ifile

	return $?
}

#
# yesno()
# askfor for yes or no to prompt sent as $1
# return 0 for yes, 1 for no. will not return until answer given.
#
yesno()
{
	_ans=
	while [ "$_ans" = "" ]
	do
		echo -n "$1" '(yes or no) [default = yes]: ' > /dev/tty
		read _ans
		case "$_ans" in
		yes | y )
			return 0
			;;
		no | n)
			return 1
			;;
		"")
			return 0
			;;
		*)
			_ans=
			;;
		esac
	done
}

#
# cleanup()
# do final cleanup
cleanup()
{
	# i created them - don't leave anything
	if [ -f $NewDirs ]
	then
		rm -rf `cat $NewDirs`
	fi

	rm -f $Files

	return
}

#
# error() prints an error message to stderr
#

error()
{
	echo "$Myname: $*" 1>&2
}

#
# position_tape()
# position tape to file $1 unless $1 = rew
# 
position_tape()
{
	if [ $From_Disk -eq 1 ]
	then
		return 0
	fi

	if [ $1 = rew ]
	then
		if [ "$Rhost" != "" ]
		then
			s=`rsh -n $Rhost "/bin/sh -c 'mt -f $Tape rew 1>/dev/null 2>&1; echo \\\$?'"`
		else
			mt -f $Tape rew 1>/dev/null 2>&1
			s=$?
		fi
		return $s
	fi

	#
	# position tape to file $1, try asf first if it fails try rew,fsf
	#
	if [ "$Rhost" != "" ]
	then
		s=`rsh -n $Rhost "/bin/sh -c 'mt -f $Tape asf $1 1>/dev/null 2>&1; echo \\\$?'"`
		if [ "$s" != 0 ]
		then
			s=`rsh -n $Rhost "/bin/sh -c 'mt -f $Tape rew 1>/dev/null 2>&1; mt -f $Tape fsf $1 1>/dev/null 2>&1; echo \\\$?'"`
		fi
	else
		mt -f $Tape asf $1 1>/dev/null 2>&1
		s=$?
		if [ $s -ne 0 ]
		then
			mt -f $Tape rew 1>/dev/null 2>&1
			mt -f $Tape fsf $1 1>/dev/null 2>&1
			s=$?
		fi
	fi

	return $s
}

#
# usage() prints a usage message (usage is in the variable Usage)
# and quit.
#
usage()
{
	echo "usage: $Myname $Usage" 1>&2
	quit 2
}

#
# quit() restores the tty and exits with $1 status
#
quit()
{
	# reset tty to old vals.
	if [ -t 1 ]
	then
		stty `cat $OldStty`
	fi

	if [ -f $Here/PDFnuke ]
	then
		rm -f `cat $Here/PDFnuke`
	fi

	if [ $From_Disk -eq 1 ]
	then
		rm -f $Map_file
	fi

	rm -f $OldStty
	exit $1
}

#
# map_files() creats a file that maps tape position numbers into path
# names, for installing from disk rather than tape.
#
map_files()
{
	if [ $From_Disk -eq 0 ]
	then
		error "map_files called when not coming from disk"
		cleanup
		quit 1
	fi

	id=`egrep "^tapeid" $Tape/TOC`
	Map_file=$Idir/--map--`echo $id | awk '{print $NF}' | tr / -`-$$
	rm -f $Map_file
	exec 4<$Tape/TOC
	is_special=0
	while read key name tar_path 0<&4
	do
		case "$key" in
		special)
			is_special=1
			;;
		start)
			num=`echo $name | tr - /`
			num=`basename $num`
			echo $num $Tape/$tar_path $is_special >> $Map_file
			is_special=0
			;;
		esac
	done

	cp $Map_file $Map_file-1
	exec 4<$Map_file-1
	while read toc_file toc_path is_special 0<&4
	do
		if [ $is_special = 0 ]
		then
			exec 5<$toc_path
			while read key name1 name2 size tar_path 0<&5
			do
				case "$key" in
				position)
					num=`echo $name2 | tr - /`
					num=`basename $num`
					echo $num $Tape/$tar_path 0 >> $Map_file
					;;
				esac
			done
		fi
	done
	rm -f $Map_file-1
}

main ${1+"$@"}
exit 0
