Newsgroups: comp.sources.unix
From: rca@ingres.com (Bob Arnold)
Subject: v28i068: saenv_alldisks - sysadmin env, disk management and backups, Part04/06
References: <1.771948808.8446@gw.home.vix.com>
Sender: unix-sources-moderator@gw.home.vix.com
Approved: vixie@gw.home.vix.com

Submitted-By: rca@ingres.com (Bob Arnold)
Posting-Number: Volume 28, Issue 68
Archive-Name: saenv_alldisks/part04

#!/bin/sh
# this is saenv_alld.04 (part 4 of saenv_alld)
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/backup/doc/alld.notes continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 4; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
	echo 'x - still skipping src/backup/doc/alld.notes'
else
echo 'x - continuing file src/backup/doc/alld.notes'
sed 's/^X//' << 'SHAR_EOF' >> 'src/backup/doc/alld.notes' &&
Xcan't really be done using a macro, so we have to build a script.
XOne big advantage of doing this is that the backup.dd script can
Xbe counted on to give consistent output, which means I can eliminate
Xa lot of error checking code in the alldisks script itself.
X
XData capacities and sustained data transfer rates for various types 
Xof tape drives, *without compression*:
X					sustained
X	inter-	tape		capac-	transfer
Xtype	face	model	length	ity	rate (k/sec)
X------	------	------	------	---------------------------
X9track	pertec		2400'	150M	 500-750 (625/768/...)
X9track	scsi		2400'	150M	 500-750
Xdat	hpib		60m	1.3G	 183
Xdat	scsi		60m	1.3G	 183
Xdat	scsi		90m	2.0G	 183
X8200	scsi		112m	2.0G	 246
X8500	scsi		112m	5.0G	 500
Xqic11	scsi		600'	 25M
Xqic24	scsi		600'	 42M
Xqic60	scsi		600'	 60M
Xqic120	scsi		600'	120M	  90
Xqic150	scsi	DC600A	600'	150M	 112
Xqic250	scsi		1020'	250M	
Xqic320	scsi	DC6320	620'	320M	 200?
Xqic525	scsi	DC6525	1020'	525M	 240
Xqic555m	scsi			580M	 200
Xqic1000	scsi			1.2G	 300
Xqic1350	scsi			1.3G	 300
Xqic2gb	scsi			2.5G	 300
X3480	scsi		 	220M	1500
X
XSpecial requirements for DG's DG/UX SVR4:
X1) "dump2" oddities:
X* It takes "-flag arg" options in addition to the traditional dump key method.
X* It doesn't report a "Phase III" or "Phase IV" when writing to the media.
X* It supports operator input via named pipes (the -O flag), and other input.
X* It says "change tapes" (lower case 'c' and 't').
X* The first field of /etc/dumpdates is free form, not fixed width.
X* It handles EOT for cart and video drives, simply asking for the next tape!!!
X  However, if it hits EOT while doing network backups using remote /dev/rmt
X  devices, the /etc/rmt on the remote host will quietly drop a 50block buffer
X  which dump2 on the local host sent to be written to the /dev/rmt tape drive.
X2) Network backups which hit EOT should use no-cache "pmt" pseudo tape drives
XThese act like they work great when writing to "rmt" devices on the remote
Xmachine, but when you go to restore the data you will probably discover
Xthat "50 blocks" or so of data have been lost out of the middle of the dump.
XThe reason is that /etc/rmt on the remote host buffers data, and when it
Xhits EOT, it has nowhere to put the cache and drops it on the floor.
XIn the meantime, /etc/rmt also tells "dump2" that it has hit EOT, so
X"dump2" simply asks the operator to change tapes.  The solution is to
Xuse local, *un-cached*, pseudo tape devices (/dev/pmt/*), which are
Xconfigurable on the local host's /etc/pmttapetab file; these devices
Xare not truly local, but it looks like it to the local machine because
Xit has the /dev/pmt devices.  You must use "N" in the cache filed.
X3) Local backups using 'alldisks' to a local DAT drive require the addition
Xof a "dat" entry to /etc/dumptab; this is taken care of by the installation
Xscripts, but note that it does assume the DAT is a 2Gig device.
X
XTandem's NonStop-UX 4.0 oddities:
XIt has two filesystem types, ufs and vxfs, which use ufsdump/vxfsdump
Xand ufsrestore/vxrestore respectively.  See also the section in this
Xfile on restore's exit status.
X
XIBM AIX 3.X RS/6000 Exabytes:
X1) To list the available tape drives:
X	lsdev -C -H -c tape
X2) To list the effective attributes of a tape drive:
X	lsattr -E -l rmt0
X3) An even better listing is given by mt's "status" command:
X	mt -f /dev/rmt0.1 status
X4) To fix the blocksize of an Exabyte or QIC drive:
XAIX 3.X assumes a blocksize of 512bytes for Exabytes and cart drives
Xattached to RS/6000s.  Since an Exabyte's natural blocksize is 1024bytes,
Xthis has the unhappy effect of limiting the tape capacity to half of what
Xit ought to be.  The fix is to do something like the following, as root,
Xfor each tape drive on the AIX box:
X	chdev -l rmt0 -a block_size=1024
X
XThoughts about writing and reading header archive
XWriting:
XWe'd like tar to force fully blocked writes to standard out.
XThis is useful when we're writing to a pipeline where blocking may not be
Xmaintained, because we may be able to reconstruct it on the other end.
XSome UNIXs (e.g. Ultrix) use the 'B' key to do this.  Other UNIXs will allow
Xthe ordinary "b" key, but do not actually block to standard out.
XStill others (e.g. Pyramid SVR4) gripe about the "b" key when used
Xwith standard out.
Xcase $mhost in
X$lhost)	use tar blocked to local drive ;;
X*)		use tar blocked if possible to standard out \
X		| ddsplit obs=1b \
X		| if test $PIPESIZE_on_mediahost -ge tarblocksize ; then
X			attempt to force blocks to tarbs
X			ddjoin ibs=1b obs=$tarbs
X			| ddjoin ibs=$tarbs conv=sync of=$dev
X		else
X			attempt to force blocks to 1k instead
X			ddjoin ibs=1b obs=1k \
X			| ddjoin ibs=1k     conv=sync of=$dev
X		fi
X;;
Xesac
X
XReading:
XWe have no guarantees about the blocking of the tar archive we're trying
Xto read.  We also don't know whether it was written using tar or tar piped
Xto dd.  On local 9track tapes, this is no big deal, because tar will
Xtry to figure it out itself and many versions can handle partial blocks
Xat the end.  For local carts we can try 20b; then 2b.
X
XVerify strategy:
Xdump archives:
X	a) get list of files on media using "restore tvf ..."
X	b) figure out last file by picking the one with the largest inode
X	c) then extract it "restore xf ... <file>"
X	If the last file is successfully extracted then we have read the
X	entire dump and we assume all is well.  Special	cases like empty
X	dumps and no files (just directories) are also handled.
Xcpio archives:
X	Until version 4.26 we tried to use the same strategy as with dump.
X	We extracted "bkp.rpt" (so we could check the cpio archive against
X	the tape label) and "bkp.flist" (so we could determine the last
X	file and read the entire archive in an attempt to get it).
X	Unfortunately, because of the way cpio works, this extraction
X	forced a reading of the entire cpio archive anyway.  So trying
X	to get the last file meant reading it again - yuk!  So now we just
X	a) extract "bkp.rpt" and "bkp.flist" (which reads the entire archive)
X	b) check "bkp.rpt" against the tape label
X	If both files are extracted and the tape label checks ok then we
X	assume all is well.
Xalldisks archives (using dump or cpio):
X	a) extract the tar/cpio header archive
X	b) check "bkp.rpt" against the tape label
X	c) choose one of the filesystems to verify
X	d) do a filesystem verify (using restore or cpio as appropriate)
X
XVerify Alldisks dump strategy:
XThis is what we do:
X	for each archive ; do
X		backup verify $fs [host:]media nooffline
X	done
XThe following idea was considered but rejected:
X	skip header archive
X	for each tape ; do
X		for each archive get name of last file
X		rewind tape
X		for each archive pass if backup is empty or we can extract last file
X	done
XThe advantage would be that you could read each archive on each tape
Xserially, without repositioning the tape each time.
XThe disadvantage is that it's not guaranteed to work.  There is no
Xguarantee where "restore tf" or "restore xf" leaves the tape.  If an
Xarchive is teensy weensy, restore could position the tape at the
Xbeginning of the next archive.  Or it could leave itself in the middle
Xor end of the current archive.  Each vendors probably implements this
Xstuff differently, and may even have different strategies for different
Xtape drive types.  
X
XVerify Alldisks cpio strategy:
XMuch easier than dump (for once) - simply skip the header archive and then
Xdo "cpio -i $getlist < $mdev", and pray the vendor's version of cpio knows
Xwhat to do if an archive is continued on the next tape.
X
XExit status from restore and "cpio -[io]"
Xrestore		1	physical problem reading tape
Xrestore		1	reads tar archive from stdin
Xrestore		1	reads cpio archive from stdin
Xrestore x	1	file not in archive (SunOS 4.1.2), but see OSx ...
Xrestore x	0	file not in archive (OSx512MDNI 5.1a-910507c)
Xrestore t	31	success on NonStop-UX 4.0 ufsrestore/vxrestore
Xrestore t	32	failure on NonStop-UX 4.0 ufsrestore/vxrestore
Xcpio -i		2	wants to read 2nd tape but is too stupid to do it
Xcpio -i		2	archive is not cpio archive
Xcpio -o		2	could not archive one or more files in input file list
Xcpio -o		141	output through pipe closed prematurely
X
X##############################################################################
X
XA brief 'alldisks' backup script revision history:
X1.00	Dec 16 1988	First Release!!!  Can back up multiple filesystems
X	on one tape using BSD dump!!!
X2.00	Mar  6 1989	"get" mode added to retrieve data from backups!!!
X3.00	Sep  4 1990	Can do cpio backups!!!
X4.00	Mar 19 1991	verify mode!!!
X4.46	May 13 1993 (really an alpha alldisks 5.00):
X	add "backup verify alldisks" - COOL!!
X	add "backup <level> <fsname|alldisks> <media> verifytoo"
X	add "skip S" get/verify opt to skip "S" number of files
X	add "noauto" verify opt says don't automate verification
X	add "notcont" get/verify opt to say archive isn't continued on next vol
X	add "dir" media type so we can do a backup to files in a directory
X	add "file" media type so we can do a backup to file(s)
X	add "bkp.site" site configuration file
X	add "bkp.host" host-specific config file to set permanent host behaviors
X
SHAR_EOF
echo 'File src/backup/doc/alld.notes is complete' &&
chmod 0664 src/backup/doc/alld.notes ||
echo 'restore of src/backup/doc/alld.notes failed'
Wc_c="`wc -c < 'src/backup/doc/alld.notes'`"
test 20677 -eq "$Wc_c" ||
	echo 'src/backup/doc/alld.notes: original size 20677, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= src/backup/README ==============
if test -f 'src/backup/README' -a X"$1" != X"-c"; then
	echo 'x - skipping src/backup/README (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting src/backup/README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'src/backup/README' &&
X
X	Intro To The Famous 'alldisks' UNIX Backup Script	p. 1 of 8
X
XSo, you want to do backups on your machine?  Great!  Welcome to the
X'alldisks' backup script.  It has saved many users much time, hassle,
Xand money.
X
XThis "Intro" is also "The Manual".  Please read it.
X
XWhy is 'alldisks' so great?  Well, there are tons of reasons, a few of
Xwhich are listed here:
X1) It can put backups of multiple filesystems onto one tape.
X2) It can help restore files from one-filesystem (AKA 'onedisk') or
Xmulti-filesystem tapes.
X3) It can verify backup tapes.
X4) It works on scads of UNIX boxes with all sorts of OS/HW combinations.
X5) It uses the vendor-supplied 'dump/restore' utilities where possible,
Xbecause these are much better than cpio, tar, pax, fric/frec, bru, or
Xany other directory-based backup utility which might come from the
Xvendor.  However, if dump/restore aren't available it will use cpio
X(and it tries to work around as many of cpio's shortcomings as possible).
X6) It can handle backups over the net and multiple tapes, even when
Xusing cpio (backups over the net are discouraged because of the massive
Xnetwork traffic they generate).
X7) It reports any problems it detects, so you find out about them in
Xa timely fashion.
X
XThe name of the 'alldisks' script is "backup".  We speak of it as 'alldisks'
Xbecause you most often use it with a command something like this:
X
X	backup full alldisks video0
X
XFor a complete usage message, just say:
X
X	backup help
X
XInstructions on how to install it are on the next page.
X
X	Intro To The Famous 'alldisks' UNIX Backup Script	p. 2 of 8
X
XWhat do I need to do before using it?
XHere are the installation instructions:
X1) Presumably:
X	a) you are logged into the master sysadmin machine and you are in
X	   in the directory where you extracted the 'saenv_alld' shar archive
X	b) you defined that machine as SAHOST in the "dist/sahead" file
X	   and you defined that directory as SAHOME
X	c) you have installed the 'saenv' toolset on this machine
X2) Edit three config files in the "dist" directory:
Xbkp.opers:	Put all your 'operators' in it.  An 'operator' is anyone
X		who might use the script at your site.  You'll be putting
X		in their initials, login, and full name.
Xbkp.media:	List all the devices you'll be using for backups on the
X		various machines at your site.  Instructions can be found in
X		"bkp.media" itself, but basicly you can take the examples and
X		tweak them to describe your tape drives.  To keep things simple
X		at the beginning, you can simply define the tape drive on
X		your master sysadmin host (it does have one, doesn't it? :-)
Xbkp.site:	Has site-wide configuration paramaters for the backup script.
X		This is 'sh' code, so be careful.  There are instructions in
X		the bkp.site file itself.  You may not actually have to change
X		anything, but you may find it useful to reconfigure it.
XNote1: You can change any of these files and redistribute them at any time.
XNote2: The files in the "dist" directory were copied there from the
Xoriginals in the "src/backup" directory when you ran "firstinst-saenv".
X3) Set up a 'backup' account on your master sysadmin machine ($SAHOST).
XPresumably you have a tape drive attached to $SAHOST, and you have defined
Xan entry for it in the "bkp.media" file.  The UID for the 'backup' account
Xon $SAHOST should 194, unless you redefine $bkpuid in "bkp.site".  The GID
Xshould be the operator group on $SAHOST.
X4) Make sure you are in the SAHOME directory, and run
X	./bin/inst-alldisks <SAHOST>
Xto install the 'alldisks' backup toolset on your master sysadmin machine.
X5) You can install the 'alldisks' toolset on other hosts just by creating
Xa backup account on the <host> (you don't have to do this if /home/backup
Xis OK with you, or you redefine $bhdir in "bkp.site") and then doing
Xone of the following.
X	If the 'saenv' toolset has not been installed on your target host, do:
X		./bin/inst-toolset <host>
X	If the 'saenv' toolset has been installed on your target host, do:
X		./bin/inst-alldisks <host>
Xfor each host you want to install it on.
X6) This completes the 'alldisks' installation process.
X
X	Intro To The Famous 'alldisks' UNIX Backup Script	p. 3 of 8
X
XWhere does it live?
XIn backup's home directory on each machine.  If backup's home directory is
X"/home/backup", then the script itself is called "/home/backup/backup".
X
XHow do I use it?
X1) Log in to your machine as 'backup'.  Enter your initials when asked.
X2) Issue the backup command.  Say "backup help" for a complete list of options.
XTypical backup commands are:
X	backup full alldisks video0	# done perhaps one day each week
X	backup incr alldisks video0	# done perhaps four days each week
X	backup full /home friend:cart0	# network backup to cart0 on 'friend'
XThat's all!
X
XWhy should I label the backup tapes?
XBecause you will forget what's on them if you don't label them.
XBesides, your coworkers may need them when you aren't available.
X
XWhat information belongs on a proper tape label?
X1) hostname of the system being backed up
X2) name of filesystem (e.g. /usr or 'alldisks')
X3) date backup was made
X4) backup level (e.g. full or incremental)
X5) tape number (e.g. "tape 1 of 3", "tape 2 of 3", etc.)
X6) name of media host (in case the backup was done over the net to another box)
X7) For alldisks tapes, which have several filesystems on each tape, you *must*
Xnote the name of the first filesystem on each tape.  This is easy: the backup
Xscript tells you this info when it's done.  You will be very unhappy and have
Xa hard time retrieving data if this info is not written on your alldisks
Xtape labels.
X8) If a filesystem backup is continued onto another tape, this *must* be noted.
X
XHow do I take care of my tapes?
XTapes can be damaged by cold, heat, moisture, impact, magnets, and time.
XStore them in a cool dry safe place.  Keep them away from paper clip holders,
Xvacuum cleaners, disk drives, and magnetic desk toys.  Well-cared for tapes can
Xlast several years, but a tape can go bad for unexplained reasons at any time.
X
XCan I use 'alldisks' to archive only one filesystem?
XYes - that's called a "onedisk" archive.  You would say something like:
X	backup full /home cart0
X
XWhat does a "onedisk" tape look like?
XIt's a simple dump (or cpio) archive of the filesystem.
X
XWhat does an "alldisks" tape look like?
XIf BSD dump is available it looks like this:
X	|| tar_header  | dump1 | dump2 | dump............... ||
XIf BSD dump is not available it looks like this:
X	|| cpio_header | cpio1 | cpio2 | cpio............... ||
XThe tar/cpio header contains a list of all the filesystems in the
Xalldisks backup tape set, and other useful info for debugging purposes.
X
X	Intro To The Famous 'alldisks' UNIX Backup Script	p. 4 of 8
X
XWhat are all the files in backup's home directory?
X.cshrc		standard backup account .cshrc
X.profile	standard backup account .profile
X.getoper.csh	asks for your personal login name when you log in as backup
X.getoper.sh	asks for your personal login name when you log in as backup
Xbackup		'alldisks' script (or maybe a setuid binary to call backup.sh)
Xbackup.dd	"dd" wrapper to handle network dd's and non-standard dd messages
Xbackup.N.NN	old backup scripts - the "N.NN" part is their version number
Xbackup.c	C code for setuid binary wrapper to call backup.sh
Xbackup.sh	'alldisks' script if it is called it from a setuid binary
Xcpiodates	logs cpio backups (like /etc/dumpdates for BSD dump)
Xprobsent	tracks problems alldisks has *tried* to email to DC calltrack
Xbkp.donot	lists filesystems on this host which we never back up
Xbkp.listN	list(s) of filesystems: used with 'backup <level> listN <media>'
Xbkp.nofm	lists filesystems which we don't put on full alldisks backups
Xbkp.opers	lists operators at your site
X
XAnd what are all the subdirectories?
XEach time the alldisks script is run, it creates a working directory called
X"mmdd.HHMMSSmt".  The names are basically date-stamps, but they also describe
Xthe "mode" and "type" of backup made:
X	The modes are the basic alldisks modes: f=full, i=incr, g=get, v=verify
X	The types are o=onedisk and m=multifilesystem(alldisks)
X
XSo what are all the files in the subdirectories?
XThere are lots of them, and you normally don't have to think about them.
XIf you do, you probably will care most about these:
Xb.NN.out	saves dump/cpio output for each filesystem
Xbkp.dfout	list of filesystems that could go on an alldisks tape
Xbkp.rpt		report on the backup
Xbkp.fail	known failures, if detected, are listed here
Xbkp.probsend	notes problems we should report if it hasn't already been done
X
XAre there any other important files?
XYes.  There are three (or possibly four):
X1) 'alldisks' uses a list of media devices called 'bkp.media'.
XThe master version is maintained by your friendly local syadmins.
XA local copy of the master is kept on your machine, in /etc/dist/bkp.media.
XIf you are planning to use a tape drive attached to your box,
Xthe master bkp.media must contain info about it.  Alternatively, you can
Xcreate your own local bkp.media in backup's home directory - 'alldisks'
Xwill use that one instead if it exists.
X2) /etc/dist/sahead is sourced by 'alldisks' and can't run without it.
X3) /etc/saenv is a research report specific to your machine.  It is
Xalso sourced by 'alldisks' and can't run without it.
X4) /etc/dist/bkp.site describes alldisks behaviour at your entire site.
XIt is possible that you will like the defaults listed in it; if so it
Xdoes not need to be distributed to /etc/dist on each machine.
X
XIf I wanted to automate my backups, could I?
XYes, *if* your backups will all fit on one tape.  In root's crontab file
Xfor your system, you could put two entries that looked something like this:
X0 20 * * 5   /home/backup/backup full alldisks video0 cron 2>&1 | Mail root you
X0 20 * * 1-4 /home/backup/backup incr alldisks video0 cron 2>&1 | Mail root you
XThis would do a full backup on Friday evening at 8pm, and incremental
Xbackups Monday-Thursday at 8pm.  NOTE - You have to remember to change
Xthe tapes yourself!
X
X	Intro To The Famous 'alldisks' UNIX Backup Script	p. 5 of 8
X
XHow do I know if my backups are any good?
XThere are several methods.  The more work you want to do, the more
Xthoroughly you can check your backups.  In order of easy to hard:
X1) Look at the output from the backup.  No complaints is probably good
Xnews, but there are no guarantees.  The 'alldisks' script knows about
Xcertain failures, and makes an effort to report them.  However, it can't
Xpossibly know about all types of possible failures.
X2) Check "bkp.rpt" and "b.NN.out" files in the working directory for errors.
X3) Run 'backup verify /fsname [host:]media' for selected filesystems on an
Xalldisks backup.
X4) Run 'backup verify alldisks [host:]media' for alldisks tapes,
Xand 'backup verify onedisk [host:]media' for onedisk backups.
XVerifying an alldisks backup can take more than twice as long as making it did.
X
XA typical onedisk backup/verify sequence might be:
X	backup full /home cart0		# make the 'onedisk' backup of /home
X	backup verify onedisk cart0	# verify the backup
X
XA typical multi-filesystem backup/verify sequence might be:
X	backup full alldisks video0	# make the multi-filesystem backup
X	backup verify alldisks video0	# verify all filesystem archives, or
X	backup verify listdisks video0	# choose only one filesystem to verify
X
XWhen doing a "get" or "verify", I have to wait for alldisks to ask
Xlots of questions.  Is there an easier way?
XYes - the number of "extra" volumes and the name of the first filesystem
Xon each extra volume can be specified on the command line.
X        a) an alldisks tape set with only 1 tape:
X                backup verify lastdisk dat0 0
X        b) an alldisks tape set with three tapes, telling alldisks the
X        names of the first filesystems on extra tape 2 and extra tape 3
X                backup verify lastdisk video5 2 /fs1_tape2 /fs1_tape3
X        c) same as example "b)", but showing what to do if the first
X        filesystem on extra tape 2 is continued from the first tape;
X        notice the word "cont" on the command line:
X                backup verify lastdisk video1 2 /fs1_tape2 cont /fs1_tape3
XOther questions can also be answered in advance on the command line;
Xdo a "backup help" to see all the options.
X
XWhen doing a "verify", can I just get it going and come back a while later
Xto find out how it went?
XYes, but only if you specify the number of "extra" volumes and the name of the
Xfirst filesystem on each extra volume.  At that point, alldisks goes into
X"autoverify" mode.  You won't have to answer any other questions unless the
Xfilesystem you are verifying is not on the first tape.
X
X	Intro To The Famous 'alldisks' UNIX Backup Script	p. 6 of 8
X
XCan alldisks do network backups?
XSure.  But Be Aware:
X1) Backups of hosts *outside* the machine room using tape drives *in* the
Xmachine room are disallowed because hosts in the machine room do not trust
Xmachines outside the machine room.
X2) Backups *between* subnets are *very* strongly discouraged.
X3) If you insist on cratering your own subnet, you may do so until someone
Xcomplains.  You'll need to find a friendly workstation owner with a tape drive
Xand a similar OS.  Your host must be listed in your friend's /etc/hosts.equiv,
Xand your friend must remove /etc/dist/hosts.equiv.  For SunOS, the target host
Xmust also have a 'backup' account.
XA backup over the net to a cartridge drive on a friendly host might look
Xlike this:
X	backup full /home friend:cart0	# network backup to cart on 'friend'
X
XOK, I had a small disaster and I want to get a few of my files back.  Thank
Xgoodness I have backup tapes!  Brilliant!  Now what do I do?
XSimple:
X	backup get onedisk dat1		# get files from a onedisk backup
X	backup get listdisks dat1	# get files from an alldisks backup
XThe alldisks script is a front end for BSD "restore" (which reads archives
Xmade by BSD "dump") and "cpio".  The script will position the tape at the
Xcorrect archive for you, and get some key information from you before starting
Xrestore or cpio.  Naturally, you'll need to know how to use these programs
Xto take full advantage of them.  Luckily, restore in interactive mode is
Xpretty cool and also has a 'help' command.  Unfortunately, if you're stuck
Xusing cpio, you've got a much bigger problem because cpio doesn't have an
Xinteractive mode.
X
XOh, no!  My disaster turns out to be much bigger than I thought.  It turns
Xout my disk is fried and I had to have it replaced and newfs'd.  I have to
Xrestore an entire filesystem!  Now I'm *really* glad I made backups.  How
Xdo I get an entire filesystem?
XSame answer as above:
X	backup get onedisk cart0	# get files from a onedisk backup
X	backup get listdisks video5	# get files from an alldisks backup
X	backup get /usr friend:dat1	# network get of /usr from alldisks set
X
XGee, "backup get" sure asks me lots of questions.  Is there any way to
Xjust start it up and have it do the right thing?
XSure (but you do have to know all the answers :-) in advance:
X	backup get /fsname friend:dat1 0 interactive target <target_dir>
XDitto for verify, if we have an alldisks backup with two extra tapes:
X	backup verify /home friend:dat0 2 /fs1_t2 /fs1_t3
XThe "/fs1_t2" is the name of the first filesystem on the second tape,
Xand "/fs1_t3" is the name of the first filesystem on the third tape.
X
X
X	Intro To The Famous 'alldisks' UNIX Backup Script	p. 7 of 8
X
XCould you explain more about the filesystem lists which can be used to
Xmanage tape usage?  Which ones work, and when?
XSure.  Let's review for a moment:
Xbkp.donot     lists filesystems we never back up
Xbkp.listN     list(s) of filesystems: used with 'backup <level> listN <media>'
Xbkp.nofm      lists filesystems we don't put on full multi-filesystem backups
X* The two files "bkp.donot" and "bkp.nofm" are always honored, by all
Xthree types of multi-filesystem backups: alldisks, listed, and unlisted.
XAny filesystem listed in bkp.donot will never be backed up; any filesystem
Xlisted in bkp.nofm will left be off of any full multi-filesystem backup.
X* About bkp.listN, these files will typically be named "bkp.list1",
X"bkp.list2", and so on.  Like bkp.donot and bkp.nofm, they belong in backup's
Xhome directory.  An alldisks backup doesn't care whether or not a filesystem
Xis listed in a bkp.listN file.
X* Using a "onedisk/alldisks" tape management scheme:
XIf a machine has too much data to fit onto one tape, you may want to use
Xthis scheme to back up your filesystems.  The idea is to put one or more
Xbig filesystems in bkp.nofm.  A full alldisks backup will not put those
Xfilesystems on the alldisks tape.  Then you would back up each of those
Xfilesystems onto seperate onedisk tapes.
X* Using a "listN/unlisted" scheme:
XHowever, if one of your machines has more data than can fit on one tape,
Xand you have the luxury of two available tape drives, you might want to
Xgo to a "listN/unlisted" scheme.  Let's say you have two Exabyte 8500 5Gig
Xdrives and 8Gig of data to back up, you might want to list half of your
Xfilesystems in bkp.list1, and leave the rest unlisted to be backed up when
Xyou do you do "backup ... unlisted ...".  For example, you might say:
X      backup full list1 video0        # uses the bkp.list1 file
X      backup full unlisted video1     # excludes filesystems in bkp.list1
XIf you do go to this scheme, it is strongly recommended that you
Xdeliberately leave some filesystems out of the bkp.listN files so that
Xa "backup ... unlisted ..." will catch them.  If you hardcode all of
Xyour filesystems into the bkp.listN files and never do a "backup ...
Xunlisted ...", you run the risk that someday you will add another
Xfilesystem to your machine and forget to add it to the bkp.listN files;
Xthen your new filesystem won't be backed up.  A good rule of thumb might
Xbe to leave the root, /var, and /usr filesystems to be caught by your
X"unlisted" backups.
X
X	Intro To The Famous 'alldisks' UNIX Backup Script	p. 8 of 8
X
XWhat else should I read?
XWe recommend that you read:
X1) The output from "backup help" to see all command-line features and options
X2) The output from "backup examples" to see some examples
X3) The "README.PROB" file in this directory
X4) The attached documents in the "doc" directory with more miscellaneous info:
X	alld.features (old, so it doesn't include newer features)
X	alld.notes
X	alld.prob
X	alld.q
X	gen.restore.q
X5) Man pages for your OS: dump(8), restore(1), tar(1), cpio(1), dd(1)
X6) 'alldisks' itself:  The comments throughout the script contain big
Xhelpful info.  At over 150k of fairly heavily commented code, the script
Xis a great learning experience for the somewhat knowledgable shell coder.
X7) "If You've Seen One UNIX, You've Seen Them All", Bob Arnold,
XLarge Installation Systems Administration V Conference Proceedings,
XUSENIX, 1991.
X8) "Torture-testing Backup and Archive Programs: Things You
XOught to Know But Probably Would Rather Not", Elizabeth Zwicky,
XLarge Installation Systems Administration V Conference
XProceedings, USENIX, 1991.
X9) "Issues with Online Backups", Steve Shumway, Large Installation
XSystems Administration V Conference Proceedings, USENIX, 1991.
SHAR_EOF
chmod 0644 src/backup/README ||
echo 'restore of src/backup/README failed'
Wc_c="`wc -c < 'src/backup/README'`"
test 19005 -eq "$Wc_c" ||
	echo 'src/backup/README: original size 19005, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= src/backup/.cshrc ==============
if test -f 'src/backup/.cshrc' -a X"$1" != X"-c"; then
	echo 'x - skipping src/backup/.cshrc (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting src/backup/.cshrc (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'src/backup/.cshrc' &&
X## Standard Data Center .cshrc for user, root and backup accounts
X## 3/10/94, rca
X
X## Warning - this does NOT work on SCO, because SCO's csh reverses the
X## sense of "||" and "&&".
X
X## we always want the path, so try to get it from /etc/saenv
X# if we don't have system administration environment research report
Xif ( ! -r /etc/saenv || -z /etc/saenv ) then
X	set host=''
X	set arch=''
X	set mailer=''
X	set path=(/usr/ucb /bin /etc /usr/bin /usr/etc /sbin /usr/sbin /usr/5bin /usr/local/bin /usr/lbin)
X# else get info from it
Xelse
X	set path=(/usr/ucb /bin /etc /usr/bin /usr/etc /sbin /usr/sbin /usr/5bin /usr/local/bin /usr/lbin)
X	# delete non-PATH lines, strip PATH= and comments, change ":" to
X	# "<SPACE>";
X	# the only way to quote a "!" in csh is with a backslash, and we
X	# need a second one for the subshell
X	# delete /etc/dist/bin now, but if we're root put it back
X	set path=(`sed -e '/^PATH=/\\!d' -e 's/^PATH=//' -e 's/[ 	].*//' -e 's/:/ /g' -e 's,/etc/dist/bin,,' /etc/saenv`)
X	set arch=`sed -n -e 's/^ARCH_S=\([^ 	]*\)[	].*/\1/p' /etc/saenv`
X	set host=`sed -n -e 's/^HOST=\([^ 	]*\)[	].*/\1/p' /etc/saenv`
X	set mailer=`sed -n -e 's/^MAILER=\([^ 	]*\)[	].*/\1/p' /etc/saenv`
Xendif
X# in case $host is null after attempt to get it from /etc/saenv
Xif ( "$host" == "" ) then
X	# The sed is needed because SCO's csh's thinks "||" means "and",
X	# and we want unqualified hostnames
X	set host=`(hostname || uname -n ) | sed -e 's/\..*//p' -e '1q'`
Xendif
X# in case $mailer is null after attempt to get it from /etc/saenv
Xif ( "$mailer" == "" ) then
X	# most common around here
X	set mailer=Mail
Xendif
X# in case $path is null after attempt to get it from /etc/saenv
Xif ( "$path" == "" ) then
X	set path=(/usr/ucb /bin /etc /usr/bin /usr/etc /sbin /usr/sbin /usr/5bin /usr/local/bin /usr/lbin)
Xendif
X# add X11R4 to the path - needed even for non-interactive X11 tools
X# like .mwmrc which use the path from .cshrc
Xif ( "$arch" != "" && -d /usr/local/X11R4/bin/$arch ) then
X	set path=($path /usr/local/X11R4/bin/$arch)
X	if ( "$host" != "" ) then
X		set display=$host
X	else
X		set display=unix
X	endif
X	setenv	DISPLAY ${display}:0.0
X	if ($?LD_LIBRARY_PATH) then
X		setenv	LD_LIBRARY_PATH	${LD_LIBRARY_PATH}:/usr/local/X11R4/lib/$arch
X	else
X		setenv	LD_LIBRARY_PATH	/lib:/usr/lib:/usr/local/X11R4/lib/$arch
X	endif
Xendif
X# add openwin to the path if we have it
Xif ( -d /usr/openwin/bin ) then
X	set path=(/usr/openwin/bin $path)
X	setenv	OPENWINHOME	/usr/openwin
Xendif
X
X## if we have an interactive shell
Xif ( $?prompt ) then
X
X	## find out who we are, if we can
X	set whouser=''
X	set whologname=''
X	set whoami=''
X	# $USER is BSD
X	if ( $?USER ) then
X		set whouser=$USER
X	endif
X	# LOGNAME is SysV
X	if ( $?LOGNAME ) then
X		set whologname=$LOGNAME
X	endif
X	# if both of these are empty then we really need $whoami
X	if ( "$whouser" == "" || "$whologname" == "" ) then
X		# In csh we can't quote "!" except with backslashes, and we
X		# need two of them because of the subshell.
X		# We need the Bourne shell so we can toss any standard error
X		# from the "who am i", which can occur under HP-UX with C2
X		# security if the shell isn't attached to a tty.
X		set whoami=`sh -c 'who am i 2> /dev/null' | sed -e 's/[ 	].*//' -e 's/^.*\\!//'`
X	endif
X
X	## see if we're root or not
X	set amroot=0		# assume we're an ordinary user ...
X	set promptchar='>'	# with an ordinary prompt
X	touch /tmp/.cshrc$$
X	if ( `ls -l /tmp/.cshrc$$ | egrep root | wc -l` ) then
X		set amroot=1
X		set promptchar='#'
X	endif
X	rm -f /tmp/.cshrc$$
X	# if we're root add /etc/dist/bin to path and handle preferred shells
X	if ( $amroot ) then
X		set path=($path /etc/dist/bin)
X	# else add "~/bin" and "." to the path
X	else
X		# add ~/bin if it exists
X		if ( -d ~/bin ) set path=($path ~/bin )
X		# add "." (current directory) to the path; put it last 
X		set path=($path .)
X	endif
X
X	# deal with terminal stuff here
X	if ( $?TERM ) then
X		# if $TERM == network or dumb, then we guess that we're coming
X		# in from a terminal server or some unix box which doesn't
X		# know about its serial lines
X		if ( $TERM == network || $TERM == unknown || $TERM == dumb ) then
X			setenv  TERM    vt100
X		endif
X		# HP xterm weirdness
X		set x=`egrep "^OS_S=HP-UX[ 	]" /etc/saenv >& /dev/null`
X		if ( $TERM == "xterm" && $#x ) then
X			/usr/bin/X11/resize > /tmp/$$
X			source /tmp/$$
X			rm /tmp/$$
X		endif
X	endif
X
X	## Finally we can get on with all this normal stuff!
X	# set shell variables
X	set	history=100			# remember 100 commands
X	set	ignoreeof			# no <CTRL>D
X	set	autologout=0			# turn off HP-UX autologout
X	set	prompt="$host \!$promptchar "	# set prompt
X	set	filec				# set file completion
X	# set environment variables
X	setenv	SHELL	/bin/csh
X	setenv	EXINIT	"se ai redraw magic shell=$SHELL terse nowarn sm"
X	setenv	MANPATH	/usr/local/man:/usr/man
X	setenv	EDITOR	vi
X	# useful command aliases
X	alias	a	alias
X	alias	c	clear
X	alias	d	dirs
X	alias	dec	"(stty intr '^c' erase '^?' ; stty susp '^z' ; stty echoe ; stty crt) >& /dev/null"
X	alias	h	history
X	alias	hm	"history | more"
X	alias	j	jobs -l
X	alias	ls	ls -FC
X	alias	m	$mailer
X	alias	mail	$mailer
X	alias	resize	'eval `/usr/bin/X11/resize`'	# for HP-UX xterms
X	alias	so	source
X	alias	z	suspend
X
X	## get local .cshrc if any
X	set local=~/.cshrc.$host
X	if ( -o $local && -r $local && -f $local && ! -z $local ) source $local
X
X	## for backup account
X	set getop=.getoper.csh
X	if ( -o $getop && -r $getop && -f $getop && ! -z $getop ) then
X		set path=(~backup $path)
X		source $getop
X		# say whether backups have to be done as root
X		if ( `ls -l backup | egrep -c '^...x'` ) then
X			echo ""
X			echo "Backups on $host must be done as root."
X			echo ""
X		endif
X	endif
X
X	## finish up
X	unset arch host	mailer		# from /etc/saenv
X	unset local			# for .cshrc.$host
X	unset getop			# for .getoper.csh for backup account
X	unset display			# for X11
X	unset x				# misc
X	unset amroot promptchar		# root stuff
X	unset whologname whouser whoami	# who we are
X	unset echo verbose		# defense against debugging
Xendif
SHAR_EOF
chmod 0644 src/backup/.cshrc ||
echo 'restore of src/backup/.cshrc failed'
Wc_c="`wc -c < 'src/backup/.cshrc'`"
test 5952 -eq "$Wc_c" ||
	echo 'src/backup/.cshrc: original size 5952, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= src/backup/.getoper.csh ==============
if test -f 'src/backup/.getoper.csh' -a X"$1" != X"-c"; then
	echo 'x - skipping src/backup/.getoper.csh (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting src/backup/.getoper.csh (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'src/backup/.getoper.csh' &&
X#!/bin/csh
X# .getoper.csh is used to set up environment for backup operators
Xecho ""
Xwhile (1)
X	echo -n "Please enter your intials: "
X	set oper=$<
X	if ( "$oper" == "" ) continue
X	foreach f ( bkp.opers bkp.opers.loc )
X		if ( -f $f ) then
X			# each part of the regular expression has to be quoted
X			# seperately, since the csh wants to interpret
X			# "$oper[ 	]" as a csh variable similar
X			# to $argv[2], say.
X			if ( `grep -c "^$oper""[ 	]" $f` ) then
X				setenv OPER $oper
X				unset oper
X				break
X			endif
X		endif
X	end
X	if ($?OPER) break
X	echo "I don't know who $oper is."
X	echo -n "Do you wish to be added as a backup operator? "
X	set ans=$<
X	if ( "$ans" == "y" || "$ans" == "Y" || "$ans" == "yes" || "$ans" == "YES" )  then
X		echo -n "Enter your personal login name: "
X		set operlogin=$<
X		echo -n "Enter your Full Name: "
X		setenv OPER $oper
X		echo "$OPER	$operlogin		$<" >> $HOME/bkp.opers
X		unset oper
X		unset operlogin
X		break
X	endif
X	setenv OPER '??'
X	break
Xend
Xset prompt="$OPER.backup@$prompt"
SHAR_EOF
chmod 0644 src/backup/.getoper.csh ||
echo 'restore of src/backup/.getoper.csh failed'
Wc_c="`wc -c < 'src/backup/.getoper.csh'`"
test 1007 -eq "$Wc_c" ||
	echo 'src/backup/.getoper.csh: original size 1007, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= src/backup/.getoper.sh ==============
if test -f 'src/backup/.getoper.sh' -a X"$1" != X"-c"; then
	echo 'x - skipping src/backup/.getoper.sh (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting src/backup/.getoper.sh (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'src/backup/.getoper.sh' &&
X:
X# .getoper.sh is used to set up environment for backup operators
Xecho ""
Xwhile : ; do
X	echo "Please enter your intials:" "\c"
X	read OPER
X	test -z "$OPER" && continue
X	grep "^$OPER[ 	]" bkp.opers > /dev/null && export OPER && break
X	echo "I don't know who $OPER is."
X	echo "Do you wish to be added as a backup operator?" "\c"
X	read ans
X	case $ans in
X	[yY]*)
X		echo "Enter your personal login name:" "\c"
X		read login
X		echo "Enter your Full Name:" "\c"
X		read name
X		echo "$OPER	$login		$name" >> bkp.opers
X		break
X	;;
X	esac
X	OPER='??'
X	export OPER
X	break
Xdone
XPS1="$OPER.backup@`uname -n` \$ "
SHAR_EOF
chmod 0644 src/backup/.getoper.sh ||
echo 'restore of src/backup/.getoper.sh failed'
Wc_c="`wc -c < 'src/backup/.getoper.sh'`"
test 596 -eq "$Wc_c" ||
	echo 'src/backup/.getoper.sh: original size 596, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= src/backup/.profile ==============
if test -f 'src/backup/.profile' -a X"$1" != X"-c"; then
	echo 'x - skipping src/backup/.profile (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting src/backup/.profile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'src/backup/.profile' &&
X:
X# standard Data Center .profile for backup accounts forced to use sh
X# 07/20/92, rca
X
X# note that .profile is only used by "sh" login shells so there's
X# no need to test for this, unlike .cshrc for csh.
X
X# we always want the path
Xp="`grep '^PATH=' /etc/saenv | sed -e 's/[ 	].*/:./'`"
Xif test -n "$p" ; then
X	eval $p
Xelse
X	PATH=/bin:/etc:/usr/bin:/usr/etc:/sbin:/usr/sbin:/usr/ccs/bin:/usr/lbin:/usr/local/bin:.
Xfi
Xexport PATH
X
X# get $OPER for backup script
Xif test -f .getoper.sh ; then
X	. ./.getoper.sh
X	# say if backups have to be done as root
X	if test `ls -l backup 2> /dev/null  | grep -c '^...x'` -eq 1 ; then
X		echo ""
X		echo "Backups on `uname -n` must be done as root."
X		echo ""
X	fi
Xfi
X
Xls()	{ /bin/ls -FC $* ; }
Xdec()	{ stty echoe || stty crt ; stty intr '^c' ; stty erase '^?' ; }
SHAR_EOF
chmod 0644 src/backup/.profile ||
echo 'restore of src/backup/.profile failed'
Wc_c="`wc -c < 'src/backup/.profile'`"
test 795 -eq "$Wc_c" ||
	echo 'src/backup/.profile: original size 795, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= src/backup/linst-alldisks ==============
if test -f 'src/backup/linst-alldisks' -a X"$1" != X"-c"; then
	echo 'x - skipping src/backup/linst-alldisks (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting src/backup/linst-alldisks (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'src/backup/linst-alldisks' &&
X:
X# linst-alldisks - local install backup script - written by Bob Arnold
X#
X# "inst-alldisks" on $SAHOST supplies this script with necessary files
X# and then calls this script.  We report on success or failure of installation.
X# Basic strategy is for inst-alldisks to copy this script
X# and necessary files to the remote host, and then run this script
X# on the remote machine.
X
X. /etc/dist/sahead		# do this always
X
X# go to installation directory created by inst-alldisks and get any
X# site-wide definitions
Xtdir=/tmp/ialld
Xcd $tdir
Xtest -f ./bkp.site && . ./bkp.site
X
X## Change these three in the master 'bkp.site' on $SAHOST if you want
Xbkpuid=${bkpuid-194}		# backup's default user id at your site
Xchkaixdev=${chkaixdev-false}	# no warning about AIX 3.X video drives
Xperm=${perm-755}		# set to 4755 if you want it to be setuid
Xbhdir=${bhdir-/home/backup}	# default home directory
Xdevdata=bkp.media		# media device data file
XUSAGE="usage: $pr [-verbose] [backup_home_dir]"	# usage string
X
Xumask 002
X
X# process command args
Xwhile test $# -gt 0 ; do
X	case $1 in
X	-v*)	set -x ;;
X	/*)	bhomearg=$1 ;;
X	*)	echo "$USAGE" ; exit 1 ;;
X	esac
X	shift
Xdone
X
X## Deal with 'backup' account issues.  Generally speaking, if we already have
X## a backup account, we leave it alone.  That means we don't touch the 'backup'
X## entry in /etc/passwd, nor move the home directory, even if the user
X## spec'ed a different home directory on the command line.
X## If necessary, install backup entry in /etc/passwd and create home directory
X
Xpwent=`grep "^backup:[^:]*:$bkpuid:" /etc/passwd | sed -e '1q'`
X
X# get home directory from a) /etc/passwd, b) command arg, or c) default $bhdir
Xif test -n "$pwent" ; then
X	phome=`echo "$pwent" | awk -F: '{print $6}'`
X	# if we got a home arg and it doesn't agree with /etc/passwd
X	if test -n "$bhomearg" -a "$bhomearg" != "$phome" ; then
X		echo "$pr: You specified home directory '$bhomearg'."
X		echo "$pr: The home directory in $HOST:/etc/passwd is '$phome'"
X		echo "$pr: Please change backup's home directory in $HOST:/etc/passwd"
X		echo "$pr: and try again."
X		exit 1
X	fi
X	bhdir=$phome
Xelif test -n "$bhomearg" ; then
X	bhdir=$bhomearg
Xelse
X	bhdir=$bhdir
Xfi
X
X## make home directory if necessary
Xif test -n "$bhdir" -a ! -d "$bhdir" ; then
X	$DTGTBIN/mkpath $bhdir
X	if test $? -ne 0 ; then
X		echo "$pr: Could not make home directory '$bhdir'" 1>&2
X		exit 1
X	fi
Xfi
X
X## make sure home directory isn't NFS'd from elsewhere
X# The 'not a file system' is to handle AT&T's SVR3.2.1 df which complains
X# but exits with status 0.
X# AIX 2.2.1 does a similar thing with 'Cannot find file system'
Xdf=`df $bhdir 2> /dev/null | egrep 'not a file system|Cannot find file system'`
Xif test $? -eq 0 -o -z "$df" ; then
X	: do nothing because the system cannot help us answer this question
Xelif echo "$df" | egrep '^/dev/|^/adj/[^ 	]*dev/|\(/dev/.*\):' > /dev/null ; then
X	: we are on a local filesystem, so do nothing
Xelse
X	echo "$pr: backup's home directory is on an NFS filesystem" 1>&2
X	echo "$df"
X	exit 1
Xfi
X
X## make sure we can create files in backup's homedir
Xtouch $bhdir/junk
Xif test $? -ne 0 ; then
X	echo "$pr: Cannot create files in home directory '$bhdir'" 1>&2
X	exit 1
Xfi
Xrm -f $bhdir/junk
X
Xif test -z "$pwent" ; then
X	#if we're using dump, set up group stuff properly
X	if test -z "$DUMP_P" ; then
X		# make sure we define $newent
X		newent=`cat newent.$SAHOST`
X	else
X		# get machine's operator group ...
X		opgrp=`sed -n -e 's/^operator:[^:]*:\([0-9][0-9]*\):.*/\1/p' /etc/group`
X		case "$opgrp" in
X		[1-9]|[1-9][0-9]*)
X			# got one so put it in backup's passwd entry
X			newent="`awk -F: 'BEGIN {OFS=":"} /^backup:/ {print $1,$2,$3,'$opgrp',$5,$6,$7}' pwent.$SAHOST`"
X		;;
X		*)
X			# didn't get one, so create one using $bkpuid which
X			# is our fallback
X			echo "operator:*:$bkpuid:" >> /etc/group
X			newent=`cat newent.$SAHOST`
X		;;
X		esac
X	fi
X	# handle home directory and login shell
X	if test -n "$CSH_P" ; then
X		homeshell=$bhdir:$CSH_P
X	else
X		homeshell=$bhdir:/bin/sh
X	fi
X	newent=`echo "$newent" | sed -e "s,[^:]*:[^:]*\$,$homeshell,"`
X	# now we can add the passwd entry for the backup account
X	echo "$newent" >> /etc/passwd
X	if test $MKPW_B = true ; then
X		rm -f /etc/passwd.dir /etc/passwd.pag
X		mkpasswd /etc/passwd
X	fi
X	# If /etc/shadow exists, try to deal by running pwconv, an SVR[34] tool.
X	# If pwconv doesn't exist, no harm done; and if it does exist, great.
X	# We don't want to willy-nilly run pwconv, because it will create
X	# an /etc/shadow where none existed before.
X	# Try it in a subshell to filter out any "pwconv: not found" (or such)
X	# messages from the shell, and then put any other shell/pwconv output
X	# back on stderr where it belongs.
X	test -f /etc/shadow && ( pwconv ) 2>&1 | grep -v '[Nn]ot found' 1>&2
Xfi
X
X## figure out exactly what we're going to install - depends on several factors
X# deal with source file and name of installed version
X# make some assumptions here, which we'll change as needed
Xsource=backup
Xinstall=backup
Xcase "$SUIDSCRIPT_S" in
X\#!/bin/sh)
X	case "$OS_S$OSLEVEL_S" in
X	# This pyramid OS supports SUID scripts only for UID's < 100, which
X	# the OS research tool can't reasonably be designed to figure out
X	# Ditto for HP-UX8.00 it seems.
X	OSx512MDNI*|HP-UX8.0*)	test $bkpuid -ge 100 && perm=755 ;;
X	*)			: do nothing since we are OK ;;
X	esac
X;;
X\:)
X	source=backup.colon
X	echo : > $source
X	cat backup >> $source
X;;
X'')
X	case "$SUIDWRAP_B" in
X	true)
X		install=backup.sh
X		# the x and eval are to strip the double quotes from
X		# the '#define SCRIPT_P "/home/backup/backup.sh"'
X		# in backup.c
X		x=`awk '/\#define SCRIPT_P/ {print $3}' backup.c`
X		if test "`eval echo $x`" != $bhdir/$install ; then
X			sed -e '/SCRIPT_P/s,".*","'$bhdir/$install'",' backup.c > nbackup.c
X			mv nbackup.c backup.c
X		fi
X		cc backup.c
X	;;
X	*)
X		perm=755
X		# if we don't support binary setuid wrappers, and
X		#    we don't support #! interpretation, and
X		#    we do have a path to csh, then
X		#	the backup account will have a csh, and the
X		#	system will assume that the 'alldisks' script is a
X		#	csh-script because of the leading '#'.  We have to
X		#	prevent this by prepending a ':' at the start of the
X		#	alldisks script.
X		case "$INTERP_B$CSH_P" in
X		false/*)
X			source=backup.colon
X			echo : > $source
X			cat backup >> $source
X		;;
X		esac
X	;;
X	esac
X;;
Xesac
X
X## test for an "sh" bug first encountered under HP-UX 3.10, where a
X## sourced file becomes $0.  Since alldisks sources sahead, if it trips over
X## this bug "pr" gets set to "sahead", when it should say "backup" :-(
X## we hack around it if necessary
Xecho ':
X. /etc/dist/sahead
Xecho $pr' > chk_sh_source
Xchmod +x chk_sh_source
Xif test `./chk_sh_source` != "chk_sh_source" ; then
X	# you'd think you'd be able to edit $source in place using "ed",
X	# but noooooo, ed is busted under HP-UX 3.10 too, so it's easiest to
X	# do this with awk
X	awk '{print} ; /^\. \/etc\/dist\/sahead/ {print "pr=backup	# linst-alldisks: hack because '"$OS_S $OSLEVEL_S"' sh \".\" bug renames $0"}' $source > $source.hack
X	source=$source.hack
Xfi
X
X## prepare $bhdir to receive new stuff
Xcd $bhdir
X#rm -f $devdata		# remove local $devdata file - uncomment as necessary
X## save old backup script if it exists
Xif test -f $install ; then
X	# get old version number
X	oldversion=`grep '^version=' $install | sed -e 's/^version=\([1-9]*\.[0-9][0-9]\).*/\1/'`
X	# if that doesn't work, punt
X	if test -z "$oldversion" ; then
X		oldversion="old"
X	fi
X	mv $install $install.$oldversion
Xfi
X
X## ok, we're finally ready to install new stuff
Xcd $tdir
Xmv $devdata bkp.site $DTGT
Xmv backup.dd $bhdir
Xmv $source $bhdir/$install
Xif test -f a.out ; then
X	mv a.out $bhdir/backup
X	if test -f $bhdir/backup.c ; then
X		mv $bhdir/backup.c $bhdir/backup.c.$oldversion
X	fi
X	cp backup.c $bhdir
Xfi
Xif test -n "$CSH_P" ; then
X	mv bkp.opers .getoper.csh .cshrc   $bhdir
Xelse
X	mv bkp.opers .getoper.sh  .profile $bhdir
Xfi
X
X## permissions and ownership
Xcd $bhdir
Xchown backup . .??* bkp.opers*
Xchown root   backup $install $DTGT/$devdata
Xchmod $perm  backup $install
Xchmod 644    $DTGT/$devdata bkp.opers*
X
X## for DG/UX, we need to put entries in /etc/dumptab in case we end up
X## using "dump2"
Xo="$OS_S$OSLEVEL_S"
Xcase "$o" in
Xdgux*)
X	egrep '^dat	' /etc/dumptab > /dev/null
X	if test $? -ne 0 ; then
X		echo "$pr: $o: Putting 'dat' entry in /etc/dumptab for 'dump2'"
X		echo "dat		16		2000M	# entry by $pr" >> /etc/dumptab
X	fi
X;;
XAIX3.*)
X	if test "$chkaixdev" = true ; then
X		echo ""
X		echo "$pr: $o: Check block size of any video devices on $HOST."
X		echo "$pr: $o: AIX 3.X video drives come blocked at 512bytes/1024byte"
X		echo "$pr: $o: block, so they can use only half the tape capacity."
X		echo "$pr: $o: For a video drive called '/dev/rmt0', use 'rmt0':"
X		echo "$pr: $o: To Check:  'lsattr -l rmt0 -a block_size -E'"
X		echo "$pr: $o: To Fix:    'chdev  -l rmt0 -a block_size=1024'"
X		echo "$pr: $o: To Break:  'chdev  -l rmt0 -a block_size=512'"
X	fi
X;;
Xesac
X
X## show user the results
Xcase "$install" in
X	backup)		ls -l $bhdir/backup ;;
X	backup.sh)	ls -l $bhdir/backup $bhdir/backup.sh ;;
Xesac
X
X# cleanup installation stuff
Xtest -d $tdir && rm -rf $tdir
SHAR_EOF
chmod 0755 src/backup/linst-alldisks ||
echo 'restore of src/backup/linst-alldisks failed'
Wc_c="`wc -c < 'src/backup/linst-alldisks'`"
test 9092 -eq "$Wc_c" ||
	echo 'src/backup/linst-alldisks: original size 9092, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= src/backup/backup ==============
