[net.sources] ts and tcp - tape utilities

lmc@denelvx.UUCP (Lyle McElhaney) (12/02/84)

Well, it seems that there was a bug in the posting of ts.c and tcp.c that
I made about a month ago. Soooo...

ts.c - reads in a tape and outputs a synopsis of files and block sizes.
tcp.c - allows an exact tape copy of any tape to be made with only one tape
	drive.

Manual pages went out the first time; I'll not repeat them here. (I'll mail
them on request).

: - - - - - - - - - - - - - cut here - - - - - - - - - - - - - - - - -
: This is a shar archieve.  Extract with sh, not csh.
: The rest of this file will extract:
: ts.c tcp.c
echo extracting - ts.c
sed 's/^X//' > ts.c << 'FUNKYSTUFF'
X/*
X *      ts - This program outputs a file/record description of a tape's
X *      structure.
X *
X *      Exits:  0 - normal.
X *              1 - usage error.
X *              2 - tape read error.
X *              3 - SIGINT received.
X *
X *      Copyright (C) 1983, 1984 Lyle McElhaney
X *      Permission to copy for non-commercial use granted under condition
X *      that this notice remains intact in the copy.
X *
X *      Address: 2489 W. Ridge Rd., Littleton, CO 80120
X *      ....denelcor!lmc
X */
X#include <stdio.h>
X#include <signal.h>
X
X#define MAXBUF=32767
X/*      This can be whatever maximum the machine/os will take.
X *      16000 is allowed on an 11/44 running System 3 Unix (tm).
X */
X
X#ifndef YES
X#define YES 1
X#define NO 0
X#endif
X
Xchar tape[]="/dev/rmt0\0\0";
Xchar buff[MAXBUF];
XFILE *tapedev;
Xlong recno, nrec, fsize, filen;
Xextern void sig();
X
Xmain (argc, argv)
X    int argc;
X    char **argv;
X{
X    char *p;
X    int n;
X
X    argv++;
X    if (argc > 1) {
X	p = *argv;
X	if (*p == '-') {
X	    p++;
X	    while (*p != '\0') {
X		switch (*p++) {
X		case '2':
X		case '3':
X		case '4':
X		case '5':
X		case '6':
X		case '7':
X		case '8':
X		case '9':
X		case '0':
X		    tape[8] = *(p-1);
X		    break;
X		case '1':
X		    tape[8] = '1';
X		    if (*p >= '0' && *p <= '5')
X			tape[9] = *p++;
X		    break;
X		default:
XUsage:
X		    fprintf (stderr, "Usage: ts [-0...15]\n");
X		    exit (2);
X		}
X	    }
X	    argc--;
X	    argv++;
X	}
X    else goto Usage;
X    }
X
X    signal (SIGINT, sig);
X    if ((tapedev = fopen (tape, "r")) == NULL) {
X	fprintf (stderr, "ts: cannot open %s\n", tape);
X	exit (2);
X    }
X
X    filen = 0;
X    for (;;) {
X	recno = nrec = 0;
X	for (;;) {
X	    n = read (fileno (tapedev), buff, sizeof buff);
X	    if (n > 0) {
X		if (recno == 0) {
X		    printf ("File %ld:\n", filen);
X		    fsize = n;
X		}
X		if (n != fsize) {
X		    printf ("    Records %ld through %ld (%ld records), length = %ld bytes\n",
X			    nrec, recno - 1, recno - nrec, fsize);
X		    fsize = n;
X		    nrec = recno;
X		}
X		recno ++;
X	    } else goto Out;
X	}
XOut:    if (n == 0) {
X	    if (recno != 0)
X		printf ("    Records %ld through %ld (%ld records), length = %ld bytes\n",
X		    nrec, recno - 1, recno - nrec, fsize);
X	} else {
X	    printf ("Tape read error %d in record %ld\n", n, recno);
X	    exit (1);
X	}
X	if (recno == 0) break;
X	filen ++;
X    }
X    printf ("End of tape reached.\n");
X    fclose (tapedev);
X    exit (0);
X}
X
Xvoid sig ()
X{
X    printf ("    Records %ld through %ld (%ld records), length = %ld bytes\n",
X	    nrec, recno-1, recno - nrec, fsize);
X    printf ("ts: aborted by interrupt at that point.\n");
X    close (tapedev);
X    exit (3);
X}
FUNKYSTUFF
echo extracting - tcp.c
sed 's/^X//' > tcp.c << 'FUNKYSTUFF'
X/*
X *      tcp - this routine runs in input (-i) and output (-o) modes. On
X *      input, it reads a tape's contents (out to the double tape-marks)
X *      and writes that data to files in a the current directory, along
X *      with a file of data which will allow reconstruction of the tape
X *      in the output mode.
X *
X *      Copyright (C) 1983, 1984 Lyle McElhaney
X *      Permission to copy for non-commercial use granted under condition
X *      that this notice remains intact in the copy.
X *
X *      Address: 2489 W. Ridge Rd., Littleton, CO 80120
X *      ....denelcor!lmc
X *
X */
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/ioctl.h>
X#ifdef MTIO
X#include <sys/mtio.h>
X#endif
X#define MAXBUF 32768            /* maximum tape physical record size */
X#ifndef YES
X#define NO 0
X#define YES 1
X#endif
X#define NYU 2
X
Xextern char *index();
Xextern int errno;
Xchar nrtape[]="/dev/nrmt8\0\0";
Xchar tape[]="/dev/rmt8\0\0";
Xchar ffh[]="tcp,f";      /* headers for temp filenames */
Xchar nfh[]="tcp,n";
Xchar format[]="%s%02d%05d"; /* format of filenames. args: [fcn]fh, tapen, nfile */
X#define FMTSIZ 13       /* limit on size of filenames created + 1 */
Xchar ffile[FMTSIZ], cfile[FMTSIZ];
Xchar buff[MAXBUF];
Xchar buf[10];
Xint nfile;
Xint tapen=0;
Xint inmode=NYU;         /* input mode - not yet set. User must choose. */
XFILE *tapedev, *filedev, *ctldev;
Xlong recno, nrec, fsize, filen;
X#ifdef MTIO
Xint convmode=NO;        /* conversational mode default to no */
Xstruct mtop mtop;
X#endif
X
Xmain (argc, argv)
X    int argc;
X    char **argv;
X{
X    char *p;
X    int n;
X
X    argv++;
X    if (argc > 1) {
X	p = *argv;
X	if (*p == '-') {
X	    p++;
X	    while (*p != '\0') {
X		switch (*p++) {
X#ifdef MTIO
X		case 'c':
X			convmode = YES;
X			break;
X#endif
X		case 'i':
X			if (inmode != NYU) goto Usage;
X			inmode = YES;
X			break;
X		case 'o':
X			if (inmode != NYU) goto Usage;
X			inmode = NO;
X			break;
X		case 'n':
X			tapen = atoi (p);
X			break;
X		case '2':
X		case '3':
X		case '4':
X		case '5':
X		case '6':
X		case '7':
X		case '8':
X		case '9':
X		case '0':
X		    tape[8] = nrtape[9] = *(p-1);
X		    break;
X		case '1':
X		    tape[8] = nrtape[9] = '1';
X		    if (*p >= '0' && *p <= '5')
X			tape[9] = nrtape[10] = *p++;
X		    break;
X		default:
XUsage:
X		    fprintf (stderr, "Usage: tcp [-i] [-o] [-nxx] [-1...15]\n");
X		    exit (2);
X		}
X	    }
X	    argc--;
X	    argv++;
X	}
X    } else goto Usage;
X    if (inmode == NYU) goto Usage;
X
X    if (inmode) {
X/*
X *      input mode - read tape into files.
X */
X	sprintf (cfile, format, nfh, tapen, 0);
X	if ((ctldev = fopen (cfile, "w+")) == NULL) {
X	    fprintf (stderr, "tcp: cannot open %s\n", cfile);
X	    exit (2);
X	}
X	if ((tapedev = fopen (tape, "r")) == NULL) {
X	    fprintf (stderr, "tcp: cannot open %s\n", tape);
X	    exit (2);
X	}
X	filen = 0;
X	for (;;) {
X	    recno = nrec = 0;
Xreread:     while ((n = read (fileno (tapedev), buff, sizeof buff)) > 0) {
X		if (recno == 0) {
X		    fsize = n;
X		    sprintf (ffile, format, ffh, tapen, filen);
X		    if ((filedev = fopen (ffile, "w+")) == NULL) {
X			fprintf (stderr, "tcp: cannot open %s\n", ffile);
X			exit (2);
X		    }
X		}
X		if (write (fileno (filedev), buff, n) <= 0) {
X		    fprintf (stderr, "tcp: file write error #%d in %s\n",
X			errno, ffile);
X		    exit (2);
X		}
X		if (fsize != n) {
X			fprintf (ctldev, "%d,%d\n", recno - nrec, fsize);
X			fsize = n;
X			nrec = recno;
X		}
X		recno ++;
X	    }
X	    if (n == 0)
X		if (recno == 0)
X		    break;
X		else {
X		    fprintf (ctldev, "%d,%d\n0,0\n", recno - nrec, fsize);
X		    filen ++;
X		    fclose (filedev);
X		}
X	    else {
X		printf ("Tape read error %d in record %ld\n", n, recno);
X#ifdef MTIO
X		for (;;) {
X		    if (convmode) {
X			printf ("Abort, Retry, or Ignore? ");
X			if (gets (buf) != NULL) {
X			    if (*buf == 'R' || *buf == 'r') {
X				mtop.mt_count = 1;
X				mtop.mt_op = MTBSR;
X				if (ioctl (fileno (tapedev), MTIOCTOP, &mtop) < 0) {
X				    printf ("error %d in ioctl; ignoring prev error.\n", errno);
X				    recno ++;
X				}
X				goto reread;
X			    } else if (*buf == 'I' || *buf == 'i') {
X				recno ++;
X				goto reread;
X			    } else if (*buf == 'A' || *buf == 'a')
X				exit (1);
X			}
X		    } else
X			exit (1);
X		}
X#else
X	    exit (1);
X#endif  MTIO
X	    }
X	}
X	fclose (tapedev);
X	fprintf (ctldev, "0,1\n");
X	fclose (ctldev);
X    } else {
X/*
X *      output mode - copy files back out to tape.
X */
X	sprintf (cfile, format, nfh, tapen, 0);
X	if ((ctldev = fopen (cfile, "r")) == NULL) {
X	    fprintf (stderr, "tcp: cannot open %s\n", cfile);
X	    exit (2);
X	}
X	recno = 0;
X	for (;;) {
X	    if (fgets (buf, sizeof(buf), ctldev) == NULL) {
X		fprintf (stderr, "tcp: file %s malformed.\n", cfile);
X		exit (2);
X	    }
X	    nrec = atoi (buf);
X	    n = atoi (index (buf, ',') + 1);
X	    if (nrec != 0) {
X		if (recno == 0) {
X		    if ((tapedev = fopen (nrtape, "a")) == NULL) {
X			fprintf (stderr, "tcp: cannot open %s\n", nrtape);
X			exit (2);
X		    }
X		    sprintf (ffile, format, ffh, tapen, filen);
X		    if ((filedev = fopen (ffile, "r")) == NULL) {
X			fprintf (stderr, "tcp: cannot open %s\n", ffile);
X			exit (2);
X		    }
X		}
X		for (; nrec > 0; nrec--) {
X		    if (read (fileno (filedev), buff, n) <= 0) {
X			fprintf (stderr, "tcp: file read error #%d in %s\n",
X			    errno, ffile);
X			exit (2);
X		    }
X		    if (write (fileno (tapedev), buff, n) <= 0) {
X			fprintf (stderr, "tcp: tape write error #%d in %s\n",
X			    errno, nrtape);
X			exit (2);
X		    }
X		    recno ++;
X		}
X	    } else if (n == 0) {
X		fclose (filedev);
X		fclose (tapedev);
X		filen ++;
X		recno = 0;
X	    } else
X		break;
X	}
X	fclose (ctldev);
X    }
X    exit (0);
X}
FUNKYSTUFF