[comp.sources.unix] v21i102: Table of Contents for Exebyte 8mm tapes

rsalz@bbn.com (Rich Salz) (04/12/90)

Submitted-by: Matt Landau <mlandau@diamond.bbn.com>
Posting-number: Volume 21, Issue 102
Archive-name: exebyte_toc

Exetoc is a program that allows you to write a table of contents file onto
the front of a 2GB helical scan tape, read it back later, and update it
without disturbing the other contents of the tape.

It does this by reserving a fixed amount of space at the start of the tape
(about 10 megabytes in the current implementation) that can be used to
store information about the contents of the tape.  About 2 megabytes of
this space is available for keeping the table of contents.  The rest acts
as a buffer space between the end of the table of contents and the first
data file on the tape.

#! /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 shell archive."
# Contents:  Makefile exetoc.c smtops.c exitcodes.h smtio.h smtops.h
#   exetoc.man
# Wrapped by mlandau@dilithium on Wed Apr 11 14:41:09 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(765 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
XSRCS = exetoc.c smtops.c
XOBJS = exetoc.o smtops.o
XHDRS = exitcodes.h smtio.h smtops.h
XDOCS = exetoc.man
X
X# Uncomment this if you have librmt.a installed someplace
XRMT  = -DREMOTE=1 -I/usr/local/include
XLIBS = /usr/local/lib/librmt.a
X
X# Uncomment this if you DON'T have librmt.a installed someplace
X#RMT  =
X#LIBS =
X
XCFLAGS = $(RMT) -O
X
XBINDIR = /usr/local/bin
XMANDIR = /usr/local/man/man1
XMANEXT = 1
X
Xexetoc: $(OBJS)
X	cc $(CFLAGS) -o exetoc $(OBJS) $(LIBS)
X
Xinstall: exetoc
X	install -s exetoc $(BINDIR)
X	cp exetoc.man $(MANDIR)/exetoc.$(MANEXT)
X
Xclean:
X	/bin/rm -f exetoc a.out $(OBJS) core *.BAK *.CKP
X
Xshar:
X	shar Makefile $(SRCS) $(HDRS) $(DOCS) >exetoc.shar
X
Xsaber:
X	# load $(SRCS)
X
X
Xexetoc.o: exitcodes.h smtio.h smtops.h
Xsmtops.o: exitcodes.h smtio.h smtops.h
END_OF_Makefile
if test 765 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f exetoc.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"exetoc.c\"
else
echo shar: Extracting \"exetoc.c\" \(8029 characters\)
sed "s/^X//" >exetoc.c <<'END_OF_exetoc.c'
X/* 
X * exetoc.c  --  A program to read, write, and rewrite tables of contents
X * 		 on tapes in an exebyte tape drive.
X * 
X * USAGE:	exetoc [-t|f tape] [-g file] [-p file] [-i] [-v] [-q]
X * 
X * 			-t specifies the tape drive, default is /dev/rsmt0
X *			-f is a synonym for -t, a la mt.
X * 			-g gets the table of contents from the tape and
X * 				sticks it into "file", which may be "-"
X * 				for standard output.
X * 			-p puts the table of contents contained in "file"
X * 				onto the front of the tape.  You can use
X * 				"-" to take the table of contents from
X * 				standard input.
X * 			-i initializes the tape by creating a blank table
X * 				of contents.
X * 			-v verifies that this tape has been initialized.
X * 			-q causes the program to work quietly.
X * 
X * 		You MUST provide exactly one of the -i, -g, -p, or -v flags.
X */
X 
X#if !lint && !SABER
Xstatic char RcsId[] = "$Header: exetoc.c,v 1.3 89/10/27 16:14:34 mlandau Exp $";
X#endif
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include "exitcodes.h"
X#include "smtops.h"
X
X#define	FORWARD		/* nothing */
X
X#define KBytes(n)	(n * 1024)
X#define MBytes(n)	(1024 * KBytes(n))
X#define MIN(a, b)	((a) < (b) ? (a) : (b))
X#define	streq(s1, s2)	(!strcmp(s1, s2))
X
X#define	IOBUF_SIZE	KBytes(62)	/* Exebyte likes 62KB chunks */
X#define TOC_SIZE 	MBytes(10)	/* TOC occupied 10 MB on the tape */
X#define	TOC_USEABLE	MBytes(2)	/* About 2 MB of it can be used */
X
X#define TOC_MARKER	"[ExeTOC Table of Contents]"
X
X#define OP_NONE		0
X#define OP_VERIFY	1
X#define OP_INIT		2
X#define OP_FETCH	3
X#define OP_STORE	4
X
X/* Getopt stuff */
Xextern	char	*optarg;
Xextern	int	optind;
Xextern	int	opterr;
X
X/* Linked in later */
Xextern	char	*getenv();
Xextern	char	*rindex();
X
X/* Shut Saber up */
XFORWARD void	usage();
XFORWARD void	set_operation();
XFORWARD void	mark_tape();
XFORWARD	void	initialize_tape();
XFORWARD int	check_tape();
XFORWARD void	toc_to_file();
XFORWARD void	toc_from_file();
XFORWARD void	rewind_named_device();
X
X
X/* Only need one big buffer to hold the table of contents */
Xstatic char Buffer[IOBUF_SIZE];
Xstatic int  Quiet = 0;
X
Xmain(argc, argv)
Xint	argc;
Xchar	**argv;
X{   
X    int	  option;
X    int	  operation = OP_NONE;
X    char *tapename = "/dev/rsmt0";
X    int	  hastoc;
X    int   tapefd;
X    int	  tocfd;
X    
X    opterr = 0;
X    if ((tapename = getenv("EXEBYTE")) == NULL)
X	tapename = "/dev/rsmt0";
X    while ((option = getopt(argc, argv, "t:f:g:p:ivq")) != EOF)
X    {   
X	switch (option)
X	{   
X	  case 't':
X	  case 'f':
X	    tapename = optarg;
X	    break;
X	    
X	  case 'g':
X	    set_operation(&operation, OP_FETCH);
X	    if (streq(optarg, "-"))
X		tocfd = fileno(stdout);
X	    else
X		tocfd = check_open(optarg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
X	    break;
X	    
X	  case 'p':
X	    set_operation(&operation, OP_STORE);
X	    if (streq(optarg, "-"))
X		tocfd = fileno(stdin);
X	    else 
X		tocfd = check_open(optarg, O_RDONLY, 0666);
X	    break;
X	    
X	  case 'i':
X	    set_operation(&operation, OP_INIT);
X	    break;
X	    
X	  case 'v':
X	    set_operation(&operation, OP_VERIFY);
X	    break;
X	    
X	  case 'q':
X	    Quiet = 1;
X	    break;
X	    
X	  default:
X	    usage(argv[0]);
X	    exit(EXIT_USAGE);
X	    /* NOTREACHED */
X	    break;
X	}
X    }
X    
X    switch (operation)
X    {   
X      case OP_NONE:
X	fputs("You must specify one of -g, -p, -i, or -v\n", stderr);
X	exit(EXIT_USAGE);
X	
X      case OP_INIT:
X	tapefd = smt_open(tapename, O_WRONLY);
X	initialize_tape(tapefd);
X	smt_close(tapefd);
X	rewind_named_device(tapename);
X	exit(EXIT_OK);
X	
X      case OP_VERIFY:
X	tapefd = smt_open(tapename, O_RDONLY);
X	hastoc = check_tape(tapefd);
X	smt_close(tapefd);
X	rewind_named_device(tapename);
X	if (!Quiet)
X	    printf("Tape in %s %s a labeled ExeTOC tape.\n", 
X		   tapename, hastoc ? "is" : "is not");
X	exit(hastoc ? EXIT_OK : EXIT_NOTOC);
X	
X      case OP_FETCH:
X	tapefd = smt_open(tapename, O_RDWR);
X	if (!check_tape(tapefd))
X	{   
X	    fprintf(stderr, "Tape in %s is not a labeled ExeTOC tape.\n", 
X		   	     tapename);
X	    exit(EXIT_NOTOC);
X	}
X	toc_to_file(tapefd, tocfd);
X	smt_close(tapefd);
X	rewind_named_device(tapename);
X	if (tocfd != fileno(stdout))
X	    close(tocfd);
X	exit(EXIT_OK);
X	
X      case OP_STORE:
X	tapefd = smt_open(tapename, O_RDWR);
X	if (!check_tape(tapefd))
X	{   
X	    fprintf(stderr, "Tape in %s is not a labeled ExeTOC tape.\n", 
X		   	     tapename);
X	    exit(EXIT_NOTOC);
X	}
X	mark_tape(tapefd);
X	toc_from_file(tapefd, tocfd);
X	smt_close_without_eof(tapefd);
X	rewind_named_device(tapename);
X	if (tocfd != fileno(stdin))
X	    close(tocfd);
X	exit(EXIT_OK);
X	
X      default:
X	fprintf(stderr, "Unknown tape operation code (%d)\n", operation);
X	exit(EXIT_USAGE);
X    }
X}
X
Xvoid	usage(progname)
Xchar	*progname;
X{   
X    static char *summary = 
X	"usage: %s [-t tape] [-g file] [-p file] [-i] [-v] [-q]\n";
X    static char *syntax[] = {
X	"",
X	"\t-t specifies the tape device.  Default is $EXEBYTE, or /dev/rsmt0.",
X	"\t-g gets the table of contents from the tape into the named file.",
X	"\t-p puts the table of contants in the named file onto the tape.",
X	"\t-i initializes a new tape so it can include a table of contents.",
X	"\t-v verifies that a tape has previously been initialized.",
X	"\t-q causes the program to work more quietly than usual.",
X	"",
X	"(Note: the tape is always rewound after any of these operations.)",
X	NULL
X    };
X    char	*p;
X    register int i;
X    
X    if ((p = rindex(progname, '/')) != NULL)
X	progname = p+1;
X
X    fprintf(stderr, summary, progname);
X    for (i = 0; syntax[i] != NULL; ++i)
X	fprintf(stderr, "%s\n", syntax[i]);
X}
X
X
X	 
Xvoid	rewind_named_device(name)
Xchar	*name;
X{   
X    int tapefd = smt_open(name, O_RDONLY);
X    
X    smt_rewind(tapefd);
X    smt_close(tapefd);
X}
X
X
Xvoid	set_operation(op, opcode)
Xint	*op;
Xint	opcode;
X{   
X    if (*op != OP_NONE)
X    {   
X	fputs("Only one of -g, -p, -i, and -q may be supplied.\n", stderr);
X	exit(EXIT_USAGE);
X    }
X    *op = opcode;
X}
X
X
Xint	check_open(name, mode, perm)
Xchar	*name;
Xint	mode;
Xint	perm;
X{   
X    int	fd;
X    
X    if ((fd = open(name, mode, perm)) < 0)
X    {   
X	perror(name);
X	exit(EXIT_IO);
X    }
X    return (fd);
X}
X
X
Xvoid	mark_tape(tapefd)
Xint	tapefd;
X{   
X    bzero(Buffer, sizeof(Buffer));
X    strcpy(Buffer, TOC_MARKER);
X    smt_rewind(tapefd);
X    if (smt_write(tapefd, Buffer, sizeof(Buffer)) < sizeof(Buffer))
X    {   
X	perror("tape label");
X	exit(EXIT_IO);
X    }
X}
X
X
Xvoid	initialize_tape(tapefd)
Xint	tapefd;
X{   
X    int	nbufs = (TOC_SIZE / IOBUF_SIZE);
X    
X    mark_tape(tapefd);
X    bzero(Buffer, sizeof(Buffer));
X    while (--nbufs > 0)
X	smt_write(tapefd, Buffer, sizeof(Buffer));
X}
X
X
Xint	check_tape(tapefd)
Xint	tapefd;
X{   
X    smt_rewind(tapefd);
X    return (smt_read(tapefd, Buffer, sizeof(Buffer)) == sizeof(Buffer) 
X	    &&
X	    streq(Buffer, TOC_MARKER));
X}
X
X
Xvoid	toc_to_file(tapefd, tocfd)
Xint	tapefd;
Xint	tocfd;
X{   
X    int		   n;
X    register int   i;
X    register char *bp;
X    
X    bzero(Buffer, sizeof(Buffer));
X    while ((n = smt_read(tapefd, Buffer, sizeof(Buffer))) > 0)
X    {   
X	if (n < sizeof(Buffer))
X	{   
X	    perror("tape read");
X	    exit(EXIT_IO);
X	}
X	for (bp = Buffer, i = 0; i < sizeof(Buffer) && *bp != 0; bp++, i++)
X	    continue;
X	if (write(tocfd, Buffer, i) != i)
X	{   
X	    perror("file write");
X	    exit(EXIT_IO);
X	}
X	if (i < sizeof(Buffer))
X	    break;
X    }
X}
X
X
Xvoid 	toc_from_file(tapefd, tocfd)
Xint	tapefd;
Xint	tocfd;
X{   
X    struct stat s;
X    int		n;
X    
X    if (tocfd != fileno(stdin))
X    {   
X	if (fstat(tocfd, &s) < 0)
X	{   
X	    perror("fstat");
X	    exit(EXIT_IO);
X	}
X	if (s.st_size > TOC_USEABLE)
X	{   
X	    fputs("Table of Contents file is too large.\n", stderr);
X	    exit(EXIT_TOOBIG);
X	}
X    }
X    
X    bzero(Buffer, sizeof(Buffer));
X    while ((n = read(tocfd, Buffer, sizeof(Buffer))) > 0)
X    {   
X	if (n < sizeof(Buffer))
X	    bzero(Buffer + n, sizeof(Buffer) - n);
X	if (smt_write(tapefd, Buffer, sizeof(Buffer)) < sizeof(Buffer))
X	{   
X	    perror("tape write");
X	    exit(EXIT_IO);
X	}
X    }
X    if (n < 0)
X    {   
X	perror("file read");
X	exit(EXIT_IO);
X    }
X}
END_OF_exetoc.c
if test 8029 -ne `wc -c <exetoc.c`; then
    echo shar: \"exetoc.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f smtops.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"smtops.c\"
else
echo shar: Extracting \"smtops.c\" \(3587 characters\)
sed "s/^X//" >smtops.c <<'END_OF_smtops.c'
X#if !lint && !SABER
Xstatic char RcsId[] = "$Header: smtops.c,v 1.2 89/10/27 16:14:58 mlandau Exp $";
X#endif
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <sys/types.h>
X#include <sys/ioctl.h>
X#include <sys/mtio.h>
X
X#if REMOTE
X#include <rmt.h>
X#endif
X
X#include "exitcodes.h"
X#include "smtops.h"
X
X
X/****************************************************************************
X * BASIC MAGTAPE OPERATIONS FOR EXEBYTE DRIVES
X ***************************************************************************/
X
X
X/*
X * smt_open():  Open a tape device.
X * 
X * Actually, it's just a wrapper around open, but data abstraction is 
X * good, right?
X */
X 
X
Xint	smt_open(device, mode)
Xchar	*device;
Xint	mode;
X{   
X    int	fd;
X    
X    if ((fd = open(device, mode)) < 0)
X    {   
X	perror(device);
X	exit(EXIT_IO);
X    }
X    return (fd);
X}
X
X
X/* 
X * smt_close():  Close a tape device -- this is just a wrapper around close.
X */
X 
Xvoid	smt_close(tapefd)
Xint	tapefd;
X{   
X    if (close(tapefd) < 0)
X    {   
X	perror("tape close");
X	exit(EXIT_IO);
X    }
X}
X
X
X/* 
X * smt_close_without_eof():  Rewind and close a tape device.
X * 
X * 	This routine provides a rewind-and-close operation, which is
X * 	necessary to prevent the tape device driver from adding an EOF
X * 	mark to the tape if the last operation before closing the device
X * 	was a write.  Since we are continutally rewriting the same file,
X *	we need to inform the driver that we don't want a new EOF mark
X * 	every time we do so.
X */
X 
Xvoid	smt_close_without_eof(tapefd)
Xint	tapefd;
X{   
X    smt_rewind(tapefd);
X    smt_close(tapefd);
X}
X
X
X/* 
X * smt_read():  Read from the tape drive
X * smt_write(): Write to the tape drive
X * 
X * 
X * 	This are wrappers around read and write.  They're mostly here
X * 	so that we can use the rmt library if we want to.
X */
X 
Xint	smt_read(tapefd, buffer, count)
Xint	tapefd;
Xchar	*buffer;
Xint	count;
X{   
X    return (read(tapefd, buffer, count));
X}
X
X
Xint	smt_write(tapefd, buffer, count)
Xint	tapefd;
Xchar	*buffer;
Xint	count;
X{   
X    return (write(tapefd, buffer, count));
X}
X
X
X/* 
X * smt_status():  Return the status of the tape drive.
X * 
X * This code is cribbed from the mts command.  The smt_stat structure
X * looks like this:
X * 
X * 	struct smt_stat
X * 	{
X * 		char   smt_type[8];	-- cartridge type
X *		u_long smt_remain;	-- KBytes left on tape
X *		u_long smt_size;	-- Total size of tape (KBytes)
X * 		u_long smt_ecc;		-- ECC numbers
X * 		long   smt_wp:1;	-- write protected?
X * 		long   smt_bot:1;	-- at beginning of tape?
X *	}
X */
X
Xstruct smt_stat	*smt_status(tapefd)
Xint		 tapefd;
X{   
X    static struct smt_stat status;
X    
X    if (ioctl(tapefd, SMTIOGETSTAT, &status) < 0)
X    {   
X	perror("tape status");
X	exit(EXIT_IO);
X    }
X    return (&status);
X}
X
X
X
X/* 
X * smt_rewind():  Rewind a tape and verify that it worked.
X */
X
Xvoid	smt_rewind(tapefd)
Xint	tapefd;
X{   
X    static struct mtop rewind_op = { MTREW, 1 };
X    
X    if (ioctl(tapefd, MTIOCTOP, &rewind_op) < 0)
X    {   
X	perror("tape rewind");
X	exit(EXIT_IO);
X    }
X#if !REMOTE
X    /* rmtlib.a does not like the custom ioctls used in the smt_status
X       routine, so don't use it internally */
X    if (!smt_status(tapefd)->smt_bot)
X    {   
X	fputs("Could not rewind tape for some unknown reason.");
X	exit(EXIT_IO);
X    }
X#endif
X}
X
X
X/* 
X * smt_eof():  Write an EOF mark on the tape.
X * 
X * We will probably never need this, but it doesn't hurt to include it.
X */
X 
Xvoid	smt_eof(tapefd)
Xint	tapefd;
X{   
X    static struct mtop eof_op = { MTWEOF, 1 };
X    
X    if (ioctl(tapefd, MTIOCTOP, &eof_op) < 0)
X    {   
X	perror("write eof");
X	exit(EXIT_IO);
X    }
X}
X
X
END_OF_smtops.c
if test 3587 -ne `wc -c <smtops.c`; then
    echo shar: \"smtops.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f exitcodes.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"exitcodes.h\"
else
echo shar: Extracting \"exitcodes.h\" \(153 characters\)
sed "s/^X//" >exitcodes.h <<'END_OF_exitcodes.h'
X#ifndef EXITCODES_H
X#define EXITCODES_H 1
X
X#define EXIT_OK		0
X#define EXIT_USAGE	1
X#define	EXIT_IO		2
X#define EXIT_NOTOC	3
X#define EXIT_TOOBIG	4
X
X#endif
END_OF_exitcodes.h
if test 153 -ne `wc -c <exitcodes.h`; then
    echo shar: \"exitcodes.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f smtio.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"smtio.h\"
else
echo shar: Extracting \"smtio.h\" \(445 characters\)
sed "s/^X//" >smtio.h <<'END_OF_smtio.h'
X#include <sys/ioctl.h>
X
X/* structures and defines for ioctls */
Xstruct smt_stat {
X	char	smt_type[8];	/* Cartridge type */
X	unsigned long	smt_remain;		/* # of kilobytes remaining on tape */
X	unsigned long	smt_size;		/* size (in kb) of tape */
X	unsigned long	smt_ecc;		/* ECC count */
X	long	smt_wp:1;		/* Write protected */
X	long	smt_bot:1;		/* At beginning of tape */
X};
X
X#define	SMTIOGETSTAT	_IOR(m,0,struct smt_stat)	/* get the drive status */
END_OF_smtio.h
if test 445 -ne `wc -c <smtio.h`; then
    echo shar: \"smtio.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f smtops.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"smtops.h\"
else
echo shar: Extracting \"smtops.h\" \(308 characters\)
sed "s/^X//" >smtops.h <<'END_OF_smtops.h'
X#ifndef	SMTOPS_H
X#define	SMTOPS_H 1
X
X#include "smtio.h"
Xextern	struct smt_stat	*smt_status();
X
Xextern	int	   	 smt_open();
Xextern	void	   	 smt_close();
Xextern  void		 smt_close_without_eof();
Xextern	void	   	 smt_rewind();
Xextern	void		 smt_eof();
Xextern	int		 smt_read();
Xextern	int		 smt_write();
X
X#endif
END_OF_smtops.h
if test 308 -ne `wc -c <smtops.h`; then
    echo shar: \"smtops.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f exetoc.man -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"exetoc.man\"
else
echo shar: Extracting \"exetoc.man\" \(3224 characters\)
sed "s/^X//" >exetoc.man <<'END_OF_exetoc.man'
X.TH EXETOC 1L "27 Oct 1989"
X.SH NAME
Xexetoc \- Manage a table of contents on an Exebyte 2GB tape cartridge.
X.SH SYNOPSIS
X.B exetoc
X.BI [-t tape ]
X.BI [-g file ]
X.BI [-p file ]
X.B  [-i]
X.B  [-v]
X.B  [-q]
X.SH DESCRIPTION
X.B Exetoc is a program that allows you to write a table of contents
Xfile onto the front of a 2GB helical scan tape, read it back later, 
Xand update it without disturbing the other contents of the tape.  
X.PP
XIt does this by reserving a fixed amount of space at the start of 
Xthe tape (about 10 megabytes in the current implementation) that can be 
Xused to store information about the contents of the tape.  About 2 
Xmegabytes of this space is available for keeping the table of
Xcontents.  The rest acts as a buffer space between the end of the table 
Xof contents and the first data file on the tape.
X.SH OPTIONS
X.B Exetoc understands the following options:
X.TP
X.BI -t tapedrive
XSets the tape drive name to something other than the default, which
Xis derived by looking for the environment variable EXETOC, or using
X"/dev/rsmt0" if the environment variable is not set.  Exetoc is normally 
Xlinked with the remote tape library, allowing you to use 
Xnames of the form \fIhost:device\fP for direct access to remote tape 
Xdrives.
X.TP
X.BI -g file
XGets the table of contents from the tape and places a copy of
Xit into the named file.  If \fIfile\fP is given as -, the table of 
Xcontents is copied to standard output.
X.TP
X.BI -p file
XPuts a table of contents onto the tape.  The contents of the table
Xare taken from the named file, or from standard input if \fIfile\fP
Xis given as -.  This flag may be used to create and rewrite tables
Xof contents.
X.TP
X.B -i
XInitializes a tape by creating a blank table of contents at the
Xfront of the tape.  You must initialize a tape with the -i flag before
Xyou can write a table of contents onto it for the first time.
X.TP 
X.B -v
XVerifies that the tape in the tape drive has previously been initialized
Xwith exetoc -i.
X.TP
X.B -q
XCauses the program to work more quietly than it otherwise would.
X.LP
XAny other option causes exetoc to deliver a lengthy message explaining
Xthe legal flags.
X.SH "ENVIRIONMENT VARIABLES"
X.TP
XEXEBYTE
XSpecifies the default tape drive to use.  Exetoc is normally linked
Xwith the remote tape library, allowing you to use names of the form
X\fIhost:device\fP for direct access to remote tape drives.
X.SH "EXIT STATUS"
XExetoc exits with one of the following well-defined status codes:
X.TP
X0
Xindicates successful completion of an operation.
X.TP
X1
Xindicates an error in usage (illegal command line flag, for instance).
X.TP
X2
Xindicates an I/O error of some kind.  A diagnostic message is printed
Xon standard error in this case, explaining what the error was.
X.TP
X3
Xindicates that a read, write, or verify operation was attempted with a 
Xtape that has never been initialized to hold a table of contents.
X.TP
X4
Xindicates that the table of contents file you are trying to write onto
Xthe tape is too large to fit.
X.SH BUGS
XThe tape is rewound after \fIany\fP exetoc operation, even if the no-rewind
Xdevice was specified on the command line.
X.SH "SEE ALSO"
X.nf
Xdd(1), bdd(1), mt(1)
X.SH AUTHOR
X.nf
XMatt Landau, BBN Systems and Technologies Corp.  (mlandau@bbn.com)
END_OF_exetoc.man
if test 3224 -ne `wc -c <exetoc.man`; then
    echo shar: \"exetoc.man\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0

exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.