News archiver for 3b1 tape drives, Part 2 of 2

Vernon C. Hoxie vern at zebra.UUCP
Sat Jan 6 22:39:04 AEST 1990


	This is the remainder of the scripts which will archive news
articles to tape and provice retrieval by subject.  Enjoy.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 2)."
# Contents:  Theory pick.files.c wr.tape.sh
# Wrapped by root at quagga on Fri Jan  5 21:24:52 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Theory -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Theory\"
else
echo shar: Extracting \"Theory\" \(7856 characters\)
sed "s/^X//" >Theory <<'END_OF_Theory'
X	The information supplied with the floppy tape machine isn't
Xoverly instructional.  Efforts to produce variations to the canned
Xprocess provided are frustrated by lack of ioctl(2) or by header files.
XEven a definition of the tape header is missing.
X
X	When formatting the tape, references are made to 6 streams and
X254 segments.  I interpret 'streams' to mean 'tracks' made by a six layer
Xrecording head.  Why there are 254 'segments' instead of a round number
Xlike 255 segments is weird.  And how many 'bytes' to a 'segment' is
Xnever defined.
X
X	I have experimentally determined that a tape without any defective
X'segments' can hold 45566 blocks of data with 512 bytes per block.  If
Xthe two tape header blocks are added, this comes to a round 0xb200
Xblocks.  But this value doesn't divide by the six tracks into an even
Xnumber.  So, how many blocks are there?
X
X	The 45566 number was determined by nearly filling a tape and
Xthen testing for overflow with 'Tmakesslist'.  This program returns
X-1 if the size of the file collection to be taped is greater than the
Xspace available on the tape.  The size of the test collection was
Xreduced by 512 bytes until a '0' was returned from 'Tmakesslist'.
XThis is the same tactic used in 'wr.tape' to fill the ninth part of the
Xtape.
X
X	Since the manual refers to each tape as a "volume", I have
Xadopted the term "chapter" to refer to the nine parts of the tape.
X
X	This 'suite' of four scripts is designed to be run independently.
XThe four parts are 'squirrel.sh', 'prep.sh', 'wr.tape.sh' and 'rd.tape.sh'.
X'Wr.tape.sh' does need a parent process which has exported the needed
Xdefinitions.  The scipts are supported by 'read.vtoc.c', 'group.c', and
X'pick.files.c' and the common script 'header.sh'.
X
X	The general concept is that 'squirrel' searches the directories
Xlisted in 'save.list'.  For each article it finds, it examines the
X"Message-Id:" number and compares this number against the entries in the
X'link.list' file.  Failing to find an entry in 'link.list', the article
Xis linked into '/news/.tape.ops/arcdir'.  A successful comparison of the
X"Message:Id:" indicates that the current article has already been queued
Xfor taping during an earlier pass through the directories.  Each time
X'squirrel' is run, the 'link.list' is examined as to how long each entry
Xhas been held.  Entries over two months in age, are purged.
X
X	'Squirrel.sh' updates the 'params' file with the next number to
Xbe used for file names in the 'arcdir' and the total number of bytes
Xcurrently in the 'arcdir'.  It then calculates the ideal size the next
Xchapter of the tape and makes an estimate of the number of blocks the
Xsaved data will consume on the tape.  This information is then e-mailed
Xto the News Administrator.
X
X	When enough articles have been 'squirrelled' to fill a tape
Xchapter, 'prep.sh' should be called to process the articles for transfer
Xto tape.  Each article in the 'savdir' is examined and the "Subject: "
Xline is copied to the 'contents' file.  The file name ( a number ) is
Xappended to the subject line with a 'tab' character as delimiter.  This
Xnumber is used in ordering the files on the tape and for accessing the
Xarticles during read out.
X
X	After the 'contents' file is completed, it is sorted then the 'c'
Xsupport program, 'group', is called to bring similar titles together in
Xthe 'contents' file.  'Group' writes its result back to 'contents' and to
X'c.pntrs'.  'C.pntrs' has the file names ( numbers ) arranged in the same
Xorder that their titles appear in 'contents'.  This list is used to call
Xeach article in 'arcdir', strip the "Path: " line from the article and
Xput the compressed copy of the remainder of the article in 'savdir'. 
XThis step of the operation is excruciatingly slow!!  It takes nearly an
Xhour to process 800 articles.
X
X	The 'wr.tape' script goes through a series of status verification
Xtests to determine if the correct tape is inserted and is ready for
Xwriting.  It also requires that a 'contents' and a 'c.pntrs' file are
Xavailable.  The latest data pertinent to the writing operation is
Xextracted from the 'params' file.  'Tgetname' is then called to produce
Xa '/tmp/vtoc' file.  This file contains the tape header blocks.  A 'c'
Xsupport program named 'read.vtoc' is called to interpret the '/tmp/vtoc'
Xinformation.  'Read.vtoc' is a replacement for the 'TdsplSSs' program
Xbut without the obnoxious window.
X
X	Having determined the offset from 'read.vtoc', 'Tmakesslist' is
Xcalled to produce the 'ss.filelist'.  This file is used by 'tapecpio'
Xto write to the tape and needed by the read operation to access individual
Xfiles in a tape chapter.
X
X	'Tmakesslist' returns the number of tapes required to hold the
Xfile list presented to it.  Since our file lists are approximately the
Xsize of 1/9 th of a tape, this is no consequence except when writing to
Xthe last chapter.  In order to fill this last chapter, the number of
Xfiles presented to 'wr.tape' and 'Tmakesslist' should be more than
Xenough to fill the tape.  The list is trimmed article by article until a
Xfit is accomplished.  Files written to tape are removed from the 'arcdir'
Xafter the write operation.  The articles which were trimmed remain in
Xthe 'arcdir' and are renamed ( renumbered ) and left as seed for the
Xnext write operation.
X
X	'Rd.tape' runs some of the same qualification tests on the tape
Xas 'wr.tape'.  It also uses 'read.vtoc' to present the Volume Table of
XContents to the user.  When a chapter is selected, the 'contents' file
Xis read from the tape and 'pick.files' is called to present this file to
Xthe user.  'Pick.files' opens a new full screen window and lists the
X"Subject:" lines from the saved articles.
X
X	This window can be scrolled one line at a time with the
X"Up Arrow" or the "Down Arrow" or a page at a time with the "Page"
Xor "<shift> Page" keys.  The "Home" and "<shift> Home" key select the
Xfirst page or last page of the file.  Individual articles are selected
Xby using the "Mark" key.
X
X	The mouse may also be used to browse the 'contents'.  When the
Xmouse icon points to the top or bottom line, and the center mouse button
Xis pressed, the display will scroll back or forward one line at a time.
XWith the icon elsewhere, the center button will cause the display to page
Xback or forward and the right button will select the head or tail of the
X'contents' depending as whether the icon is in the top or bottom half of
Xthe screen.  Articles are selected with the left mouse button.
X
X	Selected articles are displayed in reverse video and may
Xde-selected by either of the means by which they were selected.  Up to
X100 articles may be selected during each iteration of the 'rd.tape' script.
XThe display is terminated by pressing the 'q', 'Exit' or 'Save' key. 
XUpon termination, the selected file numbers are written to 'r.pntrs' and
Xfed to 'tapecpio' for retrieval.  Retrieved articles will be be found in
X'/news/.tape.ops/'tape name'/'chapter number'/'article number'.Z.  It will
Xstill be in the compressed format.
X
X	A second set of scripts are included to convert tapes which were
Xwritten by the standard process to the specaial compressed format.  This
Xprocess is excruciatingly slow.  Plan on taking a couple of days to
Xgenerate one compressed tape.
X
X	A copy script is provided which will copy chapters from a tape
Xgenerated by this process.  It is intended to be a recovery tool when
Xconfronted with a verification failure.  Read the comments at the
Xbeginning of 'copy.sh' before running.  This can probablly be hacked to
Xpermit copying tapes generated by the standard process.  I suggest that
Xthe you remove the references to CONFILE and CPNTRS from the 'wr.tape.sh'.
X
X	The 'wr.tape.sh' script requires that it be called from another
Xscript which has exported the necessary definitions.  This was so that
Xthe 'copy.sh' could use the standard 'wr.tape.sh' from the '/new/.tape.ops'
Xdirectory.
END_OF_Theory
if test 7856 -ne `wc -c <Theory`; then
    echo shar: \"Theory\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f pick.files.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"pick.files.c\"