if test -f 'src/backup/backup' -a X"$1" != X"-c"; then
	echo 'x - skipping src/backup/backup (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting src/backup/backup (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'src/backup/backup' &&
X#!/bin/sh
X# cannot put ":" as first line, setuid sh scripts are unsupported on some hosts
X
X################################################################################
X# This is the famous "alldisks" backup script.  It is justly renowned for
X# it's good design and great utility.  It has saved many users much time,
X# hassle, and money.
X#
X#		Bob Arnold (rca@ingres.com)
X#
X# For a usage message, say "backup help".
X#
X# Can be run out of cron with an entry in root's or backup's crontab, e.g.:
X# 00 22 * * * /home/backup/backup full alldisks video0 cron 2>&1 | Mail yourself
X#
X# See the README file for
X#	Installation instructions
X#	Script outline
X#	Variable naming conventions
X#	Discussions of design issues
X#	How to add a new command arg
X#	Revision history
X#	Need/Want feature list
X################################################################################
X
X# have to get this done right away, in case we are writing to STDOUT;
X# use filedescriptor 8 here because we use 9 elsewhere (and more commonly too)
Xif echo " $* " | egrep ' file - ' > /dev/null ; then
X	if echo " $* " | egrep ' (full|incr|tincr) ' > /dev/null ; then
X		exec 8>&1
X		exec 1> /dev/tty
X	elif echo " $* " | egrep ' get ' > /dev/null ; then
X		exec 8>&0
X		exec 0> /dev/tty
X	fi
Xfi
X
X## initial stuff
Xversion=5.00					# Fri Jun 17 12:02:29 PDT 1994
X# home directory
Xhdir=`awk -F: '/^backup:/ {print $6}' /etc/passwd`
X# we need exactly one backup account
Xif test `echo "$hdir" | wc -w` -ne 1 ; then
X	grep '^backup:' /etc/passwd
X	echo "$pr: There should be only one backup account in /etc/passwd; please fix.  Quitting."
X	exit 1
X# and we need backup's home directory
Xelif test ! -d "$hdir" ; then
X	echo "$pr: Home directory for 'backup' doesn't exist!  Quitting."
X	exit 1
Xfi
Xcd $hdir					# go to ~backup
X. /etc/dist/sahead				# MUST source sahead
Xtest -f $DTGT/bkp.site && . $DTGT/bkp.site	# get any site-wide definitions
Xtest -f $hdir/bkp.host && . $hdir/bkp.host	# get host-specific definitions
Xumask ${umask-007}				# so world can't read output
Xexec 9>&1					# FD 9 is copy of STDOUT
X# if there is a local backup script use that instead (but not recursively!)
Xcase $pr in
X$pr.local)
X	echo "$pr: Running $pr $*"
X;;
X$pr)
X	if test -f ./$pr.local ; then
X		echo "WARNING: using backup.local $*"
X		echo "Please REPORT THIS to the proper authorities!"
X		./backup.local $*
X		exit $?
X	fi
X;;
Xesac
X# trap - simply cleanup on exit
Xtrap ":                             ; /bin/rm -f \$rmlist ; exit  " 0
X# trap - if interrupted, log, cleanup and die
Xtrap "echo $pr: Interrupted. Quitting. | tee -a \$workdir/\$report ; /bin/rm -f \$rmlist ; exit 1" 1 2 3 15
X
X# set variables, including defaults
Xdate="`date`"		# save startup date for report and $workdir name
Xstartdir=`pwd`		# save startup directory
Xcmdargs=$*		# save command arguments for later use
Xmode=			# command arg	mode (help|examples|usage|full|incr|get|verify|devcheck)
Xfs=			# command arg	filesystem to be backed up or gotten
Xmedia=			# command arg	media type (dir|file|null) or media alias in $devdata ([host:]cartN|datN|tapeN|tkN|videoN)
X# [opt] command options - default assumptions (shown in alphabetical order)
Xcheck=true		# [opt]	assume we do the device checks
Xcron=false		# [opt]	assume we are not running from cron
Xdemo=false		# [opt]	assume not a script demo
Xextravol=		# [opt] assume unspecified # of extra vols in backup set
Xfsbkp=true		# [opt] assume /fsname is a real filesystem
Xfitguess=true		# [opt] assume we guess whether backups will fit
X#header=${header-false}	# [opt] assume we don't put headers on onedisk backups
Xheader=false		# don't put headers on onedisk backups
Xjoke=${joke-true}	# [opt]	assume we do cpio joke if using cpio
Xlabelq=true		# [opt] assume we ask $OPER to check paper label
Xoptlk=${optlk-false}	# [opt] assume optional lock not set (always lock for cpio)
Xlistf=			# [opt] assume no listfile with filesystems to backup
Xmail=${mail-true}	# [opt]	assume we mail reports to $rptto
Xmhost=			# [opt]	assume host with media device is local
Xoffline=${offline-true}	# [opt]	assume we take media offline
Xprobq=true		# [opt] assume we ask if backup failed
Xshowdd=false		# [opt]	assume backup.dd doesn't show dd command
Xupdate=true		# [opt]	assume we update dumpdates/$bdatef
Xautoverify=true		# [opt] assume user wants as much automation as possible
Xtargetarg=false		# [opt] assume user doesn't spec restore target
Xverifytoo=false		# [opt] assume user doesn't want to verify this backup
X# end of [opt] default assumptions
Xbprog=			# backup program (cpio vs. dump)
Xdlevel=			# dump level (0|5)
Xincr=${incr-5}		# dump incremental level
Xtest_incr=9		# dump incremental level for testing
Xmtype=			# type of media, based on "$media" media alias
Xmistape=true		# media is a tape; set to false iff mtype is (dir|file)
Xoplist=$hdir/bkp.opers	# master file containing list of known operators
Xoplistloc=$oplist.loc	# local file containing local operators
XOPER=$OPER		# OPER is already set in environment, we hope
Xdate4=`echo $date \
X| awk '{ m["Jan"]=1 ; m["Feb"]=2 ; m["Mar"]=3 ; m["Apr"]=4 ; m["May"]=5 ; m["Jun"]=6 ; m["Jul"]=7 ; m["Aug"]=8 ; m["Sep"]=9 ; m["Oct"]=10 ; m["Nov"]=11 ; m["Dec"]=12 ; printf "%02d%02d\n", m[$2],$3}'`
Xdate7=`echo $date | awk '{printf "%d%s%02d\n", $6%100,$2,$3}'`	# 7-char date
Xtime6=`echo $date | awk '{print $4}' | sed -e 's/://g'`		# 6-char time
Xnobkp=$hdir/bkp.donot	# local list of filesystems *NOT* to backup
Xnofm=$hdir/bkp.nofm	# do not backup when doing full multi-volume backups
Xbdatef=$hdir/cpiodates	# like dumpdates but we use it to log cpio backups
Xprobsent=$hdir/probsent	# when we tried to report backup probs; cleared if fixed
Xlockf=$hdir/LOCK	# lock file used by pony:/backupd.disk and cpio backups
Xbdd=$hdir/backup.dd	# reliable script wrapper for (possibly remote) dd
Xnobkptmp=bkp.donot.tmp	# version of $nobkp massaged for "egrep -v"
Xlistftmp=bkp.listf.tmp	# version of $listf massaged for "egrep"
Xdevdata=bkp.media	# file for cart|dat|tape|tk|video device data
Xdft1=bkp.dft1		# "df" output, stage 1 (just get it)
Xdft2=bkp.dft2		# "df" output, stage 2 (SysV to BSD format conversion)
Xdft3=bkp.dft3		# "df" output, stage 3 (stripping unwanted filesystems)
Xdfout=bkp.dfout		# "df" output, final; lists filesystems on multifs tapes
Xdflocal=bkp.dflocal	# "df" output, lists all valid local filesystems
Xbreport=bkp.rpt		# backup mode report file (early version put in header)
Xgvreport=gv.rpt		# "get" or "verify" report file
Xfailrpt=bkp.fail	# operator's reported reason for backup failure
Xfirstblist=bkp.firstb	# list of first backups on each tape
X# the next six files are only created if we're doing a cpio backup
Xflist=bkp.flist		# files to be backed up
Xfiltert1=bkp.filtert1	# files not to back up, stage 1
Xfilter=bkp.filter	# files not to back up, (mounted subdirs + $nobkp)
Xtopfilter=bkp.topfilter	# files at top of $fs that we don't want to give to find
Xtoplist=bkp.topout	# files at top of $fs that we do want to give to find
Xtouchf=/tmp/bkp.newer$$	# find files newer than $touchf for cpio incremental
Xfalseprob=bkp.falseprob	# list of known false backup problems, used via fgrep
Xproblist=bkp.problist	# list of known backup problems, used via fgrep
Xprobsend=bkp.probsend	# send reports of problems with these filesystems
Xstatlist=bkp.statlist	# list of exit statuses for dump/cpio
Xstatprob=bkp.statprob	# list of problem exit statuses for dump/cpio
Xtarhead=bkp.tarhead	# tar header archive for alldisks archives using dump
Xvolmap=bkp.volmap	# map of volumes to filesystems
Xdatecpio=		# set later: SysV date of start of actual cpio
Xhfstat=			# exit status's of dd'ing tar/cpio header file on media
Xexpire=${expire-21}	# remove log dirs more than $expire days old
Xbadmedia=false		# later set to true if operator spec's a bad media type
Xbadrewdev=false		# later set to true if $devdata has bad rewind device
Xbadnorewdev=false	# later set to true if $devdata has bad norewind device
Xmtestf1=/tmp/bkpt1.$$	# media test file 1, has unique info, created on the fly
Xmtestf2=/tmp/bkpt2.$$	# media test file 2, has unique info, created on the fly
Xmtestf3=/tmp/bkpt3.$$	# media test file 3, output file compared to $mtestf[12]
Xmtestf4=/tmp/bkpt4.$$	# media test file 3, output file compared to $mtestf[12]
Xmtestobs=5k		# media test output (write) block size (cart/dat/video >= 1k, 3B15 tape <= 5k, most video/cart/tape devices work with 10k)
Xmtestibs=		# media test input  (read)  block size (set later - depends on $bprog and $multi)
Xpass=/tmp/bkp.pas$time6	# passes info from "| while" subshell to this shell
Xibs=512			# dd option used by cpio backups (guess no "B" or "C")
Xobs=5120		# dd option used by cpio backups (guess no "B" or "C")
Xfileskip=0		# in "get" mode, assume it's a onedisk backup
Xmaxvol=20		# in "get" mode, max number of volumes in backup set
Xonline=''		# used to make sure the media is on line
Xfirstvol=''		# used to make sure we didn't leave vol 1 on by mistake
Xvlist=/tmp/bkp.vlist	# in "verify" mode, output from "restore tfv ..."
Xwhodid=/tmp/bkp.whodid	# in "get/verify" modes, $OPER from original backup
Xprobto=${probto-root}	# who do we send problems to (redefined by $PROBTO)
Xrptto=${rptto-$STASH}	# who do we send reports to
X# get info from sysadmin environment file /etc/saenv
Xlhost=$HOST		# local hostname
Xrsh=$RSH_C		# remote shell command
Xepre="$ECHOPRE"		# echo's no-newline prefix
Xesuf="$ECHOSUF"		# echo's no-newline suffix
X# removal list for cleanup
Xrmlist="$lockf $nobkptmp $mtestf1 $mtestf2 $mtestf3 $mtestf4"
Xfstablist="checklist filesystems fstab vfstab"
X## first major initialization chunk ends here
X
X###############################################################################
X
X## define character strings and macros which may be used repeatedly.
X##
X## A macro is a single-quoted or double-quoted string which contains
X## shellscript code.  To use a macro, simply "eval" it.  When eval'ing a
X## a macro, it may be unquoted or double-quoted.  How you write the macro's
X## shellscript code depends on whether or not you intend to double-quote
X## it when you invoke it.
X##	a) eval $MACRO
X##		* newlines are not preserved in the code, so ...
X##		* the macro can't have comments (except at the very end), and
X##		* the macro must have semicolons at the end of each command
X##	b) eval "$MACRO"
X##		* newlines are preserved in the code, so ...
X##		* the macro may contain comments
X##		* the macro does not need semicolons at the end of each command
X## The reason for the difference is that newlines are preserved by eval when
X## eval'ing a double-quoted string, whereas newlines are not preserved
X## when eval'ing an unquoted macro.
X##
X## To embed a single quote (') into a single-quoted macro string, you have
X## to do something like the following:
X## MACRO='echo foo'"\'"'bar' ; eval "$MACRO" ; eval $MACRO
X## which would produce the following output:
X## foo'bar
X## foo'bar
X## The key to producing the singlequote output is the ("\'") part of the macro.
X## Note that this works whether or not you invoke the macro with doublequotes.
X
X# USAGE - usage message
XUSAGE="
Xusage:
Xbackup help
Xbackup examples
Xbackup usage
Xbackup level       /fsname                                  [host:]media [opts]
X       <full|incr> </fsname|alldisks|listN|unlisted>        [host:]media [opts]
Xbackup get    get_mode                                      [host:]media [opts]
X       get    <onedisk|listdisks|/fsname>                   [host:]media [opts]
Xbackup verify verify_mode                                   [host:]media [opts]
X       verify <onedisk|listdisks|/fsname|alldisks|lastdisk> [host:]media [opts]
Xbackup devcheck                                             [host:]media [opts]
Xbackup devcheck             [host:]<mtype>,/dev/<rewind>,/dev/<norewind> [opts]
X
XPlease use 'backup usage' and/or 'backup examples' to get more info."
X
X# USAGE_LONG - more info on usage
XUSAGE_LONG="$USAGE
Xmodes:		help, examples, usage, full, incr, get, verify, devcheck
Xmedia:		media = 'media alias' for various 'media types'; for example
X		cartN, datN, nullN, tapeN, tkN, or videoN,
X		where 'N' = unit number.
X		See '$devdata' for valid media hosts and media aliases.
X		'[host:]null', '[host:]file <filename>', and
X		'[host:]dir <dirname>' are also valid.
X		In devcheck mode, media can be an alias or real device names.
Xget_modes:	'listdisks' and '/fsname' get_modes imply we are restoring
X		from a multifilesystem backup
Xverify_modes:	'alldisks', 'listdisks', '/fsname', and 'lastdisk' imply
X		we are verifying filesystem(s) on a multifilesystem backup
Xmtype:		media type: cart, dat, tape, tk, or video
X
Xdir [host:]dirname	<dirname> is a directory of onedisk/alldisks archives
Xfile [host:]filename	<filename> is an ordinary file, not a tape device
X
Xopts (all options work with all modes, except as noted):
XE [ /fsname [cont] ] ...
X		get/verify: 'E' = number of *extra* volumes in backup set
X		For example a three-tape backup set has '2' extra volumes.
X		Specify '0' extra volumes if a backup has only one tape.
X		'/fsname ...' = first filesystem on each extra volume
X		'cont' = if that filesystem was continued from previous volume
X		'/fsname' can be 'unknown', but this is strongly discouraged
Xcpio		forces usage of cpio even if a version of BSD dump is available
Xcron		handle running from cron (by setting OPER=cron)
Xdemo		echo's media work without actually doing it
Xentire		get: restore entire archive
Xfifo		DG's dump2 can use fifo for answering queries
Xfsfalse		/fsname is not a filesystem - used to back up directories
Xheader		put a header file even on a onedisk backup tape (not implemented)
Xinteractive	get: do interarctive restore of archive (unsupported for cpio)
Xlist <listfile>	backup filesystems in <listfile>
XlistN		backup filesystems in $hdir/bkp.listN 
Xlock		set optional lock (mandatory lock set regardless for cpio work)
Xnoall		sets all 'no' options shown below
Xnoauto		verify: turn off autoverify mode
Xnocheck		skips the normal check of the rewind and norewind devices
Xnofitguess	skips the normal guess whether an alldisks will fit on media
Xnojoke		skips the normal cpio joke
Xnolabelq	skips the normal get/verify question to check info against label
Xnomail		skips the normal mailing of reports to $rptto
Xnooffline	skips the normal taking media offline
Xnoprobq		skips the normal question re did the backup fail or not
Xnotcont		get/verify: this filesystem is not continued on next volume
Xnoupdate	skips the normal update of /etc/dumpdates or ~backup/cpiodates
Xshowdd		tell backup.dd to show 'dd' commands
Xskip S		get/verify: skip 'S' number of tapefiles on this volume
Xtarget <dir>	get: put restoration tree into specified target directory"
X
XEXAMPLES="
XTypical backup commands are:
Xbackup full alldisks video0     # done perhaps one day each week
Xbackup incr alldisks video0     # done perhaps four days each week
Xbackup full /home dat0		# local onedisk backup of /home to dat0 drive
Xbackup full /home friend:cart0  # network onedisk backup to cart0 on 'friend'
X
XA typical onedisk backup/verify sequence might be:
Xbackup full /home cart0 nooffline	# make the 'onedisk' backup of /home
Xbackup verify onedisk cart0		# verify the 'onedisk' archive of /home
X
XA typical multi-filesystem backup/verify sequence might be:
Xbackup full alldisks video0 nooffline	# do alldisks backup, leave tape in
Xbackup verify alldisks video0		# verify all archives, eject tape
X
XOr, alternatively, you could do:
Xbackup full alldisks video0 verifytoo	# do alldisks backup and verify it too
X
XGet/Verification can ask lots of questions.  Many of them you can answer
Xin advance on the command line.  For example, you can tell 'alldisks' the
Xnumber of 'extra' volumes and the name of the first filesystem on each
Xextra volume:
X        a) an alldisks tape set with only one tape:
X                backup verify lastdisk dat0 0
X        b) an alldisks tape set with three tapes, telling alldisks the
X        names of the first filesystems on extra tape 2 and extra tape 3
X                backup verify lastdisk video5 2 /fs1_tape2 /fs1_tape3
X        c) same as example 'b)', but showing what to do if the first
X        filesystem on extra tape 2 is continued from the first tape;
X        notice the word 'cont' on the command line:
X                backup verify lastdisk video1 2 /fs1_tape2 cont /fs1_tape3
X
XAutoverification is turned on unless it is possible the archive we are
Xverifying could span multiple tapes, as in example 'c)' above.
X
XIf you need to recover a few files, or even an entire filesystem:
Xbackup get onedisk cart0        # get files from a onedisk backup
Xbackup get listdisks video5     # get files from an alldisks backup
Xbackup get /usr friend:dat1     # network get of /usr from an alldisks backup
X
XIf you know all the answers to questions asked in 'verify' mode:
Xbackup verify /home friend:dat0 2 /fs1_t2 /fs1_t3
X
XDitto for 'get' mode, if we have an alldisks backup with one extra tape:
Xbackup get /fsname friend:cart1 1 /fs1_t2 interactive target <target_dir>
X"
X
X# READ - if we are running from cron, it is impossible (and nonsensical)
X# to do a "read" from a terminal.  Obviously if the user does something
X# from cron so that dump/cpio/restore require a read from a tty there's
X# nothing we can do about that.  But we can keep alldisks from doing a
X# tty read.  This macro is used where appropriate.
X#
X# Note the final read is left to the user to decide what to read.  Therefore,
X# the last line of this macro *must* say "read<SPACE><SINGLE_QUOTE>".
XREAD='
Xif test "$cron" = true ; then
X	{
X		echo ''		# probably we need a newline to keep it pretty
X		echo "$pr: I need input from a terminal but I am running from cron."
X		echo "$pr: Quitting."
X	} | tee -a $workdir/$report
X	exit 1
Xfi
Xread '
X
X# KNOWNPROBS - used (via fgrep -f $problist) to check for messages similar to:
X# "DUMP: Can't open /etc/fstab for dump table information."	(This happens if /etc/fstab does not exist, and since dump can't read the dump table (dumpdates) then it does a backup from the epoch)
X# "DUMP: Cannot open /dev/rrf1a"	(check perms on device)
X# "DUMP: do you want to abort"		(dump may have been interrupted)
X# "DUMP: bread: (THIS SHOULD NOT HAPPEN)(dump got a block read error)
X# "DUMP: (This should not happen)bread from /dev/rrf4c [block 975706]: count=2048, got=-1" (SunOS 4.1.2)
X# "DUMP: read error! sector 49310 of /dev/rdsk/c0t1d0s6" (Solaris 2.3 ufsdump got a block read error)
X# "DUMP: can't create child: Resource temporarily unavailable" (Solaris 2.3 ufsdump for some unknown reason)
X# "DUMP: SIGSEGV()  ABORTING!"		(too many bread errors: SunOS 4.x)
X# "Lost connection to remote host."	(network connection died mysteriously)
X# "remotehost: Connection timed out"	(network connection never established)
X# "DUMP: The ENTIRE dump is aborted."	(various reasons ...)
X# "dump: The ENTIRE dump is aborted"	(various reasons under DEC_OSF/1 ...)
X# "/etc/dtmp: Permission denied"	(probably ran as "backup", not "root")
X# "/etc/dumpdates: Permission denied"	(dump/rdump couldn't read/write dumpdates on HP-UX)
X# "/etc/dump: Not found"		(or similar: /etc/saenv has bad DUMP_P entry)
X# "$pr: Backup of '$fs' ABORTED, need more room in /usr/tmp."	(like it says)
X# "$pr: Backup of '$fs' volume $fsvoln ABORTED."	(probably hit EOT or bad tape)
X# "dd: write error"	(check write protected, EOT, or bad tape)
X# "Permission denied."	(can happen in middle of alldisks to remote host)
X#
X#		See also $KNOWNFALSEPROBS !!
X#
X# We create $problist this way, rather than distribute it, because this
X# way we can maintain comments with the list of known problems.
XKNOWNPROBS="DUMP: Cannot open
XDUMP: Can't open /etc/fstab for dump table information.
XDUMP: can't create child:
X abort
X ABORT
Xbread
XConnection
Xconnection
Xdd: read error
Xdd: write error
X Not found
X not found
Xpermission denied
XPermission denied
Xread error"
X
X# KNOWNFALSEPROBS - some versions put out misleading messages, which we
X# may look like problems but really are not problems.
X# KNOWNPROBS - used (via fgrep -f $falseprob) to check for messages like:
X# Unfortunately, Pyramid's SVR4 also puts out the following error message:
X# UFSDUMP: NEEDS ATTENTION: Do you want to restart?: ("yes" or "no")
X# UFSDUMP: This tape will rewind.  After it is rewound,
X# UFSDUMP: replace the tape and this dump volume will be rewritten,
X# UFSDUMP: or abort and restart the dump, specifying correct tape capacity.
X# notice::::::^^^^^ the word abort here is misleading
XKNOWNFALSEPROBS="DUMP: or abort and restart the dump,"
X
X# QUOTEDQ - the letter 'q' quoted in single quotes, needed by EXITQ and BREAKQ
X# You would think there'd be an easier way, but there's not.
XQUOTEDQ="'q'"
X
X# SQUOTE - A single quote suitable for being echo'ed by a macro
X# may need to be used like MACRO='echo "$pr: Can${SQUOTE}t do something" ;'
XSQUOTE="'"
X
X# EXITQ - Does user want to quit/exit program?
XEXITQ='
Xecho $epre "$pr: Enter $QUOTEDQ to quit, anything else to continue: "$esuf
Xeval "$READ" ans
Xcase $ans in
X[qQ]*)	echo "$pr: OK, will quit.  Bye." ; exit ;;
Xesac
X'
X
X# BREAKQ - break out of current loop?
X# This is tricky.  For starters, we have to ask the user this question
X# but we can't read from standard in since dd may be reading from there.
X# But we still want to read from the terminal so we read from
X# /dev/tty and close the input with awk.  Then, getting the quoting
X# and variable evaluation correct is a bit of a mess too.
X# Last, we say we are quitting but we do actually do a 'break', not an 'exit'.
XBREAKQ='
Xecho $epre "$pr: Enter $QUOTEDQ to quit, anything else to continue: "$esuf
Xans=`awk '"'{print ; exit}'"' < /dev/tty`
Xcase $ans in
X[qQ]*)	echo "$pr: OK, will quit.  Bye." ; break ;;
Xesac
X'
X
X# CHECKQ - double check with the operator to see if they really want to do
XCHECKQ='
X	while : ; do
X		echo $epre "$pr: $checkq [yn] "$esuf
X		eval "$READ" ans
X		case "$ans" in
X		y*|Y*)	echo "$pr: OK, just checking.  Will do."   ; break ;;
X		n*|N*)	echo "$pr: OK, we won'"'"'t do one.  Bye." ; exit ;;
X		*)	echo "$pr: Answer '"'y' or 'n'"'." ; continue ;;
X		esac
X	done
X'
X
X# MREADYQ - Is the media ready?
XMREADYQ='
Xecho $epre "$pr: Press <RETURN> when the $media is on line: "$esuf
Xeval "$READ" gaba_gaba_hey
X'
X
X# define awk script to look at backup reports
XBRPT_AWK='
X# output format
XBEGIN {
X	# set up printf formats for the label
X	topbottom="\t\t+---------------------------------------+\n"
X	label="\t\t| %-9s %-11s NA of NA        |\n\t\t| %-21s %s %02d-%s-%s |\n"
X}
X# get filesystem arg
X$1 == "#Invocation:" {
X	print "\t" $0
X	for (i=2; i<=NF; i++)
X		if ($i ~ /\/|alldisk|list[0-9]/) {
X			fs=$i
X		} else if ($i ~ /list/) {
X			fs=sprintf("list=%s", $(i+1))
X		}
X}
X# get alldisks backup script version
X$1 == "#Version:" {
X	version=$2
X}
X# get date info
X$1 == "#Start" {
X	weekday=$3; month=$4; day=$5; time=$6; tzone=$7; year=$8
X}
X$1 == "#Workdir:" {
X	print "\t" $0
X}
X# get other info
X/^[^\#]/ {
X	lhost=$1; mhost=$2; mode=$3; media=$4; mdev=$5; multi=$6; OPER=$7;
X}
X# print label info
XEND {
X	printf("\tOPER=\t     %s\n", OPER)
X	if (length(version)) {print "\tversion=" version}
X	print "\tlabel="
X	printf(topbottom)
X	if (mhost != lhost) {printf("\t\t| Remote Host: %-24s |\n", mhost)}
X	printf(label, lhost, mode, fs, weekday, day, month, year)
X	printf(topbottom)
X	print OPER > "'"$whodid"'"
X}
X'
X
X# report original command line invocation, check against label
X# note - report_p is path to report file we're trying to check.
XLABELQ='
X# our parent may have already done this
Xif test -z "$parent" ; then
X	if test $labelq = true ; then
X		echo "$pr: Operator $OPER - Check this info against the label on the $media:"
X	else
X		echo "$pr: Operater $OPER - Skipping label check:"
X	fi
X	awk "$BRPT_AWK" $report_p
X	if test $labelq = true ; then
X		eval "$EXITQ"
X	fi
Xfi
X'
X
X# SHOWDD shows user what's happening with dd commands if showdd is true
XSHOWDD='
Xtest "$showdd" = true && echo $pr showdd:'
X
X# REW macro rewinds the media, if appropriate
XREW='
Xcase $mtype in
Xdir|file|null)
X	: nothing to rewind
X;;
X*)
X	if test -n "$mt" ; then
X		echo "$mt $rewdev rewind" >> $workdir/$report
X		$mt $rewdev rewind
X	else
X		eval $SHOWDD Rewind $media
X		echo "$bdd if=$rewdev of=/dev/null count=1 bs=$mtestibs 2> /dev/null" >> $workdir/$report
X		$bdd if=$rewdev of=/dev/null count=1 bs=$mtestibs 2> /dev/null
X	fi
X	if test $? -ne 0 ; then
X		echo "$pr: The $media rewind is acting strangely."
X		echo "$pr: Please look at the $media drive."
X		echo $epre "$pr: Press <RETURN> after the $media is rewound: "$esuf
X		eval "$READ" axis_bold_as_love
X	fi
X;;
Xesac
X'
X
X# OFFLINE macro rewinds media and tries to take it offline if necessary
XOFFLINE='
Xeval "$REW"
Xif test $? -eq 0 -a -n "$mt" -a $offline = true ; then
X	echo "$pr: Taking the $media offline."
X	echo "$mt $rewdev offline" >> $workdir/$report
X	# DG SVR4 "mt" uses "unload" instead of "offline".  Their "offline"
X	# command is a noop.
X	# NCR SVR4 and Tandem NonStop-UX 4.0:
X	# "mt" does not support the "offline" command even though
X	# their mt(1) man page says it does.  The "unload" command does not
X	# work either.
X	case "$VENDOR_S$OS_S$OSLEVEL_S" in
X	*dgux5.4R2.*)		$mt $rewdev unload ;;
X	*NonStop-UX*|NCR*)	: do nothing ;;
X	*)			$mt $rewdev offline ;;
X	esac
Xfi
X'
X
X# CHKMEDIA - suggests fixes for media read/write problems
XCHKMEDIA='
Xecho "$pr: -> Is the drive on line?"
Xecho "$pr: -> If $mhost:$media has a tape switch, is it set to $mhost?"
Xecho "$pr: -> Does cycling power on the drive help?"
Xecho "$pr: -> Does cleaning the drive help?"
Xecho "$pr: -> Are the cables to the drive OK?"
Xecho "$pr: -> Is someone else really using the drive (check with '"'"'ps $PSALL_K'"'"')?"
Xecho "$pr: -> Is the tape broken?"
Xecho "$pr: -> Does the drive have a fault light?"
Xecho "$pr: -> Does rebooting the machine help?"
Xecho "$pr: Please fix the problem."
X'
X
X# CHKMWRITE - reports media write problem and suggests fixes.
XCHKMWRITE='
Xecho "$pr: Can'"'"'t write to the $media.  Check:"
Xecho "$pr: -> Is the $media write-protected?"
Xcase $mtype$OS_S$OSLEVEL_S in
XcartAIX3*)	echo "$pr: -> Is the $media a '"'"'3M 6150'"'"'?" ;;
Xcart*)		echo "$pr: -> Is the $media 12,500ftpi-compatible?" ;;
Xesac
Xeval "$CHKMEDIA"
X'
X
X# CHKMREAD - reports media read problem and suggests fixes.
XCHKMREAD='
Xecho "$pr: Can'"'"'t read from drive $media.  Check:"
Xeval "$CHKMEDIA"
X'
X
X# MAILRPT - if we're sending $report to $rptto, do it
XMAILRPT='
Xtest $mail = true && $MAILER -s $report,$lhost $rptto < $workdir/$report
X'
X
X# PROBTO - define who we send problems reports to
XPROBTO='
X# if mode is get or verify, ask if we want to send problem report
X# else send problem report automatically
Xcase "$mode$OS_S" in
Xget*|verify*)	probto="ct-3@$SAHOST"  ;;
X*ULTRIX)	probto="ct-16@$SAHOST" ;;
X*)		probto="ct-12@$SAHOST" ;;
Xesac
X'
X
X# LNFSTABLIST - link fstab list from parent
XLNFSTABLIST='
X	# for multi-fstype OS such
X	# as NonStop-UX
X	for f in $fstablist ; do
X		ln ../$f . 2> /dev/null
X	done
X'
X
X# SKIP2ARCHIVE - position tape on correct archive for get or verify
XSKIP2ARCHIVE='
X# The code tries to handle the case when we do not know which volume
X# the backup is on, based on the assumption that hitting EOT will
X# generate a message of some sort.  If this assumption is wrong, there is
X# no possibility of developing a successful strategy.  Another assumption
X# is that an incomplete dump at EOT is successfully skipped by mt "fsf".
X# True/false/NA values for both assumptions are shown below:
X#
X#		"fsf" works
X#	EOT	for partial
X#	message	dump		hardware		attached to
X#	-------	---------------	-----------------------	-----------------
X#	true	true		E8200 Sun		Sun 4/690
X#	false	NA		E8500 MicroTechnologies	Sun 4/380
X#
X# make sure tape is been rewound after getting the tar
X# header file - needed for slow rewind on video drives
Xeval "$REW"
Xcurdir=`pwd`
Xcd $workdir
Xif test $mtype = dir -o $mtype = file ; then
X	fileskip=0
X	echo	"#skipcmd: mtype $mtype - nothing to skip" >> $report
Xelif test -n "$mt" ; then
X	echo	"#skipcmd: $mt $norewdev fsf 1 2>&1 | tee err.mt | wc -l" >> $report
Xelse
X	echo	"#skipcmd: $bdd if=$norewdev of=/dev/null bs=$mtestibs 2>&1 | tee -a err.dd" >> $report
Xfi
Xn=0		# number of tapefiles we have successfully skipped
Xwhile test $n -lt $fileskip ; do
X	# try to skip a file:
X	# if we have mt
X	if test -n "$mt" ; then
X		# we hope that mt will report errors,
X		# which the subshell will put to
X		# standard out or standard error
X		echo "$pr: $mt $norewdev fsf 1 2>&1 | tee err.skip | wc -l"
X		skipstat=` $mt $norewdev fsf 1 2>&1 | tee err.skip | wc -l`
X	# else we have to emulate mt somehow
X	else
X		eval $SHOWDD Use dd to forward-skip-file
X		echo "$bdd if=$norewdev of=/dev/null bs=$mtestibs 2>&1 | tee -a err.skip"
X		$bdd       if=$norewdev of=/dev/null bs=$mtestibs 2>&1 | tee -a err.skip
X		skipstat=$?
X	fi
X	# mt commands for HP-UX dat drives return 2-3 seconds before the tape
X	# actually finishes positioning itself
X	case $OS_S$mtype in
X	HP-UXdat)	sleep 4 ;;
X	esac
X	# if we skipped a file
X	if test $skipstat -eq 0 ; then
X		n=`expr $n + 1`
X		echo "$pr: Skipped $n of $fileskip $media files." | tee -a $report
X	# else we ran off the end of the media or hit a bad spot (we assume
X	# we hit EOT, and pretty much ignore the bad spot possibility)
X	else
X		# try to take the tape offline in background while we
X		# do a bit of work
X		eval "$OFFLINE" &
X		cat err.skip | tee -a $report
X		echo "$pr: Error skipping `expr $n + 1` of $fileskip $media files." | tee -a $report
X		echo "$pr: Time to make some guesses:"
X		echo "$pr: Guess: We hit End-Of-Tape (but it could be a bad spot on the $mtype)."
X		echo "$pr: Guess: It was not on volume $onvol."
X		echo "$pr: Guess: The last media file we skipped on volume $onvol"
X		echo "$pr: was an incomplete archive."
X		# do some calcs now ...
X		onvol=`expr $onvol + 1`			# is it on next volume?
X		x=`awk "NR==$n {print \\$NF}" $dfout`	# 1st fs on next volume
X		n=`expr $n - 1`				# for incomplete archive
X		fileskip=`expr $fileskip - $n`		# recalc $fileskip
X		n=0					# reset "skipped" count
X		# record new guesses and report to operator
X		echo "#fs=$fs bkpn=$bkpn onvol=$onvol fileskip=$fileskip" >> $report
X		echo "$pr: Guess: We have to skip $fileskip file(s) on volume $onvol"
X		echo "$pr: to position the $media at the backup of $fs."
X		echo "$pr: Guess: The first filesystem on volume $onvol is $x"
X		echo "$pr: Please WRITE '\''Guess:$x'\'' ON VOLUME $onvol."
X		eval "$EXITQ"
X		echo "$pr: Please mount volume $onvol."
X		# wait for offline attempt to complete
X		wait
X		eval "$MREADYQ"
X	fi
Xdone
Xcase $mtype in
Xdir|file)	: do nothing ;;
X*)		echo "$pr: We have positioned the $media." ;;
Xesac
Xcd $curdir
X'
X
X# DO_GETCORE - the core of the DO_GET macro
X# This macro needs definitions for $getlist, $rans, $rmode, and $rout
XDO_GETCORE='
X	# must redefine getcore every time because
X	# 	1) $rmode can change in the middle of the script for a verify
X	#	2) $restore can change for Tandem
X	# $getlist is provided because
X	#	1) someday we may figure out how to do a selective/interactive
X	#	   cpio restore
X	#	2) when verifying using restore, the extraction phase needs it
X	case $mhost in
X	$lhost)	mhostdev=$mdev        ;;
X	*)	mhostdev=$mhost:$mdev ;;
X	esac
X	rkey=$rmode$roptkey
X	cpiocore="cpio -icdum$ckey $getlist"
X	case $bprog$mhost/$OS_S in
X	cpio$lhost/*)	getcore="                      $cpiocore < $mdev" ;;
X	cpio*/*)	getcore="$bdd if=$mdev bs=5k | $cpiocore        " ;;
X	*/DEC_OSF/1)	getcore="$restore -f $mhostdev     -$rkey $ropts" ;;
X	*/*)		getcore="$restore $DRMINUS$rkey $mhostdev $ropts" ;;
X	esac
X	case $bprog in
X	cpio)	getcmd="$getcore" ;;
X	*)	getcmd="$rans $getcore $getlist $rout" ;;
X	esac
X	eval echo \""$pr: $getcmd"\" | tee -a $workdir/$report
X	eval "$getcmd"
X	getstat=$?
X	echo "getstat=$getstat" >> $workdir/$report
X'
X
X# DO_GET - things we always do when getting something from an archive
XDO_GET='
X	# special code for  NonStop-UX4.0 which has both
X	# vxfs and ufs filesystem types.
X	case "$OS_S$OSLEVEL_S" in
X	NonStop-UX4.0)
X		# if we are trying to verify a onedisk backup
X		if test ! -f $workdir/vfstab ; then
X			: do nothing, but pray we have the correct restore
X		# else try to determine the correct restore from vfstab;
X		# we should have vfstab if we are doing an alldisks
X		# verify, or if our parent is an alldisks verify
X		else
X			fstype=`awk "/^#/ {next} ; \\$3 == \"$fs\" {print \\$4}" $workdir/vfstab`
X			case $fstype in
X			ufs)	restore=$RESTOR_P ;;
X			vxfs)	restore=/sbin/vxrestore ;;
X			esac
X		fi
X	;;
X	esac
X	eval "$DO_GETCORE"
X	# and more special code ...
X	case "$OS_S$OSLEVEL_S" in
X	# else we guessed wrong about the correct restore program so
X	# try the other one
X	NonStop-UX4.0)
X		# Both ufsrestore and vxrestore under NonStop-UX4.0 use 31
X		# exit status for a successful table listing (but why?)
X		# and 32 for failure
X		case $getstat in
X		# we were lucky and the "ufsrestore" guess was correct
X		31)
X			: so do nothing
X		;;
X		# we were unlucky so try the other one
X		32)
X			case $RESTOR_P in
X			*/vx*)	restore=$RESTOR_P ;;
X			*/ufs*)	restore=/sbin/vxrestore ;;
X			esac
X			# we should not have to reposition the tape,
X			# since this is a onedisk backup
X			eval "$DO_GETCORE"
X		;;
X		esac
X	;;
X	esac
X'
X
X# EGREPF - egrep -f
X# if there are too many filesystems listed in the fsfilters or lists,
X# egrep -f <fsfilter|list> may cause egrep to croak:
X# egrep: regular expression too long
X# $EGREPF macro needs:
X#	egrepff		egrep pattern file	must exist
X#	egrepfi		egrep input file	can be null or real file(s)
X#	egrepfo		egrep output file	can be null or a real file
X#	egrepfr		egrep '-v' flag		can be null or '-v'
X# The 'eval' and $outcode are required since some OS (Pyramid's OSx and
X# DEC's Ultrix) don't handle 'eval "$EGREPF" > some_output_file' kindly.
X# The 'cat' commands are to work around a NonStop-UX4.0 bug in "egrep -f"
X# ('egrep -f $egrepff somefile' breaks :-( ) and to allow $egrepfi to have
X# more than one file
XEGREPF='
X	case "$egrepfo" in
X	"")	outcode="" ;;
X	*)	outcode=">> $egrepfo" ;;
X	esac
X	echo oh_blah_dee_oh_blah_dah \
X	| egrep -f $egrepff 2>&1 \
X	| egrep "egrep: regular expression too long" > /dev/null
X	# if we do not have the problem, life is easy
X	if test $? -ne 0 ; then
X		cat $egrepfi | eval egrep $egrepfv -f $egrepff $outcode
X	# else we have to deal with it
X	else
X		split -5 $egrepff egrepf.
X		# if -v, do egreps in a pipeline
X		case $egrepfv in
X		-v)
X			for i in egrepf.* ; do
X				if test -z "$egrepcmd" ; then
X					egrepcmd="egrep -v -f $i"
X				else
X					egrepcmd="$egrepcmd | egrep -v -f $i"
X				fi
X			done
X			cat $egrepfi | eval $egrepcmd $outcode
X		;;
X		# if not -v, grep through each split file in turn
X		"")
X			for i in egrepf.* ; do
X				cat $egrepfi | eval egrep -f $i $outcode
X			done
X		;;
X		*)
X			echo "$pr: EGREPF macro: egrepfv must be empty or -v."
X			exit 1
X		;;
X		esac
X		rm egrepf.*
X	fi
X'
X
X# FSNNPLUS1 - increment $fsnn
XFSNNPLUS1='
Xfsnn=`expr $fsnn + 1`
X# make sure $fsnn is two digits (need for later sorting)
Xcase $fsnn in
X[0-9])	fsnn=0$fsnn ;;
X*)	fsnn=$fsnn ;;
Xesac
X'
X
X# MDEV - need to reassign $mdev if we're a dir or file
XMDEV='
Xcase $mtype$diskfile$multi in
Xdir-false|file-false)	mdev="-" ;;
Xdir*false|file*false)	mdev=$mdevbase ;;
Xdir-true|file-true)	echo "$pr: Cannot do alldisks to STDOUT" ; exit 1 ;;
Xdir*true|file*true)	mdev=$mdevbase.$fsnn ;;
Xesac
X'
X
X# GVRPT_ED - ed script to edit get/verify output from restore
X# the "1kx" is as close as I can find to a no-op in ed, inserted to make
X# the substitutions look prettier
X# we want to add newlines for typical "restore" output like
X#	restore ><SPACE>
X#	Specify next volume #:<SPACE>
X#	set owner/mode for '.'? [yn]<SPACE>
X#	continue? [yn]<SPACE>
X#	Directories already exist, set modes anyway? [yn]	# Solaris 2.1
X#	then enter volume name (default: /dev/rast4)		# Dynix/ptx
X# to make $gvreport more readable
X# These regular expressions will also work for "ufsrestore > " and such.
XGVRPT_ED='1kx
Xg/restore > /s//&\
X/g
Xg/? \[[yn]*\]* */s//&\
X/g
Xg/[sS]et owner\/mode for .... \[[yn]*\]* */s//&\
X/g
Xg/[dD]irectories already exist, set modes anyway? \[[yn]*\] */s//&\
X/g
Xg/[sS]pecify next volume \#: /s//&\
X/g
Xg/then enter volume name .*/s//&\
X/g
Xw
Xq
X'
X
X###############################################################################
X
X# source the site-defined post-definition macro here, immediately after
X# defining initial simple variables and MACROs, and before we start
X# getting other information from the command line
Xeval "$DOPOSTDEFS"
X
X## report version number
Xecho "$pr: 'alldisks' backup script, version $version"
X
X## get invocation (command line) options
X# options can be in any order since they're unique
X# more option checking happens later
X# getmode is actually used for "verify" mode too
Xtest -n "$cmdargs" && set $cmdargs
Xwhile test $# -gt 0 ; do
X	case $1 in
X	## examples/help/usage modes
X	examples)
X		echo "$EXAMPLES"
X		exit 0
X	;;
X	help)
X		echo "$USAGE"
X		exit 0
X	;;
X	usage)
X		echo "$USAGE_LONG"
X		exit 0
X	;;
X	## backup/get/verify/devcheck modes
X	f|full)
X		mode=full
X	;;
X	i|inc*)
X		mode=incr
X	;;
X	t|tinc*)
X		mode=tincr
X	;;
X	get)
X		mode=get
X	;;
X	verify)
X		mode=verify
X	;;
X	devcheck)
X		mode=devcheck
X		case "$2" in
X		# media spec'ed as [host:]<mtype>,/dev/<rewind>,/dev/<norewind>
X		*,*/dev/*,/dev/*)
X			media=devnames
X			mhost=`   expr $2 : '\(..*\):.*' \| $lhost`
X			mtype=`   expr $2 : '.*:\(..*\),.*,.*' \| $2 : '\(..*\),.*,.*'`
X			rewdev=`  expr $2 : '.*,/dev/\(..*\),.*'`
X			norewdev=`expr $2 : '.*,.*,/dev/\(..*\)'`
X			shift
X		;;
X		esac
X	;;
X	## valid as both getmodes and backup modes
X	/*)
X		multi=false
X		getmode=knownfs
X		fs=$1
X	;;
X	alldisk*)
X		multi=true
X		getmode=alldisks
X		multitype=alldisks
X	;;
X	## valid only as backup modes
X	list)
X		shift
X		multi=true
X		case "$1" in
X		'')	echo "$pr: No list file specified." ; echo "$USAGE" ; exit 1 ;;
X		/*)	listf=$1 ;;
X		*)	listf=$startdir/$1 ;;
X		esac
X		multitype=list
X	;;
X	list[0-9]*)
X		multi=true
X		listf=$hdir/bkp.$1
X		multitype=list
X	;;
X	unlisted)
X		multi=true
X		multitype=unlisted
X	;;
X	## valid only as getmodes
X	lastdisk)
X		multi=false
X		getmode=lastdisk
X	;;
X	listdisk*)
X		multi=false
X		getmode=listdisks
X	;;
X	onedisk)
X		multi=false
X		getmode=onedisk
X	;;
X	## media aliases and hosts
X	null|cart*|dat*|tape*|tk*|video*)
X		marg=$1
X		media=$1
X		mhost=$lhost
X	;;
X	*:null|*:cart*|*:dat*|*:tape*|*:tk*|*:video*|*:/dev/*,/dev/*)
X		marg=$1
X		media=`expr $1 : '.*:\(.*\)'`
X		mhost=`expr $1 : '\(.*\):.*'`
X	;;
X	dir|file)
X		marg=$1
X		media=$1
X		mhost=$lhost
X		mistape=false
X		offline=false
X		shift
X		diskfile=$1
X		#case $diskfile in "-") probq=false ;; esac
X	;;
X	*:dir|*:file)
X		marg=$1
X		media=`expr $1 : '.*:\(.*\)'`
X		mhost=`expr $1 : '\(.*\):.*'`
X		offline=false
X		shift
X		diskfile=$1
X	;;
X	## options
X	d|demo)
X		echo "$pr demo: media commands will be echoed, not done."
X		demo=true
X	;;
X	cpio)
X		bprog=cpio	# use cpio even if BSD dump is available
X		cpioarg=$1
X	;;
X	cron)
X		cron=true
X		probq=false
X		OPER=cron
X	;;
X	entire)
X		entire=true
X	;;
X	header)
X		#header=true
X		header=false
X		echo "$pr: NOTE: header option not implemented yet"
X	;;
X	interactive)
X		entire=false
X	;;
X	fifo)
X		opfifo="O $hdir/bkp.opfifo"	# dump2's output fifo option
X	;;
X	fsfalse)
X		fsbkp=false	# we're backing up an ordinary file/directory
X	;;
X	lock)
X		optlk=true
X	;;
X	noall)
X		autoverify=false
X		check=false
X		fitguess=false
X		joke=false
X		labelq=false
X		mail=false
X		offline=false
X		probq=false
X		update=false
SHAR_EOF
true || echo 'restore of src/backup/backup failed'
fi
echo 'End of saenv_alld part 4'
echo 'File src/backup/backup is continued in part 5'
echo 5 > _shar_seq_.tmp
exit 0
