# Copyright (c) 1986, 1987 AT&T # All Rights Reserved # THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T # The copyright notice above does not evidence any # actual or intended publication of such source code. #ident "@(#)tapepkg 1.1.2.3" # Script to install/remove multiple packages from SCSI tape. #menu# install/remove packages from SCSI tape. #help# #help# Tapepkg will allow you to install or remove software packages from #help# SCSI tape. You will be asked to select the tape drive to be #help# used and which packages you wish to install (remove) from the tape #help# (the tape is first scanned to determine which packages are #help# contained on it). #help# #help# After selecting the packages to be installed (removed), the packages #help# are then read from the tape and installed (removed). #help# #help# Any packages requiring user interaction will require input at the #help# time of installation. PATH=$PATH:/usr/lbin export PATH set -u export INSTTAPE INSTTAPE= TMPNODE= EC=1 # Default exit condition is ERROR ALL= REBOOT=0 # Default is not re-boot required. P4NAME= LOCK=/tmp/tapelock$$ FILE=/usr/tmp/INSTCMD$$ # file to hold installation/removal commands # (list of files to be installed/removed) trap 'cleanup' 0 1 2 3 15 > $FILE # Zero file echo " \n\n\nColumbia MCC tape load procedure\n\n" cleanup () { # /tmp/$$* catches $$INSTALL rm -f $FILE ${FILE}.ed $LOCK /tmp/$$* /usr/tmp/pkglist $TMPNODE ${TMPNODE}n 2>/dev/null exit $EC } display_1 () { echo "\nFine. Please keep in mind that the following SMSCRC software packages" echo "require operator intervention, even though you have requested that" echo "default responses be used." echo "" echo " 0015AA 10Base5 Network Interface" echo " 0015DA SNA/3270 Emulator" echo " 0015DA BSC/3270 Emulator" echo "" echo "If any of the above packages are contained on your load tape, they" echo "will require you to provide hardware configuration information." } ## Check to see if setup has been run on the machine if [ -s /etc/rc2.d/S00firstcheck ] then echo "The procedure \"setup\" has not been run on this machine." echo "Please run this procedure to initialize the system date and time" echo "before attempting to load software.\n\n" echo "Procedure aborted.\n" exit 1 fi ## Determine how many Prelude packages have been loaded. if [ -f /usr/options/pre-* ] then PRE1=`ls /usr/options/pre-*|wc|cut -c1-7` else PRE1="" fi if ls /tmp/tapelock* 2>/dev/null 1>&2 then echo "\n\n\07 NOTICE: Only one person at a time may install/remove packages from SCSI tape. Someone else is using this command at this time- Try again later.\n\n" cleanup else /usr/bin/id > $LOCK # Set up lock file fi # make sure that partition 4 can be referenced by "devnm / | sed s/s0/s4/" root=`/etc/devnm / | sed 's/ .*//'` case $root in *d0s0) P4NAME=`echo $root | sed s/s0/s4/` break ;; *mir000) /etc/scsi/mirror `echo $root | sed s/dsk/rdsk/` | \ grep '^Disk' >/tmp/$$mirror P4NAME=` while read aline do set -- $aline if [ "$3" = ":" ] then root=\`echo $4 | sed 's/rdsk/dsk/; s/d0s0/d0s4/'\` else root=\`echo $5 | sed 's/rdsk/dsk/; s/d0s0/d0s4/'\` fi if [ ! -b $root -o \`expr $root : '.*d0s4$'\` -eq 0 ] then continue fi if dd if=$root count=1 >/dev/null 2>/tmp/$$dd then echo "1+0 records in\n1+0 records out" >/tmp/$$echo if cmp -s /tmp/$$echo /tmp/$$dd then echo $root break fi fi done < /tmp/$$mirror` if [ -z "$P4NAME" ] then echo ERROR: $0 cannot locate partition 4 on the root device. cleanup fi break ;; *) echo ERROR: $0 cannot determine the root device. A \"devnm /\" should echo have responded with either /dev/dsk/c\?t\?d0s0 or /dev/dsk/mir000. cleanup ;; esac diskumount () { # perform a umount, complain if it doesn't work msg=`/etc/umount ${ddrive} 2>&1` case "${msg}" in '' ) echo "\n\n";; *' busy' ) echo >&2 " The file system is \"busy\" which means that either some command is using files under it or someone is logged in and currently in a directory within the file system." cleanup ;; *' not mounted' ) ;; * ) admerr $0 "/etc/umount got '${msg}'" cleanup;; esac } tinstall () { # Tape install/remove version of sysadm installpkg/removepkg # trap 'EC=0; cleanup' 1 2 15 maxtry=5 ddrive=$P4NAME while true do if readpkg ${INSTTAPE:?} then : else echo "Package read FAILED." cleanup fi fulllabel=`disklabel -y $$ ${ddrive}` fsname= label= eval `labelfsname "${fulllabel}"` if [ "$label" = $1 ] then break # Found it! else maxtry=`expr $maxtry - 1` echo "\nTape out of sync: Looking for $1, read $label" if [ "$maxtry" = 0 ] then echo "Could not recover...\n\n" rewind cleanup else echo "Trying to re-sync the tape..." fi fi done case "${fsname}" in instal | install ) trap 'trap "" 1 2; cd /; diskumount; cleanup' 0 /etc/umount ${ddrive} 2>/dev/null chmod 700 /install if /etc/mount ${ddrive} /install -r then : # OK else cleanup fi ;; * ) echo >&2 ' This removable medium is not labeled properly and will not work.' cleanup ;; esac trap 'trap "" 1 2; cd /; diskumount; cleanup' 0 cd /tmp case $INSTRM in install) if [ ! -r /install/install/INSTALL ] then admerr $0 'Improperly built software removable medium.' diskumount cleanup fi if [ $DEFINS = default -a -s /install/install/DINSTALL ] then cp /install/install/DINSTALL $$INSTALL else cp /install/install/INSTALL $$INSTALL fi;; remove) if [ ! -r /install/install/UNINSTALL ] then echo >&2 ' This package will not remove itself. Consult the instructions that came with the medium.' diskumount return # On to next package in list... fi cp /install/install/UNINSTALL $$INSTALL;; *) echo "ERROR in tinstall/INSTRM case." cleanup ;; esac chmod +x $$INSTALL trap '' 1 2 # Block interrupts if [ "$INSTRM" = install -a -r /etc/coredirs -a ! -f $$installpkg ] then # A problem in cpio makes it change the modes and # ownership of directories it did not create. This trick # records and later restores the existing values. The # directories to be protected are listed in /etc/coredirs. cpio -o $$installpkg 2>/dev/null fi /tmp/$$INSTALL ${ddrive} /install || echo \ 'WARNING: Installation/removal may not have completed properly.' if [ "$INSTRM" = install -a -f $$installpkg ] then # Restore the directory modes and ownerships. cpio -id <$$installpkg >/dev/null 2>&1 fi rm -f $$INSTALL diskumount trap 'cleanup' 0 1 2 } rewind () { # Shell to rewind tape # removes the "n" at the end of the device name # If tape is at BOT, reads until first FILE Mark, then rewinds. if=`echo ${INSTTAPE:?} | sed 's/n$//'` dd if=$if of=/dev/null bs=1 count=1 2>/dev/null # initiate rewind dd if=$if of=/dev/null bs=1 count=1 2>/dev/null # wait for rewind to complete } case `askx -q " Do you wish to install or remove packages?\n" \ -c "install remove quit i r q"` in install|i) INSTRM=install;; remove|r) INSTRM=remove;; quit|q) EC=0; cleanup;; esac DEFINS=nodefault if [ $INSTRM = "install" ] then case `askx -q " Do you wish to use default responses for the software packages?\n" \ -c "yes no quit y n q"` in yes|y) DEFINS=default;; no|n) DEFINS=nodefault;; quit|q) EC=0; cleanup;; esac fi export DEFINS if [ $DEFINS = default ] then display_1 fi echo "\n" INSTTAPE=`selectdevice -q \ "Select the tape drive to use:" -c $$ /dev/rSA qtape` echo "\07 Insert the removable medium for the package(s) you want to $INSTRM into the `basename $INSTTAPE` drive. Press when ready. Type q to quit. \c" read a echo if [ "$a" = q ] then EC=0; cleanup fi # Take the sysadm name and transform it into the /dev/rmt # name with the no-rewind option inode=`ls -i $INSTTAPE | cut -c1-6` newname=`ls -i /dev/rmt | grep "$inode" 2>/dev/null | cut -c7-` if [ -z "$newname" ] then echo "ERROR: cannot determine /dev/rmt name from SA name." cleanup fi # is87-23107 & is87-21901 # Make tape software operate with any tape device TMPNODE=/tmp/${newname} ls -og /dev/rmt/${newname}n | \ ( IFS=",$IFS" read perm links major minor otherstuff /etc/mknod $TMPNODE c $major 0 /etc/mknod ${TMPNODE}n c $major 1 ) INSTTAPE=${TMPNODE}n # # Remove package list and try to read it from the tape... rm -f /usr/tmp/pkglist 2>/dev/null cd /usr/tmp; cpio -ic \*pkglist < $INSTTAPE >/dev/null 2>&1 if [ $? = 1 ] then echo "\n\n\ The medium may not be properly inserted. Re-insert the medium and try again.\n\n" cleanup fi if [ ! -f /usr/tmp/pkglist ] then # read of pkglist from tape failed... rewind and try again. rewind dd if=$INSTTAPE of=/dev/null bs=9k 2>/dev/null # Skip file dd if=$INSTTAPE of=/dev/null bs=9k 2>/dev/null # Skip file cpio -ic \*pkglist < $INSTTAPE >/dev/null 2>&1 if [ ! -f /usr/tmp/pkglist ] then echo "\07\nRead of tape package header FAILED.\n"; cleanup fi fi NPKGS=`cat /usr/tmp/pkglist | wc -l` > $FILE for pkg in `cat /usr/tmp/pkglist` do echo $pkg | sed 's/=/ /g' | sed 's/.*%\(.*\)%\(.*\)%\(.*\)%.*$/skip \1 # \2 # RB=\3/' >> $FILE done while true do INVALID=false > ${FILE}.ed echo "\n\nPackages available:\n" cat /usr/tmp/pkglist | sed 's/%.*$//' | pr -2tn5w80 | sed 's/=/ /g' echo "\n\07Enter selection(s) to $INSTRM [all help quit]: \c" read a if [ ! "$a" ] then echo >&2 "\n\07You must enter something." a=help fi for i in $a do case $i in [1-9] | [0-9][0-9]) # Normal number if [ "$i" -gt "$NPKGS" ] then echo >&2 "\n\07Choice ($i) out of range." INVALID=true; break fi echo "${i}s/skip[^#]*#/tinstall/" >> ${FILE}.ed ;; [1-9]-[1-9] |\ [1-9]-[0-9][0-9] |\ [0-9][0-9]-[0-9][0-9]) # Range eval `echo $i | sed 's/\(.*\)-\(.*\)$/start=\1 end=\2/'` if [ "$start" -gt "$end" ] then echo >&2 "\n\07Invalid range: $i" INVALID=true; break fi if [ "$end" -gt "$NPKGS" ] then echo >&2 "\n\07Invalid range: $i" INVALID=true; break fi j=$start while [ "$j" -le "$end" ] do echo "${j}s/skip[^#]*#/tinstall/" >> ${FILE}.ed j=`expr $j + 1` done ;; all|ALL) # all choices j=1 while [ "$j" -le "$NPKGS" ] do echo "${j}s/skip[^#]*#/tinstall/" >> ${FILE}.ed j=`expr $j + 1` done ;; q|quit|Q|QUIT) echo "\n\n\07QUIT- Nothing ${INSTRM}ed.\n" EC=0; cleanup ;; h|help|H|HELP|?) echo "\n\n\ Enter the number(s) of the packages you wish to install/remove. You may enter: o numbers seperated by spaces (eg. 1 4 10) o ranges of numbers (eg. 4-9) o combinations of numbers and ranges (eg. 1 3 10-15) o all - $INSTRM all packages o quit - do not $INSTRM anything Enter to continue: \c" read a INVALID=true; break ;; *) echo >&2 "\n\07Invalid input: $i" INVALID=true; break ;; esac done if [ "$INVALID" = false ] then break fi done echo "\$a\nskip rope\n.\n\$\n?^tinstall?ka\n'a,\$s/^skip/delete/\ng/^delete/d\nw\nq" >> ${FILE}.ed cat ${FILE}.ed | ed - $FILE >/dev/null 2>&1 echo "rewind" >> $FILE # Rewind tape when done installing/removing echo "\n\nSelection complete--- ${INSTRM}pkg starting.\n\n" # Execute the file containing commands for installation/removal... . $FILE if grep "tinstall.*RB=2" $FILE > /dev/null 2>&1 then REBOOT=2 elif grep "tinstall.*RB=1" $FILE > /dev/null 2>&1 then REBOOT=1 else REBOOT=0 fi case $REBOOT in 0) #No re-boot necessary ;; 1) #init 6 required echo "\n\nExecute \"cd /; shutdown -i6 -g0 -y\" and" echo "wait for the \"Console Login:\" prompt." ;; 2) #init 0 required on removepkg, init 6 on installpkg if [ "$INSTRM" = install ] then echo "\n\nExecute \"cd /; shutdown -i6 -g0 -y\" and" echo "wait for the \"Console Login:\" prompt." else echo "You have requested the removal of a package that" echo "contains a hardware device. If the removal of the" echo "software has completed successfully, you now need" echo "to remove associated the hardware." echo "\n\nExecute \"cd /; shutdown -i0 -g0 -y\" and" echo "wait for the machine to power down- then remove the" echo "hardware." fi ;; *) echo "An error has occured within the $0 command." cleanup ;; esac ## Determine how many Prelude packages have been loaded during this session ## if [ -f /usr/options/pre-* ] then PRE2=`ls /usr/options/pre-*|wc|cut -c1-7` > /dev/null 2>&1 else PRE2="" fi ## ## Execute pradmin to rebuild the Prelude menus if Prelude packages have been ## loaded during this session if [ $DEFINS = default -a "$PRE1" != "$PRE2" ] then echo "\nRebuilding Prelude menu for newly installed Prelude software." /usr/bin/pradmin <<-EOFX >/dev/null 2>&1 in q EOFX fi echo "\07\n\nThe ${INSTRM}pkg from SCSI tape has completed-\ \nYou may remove the tape after the rewind is complete.\n\n" EC=0; cleanup