else
echo shar: Extracting \"pick.files.c\" \(7691 characters\)
sed "s/^X//" >pick.files.c <<'END_OF_pick.files.c'
X/* This is a program to display the 'contents' file a previously	*/
X/* selected chapter of an archive tape produced by the 'prep' and 	*/
X/* 'wr.tape' scripts.  This program is designed to be specifically 	*/
X/* called by 'rd.tape'.  It expects that 'rd.tape' has already read 	*/
X/* a 'contents' file from the tape and that file is in the current 	*/
X/* working directory. 							*/
X/* 	This file produces a scrollable menu from which specific 	*/
X/* 	titles can be selected by positioning the cursor next to 	*/
X/* 	the desired title and pressing the 'Mark' key.  Selected 	*/
X/* 	titles are indicated by highlightling.  Any previoulsy 		*/
X/* 	selected title can be de-selected by again positioning the 	*/
X/* 	cursor next to the title and pressing the 'Mark' key. 		*/
X/* The output of this program is to a 'pntrs' file in the current 	*/
X/* working directory.  Since all files produced by 'prep' are numerical */
X/* with a '.Z' suffix, this is the format of the entries in 'pntrs'. 	*/
X/* 	Cursor motion is currently limited to the 'up-arrow', 		*/
X/* 	'dn-arrow', 'Home', 'Shift-Home', 'Page' and 'Shift Page' keys. */
X
X#include <fcntl.h>
X#include <malloc.h>
X#include <stdio.h>
X#include <sys/window.h>
X#include <sys/termio.h>
X
X#define lines 23
X#define PFILE "r.pntrs"
X/* Can we legally copy definitions from <mewu.h> ? */
Xtypedef struct
X{
X	char		*mi_name;	/* name of item			*/
X	char		mi_flags;	/* flags			*/
X	int		mi_val;		/* user-supplied value		*/
X} mitem_t;
X
Xmitem_t *pit, *r2, *top;
X
Xstruct termio tt;
Xstatic struct uwdata uw = { 0, 12, 720, 276, 0x1 };
X	/* 80 chars per line *  9 pixels per char = 720  */
X	/* 23 lines per page * 12 pixels per line = 276 */
Xstatic struct umdata um = { 0x09, 0, 12, 720, 12, 0 };
Xstatic struct utdata ud = { WTXTPROMPT,
X"Use 'Mark' to select titles, 'q' or 'Exit' to leave." };
X
Xint lncnt;
X
XFILE *fn;
X
Xmain()
X{
X	int i, fd;
X	if (( fd = open( "/dev/window", O_RDWR )) < 0 )
X	{
X		perror( "Opening window" );
X		exit();
X	}
X	ioctl( fd, TCGETA, &tt );
X	tt.c_lflag &= ~0112;		/* Set raw mode, no echo */
X	tt.c_cc[VMIN] = 1;
X	tt.c_cc[VTIME] = 1;
X	ioctl( fd, TCSETA, &tt );
X	ioctl( fd, WIOCSETD, &uw );
X	ioctl( fd, WIOCSETTEXT, &ud );
X	ioctl( fd, WIOCSETMOUSE, &um );
X	close(0);
X	dup(fd);
X	close(1);
X	dup(fd);
X	close(2);
X	dup(fd);
X	close(fd);
X	set_data();
X	top = r2;
X	lncnt = 1;
X	printf( "\033[2J" );		/* Erase screen */ 
X	write_page( );
X	while ( do_funct( ));
X	printf( "\033[2J\033[1;1H\033[0m" );
X		/* Home, Erase entire screen, Attributes to normal. */
X	fn = fopen( PFILE, "r+" );
X	for ( pit = r2; pit->mi_val; pit++ )
X		if ( pit->mi_flags ) fprintf( fn, "%d.Z ", pit->mi_val );
X	fclose( fn );
X	exit();
X}
X
Xset_data( )
X{
X	int in, lcnt;
X	long size;
X	char *p, *pq;
X	char *r1;
X	in = open("contents", O_RDONLY );
X	size = lseek( in, 0, 2 );
X	lseek( in, 0, 0 );
X	r1 = malloc( size );
X	read( in, r1, size );
X	close( in );
X	for( p = r1, lcnt = 0; p <= r1 + size ; p++ )
X		if ( *p == '\n' ) lcnt++;
X	r2 = (mitem_t *)calloc( lcnt + 1, sizeof( mitem_t));
X	for( p = pq = r1, pit = r2; p <= r1 + size; p++ )
X	{
X		if ( *p == '\t' )
X		{
X			*p = '\0';
X			pit->mi_name = pq;
X			pit->mi_val = atoi( ++p );
X			pit++;
X		}
X		else if ( *p == '\n' ) pq = ++p;
X	}
X	pit->mi_name = '\0';
X	pit->mi_flags = 0;
X	pit->mi_val = 0;
X	return;
X}
X
Xwrite_page( )
X{
X	int i;
X	pit = top;
X	printf( "\033[1;1H" );	/* Home */
X	for ( i = 1; i <= lines ; i++ )
X	{
X		if ( pit->mi_val == 0 )	break;
X		if ( pit->mi_flags ) printf( "\033[7m" ); /* Reverse */
X		else printf( "\033[0m" ); 	/* Normal video */
X		printf( "\033[=0w%s\033[0K", pit->mi_name );
X		pit++;
X		if ( i < lines ) putchar( '\n' );
X	}
X	if ( i < lines )
X	{
X		lncnt = --i;
X		printf( "\007\033[J" );
X				/* Beep & Erase to end of display */
X	}
X	printf( "\033[%d;1H", lncnt ); 		/* Cursor to 'lncnt' */
X	pit = top;
X	for ( i = 1; i < lncnt; i++ ) pit++;
X}
X	
Xdo_funct( ch )
Xchar ch;
X{
X	int i, x, y, button, reason, pos;
X	char report[25];
X	char *r;
X	ch = getchar( );
X	if ( ch == 'q' ) return( 0 );
X	else if (( ch = getchar( )) == '[')
X	{
X		switch ( ch = getchar( ) )
X		{
X			case 'A': move_up( ); 	/* "Up Arrow" */
X				  break;
X			case 'B': move_down( );	/* "Down Arrow" */
X				  break;
X			case 'H': home();	/* "Home" */
X			 if ( top == r2 )
X				{
X					putchar( '\007' ); /* Beep */
X					break;
X				}
X				lncnt = 1;
X				top = r2;
X				write_page( );
X				break;
X			case 'U': page_f();	/* "Page" */
X				  break;
X			case 'V': page_b();	/* "^Page" */
X				  break;
X			case '?':		/* "Mouse" */
X				r = report;
X				while (( ch = getchar( )) != 'M' )
X					*r++ = ch;
X				*r = '\0';
X				r = report;
X				x = 0;
X				while ( *r != ';' ) x = (x * 10)
X						+ ( *r++ & 0x0f );
X				y = 0;
X				r++;
X				while ( *r != ';' ) y = (y * 10)
X						+ ( *r++ & 0x0f );
X				button = 0;
X				r++;
X				while ( *r != ';' ) button = (button * 10)
X						+ ( *r++ & 0x0f );
X				reason = 0;
X				r++;
X				while ( *r ) reason = (reason * 10)
X						+ ( *r++ & 0x0f );
X				if ( reason & 0x8 )
X				{
X					i = lncnt - 1;
X					pos = y / 12;
X					if ( pos < i )
X							move_up();
X					else if ( pos > i )
X							move_down();
X					um.um_y = 12 * i;
X					ioctl( 1, WIOCSETMOUSE, &um );
X				}
X				switch ( button )
X				{
X					case 1:  /* Right button */
X						if ( lncnt < 12 ) home();
X						else tail();
X						break;
X					case 2: /* Middle button */
X						if ( lncnt == 1 )
X							move_up();
X						else if ( lncnt == lines )
X							move_down();
X						else if ( lncnt < 12 )
X							page_b();
X						else page_f();
X						break;
X					case 4:  /* Left button */
X						mark();
X						break;
X				}
X		}
X	}
X	else if ( ch == 'O' )
X	{
X		ch = getchar( );	/* "Exit" or "Save" */
X		if ( ch == 'k' || ch == 'o') return( 0 );
X	}
X	else if ( ch == 'N' )
X	{
X		switch ( ch = getchar( ))
X		{
X			case 'i': mark();	/* "Mark" */
X				  break;
X			case 'M': tail();	/* "^Home" */
X				  break;
X		}
X	}
X	return( 1 );
X}
X
Xmark()
X{
X	pit->mi_flags = ! pit->mi_flags;
X	if ( pit->mi_flags ) printf( "\033[7m" ); /* Reverse */
X	else printf( "\033[0m" ); /* Normal video */
X	printf( "\033[=0w%s\033[0K\015", pit->mi_name );
X}
X
Xtail()
X{
X	int i;
X	mitem_t *was;
X	i = 1;
X	was = top;
X	while ( (top++)->mi_val ) i++;
X	if ( i <= lines )
X	{
X		top = was;
X		putchar( '\007' );	/* Beep */
X		return;
X	}
X	for ( i = 0; i <= lines; i++ ) --top;
X	if ( top < r2 )	top = r2;
X	lncnt = lines;
X	write_page( );
X}
X
Xhome()
X{
X	if ( top == r2 )
X	{
X		putchar( '\007' ); /* Beep */
X		return;
X	}
X	lncnt = 1;
X	top = r2;
X	write_page( );
X}
X
Xpage_b()
X{
X	int i;
X	if ( top == r2 )
X	{
X		putchar( '\007' );	/* Beep */
X		return;
X	}
X	for ( i = 1; i <= lines; i++ ) top--;
X	if ( top < r2 )
X	{
X		top = r2;
X		putchar( '\007' );	/* Beep */
X	}
X	lncnt = 11;
X	write_page( );
X}
X
Xpage_f()
X{
X	int i;
X	mitem_t *was;
X	was = top;
X	for ( i = 1; i <= lines; i++ ) top++;
X	if ( ! top->mi_val )
X	{
X		top = was;
X		putchar( '\007' );	/* Beep */
X		return;
X	}
X	lncnt = 12;
X	write_page( );
X}
X
Xmove_up( )
X{
X	if ( lncnt <= 1 )
X	{
X		if ( top > r2 )
X		{
X			pit = --top;
X		if ( pit->mi_flags ) printf( "\033[7m" ); /* Reverse */
X		else printf( "\033[0m" ); /* Normal video */
X		printf( "\033M\033[=0w%s\033[0K\015",
X					pit->mi_name );
X/* \033M = negative line feed; \033[=0w = line wrapping off; 	*/
X/*  %s = write mi_name; \033[0K = erase to end of line;		*/
X/* \015 = put cursor at beginning of line 			*/
X		}
X		else putchar( '\007' ); /* Beep */
X		lncnt = 1;
X	}
X	else
X	{
X		printf( "\033[%d;1H", --lncnt );
X		pit--;
X	}
X}
X
Xmove_down( )
X{
X	if ( (++pit)->mi_val == 0 )
X	{
X		pit--;
X		putchar( '\007' ); /* Beep */
X		return;
X	}
X	if ( ++lncnt > lines )
X	{
X		if ( pit->mi_flags ) printf( "\033[7m" ); /* Reverse */
X		else printf( "\033[0m" ); /* Normal video */
X		printf( "\033[1S\015\033[=0w%s\033[0K\015",
X					pit->mi_name );
X		top++;
X		lncnt = lines;
X	}
X	else printf( "\033[%d;1H", lncnt );
X}
END_OF_pick.files.c
if test 7691 -ne `wc -c <pick.files.c`; then
    echo shar: \"pick.files.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f wr.tape.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"wr.tape.sh\"
