home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / apple2 / 52 < prev    next >
Encoding:
Internet Message Format  |  1991-05-02  |  38.9 KB

  1. From: jac@yoko.rutgers.edu (Jonathan A. Chandross)
  2. Newsgroups: comp.sources.apple2
  3. Subject: v001SRC034:  Nulib - Archive Library Tools (Unix) 03/10
  4. Message-ID: <May.1.18.09.53.1991.23482@yoko.rutgers.edu>
  5. Date: 1 May 91 22:09:55 GMT
  6. Approved: jac@paul.rutgers.edu
  7.  
  8.  
  9. Submitted-by: Andy McFadden (fadden@cory.berkeley.edu)
  10. Posting-number: Volume 1, Source:34
  11. Archive-name: archive/unix/nulib/part03.10
  12. Architecture: UNIX
  13. Version-number: 3.03
  14.  
  15.  
  16. =nuread.c
  17. -/*
  18. - * nuread.c - read NuFX archives (header info only) into structures
  19. - *
  20. - * NuLib v3.0  February 1991  Freeware (distribute, don't sell)
  21. - * By Andy McFadden (fadden@cory.berkeley.edu)
  22. - */
  23. -#ifdef APW
  24. -segment "NuMain"
  25. -#endif
  26. -
  27. -#include "nudefs.h"
  28. -#include <stdio.h>
  29. -#include <fcntl.h>
  30. -#include <errno.h>
  31. -
  32. -#ifdef MSDOS     /* For file IO */
  33. -# include <stdlib.h>        /* errno, among others */
  34. -# include <string.h>
  35. -# include <io.h>
  36. -# include <sys/types.h>
  37. -# include <sys/stat.h>
  38. -#endif
  39. -
  40. -#ifdef CRC_TAB
  41. -# include "crc.h"     /* fast CRC lookup */
  42. -#endif
  43. -#include "nuread.h"
  44. -#include "nupak.h"  /* uses PAKBUFSIZ */
  45. -#include "nuetc.h"
  46. -
  47. -#define UNKNOWN_FN    "<No Filename>"
  48. -
  49. -/* quick proc to save x00 bytes of static storage */
  50. -void OtherArc(str1, str2)
  51. -{
  52. -    fprintf(stderr, "File may be %s; try \"%s\".\n", str1, str2);
  53. -}
  54. -
  55. -/* swap two bytes if HiLo is TRUE */
  56. -void HiSwap(ptr, a, b)
  57. -onebyt *ptr;
  58. -register onebyt a, b;
  59. -{
  60. -    register onebyt tmp;
  61. -
  62. -    if (HiLo) {
  63. -    tmp = ptr[a], ptr[a] = ptr[b], ptr[b] = tmp;
  64. -    }
  65. -}
  66. -
  67. -
  68. -/* copy bytes from buffer to buffer, reversing byte order if necessary */
  69. -void BCopy(srcptr, destptr, num, order)
  70. -onebyt *srcptr, *destptr;
  71. -register int num;
  72. -BOOLEAN order;    /* true if byte ordering is important */
  73. -{
  74. -    register int i = num--;
  75. -
  76. -    if (order && HiLo) {
  77. -    while (i--) {  /* copy & reverse */
  78. -        *(destptr+i) = *(srcptr + num - i);  /* dest+3 = src + 3 - 3 .. */
  79. -    }
  80. -    } else if (order) {
  81. -    while (i--) {  /* copy only */
  82. -        *(destptr+i) = *(srcptr + i);
  83. -    }
  84. -    } else {
  85. -    while (i--) {  /* byte ordering not important; just copy */
  86. -        *(destptr+i) = *(srcptr+i);
  87. -    }
  88. -    }
  89. -}
  90. -
  91. -
  92. -/*
  93. - * Calculate CRC on a region
  94. - *
  95. - * A CRC is the result of a mathematical operation based on the
  96. - * coefficients of a polynomial when multiplied by X^16 then divided by
  97. - * the generator polynomial (X^16 + X^12 + X^5 + 1) using modulo two
  98. - * arithmetic.
  99. - *
  100. - * This routine is a slightly modified verison of one found in:
  101. - * _Advanced Programming Techniques for the Apple //gs Toolbox_
  102. - * By Morgan Davis and Dan Gookin (Compute! Publications, Inc.)
  103. - * It can either calculate the CRC bit-by-bit or use a table.
  104. - * [ one of the few //gs books worth the money    +atm ]
  105. - */
  106. -twobyt CalcCRC(seed, ptr, count)
  107. -twobyt seed;  /* initial value for CRC */
  108. -onebyt *ptr;  /* pointer to start of data buffer */
  109. -int count;    /* number of bytes to scan through - note 64K max */
  110. -{
  111. -    register int x;
  112. -    register twobyt CRC = seed;
  113. -
  114. -    do {
  115. -#ifndef CRC_TAB
  116. -    CRC ^= *ptr++ << 8;          /* XOR hi-byte of CRC w/data     */
  117. -    for (x = 8; x; --x)          /* Then, for 8 bit shifts...     */
  118. -        if (CRC & 0x8000)          /* Test hi order bit of CRC     */
  119. -        CRC = CRC << 1 ^ 0x1021;  /* if set, shift & XOR w/$1021 */
  120. -        else
  121. -        CRC <<= 1;          /* Else, just shift left once. */
  122. -#else
  123. -    CRC = updcrc(*ptr++, CRC);      /* look up new value in table  */
  124. -#endif
  125. -    } while (--count);
  126. -    return (CRC);
  127. -}
  128. -
  129. -
  130. -/*
  131. - * Test an archive's integrity.
  132. - *
  133. - * Reads the entire file, and checks CRCs for certain things.
  134. - */
  135. -void NuTest(filename, options)
  136. -char *filename;
  137. -char *options;
  138. -{
  139. -    ListHdr *archive;
  140. -    onebyt *copybuf;  /* buffer for reading record */
  141. -    int partial;   /* size for partial read */
  142. -    unsigned int rec;
  143. -    RNode *RNodePtr;
  144. -    MHblock *MHptr;
  145. -    TNode *TNodePtr;
  146. -    long hdr_size, total_size, thread_size;
  147. -    int srcfd;    /* file descriptor */
  148. -    int thread;
  149. -    twobyt CRC, RecordCRC;
  150. -    long CRCsum = 0L;    /* sum of CRCs for all records */
  151. -    BOOLEAN check_thread_crc;    /* TRUE if we want to check a give thread */
  152. -    static char *procName = "NuTest";
  153. -
  154. -    printf("Testing %s", filename);
  155. -    if (verbose) printf("\n");
  156. -    else       { printf("...");  fflush(stdout); }
  157. -
  158. -    archive = NuRead(filename);  /* this catches most errors... */
  159. -
  160. -    MHptr = archive->MHptr;
  161. -    RNodePtr = archive->RNodePtr;
  162. -    copybuf = (onebyt *) Malloc(PAKBUFSIZ);
  163. -    if ((srcfd = open(filename, O_RDONLY | O_BINARY)) < 0)
  164. -    Fatal("Unable to close archive", procName);
  165. -    if (lseek(srcfd, (long) MHsize, S_ABS) < 0)  /* seek past master block */
  166. -    Fatal("Bad seek (MH)", procName);
  167. -
  168. -    for (rec = 0; rec < (unsigned int) MHptr->total_records; rec++) {
  169. -    if (verbose) printf("Record %d (%s): ", rec, RNodePtr->filename);
  170. -    hdr_size = (long) RNodePtr->RHptr->attrib_count;
  171. -    hdr_size += (long) RNodePtr->filename_length;
  172. -    total_size = hdr_size;
  173. -    TNodePtr = RNodePtr->TNodePtr;
  174. -    for (thread=0; thread < (int)RNodePtr->RHptr->total_threads; thread++){
  175. -        if (TNodePtr == (TNode *) NULL) {
  176. -        fprintf(stderr, "Internal error: Bad thread structure\n");
  177. -        Quit(-1);
  178. -        }
  179. -        hdr_size += (long) THsize;
  180. -        total_size += (long) THsize;
  181. -        total_size += TNodePtr->THptr->comp_thread_eof;
  182. -        TNodePtr = TNodePtr->TNext;
  183. -    }
  184. -    if (verbose) {
  185. -        printf("total record size = %ld (%d threads)\n", total_size,
  186. -        (int) RNodePtr->RHptr->total_threads);
  187. -        fflush(stdout);
  188. -    }
  189. -
  190. -    /* read record header */
  191. -    RecordCRC = 0;
  192. -    while (hdr_size != 0L) {
  193. -        if (hdr_size > (long) PAKBUFSIZ) {
  194. -        partial = (unsigned int) PAKBUFSIZ;
  195. -        hdr_size -= (long) PAKBUFSIZ;
  196. -        } else {
  197. -        partial = (unsigned int) hdr_size;
  198. -        hdr_size = 0L;
  199. -        }
  200. -
  201. -        if (read(srcfd, copybuf, partial) != partial) {
  202. -        fprintf(stderr, ">>> Read error");
  203. -        if (verbose) fprintf(stderr, "\n");
  204. -        else fprintf(stderr,
  205. -            " - record %d (%s)\n",  rec, RNodePtr->filename);
  206. -        fprintf(stderr, "Operation aborted.\n");
  207. -        Quit(-1);
  208. -        }
  209. -        if (verbose) RecordCRC = CalcCRC(CRC, (onebyt *) copybuf, partial);
  210. -    }
  211. -
  212. -    TNodePtr = RNodePtr->TNodePtr;
  213. -    for (thread=0; thread < (int)RNodePtr->RHptr->total_threads; thread++){
  214. -        if (lseek(srcfd, (long) TNodePtr->fileposn, S_ABS) < 0)
  215. -        Fatal("whoops!", procName);
  216. -        thread_size = TNodePtr->THptr->comp_thread_eof;
  217. -
  218. -        /* decide whether or not to check thread CRCs */
  219. -        check_thread_crc = FALSE;
  220. -        if (RNodePtr->RHptr->version_number >= 2)    /* valid CRCs */
  221. -        if (TNodePtr->THptr->thread_class == 2)    /* data_thread */
  222. -            check_thread_crc = TRUE;
  223. -        if (RNodePtr->RHptr->version_number == 3)    /* CRC of uncom data */
  224. -        if (TNodePtr->THptr->thread_format != 0x0000)
  225. -            check_thread_crc = FALSE;        /* can't check comp */
  226. -
  227. -        if (check_thread_crc) CRC = 0xffff;
  228. -        while (thread_size != 0L) {
  229. -        if (thread_size > (long) PAKBUFSIZ) {
  230. -            partial = (unsigned int) PAKBUFSIZ;
  231. -            thread_size -= (long) PAKBUFSIZ;
  232. -        } else {
  233. -            partial = (unsigned int) thread_size;
  234. -            thread_size = 0L;
  235. -        }
  236. -
  237. -        if (read(srcfd, copybuf, partial) != partial) {
  238. -            fprintf(stderr, ">>> Read error in thread");
  239. -            if (verbose) fprintf(stderr, " %d\n", thread);
  240. -            else fprintf(stderr, " - record %d (%s), thread %d\n",
  241. -                rec, RNodePtr->filename, thread);
  242. -            fprintf(stderr, "Operation aborted.\n");
  243. -            Quit(-1);
  244. -        }
  245. -
  246. -        if (verbose)
  247. -            RecordCRC = CalcCRC(RecordCRC, (onebyt *)copybuf, partial);
  248. -
  249. -        /* calculate CRC for thread, and compare with thread_crc */
  250. -        if (check_thread_crc)
  251. -            CRC = CalcCRC(CRC, (onebyt *) copybuf, partial);
  252. -#ifdef DEBUG
  253. -        printf(
  254. -"At posn %ld: rec %d/thread %d (%ld bytes)  CalcCRC = 0x%.4x (0x%.4x)\n",
  255. -TNodePtr->fileposn, rec, thread, thread_size, CRC, TNodePtr->THptr->thread_crc
  256. -        );
  257. -#endif
  258. -        }
  259. -
  260. -        /* check and see if CRC matches */
  261. -        if (check_thread_crc) {
  262. -        if (CRC != TNodePtr->THptr->thread_crc) {
  263. -            fprintf(stderr, ">>> Bad CRC for thread %d",
  264. -            thread);
  265. -            if (verbose) fprintf(stderr, "\n");
  266. -            else fprintf(stderr, " in record %d\n", rec);
  267. -        } else {
  268. -            if (verbose) printf("--- CRC matched for thread %d\n",
  269. -            thread);
  270. -        }
  271. -        }
  272. -        TNodePtr = TNodePtr->TNext;
  273. -    }
  274. -
  275. -    if (verbose) {
  276. -        printf("--- CRC for entire record was $%.4x\n", RecordCRC);
  277. -        CRCsum += RecordCRC;
  278. -    }
  279. -    RNodePtr = RNodePtr->RNext;
  280. -    }
  281. -    if (close(srcfd) < 0)
  282. -    Fatal("Unable to close archive", procName);
  283. -
  284. -    free(copybuf);
  285. -    if (verbose) printf("Sum of CRCs = $%.8lx\n", CRCsum);
  286. -    printf("done.\n");
  287. -}
  288. -
  289. -
  290. -/*
  291. - * Read thread header data, and skip data fields
  292. - */
  293. -
  294. -static TNode *ReadThreads(fd, RHptr, RNodePtr, CRC_ptr)
  295. -int fd;
  296. -RHblock *RHptr;
  297. -RNode *RNodePtr;
  298. -twobyt *CRC_ptr;  /* CRC seed; result is returned thru this */
  299. -{
  300. -    int i;
  301. -    unsigned int size;
  302. -    BOOLEAN first;
  303. -    TNode *TNodePtr, *THeadPtr = (TNode *) NULL;
  304. -    THblock *THptr;
  305. -    char filebuf[THsize];
  306. -    twobyt CRC = *CRC_ptr;
  307. -    static char *procName = "ReadThreads";
  308. -
  309. -    RNodePtr->unc_len = 0L;
  310. -    RNodePtr->comp_len = 0L;
  311. -    first = TRUE;
  312. -    for (i = 0; i < RHptr->total_threads; i++) {
  313. -    if (first) {  /* create first block, or... */
  314. -        TNodePtr = (TNode *) Malloc(sizeof(TNode));
  315. -        THeadPtr = TNodePtr;
  316. -        first = FALSE;
  317. -    } else {  /* create next block and go on */
  318. -        TNodePtr->TNext = (TNode *) Malloc(sizeof(TNode));
  319. -        TNodePtr = TNodePtr->TNext;
  320. -    }
  321. -    TNodePtr->TNext = (TNode *) NULL;
  322. -
  323. -    /* Create the thread header block, and read it in */
  324. -    TNodePtr->THptr = (THblock *) Malloc(sizeof(THblock));
  325. -    THptr = TNodePtr->THptr;
  326. -
  327. -    if (size = read(fd, filebuf, THsize) < THsize) {  /* should be 16 */
  328. -        printf("read size = %d, THsize = %d\n", size, THsize);
  329. -        Fatal("ReadThread (THblock)", procName);
  330. -    }
  331. -    CRC = CalcCRC(CRC, (onebyt *) filebuf, 16);  /* hdr CRC part(s) 5/5 */
  332. -
  333. -    /* copy all fields... */
  334. -    BCopy(filebuf+0, (onebyt *) &THptr->thread_class, 2, TRUE);
  335. -    BCopy(filebuf+2, (onebyt *) &THptr->thread_format, 2, TRUE);
  336. -    BCopy(filebuf+4, (onebyt *) &THptr->thread_kind, 2, TRUE);
  337. -    BCopy(filebuf+6, (onebyt *) &THptr->thread_crc, 2, TRUE);
  338. -    BCopy(filebuf+8, (onebyt *) &THptr->thread_eof, 4, TRUE);
  339. -    BCopy(filebuf+12, (onebyt *) &THptr->comp_thread_eof, 4, TRUE);
  340. -
  341. -    RNodePtr->unc_len += THptr->thread_eof;
  342. -    RNodePtr->comp_len += THptr->comp_thread_eof;
  343. -    if (THptr->comp_thread_eof > 2097152L)    /* SANITY CHECK */
  344. -        fprintf(stderr, "Sanity check: found comp_thread_eof > 2MB\n");
  345. -    }
  346. -
  347. -    /* skip the actual data */
  348. -    TNodePtr = THeadPtr;
  349. -    for (i = 0; i < RHptr->total_threads; i++) {
  350. -    THptr = TNodePtr->THptr;
  351. -    if ((TNodePtr->fileposn = lseek(fd, 0L, S_REL)) < 0)
  352. -        Fatal("Bad thread posn lseek()", procName);
  353. -
  354. -    /* pull filenames out of threads, if present */
  355. -    if (THptr->thread_class == 0x0003) {    /* filename thread */
  356. -        RNodePtr->filename = (char *) Malloc(THptr->thread_eof +1);
  357. -        if (read(fd, RNodePtr->filename, THptr->thread_eof) < 0) {
  358. -        fprintf(stderr, "Error on thread %d\n", i);
  359. -        Fatal("Unable to read filename", procName);
  360. -        }
  361. -        RNodePtr->filename[THptr->thread_eof] = '\0';
  362. -        RNodePtr->real_fn_length = THptr->thread_eof;
  363. -
  364. -        {        /* patch to fix bug in ShrinkIt v3.0.0 */
  365. -        int j, name_len = strlen(RNodePtr->filename);
  366. -
  367. -        for (j = 0; j < name_len; j++) {
  368. -            RNodePtr->filename[j] &= 0x7f;    /* clear hi bit */
  369. -        }
  370. -        }
  371. -
  372. -        if (lseek(fd, TNodePtr->fileposn, S_ABS) < 0)
  373. -        Fatal("Unable to seek back after fn", procName);
  374. -    }
  375. -    if (lseek(fd, THptr->comp_thread_eof, S_REL) < 0)
  376. -        Fatal("Bad skip-thread seek", procName);
  377. -    TNodePtr = TNodePtr->TNext;
  378. -    }
  379. -    *CRC_ptr = CRC;
  380. -    return (THeadPtr);
  381. -}
  382. -
  383. -
  384. -/*
  385. - * Read header data from a NuFX archive into memory
  386. - */
  387. -ListHdr *NuRead(filename)
  388. -char *filename;
  389. -{
  390. -    int fd;  /* archive file descriptor */
  391. -    char namebuf[MAXFILENAME];
  392. -    int rec, num;
  393. -    BOOLEAN first;
  394. -    twobyt namelen;
  395. -    twobyt CRC;
  396. -    ListHdr *ListPtr;  /* List Header struct */
  397. -    MHblock *MHptr;  /* Master Header block */
  398. -    RNode *RNodePtr;  /* Record Node */
  399. -    RHblock *RHptr;  /* Record Header block */
  400. -    onebyt filebuf[RECBUFSIZ];    /* must be > RH, MH, or atts-RH size */
  401. -    static char *procName = "NuRead";
  402. -
  403. -    ListPtr = (ListHdr *) Malloc(sizeof(ListHdr));  /* create head of list */
  404. -    ListPtr->arc_name = (char *) Malloc(strlen(filename)+1); /* archive fnam */
  405. -    strcpy(ListPtr->arc_name, filename);
  406. -    ListPtr->MHptr = (MHblock *) Malloc(sizeof(MHblock));  /* master block */
  407. -
  408. -    if ((fd = open(filename, O_RDONLY | O_BINARY)) < 0) {
  409. -    if (errno == ENOENT) {
  410. -        fprintf(stderr, "%s: can't find file '%s'\n", prgName, filename);
  411. -        Quit (-1);
  412. -    } else
  413. -        Fatal("Unable to open archive", procName);
  414. -    }
  415. -
  416. -    /* create and read the master header block */
  417. -    MHptr = ListPtr->MHptr;
  418. -    if (read(fd, filebuf, MHsize) < MHsize) {
  419. -    fprintf(stderr, "File '%s' may not be a NuFX archive\n", filename);
  420. -    Fatal("Unable to read Master Header Block", procName);
  421. -    }
  422. -
  423. -    CRC = CalcCRC(0, (onebyt *) filebuf+8, MHsize-8);  /* master header CRC */
  424. -
  425. -    /* Copy data to structs, correcting byte ordering if necessary */
  426. -    BCopy(filebuf+0, (onebyt *) MHptr->ID, 6, FALSE);
  427. -    BCopy(filebuf+6, (onebyt *) &MHptr->master_crc, 2, TRUE);
  428. -    BCopy(filebuf+8, (onebyt *) &MHptr->total_records, 4, TRUE);
  429. -    BCopy(filebuf+12, (onebyt *) &MHptr->arc_create_when, sizeof(Time), FALSE);
  430. -    BCopy(filebuf+20, (onebyt *) &MHptr->arc_mod_when, sizeof(Time), FALSE);
  431. -    BCopy(filebuf+28, (onebyt *) &MHptr->master_version, 2, TRUE);
  432. -    BCopy(filebuf+30, (onebyt *) MHptr->reserved1, 8, FALSE);
  433. -    BCopy(filebuf+38, (onebyt *) &MHptr->master_eof, 4, TRUE);  /* m_v $0001 */
  434. -    BCopy(filebuf+42, (onebyt *) MHptr->reserved2, 6, FALSE);
  435. -
  436. -    if (strncmp(MHptr->ID, MasterID, 6)) {
  437. -    fprintf(stderr, "\nFile '%s' is not a NuFX archive\n", filename);
  438. -    if ((filebuf[0] == 10) && (filebuf[1] == 71) &&
  439. -        (filebuf[2] == 76) && (filebuf[18] == 2))
  440. -#ifdef NO_BLU
  441. -        OtherArc("Binary II", "unblu");
  442. -#else
  443. -        fprintf(stderr, "File may be Binary II; try 'B' option\n");
  444. -#endif
  445. -    if ((filebuf[0] == '\037') && (filebuf[1] == '\036'))
  446. -        OtherArc("packed", "unpack");
  447. -    if ((filebuf[0] == (onebyt)'\377') && (filebuf[1] == '\037'))
  448. -        OtherArc("compacted", "uncompact");
  449. -    if ((filebuf[0] == '\037') && (filebuf[1] == (onebyt)'\235'))
  450. -        OtherArc("compressed", "uncompress");
  451. -    if ((filebuf[0] == 0x76) && (filebuf[1] == 0xff))
  452. -        OtherArc("SQueezed", "usq");
  453. -    if ((filebuf[0] == 0x04) && (filebuf[1] == 0x03) &&
  454. -        (filebuf[2] == 0x4b) && (filebuf[3] == 0x50))
  455. -        OtherArc("a ZIP archive", "UnZip");
  456. -    if (!strncmp((char *) filebuf, "ZOO", 3))    /* zoo */
  457. -        OtherArc("a ZOO archive", "zoo");
  458. -    if ((filebuf[0] == 0x1a) && (filebuf[1] == 0x08))    /* arc */
  459. -        OtherArc("an ARC archive", "arc");
  460. -    if (!strncmp((char *) filebuf, "SIT!", 4))    /* StuffIt */
  461. -        OtherArc("a StuffIt archive", "StuffIt (Macintosh)");
  462. -    if (!strncmp((char *) filebuf, "<ar>", 4))    /* system V arch */
  463. -        OtherArc("a library archive (Sys V)", "ar");
  464. -    if (!strncmp((char *) filebuf, "!<arch>", 7))
  465. -        OtherArc("a library archive", "ar");
  466. -    if (!strncmp((char *) filebuf, "#! /bin/sh", 10) ||
  467. -        !strncmp((char *) filebuf, "#!/bin/sh", 9))
  468. -        OtherArc("a shar archive", "/bin/sh");
  469. -    if (!strncmp((char *) filebuf, "GIF87a", 6))
  470. -        OtherArc("a GIF picture", "?!?");
  471. -    /* still need ZIP */
  472. -
  473. -    Quit (-1);
  474. -    }
  475. -
  476. -    if (CRC != MHptr->master_crc)
  477. -    printf("WARNING: Master Header block may be corrupted (bad CRC)\n");
  478. -
  479. -    if (MHptr->master_version > MAXMVERS)
  480. -    printf("WARNING: unknown Master Header version, trying to continue\n");
  481. -
  482. -    /* main record read loop */
  483. -    first = TRUE;
  484. -    for (rec = 0; rec < (unsigned int) MHptr->total_records; rec++) {
  485. -    if (first) {  /* allocate first, or... */
  486. -        ListPtr->RNodePtr = (RNode *) Malloc(sizeof(RNode));
  487. -        RNodePtr = ListPtr->RNodePtr;
  488. -        first = FALSE;
  489. -    } else {  /* allocate next, and go on */
  490. -        RNodePtr->RNext = (RNode *) Malloc(sizeof(RNode)); /* next Rnode */
  491. -        RNodePtr = RNodePtr->RNext;  /* move on to next record */
  492. -    }
  493. -    RNodePtr->RNext = (RNode *) NULL;
  494. -
  495. -    RNodePtr->RHptr = (RHblock *) Malloc(sizeof(RHblock)); /* alloc blk */
  496. -    /* expansion here */
  497. -    RHptr = RNodePtr->RHptr;
  498. -    if (read(fd, filebuf, RHsize) < RHsize) {  /* get known stuff */
  499. -        fprintf(stderr,"%s: error in record %d (at EOF?)\n", prgName, rec);
  500. -        Fatal("Bad RHblock read", procName);
  501. -    }
  502. -
  503. -    /* rec hdr CRC part 1/5 */
  504. -    CRC = CalcCRC(0, (onebyt *) filebuf+6, RHsize-6);
  505. -
  506. -    BCopy(filebuf+0, (onebyt *) RHptr->ID, 4, FALSE);
  507. -    BCopy(filebuf+4, (onebyt *) &RHptr->header_crc, 2, TRUE);
  508. -    BCopy(filebuf+6, (onebyt *) &RHptr->attrib_count, 2, TRUE);
  509. -    BCopy(filebuf+8, (onebyt *) &RHptr->version_number, 2, TRUE);
  510. -    BCopy(filebuf+10, (onebyt *) &RHptr->total_threads, 2, TRUE);
  511. -    BCopy(filebuf+12, (onebyt *) &RHptr->reserved1, 2, TRUE);
  512. -    BCopy(filebuf+14, (onebyt *) &RHptr->file_sys_id, 2, TRUE);
  513. -    BCopy(filebuf+16, (onebyt *) &RHptr->file_sys_info, 1, TRUE);
  514. -    BCopy(filebuf+17, (onebyt *) &RHptr->reserved2, 1, TRUE);
  515. -    BCopy(filebuf+18, (onebyt *) &RHptr->access, 4, TRUE);
  516. -    BCopy(filebuf+22, (onebyt *) &RHptr->file_type, 4, TRUE);
  517. -    BCopy(filebuf+26, (onebyt *) &RHptr->extra_type, 4, TRUE);
  518. -    BCopy(filebuf+30, (onebyt *) &RHptr->storage_type, 2, TRUE);
  519. -    BCopy(filebuf+32, (onebyt *) &RHptr->create_when, sizeof(Time), FALSE);
  520. -    BCopy(filebuf+40, (onebyt *) &RHptr->mod_when, sizeof(Time), FALSE);
  521. -    BCopy(filebuf+48, (onebyt *) &RHptr->archive_when, sizeof(Time), FALSE);
  522. -    BCopy(filebuf+56, (onebyt *) &RHptr->option_size, 2, TRUE);
  523. -    /* expansion here */
  524. -
  525. -    if (strncmp(RHptr->ID, RecordID, 4)) {
  526. -        fprintf(stderr, "%s: Found bad record ID (#%d) -- exiting\n",
  527. -                                prgName, rec);
  528. -        Quit (-1);
  529. -    }
  530. -
  531. -    /* read remaining (unknown) attributes into buffer, if any */
  532. -    num = RHptr->attrib_count - RHsize - 2;
  533. -    if (num > RECBUFSIZ) {
  534. -        fprintf(stderr, "ERROR: attrib_count > RECBUFSIZ\n");
  535. -        Quit (-1);
  536. -    }
  537. -    if (num > 0) {
  538. -        if (read(fd, filebuf, num) < num)
  539. -        Fatal("Bad xtra attr read", procName);
  540. -        CRC = CalcCRC(CRC, (onebyt *) filebuf, num);  /* hdr CRC part 2/5 */
  541. -    }
  542. -
  543. -    if (read(fd, (char *) &namelen, 2) < 2)  /* read filename len */
  544. -        Fatal("Bad namelen read", procName);
  545. -    CRC = CalcCRC(CRC, (onebyt *) &namelen, 2);  /* rec hdr CRC part 3/5 */
  546. -
  547. -    HiSwap((onebyt *) &namelen, 0, 1);
  548. -    /* read filename, and store in struct */
  549. -    if (namelen > MAXFILENAME) {
  550. -        fprintf(stderr, "ERROR: namelen > MAXFILENAME\n");
  551. -        Quit (-1);
  552. -    }
  553. -    RNodePtr->filename_length = namelen;
  554. -
  555. -    if (namelen > 0) {
  556. -        RNodePtr->real_fn_length = namelen;
  557. -        if (read(fd, namebuf, namelen) < namelen)
  558. -        Fatal("Bad namebuf read", procName);
  559. -        /* rec hdr CRC part 4/5 */
  560. -        CRC = CalcCRC(CRC, (onebyt *) namebuf, namelen); 
  561. -
  562. -        RNodePtr->filename = (char *) Malloc(namelen+1);  /* store fname */
  563. -        BCopy(namebuf, (onebyt *) RNodePtr->filename, namelen, FALSE);
  564. -        RNodePtr->filename[namelen] = '\0';
  565. -    } else {
  566. -        RNodePtr->filename = UNKNOWN_FN;
  567. -        RNodePtr->real_fn_length = strlen(UNKNOWN_FN);
  568. -    }
  569. -
  570. -    RNodePtr->TNodePtr = ReadThreads(fd, RHptr, RNodePtr, &CRC);
  571. -    /* rec hdr CRC part 5/5 calculated by ReadThreads */
  572. -
  573. -    if (CRC != RHptr->header_crc) {
  574. -        printf("WARNING: Detected a bad record header CRC\n");
  575. -        printf("         Rec %d in file '%.60s'\n",rec,RNodePtr->filename);
  576. -    }
  577. -    }
  578. -
  579. -    /* begin adding new files at  this point */
  580. -    if ((ListPtr->nextposn = lseek(fd, 0L, S_REL)) < 0)
  581. -    Fatal("Bad final lseek()", procName);
  582. -
  583. -    if (close(fd) < 0) {
  584. -    Fatal("Bad close", procName);
  585. -    }
  586. -
  587. -    if (MHptr->master_version > 0x0000) {
  588. -    if (MHptr->master_eof != ListPtr->nextposn) {
  589. -        printf("WARNING: master_eof (stored)=%ld, nextposn (actual)=%ld\n",
  590. -        MHptr->master_eof, ListPtr->nextposn);
  591. -        printf(
  592. -        "         (master_eof will be fixed if archive is changed)\n");
  593. -    }
  594. -    }
  595. -    
  596. -    return (ListPtr);
  597. -}
  598. -
  599. =nuext.c
  600. -/*
  601. - * nuext.c - operations which extract from a NuFX archive
  602. - *
  603. - * NuLib v3.0  February 1991  Freeware (distribute, don't sell)
  604. - * By Andy McFadden (fadden@cory.berkeley.edu)
  605. - */
  606. -#ifdef APW
  607. -segment "NuMain"
  608. -#endif
  609. -
  610. -#include "nudefs.h"
  611. -#include <stdio.h>
  612. -#ifdef BSD43
  613. -# include <strings.h>
  614. -#else  /* SYSV, APW, MSC */
  615. -# include <string.h>
  616. -#endif
  617. -#include <fcntl.h>
  618. -
  619. -#ifdef UNIX
  620. -# include <errno.h>
  621. -# include <time.h>
  622. -# include <sys/types.h>
  623. -# include <sys/stat.h>
  624. -#endif
  625. -#ifdef APW
  626. -# include <types.h>
  627. -# include <prodos.h>
  628. -# include <shell.h>
  629. -# include <strings.h>
  630. -#endif
  631. -#ifdef MSDOS
  632. -# include <io.h>
  633. -# include <time.h>
  634. -# include <stdlib.h>
  635. -# include <errno.h>
  636. -# include <direct.h>
  637. -# include <utime.h>
  638. -# include <sys/types.h>
  639. -# include <sys/stat.h>
  640. -#endif
  641. -
  642. -#include "nuread.h"
  643. -#include "nuext.h"
  644. -#include "nupak.h"
  645. -#include "nuetc.h"
  646. -
  647. -static BOOLEAN extall;    /* extract all files? */
  648. -static BOOLEAN print;   /* extract to screen rather than file? */
  649. -
  650. -
  651. -/*
  652. - * Get the answer to a yes/no question.
  653. - *
  654. - * Returns TRUE for yes, FALSE for no.  May return additional things in the
  655. - * future... (y/n/q)?
  656. - */
  657. -int AskYesNo()
  658. -{
  659. -    char buf[16];  /* if user answers with >16 chars, bad things happen */
  660. -    char c;
  661. -
  662. -    printf(" (y/n)? ");
  663. -    fflush(stdout);
  664. -    gets(buf);
  665. -    c = *buf;
  666. -    if ((c == 'y') || (c == 'Y'))
  667. -    return (TRUE);
  668. -    else
  669. -    return (FALSE);
  670. -}
  671. -
  672. -
  673. -/*
  674. - * Convert a filename to one legal in the present file system.
  675. - *
  676. - * Does not allocate new space; alters string in place (so original string
  677. - * will be "corrupted").  Assumes that it has been passed a filename without
  678. - * the filename separators.
  679. - */
  680. -void ConvFileName(str)
  681. -char *str;
  682. -{
  683. -    int idx = 0;
  684. -#ifdef UNIX
  685. -
  686. -    while (*str != '\0') {
  687. -    if ((*str > 127) || (*str < 0)) *str &= 0x7f;  /* clear hi bit */
  688. -    if (*str == '/') *str = '.';
  689. -    if (++idx > 255) { *str = '\0'; break; }
  690. -    str++;
  691. -    }
  692. -#else
  693. -# ifdef APW
  694. -    static char *legal =
  695. -    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.";
  696. -
  697. -    /* assumes ProDOS limits, not GS/OS */
  698. -    if ( ((*str < 'A') && (*str > 'Z'))  ||  ((*str < 'a') && (*str > 'z')) )
  699. -    *str = 'X';  /* must start with alpha char */
  700. -    while (*str != '\0') {
  701. -    if (!INDEX(legal, *str)) *str = '.';
  702. -    if (++idx > 15) { *str = '\0'; break; }
  703. -    str++;
  704. -    }
  705. -# endif /* APW */
  706. -# ifdef MSDOS
  707. -    while (*str != '\0') {
  708. -       if ((*str > 127) || (*str < 0)) *str &= 0x7f;  /* clear hi bit */
  709. -       if (*str == '/') *str = '_';
  710. -       if (*str == '\\') *str = '_';
  711. -       if (*str == '!') *str = '_';
  712. -       if (*str == ':') *str = '_';
  713. -       if (++idx > 255) { *str = '\0'; break; }
  714. -       str++;
  715. -    }
  716. -# endif /* MSDOS */
  717. -
  718. -# ifndef APW
  719. -# ifndef MSDOS
  720. -    printf("Need [other] filename converter\n");  /* +PORT+ */
  721. -# endif /* none2 */
  722. -# endif /* none1 */
  723. -#endif /*UNIX*/
  724. -}
  725. -
  726. -/*
  727. - * Set a file's attributes according to info in a record structure.
  728. - */
  729. -void SetFInfo(filename, RHptr)
  730. -char *filename;
  731. -RHblock *RHptr;
  732. -{
  733. -    static char *procName = "SetFInfo";
  734. -#ifdef UNIX
  735. -    long ltime;
  736. -    time_t timep[2];
  737. -
  738. -    ltime = ReduceTime(&RHptr->mod_when);  /* set both to mod time */
  739. -    timep[0] = ltime;  /* accessed */
  740. -    timep[1] = ltime;  /* modified */
  741. -    utime(filename, timep);
  742. -
  743. -    if ((RHptr->access == 0xe3L) || (RHptr->access == 0xc3L))  /* unlocked */
  744. -    chmod(filename, S_IREAD | S_IWRITE | 044);
  745. -    if ((RHptr->access == 0x21L) || (RHptr->access == 0x01L))  /* locked */
  746. -    chmod(filename, S_IREAD | 044);
  747. -
  748. -#else  /* UNIX */
  749. -# ifdef APW
  750. -    /*
  751. -     * Call ProDOS SET_FILE_INFO to set attributes for a file.
  752. -     * Uses the information in the record header block.
  753. -     */
  754. -    FileRec finfo;
  755. -    OpenRec oinfo;
  756. -    twobyt date, time;
  757. -    long ltime;
  758. -
  759. -    finfo.pathname = c2pstr(filename);    /* temp storage...? */
  760. -    finfo.fAccess = (twobyt) RHptr->access;
  761. -    finfo.fileType = (twobyt) RHptr->file_type;
  762. -    finfo.auxType = RHptr->extra_type;
  763. -    finfo.storageType = 0;  /* RHptr->storage_type otherwise */
  764. -    ltime = ReduceTime(&RHptr->create_when);
  765. -    date = (twobyt) ltime;  /* date is lower 16 */
  766. -    time = (twobyt) (ltime >> 16);  /* time is upper */
  767. -    finfo.createDate = date;
  768. -    finfo.createTime = time;
  769. -    ltime = ReduceTime(&RHptr->mod_when);
  770. -    date = (twobyt) ltime;  /* date is lower 16 */
  771. -    time = (twobyt) (ltime >> 16);  /* time is upper */
  772. -    finfo.modDate = date;
  773. -    finfo.modTime = time;
  774. -
  775. -    SET_FILE_INFO( &finfo );
  776. -    ToolErrChk();
  777. -# endif /* APW */
  778. -# ifdef MSDOS
  779. -    long ltime;
  780. -    time_t timep[2];
  781. -
  782. -    ltime = ReduceTime(&RHptr->mod_when);
  783. -    timep[0] = ltime;  /* accessed */
  784. -    timep[1] = ltime;  /* modified */
  785. -    utime(filename, timep);
  786. -
  787. -    if ((RHptr->access == 0xe3L) || (RHptr->access == 0xc3L))  /* unlocked */
  788. -       chmod(filename, S_IREAD | S_IWRITE | 044);
  789. -    if ((RHptr->access == 0x21L) || (RHptr->access == 0x01L))  /* locked */
  790. -       chmod(filename, S_IREAD | 044);
  791. -# endif /* MSDOS */
  792. -
  793. -# ifndef APW
  794. -# ifndef MSDOS
  795. -    printf("need [other] SetFInfo stuff\n");  /* +PORT+ */
  796. -# endif /* none2 */
  797. -# endif /* none1 */
  798. -#endif /* APW */
  799. -}
  800. -
  801. -
  802. -/*
  803. - * Create a subdirectory
  804. - *
  805. - * This routine will exit on most errors, since generally more than one file
  806. - * will be unpacked to a given subdirectory, and we don't want it charging
  807. - * bravely onward if it's going to run into the same problem every time.
  808. - */
  809. -void CreateSubdir(pathname)
  810. -char *pathname;
  811. -{
  812. -    char *buffer = (char *) Malloc(MAXFILENAME+6);
  813. -    static char *procName = "CreateSubdir";
  814. -#ifdef UNIX
  815. -    struct stat st;
  816. -
  817. -    /* if no directory exists, then make one */
  818. -    if (stat(pathname, &st) < 0)
  819. -    if (errno == ENOENT) {
  820. -        sprintf(buffer, "mkdir %s", pathname);
  821. -        if (system(buffer) != 0)  /* call UNIX mkdir to create subdir */
  822. -        Fatal("Unable to create subdir", procName);
  823. -    } else {
  824. -        Fatal("Unable to create dir", procName);
  825. -    }
  826. -#else
  827. -# ifdef APW
  828. -    static FileRec create_p = { "", 0x00e3, 0x000f, 0L, 0x000d, 0, 0 }; /*dir*/
  829. -    FileRec info_p;  /* check if file exists, is dir */
  830. -    int err;  /* holds _toolErr */
  831. -
  832. -    strcpy(buffer, pathname);
  833. -    c2pstr(buffer);
  834. -    info_p.pathname = buffer;
  835. -    GET_FILE_INFO( &info_p );
  836. -
  837. -    switch (_toolErr) {
  838. -    case 0x0000:  /* no error */
  839. -    if (info_p.storageType != 0x000d)  /* not a DIR? */
  840. -        Fatal("File in path exists, is not a directory.", procName);
  841. -    return;  /* file exists, is directory, no need to create */
  842. -
  843. -    case fileNotFound:
  844. -    create_p.pathname = buffer;
  845. -    CREATE( &create_p );
  846. -    if   (!_toolErr) return;   /* created okay? */
  847. -    else ToolErrChk();
  848. -
  849. -    default:  /* unknown error */
  850. -    ToolErrChk();
  851. -    Fatal("whoops!", procName); /* shouldn't get here */
  852. -    }
  853. -# endif /* APW */
  854. -# ifdef MSDOS
  855. -    struct stat st;
  856. -
  857. -    /* if no directory exists, then make one */
  858. -    if (stat(pathname, &st) < 0)
  859. -    if (errno == ENOENT) {
  860. -        if (mkdir(pathname) != 0)
  861. -        Fatal("Unable to create subdir", procName);
  862. -        } else {
  863. -        Fatal("Unable to create dir", procName);
  864. -        }
  865. -# endif /* MSDOS */
  866. -
  867. -# ifndef APW
  868. -# ifndef MSDOS
  869. -
  870. -    /* don't forget to check if it exists first... */  /* +PORT+ */
  871. -    printf("don't know how to create [other] subdirectories\n"); /* mkdir() */
  872. -# endif /* none2 */
  873. -# endif /* none1 */
  874. -#endif /* UNIX */
  875. -    free(buffer);
  876. -}
  877. -
  878. -
  879. -/*
  880. - * Given a pathname, create subdirectories as needed.  All file names are run
  881. - * through a system-dependent filename filter, which means that the pathname
  882. - * has to be broken down, the subdirectory created, and then the pathname
  883. - * reconstructed with the "legal" pathname.  The converted filename is held
  884. - * in a static buffer; subsequent calls will overwrite the previous string.
  885. - *
  886. - * This is useful when unpacking "dir1/dir2/fubar" and dir1 and dir2 don't
  887. - * necessarily exist.
  888. - *
  889. - * It is assumed that all filenames are relative to the current directory.
  890. - * According to the NuFX docs (revision 3 2/3/89), initial separators (like
  891. - * "/", "\", or ":") should NOT be included.  If they are, this routine may
  892. - * break.
  893. - */
  894. -static char *CreatePath(pathname, fssep)
  895. -char *pathname;  /* full pathname; should not include ProDOS volume name */
  896. -onebyt fssep;  /* file system pathname separator, usually "/" or "\" */
  897. -{
  898. -    int idx;
  899. -    char *ptr;
  900. -    static char workbuf[MAXFILENAME];  /* work buffer; must be static */
  901. -    static char *procName = "CreatePath";
  902. -
  903. -    idx = 0;
  904. -    while (TRUE) {  /* move through string */
  905. -    ptr = INDEX(pathname, fssep);    /* find break */
  906. -    if (ptr)  /* down to actual filename? */
  907. -        *ptr = '\0';  /* no, isolate this part of the string */
  908. -
  909. -    strcpy(&workbuf[idx], pathname);  /* copy component to buf */
  910. -    ConvFileName(&workbuf[idx]); /* convert to legal str; may be shorter */
  911. -    idx += strlen(&workbuf[idx]);  /* advance index to end of string */
  912. -    if (!ptr) {  /* down to actual filename? */
  913. -        workbuf[idx] = '\0';  /* yes, clean up */
  914. -        break;  /* out of while */
  915. -    }
  916. -    workbuf[idx] = '\0';
  917. -
  918. -    CreateSubdir(workbuf);    /* system-dependent dir create */
  919. -
  920. -#ifdef UNIX
  921. -    workbuf[idx++] = '/';    /* tack a filename separator on, and advance */
  922. -    *ptr = '/';    /* be nice */
  923. -#else
  924. -# ifdef APW
  925. -    workbuf[idx++] = '/';
  926. -    *ptr = '/';
  927. -# endif
  928. -# ifdef MSDOS
  929. -    workbuf[idx++] = '\';
  930. -    *ptr = '\';
  931. -# endif
  932. -# ifndef APW        /* +PORT+ */
  933. -# ifndef MSDOS
  934. -    workbuf[idx++] = '/';
  935. -    *ptr = '/';
  936. -# endif
  937. -# endif
  938. -#endif /*UNIX*/
  939. -
  940. -/* was:    workbuf[idx++] = fssep;  /* tack an fssep on the end, and advance */
  941. -/* was:    *ptr = fssep;    /* be nice */
  942. -
  943. -    pathname = ptr+1;  /* go again with next component */
  944. -    }
  945. -
  946. -    return (workbuf);
  947. -}
  948. -
  949. -
  950. -/*
  951. - * Extract a thread, and place in a file.
  952. - *
  953. - * Returns TRUE if the extract was successful, FALSE otherwise.  The most
  954. - * common reason for a FALSE return value is a "no" answer when asked about
  955. - * overwriting an existing file.
  956. - */
  957. -static BOOLEAN ExtractThread(arcfd, fileposn, destpn, THptr)
  958. -int arcfd;    /* source file descriptor (must be open) */
  959. -long fileposn;    /* position of data in source file */
  960. -char *destpn;    /* destination filename */
  961. -THblock *THptr;  /* pointer to thread info */
  962. -{
  963. -    int dstfd;    /* destination file descriptor */
  964. -    static char *procName = "ExtractThread";
  965. -
  966. -    if (!print) {
  967. -    if (Exists(destpn)) {
  968. -        if (interact) {
  969. -        if (verbose) printf("file exists, overwite");
  970. -        else         printf("%s exists, overwite", destpn);
  971. -        if (!AskYesNo()) {  /* return w/o overwriting */
  972. -            return (FALSE);
  973. -        }
  974. -        }
  975. -        if (verbose) { printf("overwriting..."); fflush(stdout); }
  976. -        if (unlink(destpn) < 0)
  977. -        Fatal("Unable to remove existing file", procName);
  978. -    }
  979. -
  980. -    if ((dstfd =
  981. -        open(destpn, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, WPERMS)) < 0)
  982. -        Fatal("Unable to open target path", procName);
  983. -
  984. -    if (lseek(arcfd, fileposn, S_ABS) < 0)
  985. -        Fatal("Seek failed", procName);
  986. -
  987. -    if (!UnpackFile(arcfd, dstfd, THptr,
  988. -            dopack ? THptr->thread_format : 0, pakbuf)) {
  989. -        if (close(dstfd) < 0)
  990. -        Fatal("Dest close failed", procName);
  991. -        unlink(destpn);  /* some sys can't delete while file open */
  992. -    } else {
  993. -        if (close(dstfd) < 0)
  994. -        Fatal("Dest close failed", procName);
  995. -    }
  996. -
  997. -    } else {  /* print */
  998. -    if ((dstfd = fileno(stdout)) < 0)
  999. -        Fatal("Unable to get file for stdout", procName);
  1000. -    if (lseek(arcfd, fileposn, S_ABS) < 0)
  1001. -        Fatal("Seek failed", procName);
  1002. -
  1003. -    if (!UnpackFile(arcfd, dstfd, THptr,
  1004. -                dopack ? THptr->thread_format : 0, pakbuf)) {
  1005. -        printf("Unpack failed.\n");
  1006. -        return (FALSE);
  1007. -    }
  1008. -    fflush(stdout);
  1009. -    }
  1010. -
  1011. -    return (TRUE);
  1012. -}
  1013. -
  1014. -
  1015. -/*
  1016. - * Handle message_threads
  1017. - */
  1018. -static void message_thread(arcfd, RNodePtr, TNodePtr)
  1019. -int arcfd;
  1020. -RNode *RNodePtr;
  1021. -TNode *TNodePtr;
  1022. -{
  1023. -    int i;
  1024. -    int oldTo, oldFrom;
  1025. -    static char *procName = "message_thread";
  1026. -
  1027. -    switch (TNodePtr->THptr->thread_kind) {
  1028. -    case 0x0000:  /* ASCII text */
  1029. -    printf("Found ASCII text thread\n");
  1030. -    break;
  1031. -    case 0x0001:  /* ASCII text, predefined size */
  1032. -    if (verbose && !print && TNodePtr->THptr->thread_eof) {
  1033. -        printf("\n--- Comment for file '%s':\n", RNodePtr->filename);
  1034. -        fflush(stdout);
  1035. -        if (lseek(arcfd, TNodePtr->fileposn, S_ABS) < 0)
  1036. -        Fatal("unable to seek to comment", procName);
  1037. -        oldTo = transto;
  1038. -        oldFrom = transfrom;
  1039. -        transto = -1;    /* switch to CR -> current mode */
  1040. -        transfrom = 0;    /* (assumes created under ProDOS) */
  1041. -                /* may need to fix this later (but how?) */
  1042. -        FCopy(arcfd, fileno(stdout), TNodePtr->THptr->thread_eof,
  1043. -        pakbuf, TRUE);
  1044. -#ifdef FUBAR
  1045. -        print = TRUE;
  1046. -        verbose = FALSE;  /* turn off "unshrinking..." messages */
  1047. -        ExtractThread(arcfd,TNodePtr->fileposn, "stdout", TNodePtr->THptr);
  1048. -        print = FALSE;
  1049. -        verbose = TRUE;
  1050. -#endif
  1051. -        transto = oldTo;
  1052. -        transfrom = oldFrom;
  1053. -        putchar('\n');
  1054. -    }
  1055. -    break;
  1056. -    default:
  1057. -    printf("Found unknown message_thread %.4x in '%s'\n",
  1058. -        TNodePtr->THptr->thread_kind, RNodePtr->filename);
  1059. -    break;
  1060. -    }
  1061. -}
  1062. -
  1063. -/*
  1064. - * Handle control_threads
  1065. - */
  1066. -static void control_thread(arcfd, RNodePtr, TNodePtr)
  1067. -int arcfd;
  1068. -RNode *RNodePtr;
  1069. -TNode *TNodePtr;
  1070. -{
  1071. -    switch (TNodePtr->THptr->thread_kind) {
  1072. -    case 0x000:  /* create dir */
  1073. -    printf("Found create directory control thread\n");
  1074. -    break;
  1075. -    default:
  1076. -    printf("Found unknown control_thread %.4x in '%s'\n",
  1077. -        TNodePtr->THptr->thread_kind, RNodePtr->filename);
  1078. -    break;
  1079. -    }
  1080. -}
  1081. -
  1082. -
  1083. -/*
  1084. - * Handle data_threads
  1085. - *
  1086. - * Does not guarantee that the archive file position is anything rational;
  1087. - * the TNode's fileposn should be (and is) used here.
  1088. - */
  1089. -static void data_thread(arcfd, RNodePtr, TNodePtr)
  1090. -int arcfd;
  1091. -RNode *RNodePtr;
  1092. -TNode *TNodePtr;
  1093. -{
  1094. -    long fileposn;     /* absolute position of thread in file */
  1095. -    long old_eof;
  1096. -    char *fn;
  1097. -    int ov;
  1098. -
  1099. -    if (print)  /* this is something of a hack... */
  1100. -    if (TNodePtr->THptr->thread_kind != 0x0000) {  /* not a data fork? */
  1101. -        fprintf(stderr, "Can't print non-data fork for '%s'.\n",
  1102. -                RNodePtr->filename);
  1103. -        return;  /* this hoses the file posn... */
  1104. -    } else {
  1105. -        if (verbose) printf("\n*****  %s  *****\n", RNodePtr->filename);
  1106. -        fflush(stdout);
  1107. -        ov = verbose;
  1108. -        verbose = FALSE;  /* turn off "unshrinking..." messages */
  1109. -        fileposn = TNodePtr->fileposn;
  1110. -        ExtractThread(arcfd,fileposn, "stdout", TNodePtr->THptr);
  1111. -        verbose = ov;
  1112. -        return;
  1113. -    }
  1114. -
  1115. -    switch (TNodePtr->THptr->thread_kind) {
  1116. -    case 0x0000:  /* data fork */
  1117. -    if (verbose) {
  1118. -        printf("Extracting '%s' (data)...", RNodePtr->filename);
  1119. -        fflush(stdout);
  1120. -    }
  1121. -
  1122. -    /* create any needed subdirs */
  1123. -    fn = CreatePath(RNodePtr->filename, RNodePtr->RHptr->file_sys_info);
  1124. -
  1125. -    /* extract the file */
  1126. -    if (ExtractThread(arcfd, TNodePtr->fileposn, fn, TNodePtr->THptr)) {
  1127. -        SetFInfo(fn, RNodePtr->RHptr);  /* set file attributes, dates... */
  1128. -        if (verbose) printf("done.\n");
  1129. -    }
  1130. -    break;
  1131. -
  1132. -    case 0x0001:  /* disk image */
  1133. -/*    printf("Found disk image (not extracted)\n");*/
  1134. -
  1135. -    if (verbose) {
  1136. -        printf("Extracting '%s' (disk image)...", RNodePtr->filename);
  1137. -        fflush(stdout);
  1138. -    }
  1139. -
  1140. -    /* setup path (normalize file name) */
  1141. -    fn = CreatePath(RNodePtr->filename, RNodePtr->RHptr->file_sys_info);
  1142. -
  1143. -    /* thread_eof is invalid for disks, so figure it out */
  1144. -    old_eof = TNodePtr->THptr->thread_eof;
  1145. -    if (RNodePtr->RHptr->storage_type <= 3) {    /* should be block */
  1146. -        TNodePtr->THptr->thread_eof =        /* size, but shk301 */
  1147. -        RNodePtr->RHptr->extra_type * 512;    /* stored it wrong */
  1148. -    } else {
  1149. -        TNodePtr->THptr->thread_eof =
  1150. -        RNodePtr->RHptr->extra_type * RNodePtr->RHptr->storage_type;
  1151. -    }
  1152. -
  1153. -    /* extract the disk into a file */
  1154. -    if (ExtractThread(arcfd, TNodePtr->fileposn, fn, TNodePtr->THptr)) {
  1155. -        /*SetFInfo(fn, RNodePtr->RHptr);/* set file attributes, dates... */
  1156. -        if (verbose) printf("done.\n");
  1157. -    }
  1158. -
  1159. -    TNodePtr->THptr->thread_eof = old_eof;
  1160. -    break;
  1161. -
  1162. -    case 0x0002:  /* resource_fork */
  1163. -    printf("Found resource_fork (not extracted)\n");
  1164. -    break;
  1165. -    default:
  1166. -    printf("Found unknown data_thread %.4x in '%s'\n",
  1167. -        TNodePtr->THptr->thread_kind, RNodePtr->filename);
  1168. -    break;
  1169. -    }
  1170. -}
  1171. -
  1172. -
  1173. -/*
  1174. - * Extract files from archive
  1175. - *
  1176. - * Scan archive, extracting files which start with the strings in "names".
  1177. - * Calls subroutines to handle the various thread_class types.
  1178. - */
  1179. -static void Extract(filename, namecount, names)
  1180. -char *filename;
  1181. -int namecount;
  1182. -char **names;
  1183. -{
  1184. -    ListHdr *archive;
  1185. -    int arcfd;    /* archive file descriptor */
  1186. -    int rec, idx;
  1187. -    MHblock *MHptr;   /* Master Header block */
  1188. -    RNode *RNodePtr;  /* Record Node */
  1189. -    TNode *TNodePtr;   /* Thread block */
  1190. -    int len, *lentab;  /* hold strlen() of all names */
  1191. -    char *pn;  /* archived pathname */
  1192. -    int thread;  /* current thread #; max 65535 threads */
  1193. -    BOOLEAN gotone = FALSE;
  1194. -    static char *procName = "Extract";
  1195. -
  1196. -    archive = NuRead(filename);
  1197. -    if ((arcfd = open(archive->arc_name, O_RDONLY | O_BINARY)) < 0)
  1198. -    Fatal("Unable to open archive", procName);
  1199. -
  1200. -    pakbuf = (onebyt *) Malloc(PAKBUFSIZ);  /* allocate unpack buffer */
  1201. -
  1202. -    lentab = (int *) Malloc( sizeof(int) * namecount ); /* calloc() is nicer */
  1203. -    for (idx = 0; idx < namecount; idx++)  /* calc. once (for efficiency) */
  1204. -    lentab[idx] = strlen(names[idx]);
  1205. -
  1206. -    MHptr = archive->MHptr;
  1207. -    RNodePtr = archive->RNodePtr;
  1208. -
  1209. -    if (!namecount)
  1210. -    extall = TRUE;
  1211. -
  1212. -    /* main record read loop */
  1213. -    for (rec = 0; rec < MHptr->total_records; rec++) {
  1214. -    pn = RNodePtr->filename;
  1215. -    len = strlen(pn);
  1216. -    if (RNodePtr->RHptr->version_number > MAXVERS) {
  1217. -        printf("Unable to extract '%s': unknown record version_number\n",
  1218. -            pn);
  1219. -        continue;  /* with for */
  1220. -    }
  1221. -
  1222. -    for (idx = 0; extall || idx < namecount; idx++) { /* find arced file */
  1223. -        /* try to match argument with first few chars of stored filename */
  1224. -        /* or the entire filename, depending on EXPAND flag */
  1225. -        if (extall || ((len >= lentab[idx]) && doExpand ?
  1226. -            (!strncasecmp(pn, names[idx], lentab[idx])) :
  1227. -            (!strcasecmp(pn, names[idx])) )) {
  1228. -
  1229. -        gotone = TRUE;
  1230. -        /* go through all threads */
  1231. -        TNodePtr = RNodePtr->TNodePtr;
  1232. -        for (thread = 0; thread < (int) RNodePtr->RHptr->total_threads;
  1233. -                                   thread++) {
  1234. -            switch(TNodePtr->THptr->thread_class) {
  1235. -            case 0x0000:
  1236. -            message_thread(arcfd, RNodePtr, TNodePtr);
  1237. -            break;
  1238. -            case 0x0001:
  1239. -            control_thread(arcfd, RNodePtr, TNodePtr);
  1240. -            break;
  1241. -            case 0x0002:
  1242. -            /* don't extract if doMessages is set */
  1243. -            if (!doMessages)
  1244. -                data_thread(arcfd, RNodePtr, TNodePtr);
  1245. -            break;
  1246. -            case 0x0003:
  1247. -            /* filename_thread; ignore */
  1248. -            break;
  1249. -            default:
  1250. -            printf("Unknown thread_class %.4x for '%s'\n",
  1251. -                TNodePtr->THptr->thread_class, RNodePtr->filename);
  1252. -            break;
  1253. -            }
  1254. -            TNodePtr = TNodePtr->TNext;
  1255. -        }
  1256. -        break;    /* out of filename matching (inner) FOR loop */
  1257. -        }
  1258. -    }
  1259. -
  1260. -    RNodePtr = RNodePtr->RNext;  /* move on to next record */
  1261. -    }
  1262. -    if (!gotone && verbose)
  1263. -    printf("None selected\n");
  1264. -    if (close(arcfd) < 0)
  1265. -    Fatal("Source (archive) close failed", procName);
  1266. -
  1267. -}
  1268. -
  1269. -/*
  1270. - * Entry point to extract routines.
  1271. - */
  1272. -void NuExtract(filename, namecount, names, options)
  1273. -char *filename;
  1274. -int namecount;
  1275. -char **names;
  1276. -char *options;
  1277. -{
  1278. -    static char *procName = "NuExtract";
  1279. -
  1280. -    if (*options == 'p') {  /* printing rather then extracting to file */
  1281. -    print = TRUE;
  1282. -    dopack = TRUE;  /* no extract uncompressed! */
  1283. -    } else print = FALSE;
  1284. -
  1285. -    Extract(filename, namecount, names);  /* do stuff */
  1286. -}
  1287. -
  1288. + END OF ARCHIVE
  1289.