rs@uunet.UU.NET (Rich Salz) (08/04/87)
Submitted-by: Dick Grune <dick@cs.vu.nl>
Posting-number: Volume 10, Issue 89
Archive-name: magtapetools/Part02
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin
echo Extracting \a\n\s\i\.\h
sed 's/^X//' > \a\n\s\i\.\h << '+ END-OF-FILE '\a\n\s\i\.\h
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X#include <stdio.h>
X
Xextern char *strcpy();
X
X#define NL '\n'
X#define TAB '\t'
X#define SP ' '
X#define EOS '\0'
X
X#define TRUE 1
X#define FALSE 0
X
X#define MAXSTR 128
X
X/*
X * It is tempting to use structs for the declaration of the label data
X * structures, access the fields through selectors and let the C-compiler
X * do the offset calculation. There are, however, two problems:
X * 1. alignment is different on different machines (VAX vs. PDP11),
X * 2. according to the book the fields may even be arranged in inverse
X * order.
X * So structs are out and defines are in.
X * A field is implemented as a pair: an address and a length.
X */
X
X/* the general fields */
X#define Whole(p) &(p)[0], sizeof (p)
X#define Labidf(p) &(p)[0], 4
X
X/* the VOL1 label */
X#define Volidf(p) &(p)[4], 6
X#define Volacc(p) &(p)[10], 1
X#define Sp1(p) &(p)[11], 26
X#define Ownidf(p) &(p)[37], 14
X#define Sp2(p) &(p)[51], 28
X#define Labvers(p) &(p)[79], 1
X
X/* dates */
X#define Sp(p) &(p)[0], 1
X#define Date(p) &(p)[1], 5
X#define Yr(p) &(p)[1], 2
X#define Yd(p) &(p)[3], 3
X
X/* the HDR1 label */
X#define Fileidf(p) &(p)[4], 17
X#define Filesetidf(p) &(p)[21], 6
X#define Filsecnum(p) &(p)[27], 4
X#define Filseqnum(p) &(p)[31], 4
X#define Gennum(p) &(p)[35], 4
X#define Genversnum(p) &(p)[39], 2
X#define Creatdate(p) &(p)[41], 6
X#define Expirdate(p) &(p)[47], 6
X#define Fileacc(p) &(p)[53], 1
X#define Blkcount(p) &(p)[54], 6
X#define Syscode(p) &(p)[60], 13
X#define Sp3(p) &(p)[73], 7
X
X/* the HDR2 label */
X#define Recformat(p) &(p)[4], 1
X#define Blklength(p) &(p)[5], 5
X#define Reclength(p) &(p)[10], 5
X#define Syssoftw(p) &(p)[15], 35
X#define Bufoffset(p) &(p)[50], 2
X#define Sp4(p) &(p)[52], 28
X
X/* the USRn label */
X#define Contents(p) &(p)[4], 76
X
X
Xextern int unit;
Xextern char *nmdns;
Xextern TPFILE *tf;
X
X#define ASK_NO 0 /* use default and check */
X#define ASK_YES 1 /* ask and check */
X#define ASK_SUG 2 /* suggest default and check */
X#define ASK_ERR 3 /* ask again and check */
X
X/* Macros to define an additional control structure to handle
X interactive input, under the presence of user errors.
X*/
X#define inmood(md) {int mood = md; for (;;mood=ASK_ERR)
X#define iferr(cond) if(cond){print_loc();
X#define enderr continue;}
X#define endmood break;}
X
Xextern char *sps2txt(), *str2txt(), *expl2str(), *tty_line(), *tty_str();
Xextern char *enq_str(), *fld2str(), *char2str();
Xextern int enq_int(), isascstr(), fld2int();
Xextern fld2fld(), str2fld(), prf_s(), errors();
X
Xstruct format {
X char type;
X int (*checkpar)();
X int (*cpblk)();
X};
X
Xextern struct format formats[];
Xextern struct format *format_of_type();
X
Xextern char filename[MAXSTR];
Xextern FILE *file;
Xextern int filseqnum;
Xextern int filsecnum;
Xextern char rectype[1];
Xextern struct format *recformat;
Xextern int blklength;
Xextern int reclength;
Xextern int bufoffset;
Xextern int reccount;
Xextern int blkcount;
X
Xextern char VOL1buf[80];
Xextern char HDR1buf[80];
Xextern char HDR2buf[80];
+ END-OF-FILE ansi.h
chmod 'u=rw,g=r,o=r' \a\n\s\i\.\h
set `sum \a\n\s\i\.\h`
sum=$1
case $sum in
43328) :;;
*) echo 'Bad sum in '\a\n\s\i\.\h >&2
esac
echo Extracting \e\t\o\a\.\h
sed 's/^X//' > \e\t\o\a\.\h << '+ END-OF-FILE '\e\t\o\a\.\h
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
Xextern char _etoa[]; /* from etoa.c */
X
X#define ebc2asc(c) (_etoa[(c)&0377])
+ END-OF-FILE etoa.h
chmod 'u=rw,g=r,o=r' \e\t\o\a\.\h
set `sum \e\t\o\a\.\h`
sum=$1
case $sum in
11080) :;;
*) echo 'Bad sum in '\e\t\o\a\.\h >&2
esac
echo Extracting \o\p\t\i\o\n\s\.\h
sed 's/^X//' > \o\p\t\i\o\n\s\.\h << '+ END-OF-FILE '\o\p\t\i\o\n\s\.\h
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X/* Having a chunk out of a switch statement as a separate include
X file is unusual, but this file does implement a conceptual unit:
X the handling of the standard command line options for describing
X a generalized magtape. See mag.1.
X
X This include file assumes
X aux.h to be included
X tp.h idem
X uses and updates
X argc as supplied by main()
X argv idem
X sets
X unit the unit number
X nmdns file name or density
X and jumps to
X Lbad on bad command line parameters
X*/
X
X default:
X goto Lbad;
X case 'c': /* character device */
X unit = TP_CDEV;
X if (argc < 2)
X goto Lbad;
X nmdns = argv[1];
X argc--, argv++;
X break;
X case 'f': /* tape image */
X unit = TP_IMAG;
X if (argc < 2)
X goto Lbad;
X nmdns = argv[1];
X argc--, argv++;
X break;
X case 'h': /* high density */
X nmdns = TP_DENH;
X break;
X case 'l': /* low density */
X nmdns = TP_DENL;
X break;
X case 'm': /* unit number (real tape unit) */
X if (argc < 2)
X goto Lbad;
X if (!is_digit(argv[1][0]))
X goto Lbad;
X unit = atoi(argv[1]);
X argc--, argv++;
X break;
+ END-OF-FILE options.h
chmod 'u=rw,g=r,o=r' \o\p\t\i\o\n\s\.\h
set `sum \o\p\t\i\o\n\s\.\h`
sum=$1
case $sum in
18446) :;;
*) echo 'Bad sum in '\o\p\t\i\o\n\s\.\h >&2
esac
echo Extracting \a\n\s\i\.\c
sed 's/^X//' > \a\n\s\i\.\c << '+ END-OF-FILE '\a\n\s\i\.\c
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X#include "aux.h"
X#include "tp.h"
X#include "ansi.h"
X
Xextern char *sprintf();
X
Xint unit = 0;
Xchar *nmdns = TP_DENN;
XTPFILE *tf = NULL;
X
Xchar filename[MAXSTR];
XFILE *file = NULL;
Xint filseqnum = 0;
Xint filsecnum = 1;
Xchar rectype[1] = 'F';
Xstruct format *recformat;
Xint blklength = 1920;
Xint reclength = 80;
Xint bufoffset = 0;
Xint reccount;
Xint blkcount;
X
Xchar VOL1buf[80];
Xchar HDR1buf[80];
Xchar HDR2buf[80];
X
Xchar *
Xsps2txt(p) {
X return p == 0 ? "<empty>" : p == 1 ? "<space>" : "<spaces>";
X}
X
Xchar *
Xstr2txt(s)
X char *s;
X{
X int p = 0;
X
X while (s[p] != EOS) {
X if (s[p] != SP)
X return s;
X p++;
X }
X return sps2txt(p);
X}
X
X/* An expl(anation) is an explanatory string which contains the name of the
X * object being explained as the first item between ` and ' . The expl may
X * contain one %s which is replaced by the default (string) value.
X */
X
Xchar * /* transient */
Xexpl2str(expl)
X char *expl;
X{
X static char str[MAXSTR];
X char *nm = expl, cnt = 0;
X
X while (*nm != EOS && *nm != '`') {
X nm++;
X }
X nm++;
X while (*nm != EOS && *nm != '\'') {
X if (cnt < MAXSTR-1)
X str[cnt++] = *nm;
X nm++;
X }
X str[cnt] = EOS;
X return str;
X}
X
Xchar * /* transient */
Xtty_line() {
X static char ans[MAXSTR];
X int cnt = 0;
X int ch;
X
X while ((ch = getchar()) != NL) {
X if (ch == EOF)
X errors("\n*** No interaction!!!");
X if (cnt < MAXSTR-1)
X ans[cnt++] = ch;
X }
X ans[cnt] = EOS;
X return ans;
X}
X
Xchar * /* transient */
Xtty_str(prompt, expl, md, def)
X char *prompt, *expl, md, *def;
X{
X static char conversation = FALSE;
X char *str;
X int err = 0;
X
X if (!conversation) {
X prf_s("\n\
X I shall have to ask some questions; to get more information,\n\
X answer a question with a single question mark (?).\n\n", "");
X conversation = TRUE;
X }
X while (err < 3) {
X printf(prompt, expl2str(expl));
X str= tty_line();
X if (strcmp(str, "?") == 0) {
X printf("\n");
X prf_s(expl, def);
X printf("\n");
X }
X else
X if (strlen(str) > 0)
X return str;
X else
X if (md == ASK_SUG)
X return NULL;
X else {
X printf("I do need an answer!\n");
X err++;
X }
X }
X errors("\nSorry");
X return str;
X}
X
Xchar * /* transient */
Xenq_str(expl, md, def)
X char *expl, *def;
X{
X char *str;
X
X switch (md) {
X case ASK_NO:
X str = def;
X break;
X case ASK_YES:
X print_loc();
X str = tty_str("Please type your %s: ", expl, md, def);
X break;
X case ASK_SUG:
X print_loc();
X printf("Default %s: ", expl2str(expl));
X prf_s("%s\n", str2txt(def));
X str = tty_str("Please type a new %s, or press RETURN: ",
X expl, md, def);
X if (str == NULL)
X str = def;
X break;
X case ASK_ERR:
X str = tty_str("Please type a new %s: ", expl, md, def);
X break;
X }
X
X return str;
X}
X
Xint
Xenq_int(expl, md, def, max)
X char *expl;
X{
X int res;
X char deftxt[MAXSTR];
X
X VOID(sprintf(deftxt, "%d", def));
X inmood (md) {
X char *str = enq_str(expl, mood, deftxt);
X char *ptr = str;
X char ch;
X
X res = 0;
X while ((ch = *ptr++) != EOS) {
X int dig = char2int(ch) -'0';
X
X if (dig < 0 || dig > 9) {
X res = -1;
X break;
X }
X if (res > max/10 || res*10 > max - dig) {
X /* airtight, waterproof and overflow-resistant */
X res = -2;
X break;
X }
X res = res*10 + dig;
X }
X iferr (res == -1) {
X printf("The %s `%s' is not numeric\n",
X expl2str(expl), str);
X enderr;
X }
X iferr (res == -2) {
X printf("The %s `%s' is too large\n",
X expl2str(expl), str);
X printf("The maximum value is %d\n", max);
X enderr;
X }
X endmood;
X }
X return res;
X}
X
Xint
Xisascstr(str)
X char *str;
X{
X char ch;
X
X while ((ch = *str++) != EOS)
X if (!is_ascii95(ch))
X return FALSE;
X return TRUE;
X}
X
Xint
Xfld2int(addr, size)
X char *addr;
X{
X int res = 0, i;
X
X for (i = 0; i < size; i++) {
X char ch = addr[i];
X int dig = char2int(ch) - '0';
X
X if (ch == SP)
X continue;
X if (dig < 0 || dig > 9)
X return -1;
X res = res * 10 + dig;
X }
X return res;
X}
X
Xchar * /* transient */
Xfld2str(addr, size)
X char *addr;
X{
X static char str[MAXSTR];
X int i;
X
X for (i = 0; i < size; i++)
X if (i < MAXSTR-1)
X str[i] = addr[i];
X while (i > 0 && str[i-1] == SP)
X i--;
X str[i] = EOS;
X return str;
X}
X
Xfld2fld(str, s1, addr, s2)
X char *str, *addr;
X{
X if (s1 != s2)
X abort();
X while (s1-- > 0)
X *addr++ = *str++;
X}
X
Xstr2fld(str, addr, size)
X char *str, *addr;
X{
X while (size-- > 0)
X *addr++ = *str != EOS ? *str++ : SP;
X}
X
Xchar * /* transient */
Xchar2str(ch) {
X static char buff[7];
X
X if (is_ascii95(ch))
X VOID(sprintf(buff, "%c", ch));
X else
X VOID(sprintf(buff, "\\[%03o]", char2int(ch)));
X return buff;
X}
X
X/*
X * `prf_s' prints a possibly ugly string `s' under a format `f' that may
X * be so long that it normally blows up the `printf' routine.
X */
Xprf_s(f, s)
X char *f, *s;
X{
X char fch;
X
X while ((fch = *f++) != EOS) {
X if (fch != '%')
X putchar(fch);
X else {
X int sch;
X
X f++;
X while ((sch = *s++) != EOS)
X printf("%s", char2str(sch));
X }
X }
X}
X
Xerrors(str)
X char *str;
X{
X printf("%s\n", str);
X if (tf != NULL)
X tpclose(tf);
X exit(1);
X}
X
Xstruct format *
Xformat_of_type(ch)
X char ch;
X{
X struct format *fm;
X
X for (fm = &formats[0]; fm->type != EOS; fm++)
X if (fm->type == ch)
X return fm;
X return NULL;
X}
+ END-OF-FILE ansi.c
chmod 'u=rw,g=r,o=r' \a\n\s\i\.\c
set `sum \a\n\s\i\.\c`
sum=$1
case $sum in
48369) :;;
*) echo 'Bad sum in '\a\n\s\i\.\c >&2
esac
echo Extracting \e\t\o\a\.\c
sed 's/^X//' > \e\t\o\a\.\c << '+ END-OF-FILE '\e\t\o\a\.\c
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X/* To convert from EBCDIC to Ascii you need the table
X USASCII-8 TO EBCDIC-8 CORRESPONDENCE rather than the reverse,
X which strikes me as kind of counterintuitive.
X
X This table is Table 4 from
X Communications of the ACM, Vol 11, #11, Nov 1968, p 787.
X*/
X
X#define S(c,r) (c<<4) + r /* implements the C/R convention */
X
Xchar _etoa[] = { /* to be used in ebc2asc() */
X /* col 0 */
X S( 0, 0), S( 0, 1), S( 0, 2), S( 0, 3),
X S( 9,12), S( 0, 9), S( 8, 6), S( 7,15),
X S( 9, 7), S( 8,13), S( 8,14), S( 0,11),
X S( 0,12), S( 0,13), S( 0,14), S( 0,15),
X /* col 1 */
X S( 1, 0), S( 1, 1), S( 1, 2), S( 1, 3),
X S( 9,13), S( 8, 5), S( 0, 8), S( 8, 7),
X S( 1, 8), S( 1, 9), S( 9, 2), S( 8,15),
X S( 1,12), S( 1,13), S( 1,14), S( 1,15),
X /* col 2 */
X S( 8, 0), S( 8, 1), S( 8, 2), S( 8, 3),
X S( 8, 4), S( 0,10), S( 1, 7), S( 1,11),
X S( 8, 8), S( 8, 9), S( 8,10), S( 8,11),
X S( 8,12), S( 0, 5), S( 0, 6), S( 0, 7),
X /* col 3 */
X S( 9, 0), S( 9, 1), S( 1, 6), S( 9, 3),
X S( 9, 4), S( 9, 5), S( 9, 6), S( 0, 4),
X S( 9, 8), S( 9, 9), S( 9,10), S( 9,11),
X S( 1, 4), S( 1, 5), S( 9,14), S( 1,10),
X /* col 4 */
X S( 2, 0), S(10, 0), S(10, 1), S(10, 2),
X S(10, 3), S(10, 4), S(10, 5), S(10, 6),
X S(10, 7), S(10, 8), S( 5,11), S( 2,14),
X S( 3,12), S( 2, 8), S( 2,11), S( 2, 1),
X /* col 5 */
X S( 2, 6), S(10, 9), S(10,10), S(10,11),
X S(10,12), S(10,13), S(10,14), S(10,15),
X S(11, 0), S(11, 1), S( 5,13), S( 2, 4),
X S( 2,10), S( 2, 9), S( 3,11), S( 5,14),
X /* col 6 */
X S( 2,13), S( 2,15), S(11, 2), S(11, 3),
X S(11, 4), S(11, 5), S(11, 6), S(11, 7),
X S(11, 8), S(11, 9), S( 7,12), S( 2,12),
X S( 2, 5), S( 5,15), S( 3,14), S( 3,15),
X /* col 7 */
X S(11,10), S(11,11), S(11,12), S(11,13),
X S(11,14), S(11,15), S(12, 0), S(12, 1),
X S(12, 2), S( 6, 0), S( 3,10), S( 2, 3),
X S( 4, 0), S( 2, 7), S( 3,13), S( 2, 2),
X
X /* col 8 */
X S(12, 3), S( 6, 1), S( 6, 2), S( 6, 3),
X S( 6, 4), S( 6, 5), S( 6, 6), S( 6, 7),
X S( 6, 8), S( 6, 9), S(12, 4), S(12, 5),
X S(12, 6), S(12, 7), S(12, 8), S(12, 9),
X /* col 9 */
X S(12,10), S( 6,10), S( 6,11), S( 6,12),
X S( 6,13), S( 6,14), S( 6,15), S( 7, 0),
X S( 7, 1), S( 7, 2), S(12,11), S(12,12),
X S(12,13), S(12,14), S(12,15), S(13, 0),
X /* col A */
X S(13, 1), S( 7,14), S( 7, 3), S( 7, 4),
X S( 7, 5), S( 7, 6), S( 7, 7), S( 7, 8),
X S( 7, 9), S( 7,10), S(13, 2), S(13, 3),
X S(13, 4), S(13, 5), S(13, 6), S(13, 7),
X /* col B */
X S(13, 8), S(13, 9), S(13,10), S(13,11),
X S(13,12), S(13,13), S(13,14), S(13,15),
X S(14, 0), S(14, 1), S(14, 2), S(14, 3),
X S(14, 4), S(14, 5), S(14, 6), S(14, 7),
X /* col C */
X S( 7,11), S( 4, 1), S( 4, 2), S( 4, 3),
X S( 4, 4), S( 4, 5), S( 4, 6), S( 4, 7),
X S( 4, 8), S( 4, 9), S(14, 8), S(14, 9),
X S(14,10), S(14,11), S(14,12), S(14,13),
X /* col D */
X S( 7,13), S( 4,10), S( 4,11), S( 4,12),
X S( 4,13), S( 4,14), S( 4,15), S( 5, 0),
X S( 5, 1), S( 5, 2), S(14,14), S(14,15),
X S(15, 0), S(15, 1), S(15, 2), S(15, 3),
X /* col E */
X S( 5,12), S( 9,15), S( 5, 3), S( 5, 4),
X S( 5, 5), S( 5, 6), S( 5, 7), S( 5, 8),
X S( 5, 9), S( 5,10), S(15, 4), S(15, 5),
X S(15, 6), S(15, 7), S(15, 8), S(15, 9),
X /* col F */
X S( 3, 0), S( 3, 1), S( 3, 2), S( 3, 3),
X S( 3, 4), S( 3, 5), S( 3, 6), S( 3, 7),
X S( 3, 8), S( 3, 9), S(15,10), S(15,11),
X S(15,12), S(15,13), S(15,14), S(15,15)
X};
X
+ END-OF-FILE etoa.c
chmod 'u=rw,g=r,o=r' \e\t\o\a\.\c
set `sum \e\t\o\a\.\c`
sum=$1
case $sum in
05699) :;;
*) echo 'Bad sum in '\e\t\o\a\.\c >&2
esac
echo Extracting \a\n\s\i\r\.\c
sed 's/^X//' > \a\n\s\i\r\.\c << '+ END-OF-FILE '\a\n\s\i\r\.\c
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X/*
X * Name: ansir, read ANSI standard labelled tape
X * Version: 820314
X */
X
X#define MSGUSE "Usage: ansir [-cfhlmijnpg] [ name ... ]"
X
Xextern char *strncpy();
X
X#include "aux.h"
X#include "tp.h"
X#include "ansi.h"
X#include "etoa.h"
X
X#define MAXBLK TP_MAXB
X#define MINSIZE 6 /* smaller is a noise block */
X#define CRECSEP "\n" /* record separator for coded files */
X
Xchar iflag = FALSE, jflag = FALSE, nflag = FALSE, pflag = FALSE, gflag = FALSE;
Xchar ok_fln, ok_rct, ok_blk, ok_rec, ok_bfo, ok_loc, skip_it;
Xchar **filelist = NULL;
X
Xchar *labcode = NULL;
Xchar *filecode = NULL; /* may be `ascii', `ebcdic' or `binary' */
Xchar *ascii = "ASCII";
Xchar *ebcdic = "EBCDIC";
Xchar *binary = "BINARY";
Xchar binrecsep[MAXSTR];
X
Xint bsize = 0;
Xchar block[MAXBLK];
X
X#define MAXUGLY 99 /* upper limit for tallying */
Xchar uglies[256]; /* for tallying non-UNIX-ASCII chars */
Xlong tot_uglies;
X
Xint HDR1blc; /* block count as found in HDR1-label */
X
Xmain(argc, argv)
X int argc;
X char *argv[];
X{
X argc--, argv++;
X while (argc > 0 && argv[0][0] == '-') {
X char *pp = argv[0];
X
X while (*++pp) {
X switch (*pp) {
X /* insert cases to handle the standard options */
X#include "options.h"
X /* special options */
X case 'g':
X gflag = TRUE;
X break;
X case 'i':
X iflag = TRUE;
X break;
X case 'j':
X iflag = jflag = TRUE;
X break;
X case 'n':
X nflag = TRUE;
X break;
X case 'p':
X pflag = TRUE;
X break;
X }
X }
X argc--, argv++;
X }
X
X if (argc > 0)
X filelist = argv;
X
X tf = tpopen(unit, nmdns, "rx");
X nextblk();
X
X lblVOL1();
X lblUSR("UVL");
X while (bsize > 0) {
X clearflags();
X lblHDR1();
X lblHDR2();
X lblUSR("HDR");
X lblUSR("UHL");
X read_tm();
X copy();
X lblEOF1();
X lblEOF2();
X lblUSR("EOF");
X lblUSR("UTL");
X read_tm();
X }
X if (pflag)
X printf("\nEnd of tape\n");
X tpclose(tf);
X exit(0);
X
XLbad:
X errors(MSGUSE);
X exit(1);
X}
X
Xclearflags() {
X ok_fln = ok_rct = ok_blk = ok_rec = ok_bfo = ok_loc = skip_it = FALSE;
X}
X
X/*
X * Reads the VOL1-label and prints its contents
X */
X
XlblVOL1() {
X
X if (!label("VOL1", Whole(VOL1buf))) {
X missing("VOL1");
X return;
X }
X
X if (pflag)
X prVOL1();
X}
X
XlblUSR(idf)
X char *idf;
X{
X char USRnbuf[80];
X
X while (label(idf, Whole(USRnbuf)))
X if (pflag && !skip_it) {
X prhead(Labidf(USRnbuf));
X prfield("Contents", Contents(USRnbuf));
X }
X}
X
X/*
X * Reads the HDR1-label, prints its contents, and sets `filename'
X */
X
XlblHDR1() {
X
X filseqnum++;
X if (!label("HDR1", Whole(HDR1buf))) {
X missing("HDR1");
X ok_fln = FALSE;
X return;
X }
X
X strcpy(filename, fld2str(Fileidf(HDR1buf)));
X ok_fln = TRUE;
X
X if (!interesting(filename)) {
X skip_it = TRUE;
X return;
X }
X
X if (pflag)
X prHDR1();
X
X if (fld2int(Filsecnum(HDR1buf)) != filsecnum) {
X print_loc();
X printf("File section number not %d\n", filsecnum);
X }
X if (fld2int(Filseqnum(HDR1buf)) != filseqnum) {
X print_loc();
X printf("File sequence number not in order\n");
X }
X
X HDR1blc = fld2int(Blkcount(HDR1buf));
X if (chk_int("block count", HDR1blc) && HDR1blc != 0) {
X print_loc();
X printf("Block count starts from %d\n", HDR1blc);
X }
X}
X
X/*
X * Reads the HDR2-label, prints its contents and sets
X * `recformat', `blklength', `reclength' and `bufoffset'.
X */
X
XlblHDR2() {
X int found = label("HDR2", Whole(HDR2buf));
X
X if (skip_it)
X return;
X
X if (!found) {
X missing("HDR2");
X ok_rct = ok_blk = ok_rec = ok_bfo = FALSE;
X return;
X }
X
X if (pflag)
X prHDR2();
X
X fld2fld(Recformat(HDR2buf), Whole(rectype));
X ok_rct = TRUE;
X blklength = fld2int(Blklength(HDR2buf));
X ok_blk = chk_int("block length", blklength);
X reclength = fld2int(Reclength(HDR2buf));
X ok_rec = chk_int("record length", reclength);
X bufoffset = fld2int(Bufoffset(HDR2buf));
X ok_bfo = chk_int("buffer offset", bufoffset);
X}
X
Xint
Xlabel(idf, addr, size)
X char *idf, *addr;
X{
X if (bsize <= 0)
X return FALSE;
X if (labcode != NULL)
X return is_lab(idf, addr, size);
X labcode = ascii;
X if (is_lab(idf, addr, size))
X return TRUE;
X labcode = ebcdic;
X if (is_lab(idf, addr, size))
X return TRUE;
X labcode = NULL;
X return FALSE;
X}
X
Xint
Xis_lab(idf, addr, size)
X char *idf, *addr;
X{
X int sz = bsize < size ? bsize : size;
X
X VOID(strncpy(addr, block, sz));
X if (labcode == ebcdic)
X conv(addr, sz);
X str2fld("", addr+sz, size-sz);
X if (strhead(idf, addr)) {
X nextblk();
X return TRUE;
X }
X return FALSE;
X}
X
Xint
Xstrhead(s1, s2)
X char *s1, *s2;
X{
X while (*s1)
X if (*s1++ != *s2++)
X return FALSE;
X return TRUE;
X}
X
Xread_tm() {
X if (bsize == 0)
X nextblk();
X else {
X print_loc();
X printf("Tape mark missing\n");
X }
X}
X
Xnextblk() {
X
X do bsize = tpread(tf, block, MAXBLK);
X while (bsize > 0 && bsize < MINSIZE);
X}
X
Xint
Xinteresting(fn)
X char *fn;
X{
X char **lst = filelist, *nm;
X
X if (lst == NULL)
X return TRUE;
X while ((nm = *lst++) != NULL)
X if (strcmp(nm, fn) == 0)
X return TRUE;
X return FALSE;
X}
X
Xconv(addr, size)
X char *addr;
X{
X while (size-- > 0) {
X *addr = ebc2asc(*addr);
X addr++;
X }
X}
X
Xchar
Xasc2ebc(ch)
X char ch;
X{
X char ch1 = 0;
X
X while (ch != ebc2asc(ch1))
X ch1++;
X return ch1;
X}
X
X/*
X * copy one file
X */
X
Xcopy() {
X
X init_copy();
X
X do copypart();
X while (change_tape());
X
X end_copy();
X}
X
Xinit_copy() {
X int i;
X
X blkcount = reccount = 0;
X tot_uglies = 0L;
X for (i = 0; i < n_items(uglies); i++)
X uglies[i] = 0;
X
X getpars();
X}
X
Xend_copy() {
X
X if (pflag && !skip_it) {
X printf("\n");
X if (file != NULL)
X printf("Record count: %d\n", reccount);
X printf("Block count: %d\n", blkcount);
X if (file != NULL)
X prf_s("File copied: %s\n", filename);
X else
X printf("File skipped\n");
X }
X
X if (file != NULL) {
X
X VOID(fclose(file));
X file = NULL;
X if (tot_uglies != 0L) {
X int i;
X
X print_loc();
X printf("File contained %ld non-printing character%s:\n",
X english(tot_uglies));
X for (i = 0; i < n_items(uglies); i++) {
X int n = char2int(uglies[i]);
X
X if (n != 0) {
X if (n <= MAXUGLY)
X printf("%s: %d\n",
X char2str(i), n);
X else printf("%s: >%d\n",
X char2str(i), MAXUGLY);
X }
X }
X }
X }
X}
X
X/*
X * getpars sets `filename', `filecode', `recformat'
X * and as many further parameters as is necessary
X */
X
Xextern struct format fdummy;
X
Xgetpars() {
X
X if (nflag || skip_it) {
X recformat = &fdummy;
X return;
X }
X
X inmood (!ok_fln ? ASK_YES : iflag ? ASK_SUG : ASK_NO) {
X strcpy(filename, enq_str("\
X The `file name' is the name under which the tape file will be\n\
X stored on disk. The named file must not already exist.\n\
X Use a minus - to skip the file.\n",
X mood, filename));
X
X if (strcmp(filename, "-") == 0) {
X recformat = &fdummy;
X return;
X }
X iferr (!isascstr(filename)) {
X prf_s("Filename %s contains non-printing chars\n",
X filename);
X enderr;
X }
X iferr ((file = fopen(filename, "r")) != NULL) {
X prf_s("File %s already exists\n", filename);
X VOID(fclose(file));
X file = NULL;
X enderr;
X }
X iferr ((file = fopen(filename, "w")) == NULL) {
X prf_s("Cannot create %s\n", filename);
X enderr;
X }
X endmood;
X }
X
X inmood ( labcode == NULL && filecode == NULL ? ASK_YES :
X labcode == NULL || iflag ? ASK_SUG : ASK_NO
X ) {
X filecode = enq_str("\
X The `character code' is the code of the file on tape; it may be\n\
X ASCII, EBCDIC (usual for IBM-tapes) or BINARY (no conversion).\n\
X When in doubt, use %s.\n",
X mood,
X filecode != NULL ? filecode :
X labcode != NULL ? labcode :
X ascii);
X switch (filecode[0]) {
X case 'A':
X filecode = ascii;
X break;
X case 'B':
X filecode = binary;
X break;
X case 'E':
X filecode = ebcdic;
X break;
X default:
X printf("`%s' is not a character code\n", filecode);
X filecode = NULL;
X }
X iferr (filecode == NULL) {
X printf("Specify %s, %s or %s\n",
X ascii, ebcdic, binary);
X enderr;
X }
X endmood;
X }
X
X if (filecode == binary)
X strcpy(binrecsep,
X enq_str("\
X The `record separator' only applies to the character code\n\
X BINARY, where it specifies what character(s) should be written\n\
X to disk for each end-of-record on the tape. You will probably\n\
X want it to be empty, but, when in doubt, try a recognizable\n\
X string like }}}} and examine the results.\n",
X ASK_SUG, binrecsep));
X
X inmood (!ok_rct || jflag ? ASK_SUG : ASK_NO) {
X char *rct = enq_str("\
X The `record format' tells how the block on tape must be cut into\n\
X text records (lines). There are five standard ways to do so:\n\
X F: each N consecutive characters form a record, where N is the\n\
X `record length',\n\
X D: a header in each record tells its length,\n\
X U: each block is one record,\n\
X S: a special format in which records may be longer than blocks,\n\
X V: IBM Variable format.\n\
X When in doubt, use %s and examine the results, or try them all.\n",
X mood, !ok_rct ? "U" : fld2str(Whole(rectype)));
X
X iferr ( strlen(rct) != 1
X || (recformat = format_of_type(rct[0])) == NULL
X ) {
X printf("`%s' is not an ANSI format\n", rct);
X printf("Please specify F, D, U, S or V\n");
X enderr;
X }
X iferr (recformat->cpblk == NULL) {
X printf("%s-format not implemented\n", rct);
X enderr;
X }
X str2fld(rct, Whole(rectype));
X endmood;
X }
X
X inmood (!ok_blk || jflag ? ASK_SUG : ASK_NO) {
X blklength = enq_int("\
X The `block length' is the maximum number of significant\n\
X characters in any physical block (as demarcated by two\n\
X interrecord gaps) on the tape. Unless you know the exact value,\n\
X use a large number like %s.\n",
X mood, !ok_blk ? MAXBLK : blklength, MAXBLK);
X
X iferr (blklength < MINSIZE) {
X printf("Block length cannot be smaller than %d\n",
X MINSIZE);
X enderr;
X }
X endmood;
X }
X
X (*recformat->checkpar)();
X
X bufoffset = enq_int("\
X The `buffer offset' is the position in each block on the tape at\n\
X which the real information starts. Unless you know the exact\n\
X value, use 0.\n",
X !ok_bfo || jflag ? ASK_SUG : ASK_NO,
X !ok_bfo ? 0 : bufoffset,
X blklength - 1);
X}
X
Xcopypart() {
X while (bsize > 0) {
X int used;
X
X ++blkcount;
X if (bsize > blklength) {
X print_loc();
X printf("Actual block size = %d, not %d as in label\n",
X bsize, blklength);
X }
X if (filecode == ebcdic)
X conv(block, bsize);
X used = bufoffset;
X used += (*recformat->cpblk) (&block[used], bsize-used);
X if (!filler(&block[used], bsize-used)) {
X print_loc();
X printf("At block %d, after record %d:",
X blkcount, reccount);
X printf(" %d char%s garbage ignored\n",
X english(bsize-used));
X }
X nextblk();
X }
X read_tm();
X}
X
Xint
Xchange_tape() {
X return FALSE; /* not yet implemented */
X}
X
XcheckF() {
X
X inmood (!ok_rec || jflag ? ASK_SUG : ASK_NO) {
X reclength = enq_int("\
X The `record length' is a number N such that a <newline> is\n\
X assumed after each N characters read from tape. When in doubt,\n\
X use %s and examine the results for a better value.\n",
X mood,
X !ok_rec || blklength < reclength ?
X blklength : reclength,
X blklength);
X
X iferr (reclength == 0) {
X printf("Record length cannot be zero\n");
X enderr;
X }
X endmood;
X }
X}
X
X
Xint
XcpFblk(buf, size)
X char *buf;
X{
X int i = 0;
X
X while (i <= size - reclength) {
X char *rec = &buf[i];
X int sz = reclength;
X
X reccount++;
X if (filecode != binary) {
X char pad = rec[sz-1];
X
X if (!is_ascii95(pad) || pad == SP) /* liberal */
X while (sz > 0 && rec[sz-1] == pad)
X sz--;
X }
X put_rec(rec, sz);
X put_eor();
X i += reclength;
X }
X return i;
X}
X
Xint
XcpUblk(buf, size)
X char *buf;
X{
X reccount++;
X put_rec(buf, size);
X put_eor();
X return size;
X}
X
X#define DVPREF 4 /* size of D or V length prefix */
X
Xint
XcpDVblk(buf, size)
X char *buf;
X{
X int i = rectype[0] == 'V' ? DVPREF : 0;
X
X while (size - i >= DVPREF) {
X char *rec = &buf[i];
X int sz = DVlength(rec);
X
X if (sz < DVPREF || size - i - sz < 0)
X break;
X
X reccount++;
X put_rec(rec + DVPREF, sz - DVPREF);
X put_eor();
X i += sz;
X }
X return i;
X}
X
Xint
XDVlength(buf)
X char *buf;
X{
X int res = 0;
X
X if (rectype[0] == 'V') {
X int i;
X for (i = 0; i <= 1; i++) {
X char ch = buf[i];
X res = res*256 +
X char2int(filecode == ebcdic ?
X asc2ebc(ch) : ch);
X }
X }
X else
X res = fld2int(buf, DVPREF);
X return res;
X}
X
X#define SPREF 5 /* size of S length prefix */
X
Xint
XcpSblk(buf, size)
X char *buf;
X{
X int i = 0;
X
X while (size - i >= SPREF) {
X char *rec = &buf[i];
X char ind = rec[0];
X int sz = fld2int(rec+1, SPREF-1);
X
X if (sz < SPREF || size - i - sz < 0)
X break;
X
X if (ind == '0' || ind == '1')
X reccount++;
X put_rec(rec + SPREF, sz - SPREF);
X if (ind == '0' || ind == '3')
X put_eor();
X i += sz;
X }
X return i;
X}
X
Xskip() {
X return;
X}
X
Xint
Xskpblk(buf, size)
X char *buf;
X{
X VOID(buf);
X return size;
X}
X
Xint
Xfiller(addr, size)
X char *addr;
X{
X char ch = *addr;
X
X while (size--)
X if (ch != *addr++)
X return FALSE;
X return TRUE;
X}
X
Xstruct format formats[] = {
X {'F', checkF, cpFblk},
X {'U', skip, cpUblk},
X {'D', skip, cpDVblk},
X {'V', skip, cpDVblk}, /* to cater for you know whom */
X {'S', skip, cpSblk},
X {EOS, NULL, NULL}
X};
X
Xstruct format fdummy = {EOS, skip, skpblk};
X
Xput_rec(rec, size)
X char *rec;
X{
X int i;
X
X for (i = 0; i < size; i++) {
X int ch = char2int(rec[i]);
X
X if (filecode == binary || is_ascii95(ch))
X putc(ch, file);
X else {
X fprintf(file, "%s", char2str(ch));
X if (uglies[ch] <= MAXUGLY)
X uglies[ch]++;
X tot_uglies++;
X }
X }
X}
X
Xput_eor() {
X char *sep = filecode == binary ? binrecsep : CRECSEP;
X char ch;
X
X while ((ch = *sep++) != EOS)
X putc(ch, file);
X}
X
X/*
X * Reads the EOF1-label and checks block count
X */
X
XlblEOF1() {
X int bcount;
X int found = label("EOF1", Whole(HDR1buf));
X
X if (skip_it)
X return;
X
X if (!found) {
X missing("EOF1");
X return;
X }
X
X bcount = fld2int(Blkcount(HDR1buf));
X
X if (pflag)
X prHDR1();
X
X if (HDR1blc >= 0 && bcount != blkcount + HDR1blc) {
X print_loc();
X printf(
X "File holds %d block%s whereas labels report %d block%s\n",
X english(blkcount), english(bcount - HDR1blc));
X }
X}
X
X/*
X * Read EOF2-label
X */
X
XlblEOF2() {
X int found = label("EOF2", Whole(HDR2buf));
X
X if (skip_it)
X return;
X
X if (!found) {
X missing("EOF2");
X return;
X }
X
X if (pflag)
X prHDR2();
X}
X
X/*
X * Print routines
X */
X
XprVOL1() {
X prhead(Labidf(VOL1buf));
X printf("The labels are in %s\n", labcode);
X prfield("Volume serial number", Volidf(VOL1buf));
X prfield("Volume accessibility", Volacc(VOL1buf));
X prunused(Sp1(VOL1buf));
X prfield("Owner identification", Ownidf(VOL1buf));
X prunused(Sp2(VOL1buf));
X prfield("Label version", Labvers(VOL1buf));
X}
X
XprHDR1() {
X prhead(Labidf(HDR1buf));
X prfield("File identifier", Fileidf(HDR1buf));
X prfield("Set identifier", Filesetidf(HDR1buf));
X prfield("File section number", Filsecnum(HDR1buf));
X prfield("File sequence number", Filseqnum(HDR1buf));
X if (gflag) {
X prfield("Generation number", Gennum(HDR1buf));
X prfield("Generation version number", Genversnum(HDR1buf));
X }
X prfield("Creation date", Creatdate(HDR1buf));
X prfield("Expiration date", Expirdate(HDR1buf));
X prfield("File accessibility", Fileacc(HDR1buf));
X prfield("Block count", Blkcount(HDR1buf));
X prfield("System code", Syscode(HDR1buf));
X prunused(Sp3(HDR1buf));
X}
X
XprHDR2() {
X prhead(Labidf(HDR2buf));
X prfield("Record format", Recformat(HDR2buf));
X prfield("Block length", Blklength(HDR2buf));
X prfield("Record length", Reclength(HDR2buf));
X prfield("System software", Syssoftw(HDR2buf));
X prfield("Buffer offset", Bufoffset(HDR2buf));
X prunused(Sp4(HDR2buf));
X}
X
Xprhead(addr, size)
X char *addr;
X{
X printf("\nInformation from the %s-label\n", fld2str(addr, size));
X}
X
Xprfield(nm, addr, size)
X char *nm, *addr;
X{
X char *str = fld2str(addr, size);
X
X printf("%s: ", nm);
X prf_s("%s\n", *str == EOS ? sps2txt(size) : str);
X}
X
Xprunused(addr, size)
X char *addr;
X{
X char *str = fld2str(addr, size);
X
X if (strlen(str) > 0)
X prf_s("Unused field: %s\n", str);
X}
X
Xmissing(idf)
X char *idf;
X{
X print_loc();
X printf("%s-label missing\n", idf);
X}
X
Xint
Xchk_int(nm, val)
X char *nm;
X{
X if (val < 0) {
X print_loc();
X printf("Garbage in %s field\n", nm);
X return FALSE;
X }
X else
X return TRUE;
X}
X
Xprint_loc() {
X
X if (ok_loc || pflag)
X return;
X if (ok_fln)
X prf_s("\n*** At file `%s':\n", filename);
X else
X printf("\n*** At file number %d:\n", filseqnum);
X ok_loc = TRUE;
X}
+ END-OF-FILE ansir.c
chmod 'u=rw,g=r,o=r' \a\n\s\i\r\.\c
set `sum \a\n\s\i\r\.\c`
sum=$1
case $sum in
51802) :;;
*) echo 'Bad sum in '\a\n\s\i\r\.\c >&2
esac
echo Extracting \a\n\s\i\w\.\c
sed 's/^X//' > \a\n\s\i\w\.\c << '+ END-OF-FILE '\a\n\s\i\w\.\c
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X/*
X * Name: ansiw, write ANSI standard labelled tape
X * Version: 820314
X */
X
X#define MSGUSE "Usage: ansiw [-cfhlmignpv] [ file ... ]"
X
X#include "aux.h"
X#include "sys.h"
X#include "tp.h"
X#include "tploc.h" /* to get SYSCODE */
X#include "ansi.h"
X
X#define MAXBLK 2048
X#define MINBLK 18
X#define FILLER '^'
X
Xchar iflag = FALSE, gflag = FALSE, pflag = FALSE, vflag = FALSE;
Xchar block[MAXBLK];
X
Xstruct DD {
X long size;
X long lrecl;
X char ascii95;
X char example;
X} dd;
Xstruct DD empty_dd = {0L, 0L, TRUE, EOS};
X
X#define divis(m, n) ((n)!=0&&(m)%(n)==0)
X
Xmain(argc, argv)
X int argc;
X char *argv[];
X{
X argc--, argv++;
X while (argc > 0 && argv[0][0] == '-') {
X char *pp = argv[0];
X
X while (*++pp) {
X switch (*pp) {
X /* insert cases to handle the standard options */
X#include "options.h"
X /* special options */
X case 'g':
X gflag = TRUE;
X break;
X case 'i':
X iflag = TRUE;
X break;
X case 'n':
X unit = TP_IMAG;
X nmdns = "/dev/null";
X break;
X case 'p':
X pflag = TRUE;
X break;
X case 'v':
X vflag = TRUE;
X break;
X }
X }
X argc--, argv++;
X }
X tf = tpopen(unit, nmdns, "w");
X
X check_args(argc, argv);
X
X lblVOL1(iflag || vflag ? ASK_SUG : ASK_NO);
X
X while (argc-- != 0) {
X strcpy(filename, argv[filseqnum]);
X filseqnum++;
X blkcount = 0;
X
X opendd(filename);
X if (file == NULL) {
X printf(">>> File %s ", filename);
X errors("has suddenly disappeared!!!");
X }
X lblHDR1(iflag ? ASK_SUG : ASK_NO);
X lblHDR2(iflag ? ASK_SUG : ASK_NO);
X wrt_tm();
X copy();
X wrt_tm();
X lblEOF1();
X lblEOF2();
X wrt_tm();
X }
X
X wrt_tm();
X tpclose(tf);
X exit(0);
X
XLbad:
X errors(MSGUSE);
X exit(1);
X}
X
Xcheck_args(c, v)
X char *v[];
X{
X char ok = TRUE;
X
X while (c-- > 0) {
X int f = open(*v, 0);
X
X if (f < 0) {
X printf("Cannot open %s\n", *v);
X ok = FALSE;
X }
X else VOID(close(f));
X v++;
X }
X if (!ok)
X errors("Stop");
X}
X
Xwrt_tm()
X{ /* writes a tapemark */
X tpwrite(tf, "", 0);
X}
X
Xlong
Xtab(p)
X long p; /* the position in which a tab from p would land */
X{
X return (p/8+1)*8;
X}
X
X/*
X * `opendd' opens the file `fn' and determines its `dd' parameters
X */
X
Xopendd(fn)
X char *fn;
X{
X int ch;
X long lr;
X
X dd = empty_dd;
X if ((file = fopen(fn, "r")) == NULL)
X return;
X
X lr = 0L;
X while ((ch = getc(file)) != EOF) {
X dd.size++;
X if (ch == NL) {
X if (lr > dd.lrecl)
X dd.lrecl = lr;
X lr = 0L;
X }
X else
X if (ch == TAB) {
X lr = tab(lr);
X }
X else {
X lr++;
X if (!is_ascii95(ch)) {
X dd.ascii95 = FALSE;
X dd.example = ch;
X }
X }
X }
X if (lr > dd.lrecl)
X dd.lrecl = lr;
X
X VOID(fclose(file));
X file = fopen(fn, "r");
X}
X
X/*
X * the writing of labels
X */
X
XlblVOL1(md) {
X char *owner = username();
X
X str2fld("", Whole(VOL1buf));
X str2fld("VOL1", Labidf(VOL1buf));
X
X enq_fld("\
X The `volume serial number' is the six-character identification\n\
X number of the tape itself, as it should appear on the sticker on\n\
X the reel. When in doubt, use the default %s.\n",
X md, "222222", Volidf(VOL1buf));
X enq_fld("\
X The `volume accessibility symbol' is a single character,\n\
X recorded on the tape, which indicates how publicly accessible the\n\
X whole tape is. It is not well defined, but a single space is\n\
X generally taken to mean: accessible by anybody.\n",
X md, " ", Volacc(VOL1buf));
X enq_fld("\
X The `owner identification' is the name of the owner, as recorded\n\
X on the tape. On some systems it interacts with the file\n\
X accessibility symbol. When in doubt, specify a short string of\n\
X letters.\n",
X owner == NULL ? ASK_YES : md, owner, Ownidf(VOL1buf));
X str2fld("1", Labvers(VOL1buf));
X
X tpwrite(tf, Whole(VOL1buf));
X}
X
XlblHDR1(md) {
X char *today = sysdate();
X
X str2fld("", Whole(HDR1buf));
X str2fld("HDR1", Labidf(HDR1buf));
X enq_fld("\
X The `file identifier' is the name of the file, as recorded on\n\
X the tape. When in doubt, specify a six-letter mnemonic name.\n",
X md, filename, Fileidf(HDR1buf));
X
X fld2fld(Volidf(VOL1buf), Filesetidf(HDR1buf));
X int2fld(filsecnum, Filsecnum(HDR1buf));
X int2fld(filseqnum, Filseqnum(HDR1buf));
X enq_num("\
X The `generation number' is a counter that some operating systems\n\
X attach to a file and that is increased each time the file is\n\
X updated. Use 1.\n",
X gflag ? md : ASK_NO, 1, Gennum(HDR1buf));
X enq_num("\
X The `generation version number' tells how often an attempt to\n\
X write the file to tape has failed. Use 0.\n",
X gflag ? md : ASK_NO, 0, Genversnum(HDR1buf));
X dat2fld(today, Creatdate(HDR1buf));
X enq_dat("\
X The `expiration date' is the date, recorded on the tape, after\n\
X which the file may be overwritten. The format is 2 digits for\n\
X the year, followed by 3 digits for the day in the year, e.g.,\n\
X 86365 for the last day of 1986. When in doubt, use today's date,\n\
X %s, to make the receiver's life easier.\n",
X md, today, Expirdate(HDR1buf));
X enq_fld("\
X The `file accessibility symbol' is a single character, recorded\n\
X on the tape, which indicates how publicly accessible the file is.\n\
X It is not well defined, but a single space is generally taken to\n\
X mean: accessible by anybody.\n",
X md, " ", Fileacc(HDR1buf));
X int2fld(blkcount, Blkcount(HDR1buf));
X
X str2fld(SYSCODE /* from tploc.h */, Syscode(HDR1buf));
X
X tpwrite(tf, Whole(HDR1buf));
X}
X
XlblHDR2(md) {
X
X str2fld("", Whole(HDR2buf));
X str2fld("HDR2", Labidf(HDR2buf));
X
X if (!iflag) {
X str2fld("F", Whole(rectype));
X blklength = 1920;
X reclength = 80;
X }
X
X if (!dd.ascii95) {
X printf("`%s' contains non-ASCII95 characters, e.g., %s\n",
X filename, char2str(dd.example));
X printf("Perhaps the file code should have been BINARY");
X str2fld("U", Whole(rectype));
X }
X
X if (dd.lrecl > MAXBLK) {
X printf("`%s' has a record length > %d\n", filename, MAXBLK);
X printf("Only U-format is possible\n");
X str2fld("U", Whole(rectype));
X recformat = format_of_type('U');
X }
X else
X inmood (!dd.ascii95 ? ASK_SUG : md) {
X char *rct = enq_str("\
X The `record format' tells how lines from the disk file should be\n\
X converted to records to be packed into blocks to be recorded on\n\
X tape. Although many formats exist, only two are any good in\n\
X Information Interchange:\n\
X F (Fixed): spaces are added at the end of the line until its\n\
X length is `record length', and `block length'/`record length'\n\
X of these records form a block;\n\
X U (Undefined): `block length' characters are stored in a block.\n\
X Unless the disk file contains non-ASCII characters, use F.\n",
X mood, fld2str(Whole(rectype)));
X
X iferr ( strlen(rct) != 1
X || (recformat = format_of_type(rct[0])) == NULL
X || recformat->cpblk == NULL
X ) {
X printf(
X "Only F- and U-formats are allowed for portability\n"
X );
X enderr;
X }
X
X str2fld(rct, Whole(rectype));
X endmood;
X }
X
X (*recformat->checkpar)(md);
X
X fld2fld(Whole(rectype), Recformat(HDR2buf));
X int2fld(blklength, Blklength(HDR2buf));
X int2fld(reclength, Reclength(HDR2buf));
X int2fld(bufoffset, Bufoffset(HDR2buf));
X
X tpwrite(tf, Whole(HDR2buf));
X}
X
XcheckF(md) {
X int lr;
X
X inmood (md) {
X getBlklength(mood);
X iferr (blklength < reclength) {
X printf("Block length < phys. record length (=%ld)\n",
X dd.lrecl);
X enderr;
X }
X endmood;
X }
X
X lr = dd.lrecl;
X while (!divis(blklength, lr))
X lr++;
X if (lr < 80 && divis(blklength, 80))
X lr = 80;
X reclength = lr;
X
X inmood (md) {
X reclength = enq_int("\
X The `record length' is the number of characters into which each\n\
X line (record) is stretched before it is written to tape. It must\n\
X divide the block length. Unless the receiver has been very\n\
X specific, use %s.\n",
X mood, reclength, blklength);
X iferr (reclength == 0 || !divis(blklength, reclength)) {
X printf(
X "The block length is not a multiple of the record length\n"
X );
X enderr;
X }
X iferr (reclength < dd.lrecl) {
X printf("Record length < phys. record length (=%ld)\n",
X dd.lrecl);
X enderr;
X }
X endmood;
X }
X}
X
XcheckU(md) {
X getBlklength(md);
X reclength = blklength;
X}
X
XgetBlklength(md) {
X inmood (md) {
X blklength =
X enq_int("\
X The `block length' is the number of characters in each physical\n\
X block written to tape. Unless the receiver has specified\n\
X something else, use %s.\n",
X mood,
X (rectype[0] == 'F' && dd.lrecl > 1920) ?
X MAXBLK : !iflag ? 1920 : blklength,
X MAXBLK);
X iferr (blklength < MINBLK) {
X printf("The minimum block length is %d\n", MINBLK);
X enderr;
X }
X endmood;
X }
X}
X
X
XlblEOF1() {
X str2fld("EOF1", Labidf(HDR1buf));
X int2fld(blkcount, Blkcount(HDR1buf));
X tpwrite(tf, Whole(HDR1buf));
X}
X
XlblEOF2() {
X str2fld("EOF2", Labidf(HDR2buf));
X tpwrite(tf, Whole(HDR2buf));
X}
X
X/*
X * the copying of the file
X */
X
Xcopy() {
X int size;
X
X blkcount = reccount = 0;
X
X while ((size = (*recformat->cpblk)()) > 0) {
X while (size < MINBLK)
X block[size++] = FILLER;
X tpwrite(tf, block, size);
X ++blkcount;
X }
X VOID(fclose(file));
X file = NULL;
X if (pflag) {
X printf("File name: %s\n", filename);
X printf("Record format: %s\n", rectype);
X printf("Block length: %d; number of blocks: %d\n",
X blklength, blkcount);
X printf("Record length: %d; number of records: %d\n\n",
X reclength, reccount);
X }
X}
X
Xint
XcpFblk() {
X int ch;
X int count = 0;
X
X while (count < blklength && (ch = getc(file)) != EOF) {
X int rpos = 0;
X reccount++;
X while (ch != NL && ch != EOF) {
X if (ch == TAB) {
X int nrpos = (int)tab((long)rpos);
X while (rpos < nrpos) {
X block[count++] = SP, rpos++;
X }
X }
X else {
X block[count++] = ch, rpos++;
X }
X ch = getc(file);
X }
X while (rpos < reclength) {
X block[count++] = SP, rpos++;
X }
X }
X return count;
X}
X
Xint
XcpUblk() {
X int ch;
X int count = 0;
X
X while (count < blklength && (ch = getc(file)) != EOF) {
X block[count++] = ch;
X }
X if (count > 0)
X reccount++;
X return count;
X}
X
Xstruct format formats[] = {
X {'F', checkF, cpFblk},
X {'U', checkU, cpUblk},
X {'D', NULL, NULL},
X {'S', NULL, NULL},
X {EOS, NULL, NULL}
X};
X
X/*
X * the setting of fields
X */
X
Xint2fld(n, addr, size)
X char *addr;
X{
X addr += size;
X while (size-- > 0) {
X *--addr = n % 10 + '0';
X n = n / 10;
X }
X}
X
Xdat2fld(str, addr, size)
X char *str, *addr;
X{
X str2fld("", addr, size);
X str2fld(str, Date(addr));
X}
X
Xenq_fld(expl, md, def, addr, size)
X char *expl, *def, *addr;
X{
X char *ans;
X
X inmood (md) {
X ans = enq_str(expl, mood, def);
X iferr (strlen(ans) == 0) {
X printf("No empty answer allowed\n");
X enderr;
X }
X iferr (strlen(ans) > size) {
X printf("The %s is too long\n", expl2str(expl));
X printf("The maximum length is %d character%s\n",
X english(size));
X enderr;
X }
X iferr (!isascstr(ans)) {
X printf("The %s `%s' contains non-printing chars\n",
X expl2str(expl), ans);
X enderr;
X }
X endmood;
X }
X str2fld(ans, addr, size);
X}
X
Xenq_dat(expl, md, def, addr, size)
X char *expl, *def, *addr;
X{
X dat2fld(def, addr, size);
X inmood (md) {
X int yd;
X
X enq_fld(expl, mood, def, Date(addr));
X iferr (fld2int(Yr(addr)) < 0) {
X printf("Year must be numeric\n");
X enderr;
X }
X yd = fld2int(Yd(addr));
X iferr (yd < 1 || yd > 366) {
X printf("Date in year must be between 1 and 366\n");
X enderr;
X }
X endmood;
X }
X}
X
Xenq_num(expl, md, def, addr, size)
X char *expl, *addr;
X{
X int2fld(enq_int(expl, md, def, tento(size)-1), addr, size);
X}
X
Xint
Xtento(n) {
X int res = 1;
X
X while (n--)
X res *= 10;
X return res;
X}
X
Xprint_loc() {
X /* dummy in ansiw.c; useful in ansir.c */
X return;
X}
+ END-OF-FILE ansiw.c
chmod 'u=rw,g=r,o=r' \a\n\s\i\w\.\c
set `sum \a\n\s\i\w\.\c`
sum=$1
case $sum in
35905) :;;
*) echo 'Bad sum in '\a\n\s\i\w\.\c >&2
esac
echo Extracting \c\p\t\p\.\c
sed 's/^X//' > \c\p\t\p\.\c << '+ END-OF-FILE '\c\p\t\p\.\c
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X/*
X * Name: cptp, copy tape
X * Version: 820314
X *
X * `Cptp' converts between real tapes and tape images on disk.
X */
X
X#define MSGUSE "Usage is: cptp [-cfhlmx] [of=file | if=file]"
X
X#include <stdio.h>
X#include "aux.h"
X#include "tp.h"
X
Xint unit = 0;
Xchar *nmdns = TP_DENN;
Xchar *rx = "r";
XTPFILE *from, *to;
Xchar *filename;
Xint size;
Xchar buff[TP_MAXB];
X
Xmain(argc, argv)
X char *argv[];
X{
X char *arg;
X
X argc--, argv++;
X while (argc > 0 && argv[0][0] == '-') {
X char *pp = argv[0];
X
X while (*++pp) {
X switch (*pp) {
X /* insert cases to handle the standard options */
X#include "options.h"
X /* special options */
X case 'x':
X rx = "rx";
X break;
X }
X }
X argc--, argv++;
X }
X if (argc != 1)
X goto Lbad;
X arg = argv[0];
X if (arg[0] == '\0' || arg[1] != 'f' || arg[2] != '=')
X goto Lbad;
X filename = &arg[3];
X
X tperrout(stdout);
X switch (arg[0]) {
X case 'o':
X if (open(filename, 0) > 0)
X error("Output file already exists");
X from = tpopen(unit, nmdns, rx);
X to = tpopen(TP_IMAG, filename, "w");
X break;
X case 'i':
X from = tpopen(TP_IMAG, filename, "r");
X to = tpopen(unit, nmdns, "w");
X break;
X default:
X goto Lbad;
X }
X
X while ((size = tpread(from, buff, TP_MAXB)) >= 0) {
X if (size == TP_MAXB)
X printf("Block too long; information may be lost\n");
X tpwrite(to, buff, size);
X }
X tpclose(from);
X tpclose(to);
X exit(0);
X
XLbad:
X error(MSGUSE);
X exit(1);
X}
X
Xerror(str)
X char *str;
X{
X fprintf(stderr, "%s\n", str);
X exit(1);
X}
+ END-OF-FILE cptp.c
chmod 'u=rw,g=r,o=r' \c\p\t\p\.\c
set `sum \c\p\t\p\.\c`
sum=$1
case $sum in
62900) :;;
*) echo 'Bad sum in '\c\p\t\p\.\c >&2
esac
echo Extracting \r\a\w\t\p\.\c
sed 's/^X//' > \r\a\w\t\p\.\c << '+ END-OF-FILE '\r\a\w\t\p\.\c
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X/*
X * Name: rawtp, read raw tape
X * Version: 820314
X *
X Selected portions are read from tape and written to files.
X
X*/
X
X#define MSGUSE "Usage is: rawtp [-cfhlmx] XX [ param ... ]"
X
X#include <stdio.h>
X#include "aux.h"
X#include "tp.h"
X
X#define TRUE 1
X#define FALSE 0
X#define EOS '\0'
X
X#define EOB 0 /* End Of Block */
X#define EOX -1 /* End Of File (to avoid confusion with EOF) */
X#define EOT -2 /* End Of Tape */
X#define AT_EOB (ilength <= EOB)
X#define AT_EOX (ilength <= EOX)
X#define AT_EOT (ilength <= EOT)
X
Xchar name [128];
Xchar *eoname = &name[0];
XFILE *ofile = NULL;
X
XTPFILE *tape;
Xint unit = 0;
Xchar *nmdns = TP_DENN;
Xchar *rx = "r";
Xchar buff[TP_MAXB];
X
Xchar *strins();
X
Xmain(argc, argv)
X char **argv;
X{
X extern int ilength;
X
X argc--, argv++;
X while (argc > 0 && argv[0][0] == '-') {
X char *pp = argv[0];
X
X while (*++pp) {
X switch (*pp) {
X /* insert cases to handle the standard options */
X#include "options.h"
X /* special options */
X case 'x':
X rx = "rx";
X break;
X }
X }
X argc--, argv++;
X }
X if (argc < 1)
X goto Lbad;
X if (**argv == '+' || **argv == '-')
X goto Lbad;
X set_name(argv);
X argc--, argv++;
X
X ilength = EOT; /* fake empty tape to test parameters */
X params(argc, argv);
X
X tperrout(stdout);
X tape = tpopen(unit, nmdns, rx);
X ilength = EOB; /* and now for keeps */
X skipIRG();
X params(argc, argv);
X tpclose(tape);
X exit(0);
X
XLbad:
X error(MSGUSE, "");
X exit(1);
X}
X
Xset_name(argv)
X char **argv;
X{
X register char *pt;
X
X eoname = strins(eoname, *argv);
X eoname = strins(eoname, "01aaa01");
X *eoname = EOS;
X for (pt = eoname; pt > name; pt--)
X if (pt[-1] == '/') break;
X if (eoname - pt > 14)
X error("%s: file name too long", name);
X}
X
Xparams(argc, argv)
X char **argv;
X{
X VOID(strins(eoname-7, "01"));
X if (!argc)
X param("+1x");
X else
X while (argc--) {
X param(*argv++);
X incr(eoname-6);
X }
X}
X
Xchar *ppar; /* parameter being processed */
X
Xparam(arg)
X char *arg;
X{
X register int repl;
X
X ppar = arg;
X repl = getxrepl(ppar);
X if (repl == 0) repl--;
X VOID(strins(eoname-5, "aaa"));
X while (repl-- && instr())
X incr(eoname-3);
X}
X
Xint moved;
X
Xint
Xinstr() {
X char *p = ppar;
X
X moved = FALSE;
X VOID(strins(eoname-2, "01"));
X while (simp_instr(&p))
X incr(eoname-1);
X return moved;
X}
X
Xint copy = FALSE;
X
Xint
Xsimp_instr(pp)
X char **pp;
X{
X register int cnt;
X
X switch (**pp) {
X case EOS:
X case 'x':
X return FALSE;
X case '+':
X copy = TRUE;
X break;
X case '-':
X copy = FALSE;
X break;
X default:
X error("%s: bad parameter", ppar);
X }
X (*pp)++;
X cnt = getint(pp);
X while (cnt-- && copyfile()) {
X }
X if (**pp == '.')
X (*pp)++;
X cnt = getint(pp);
X while (cnt-- && copyblock()) {
X }
X if (**pp == '.')
X (*pp)++;
X cnt = getint(pp);
X while (cnt-- && copychar()) {
X }
X if (copy)
X dropfile();
X return TRUE;
X}
X
Xint ilength;
X
X/* ilength contains the number of characters the tape is ahead of the user;
X * or it is EOX or EOT
X */
Xchar *iptr;
X
Xint
Xcopyfile() {
X
X if (AT_EOT)
X return FALSE;
X while (copyblock()) {}
X skipTM();
X return TRUE;
X}
X
Xint
Xcopyblock() {
X
X if (AT_EOX)
X return FALSE;
X if (!copy)
X ilength = EOB;
X else
X while (copychar()) {}
X skipIRG();
X return TRUE;
X}
X
Xint
Xcopychar() {
X
X if (AT_EOB)
X return FALSE;
X outchar(*iptr);
X iptr++;
X ilength--;
X return TRUE;
X}
X
Xoutchar(c) {
X
X if (!copy)
X return;
X if (ofile == NULL) {
X getfile();
X moved = TRUE;
X }
X putc(c, ofile);
X}
X
X/* physical tape movers */
X
XskipTM() {
X
X if (AT_EOT)
X return;
X ilength = EOB;
X skipIRG();
X}
X
XskipIRG() {
X int size;
X
X if (AT_EOX)
X return;
X size = tpread(tape, buff, TP_MAXB);
X ilength = size < 0 ? EOT : size == 0 ? EOX : size;
X iptr = buff;
X if (!AT_EOT)
X moved = TRUE;
X}
X
X/* output file registration */
X
Xgetfile() {
X
X if ((ofile = fopen(name, "w")) == NULL)
X error("%s: cannot create", name);
X}
X
Xdropfile() {
X
X if (ofile != NULL) {
X VOID(fclose(ofile));
X ofile = NULL;
X }
X}
X
X/* service routines */
X
Xchar *
Xstrins(s1, s2)
X char *s1, *s2;
X{
X while (*s2 != EOS)
X *s1++ = *s2++;
X return s1;
X}
X
Xint
Xgetint(pp)
X char **pp;
X{
X register int val, res = 0;
X
X for (;;) {
X val = **pp - '0';
X if (val < 0 || val > 9)
X return res;
X (*pp)++;
X res = res*10 + val;
X }
X}
X
Xincr(p)
X char *p;
X{
X (*p)++;
X if (*p == '9' + 1) {
X *p = '0';
X incr(p-1);
X }
X else
X if (*p == 'z' + 1) {
X *p = 'a';
X incr(p-1);
X }
X}
X
Xint
Xgetxrepl(p)
X char *p;
X{
X register int r;
X
X while (*p != 'x')
X if (!*p++)
X return 1;
X p++;
X r = getint(&p);
X if (*p)
X error("%s: bad replicator", p);
X return r;
X}
X
Xerror(p1, p2)
X char *p1, *p2;
X{
X printf(p1, p2);
X printf("\n");
X exit(1);
X}
+ END-OF-FILE rawtp.c
chmod 'u=rw,g=r,o=r' \r\a\w\t\p\.\c
set `sum \r\a\w\t\p\.\c`
sum=$1
case $sum in
43915) :;;
*) echo 'Bad sum in '\r\a\w\t\p\.\c >&2
esac
echo Extracting \s\u\r\v\e\y\.\c
sed 's/^X//' > \s\u\r\v\e\y\.\c << '+ END-OF-FILE '\s\u\r\v\e\y\.\c
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X/*
X * Name: survey, survey contents of magtape
X * Version: 820314
X */
X
X#define MSGUSE "Usage is: survey [-cfhlmpx]\n"
X
X#include <stdio.h>
X#include "aux.h"
X#include "tp.h"
X#include "etoa.h"
X
X#define WIDTH 64
X
Xint unit = 0;
Xchar *nmdns = TP_DENN;
Xchar *rx = "r";
XTPFILE *tf;
Xchar buff[TP_MAXB];
Xint size;
X
Xchar pflag = 0;
X
Xmain(argc, argv)
X char *argv[];
X{
X argc--, argv++;
X while (argc > 0 && argv[0][0] == '-') {
X char *pp = argv[0];
X
X while (*++pp) {
X switch (*pp) {
X /* insert cases to handle the standard options */
X#include "options.h"
X /* special options */
X case 'p':
X pflag = 1;
X break;
X case 'x':
X rx = "rx";
X break;
X }
X }
X argc--, argv++;
X }
X
X if (argc != 0)
X goto Lbad;
X
X tf = tpopen(unit, nmdns, rx);
X
X while ((size = tpread(tf, buff, TP_MAXB)) >= 0) {
X printf("%6d", size);
X if (pflag)
X expose();
X printf("\n");
X }
X exit(0);
X
XLbad:
X fprintf(stderr, MSGUSE);
X exit(1);
X}
X
Xint
Xhex(ch) {
X return "0123456789ABCDEF"[ch&017];
X}
X
Xint
Xprintable(ch)
X char ch;
X{
X int i = char2int(ch); /* 8 bits only */
X
X return is_ascii95(i) ? i : '?';
X}
X
Xexpose() {
X if (size == 0)
X printf("\t* * * TAPE MARK * * *\n");
X else {
X int i;
X printf("\t");
X for (i = 0; i < WIDTH && i < size; i++) {
X printf("%c", printable(buff[i]));
X }
X printf("\n EBC:\t");
X for (i = 0; i < WIDTH && i < size; i++) {
X printf("%c", printable(ebc2asc(buff[i])));
X }
X printf("\n HEX:\t");
X for (i = 0; i < WIDTH/2 && i < size; i++) {
X char ch = buff[i];
X printf("%c%c", hex(ch>>4), hex(ch));
X }
X printf("\n");
X }
X}
X
+ END-OF-FILE survey.c
chmod 'u=rw,g=r,o=r' \s\u\r\v\e\y\.\c
set `sum \s\u\r\v\e\y\.\c`
sum=$1
case $sum in
22800) :;;
*) echo 'Bad sum in '\s\u\r\v\e\y\.\c >&2
esac
echo Extracting \N\O\S\s\p\l\i\t\.\c
sed 's/^X//' > \N\O\S\s\p\l\i\t\.\c << '+ END-OF-FILE '\N\O\S\s\p\l\i\t\.\c
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X/*
X * Name: NOSsplit, split Cyber system tape (data format is SI)
X * Version: 820314
X */
X
X#define MSGUSE "Usage is: NOSsplit [-cfhlm[s N]] [out_name]\n"
X
X#include <stdio.h>
X#include "aux.h"
X#include "tp.h"
Xextern char *sprintf();
X
X#define MINSIZE 6 /* smaller is a noise block */
X#define BSIZE 3840 /* blocksize binary files */
X#define CSIZE 960 /* blocksize coded files */
X#define SIZE 3840 /* maximum blocksize */
X#define EORM "\055\023\035\052\027\054\000"
X#define EORL 7
X#define EOS '\0'
X
X#define lastblock(n) ((n)!=BSIZE && (n)!=CSIZE)
X#define cybln(n) ((n)*8/60*10)
X
Xint fnumber = 0;
Xchar *ofil = "x";
Xchar fname[128];
XFILE *outf;
X
Xchar buff[SIZE];
Xint size; /* number of chars in `buff' */
Xint bpos; /* number of bits consumed by `get6bits' */
Xint bstat;
X
Xint unit = 0;
Xint skipf = 0; /* number of logical records to skip (forwards) */
Xchar *nmdns = TP_DENN;
XTPFILE *tf;
X
Xchar *progname;
X
Xmain(argc, argv)
X char *argv[];
X{
X progname = argv[0];
X argc--, argv++;
X
X while (argc > 0 && argv[0][0] == '-') {
X char *pp = argv[0];
X
X while (*++pp) {
X switch (*pp) {
X /* insert cases to handle the standard options */
X#include "options.h"
X /* special options */
X case 's':
X if (argc < 2)
X goto Lbad;
X if (!is_digit(argv[1][0]))
X goto Lbad;
X skipf = atoi(argv[1]);
X argc--, argv++;
X break;
X }
X }
X argc--, argv++;
X }
X
X if (argc == 1) {
X ofil = argv[0];
X argc--, argv++;
X }
X
X if (argc != 0)
X goto Lbad;
X
X read_tape();
X exit(0);
X
XLbad:
X fprintf(stderr, MSGUSE);
X exit(1);
X
X}
X
Xread_tape() {
X int i;
X int bcnt;
X
X tperrout(stdout);
X tf = tpopen(unit, nmdns, "rx");
X
X fillbuff();
X if (size == 80 && strncmp(buff, "VOL1", 4) == 0) {
X printf("This is a labelled tape\n");
X printf("For label information use `ansir -pn'\n");
X while (size > 0)
X fillbuff();
X if (size == 0)
X fillbuff();
X }
X else printf("This is a non-labelled tape\n");
X
X for (i = 0; i < skipf; i++) {
X if (size <= 0) {
X printf("%d record%s missing\n", english(skipf-i));
X exit(1);
X }
X fnumber++;
X while (!lastblock(size))
X fillbuff();
X fillbuff();
X }
X
X if (skipf > 0)
X printf("%d logical record%s skipped\n", english(skipf));
X
X while (size > 0) {
X newcreat(fnumber++);
X
X bcnt = 1;
X while (putbuff(cybln(size)), !lastblock(size)) {
X fillbuff();
X bcnt++;
X }
X
X proc_eor(bcnt);
X
X VOID(fclose(outf));
X outf = NULL;
X fillbuff();
X }
X
X printf("%d record%s retrieved\n", english(fnumber-skipf));
X}
X
Xnewcreat(fn) {
X int i;
X
X for (i=0; ofil[i] != EOS; i++)
X fname[i] = ofil[i];
X VOID(sprintf(&fname[i], "%04d", fn));
X outf = fopen(fname, "w");
X if (outf == NULL) {
X printf("%s: cannot create `%s'\n", progname, fname);
X exit(1);
X }
X}
X
Xfillbuff() {
X
X do size = tpread(tf, buff, sizeof buff);
X while (size > 0 && size < MINSIZE /* noise record */);
X bpos = bstat = 0;
X}
X
Xputbuff(n)
X int n; /* number of 6bit chars */
X{
X
X while (n-- > 0)
X putc(get6bits(), outf);
X}
X
X
Xproc_eor(bcnt) {
X char eor[EORL];
X int i;
X
X for (i = 0; i < EORL; i++)
X eor[i] = get6bits();
X
X printf("%s: ", fname);
X printf("%d block%s, ", english(bcnt));
X if (strncmp(eor, EORM, EORL) != 0)
X printf("no proper EOR\n");
X else
X printf("EOR%2o\n", get6bits());
X}
X
X#define left(c,n) (((c)&((077<<(8-(n)))&0377))>>(8-(n)))
X#define right(c,n) (((c)&((077>>(6-(n)))&0377))<<(6-(n)))
X/*
X * These forms are constructed through program transformations; the
X * author cannot, by any stretch of imagination, guess why they work.
X */
X
Xint
Xget6bits() {
X int res = 0;
X
X switch (bstat++) {
X case 0: res = left(buff[bpos+0], 6);
X break;
X case 1: res = right(buff[bpos+0], 2) + left(buff[bpos+1], 4);
X break;
X case 2: res = right(buff[bpos+1], 4) + left(buff[bpos+2], 2);
X break;
X case 3: res = right(buff[bpos+2], 6);
X break;
X }
X if (bstat == 4) {
X bpos += 3;
X bstat = 0;
X }
X return res;
X}
+ END-OF-FILE NOSsplit.c
chmod 'u=rw,g=r,o=r' \N\O\S\s\p\l\i\t\.\c
set `sum \N\O\S\s\p\l\i\t\.\c`
sum=$1
case $sum in
08337) :;;
*) echo 'Bad sum in '\N\O\S\s\p\l\i\t\.\c >&2
esac
echo Extracting \N\O\S\t\r\.\c
sed 's/^X//' > \N\O\S\t\r\.\c << '+ END-OF-FILE '\N\O\S\t\r\.\c
X/* This file is part of the magtape handling package MAG.
X Written by Dick Grune, Vrije Universiteit, Amsterdam.
X*/
X
X/*
X * Program: NOStr, translates a Cyber 6-bit file into a UNIX ASCII file.
X * Version: 820314
X */
X
X#define MSGUSE "Usage is: NOStr -C [file]"
X
X#include <stdio.h>
X#include "aux.h"
X
X#define MAXERR 40
X#define EOS '\0'
X
XFILE *ifile; /* input file */
Xchar *iname; /* input name */
X
Xint displZ(), asciiZ(), binary();
Xstruct conv {
X char *name;
X int (*command)();
X char *expl;
X} conv[] = {
X {"d", displZ, "Z-type records in DISPLAY code"},
X {"a", asciiZ, "Z-type records in ASCII95"},
X {"b", binary, "binary, = ASCII256"}
X};
X
Xmain(argc, argv)
X char *argv[];
X{
X int p;
X
X if (argc < 2 || argc > 3 || argv[1][0] != '-' || strlen(argv[1]) != 2)
X goto Bad_usage;
X if (argc == 2 || strcmp(argv[2], "-") == 0) {
X iname = "standard input";
X ifile = stdin;
X }
X else {
X iname = argv[2];
X ifile = fopen(iname, "r");
X if (ifile == NULL) {
X fprintf(stderr, "%s: cannot open %s\n",
X argv[0], iname);
X exit(1);
X }
X }
X for (p = 0; p < n_items(conv); p++)
X if (strcmp(&argv[1][1], conv[p].name) == 0) {
X (*conv[p].command)();
X exit(0);
X }
XBad_usage:
X fprintf(stderr, MSGUSE);
X fprintf(stderr,
X "\nwhere the conversion code C is one of the following:\n");
X for (p = 0; p < n_items(conv); p++)
X fprintf(stderr, "`%s': %s\n", conv[p].name, conv[p].expl);
X exit(1);
X}
X
X#define NL '\n'
X#define TEN 10
X
Xint cwrd[TEN];
Xlong lcnt = 1;
Xlong icnt = 0;
X
XdisplZ() { /* recognize Z-type records in DISPLAY code */
X int nch;
X int zpend = 0;
X
X while (nch = get_cwrd(TEN), nch != 0) {
X int i;
X
X if (nch != TEN)
X VOID(complain("short word", 0));
X while (nch != 0 && cwrd[nch-1] == 0)
X nch--;
X if (zpend && nch > 0)
X putdispl(0); /* zero pending */
X for (i = 0; i < nch; i++)
X putdispl(cwrd[i]);
X if (nch < TEN-1)
X putascii(NL);
X zpend = nch == TEN-1;
X }
X}
X
X#define FIVE 5
X
XasciiZ() { /* recognize Z-type records in ASCII95 */
X int nch;
X
X while (nch = get_cwrd(FIVE), nch != 0) {
X int i;
X
X if (nch != FIVE)
X VOID(complain("short word", 0));
X while (nch != 0 && cwrd[nch-1] == 0)
X nch--;
X for (i = 0; i < nch; i++)
X putascii(cwrd[i]);
X if (nch < FIVE)
X putascii(NL);
X }
X}
X
Xbinary() { /* binary, also ASCII256 */
X int ch;
X
X while (ch = get12bits(), ch != EOF)
X putascii(ch);
X}
X
Xint
Xget_cwrd(n) { /* gather n (60/n)-bit bytes into a Cyber word */
X int i;
X
X for (i = 0; i < n; i++) {
X cwrd[i] = n == TEN ? get6bits() :
X n == FIVE ? get12bits() : (abort(), 0);
X if (cwrd[i] == EOF)
X break;
X }
X return i;
X}
X
Xint
Xget12bits() {
X int ch1, ch2;
X static errcnt = 0;
X
X ch1 = get6bits();
X if (ch1 == EOF)
X return EOF;
X ch2 = get6bits();
X if (ch2 == EOF)
X ch2 = 0;
X
X ch1 = (ch1 << 6) + ch2;
X if (ch1 >> 8)
X errcnt = complain("composed char wider than 8 bits", errcnt);
X return ch1;
X}
X
Xint
Xget6bits() {
X int ch = getc(ifile);
X static errcnt = 0;
X
X if (ch == EOF)
X return EOF;
X icnt++;
X if (ch >> 6)
X errcnt = complain("input char wider than 6 bits", errcnt);
X return ch;
X}
X
Xputdispl(ch) { /* convert display to ASCII */
X putchar(
X "%ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-*/()$= ,.#[]:\"_!&'?<>@\\^;"
X [ch]);
X}
X
Xputascii(ch)
X char ch;
X{
X putchar(ch);
X if (ch == NL)
X lcnt++;
X}
X
Xint
Xcomplain(s, n)
X char *s;
X{
X if (n > MAXERR)
X return n;
X fprintf(stderr,
X "At input char %ld, at output line %ld, %s in file `%s'\n",
X icnt, lcnt, s, iname);
X if (n == MAXERR)
X fprintf(stderr,
X "After %d complaints, further complaints of this type suppressed\n",
X MAXERR);
X return n+1;
X}
+ END-OF-FILE NOStr.c
chmod 'u=rw,g=r,o=r' \N\O\S\t\r\.\c
set `sum \N\O\S\t\r\.\c`
sum=$1
case $sum in
55112) :;;
*) echo 'Bad sum in '\N\O\S\t\r\.\c >&2
esac
exit 0
--
Rich $alz "Anger is an energy"
Cronus Project, BBN Labs rsalz@bbn.com
Moderator, comp.sources.unix sources@uunet.uu.net