home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume10 / magtapetools / part02 < prev    next >
Encoding:
Text File  |  1987-08-02  |  60.6 KB  |  3,088 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v10i089:  Magtape handling package, Part02/02
  5. Message-ID: <760@uunet.UU.NET>
  6. Date: 3 Aug 87 21:25:42 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 3077
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: Dick Grune <dick@cs.vu.nl>
  12. Posting-number: Volume 10, Issue 89
  13. Archive-name: magtapetools/Part02
  14.  
  15. : --------------------------- cut here --------------------------
  16. PATH=/bin:/usr/bin
  17. echo Extracting \a\n\s\i\.\h
  18. sed 's/^X//' > \a\n\s\i\.\h << '+ END-OF-FILE '\a\n\s\i\.\h
  19. X/*    This file is part of the magtape handling package MAG.
  20. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  21. X*/
  22. X
  23. X#include    <stdio.h>
  24. X
  25. Xextern char *strcpy();
  26. X
  27. X#define    NL    '\n'
  28. X#define    TAB    '\t'
  29. X#define    SP    ' '
  30. X#define    EOS    '\0'
  31. X
  32. X#define    TRUE    1
  33. X#define    FALSE    0
  34. X
  35. X#define    MAXSTR    128
  36. X
  37. X/*
  38. X * It is tempting to use structs for the declaration of the label data
  39. X * structures, access the fields through selectors and let the C-compiler
  40. X * do the offset calculation. There are, however, two problems:
  41. X *    1. alignment is different on different machines (VAX vs. PDP11),
  42. X *    2. according to the book the fields may even be arranged in inverse
  43. X *       order.
  44. X * So structs are out and defines are in.
  45. X * A field is implemented as a pair: an address and a length.
  46. X */
  47. X
  48. X/* the general fields */
  49. X#define    Whole(p)    &(p)[0], sizeof (p)
  50. X#define    Labidf(p)    &(p)[0], 4
  51. X
  52. X/* the VOL1 label */
  53. X#define    Volidf(p)    &(p)[4], 6
  54. X#define    Volacc(p)    &(p)[10], 1
  55. X#define    Sp1(p)        &(p)[11], 26
  56. X#define    Ownidf(p)    &(p)[37], 14
  57. X#define    Sp2(p)        &(p)[51], 28
  58. X#define    Labvers(p)    &(p)[79], 1
  59. X
  60. X/* dates */
  61. X#define    Sp(p)        &(p)[0], 1
  62. X#define    Date(p)        &(p)[1], 5
  63. X#define    Yr(p)        &(p)[1], 2
  64. X#define    Yd(p)        &(p)[3], 3
  65. X
  66. X/* the HDR1 label */
  67. X#define    Fileidf(p)    &(p)[4], 17
  68. X#define    Filesetidf(p)    &(p)[21], 6
  69. X#define    Filsecnum(p)    &(p)[27], 4
  70. X#define    Filseqnum(p)    &(p)[31], 4
  71. X#define    Gennum(p)    &(p)[35], 4
  72. X#define    Genversnum(p)    &(p)[39], 2
  73. X#define    Creatdate(p)    &(p)[41], 6
  74. X#define    Expirdate(p)    &(p)[47], 6
  75. X#define    Fileacc(p)    &(p)[53], 1
  76. X#define    Blkcount(p)    &(p)[54], 6
  77. X#define    Syscode(p)    &(p)[60], 13
  78. X#define    Sp3(p)        &(p)[73], 7
  79. X
  80. X/* the HDR2 label */
  81. X#define    Recformat(p)    &(p)[4], 1
  82. X#define    Blklength(p)    &(p)[5], 5
  83. X#define    Reclength(p)    &(p)[10], 5
  84. X#define    Syssoftw(p)    &(p)[15], 35
  85. X#define    Bufoffset(p)    &(p)[50], 2
  86. X#define    Sp4(p)        &(p)[52], 28
  87. X
  88. X/* the USRn label */
  89. X#define    Contents(p)    &(p)[4], 76
  90. X
  91. X
  92. Xextern int unit;
  93. Xextern char *nmdns;
  94. Xextern TPFILE *tf;
  95. X
  96. X#define    ASK_NO    0    /* use default and check */
  97. X#define    ASK_YES    1    /* ask and check */
  98. X#define    ASK_SUG    2    /* suggest default and check */
  99. X#define    ASK_ERR    3    /* ask again and check */
  100. X
  101. X/*    Macros to define an additional control structure to handle
  102. X    interactive input, under the presence of user errors.
  103. X*/
  104. X#define    inmood(md)    {int mood = md; for (;;mood=ASK_ERR)
  105. X#define    iferr(cond)    if(cond){print_loc();
  106. X#define    enderr        continue;}
  107. X#define    endmood        break;}
  108. X
  109. Xextern char *sps2txt(), *str2txt(), *expl2str(), *tty_line(), *tty_str();
  110. Xextern char *enq_str(), *fld2str(), *char2str();
  111. Xextern int enq_int(), isascstr(), fld2int();
  112. Xextern fld2fld(), str2fld(), prf_s(), errors();
  113. X
  114. Xstruct format    {
  115. X    char type;
  116. X    int (*checkpar)();
  117. X    int (*cpblk)();
  118. X};
  119. X
  120. Xextern struct format formats[];
  121. Xextern struct format *format_of_type();
  122. X
  123. Xextern char filename[MAXSTR];
  124. Xextern FILE *file;
  125. Xextern int filseqnum;
  126. Xextern int filsecnum;
  127. Xextern char rectype[1];
  128. Xextern struct format *recformat;
  129. Xextern int blklength;
  130. Xextern int reclength;
  131. Xextern int bufoffset;
  132. Xextern int reccount;
  133. Xextern int blkcount;
  134. X
  135. Xextern char VOL1buf[80];
  136. Xextern char HDR1buf[80];
  137. Xextern char HDR2buf[80];
  138. + END-OF-FILE ansi.h
  139. chmod 'u=rw,g=r,o=r' \a\n\s\i\.\h
  140. set `sum \a\n\s\i\.\h`
  141. sum=$1
  142. case $sum in
  143. 43328)    :;;
  144. *)    echo 'Bad sum in '\a\n\s\i\.\h >&2
  145. esac
  146. echo Extracting \e\t\o\a\.\h
  147. sed 's/^X//' > \e\t\o\a\.\h << '+ END-OF-FILE '\e\t\o\a\.\h
  148. X/*    This file is part of the magtape handling package MAG.
  149. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  150. X*/
  151. X
  152. Xextern char _etoa[];            /* from etoa.c */
  153. X
  154. X#define    ebc2asc(c)    (_etoa[(c)&0377])
  155. + END-OF-FILE etoa.h
  156. chmod 'u=rw,g=r,o=r' \e\t\o\a\.\h
  157. set `sum \e\t\o\a\.\h`
  158. sum=$1
  159. case $sum in
  160. 11080)    :;;
  161. *)    echo 'Bad sum in '\e\t\o\a\.\h >&2
  162. esac
  163. echo Extracting \o\p\t\i\o\n\s\.\h
  164. sed 's/^X//' > \o\p\t\i\o\n\s\.\h << '+ END-OF-FILE '\o\p\t\i\o\n\s\.\h
  165. X/*    This file is part of the magtape handling package MAG.
  166. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  167. X*/
  168. X
  169. X/*    Having a chunk out of a switch statement as a separate include
  170. X    file is unusual, but this file does implement a conceptual unit:
  171. X    the handling of the standard command line options for describing
  172. X    a generalized magtape.  See mag.1.
  173. X    
  174. X    This include file assumes
  175. X        aux.h        to be included
  176. X        tp.h        idem
  177. X    uses and updates
  178. X        argc        as supplied by main()
  179. X        argv        idem
  180. X    sets
  181. X        unit        the unit number
  182. X        nmdns        file name or density
  183. X    and jumps to
  184. X        Lbad        on bad command line parameters
  185. X*/
  186. X
  187. X    default:
  188. X        goto Lbad;
  189. X    case 'c':            /* character device */
  190. X        unit = TP_CDEV;
  191. X        if (argc < 2)
  192. X            goto Lbad;
  193. X        nmdns = argv[1];
  194. X        argc--, argv++;
  195. X        break;
  196. X    case 'f':            /* tape image */
  197. X        unit = TP_IMAG;
  198. X        if (argc < 2)
  199. X            goto Lbad;
  200. X        nmdns = argv[1];
  201. X        argc--, argv++;
  202. X        break;
  203. X    case 'h':            /* high density */
  204. X        nmdns = TP_DENH;
  205. X        break;
  206. X    case 'l':            /* low density */
  207. X        nmdns = TP_DENL;
  208. X        break;
  209. X    case 'm':            /* unit number (real tape unit) */
  210. X        if (argc < 2)
  211. X            goto Lbad;
  212. X        if (!is_digit(argv[1][0]))
  213. X            goto Lbad;
  214. X        unit = atoi(argv[1]);
  215. X        argc--, argv++;
  216. X        break;
  217. + END-OF-FILE options.h
  218. chmod 'u=rw,g=r,o=r' \o\p\t\i\o\n\s\.\h
  219. set `sum \o\p\t\i\o\n\s\.\h`
  220. sum=$1
  221. case $sum in
  222. 18446)    :;;
  223. *)    echo 'Bad sum in '\o\p\t\i\o\n\s\.\h >&2
  224. esac
  225. echo Extracting \a\n\s\i\.\c
  226. sed 's/^X//' > \a\n\s\i\.\c << '+ END-OF-FILE '\a\n\s\i\.\c
  227. X/*    This file is part of the magtape handling package MAG.
  228. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  229. X*/
  230. X
  231. X#include    "aux.h"
  232. X#include    "tp.h"
  233. X#include    "ansi.h"
  234. X
  235. Xextern char *sprintf();
  236. X
  237. Xint unit = 0;
  238. Xchar *nmdns = TP_DENN;
  239. XTPFILE *tf = NULL;
  240. X
  241. Xchar filename[MAXSTR];
  242. XFILE *file = NULL;
  243. Xint filseqnum = 0;
  244. Xint filsecnum = 1;
  245. Xchar rectype[1] = 'F';
  246. Xstruct format *recformat;
  247. Xint blklength = 1920;
  248. Xint reclength = 80;
  249. Xint bufoffset = 0;
  250. Xint reccount;
  251. Xint blkcount;
  252. X
  253. Xchar VOL1buf[80];
  254. Xchar HDR1buf[80];
  255. Xchar HDR2buf[80];
  256. X
  257. Xchar *
  258. Xsps2txt(p)    {
  259. X    return p == 0 ? "<empty>" : p == 1 ? "<space>" : "<spaces>";
  260. X}
  261. X
  262. Xchar *
  263. Xstr2txt(s)
  264. X    char *s;
  265. X{
  266. X    int p = 0;
  267. X
  268. X    while (s[p] != EOS)    {
  269. X        if (s[p] != SP)
  270. X            return s;
  271. X        p++;
  272. X    }
  273. X    return sps2txt(p);
  274. X}
  275. X
  276. X/* An expl(anation) is an explanatory string which contains the name of the
  277. X * object being explained as the first item between ` and ' . The expl may
  278. X * contain one %s which is replaced by the default (string) value.
  279. X */
  280. X
  281. Xchar * /* transient */
  282. Xexpl2str(expl)
  283. X    char *expl;
  284. X{
  285. X    static char str[MAXSTR];
  286. X    char *nm = expl, cnt = 0;
  287. X    
  288. X    while (*nm != EOS && *nm != '`')    {
  289. X        nm++;
  290. X    }
  291. X    nm++;
  292. X    while (*nm != EOS && *nm != '\'')    {
  293. X        if (cnt < MAXSTR-1)
  294. X            str[cnt++] = *nm;
  295. X        nm++;
  296. X    }
  297. X    str[cnt] = EOS;
  298. X    return str;
  299. X}
  300. X
  301. Xchar * /* transient */
  302. Xtty_line()    {
  303. X    static char ans[MAXSTR];
  304. X    int cnt = 0;
  305. X    int ch;
  306. X
  307. X    while ((ch = getchar()) != NL)    {
  308. X        if (ch == EOF)
  309. X            errors("\n*** No interaction!!!");
  310. X        if (cnt < MAXSTR-1)
  311. X            ans[cnt++] = ch;
  312. X    }
  313. X    ans[cnt] = EOS;
  314. X    return ans;
  315. X}
  316. X
  317. Xchar * /* transient */
  318. Xtty_str(prompt, expl, md, def)
  319. X    char *prompt, *expl, md, *def;
  320. X{
  321. X    static char conversation = FALSE;
  322. X    char *str;
  323. X    int err = 0;
  324. X
  325. X    if (!conversation)    {
  326. X        prf_s("\n\
  327. X    I shall have to ask some questions; to get more information,\n\
  328. X    answer a question with a single question mark (?).\n\n", "");
  329. X        conversation = TRUE;
  330. X    }
  331. X    while (err < 3)    {
  332. X        printf(prompt, expl2str(expl));
  333. X        str= tty_line();
  334. X        if (strcmp(str, "?") == 0)    {
  335. X            printf("\n");
  336. X            prf_s(expl, def);
  337. X            printf("\n");
  338. X        }
  339. X        else
  340. X        if (strlen(str) > 0)
  341. X            return str;
  342. X        else
  343. X        if (md == ASK_SUG)
  344. X            return NULL;
  345. X        else    {
  346. X            printf("I do need an answer!\n");
  347. X            err++;
  348. X        }
  349. X    }
  350. X    errors("\nSorry");
  351. X    return str;
  352. X}
  353. X
  354. Xchar * /* transient */
  355. Xenq_str(expl, md, def)
  356. X    char *expl, *def;
  357. X{
  358. X    char *str;
  359. X
  360. X    switch (md)    {
  361. X    case ASK_NO:
  362. X        str = def;
  363. X        break;
  364. X    case ASK_YES:
  365. X        print_loc();
  366. X        str = tty_str("Please type your %s: ", expl, md, def);
  367. X        break;
  368. X    case ASK_SUG:
  369. X        print_loc();
  370. X        printf("Default %s: ", expl2str(expl));
  371. X        prf_s("%s\n", str2txt(def));
  372. X        str = tty_str("Please type a new %s, or press RETURN: ",
  373. X            expl, md, def);
  374. X        if (str == NULL)
  375. X            str = def;
  376. X        break;
  377. X    case ASK_ERR:
  378. X        str = tty_str("Please type a new %s: ", expl, md, def);
  379. X        break;
  380. X    }
  381. X
  382. X    return str;
  383. X}
  384. X
  385. Xint
  386. Xenq_int(expl, md, def, max)
  387. X    char *expl;
  388. X{
  389. X    int res;
  390. X    char deftxt[MAXSTR];
  391. X
  392. X    VOID(sprintf(deftxt, "%d", def));
  393. X    inmood (md)    {
  394. X        char *str = enq_str(expl, mood, deftxt);
  395. X        char *ptr = str;
  396. X        char ch;
  397. X
  398. X        res = 0;
  399. X        while ((ch = *ptr++) != EOS)    {
  400. X            int dig = char2int(ch) -'0';
  401. X
  402. X            if (dig < 0 || dig > 9)    {
  403. X                res = -1;
  404. X                break;
  405. X            }
  406. X            if (res > max/10 || res*10 > max - dig)    {
  407. X            /* airtight, waterproof and overflow-resistant */
  408. X                res = -2;
  409. X                break;
  410. X            }
  411. X            res = res*10 + dig;
  412. X        }
  413. X        iferr (res == -1)    {
  414. X            printf("The %s `%s' is not numeric\n",
  415. X                    expl2str(expl), str);
  416. X            enderr;
  417. X        }
  418. X        iferr (res == -2)    {
  419. X            printf("The %s `%s' is too large\n",
  420. X                    expl2str(expl), str);
  421. X            printf("The maximum value is %d\n", max);
  422. X            enderr;
  423. X        }
  424. X        endmood;
  425. X    }
  426. X    return res;
  427. X}
  428. X
  429. Xint
  430. Xisascstr(str)
  431. X    char *str;
  432. X{
  433. X    char ch;
  434. X
  435. X    while ((ch = *str++) != EOS)
  436. X        if (!is_ascii95(ch))
  437. X            return FALSE;
  438. X    return TRUE;
  439. X}
  440. X
  441. Xint
  442. Xfld2int(addr, size)
  443. X    char *addr;
  444. X{
  445. X    int res = 0, i;
  446. X
  447. X    for (i = 0; i < size; i++)    {
  448. X        char ch = addr[i];
  449. X        int dig = char2int(ch) - '0';
  450. X        
  451. X        if (ch == SP)
  452. X            continue;
  453. X        if (dig < 0 || dig > 9)
  454. X            return -1;
  455. X        res = res * 10 + dig;
  456. X    }
  457. X    return res;
  458. X}
  459. X
  460. Xchar * /* transient */
  461. Xfld2str(addr, size)
  462. X    char *addr;
  463. X{
  464. X    static char str[MAXSTR];
  465. X    int i;
  466. X
  467. X    for (i = 0; i < size; i++)
  468. X        if (i < MAXSTR-1)
  469. X            str[i] = addr[i];
  470. X    while (i > 0 && str[i-1] == SP)
  471. X        i--;
  472. X    str[i] = EOS;
  473. X    return str;
  474. X}
  475. X
  476. Xfld2fld(str, s1, addr, s2)
  477. X    char *str, *addr;
  478. X{
  479. X    if (s1 != s2)
  480. X        abort();
  481. X    while (s1-- > 0)
  482. X        *addr++ = *str++;
  483. X}
  484. X
  485. Xstr2fld(str, addr, size)
  486. X    char *str, *addr;
  487. X{
  488. X    while (size-- > 0)
  489. X        *addr++ = *str != EOS ? *str++ : SP;
  490. X}
  491. X
  492. Xchar * /* transient */
  493. Xchar2str(ch)    {
  494. X    static char buff[7];
  495. X
  496. X    if (is_ascii95(ch))
  497. X        VOID(sprintf(buff, "%c", ch));
  498. X    else
  499. X        VOID(sprintf(buff, "\\[%03o]", char2int(ch)));
  500. X    return buff;
  501. X}
  502. X
  503. X/*
  504. X * `prf_s' prints a possibly ugly string `s' under a format `f' that may
  505. X * be so long that it normally blows up the `printf' routine.
  506. X */
  507. Xprf_s(f, s)
  508. X    char *f, *s;
  509. X{
  510. X    char fch;
  511. X
  512. X    while ((fch = *f++) != EOS)    {
  513. X        if (fch != '%')
  514. X            putchar(fch);
  515. X        else    {
  516. X            int sch;
  517. X
  518. X            f++;
  519. X            while ((sch = *s++) != EOS)
  520. X                printf("%s", char2str(sch));
  521. X        }
  522. X    }
  523. X}
  524. X
  525. Xerrors(str)
  526. X    char *str;
  527. X{
  528. X    printf("%s\n", str);
  529. X    if (tf != NULL)
  530. X        tpclose(tf);
  531. X    exit(1);
  532. X}
  533. X
  534. Xstruct format *
  535. Xformat_of_type(ch)
  536. X    char ch;
  537. X{
  538. X    struct format *fm;
  539. X
  540. X    for (fm = &formats[0]; fm->type != EOS; fm++)
  541. X        if (fm->type == ch)
  542. X            return fm;
  543. X    return NULL;
  544. X}
  545. + END-OF-FILE ansi.c
  546. chmod 'u=rw,g=r,o=r' \a\n\s\i\.\c
  547. set `sum \a\n\s\i\.\c`
  548. sum=$1
  549. case $sum in
  550. 48369)    :;;
  551. *)    echo 'Bad sum in '\a\n\s\i\.\c >&2
  552. esac
  553. echo Extracting \e\t\o\a\.\c
  554. sed 's/^X//' > \e\t\o\a\.\c << '+ END-OF-FILE '\e\t\o\a\.\c
  555. X/*    This file is part of the magtape handling package MAG.
  556. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  557. X*/
  558. X
  559. X/*    To convert from EBCDIC to Ascii you need the table
  560. X    USASCII-8 TO EBCDIC-8 CORRESPONDENCE rather than the reverse,
  561. X    which strikes me as kind of counterintuitive.
  562. X    
  563. X    This table is Table 4 from
  564. X    Communications of the ACM, Vol 11, #11, Nov 1968, p 787.
  565. X*/
  566. X
  567. X#define    S(c,r)    (c<<4) + r    /* implements the C/R convention */
  568. X
  569. Xchar _etoa[] =    {        /* to be used in ebc2asc() */
  570. X    /* col 0 */
  571. X    S( 0, 0), S( 0, 1), S( 0, 2), S( 0, 3),
  572. X    S( 9,12), S( 0, 9), S( 8, 6), S( 7,15),
  573. X    S( 9, 7), S( 8,13), S( 8,14), S( 0,11),
  574. X    S( 0,12), S( 0,13), S( 0,14), S( 0,15),
  575. X    /* col 1 */
  576. X    S( 1, 0), S( 1, 1), S( 1, 2), S( 1, 3),
  577. X    S( 9,13), S( 8, 5), S( 0, 8), S( 8, 7),
  578. X    S( 1, 8), S( 1, 9), S( 9, 2), S( 8,15),
  579. X    S( 1,12), S( 1,13), S( 1,14), S( 1,15),
  580. X    /* col 2 */
  581. X    S( 8, 0), S( 8, 1), S( 8, 2), S( 8, 3),
  582. X    S( 8, 4), S( 0,10), S( 1, 7), S( 1,11),
  583. X    S( 8, 8), S( 8, 9), S( 8,10), S( 8,11),
  584. X    S( 8,12), S( 0, 5), S( 0, 6), S( 0, 7),
  585. X    /* col 3 */
  586. X    S( 9, 0), S( 9, 1), S( 1, 6), S( 9, 3),
  587. X    S( 9, 4), S( 9, 5), S( 9, 6), S( 0, 4),
  588. X    S( 9, 8), S( 9, 9), S( 9,10), S( 9,11),
  589. X    S( 1, 4), S( 1, 5), S( 9,14), S( 1,10),
  590. X    /* col 4 */
  591. X    S( 2, 0), S(10, 0), S(10, 1), S(10, 2),
  592. X    S(10, 3), S(10, 4), S(10, 5), S(10, 6),
  593. X    S(10, 7), S(10, 8), S( 5,11), S( 2,14),
  594. X    S( 3,12), S( 2, 8), S( 2,11), S( 2, 1),
  595. X    /* col 5 */
  596. X    S( 2, 6), S(10, 9), S(10,10), S(10,11),
  597. X    S(10,12), S(10,13), S(10,14), S(10,15),
  598. X    S(11, 0), S(11, 1), S( 5,13), S( 2, 4),
  599. X    S( 2,10), S( 2, 9), S( 3,11), S( 5,14),
  600. X    /* col 6 */
  601. X    S( 2,13), S( 2,15), S(11, 2), S(11, 3),
  602. X    S(11, 4), S(11, 5), S(11, 6), S(11, 7),
  603. X    S(11, 8), S(11, 9), S( 7,12), S( 2,12),
  604. X    S( 2, 5), S( 5,15), S( 3,14), S( 3,15),
  605. X    /* col 7 */
  606. X    S(11,10), S(11,11), S(11,12), S(11,13),
  607. X    S(11,14), S(11,15), S(12, 0), S(12, 1),
  608. X    S(12, 2), S( 6, 0), S( 3,10), S( 2, 3),
  609. X    S( 4, 0), S( 2, 7), S( 3,13), S( 2, 2),
  610. X
  611. X    /* col 8 */
  612. X    S(12, 3), S( 6, 1), S( 6, 2), S( 6, 3),
  613. X    S( 6, 4), S( 6, 5), S( 6, 6), S( 6, 7),
  614. X    S( 6, 8), S( 6, 9), S(12, 4), S(12, 5),
  615. X    S(12, 6), S(12, 7), S(12, 8), S(12, 9),
  616. X    /* col 9 */
  617. X    S(12,10), S( 6,10), S( 6,11), S( 6,12),
  618. X    S( 6,13), S( 6,14), S( 6,15), S( 7, 0),
  619. X    S( 7, 1), S( 7, 2), S(12,11), S(12,12),
  620. X    S(12,13), S(12,14), S(12,15), S(13, 0),
  621. X    /* col A */
  622. X    S(13, 1), S( 7,14), S( 7, 3), S( 7, 4),
  623. X    S( 7, 5), S( 7, 6), S( 7, 7), S( 7, 8),
  624. X    S( 7, 9), S( 7,10), S(13, 2), S(13, 3),
  625. X    S(13, 4), S(13, 5), S(13, 6), S(13, 7),
  626. X    /* col B */
  627. X    S(13, 8), S(13, 9), S(13,10), S(13,11),
  628. X    S(13,12), S(13,13), S(13,14), S(13,15),
  629. X    S(14, 0), S(14, 1), S(14, 2), S(14, 3),
  630. X    S(14, 4), S(14, 5), S(14, 6), S(14, 7),
  631. X    /* col C */
  632. X    S( 7,11), S( 4, 1), S( 4, 2), S( 4, 3),
  633. X    S( 4, 4), S( 4, 5), S( 4, 6), S( 4, 7),
  634. X    S( 4, 8), S( 4, 9), S(14, 8), S(14, 9),
  635. X    S(14,10), S(14,11), S(14,12), S(14,13),
  636. X    /* col D */
  637. X    S( 7,13), S( 4,10), S( 4,11), S( 4,12),
  638. X    S( 4,13), S( 4,14), S( 4,15), S( 5, 0),
  639. X    S( 5, 1), S( 5, 2), S(14,14), S(14,15),
  640. X    S(15, 0), S(15, 1), S(15, 2), S(15, 3),
  641. X    /* col E */
  642. X    S( 5,12), S( 9,15), S( 5, 3), S( 5, 4),
  643. X    S( 5, 5), S( 5, 6), S( 5, 7), S( 5, 8),
  644. X    S( 5, 9), S( 5,10), S(15, 4), S(15, 5),
  645. X    S(15, 6), S(15, 7), S(15, 8), S(15, 9),
  646. X    /* col F */
  647. X    S( 3, 0), S( 3, 1), S( 3, 2), S( 3, 3),
  648. X    S( 3, 4), S( 3, 5), S( 3, 6), S( 3, 7),
  649. X    S( 3, 8), S( 3, 9), S(15,10), S(15,11),
  650. X    S(15,12), S(15,13), S(15,14), S(15,15)
  651. X};
  652. X
  653. + END-OF-FILE etoa.c
  654. chmod 'u=rw,g=r,o=r' \e\t\o\a\.\c
  655. set `sum \e\t\o\a\.\c`
  656. sum=$1
  657. case $sum in
  658. 05699)    :;;
  659. *)    echo 'Bad sum in '\e\t\o\a\.\c >&2
  660. esac
  661. echo Extracting \a\n\s\i\r\.\c
  662. sed 's/^X//' > \a\n\s\i\r\.\c << '+ END-OF-FILE '\a\n\s\i\r\.\c
  663. X/*    This file is part of the magtape handling package MAG.
  664. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  665. X*/
  666. X
  667. X/*
  668. X * Name: ansir, read ANSI standard labelled tape
  669. X * Version: 820314
  670. X */
  671. X
  672. X#define    MSGUSE    "Usage: ansir [-cfhlmijnpg] [ name ... ]"
  673. X
  674. Xextern char *strncpy();
  675. X
  676. X#include    "aux.h"
  677. X#include    "tp.h"
  678. X#include    "ansi.h"
  679. X#include    "etoa.h"
  680. X
  681. X#define    MAXBLK    TP_MAXB
  682. X#define    MINSIZE    6            /* smaller is a noise block */
  683. X#define    CRECSEP    "\n"            /* record separator for coded files */
  684. X
  685. Xchar iflag = FALSE, jflag = FALSE, nflag = FALSE, pflag = FALSE, gflag = FALSE;
  686. Xchar ok_fln, ok_rct, ok_blk, ok_rec, ok_bfo, ok_loc, skip_it;
  687. Xchar **filelist = NULL;
  688. X
  689. Xchar *labcode = NULL;
  690. Xchar *filecode = NULL;    /* may be `ascii', `ebcdic' or `binary' */
  691. Xchar *ascii = "ASCII";
  692. Xchar *ebcdic = "EBCDIC";
  693. Xchar *binary = "BINARY";
  694. Xchar binrecsep[MAXSTR];
  695. X
  696. Xint bsize = 0;
  697. Xchar block[MAXBLK];
  698. X
  699. X#define    MAXUGLY    99    /* upper limit for tallying */
  700. Xchar uglies[256];    /* for tallying non-UNIX-ASCII chars */
  701. Xlong tot_uglies;
  702. X
  703. Xint HDR1blc;    /* block count as found in HDR1-label */
  704. X
  705. Xmain(argc, argv)
  706. X    int argc;
  707. X    char *argv[];
  708. X{
  709. X    argc--, argv++;
  710. X    while (argc > 0 && argv[0][0] == '-')    {
  711. X        char *pp = argv[0];
  712. X        
  713. X        while (*++pp)    {
  714. X            switch (*pp)    {
  715. X            /* insert cases to handle the standard options */
  716. X#include    "options.h"
  717. X            /* special options */
  718. X            case 'g':
  719. X                gflag = TRUE;
  720. X                break;
  721. X            case 'i':
  722. X                iflag = TRUE;
  723. X                break;
  724. X            case 'j':
  725. X                iflag = jflag = TRUE;
  726. X                break;
  727. X            case 'n':
  728. X                nflag = TRUE;
  729. X                break;
  730. X            case 'p':
  731. X                pflag = TRUE;
  732. X                break;
  733. X            }
  734. X        }
  735. X        argc--, argv++;
  736. X    }
  737. X
  738. X    if (argc > 0)
  739. X        filelist = argv;
  740. X
  741. X    tf = tpopen(unit, nmdns, "rx");
  742. X    nextblk();
  743. X
  744. X    lblVOL1();
  745. X    lblUSR("UVL");
  746. X    while (bsize > 0)    {
  747. X        clearflags();
  748. X        lblHDR1();
  749. X        lblHDR2();
  750. X        lblUSR("HDR");
  751. X        lblUSR("UHL");
  752. X        read_tm();
  753. X        copy();
  754. X        lblEOF1();
  755. X        lblEOF2();
  756. X        lblUSR("EOF");
  757. X        lblUSR("UTL");
  758. X        read_tm();
  759. X    }
  760. X    if (pflag)
  761. X        printf("\nEnd of tape\n");
  762. X    tpclose(tf);
  763. X    exit(0);
  764. X
  765. XLbad:
  766. X    errors(MSGUSE);
  767. X    exit(1);
  768. X}
  769. X
  770. Xclearflags()    {
  771. X    ok_fln = ok_rct = ok_blk = ok_rec = ok_bfo = ok_loc = skip_it = FALSE;
  772. X}
  773. X
  774. X/*
  775. X * Reads the VOL1-label and prints its contents
  776. X */
  777. X
  778. XlblVOL1()    {
  779. X
  780. X    if (!label("VOL1", Whole(VOL1buf)))    {
  781. X        missing("VOL1");
  782. X        return;
  783. X    }
  784. X
  785. X    if (pflag)
  786. X        prVOL1();
  787. X}
  788. X
  789. XlblUSR(idf)
  790. X    char *idf;
  791. X{
  792. X    char USRnbuf[80];
  793. X
  794. X    while (label(idf, Whole(USRnbuf)))
  795. X        if (pflag && !skip_it)    {
  796. X            prhead(Labidf(USRnbuf));
  797. X            prfield("Contents", Contents(USRnbuf));
  798. X        }
  799. X}
  800. X
  801. X/*
  802. X * Reads the HDR1-label, prints its contents, and sets `filename'
  803. X */
  804. X
  805. XlblHDR1()    {
  806. X
  807. X    filseqnum++;
  808. X    if (!label("HDR1", Whole(HDR1buf)))    {
  809. X        missing("HDR1");
  810. X        ok_fln = FALSE;
  811. X        return;
  812. X    }
  813. X
  814. X    strcpy(filename, fld2str(Fileidf(HDR1buf)));
  815. X    ok_fln = TRUE;
  816. X
  817. X    if (!interesting(filename))    {
  818. X        skip_it = TRUE;
  819. X        return;
  820. X    }
  821. X
  822. X    if (pflag)
  823. X        prHDR1();
  824. X
  825. X    if (fld2int(Filsecnum(HDR1buf)) != filsecnum)    {
  826. X        print_loc();
  827. X        printf("File section number not %d\n", filsecnum);
  828. X    }
  829. X    if (fld2int(Filseqnum(HDR1buf)) != filseqnum)    {
  830. X        print_loc();
  831. X        printf("File sequence number not in order\n");
  832. X    }
  833. X
  834. X    HDR1blc = fld2int(Blkcount(HDR1buf));
  835. X    if (chk_int("block count", HDR1blc) && HDR1blc != 0)    {
  836. X        print_loc();
  837. X        printf("Block count starts from %d\n", HDR1blc);
  838. X    }
  839. X}
  840. X
  841. X/*
  842. X * Reads the HDR2-label, prints its contents and sets
  843. X * `recformat', `blklength', `reclength' and `bufoffset'.
  844. X */
  845. X
  846. XlblHDR2()    {
  847. X    int found = label("HDR2", Whole(HDR2buf));
  848. X
  849. X    if (skip_it)
  850. X        return;
  851. X
  852. X    if (!found)    {
  853. X        missing("HDR2");
  854. X        ok_rct = ok_blk = ok_rec = ok_bfo = FALSE;
  855. X        return;
  856. X    }
  857. X
  858. X    if (pflag)
  859. X        prHDR2();
  860. X
  861. X    fld2fld(Recformat(HDR2buf), Whole(rectype));
  862. X    ok_rct = TRUE;
  863. X    blklength = fld2int(Blklength(HDR2buf));
  864. X    ok_blk = chk_int("block length", blklength);
  865. X    reclength = fld2int(Reclength(HDR2buf));
  866. X    ok_rec = chk_int("record length", reclength);
  867. X    bufoffset = fld2int(Bufoffset(HDR2buf));
  868. X    ok_bfo = chk_int("buffer offset", bufoffset);
  869. X}
  870. X
  871. Xint
  872. Xlabel(idf, addr, size)
  873. X    char *idf, *addr;
  874. X{
  875. X    if (bsize <= 0)
  876. X        return FALSE;
  877. X    if (labcode != NULL)
  878. X        return is_lab(idf, addr, size);
  879. X    labcode = ascii;
  880. X    if (is_lab(idf, addr, size))
  881. X        return TRUE;
  882. X    labcode = ebcdic;
  883. X    if (is_lab(idf, addr, size))
  884. X        return TRUE;
  885. X    labcode = NULL;
  886. X    return FALSE;
  887. X}
  888. X
  889. Xint
  890. Xis_lab(idf, addr, size)
  891. X    char *idf, *addr;
  892. X{
  893. X    int sz = bsize < size ? bsize : size;
  894. X
  895. X    VOID(strncpy(addr, block, sz));
  896. X    if (labcode == ebcdic)
  897. X        conv(addr, sz);
  898. X    str2fld("", addr+sz, size-sz);
  899. X    if (strhead(idf, addr))    {
  900. X        nextblk();
  901. X        return TRUE;
  902. X    }
  903. X    return FALSE;
  904. X}
  905. X
  906. Xint
  907. Xstrhead(s1, s2)
  908. X    char *s1, *s2;
  909. X{
  910. X    while (*s1)
  911. X        if (*s1++ != *s2++)
  912. X            return FALSE;
  913. X    return TRUE;
  914. X}
  915. X
  916. Xread_tm()    {
  917. X    if (bsize == 0)
  918. X        nextblk();
  919. X    else    {
  920. X        print_loc();
  921. X        printf("Tape mark missing\n");
  922. X    }
  923. X}
  924. X
  925. Xnextblk()    {
  926. X
  927. X    do bsize = tpread(tf, block, MAXBLK);
  928. X    while (bsize > 0 && bsize < MINSIZE);
  929. X}
  930. X
  931. Xint
  932. Xinteresting(fn)
  933. X    char *fn;
  934. X{
  935. X    char **lst = filelist, *nm;
  936. X
  937. X    if (lst == NULL)
  938. X        return TRUE;
  939. X    while ((nm = *lst++) != NULL)
  940. X        if (strcmp(nm, fn) == 0)
  941. X            return TRUE;
  942. X    return FALSE;
  943. X}
  944. X
  945. Xconv(addr, size)
  946. X    char *addr;
  947. X{
  948. X    while (size-- > 0)    {
  949. X        *addr = ebc2asc(*addr);
  950. X        addr++;
  951. X    }
  952. X}
  953. X
  954. Xchar
  955. Xasc2ebc(ch)
  956. X    char ch;
  957. X{
  958. X    char ch1 = 0;
  959. X
  960. X    while (ch != ebc2asc(ch1))
  961. X        ch1++;
  962. X    return ch1;
  963. X}
  964. X
  965. X/*
  966. X * copy one file
  967. X */
  968. X
  969. Xcopy()    {
  970. X
  971. X    init_copy();
  972. X
  973. X    do copypart();
  974. X    while (change_tape());
  975. X
  976. X    end_copy();
  977. X}
  978. X
  979. Xinit_copy()    {
  980. X    int i;
  981. X
  982. X    blkcount = reccount = 0;
  983. X    tot_uglies = 0L;
  984. X    for (i = 0; i < n_items(uglies); i++)
  985. X        uglies[i] = 0;
  986. X
  987. X    getpars();
  988. X}
  989. X
  990. Xend_copy()    {
  991. X
  992. X    if (pflag && !skip_it)    {
  993. X        printf("\n");
  994. X        if (file != NULL)
  995. X            printf("Record count: %d\n", reccount);
  996. X        printf("Block count: %d\n", blkcount);
  997. X        if (file != NULL)
  998. X            prf_s("File copied: %s\n", filename);
  999. X        else
  1000. X            printf("File skipped\n");
  1001. X    }
  1002. X
  1003. X    if (file != NULL)    {
  1004. X
  1005. X        VOID(fclose(file));
  1006. X        file = NULL;
  1007. X        if (tot_uglies != 0L)    {
  1008. X            int i;
  1009. X
  1010. X            print_loc();
  1011. X            printf("File contained %ld non-printing character%s:\n",
  1012. X                english(tot_uglies));
  1013. X            for (i = 0; i < n_items(uglies); i++)    {
  1014. X                int n = char2int(uglies[i]);
  1015. X
  1016. X                if (n != 0)    {
  1017. X                    if (n <= MAXUGLY)
  1018. X                        printf("%s: %d\n",
  1019. X                            char2str(i), n);
  1020. X                    else    printf("%s: >%d\n",
  1021. X                            char2str(i), MAXUGLY);
  1022. X                }
  1023. X            }
  1024. X        }
  1025. X    }
  1026. X}
  1027. X
  1028. X/*
  1029. X * getpars sets `filename', `filecode', `recformat'
  1030. X * and as many further parameters as is necessary
  1031. X */
  1032. X
  1033. Xextern struct format fdummy;
  1034. X
  1035. Xgetpars()    {
  1036. X
  1037. X    if (nflag || skip_it)    {
  1038. X        recformat = &fdummy;
  1039. X        return;
  1040. X    }
  1041. X
  1042. X    inmood (!ok_fln ? ASK_YES : iflag ? ASK_SUG : ASK_NO)    {
  1043. X        strcpy(filename, enq_str("\
  1044. X    The `file name' is the name under which the tape file will be\n\
  1045. X    stored on disk. The named file must not already exist.\n\
  1046. X    Use a minus - to skip the file.\n",
  1047. X            mood, filename));
  1048. X
  1049. X        if (strcmp(filename, "-") == 0)    {
  1050. X            recformat = &fdummy;
  1051. X            return;
  1052. X        }
  1053. X        iferr (!isascstr(filename))    {
  1054. X            prf_s("Filename %s contains non-printing chars\n",
  1055. X                filename);
  1056. X            enderr;
  1057. X        }
  1058. X        iferr ((file = fopen(filename, "r")) != NULL)    {
  1059. X            prf_s("File %s already exists\n", filename);
  1060. X            VOID(fclose(file));
  1061. X            file = NULL;
  1062. X            enderr;
  1063. X        }
  1064. X        iferr ((file = fopen(filename, "w")) == NULL)    {
  1065. X            prf_s("Cannot create %s\n", filename);
  1066. X            enderr;
  1067. X        }
  1068. X        endmood;
  1069. X    }
  1070. X
  1071. X    inmood (    labcode == NULL && filecode == NULL ? ASK_YES :
  1072. X            labcode == NULL || iflag ? ASK_SUG : ASK_NO
  1073. X    )    {
  1074. X        filecode = enq_str("\
  1075. X    The `character code' is the code of the file on tape; it may be\n\
  1076. X    ASCII, EBCDIC (usual for IBM-tapes) or BINARY (no conversion).\n\
  1077. X    When in doubt, use %s.\n",
  1078. X            mood,
  1079. X            filecode != NULL ? filecode :
  1080. X            labcode != NULL ? labcode :
  1081. X            ascii);
  1082. X        switch (filecode[0])    {
  1083. X        case 'A':
  1084. X            filecode = ascii;
  1085. X            break;
  1086. X        case 'B':
  1087. X            filecode = binary;
  1088. X            break;
  1089. X        case 'E':
  1090. X            filecode = ebcdic;
  1091. X            break;
  1092. X        default:
  1093. X            printf("`%s' is not a character code\n", filecode);
  1094. X            filecode = NULL;
  1095. X        }
  1096. X        iferr (filecode == NULL)    {
  1097. X            printf("Specify %s, %s or %s\n",
  1098. X                    ascii, ebcdic, binary);
  1099. X            enderr;
  1100. X        }
  1101. X        endmood;
  1102. X    }
  1103. X
  1104. X    if (filecode == binary)
  1105. X        strcpy(binrecsep,
  1106. X            enq_str("\
  1107. X    The `record separator' only applies to the character code\n\
  1108. X    BINARY, where it specifies what character(s) should be written\n\
  1109. X    to disk for each end-of-record on the tape. You will probably\n\
  1110. X    want it to be empty, but, when in doubt, try a recognizable\n\
  1111. X    string like }}}} and examine the results.\n",
  1112. X                ASK_SUG, binrecsep));
  1113. X
  1114. X    inmood (!ok_rct || jflag ? ASK_SUG : ASK_NO)    {
  1115. X        char *rct = enq_str("\
  1116. X    The `record format' tells how the block on tape must be cut into\n\
  1117. X    text records (lines). There are five standard ways to do so:\n\
  1118. X    F: each N consecutive characters form a record, where N is the\n\
  1119. X       `record length',\n\
  1120. X    D: a header in each record tells its length,\n\
  1121. X    U: each block is one record,\n\
  1122. X    S: a special format in which records may be longer than blocks,\n\
  1123. X    V: IBM Variable format.\n\
  1124. X    When in doubt, use %s and examine the results, or try them all.\n",
  1125. X            mood, !ok_rct ? "U" : fld2str(Whole(rectype)));
  1126. X
  1127. X        iferr (    strlen(rct) != 1
  1128. X        ||    (recformat = format_of_type(rct[0])) == NULL
  1129. X        )    {
  1130. X            printf("`%s' is not an ANSI format\n", rct);
  1131. X            printf("Please specify F, D, U, S or V\n");
  1132. X            enderr;
  1133. X        }
  1134. X        iferr (recformat->cpblk == NULL)    {
  1135. X            printf("%s-format not implemented\n", rct);
  1136. X            enderr;
  1137. X        }
  1138. X        str2fld(rct, Whole(rectype));
  1139. X        endmood;
  1140. X    }
  1141. X
  1142. X    inmood (!ok_blk || jflag ? ASK_SUG : ASK_NO)    {
  1143. X        blklength = enq_int("\
  1144. X    The `block length' is the maximum number of significant\n\
  1145. X    characters in any physical block (as demarcated by two\n\
  1146. X    interrecord gaps) on the tape.  Unless you know the exact value,\n\
  1147. X    use a large number like %s.\n",
  1148. X            mood, !ok_blk ? MAXBLK : blklength, MAXBLK);
  1149. X
  1150. X        iferr (blklength < MINSIZE)    {
  1151. X            printf("Block length cannot be smaller than %d\n",
  1152. X                MINSIZE);
  1153. X            enderr;
  1154. X        }
  1155. X        endmood;
  1156. X    }
  1157. X
  1158. X    (*recformat->checkpar)();
  1159. X
  1160. X    bufoffset = enq_int("\
  1161. X    The `buffer offset' is the position in each block on the tape at\n\
  1162. X    which the real information starts. Unless you know the exact\n\
  1163. X    value, use 0.\n",
  1164. X        !ok_bfo || jflag ? ASK_SUG : ASK_NO,
  1165. X        !ok_bfo ? 0 : bufoffset,
  1166. X        blklength - 1);
  1167. X}
  1168. X
  1169. Xcopypart()    {
  1170. X    while (bsize > 0)    {
  1171. X        int used;
  1172. X
  1173. X        ++blkcount;
  1174. X        if (bsize > blklength)    {
  1175. X            print_loc();
  1176. X            printf("Actual block size = %d, not %d as in label\n",
  1177. X                        bsize, blklength);
  1178. X        }
  1179. X        if (filecode == ebcdic)
  1180. X            conv(block, bsize);
  1181. X        used = bufoffset;
  1182. X        used += (*recformat->cpblk) (&block[used], bsize-used);
  1183. X        if (!filler(&block[used], bsize-used))    {
  1184. X            print_loc();
  1185. X            printf("At block %d, after record %d:",
  1186. X                blkcount, reccount);
  1187. X            printf(" %d char%s garbage ignored\n",
  1188. X                    english(bsize-used));
  1189. X        }
  1190. X        nextblk();
  1191. X    }
  1192. X    read_tm();
  1193. X}
  1194. X
  1195. Xint
  1196. Xchange_tape()    {
  1197. X    return FALSE;    /* not yet implemented */
  1198. X}
  1199. X
  1200. XcheckF()    {
  1201. X
  1202. X    inmood (!ok_rec || jflag ? ASK_SUG : ASK_NO)    {
  1203. X        reclength = enq_int("\
  1204. X    The `record length' is a number N such that a <newline> is\n\
  1205. X    assumed after each N characters read from tape. When in doubt,\n\
  1206. X    use %s and examine the results for a better value.\n",
  1207. X            mood,
  1208. X            !ok_rec || blklength < reclength ?
  1209. X                blklength : reclength,
  1210. X            blklength);
  1211. X
  1212. X        iferr (reclength == 0)    {
  1213. X            printf("Record length cannot be zero\n");
  1214. X            enderr;
  1215. X        }
  1216. X        endmood;
  1217. X    }
  1218. X}
  1219. X
  1220. X
  1221. Xint
  1222. XcpFblk(buf, size)
  1223. X    char *buf;
  1224. X{
  1225. X    int i = 0;
  1226. X
  1227. X    while (i <= size - reclength)    {
  1228. X        char *rec = &buf[i];
  1229. X        int sz = reclength;
  1230. X
  1231. X        reccount++;
  1232. X        if (filecode != binary)    {
  1233. X            char pad = rec[sz-1];
  1234. X
  1235. X            if (!is_ascii95(pad) || pad == SP)    /* liberal */
  1236. X                while (sz > 0 && rec[sz-1] == pad)
  1237. X                    sz--;
  1238. X        }
  1239. X        put_rec(rec, sz);
  1240. X        put_eor();
  1241. X        i += reclength;
  1242. X    }
  1243. X    return i;
  1244. X}
  1245. X
  1246. Xint
  1247. XcpUblk(buf, size)
  1248. X    char *buf;
  1249. X{
  1250. X    reccount++;
  1251. X    put_rec(buf, size);
  1252. X    put_eor();
  1253. X    return size;
  1254. X}
  1255. X
  1256. X#define    DVPREF    4    /* size of D or V length prefix */
  1257. X
  1258. Xint
  1259. XcpDVblk(buf, size)
  1260. X    char *buf;
  1261. X{
  1262. X    int i = rectype[0] == 'V' ? DVPREF : 0;
  1263. X
  1264. X    while (size - i >= DVPREF)    {
  1265. X        char *rec = &buf[i];
  1266. X        int sz = DVlength(rec);
  1267. X
  1268. X        if (sz < DVPREF || size - i - sz < 0)
  1269. X            break;
  1270. X
  1271. X        reccount++;
  1272. X        put_rec(rec + DVPREF, sz - DVPREF);
  1273. X        put_eor();
  1274. X        i += sz;
  1275. X    }
  1276. X    return i;
  1277. X}
  1278. X
  1279. Xint
  1280. XDVlength(buf)
  1281. X    char *buf;
  1282. X{
  1283. X    int res = 0;
  1284. X
  1285. X    if (rectype[0] == 'V')    {
  1286. X        int i;
  1287. X        for (i = 0; i <= 1; i++)    {
  1288. X            char ch = buf[i];
  1289. X            res = res*256 +
  1290. X                char2int(filecode == ebcdic ?
  1291. X                            asc2ebc(ch) : ch);
  1292. X        }
  1293. X    }
  1294. X    else
  1295. X        res = fld2int(buf, DVPREF);
  1296. X    return res;
  1297. X}
  1298. X
  1299. X#define    SPREF    5    /* size of S length prefix */
  1300. X
  1301. Xint
  1302. XcpSblk(buf, size)
  1303. X    char *buf;
  1304. X{
  1305. X    int i = 0;
  1306. X
  1307. X    while (size - i >= SPREF)    {
  1308. X        char *rec = &buf[i];
  1309. X        char ind = rec[0];
  1310. X        int sz = fld2int(rec+1, SPREF-1);
  1311. X
  1312. X        if (sz < SPREF || size - i - sz < 0)
  1313. X            break;
  1314. X
  1315. X        if (ind == '0' || ind == '1')
  1316. X            reccount++;
  1317. X        put_rec(rec + SPREF, sz - SPREF);
  1318. X        if (ind == '0' || ind == '3')
  1319. X            put_eor();
  1320. X        i += sz;
  1321. X    }
  1322. X    return i;
  1323. X}
  1324. X
  1325. Xskip()    {
  1326. X    return;
  1327. X}
  1328. X
  1329. Xint
  1330. Xskpblk(buf, size)
  1331. X    char *buf;
  1332. X{
  1333. X    VOID(buf);
  1334. X    return size;
  1335. X}
  1336. X
  1337. Xint
  1338. Xfiller(addr, size)
  1339. X    char *addr;
  1340. X{
  1341. X    char ch = *addr;
  1342. X
  1343. X    while (size--)
  1344. X        if (ch != *addr++)
  1345. X            return FALSE;
  1346. X    return TRUE;
  1347. X}
  1348. X
  1349. Xstruct format formats[] =    {
  1350. X    {'F', checkF, cpFblk},
  1351. X    {'U', skip, cpUblk},
  1352. X    {'D', skip, cpDVblk},
  1353. X    {'V', skip, cpDVblk},    /* to cater for you know whom */
  1354. X    {'S', skip, cpSblk},
  1355. X    {EOS, NULL, NULL}
  1356. X};
  1357. X
  1358. Xstruct format fdummy =    {EOS, skip, skpblk};
  1359. X
  1360. Xput_rec(rec, size)
  1361. X    char *rec;
  1362. X{
  1363. X    int i;
  1364. X
  1365. X    for (i = 0; i < size; i++)    {
  1366. X        int ch = char2int(rec[i]);
  1367. X
  1368. X        if (filecode == binary || is_ascii95(ch))
  1369. X            putc(ch, file);
  1370. X        else    {
  1371. X            fprintf(file, "%s", char2str(ch));
  1372. X            if (uglies[ch] <= MAXUGLY)
  1373. X                uglies[ch]++;
  1374. X            tot_uglies++;
  1375. X        }
  1376. X    }
  1377. X}
  1378. X
  1379. Xput_eor()    {
  1380. X    char *sep = filecode == binary ? binrecsep : CRECSEP;
  1381. X    char ch;
  1382. X
  1383. X    while ((ch = *sep++) != EOS)
  1384. X        putc(ch, file);
  1385. X}
  1386. X
  1387. X/*
  1388. X * Reads the EOF1-label and checks block count
  1389. X */
  1390. X
  1391. XlblEOF1()    {
  1392. X    int bcount;
  1393. X    int found = label("EOF1", Whole(HDR1buf));
  1394. X
  1395. X    if (skip_it)
  1396. X        return;
  1397. X
  1398. X    if (!found)    {
  1399. X        missing("EOF1");
  1400. X        return;
  1401. X    }
  1402. X
  1403. X    bcount = fld2int(Blkcount(HDR1buf));
  1404. X
  1405. X    if (pflag)
  1406. X        prHDR1();
  1407. X
  1408. X    if (HDR1blc >= 0 && bcount != blkcount + HDR1blc)    {
  1409. X        print_loc();
  1410. X        printf(
  1411. X        "File holds %d block%s whereas labels report %d block%s\n",
  1412. X            english(blkcount), english(bcount - HDR1blc));
  1413. X    }
  1414. X}
  1415. X
  1416. X/*
  1417. X * Read EOF2-label
  1418. X */
  1419. X
  1420. XlblEOF2()    {
  1421. X    int found = label("EOF2", Whole(HDR2buf));
  1422. X
  1423. X    if (skip_it)
  1424. X        return;
  1425. X
  1426. X    if (!found)    {
  1427. X        missing("EOF2");
  1428. X        return;
  1429. X    }
  1430. X
  1431. X    if (pflag)
  1432. X        prHDR2();
  1433. X}
  1434. X
  1435. X/*
  1436. X * Print routines
  1437. X */
  1438. X
  1439. XprVOL1()    {
  1440. X    prhead(Labidf(VOL1buf));
  1441. X    printf("The labels are in %s\n", labcode);
  1442. X    prfield("Volume serial number", Volidf(VOL1buf));
  1443. X    prfield("Volume accessibility", Volacc(VOL1buf));
  1444. X    prunused(Sp1(VOL1buf));
  1445. X    prfield("Owner identification", Ownidf(VOL1buf));
  1446. X    prunused(Sp2(VOL1buf));
  1447. X    prfield("Label version", Labvers(VOL1buf));
  1448. X}
  1449. X
  1450. XprHDR1()    {
  1451. X    prhead(Labidf(HDR1buf));
  1452. X    prfield("File identifier", Fileidf(HDR1buf));
  1453. X    prfield("Set identifier", Filesetidf(HDR1buf));
  1454. X    prfield("File section number", Filsecnum(HDR1buf));
  1455. X    prfield("File sequence number", Filseqnum(HDR1buf));
  1456. X    if (gflag)    {
  1457. X        prfield("Generation number", Gennum(HDR1buf));
  1458. X        prfield("Generation version number", Genversnum(HDR1buf));
  1459. X    }
  1460. X    prfield("Creation date", Creatdate(HDR1buf));
  1461. X    prfield("Expiration date", Expirdate(HDR1buf));
  1462. X    prfield("File accessibility", Fileacc(HDR1buf));
  1463. X    prfield("Block count", Blkcount(HDR1buf));
  1464. X    prfield("System code", Syscode(HDR1buf));
  1465. X    prunused(Sp3(HDR1buf));
  1466. X}
  1467. X
  1468. XprHDR2()    {
  1469. X    prhead(Labidf(HDR2buf));
  1470. X    prfield("Record format", Recformat(HDR2buf));
  1471. X    prfield("Block length", Blklength(HDR2buf));
  1472. X    prfield("Record length", Reclength(HDR2buf));
  1473. X    prfield("System software", Syssoftw(HDR2buf));
  1474. X    prfield("Buffer offset", Bufoffset(HDR2buf));
  1475. X    prunused(Sp4(HDR2buf));
  1476. X}
  1477. X
  1478. Xprhead(addr, size)
  1479. X    char *addr;
  1480. X{
  1481. X    printf("\nInformation from the %s-label\n", fld2str(addr, size));
  1482. X}
  1483. X
  1484. Xprfield(nm, addr, size)
  1485. X    char *nm, *addr;
  1486. X{
  1487. X    char *str = fld2str(addr, size);
  1488. X
  1489. X    printf("%s: ", nm);
  1490. X    prf_s("%s\n", *str == EOS ? sps2txt(size) : str);
  1491. X}
  1492. X
  1493. Xprunused(addr, size)
  1494. X    char *addr;
  1495. X{
  1496. X    char *str = fld2str(addr, size);
  1497. X
  1498. X    if (strlen(str) > 0)
  1499. X        prf_s("Unused field: %s\n", str);
  1500. X}
  1501. X
  1502. Xmissing(idf)
  1503. X    char *idf;
  1504. X{
  1505. X    print_loc();
  1506. X    printf("%s-label missing\n", idf);
  1507. X}
  1508. X
  1509. Xint
  1510. Xchk_int(nm, val)
  1511. X    char *nm;
  1512. X{
  1513. X        if (val < 0)    {
  1514. X            print_loc();
  1515. X            printf("Garbage in %s field\n", nm);
  1516. X            return FALSE;
  1517. X        }
  1518. X        else
  1519. X            return TRUE;
  1520. X}
  1521. X
  1522. Xprint_loc()    {
  1523. X
  1524. X    if (ok_loc || pflag)
  1525. X        return;
  1526. X    if (ok_fln)
  1527. X        prf_s("\n*** At file `%s':\n", filename);
  1528. X    else
  1529. X        printf("\n*** At file number %d:\n", filseqnum);
  1530. X    ok_loc = TRUE;
  1531. X}
  1532. + END-OF-FILE ansir.c
  1533. chmod 'u=rw,g=r,o=r' \a\n\s\i\r\.\c
  1534. set `sum \a\n\s\i\r\.\c`
  1535. sum=$1
  1536. case $sum in
  1537. 51802)    :;;
  1538. *)    echo 'Bad sum in '\a\n\s\i\r\.\c >&2
  1539. esac
  1540. echo Extracting \a\n\s\i\w\.\c
  1541. sed 's/^X//' > \a\n\s\i\w\.\c << '+ END-OF-FILE '\a\n\s\i\w\.\c
  1542. X/*    This file is part of the magtape handling package MAG.
  1543. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  1544. X*/
  1545. X
  1546. X/*
  1547. X * Name: ansiw, write ANSI standard labelled tape
  1548. X * Version: 820314
  1549. X */
  1550. X
  1551. X#define    MSGUSE    "Usage: ansiw [-cfhlmignpv] [ file ... ]"
  1552. X
  1553. X#include    "aux.h"
  1554. X#include    "sys.h"
  1555. X#include    "tp.h"
  1556. X#include    "tploc.h"        /* to get SYSCODE */
  1557. X#include    "ansi.h"
  1558. X
  1559. X#define    MAXBLK    2048
  1560. X#define    MINBLK    18
  1561. X#define    FILLER    '^'
  1562. X
  1563. Xchar iflag = FALSE, gflag = FALSE, pflag = FALSE, vflag = FALSE;
  1564. Xchar block[MAXBLK];
  1565. X
  1566. Xstruct DD    {
  1567. X    long size;
  1568. X    long lrecl;
  1569. X    char ascii95;
  1570. X    char example;
  1571. X} dd;
  1572. Xstruct DD empty_dd =    {0L, 0L, TRUE, EOS};
  1573. X
  1574. X#define    divis(m, n)    ((n)!=0&&(m)%(n)==0)
  1575. X
  1576. Xmain(argc, argv)
  1577. X    int argc;
  1578. X    char *argv[];
  1579. X{
  1580. X    argc--, argv++;
  1581. X    while (argc > 0 && argv[0][0] == '-')    {
  1582. X        char *pp = argv[0];
  1583. X        
  1584. X        while (*++pp)    {
  1585. X            switch (*pp)    {
  1586. X            /* insert cases to handle the standard options */
  1587. X#include    "options.h"
  1588. X            /* special options */
  1589. X            case 'g':
  1590. X                gflag = TRUE;
  1591. X                break;
  1592. X            case 'i':
  1593. X                iflag = TRUE;
  1594. X                break;
  1595. X            case 'n':
  1596. X                unit = TP_IMAG;
  1597. X                nmdns = "/dev/null";
  1598. X                break;
  1599. X            case 'p':
  1600. X                pflag = TRUE;
  1601. X                break;
  1602. X            case 'v':
  1603. X                vflag = TRUE;
  1604. X                break;
  1605. X            }
  1606. X        }
  1607. X        argc--, argv++;
  1608. X    }
  1609. X    tf = tpopen(unit, nmdns, "w");
  1610. X
  1611. X    check_args(argc, argv);
  1612. X
  1613. X    lblVOL1(iflag || vflag ? ASK_SUG : ASK_NO);
  1614. X
  1615. X    while (argc-- != 0)    {
  1616. X        strcpy(filename, argv[filseqnum]);
  1617. X        filseqnum++;
  1618. X        blkcount = 0;
  1619. X
  1620. X        opendd(filename);
  1621. X        if (file == NULL)    {
  1622. X            printf(">>> File %s ", filename);
  1623. X            errors("has suddenly disappeared!!!");
  1624. X        }
  1625. X        lblHDR1(iflag ? ASK_SUG : ASK_NO);
  1626. X        lblHDR2(iflag ? ASK_SUG : ASK_NO);
  1627. X        wrt_tm();
  1628. X        copy();
  1629. X        wrt_tm();
  1630. X        lblEOF1();
  1631. X        lblEOF2();
  1632. X        wrt_tm();
  1633. X    }
  1634. X
  1635. X    wrt_tm();
  1636. X    tpclose(tf);
  1637. X    exit(0);
  1638. X
  1639. XLbad:
  1640. X    errors(MSGUSE);
  1641. X    exit(1);
  1642. X}
  1643. X
  1644. Xcheck_args(c, v)
  1645. X    char *v[];
  1646. X{
  1647. X    char ok = TRUE;
  1648. X
  1649. X    while (c-- > 0)    {
  1650. X        int f = open(*v, 0);
  1651. X
  1652. X        if (f < 0)    {
  1653. X            printf("Cannot open %s\n", *v);
  1654. X            ok = FALSE;
  1655. X        }
  1656. X        else    VOID(close(f));
  1657. X        v++;
  1658. X    }
  1659. X    if (!ok)
  1660. X        errors("Stop");
  1661. X}
  1662. X
  1663. Xwrt_tm()
  1664. X{    /* writes a tapemark */
  1665. X    tpwrite(tf, "", 0);
  1666. X}
  1667. X
  1668. Xlong
  1669. Xtab(p)
  1670. X    long p;        /* the position in which a tab from p would land */
  1671. X{
  1672. X    return (p/8+1)*8;
  1673. X}
  1674. X
  1675. X/*
  1676. X * `opendd' opens the file `fn' and determines its `dd' parameters
  1677. X */
  1678. X
  1679. Xopendd(fn)
  1680. X    char *fn;
  1681. X{
  1682. X    int ch;
  1683. X    long lr;
  1684. X
  1685. X    dd = empty_dd;
  1686. X    if ((file = fopen(fn, "r")) == NULL)
  1687. X        return;
  1688. X
  1689. X    lr = 0L;
  1690. X    while ((ch = getc(file)) != EOF)    {
  1691. X        dd.size++;
  1692. X        if (ch == NL)    {
  1693. X            if (lr > dd.lrecl)
  1694. X                dd.lrecl = lr;
  1695. X            lr = 0L;
  1696. X        }
  1697. X        else
  1698. X        if (ch == TAB)    {
  1699. X            lr = tab(lr);
  1700. X        }
  1701. X        else    {
  1702. X            lr++;
  1703. X            if (!is_ascii95(ch))    {
  1704. X                dd.ascii95 = FALSE;
  1705. X                dd.example = ch;
  1706. X            }
  1707. X        }
  1708. X    }
  1709. X    if (lr > dd.lrecl)
  1710. X        dd.lrecl = lr;
  1711. X
  1712. X    VOID(fclose(file));
  1713. X    file = fopen(fn, "r");
  1714. X}
  1715. X
  1716. X/*
  1717. X * the writing of labels
  1718. X */
  1719. X
  1720. XlblVOL1(md)    {
  1721. X    char *owner = username();
  1722. X    
  1723. X    str2fld("", Whole(VOL1buf));
  1724. X    str2fld("VOL1", Labidf(VOL1buf));
  1725. X
  1726. X    enq_fld("\
  1727. X    The `volume serial number' is the six-character identification\n\
  1728. X    number of the tape itself, as it should appear on the sticker on\n\
  1729. X    the reel. When in doubt, use the default %s.\n",
  1730. X        md, "222222", Volidf(VOL1buf));
  1731. X    enq_fld("\
  1732. X    The `volume accessibility symbol' is a single character,\n\
  1733. X    recorded on the tape, which indicates how publicly accessible the\n\
  1734. X    whole tape is. It is not well defined, but a single space is\n\
  1735. X    generally taken to mean: accessible by anybody.\n",
  1736. X        md, " ", Volacc(VOL1buf));
  1737. X    enq_fld("\
  1738. X    The `owner identification' is the name of the owner, as recorded\n\
  1739. X    on the tape. On some systems it interacts with the file\n\
  1740. X    accessibility symbol. When in doubt, specify a short string of\n\
  1741. X    letters.\n",
  1742. X        owner == NULL ? ASK_YES : md, owner, Ownidf(VOL1buf));
  1743. X    str2fld("1", Labvers(VOL1buf));
  1744. X
  1745. X    tpwrite(tf, Whole(VOL1buf));
  1746. X}
  1747. X
  1748. XlblHDR1(md)    {
  1749. X    char *today = sysdate();
  1750. X    
  1751. X    str2fld("", Whole(HDR1buf));
  1752. X    str2fld("HDR1", Labidf(HDR1buf));
  1753. X    enq_fld("\
  1754. X    The `file identifier' is the name of the file, as recorded on\n\
  1755. X    the tape.  When in doubt, specify a six-letter mnemonic name.\n",
  1756. X        md, filename, Fileidf(HDR1buf));
  1757. X
  1758. X    fld2fld(Volidf(VOL1buf), Filesetidf(HDR1buf));
  1759. X    int2fld(filsecnum, Filsecnum(HDR1buf));
  1760. X    int2fld(filseqnum, Filseqnum(HDR1buf));
  1761. X    enq_num("\
  1762. X    The `generation number' is a counter that some operating systems\n\
  1763. X    attach to a file and that is increased each time the file is\n\
  1764. X    updated. Use 1.\n",
  1765. X        gflag ? md : ASK_NO, 1, Gennum(HDR1buf));
  1766. X    enq_num("\
  1767. X    The `generation version number' tells how often an attempt to\n\
  1768. X    write the file to tape has failed. Use 0.\n",
  1769. X        gflag ? md : ASK_NO, 0, Genversnum(HDR1buf));
  1770. X    dat2fld(today, Creatdate(HDR1buf));
  1771. X    enq_dat("\
  1772. X    The `expiration date' is the date, recorded on the tape, after\n\
  1773. X    which the file may be overwritten. The format is 2 digits for\n\
  1774. X    the year, followed by 3 digits for the day in the year, e.g.,\n\
  1775. X    86365 for the last day of 1986.  When in doubt, use today's date,\n\
  1776. X    %s, to make the receiver's life easier.\n",
  1777. X        md, today, Expirdate(HDR1buf));
  1778. X    enq_fld("\
  1779. X    The `file accessibility symbol' is a single character, recorded\n\
  1780. X    on the tape, which indicates how publicly accessible the file is.\n\
  1781. X    It is not well defined, but a single space is generally taken to\n\
  1782. X    mean: accessible by anybody.\n",
  1783. X        md, " ", Fileacc(HDR1buf));
  1784. X    int2fld(blkcount, Blkcount(HDR1buf));
  1785. X
  1786. X    str2fld(SYSCODE /* from tploc.h */, Syscode(HDR1buf));
  1787. X
  1788. X    tpwrite(tf, Whole(HDR1buf));
  1789. X}
  1790. X
  1791. XlblHDR2(md)    {
  1792. X
  1793. X    str2fld("", Whole(HDR2buf));
  1794. X    str2fld("HDR2", Labidf(HDR2buf));
  1795. X
  1796. X    if (!iflag)    {
  1797. X        str2fld("F", Whole(rectype));
  1798. X        blklength = 1920;
  1799. X        reclength = 80;
  1800. X    }
  1801. X
  1802. X    if (!dd.ascii95)    {
  1803. X        printf("`%s' contains non-ASCII95 characters, e.g., %s\n",
  1804. X            filename, char2str(dd.example));
  1805. X        printf("Perhaps the file code should have been BINARY");
  1806. X        str2fld("U", Whole(rectype));
  1807. X    }
  1808. X
  1809. X    if (dd.lrecl > MAXBLK)    {
  1810. X        printf("`%s' has a record length > %d\n", filename, MAXBLK);
  1811. X        printf("Only U-format is possible\n");
  1812. X        str2fld("U", Whole(rectype));
  1813. X        recformat = format_of_type('U');
  1814. X    }
  1815. X    else
  1816. X    inmood (!dd.ascii95 ? ASK_SUG : md)    {
  1817. X        char *rct = enq_str("\
  1818. X    The `record format' tells how lines from the disk file should be\n\
  1819. X    converted to records to be packed into blocks to be recorded on\n\
  1820. X    tape. Although many formats exist, only two are any good in\n\
  1821. X    Information Interchange:\n\
  1822. X    F (Fixed): spaces are added at the end of the line until its\n\
  1823. X        length is `record length', and `block length'/`record length'\n\
  1824. X        of these records form a block;\n\
  1825. X    U (Undefined): `block length' characters are stored in a block.\n\
  1826. X    Unless the disk file contains non-ASCII characters, use F.\n",
  1827. X            mood, fld2str(Whole(rectype)));
  1828. X
  1829. X        iferr (    strlen(rct) != 1
  1830. X        ||    (recformat = format_of_type(rct[0])) == NULL
  1831. X        ||    recformat->cpblk == NULL
  1832. X        )    {
  1833. X            printf(
  1834. X            "Only F- and U-formats are allowed for portability\n"
  1835. X            );
  1836. X            enderr;
  1837. X        }
  1838. X
  1839. X        str2fld(rct, Whole(rectype));
  1840. X        endmood;
  1841. X    }
  1842. X
  1843. X    (*recformat->checkpar)(md);
  1844. X
  1845. X    fld2fld(Whole(rectype), Recformat(HDR2buf));
  1846. X    int2fld(blklength, Blklength(HDR2buf));
  1847. X    int2fld(reclength, Reclength(HDR2buf));
  1848. X    int2fld(bufoffset, Bufoffset(HDR2buf));
  1849. X
  1850. X    tpwrite(tf, Whole(HDR2buf));
  1851. X}
  1852. X
  1853. XcheckF(md)    {
  1854. X    int lr;
  1855. X
  1856. X    inmood (md)    {
  1857. X        getBlklength(mood);
  1858. X        iferr (blklength < reclength)    {
  1859. X            printf("Block length < phys. record length (=%ld)\n",
  1860. X                dd.lrecl);
  1861. X            enderr;
  1862. X        }
  1863. X        endmood;
  1864. X    }
  1865. X
  1866. X    lr = dd.lrecl;
  1867. X    while (!divis(blklength, lr))
  1868. X        lr++;
  1869. X    if (lr < 80 && divis(blklength, 80))
  1870. X        lr = 80;
  1871. X    reclength = lr;
  1872. X
  1873. X    inmood (md)    {
  1874. X        reclength = enq_int("\
  1875. X    The `record length' is the number of characters into which each\n\
  1876. X    line (record) is stretched before it is written to tape. It must\n\
  1877. X    divide the block length. Unless the receiver has been very\n\
  1878. X    specific, use %s.\n",
  1879. X            mood, reclength, blklength);
  1880. X        iferr (reclength == 0 || !divis(blklength, reclength))    {
  1881. X            printf(
  1882. X        "The block length is not a multiple of the record length\n"
  1883. X            );
  1884. X            enderr;
  1885. X        }
  1886. X        iferr (reclength < dd.lrecl)    {
  1887. X            printf("Record length < phys. record length (=%ld)\n",
  1888. X                dd.lrecl);
  1889. X            enderr;
  1890. X        }
  1891. X        endmood;
  1892. X    }
  1893. X}
  1894. X
  1895. XcheckU(md)    {
  1896. X    getBlklength(md);
  1897. X    reclength = blklength;
  1898. X}
  1899. X
  1900. XgetBlklength(md)    {
  1901. X    inmood (md)    {
  1902. X        blklength =
  1903. X            enq_int("\
  1904. X    The `block length' is the number of characters in each physical\n\
  1905. X    block written to tape. Unless the receiver has specified\n\
  1906. X    something else, use %s.\n",
  1907. X                mood,
  1908. X                (rectype[0] == 'F' && dd.lrecl > 1920) ?
  1909. X                    MAXBLK : !iflag ? 1920 : blklength,
  1910. X                MAXBLK);
  1911. X        iferr (blklength < MINBLK)    {
  1912. X            printf("The minimum block length is %d\n", MINBLK);
  1913. X            enderr;
  1914. X        }
  1915. X        endmood;
  1916. X    }
  1917. X}
  1918. X
  1919. X
  1920. XlblEOF1()    {
  1921. X    str2fld("EOF1", Labidf(HDR1buf));
  1922. X    int2fld(blkcount, Blkcount(HDR1buf));
  1923. X    tpwrite(tf, Whole(HDR1buf));
  1924. X}
  1925. X
  1926. XlblEOF2()    {
  1927. X    str2fld("EOF2", Labidf(HDR2buf));
  1928. X    tpwrite(tf, Whole(HDR2buf));
  1929. X}
  1930. X
  1931. X/*
  1932. X * the copying of the file
  1933. X */
  1934. X
  1935. Xcopy()    {
  1936. X    int size;
  1937. X
  1938. X    blkcount = reccount = 0;
  1939. X
  1940. X    while ((size = (*recformat->cpblk)()) > 0)    {
  1941. X        while (size < MINBLK)
  1942. X            block[size++] = FILLER;
  1943. X        tpwrite(tf, block, size);
  1944. X        ++blkcount;
  1945. X    }
  1946. X    VOID(fclose(file));
  1947. X    file = NULL;
  1948. X    if (pflag)    {
  1949. X        printf("File name: %s\n", filename);
  1950. X        printf("Record format: %s\n", rectype);
  1951. X        printf("Block length: %d; number of blocks: %d\n",
  1952. X            blklength, blkcount);
  1953. X        printf("Record length: %d; number of records: %d\n\n",
  1954. X            reclength, reccount);
  1955. X    }
  1956. X}
  1957. X
  1958. Xint
  1959. XcpFblk()    {
  1960. X    int ch;
  1961. X    int count = 0;
  1962. X
  1963. X    while (count < blklength && (ch = getc(file)) != EOF)    {
  1964. X        int rpos = 0;
  1965. X        reccount++;
  1966. X        while (ch != NL && ch != EOF)    {
  1967. X            if (ch == TAB)    {
  1968. X                int nrpos = (int)tab((long)rpos);
  1969. X                while (rpos < nrpos)    {
  1970. X                    block[count++] = SP, rpos++;
  1971. X                }
  1972. X            }
  1973. X            else    {
  1974. X                block[count++] = ch, rpos++;
  1975. X            }
  1976. X            ch = getc(file);
  1977. X        }
  1978. X        while (rpos < reclength)    {
  1979. X            block[count++] = SP, rpos++;
  1980. X        }
  1981. X    }
  1982. X    return count;
  1983. X}
  1984. X
  1985. Xint
  1986. XcpUblk()    {
  1987. X    int ch;
  1988. X    int count = 0;
  1989. X
  1990. X    while (count < blklength && (ch = getc(file)) != EOF)    {
  1991. X        block[count++] = ch;
  1992. X    }
  1993. X    if (count > 0)
  1994. X        reccount++;
  1995. X    return count;
  1996. X}
  1997. X
  1998. Xstruct format formats[] =    {
  1999. X    {'F', checkF, cpFblk},
  2000. X    {'U', checkU, cpUblk},
  2001. X    {'D', NULL, NULL},
  2002. X    {'S', NULL, NULL},
  2003. X    {EOS, NULL, NULL}
  2004. X};
  2005. X
  2006. X/*
  2007. X * the setting of fields
  2008. X */
  2009. X
  2010. Xint2fld(n, addr, size)
  2011. X    char *addr;
  2012. X{
  2013. X    addr += size;
  2014. X    while (size-- > 0)    {
  2015. X        *--addr = n % 10 + '0';
  2016. X        n = n / 10;
  2017. X    }
  2018. X}
  2019. X
  2020. Xdat2fld(str, addr, size)
  2021. X    char *str, *addr;
  2022. X{
  2023. X    str2fld("", addr, size);
  2024. X    str2fld(str, Date(addr));
  2025. X}
  2026. X
  2027. Xenq_fld(expl, md, def, addr, size)
  2028. X    char *expl, *def, *addr;
  2029. X{
  2030. X    char *ans;
  2031. X    
  2032. X    inmood (md)    {
  2033. X        ans = enq_str(expl, mood, def);
  2034. X        iferr (strlen(ans) == 0)    {
  2035. X            printf("No empty answer allowed\n");
  2036. X            enderr;
  2037. X        }
  2038. X        iferr (strlen(ans) > size)    {
  2039. X            printf("The %s is too long\n", expl2str(expl));
  2040. X            printf("The maximum length is %d character%s\n",
  2041. X                english(size));
  2042. X            enderr;
  2043. X        }
  2044. X        iferr (!isascstr(ans))    {
  2045. X            printf("The %s `%s' contains non-printing chars\n",
  2046. X                expl2str(expl), ans);
  2047. X            enderr;
  2048. X        }
  2049. X        endmood;
  2050. X    }
  2051. X    str2fld(ans, addr, size);
  2052. X}
  2053. X
  2054. Xenq_dat(expl, md, def, addr, size)
  2055. X    char *expl, *def, *addr;
  2056. X{
  2057. X    dat2fld(def, addr, size);
  2058. X    inmood (md)    {
  2059. X        int yd;
  2060. X        
  2061. X        enq_fld(expl, mood, def, Date(addr));
  2062. X        iferr (fld2int(Yr(addr)) < 0)    {
  2063. X            printf("Year must be numeric\n");
  2064. X            enderr;
  2065. X        }
  2066. X        yd = fld2int(Yd(addr));
  2067. X        iferr (yd < 1 || yd > 366)    {
  2068. X            printf("Date in year must be between 1 and 366\n");
  2069. X            enderr;
  2070. X        }
  2071. X        endmood;
  2072. X    }
  2073. X}
  2074. X
  2075. Xenq_num(expl, md, def, addr, size)
  2076. X    char *expl, *addr;
  2077. X{
  2078. X    int2fld(enq_int(expl, md, def, tento(size)-1), addr, size);
  2079. X}
  2080. X
  2081. Xint
  2082. Xtento(n)    {
  2083. X    int res = 1;
  2084. X
  2085. X    while (n--)
  2086. X        res *= 10;
  2087. X    return res;
  2088. X}
  2089. X
  2090. Xprint_loc()    {
  2091. X    /* dummy in ansiw.c; useful in ansir.c */
  2092. X    return;
  2093. X}
  2094. + END-OF-FILE ansiw.c
  2095. chmod 'u=rw,g=r,o=r' \a\n\s\i\w\.\c
  2096. set `sum \a\n\s\i\w\.\c`
  2097. sum=$1
  2098. case $sum in
  2099. 35905)    :;;
  2100. *)    echo 'Bad sum in '\a\n\s\i\w\.\c >&2
  2101. esac
  2102. echo Extracting \c\p\t\p\.\c
  2103. sed 's/^X//' > \c\p\t\p\.\c << '+ END-OF-FILE '\c\p\t\p\.\c
  2104. X/*    This file is part of the magtape handling package MAG.
  2105. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  2106. X*/
  2107. X
  2108. X/*
  2109. X * Name: cptp, copy tape
  2110. X * Version: 820314
  2111. X *
  2112. X * `Cptp' converts between real tapes and tape images on disk.
  2113. X */
  2114. X
  2115. X#define    MSGUSE    "Usage is: cptp [-cfhlmx] [of=file | if=file]"
  2116. X
  2117. X#include    <stdio.h>
  2118. X#include    "aux.h"
  2119. X#include    "tp.h"
  2120. X
  2121. Xint unit = 0;
  2122. Xchar *nmdns = TP_DENN;
  2123. Xchar *rx = "r";
  2124. XTPFILE *from, *to;
  2125. Xchar *filename;
  2126. Xint size;
  2127. Xchar buff[TP_MAXB];
  2128. X
  2129. Xmain(argc, argv)
  2130. X    char *argv[];
  2131. X{
  2132. X    char *arg;
  2133. X
  2134. X    argc--, argv++;
  2135. X    while (argc > 0 && argv[0][0] == '-')    {
  2136. X        char *pp = argv[0];
  2137. X        
  2138. X        while (*++pp)    {
  2139. X            switch (*pp)    {
  2140. X            /* insert cases to handle the standard options */
  2141. X#include    "options.h"
  2142. X            /* special options */
  2143. X            case 'x':
  2144. X                rx = "rx";
  2145. X                break;
  2146. X            }
  2147. X        }
  2148. X        argc--, argv++;
  2149. X    }
  2150. X    if (argc != 1)
  2151. X        goto Lbad;
  2152. X    arg = argv[0];
  2153. X    if (arg[0] == '\0' || arg[1] != 'f' || arg[2] != '=')
  2154. X        goto Lbad;
  2155. X    filename = &arg[3];
  2156. X    
  2157. X    tperrout(stdout);
  2158. X    switch (arg[0])    {
  2159. X    case 'o':
  2160. X        if (open(filename, 0) > 0)
  2161. X            error("Output file already exists");
  2162. X        from = tpopen(unit, nmdns, rx);
  2163. X        to = tpopen(TP_IMAG, filename, "w");
  2164. X        break;
  2165. X    case 'i':
  2166. X        from = tpopen(TP_IMAG, filename, "r");
  2167. X        to = tpopen(unit, nmdns, "w");
  2168. X        break;
  2169. X    default:
  2170. X        goto Lbad;
  2171. X    }
  2172. X
  2173. X    while ((size = tpread(from, buff, TP_MAXB)) >= 0)    {
  2174. X        if (size == TP_MAXB)
  2175. X            printf("Block too long; information may be lost\n");
  2176. X        tpwrite(to, buff, size);
  2177. X    }
  2178. X    tpclose(from);
  2179. X    tpclose(to);
  2180. X    exit(0);
  2181. X
  2182. XLbad:
  2183. X    error(MSGUSE);
  2184. X    exit(1);
  2185. X}
  2186. X
  2187. Xerror(str)
  2188. X    char *str;
  2189. X{
  2190. X    fprintf(stderr, "%s\n", str);
  2191. X    exit(1);
  2192. X}
  2193. + END-OF-FILE cptp.c
  2194. chmod 'u=rw,g=r,o=r' \c\p\t\p\.\c
  2195. set `sum \c\p\t\p\.\c`
  2196. sum=$1
  2197. case $sum in
  2198. 62900)    :;;
  2199. *)    echo 'Bad sum in '\c\p\t\p\.\c >&2
  2200. esac
  2201. echo Extracting \r\a\w\t\p\.\c
  2202. sed 's/^X//' > \r\a\w\t\p\.\c << '+ END-OF-FILE '\r\a\w\t\p\.\c
  2203. X/*    This file is part of the magtape handling package MAG.
  2204. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  2205. X*/
  2206. X
  2207. X/*
  2208. X * Name: rawtp, read raw tape
  2209. X * Version: 820314
  2210. X *
  2211. X   Selected portions are read from tape and written to files.
  2212. X
  2213. X*/
  2214. X
  2215. X#define    MSGUSE    "Usage is: rawtp [-cfhlmx] XX [ param ... ]"
  2216. X
  2217. X#include    <stdio.h>
  2218. X#include    "aux.h"
  2219. X#include    "tp.h"
  2220. X
  2221. X#define    TRUE    1
  2222. X#define    FALSE    0
  2223. X#define    EOS    '\0'
  2224. X
  2225. X#define    EOB    0    /* End Of Block */
  2226. X#define    EOX    -1    /* End Of File (to avoid confusion with EOF) */
  2227. X#define    EOT    -2    /* End Of Tape */
  2228. X#define    AT_EOB    (ilength <= EOB)
  2229. X#define    AT_EOX    (ilength <= EOX)
  2230. X#define    AT_EOT    (ilength <= EOT)
  2231. X
  2232. Xchar name [128];
  2233. Xchar *eoname = &name[0];
  2234. XFILE *ofile = NULL;
  2235. X
  2236. XTPFILE *tape;
  2237. Xint unit = 0;
  2238. Xchar *nmdns = TP_DENN;
  2239. Xchar *rx = "r";
  2240. Xchar buff[TP_MAXB];
  2241. X
  2242. Xchar *strins();
  2243. X
  2244. Xmain(argc, argv)
  2245. X    char **argv;
  2246. X{
  2247. X    extern int ilength;
  2248. X
  2249. X    argc--, argv++;
  2250. X    while (argc > 0 && argv[0][0] == '-')    {
  2251. X        char *pp = argv[0];
  2252. X        
  2253. X        while (*++pp)    {
  2254. X            switch (*pp)    {
  2255. X            /* insert cases to handle the standard options */
  2256. X#include    "options.h"
  2257. X            /* special options */
  2258. X            case 'x':
  2259. X                rx = "rx";
  2260. X                break;
  2261. X            }
  2262. X        }
  2263. X        argc--, argv++;
  2264. X    }
  2265. X    if (argc < 1)
  2266. X        goto Lbad;
  2267. X    if (**argv == '+' || **argv == '-')
  2268. X        goto Lbad;
  2269. X    set_name(argv);
  2270. X    argc--, argv++;
  2271. X
  2272. X    ilength = EOT;    /* fake empty tape to test parameters */
  2273. X    params(argc, argv);
  2274. X
  2275. X    tperrout(stdout);
  2276. X    tape = tpopen(unit, nmdns, rx);
  2277. X    ilength = EOB;    /* and now for keeps */
  2278. X    skipIRG();
  2279. X    params(argc, argv);
  2280. X    tpclose(tape);
  2281. X    exit(0);
  2282. X
  2283. XLbad:
  2284. X    error(MSGUSE, "");
  2285. X    exit(1);
  2286. X}
  2287. X
  2288. Xset_name(argv)
  2289. X    char **argv;
  2290. X{
  2291. X    register char *pt;
  2292. X
  2293. X    eoname = strins(eoname, *argv);
  2294. X    eoname = strins(eoname, "01aaa01");
  2295. X    *eoname = EOS;
  2296. X    for (pt = eoname; pt > name; pt--)
  2297. X        if (pt[-1] == '/') break;
  2298. X    if (eoname - pt > 14)
  2299. X        error("%s: file name too long", name);
  2300. X}
  2301. X
  2302. Xparams(argc, argv)
  2303. X    char **argv;
  2304. X{
  2305. X    VOID(strins(eoname-7, "01"));
  2306. X    if (!argc)
  2307. X        param("+1x");
  2308. X    else
  2309. X        while (argc--)    {
  2310. X            param(*argv++);
  2311. X            incr(eoname-6);
  2312. X        }
  2313. X}
  2314. X
  2315. Xchar *ppar;    /* parameter being processed */
  2316. X
  2317. Xparam(arg)
  2318. X    char *arg;
  2319. X{
  2320. X    register int repl;
  2321. X
  2322. X    ppar = arg;
  2323. X    repl = getxrepl(ppar);
  2324. X    if (repl == 0) repl--;
  2325. X    VOID(strins(eoname-5, "aaa"));
  2326. X    while (repl-- && instr())
  2327. X        incr(eoname-3);
  2328. X}
  2329. X
  2330. Xint moved;
  2331. X
  2332. Xint
  2333. Xinstr()    {
  2334. X    char *p = ppar;
  2335. X
  2336. X    moved = FALSE;
  2337. X    VOID(strins(eoname-2, "01"));
  2338. X    while (simp_instr(&p))
  2339. X        incr(eoname-1);
  2340. X    return moved;
  2341. X}
  2342. X
  2343. Xint copy = FALSE;
  2344. X
  2345. Xint
  2346. Xsimp_instr(pp)
  2347. X    char **pp;
  2348. X{
  2349. X    register int cnt;
  2350. X
  2351. X    switch (**pp)    {
  2352. X    case EOS:
  2353. X    case 'x':
  2354. X        return FALSE;
  2355. X    case '+':
  2356. X        copy = TRUE;
  2357. X        break;
  2358. X    case '-':
  2359. X        copy = FALSE;
  2360. X        break;
  2361. X    default:
  2362. X        error("%s: bad parameter", ppar);
  2363. X    }
  2364. X    (*pp)++;
  2365. X    cnt = getint(pp);
  2366. X    while (cnt-- && copyfile())    {
  2367. X    }
  2368. X    if (**pp == '.')
  2369. X        (*pp)++;
  2370. X    cnt = getint(pp);
  2371. X    while (cnt-- && copyblock())    {
  2372. X    }
  2373. X    if (**pp == '.')
  2374. X        (*pp)++;
  2375. X    cnt = getint(pp);
  2376. X    while (cnt-- && copychar())    {
  2377. X    }
  2378. X    if (copy)
  2379. X        dropfile();
  2380. X    return TRUE;
  2381. X}
  2382. X
  2383. Xint ilength;
  2384. X
  2385. X/* ilength contains the number of characters the tape is ahead of the user;
  2386. X * or it is EOX or EOT
  2387. X */
  2388. Xchar *iptr;
  2389. X
  2390. Xint
  2391. Xcopyfile()    {
  2392. X
  2393. X    if (AT_EOT)
  2394. X        return FALSE;
  2395. X    while (copyblock())    {}
  2396. X    skipTM();
  2397. X    return TRUE;
  2398. X}
  2399. X
  2400. Xint
  2401. Xcopyblock()    {
  2402. X
  2403. X    if (AT_EOX)
  2404. X        return FALSE;
  2405. X    if (!copy)
  2406. X        ilength = EOB;
  2407. X    else
  2408. X        while (copychar())    {}
  2409. X    skipIRG();
  2410. X    return TRUE;
  2411. X}
  2412. X
  2413. Xint
  2414. Xcopychar()    {
  2415. X
  2416. X    if (AT_EOB)
  2417. X        return FALSE;
  2418. X    outchar(*iptr);
  2419. X    iptr++;
  2420. X    ilength--;
  2421. X    return TRUE;
  2422. X}
  2423. X
  2424. Xoutchar(c)    {
  2425. X
  2426. X    if (!copy)
  2427. X        return;
  2428. X    if (ofile == NULL)    {
  2429. X        getfile();
  2430. X        moved = TRUE;
  2431. X    }
  2432. X    putc(c, ofile);
  2433. X}
  2434. X
  2435. X/* physical tape movers */
  2436. X
  2437. XskipTM()    {
  2438. X
  2439. X    if (AT_EOT)
  2440. X        return;
  2441. X    ilength = EOB;
  2442. X    skipIRG();
  2443. X}
  2444. X
  2445. XskipIRG()    {
  2446. X    int size;
  2447. X
  2448. X    if (AT_EOX)
  2449. X        return;
  2450. X    size = tpread(tape, buff, TP_MAXB);
  2451. X    ilength = size < 0 ? EOT : size == 0 ? EOX : size;
  2452. X    iptr = buff;
  2453. X    if (!AT_EOT)
  2454. X        moved = TRUE;
  2455. X}
  2456. X
  2457. X/* output file registration */
  2458. X
  2459. Xgetfile()    {
  2460. X
  2461. X    if ((ofile = fopen(name, "w")) == NULL)
  2462. X        error("%s: cannot create", name);
  2463. X}
  2464. X
  2465. Xdropfile()    {
  2466. X
  2467. X    if (ofile != NULL)    {
  2468. X        VOID(fclose(ofile));
  2469. X        ofile = NULL;
  2470. X    }
  2471. X}
  2472. X
  2473. X/* service routines */
  2474. X
  2475. Xchar *
  2476. Xstrins(s1, s2)
  2477. X    char *s1, *s2;
  2478. X{
  2479. X    while (*s2 != EOS)
  2480. X        *s1++ = *s2++;
  2481. X    return s1;
  2482. X}
  2483. X
  2484. Xint
  2485. Xgetint(pp)
  2486. X    char **pp;
  2487. X{
  2488. X    register int val, res = 0;
  2489. X
  2490. X    for (;;)    {
  2491. X        val = **pp - '0';
  2492. X        if (val < 0 || val > 9)
  2493. X            return res;
  2494. X        (*pp)++;
  2495. X        res = res*10 + val;
  2496. X    }
  2497. X}
  2498. X
  2499. Xincr(p)
  2500. X    char *p;
  2501. X{
  2502. X    (*p)++;
  2503. X    if (*p == '9' + 1)    {
  2504. X        *p = '0';
  2505. X        incr(p-1);
  2506. X    }
  2507. X    else
  2508. X    if (*p == 'z' + 1)    {
  2509. X        *p = 'a';
  2510. X        incr(p-1);
  2511. X    }
  2512. X}
  2513. X
  2514. Xint
  2515. Xgetxrepl(p)
  2516. X    char *p;
  2517. X{
  2518. X    register int r;
  2519. X
  2520. X    while (*p != 'x')
  2521. X        if (!*p++)
  2522. X            return 1;
  2523. X    p++;
  2524. X    r = getint(&p);
  2525. X    if (*p)
  2526. X        error("%s: bad replicator", p);
  2527. X    return r;
  2528. X}
  2529. X
  2530. Xerror(p1, p2)
  2531. X    char *p1, *p2;
  2532. X{
  2533. X    printf(p1, p2);
  2534. X    printf("\n");
  2535. X    exit(1);
  2536. X}
  2537. + END-OF-FILE rawtp.c
  2538. chmod 'u=rw,g=r,o=r' \r\a\w\t\p\.\c
  2539. set `sum \r\a\w\t\p\.\c`
  2540. sum=$1
  2541. case $sum in
  2542. 43915)    :;;
  2543. *)    echo 'Bad sum in '\r\a\w\t\p\.\c >&2
  2544. esac
  2545. echo Extracting \s\u\r\v\e\y\.\c
  2546. sed 's/^X//' > \s\u\r\v\e\y\.\c << '+ END-OF-FILE '\s\u\r\v\e\y\.\c
  2547. X/*    This file is part of the magtape handling package MAG.
  2548. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  2549. X*/
  2550. X
  2551. X/*
  2552. X * Name: survey, survey contents of magtape
  2553. X * Version: 820314
  2554. X */
  2555. X
  2556. X#define    MSGUSE    "Usage is: survey [-cfhlmpx]\n"
  2557. X
  2558. X#include    <stdio.h>
  2559. X#include    "aux.h"
  2560. X#include    "tp.h"
  2561. X#include    "etoa.h"
  2562. X
  2563. X#define    WIDTH    64
  2564. X
  2565. Xint unit = 0;
  2566. Xchar *nmdns = TP_DENN;
  2567. Xchar *rx = "r";
  2568. XTPFILE *tf;
  2569. Xchar buff[TP_MAXB];
  2570. Xint size;
  2571. X
  2572. Xchar pflag = 0;
  2573. X
  2574. Xmain(argc, argv)
  2575. X    char *argv[];
  2576. X{
  2577. X    argc--, argv++;
  2578. X    while (argc > 0 && argv[0][0] == '-')    {
  2579. X        char *pp = argv[0];
  2580. X        
  2581. X        while (*++pp)    {
  2582. X            switch (*pp)    {
  2583. X            /* insert cases to handle the standard options */
  2584. X#include    "options.h"
  2585. X            /* special options */
  2586. X            case 'p':
  2587. X                pflag = 1;
  2588. X                break;
  2589. X            case 'x':
  2590. X                rx = "rx";
  2591. X                break;
  2592. X            }
  2593. X        }
  2594. X        argc--, argv++;
  2595. X    }
  2596. X
  2597. X    if (argc != 0)
  2598. X        goto Lbad;
  2599. X
  2600. X    tf = tpopen(unit, nmdns, rx);
  2601. X
  2602. X    while ((size = tpread(tf, buff, TP_MAXB)) >= 0)    {
  2603. X        printf("%6d", size);
  2604. X        if (pflag)
  2605. X            expose();
  2606. X        printf("\n");
  2607. X    }
  2608. X    exit(0);
  2609. X
  2610. XLbad:
  2611. X    fprintf(stderr, MSGUSE);
  2612. X    exit(1);
  2613. X}
  2614. X
  2615. Xint
  2616. Xhex(ch)    {
  2617. X    return "0123456789ABCDEF"[ch&017];
  2618. X}
  2619. X
  2620. Xint
  2621. Xprintable(ch)
  2622. X    char ch;
  2623. X{
  2624. X    int i = char2int(ch);            /* 8 bits only */
  2625. X    
  2626. X    return is_ascii95(i) ? i : '?';
  2627. X}
  2628. X
  2629. Xexpose()    {
  2630. X    if (size == 0)
  2631. X        printf("\t* * * TAPE MARK * * *\n");
  2632. X    else    {
  2633. X        int i;
  2634. X        printf("\t");
  2635. X        for (i = 0; i < WIDTH && i < size; i++)    {
  2636. X            printf("%c", printable(buff[i]));
  2637. X        }
  2638. X        printf("\n  EBC:\t");
  2639. X        for (i = 0; i < WIDTH && i < size; i++)    {
  2640. X            printf("%c", printable(ebc2asc(buff[i])));
  2641. X        }
  2642. X        printf("\n  HEX:\t");
  2643. X        for (i = 0; i < WIDTH/2 && i < size; i++)    {
  2644. X            char ch = buff[i];
  2645. X            printf("%c%c", hex(ch>>4), hex(ch));
  2646. X        }
  2647. X        printf("\n");
  2648. X    }
  2649. X}
  2650. X
  2651. + END-OF-FILE survey.c
  2652. chmod 'u=rw,g=r,o=r' \s\u\r\v\e\y\.\c
  2653. set `sum \s\u\r\v\e\y\.\c`
  2654. sum=$1
  2655. case $sum in
  2656. 22800)    :;;
  2657. *)    echo 'Bad sum in '\s\u\r\v\e\y\.\c >&2
  2658. esac
  2659. echo Extracting \N\O\S\s\p\l\i\t\.\c
  2660. sed 's/^X//' > \N\O\S\s\p\l\i\t\.\c << '+ END-OF-FILE '\N\O\S\s\p\l\i\t\.\c
  2661. X/*    This file is part of the magtape handling package MAG.
  2662. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  2663. X*/
  2664. X
  2665. X/*
  2666. X * Name: NOSsplit, split Cyber system tape (data format is SI)
  2667. X * Version: 820314
  2668. X */
  2669. X
  2670. X#define    MSGUSE    "Usage is: NOSsplit [-cfhlm[s N]] [out_name]\n"
  2671. X
  2672. X#include    <stdio.h>
  2673. X#include    "aux.h"
  2674. X#include    "tp.h"
  2675. Xextern char *sprintf();
  2676. X
  2677. X#define    MINSIZE    6            /* smaller is a noise block */
  2678. X#define    BSIZE    3840            /* blocksize binary files */
  2679. X#define    CSIZE    960            /* blocksize coded files */
  2680. X#define    SIZE    3840            /* maximum blocksize */
  2681. X#define    EORM    "\055\023\035\052\027\054\000"
  2682. X#define    EORL    7
  2683. X#define    EOS    '\0'
  2684. X
  2685. X#define    lastblock(n)    ((n)!=BSIZE && (n)!=CSIZE)
  2686. X#define    cybln(n)    ((n)*8/60*10)
  2687. X
  2688. Xint fnumber = 0;
  2689. Xchar *ofil = "x";
  2690. Xchar fname[128];
  2691. XFILE *outf;
  2692. X
  2693. Xchar buff[SIZE];
  2694. Xint size;    /* number of chars in `buff' */
  2695. Xint bpos;    /* number of bits consumed by `get6bits' */
  2696. Xint bstat;
  2697. X
  2698. Xint unit = 0;
  2699. Xint skipf = 0;        /* number of logical records to skip (forwards) */
  2700. Xchar *nmdns = TP_DENN;
  2701. XTPFILE *tf;
  2702. X
  2703. Xchar *progname;
  2704. X
  2705. Xmain(argc, argv)
  2706. X    char *argv[];
  2707. X{
  2708. X    progname = argv[0];
  2709. X    argc--, argv++;
  2710. X
  2711. X    while (argc > 0 && argv[0][0] == '-')    {
  2712. X        char *pp = argv[0];
  2713. X        
  2714. X        while (*++pp)    {
  2715. X            switch (*pp)    {
  2716. X            /* insert cases to handle the standard options */
  2717. X#include    "options.h"
  2718. X            /* special options */
  2719. X            case 's':
  2720. X                if (argc < 2)
  2721. X                    goto Lbad;
  2722. X                if (!is_digit(argv[1][0]))
  2723. X                    goto Lbad;
  2724. X                skipf = atoi(argv[1]);
  2725. X                argc--, argv++;
  2726. X                break;
  2727. X            }
  2728. X        }
  2729. X        argc--, argv++;
  2730. X    }
  2731. X
  2732. X    if (argc == 1)    {
  2733. X        ofil = argv[0];
  2734. X        argc--, argv++;
  2735. X    }
  2736. X
  2737. X    if (argc != 0)
  2738. X        goto Lbad;
  2739. X
  2740. X    read_tape();
  2741. X    exit(0);
  2742. X
  2743. XLbad:
  2744. X    fprintf(stderr, MSGUSE);
  2745. X    exit(1);
  2746. X
  2747. X}
  2748. X
  2749. Xread_tape()    {
  2750. X    int i;
  2751. X    int bcnt;
  2752. X
  2753. X    tperrout(stdout);
  2754. X    tf = tpopen(unit, nmdns, "rx");
  2755. X
  2756. X    fillbuff();
  2757. X    if (size == 80 && strncmp(buff, "VOL1", 4) == 0)    {
  2758. X        printf("This is a labelled tape\n");
  2759. X        printf("For label information use `ansir -pn'\n");
  2760. X        while (size > 0)
  2761. X            fillbuff();
  2762. X        if (size == 0)
  2763. X            fillbuff();
  2764. X    }
  2765. X    else    printf("This is a non-labelled tape\n");
  2766. X
  2767. X    for (i = 0; i < skipf; i++)    {
  2768. X        if (size <= 0)    {
  2769. X            printf("%d record%s missing\n", english(skipf-i));
  2770. X            exit(1);
  2771. X        }
  2772. X        fnumber++;
  2773. X        while (!lastblock(size))
  2774. X            fillbuff();
  2775. X        fillbuff();
  2776. X    }
  2777. X
  2778. X    if (skipf > 0)
  2779. X        printf("%d logical record%s skipped\n", english(skipf));
  2780. X
  2781. X    while (size > 0)    {
  2782. X        newcreat(fnumber++);
  2783. X
  2784. X        bcnt = 1;
  2785. X        while (putbuff(cybln(size)), !lastblock(size))    {
  2786. X            fillbuff();
  2787. X            bcnt++;
  2788. X        }
  2789. X
  2790. X        proc_eor(bcnt);
  2791. X
  2792. X        VOID(fclose(outf));
  2793. X        outf = NULL;
  2794. X        fillbuff();
  2795. X    }
  2796. X
  2797. X    printf("%d record%s retrieved\n", english(fnumber-skipf));
  2798. X}
  2799. X
  2800. Xnewcreat(fn)    {
  2801. X    int i;
  2802. X
  2803. X    for (i=0; ofil[i] != EOS; i++)
  2804. X        fname[i] = ofil[i];
  2805. X    VOID(sprintf(&fname[i], "%04d", fn));
  2806. X    outf = fopen(fname, "w");
  2807. X    if (outf == NULL)    {
  2808. X        printf("%s: cannot create `%s'\n", progname, fname);
  2809. X        exit(1);
  2810. X    }
  2811. X}
  2812. X
  2813. Xfillbuff()    {
  2814. X
  2815. X    do    size = tpread(tf, buff, sizeof buff);
  2816. X    while (size > 0 && size < MINSIZE /* noise record */);
  2817. X    bpos = bstat = 0;
  2818. X}
  2819. X
  2820. Xputbuff(n)
  2821. X    int n;                /* number of 6bit chars */
  2822. X{
  2823. X
  2824. X    while (n-- > 0)
  2825. X        putc(get6bits(), outf);
  2826. X}
  2827. X
  2828. X
  2829. Xproc_eor(bcnt)    {
  2830. X    char eor[EORL];
  2831. X    int i;
  2832. X
  2833. X    for (i = 0; i < EORL; i++)
  2834. X        eor[i] = get6bits();
  2835. X
  2836. X    printf("%s: ", fname);
  2837. X    printf("%d block%s, ", english(bcnt));
  2838. X    if (strncmp(eor, EORM, EORL) != 0)
  2839. X        printf("no proper EOR\n");
  2840. X    else
  2841. X        printf("EOR%2o\n", get6bits());
  2842. X}
  2843. X
  2844. X#define    left(c,n)    (((c)&((077<<(8-(n)))&0377))>>(8-(n)))
  2845. X#define    right(c,n)    (((c)&((077>>(6-(n)))&0377))<<(6-(n)))
  2846. X/*
  2847. X * These forms are constructed through program transformations; the
  2848. X * author cannot, by any stretch of imagination, guess why they work.
  2849. X */
  2850. X
  2851. Xint
  2852. Xget6bits()    {
  2853. X    int res = 0;
  2854. X
  2855. X    switch (bstat++)    {
  2856. X    case 0:    res = left(buff[bpos+0], 6);
  2857. X        break;
  2858. X    case 1:    res = right(buff[bpos+0], 2) + left(buff[bpos+1], 4);
  2859. X        break;
  2860. X    case 2:    res = right(buff[bpos+1], 4) + left(buff[bpos+2], 2);
  2861. X        break;
  2862. X    case 3:    res = right(buff[bpos+2], 6);
  2863. X        break;
  2864. X    }
  2865. X    if (bstat == 4)    {
  2866. X        bpos += 3;
  2867. X        bstat = 0;
  2868. X    }
  2869. X    return res;
  2870. X}
  2871. + END-OF-FILE NOSsplit.c
  2872. chmod 'u=rw,g=r,o=r' \N\O\S\s\p\l\i\t\.\c
  2873. set `sum \N\O\S\s\p\l\i\t\.\c`
  2874. sum=$1
  2875. case $sum in
  2876. 08337)    :;;
  2877. *)    echo 'Bad sum in '\N\O\S\s\p\l\i\t\.\c >&2
  2878. esac
  2879. echo Extracting \N\O\S\t\r\.\c
  2880. sed 's/^X//' > \N\O\S\t\r\.\c << '+ END-OF-FILE '\N\O\S\t\r\.\c
  2881. X/*    This file is part of the magtape handling package MAG.
  2882. X    Written by Dick Grune, Vrije Universiteit, Amsterdam.
  2883. X*/
  2884. X
  2885. X/*
  2886. X * Program: NOStr, translates a Cyber 6-bit file into a UNIX ASCII file.
  2887. X * Version: 820314
  2888. X */
  2889. X
  2890. X#define    MSGUSE    "Usage is: NOStr -C [file]"
  2891. X
  2892. X#include    <stdio.h>
  2893. X#include    "aux.h"
  2894. X
  2895. X#define    MAXERR    40
  2896. X#define    EOS    '\0'
  2897. X
  2898. XFILE    *ifile;        /* input file */
  2899. Xchar    *iname;        /* input name */
  2900. X
  2901. Xint displZ(), asciiZ(), binary();
  2902. Xstruct conv    {
  2903. X    char *name;
  2904. X    int (*command)();
  2905. X    char *expl;
  2906. X} conv[] =    {
  2907. X    {"d", displZ, "Z-type records in DISPLAY code"},
  2908. X    {"a", asciiZ, "Z-type records in ASCII95"},
  2909. X    {"b", binary, "binary, = ASCII256"}
  2910. X};
  2911. X
  2912. Xmain(argc, argv)
  2913. X    char *argv[];
  2914. X{
  2915. X    int p;
  2916. X
  2917. X    if (argc < 2 || argc > 3 || argv[1][0] != '-' || strlen(argv[1]) != 2)
  2918. X        goto Bad_usage;
  2919. X    if (argc == 2 || strcmp(argv[2], "-") == 0)    {
  2920. X        iname = "standard input";
  2921. X        ifile = stdin;
  2922. X    }
  2923. X    else    {
  2924. X        iname = argv[2];
  2925. X        ifile = fopen(iname, "r");
  2926. X        if (ifile == NULL)    {
  2927. X            fprintf(stderr, "%s: cannot open %s\n",
  2928. X                    argv[0], iname);
  2929. X            exit(1);
  2930. X        }
  2931. X    }
  2932. X    for (p = 0; p < n_items(conv); p++)
  2933. X        if (strcmp(&argv[1][1], conv[p].name) == 0)    {
  2934. X            (*conv[p].command)();
  2935. X            exit(0);
  2936. X        }
  2937. XBad_usage:
  2938. X    fprintf(stderr, MSGUSE);
  2939. X    fprintf(stderr,
  2940. X        "\nwhere the conversion code C is one of the following:\n");
  2941. X    for (p = 0; p < n_items(conv); p++)
  2942. X        fprintf(stderr, "`%s': %s\n", conv[p].name, conv[p].expl);
  2943. X    exit(1);
  2944. X}
  2945. X
  2946. X#define    NL    '\n'
  2947. X#define    TEN    10
  2948. X
  2949. Xint cwrd[TEN];
  2950. Xlong lcnt = 1;
  2951. Xlong icnt = 0;
  2952. X
  2953. XdisplZ()    {    /* recognize Z-type records in DISPLAY code */
  2954. X    int nch;
  2955. X    int zpend = 0;
  2956. X
  2957. X    while (nch = get_cwrd(TEN), nch != 0)    {
  2958. X        int i;
  2959. X
  2960. X        if (nch != TEN)
  2961. X            VOID(complain("short word", 0));
  2962. X        while (nch != 0 && cwrd[nch-1] == 0)
  2963. X            nch--;
  2964. X        if (zpend && nch > 0)
  2965. X            putdispl(0);    /* zero pending */
  2966. X        for (i = 0; i < nch; i++)
  2967. X            putdispl(cwrd[i]);
  2968. X        if (nch < TEN-1)
  2969. X            putascii(NL);
  2970. X        zpend = nch == TEN-1;
  2971. X    }
  2972. X}
  2973. X
  2974. X#define    FIVE    5
  2975. X
  2976. XasciiZ()    {    /* recognize Z-type records in ASCII95 */
  2977. X    int nch;
  2978. X
  2979. X    while (nch = get_cwrd(FIVE), nch != 0)    {
  2980. X        int i;
  2981. X
  2982. X        if (nch != FIVE)
  2983. X            VOID(complain("short word", 0));
  2984. X        while (nch != 0 && cwrd[nch-1] == 0)
  2985. X            nch--;
  2986. X        for (i = 0; i < nch; i++)
  2987. X            putascii(cwrd[i]);
  2988. X        if (nch < FIVE)
  2989. X            putascii(NL);
  2990. X    }
  2991. X}
  2992. X
  2993. Xbinary()    {    /* binary, also ASCII256 */
  2994. X    int ch;
  2995. X
  2996. X    while (ch = get12bits(), ch != EOF)
  2997. X        putascii(ch);
  2998. X}
  2999. X
  3000. Xint
  3001. Xget_cwrd(n)    {    /* gather n (60/n)-bit bytes into a Cyber word */
  3002. X    int i;
  3003. X
  3004. X    for (i = 0; i < n; i++)    {
  3005. X        cwrd[i] = n == TEN ? get6bits() :
  3006. X                n == FIVE ? get12bits() : (abort(), 0);
  3007. X        if (cwrd[i] == EOF)
  3008. X            break;
  3009. X    }
  3010. X    return i;
  3011. X}
  3012. X
  3013. Xint
  3014. Xget12bits()    {
  3015. X    int ch1, ch2;
  3016. X    static errcnt = 0;
  3017. X
  3018. X    ch1 = get6bits();
  3019. X    if (ch1 == EOF)
  3020. X        return EOF;
  3021. X    ch2 = get6bits();
  3022. X    if (ch2 == EOF)
  3023. X        ch2 = 0;
  3024. X
  3025. X    ch1 = (ch1 << 6) + ch2;
  3026. X    if (ch1 >> 8)
  3027. X        errcnt = complain("composed char wider than 8 bits", errcnt);
  3028. X    return ch1;
  3029. X}
  3030. X
  3031. Xint
  3032. Xget6bits()    {
  3033. X    int ch = getc(ifile);
  3034. X    static errcnt = 0;
  3035. X
  3036. X    if (ch == EOF)
  3037. X        return EOF;
  3038. X    icnt++;
  3039. X    if (ch >> 6)
  3040. X        errcnt = complain("input char wider than 6 bits", errcnt);
  3041. X    return ch;
  3042. X}
  3043. X
  3044. Xputdispl(ch)    {    /* convert display to ASCII */
  3045. X    putchar(
  3046. X    "%ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-*/()$= ,.#[]:\"_!&'?<>@\\^;"
  3047. X        [ch]);
  3048. X}
  3049. X
  3050. Xputascii(ch)
  3051. X    char ch;
  3052. X{
  3053. X    putchar(ch);
  3054. X    if (ch == NL)
  3055. X        lcnt++;
  3056. X}
  3057. X
  3058. Xint
  3059. Xcomplain(s, n)
  3060. X    char *s;
  3061. X{
  3062. X    if (n > MAXERR)
  3063. X        return n;
  3064. X    fprintf(stderr,
  3065. X        "At input char %ld, at output line %ld, %s in file `%s'\n",
  3066. X                icnt, lcnt, s, iname);
  3067. X    if (n == MAXERR)
  3068. X        fprintf(stderr,
  3069. X    "After %d complaints, further complaints of this type suppressed\n",
  3070. X            MAXERR);
  3071. X    return n+1;
  3072. X}
  3073. + END-OF-FILE NOStr.c
  3074. chmod 'u=rw,g=r,o=r' \N\O\S\t\r\.\c
  3075. set `sum \N\O\S\t\r\.\c`
  3076. sum=$1
  3077. case $sum in
  3078. 55112)    :;;
  3079. *)    echo 'Bad sum in '\N\O\S\t\r\.\c >&2
  3080. esac
  3081. exit 0
  3082.  
  3083. -- 
  3084.  
  3085. Rich $alz            "Anger is an energy"
  3086. Cronus Project, BBN Labs    rsalz@bbn.com
  3087. Moderator, comp.sources.unix    sources@uunet.uu.net
  3088.