else
echo shar: Extracting \"wr.tape.sh\" \(9334 characters\)
sed "s/^X//" >wr.tape.sh <<'END_OF_wr.tape.sh'
X# This is the sequence of operations to write squirrelled files to tape.
X# It requires that:
X#    1. The files have been previously compressed and moved
X# 	into the 'savdir'.
X#    2.	A 'pntrs' file exists which is a listing of the 'savdir' sans .Z
X#    3. A 'contents' file exists which contains the 'Subject: ' of each
X#	file in 'savdir' with a cross reference to its name in 'arcdir'.
X#
X#	These files are normally generated by 'prep' and this program
X# is called by 'prep'.  However, these operations may be aborted during
X# a 'prep' run and resumed by calling this program as a separate
X# operation if these three parameters exist.
X
Xif [ ! "$WRKDIR" ]
Xthen
X	echo "This script must be run as a function of another process
Xso that the correct files are accessed."
X	exit 1
Xfi
X
X
X# This should be the start of the program
X
Xecho `date +%T`" Starting writing operations. "
X
Xif [ ! -f $PARAMS ]
Xthen
X	echo "Whoops! There is no 'params' file so we don't know
Xwhat to write. "
X	exit 1
Xfi
X
Xif [ ! -f $CONFILE ]
Xthen
X	echo "Whoops! There is no 'contents' file so we don't know
Xwhat to write. "
X	exit 1
Xfi
X
X# These copies are made so that 'wr.tape.sh' may be resumed after
X# preparing another tape.
Xcp $CONFILE bk.contents
Xcp $CPNTRS bk.pntrs
X
X# Get params
Xname=`sed -n 's/Name of work tape:\	//p' $PARAMS`
Xpoffset=`sed -n 's/Blocks of offset:\	//p' $PARAMS`
Xtdate=`sed -n 's/Date last taped:\	//p' $PARAMS`
Xblks=`sed -n 's/Blocks available:\	//p' $PARAMS`
Xpchap=`sed -n 's/Next chapter number:\	//p' $PARAMS`
X
Xpau=0
Xwhile [ $pau = 0 ]
Xdo
X	Tgetname -t
X	ret=$?
X	if [ $ret != 0 ]
X	then
X		echo "Please insert a tape. Q)uit or <cr> to continue. \c"
X		read -r ch
X		if [ "$ch" = "q" -o "$ch" = "Q" ]
X		then
X			exit 1
X		fi
X	else
X# From here on, the tape drive is locked, any 'exit' must perform
X# 'Tgetname -l' to unlock the drive before leaving.
X		Tgetname +l
X		Tgetname -b > /dev/null
X		ret=$?
X		set `Tgetname -r | tr -d "'"`
X		tname=$1
X		toffset=$2
X		if [ $ret = 30 ]
X		then
X			Tgetname -l
X			echo "\n\tThis tape has the \"SAFE\" key set.
X\tPlease exchange it for a tape we can write onto.
X\t	<cr> to continue. Q)uit."
X			read -r ch
X			if [ "$ch" = "q" -o "$ch" = "Q" ]
X			then
X				exit 1
X			fi
X		elif
X# 'read.vtoc -w9' will write all used chapters to standard out in column
X# format.  'read.vtoc -c' puts the next chapter number and the next offset
X# on standard output.  A return of '10' indicates that the tape is full.
X
Xecho `date +%T`" The contents of tape \""$tname"\" are:"
X			$SRCDIR/read.vtoc -w9
X			set `$SRCDIR/read.vtoc -c`
X			chap=$1
X			offset=$2
X			[ $chap -gt 9 ]
X		then
X			Tgetname -l
Xecho "\tWhoops!  This tape has all the chapters filled.  Shall we q)uit
X\tnow so that you restart another day or w)ait for another tape to cycle?
X\tEnter \"q\" or \"w\" to wait. \c"
X			read ch
X			if [ "$ch" = "q" -o "$ch" = "Q" ]
X			then
X				exit 1
X			fi
X		else
X			if [ "$poffset" -ne "$offset" ]
X			then
X				echo \
X	"\tThere is a descrepancy about which chapter should be written
X	next.  The parameters file says chapter $pchap at offset $poffset
X	while the tape says chapter $chap should be at $offset blocks.
X	Enter your choice for the chapter number. \c"
X				read ichap
X				if [ "$ichap" = "$pchap" ]
X				then
X					chap=$pchap
X					offset=$poffset
X				fi
X				echo \
X"Enter a value for the offset if $offset is unsatisfactory.
X		<cr> for OK. \c"
X				read ch
X				if [ "$ch" != "0" ]
X				then
X					offset=$ch
X				fi
X			fi
X			if [ "$tname" != "$name" ]
X			then
X				echo \
X"\tYou may have inserted the wrong tape.
X\tThis tape name is \""$tname"\" and I was expecting \""$name"\".
X\tThere are "$toffset" blocks of data already on this tape.
X\tOkay to write to this tape? <y/n> \c"
X				read -r ch
X				if [ "$ch" = "y" -o "$ch" = "Y" ]
X				then
Xecho "Shall we change the name to \""$name"\" or leave it \""$tname"\"?
XEnter 'k' to keep it as \"tname\", <cr> to continue. \c"
X					read ch
X					if
X					[ "$ch" = "k" -o "$ch" = "K" ]
X					then
X						name=$tname
X					fi
X				fi
X			fi
X		pau=1
X		fi
X	fi
X	if [ "$ch" = "w" -o "$ch" = "W" -o "$ch" = "n" -o "$ch" = "N" ]
X	then
Xecho "\tWaiting for another tape to be inserted.
X\t<cr> to continue. Q)uit \c"
X		read -r ch
X		if [ "$ch" = "q" -o "$ch" = "Q" ]
X		then
X			Tgetname -l
X			exit 1
X		fi
X		ret=1
X	fi
Xdone
X
X# Whew, don't ask me how we got through all those queries but I think
X# that there is one path through there that doesn't have a stop.
X
Xecho `date +%T`" Preparing file lists. "
Xscalped=0
X
Xif [ ! -f $SAVDIR/contents ]
Xthen
X	ln $CONFILE $SAVDIR/contents
Xfi
Xcd $SAVDIR
Xwhile
X	echo "contents" > $WRKDIR/BUfiles
X	while
X		read pntr
X	do
X		echo "$pntr.Z" >> $WRKDIR/BUfiles
X	done < $CPNTRS
X	TmakessList $offset <$WRKDIR/BUfiles > ss.filelist
X	numtps=$?
X	[ $numtps -gt 1 ]
Xdo
X# This trims down the entries in the 'savdir' until it will fit on
X# the end of the tape.  The CPNTRS file will also be trimmed.  Later
X# we will remove the entries in ARCDIR which are still in CPNTRS.
X# The rest of ARCDIR will be relabelled for the next tape.
X	> $TMP2
X	if [ $scalped -eq 0 ]
X	then
X		echo \
X"\tStandby! The file list is being trimmed to fit the tape!!
X\tThere will be some messages issued stating:
X\t\t'insert next floppy tape'.
X\tIgnore those messages and respond with a <cr>."
X		scalped=1
X	fi
X	last=`sed -n '$ !w '"$TMP2"'
X			$ p' < $CPNTRS`
X	sed '$ d' < $CONFILE > $TMP1
X	mv $TMP1 $CONFILE
X	mv $TMP2 $CPNTRS
Xdone
X
Xif [ $chap -eq 9 -a $scalped -eq 0 ]
Xthen
X	echo \
X"\tThis is the last chapter available on this tape and space is going
X\tto be left over.  Do you want to abort now and rerun this after you
X\thave collected more files? <y> to abort, <n> to continue. \c"
X	read ch
X	if [ "$ch" = "y" -o "$ch" = "Y" ]
X	then
X		Tgetname -l
X		rm -r $SAVDIR
X		rm -f /tmp/tape.vtoc
X		rm -f /tmp/ss.osets
X		rm -f /tmp/size*
X		rm -f $PWD/ss.filelist
X		rm -f $PNTRS
X		rm -f $CPNTRS
X		rm -f BUfiles
X		rm -f $CONFILE
X		rm -f $CPNTRS
X		rm -f bk.contents
X		rm -f bk.pntrs
X		rm -f /tmp/BUlist*
X		exit 1
X	fi
Xfi
X
Xecho `date +%T`\
X" Writing chapter $chap to tape '$name' starting at block $offset."
Xecho "ss.filelist" > /tmp/BUlist$$
Xcat /tmp/BUlist$$ $WRKDIR/BUfiles | tapecpio -ocvT124 2>/tmp/size$$ | \
X	   dbuf -oT124O$offset > /dev/rft3
Xret=$?
Xif [ "$ret" != "0" ]
Xthen
X	if [ $ret = 4 ]
X	then
X		echo "This tape operation has been aborted."
X		Tgetname -l
X		exit 1
X	else
X		echo "\
X\tAn error has occured while trying to create this backup-set.
X\tCheck that a formatted tape has been properly inserted and has
X\tfinished rewinding."
X
X	fi
Xfi
X
Xeval set `grep "blocks" /tmp/size$$`
XNBLOCKS=$1
X
Xset `wc -l ss.filelist`
XNFILES=$1
X
Xecho `date +%T`" Performing verify pass."
X
Xdbuf -iT124O$offset"S"$NBLOCKS /dev/rft3 > /dev/null
Xret=$?
X
Xif [ "$ret" != "0" ]
Xthen
X	echo "\
X\tAn error has been discovered while trying to verify this tape.
X\tYou should use copy the existing data on this tape to another
X\ttape using '/news/.tape.ops/copy.sh'.  Read the comments at
X\tthe beginning of that program before proceeding."
X	read
X	Tgetname -l
X	exit 1
Xfi
X
Xif [ $COPY -ne 0 ]
Xthen
X	SSNAME="Copy"
Xelse
X	case $chap in
X		1) SSNAME="This";;
X		2) SSNAME="need";;
X		3) SSNAME="for";;
X		4) SSNAME=" a ";;
X		5) SSNAME="name";;
X		6) SSNAME=" is ";;
X		7) SSNAME="very";;
X		8) SSNAME="silly";;
X		9) SSNAME="stuff";;
X	esac
Xfi
XSSCMNT=`date '+%a, %h. %d 19%y %H:%M'`
XTgetname -w "Backup by Names" "$name" "$SSNAME" "$SSCMNT" \
X		$offset $NBLOCKS $NFILES
X#            "$BTYPE"       "$TPNAME" "$SSNAME" "$SSCMNT"
X#               $OFFSET $NBLOCKS $NFILES
Xret=$?
Xif [ "$ret" != "0" ]
Xthen
X	echo "\tAn error has occurred while trying to update the data block.
X\tError number = "$ret
X	Tgetname -l
X	exit 1
Xfi
X
Xcd $WRKDIR
X
XTgetname -v
XTgetname -l
Xecho `date +%T`" Verification complete.  The new contents are:"
X$SRCDIR/read.vtoc -w9
Xchap=$?
X
Xif [ $chap -gt 9 -o $scalped -ne 0 ]
Xthen
Xecho "\tThis tape should be marked FULL and a new tape used next time."
X	offset=0
X	name=`echo $name | awk - '{ FS = "-"
X		printf("%s-%03d", $1, ++$2 ) }' -`
X	blks=$MAXOFFSET
X	chap=1
Xelse
X	set `$SRCDIR/read.vtoc -c$chap`
X	chap=$1
X	offset=$2
X	(( blks = $MAXOFFSET - offset ))
Xfi
Xtoday=`date '+%y-%m-%d'`
X
X> $TMP1
Xchgrp news $TMP1
Xchown netnews $TMP1
Xecho `date +%T`" Purging directories and support files."
X
Xif [ $COPY -eq 0 ]
Xthen
X	while
X		read pntr
X	do
X		rm -f $ARCDIR/$pntr
X	done <$CPNTRS
X
X	fnum=1
X	ls -1 $ARCDIR > $PNTRS
X	while
X		read pntr
X	do
X		if [ ! -f $ARCDIR/$fnum ]
X		then
X			mv $ARCDIR/$pntr $ARCDIR/$fnum
X			(( fnum = fnum + 1 ))
X		fi
X	done < $PNTRS
X
X	factor=`sed -n 's/Compression factor:\	//p' $PARAMS`
X	nbytes=`sed -n 's/Number of bytes held:\	//p' $PARAMS`
X	if [ "$chap" -gt 1 ]
X	then
X		(( factor = (( nbytes/NBLOCKS ) + factor)/2 ))
X	fi
Xfi
X
Xawk -F"	" - '{ if ( $0 ~ /Next fnum to link:/ ) $2 = "'"$fnum"'"
X		if ( $0 ~ /Number of bytes held:/ ) $2 = 0
X		if ( $0 ~ /Name of work tape:/ ) $2 = "'"$name"'"
X		if ( $0 ~ /Blocks of offset:/ ) $2 = "'"$offset"'"
X		if ( $0 ~ /Date last taped:/ ) $2 = "'"$today"'"
X		if ( $0 ~ /Blocks available:/ ) $2 = "'"$blks"'"
X		if ( $0 ~ /Next chapter number:/ ) $2 = "'"$chap"'"
X		if ( $0 ~ /Compression factor:/ ) $2 = "'"$factor"'"
X		print $1"	"$2 >> "'$TMP1'"
X		}' $PARAMS
Xmv $TMP1 $PARAMS
X
Xrm -r $SAVDIR
Xrm -f /tmp/tape.vtoc
Xrm -f /tmp/ss.osets
Xrm -f /tmp/size*
Xrm -f $PWD/ss.filelist
Xrm -f $PNTRS
Xrm -f $CPNTRS
Xrm -f BUfiles
Xrm -f $CONFILE
Xrm -f bk.contents
Xrm -f bk.pntrs
Xrm -f /tmp/BUlist*
X
Xecho `date +%T`" Taping finished."
Xexit 0
END_OF_wr.tape.sh
if test 9334 -ne `wc -c <wr.tape.sh`; then
    echo shar: \"wr.tape.sh\" unpacked with wrong size!
fi
chmod +x wr.tape.sh
# end of overwriting check
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Vernon C. Hoxie		       {ncar,nbires,boulder,isis}!scicom!zebra!vern
3975 W. 29th Ave.					voice: 303-477-1780
Denver, Colo., 80212				  TB+	 uucp: 303-455-2670



More information about the Unix-pc.sources mailing list