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

  1. From: np@doc.imperial.ac.uk (Nigel Perry)
  2. Newsgroups: comp.sources.mac
  3. Subject: AufsTools (part 4 of 4)
  4. Message-ID: <CSM.91.4>
  5. Date: 20 Feb 91 21:00:06 GMT
  6. Approved: bytebug@dhw68k.cts.com (Roger L. Long)
  7.  
  8. [AufsTools - part 4 of 4]
  9.  
  10. ---
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 4 (of 4)."
  18. # Contents:  unstuffit/unsit.c
  19. # Wrapped by np@asun5 on Mon Dec  3 13:15:59 1990
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'unstuffit/unsit.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'unstuffit/unsit.c'\"
  23. else
  24. echo shar: Extracting \"'unstuffit/unsit.c'\" \(31819 characters\)
  25. sed "s/^X//" >'unstuffit/unsit.c' <<'END_OF_FILE'
  26. X/* Modified Aug & Dec 90, Nigel Perry, Dept of Computing, Imperial College,
  27. X   London SW7 2BZ, np@doc.ic.ac.uk
  28. X
  29. X   If called by AUFSNAME (default unstuffit) will input/output to
  30. X   CAPS aufs disc.
  31. X
  32. X   Will now untiff multiple files.
  33. X
  34. X */
  35. X/*
  36. X           unsit - Macintosh StuffIt file extractor
  37. X
  38. X             Version 1.5f, for StuffIt 1.5
  39. X
  40. X                July 23, 1990
  41. X
  42. XThis program will unpack a Macintosh StuffIt file into separate files.
  43. XThe data fork of a StuffIt file contains both the data and resource
  44. Xforks of the packed files.  The program will unpack each Mac file into
  45. Xeither separate .data, .rsrc., and .info files that can be downloaded
  46. Xto a Mac using macput and MacTerminal over a tty line, or into a
  47. Xsingle MacBinary format file.  The MacBinary format is generally more
  48. Xconvenient for those with network connections and FTP capability.  The
  49. Xprogram is much like the "unpit" program for breaking apart Packit
  50. Xarchive files.
  51. X
  52. X            ***** IMPORTANT *****
  53. XTo extract StuffIt files that have been compressed with the Lempel-Ziv
  54. Xcompression method, unsit pipes the data through the "compress"
  55. Xprogram with the appropriate switches, rather than incorporate the
  56. Xuncompression routines within "unsit".  Therefore, it is necessary to
  57. Xhave the "compress" program on the system and in the search path to
  58. Xmake "unsit" work.  "Compress" is available from the comp.sources.unix
  59. Xarchives.
  60. X
  61. XThe program syntax is much like unpit and macput/macget, with some added
  62. Xoptions:
  63. X
  64. X    unsit [-rdulM] [-vqfm] stuffit-file.data
  65. X
  66. XOnly one of the flags r, d, u, l, or M should be specified.  The
  67. Xdefault mode is to create the three macput/MacTerminal compatible
  68. Xfile.  The -M flag will cause the output to be in MacBinary format (a
  69. Xsingle file).  This can be swapped (default = MacBinary, -M = macput)
  70. Xby changing the definitions of DEFAULT_MODE and OTHER_MODE below.  The
  71. X-r and -d flags will cause only the resource and data forks to be
  72. Xwritten.  The -u flag will cause only the data fork to be written and
  73. Xto have carriage return characters changed to Unix newline characters.
  74. XThe -l flag will make the program only list the files in the StuffIt
  75. Xfile.
  76. X
  77. XThe -v flag causes the program to list the names, sizes, type, and
  78. Xcreators of the files it is writing.  The -q flag causes it to list
  79. Xthe name, type and size of each file and wait for a 'y' or 'n' for
  80. Xeither writing that file or skipping it, respectively.  The -m flag is
  81. Xused when the input file in in the MacBinary format instead of just
  82. Xthe data fork.  It causes the program to skip the 128 byte MacBinary
  83. Xheader before looking for the StuffIt header.  It is not necessary to
  84. Xspecify the -m flag since the program now checks for MacBinary format
  85. Xinput files and handles them correctly
  86. X
  87. XVersion 1.5 of the unsit supports extracting files and folders as
  88. Ximplemented by StuffIt 1.5's "Hierarchy Maintained Folder" feature.
  89. XEach folder is extracted as a subdirectory on the Unix system with the
  90. Xfiles in the folder placed in the corresponding subdirectory.  The -f
  91. Xoption can be used to "flatten" out the hierarchy and unsit will store
  92. Xall the files in the current directory.  If the query option (-q) is
  93. Xused and a "n" response is given to a folder name, none of the files
  94. Xor folders in that folder will be extraced.
  95. X
  96. XSome of the program is borrowed from the macput.c/macget.c programs.
  97. XMany, many thanks to Raymond Lau, the author of StuffIt, for including
  98. Xinformation on the format of the StuffIt archives in the
  99. Xdocumentation.  Several changes and enhancements supplied by David
  100. XShanks (cde@atelabs.UUCP) have been incorporated into the program for
  101. Xdoing things like supporting System V and recognizing MacBinary files.
  102. XChristopher Bingham <kb@umnstat.stat.umn.edu> supplied some Macbinary
  103. Xpatches.  Code was also borrowed from the macbin program by Jim Budler
  104. Xfor convert macput format files to MacBinary.  I'm always glad to
  105. Xreceive advice, suggestions, or comments about the program so feel free
  106. Xto send whatever you think would be helpful
  107. X
  108. X
  109. X    Author: Allan G. Weber
  110. X        weber@sipi.usc.edu
  111. X        ...!usc!sipi!weber
  112. X    Date:   July 23, 1990
  113. X
  114. X*/
  115. X
  116. X#include <stdio.h>
  117. X#include <sys/types.h>
  118. X#include <sys/stat.h>
  119. X
  120. Xtypedef long OSType;
  121. X
  122. X#include "stuffit.h"
  123. X
  124. X/*
  125. X * Define the following if your Unix can only handle 14 character file names
  126. X * (e.g. Version 7 and System V).
  127. X */
  128. X/* #define SHORTNAMES */
  129. X
  130. X/*
  131. X * The following defines the name of the compress program that is used for the
  132. X * uncompression of Lempel-Ziv compressed files.  If the path is set up to
  133. X * include the right directory, this should work.
  134. X */
  135. X#define COMPRESS   "compress"
  136. X
  137. X#define IOBUFSIZ   4096
  138. X
  139. X#define MACBINHDRSIZE  128L
  140. X
  141. X#define INIT_CRC 0L
  142. Xextern unsigned short updcrc();
  143. X
  144. X#define INFOBYTES 128
  145. X
  146. X#define BYTEMASK 0xff
  147. X
  148. X#define S_SIGNATURE    0
  149. X#define S_NUMFILES     4
  150. X#define S_ARCLENGTH    6
  151. X#define S_SIGNATURE2  10
  152. X#define    S_VERSION     14
  153. X#define SITHDRSIZE    22
  154. X
  155. X#define F_COMPRMETHOD    0
  156. X#define F_COMPDMETHOD    1
  157. X#define F_FNAME          2
  158. X#define F_FTYPE         66
  159. X#define F_CREATOR       70
  160. X#define F_FNDRFLAGS     74
  161. X#define F_CREATIONDATE  76
  162. X#define F_MODDATE       80
  163. X#define F_RSRCLENGTH    84
  164. X#define F_DATALENGTH    88
  165. X#define F_COMPRLENGTH   92
  166. X#define F_COMPDLENGTH   96
  167. X#define F_RSRCCRC      100
  168. X#define F_DATACRC      102
  169. X#define F_HDRCRC       110
  170. X#define FILEHDRSIZE    112
  171. X
  172. X#define F_NAMELEN 63
  173. X#ifdef SHORTNAMES        /* short file names */
  174. X# define I_NAMELEN 15        /* 14 char file names + '\0' terminator */
  175. X#else
  176. X# define I_NAMELEN 69        /* 63 + strlen(".info") + 1 */
  177. X#endif
  178. X
  179. X/* The following are copied out of macput.c/macget.c */
  180. X#define I_NAMEOFF 1
  181. X/* 65 <-> 80 is the FInfo structure */
  182. X#define I_TYPEOFF 65
  183. X#define I_AUTHOFF 69
  184. X#define I_FLAGOFF 73
  185. X#define I_LOCKOFF 81
  186. X#define I_DLENOFF 83
  187. X#define I_RLENOFF 87
  188. X#define I_CTIMOFF 91
  189. X#define I_MTIMOFF 95
  190. X
  191. X#define INITED_BUG
  192. X#define INITED_OFF    I_FLAGOFF    /* offset to byte with Inited flag */
  193. X#define INITED_MASK    (~1)        /* mask to '&' with byte to reset it */
  194. X
  195. X#define TEXT 0
  196. X#define DATA 1
  197. X#define RSRC 2
  198. X#define MACPUT 3
  199. X#define DUMP 4
  200. X#define MACBINARY 5
  201. X
  202. X/* Swap the following definitions if you want the output to default to
  203. X   MacBinary, and the -M switch to create macput file (.data, .rsrc, .info) */
  204. X#define DEFAULT_MODE MACPUT
  205. X#define OTHER_MODE   MACBINARY
  206. X
  207. X/* #define ADDBIN */    /* add .bin to macbinary file names */
  208. X
  209. X#define NODECODE 0
  210. X#define DECODE   1
  211. X
  212. X#define H_ERROR -1
  213. X#define H_EOF    0
  214. X#define H_WRITE  1
  215. X#define H_SKIP   2
  216. X
  217. X/* if called by this name program works on aufs files */
  218. X#define AUFSNAME "unstuffit"
  219. X
  220. Xstruct node {
  221. X    int flag, byte;
  222. X    struct node *one, *zero;
  223. X} nodelist[512], *nodeptr, *read_tree();    /* 512 should be big enough */
  224. X
  225. Xstruct sitHdr sithdr;
  226. X
  227. Xchar f_info[I_NAMELEN];
  228. Xchar f_data[I_NAMELEN];
  229. Xchar f_rsrc[I_NAMELEN];
  230. X
  231. Xchar info[INFOBYTES];
  232. Xchar mname[F_NAMELEN+1];
  233. Xchar uname[F_NAMELEN+1];
  234. Xchar dname[F_NAMELEN+1];    /* directory name for aufs */
  235. Xchar iobuf[IOBUFSIZ];
  236. Xchar zbuf[128];            /* buffer of zeros to pad MacBinary forks */
  237. X
  238. Xint mode, txtmode, listonly, verbose, query, flatten;
  239. Xint bit, chkcrc, numfiles, depth;
  240. Xint aufs;            /* aufs flag */
  241. Xint debug = 0;
  242. XFILE *infp;
  243. X
  244. Xlong get4();
  245. Xshort get2();
  246. Xunsigned short write_file();
  247. X
  248. X/********************************************************************************/
  249. X/* added for aufs, nicked from various places... */
  250. X
  251. X/* following from mcvert program */
  252. X
  253. X/* Useful, though not particularly Mac related, values */
  254. Xtypedef unsigned char byte;     /* one byte, obviously */
  255. Xtypedef unsigned short word;    /* must be 2 bytes */
  256. Xtypedef unsigned long ulong;    /* 4 bytes */
  257. X
  258. X#define NAMELEN 63              /* maximum legal Mac file name length */
  259. X
  260. X/* Format of a bin file:
  261. XA bin file is composed of 128 byte blocks.  The first block is the
  262. Xinfo_header (see below).  Then comes the data fork, null padded to fill the
  263. Xlast block.  Then comes the resource fork, padded to fill the last block.  A
  264. Xproposal to follow with the text of the Get Info box has not been implemented,
  265. Xto the best of my knowledge.  Version, zero1 and zero2 are what the receiving
  266. Xprogram looks at to determine if a MacBinary transfer is being initiated.
  267. X*/ 
  268. Xtypedef struct {     /* info file header (128 bytes). Unfortunately, these
  269. X                        longs don't align to word boundaries */
  270. X            byte version;           /* there is only a version 0 at this time */
  271. X            byte nlen;              /* Length of filename. */
  272. X            byte name[NAMELEN];     /* Filename (only 1st nlen are significant)*/
  273. X            byte type[4];           /* File type. */
  274. X            byte auth[4];           /* File creator. */
  275. X            byte flags;             /* file flags: LkIvBnSyBzByChIt */
  276. X            byte zero1;             /* Locked, Invisible,Bundle, System */
  277. X                                    /* Bozo, Busy, Changed, Init */
  278. X            byte icon_vert[2];      /* Vertical icon position within window */
  279. X            byte icon_horiz[2];     /* Horizontal icon postion in window */
  280. X            byte window_id[2];      /* Window or folder ID. */
  281. X            byte protect;           /* = 1 for protected file, 0 otherwise */
  282. X            byte zero2;
  283. X            byte dflen[4];          /* Data Fork length (bytes) -   most sig.  */
  284. X            byte rflen[4];          /* Resource Fork length         byte first */
  285. X            byte cdate[4];          /* File's creation date. */
  286. X            byte mdate[4];          /* File's "last modified" date. */
  287. X            byte ilen[2];           /* GetInfo message length */
  288. X        byte flags2;            /* Finder flags, bits 0-7 */
  289. X        byte unused[14];       
  290. X        byte packlen[4];        /* length of total files when unpacked */
  291. X        byte headlen[2];        /* length of secondary header */
  292. X        byte uploadvers;        /* Version of MacBinary II that the uploading program is written for */
  293. X        byte readvers;          /* Minimum MacBinary II version needed to read this file */
  294. X            byte crc[2];            /* CRC of the previous 124 bytes */
  295. X        byte padding[2];        /* two trailing unused bytes */
  296. X            } info_header;
  297. X
  298. X/* end of mcvert stuff */
  299. X/* from CAP aufs documentation */
  300. X
  301. X#define FINFOLEN 32
  302. X#define MAXCLEN 199
  303. Xtypedef struct
  304. X{  /* byte fi_fndr[FINFOLEN]; */    /* finder info */
  305. X   /* what I think the above is... */
  306. X   ulong fndr_type, fndr_creator;
  307. X   word fndr_flags;
  308. X   ulong fndr_loc;
  309. X   word fndr_fldr;
  310. X   word fndr_icon;
  311. X   byte fndr_unused[8];
  312. X   word fndr_comment;
  313. X   ulong fndr_putaway;
  314. X   /* end of fi_fndr */
  315. X
  316. X   word fi_attr;            /* attributes */
  317. X#define FI_MAGIC1 255
  318. X   byte fi_magic1;        /* was: length of comment */
  319. X#define FI_VERSION 0x10        /* version major 1, minor 0 */
  320. X                /* if more than 8 versions then */
  321. X                /* something wrong anyway */
  322. X   byte fi_version;        /* version number */
  323. X#define FI_MAGIC 0xda
  324. X   byte fi_magic;        /* magic word check */
  325. X   byte fi_bitmap;        /* bitmap of included info */
  326. X#define FI_BM_SHORTFILENAME 0x1    /* is this included? */
  327. X#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */
  328. X   byte fi_shortfilename[12+1];    /* possible short file name */
  329. X   byte fi_macfilename[32+1];    /* possible macintosh file name */
  330. X   byte fi_comln;        /* comment length */
  331. X   byte fi_comnt[MAXCLEN+1];    /* comment string */
  332. X} FileInfo;
  333. X
  334. XFileInfo fndr_info;
  335. X
  336. X/* end aufs */
  337. X/********************************************************************************/
  338. X
  339. Xmain(argc, argv)
  340. Xint argc;
  341. Xchar *argv[];
  342. X{
  343. X    int status;
  344. X    int c;
  345. X    extern int optind;
  346. X    extern char *optarg;
  347. X    int errflg;
  348. X    int macbin;
  349. X
  350. X    mode = DEFAULT_MODE;
  351. X    errflg = 0;
  352. X    macbin = 0;
  353. X    flatten = 0;
  354. X    numfiles = 0;
  355. X    depth = 0;
  356. X    aufs = strcmp(argv[0], AUFSNAME) == 0;
  357. X
  358. X    while ((c = getopt(argc, argv, "DMdflmqruvx")) != EOF)
  359. X    switch (c) {
  360. X      case 'r':        /* extract resource fork only */
  361. X        mode = RSRC;
  362. X        break;
  363. X      case 'd':        /* extract data fork only */
  364. X        mode = DATA;
  365. X        break;
  366. X      case 'u':        /* extract data fork as Unix text file */
  367. X        mode = TEXT;
  368. X        break;
  369. X      case 'l':        /* list contents of archive */
  370. X        listonly++;
  371. X        break;
  372. X      case 'q':        /* query user on each extraction */
  373. X        query++;
  374. X        break;
  375. X      case 'v':        /* verbose mode */
  376. X        verbose++;
  377. X        break;
  378. X      case 'x':        /* don't decode data, just dump to files*/
  379. X        mode = DUMP;
  380. X        break;
  381. X      case 'm':        /* input file is in Macbinary format */
  382. X        macbin = 1;
  383. X        break;
  384. X      case 'M':        /* output file in OTHER_MODE */
  385. X        mode = OTHER_MODE;
  386. X        break;
  387. X      case 'f':        /* don't create flat directory tree */
  388. X        flatten = 1;
  389. X        break;
  390. X      case 'D':        /* debugging mode */
  391. X        debug = 1;
  392. X        break;
  393. X      case '?':
  394. X        errflg++;
  395. X        break;
  396. X    }
  397. X    if (errflg) {
  398. X    usage();
  399. X    exit(1);
  400. X    }
  401. X
  402. X    /* -a incompatible with -M and -u */
  403. X    if(aufs && (mode == MACBINARY || mode == TEXT))
  404. X    {   fprintf(stderr, "Aufs mode cannot be combined with MacBinary (-M) or text (-t) mode\n");
  405. X    exit(1);
  406. X    }
  407. X
  408. X    if (optind == argc) {
  409. X    usage();
  410. X    exit(1);
  411. X    }
  412. X    else
  413. X    while(optind < argc)
  414. X        {   if ((infp = fopen(argv[optind], "r")) == NULL)
  415. X        {   fprintf(stderr,"Can't open input file \"%s\"\n",argv[optind]);
  416. X            exit(1);
  417. X        }
  418. X
  419. X        if (macbin) {
  420. X        if (fseek(infp, MACBINHDRSIZE, 0) == -1) {
  421. X            fprintf(stderr, "Can't skip over MacBinary header\n");
  422. X            exit(1);
  423. X        }
  424. X        }
  425. X
  426. X        if (readsithdr(&sithdr) == 0) {
  427. X        fprintf(stderr, "Can't read file header\n");
  428. X        exit(1);
  429. X        }
  430. X        if (debug) {
  431. X        printf("archive header (%d bytes):\n", SITHDRSIZE);
  432. X        printf("numFiles=%d, arcLength=%ld, version=%d\n",
  433. X               sithdr.numFiles, sithdr.arcLength, sithdr.version & 0xff);
  434. X        }
  435. X        status = extract("", 0);
  436. X        if(status < 0) exit(1);
  437. X
  438. X        optind++;
  439. X    }
  440. X
  441. X    exit(0);
  442. X}
  443. X
  444. Xusage()
  445. X{
  446. X    fprintf(stderr, "Usage: unsit/unstuffit [-rdulM] [-vqfm] filename\n");
  447. X}
  448. X
  449. X/*
  450. X  extract(parent, skip) - Extract all files from the current folder.
  451. X  char *parent;           name of parent folder
  452. X  int  skip;              1 to skip all files and folders in this one
  453. X                          0 to extract them
  454. X
  455. X  returns 1 if came an endFolder record
  456. X          0 if EOF
  457. X     -1 if error (bad fileHdr, bad file, etc.)
  458. X*/
  459. X
  460. Xextract(parent, skip)
  461. Xchar *parent;
  462. Xint skip;
  463. X{
  464. X    struct fileHdr filehdr;
  465. X    struct stat sbuf;
  466. X    int status, rstat, sstat, skipit;
  467. X    char name[256];
  468. X
  469. X    while (1) {
  470. X    rstat = readfilehdr(&filehdr, skip);
  471. X    if (rstat == H_ERROR || rstat == H_EOF) {
  472. X        status = rstat;
  473. X        break;
  474. X    }
  475. X    if (debug) {
  476. X        printf("file header (%d bytes):\n", FILEHDRSIZE);
  477. X        printf("compRMethod=%d, compDMethod=%d\n",
  478. X           filehdr.compRMethod, filehdr.compDMethod);
  479. X        printf("rsrcLength=%ld, dataLength=%ld\n",
  480. X           filehdr.rsrcLength, filehdr.dataLength);
  481. X        printf("compRLength=%ld, compDLength=%ld\n",
  482. X           filehdr.compRLength, filehdr.compDLength);
  483. X        printf("rsrcCRC=%d=0x%04x, dataCRC=%d=0x%04x\n",
  484. X           filehdr.rsrcCRC, filehdr.rsrcCRC,
  485. X           filehdr.dataCRC, filehdr.dataCRC);
  486. X    }
  487. X
  488. X    skipit = (rstat == H_SKIP) ? 1 : 0;
  489. X
  490. X    if (filehdr.compRMethod == endFolder && 
  491. X        filehdr.compDMethod == endFolder) {
  492. X        status = 1;        /* finished with this folder */
  493. X        break;
  494. X    }
  495. X    else if (filehdr.compRMethod == startFolder && 
  496. X         filehdr.compDMethod == startFolder) {
  497. X        if (!listonly && rstat == H_WRITE && !flatten) {
  498. X        sstat = stat(uname, &sbuf);
  499. X        if (sstat == -1) {    /* directory doesn't exist */
  500. X            if (mkdir(uname, 0777) == -1) {
  501. X            fprintf(stderr,
  502. X                "Can't create subdirectory %s\n", uname);
  503. X            return(-1);
  504. X            }
  505. X        }
  506. X        else {        /* something exists with this name */
  507. X            if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
  508. X            fprintf(stderr, "Directory name %s already in use\n",
  509. X                uname);
  510. X            return(-1);
  511. X            }
  512. X        }
  513. X        if(aufs) /* create .finderinfo & .resource subdirectories */
  514. X        {   strcpy(dname, uname);
  515. X            strcat(dname, "/.finderinfo");
  516. X            sstat = stat(dname, &sbuf);
  517. X            if (sstat == -1) {    /* directory doesn't exist */
  518. X            if (mkdir(dname, 0777) == -1) {
  519. X                fprintf(stderr,
  520. X                    "Can't create subdirectory %s\n", dname);
  521. X                return(-1);
  522. X            }
  523. X            }
  524. X            else {        /* something exists with this name */
  525. X            if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
  526. X                fprintf(stderr, "Directory name %s already in use\n",
  527. X                    dname);
  528. X                return(-1);
  529. X            }
  530. X            }
  531. X            strcpy(dname, uname);
  532. X            strcat(dname, "/.resource");
  533. X            sstat = stat(dname, &sbuf);
  534. X            if (sstat == -1) {    /* directory doesn't exist */
  535. X            if (mkdir(dname, 0777) == -1) {
  536. X                fprintf(stderr,
  537. X                    "Can't create subdirectory %s\n", dname);
  538. X                return(-1);
  539. X            }
  540. X            }
  541. X            else {        /* something exists with this name */
  542. X            if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
  543. X                fprintf(stderr, "Directory name %s already in use\n",
  544. X                    dname);
  545. X                return(-1);
  546. X            }
  547. X            }
  548. X        }
  549. X        if (chdir(uname) == -1) {
  550. X            fprintf(stderr, "Can't chdir to %s\n", uname);
  551. X            return(-1);
  552. X        }
  553. X        sprintf(name,"%s:%s", parent, uname);
  554. X        }
  555. X        depth++;
  556. X        status = extract(name, skipit);
  557. X        depth--;
  558. X        if (status != 1)
  559. X        break;        /* problem with folder */
  560. X        if (depth == 0)    /* count how many top-level files done */
  561. X        numfiles++;
  562. X        if (!flatten)
  563. X        chdir("..");
  564. X    }
  565. X    else {
  566. X        if ((status = extractfile(&filehdr, skipit)) != 1)
  567. X        break;
  568. X        if (depth == 0)    /* count how many top-level files done */
  569. X        numfiles++;
  570. X    }
  571. X    if (numfiles == sithdr.numFiles)
  572. X        break;
  573. X    }
  574. X    return(status);
  575. X}
  576. X
  577. Xextractfile(fh, skip)
  578. Xstruct fileHdr *fh;
  579. Xint skip;
  580. X{
  581. X    unsigned short crc;
  582. X    FILE *fp, *fp1;
  583. X    int n;
  584. X
  585. X    f_data[0] = f_rsrc[0] = f_info[0] = '\0'; /* assume no output files */
  586. X    /* figure out what file names to use and what to do */
  587. X    if (!listonly && !skip) {
  588. X    switch (mode) {
  589. X      case MACPUT:        /* do both rsrc and data forks */
  590. X        if(aufs)
  591. X        {   sprintf(f_data, "%.*s", I_NAMELEN - 1, uname);
  592. X        sprintf(f_rsrc, ".resource/%.*s", I_NAMELEN - 1, uname);
  593. X        sprintf(f_info, ".finderinfo/%.*s", I_NAMELEN - 1, uname);
  594. X        }
  595. X        else
  596. X        {   sprintf(f_data, "%.*s.data", I_NAMELEN - 6, uname);
  597. X        sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
  598. X        sprintf(f_info, "%.*s.info", I_NAMELEN - 6, uname);
  599. X        }
  600. X        break;
  601. X      case RSRC:        /* rsrc fork only */
  602. X        if(aufs)
  603. X        {   sprintf(f_rsrc, ".resource/%.*s", I_NAMELEN - 1, uname);
  604. X        sprintf(f_info, ".finderinfo/%.*s", I_NAMELEN - 1, uname);
  605. X        }
  606. X        else
  607. X        sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
  608. X        break;
  609. X      case DATA:        /* data fork only */
  610. X        if(aufs)
  611. X        {   sprintf(f_data, "%.*s", I_NAMELEN - 1, uname);
  612. X        sprintf(f_info, ".finderinfo/%.*s", I_NAMELEN - 1, uname);
  613. X        }
  614. X        else
  615. X            sprintf(f_data, "%.*s.data", I_NAMELEN - 6, uname);
  616. X        break;
  617. X      case TEXT:
  618. X        sprintf(f_data, "%.*s.text", I_NAMELEN - 6, uname);
  619. X        break;
  620. X      case DUMP:        /* for debugging, dump data as is */
  621. X        sprintf(f_data, "%.*s.ddump", I_NAMELEN - 7, uname);
  622. X        sprintf(f_rsrc, "%.*s.rdump", I_NAMELEN - 7, uname);
  623. X        fh->compRMethod = fh->compDMethod = noComp;
  624. X        break;
  625. X      case MACBINARY:    /* output file in MacBinary format */
  626. X        sprintf(f_data, "%.*s.data", I_NAMELEN - 6, uname);
  627. X        sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
  628. X#ifndef ADDBIN
  629. X        sprintf(f_info, "%.*s", I_NAMELEN - 1, uname);
  630. X#else
  631. X        sprintf(f_info, "%.*s.bin", I_NAMELEN - 5, uname);
  632. X#endif /*ADDBIN*/
  633. X        break;
  634. X    }
  635. X    }
  636. X
  637. X    fp = NULL;            /* so we can tell if a file is open */
  638. X    if (f_info[0] != '\0' && check_access(f_info) != -1) {
  639. X    fp = fopen(f_info, "w");
  640. X    if (fp == NULL) {
  641. X        perror(f_info);
  642. X        exit(1);
  643. X    }
  644. X    if(aufs) /* convert info structure */
  645. X    {   register info_header *pinfo;
  646. X    
  647. X        pinfo = (info_header *)info;
  648. X
  649. X        /* make the .finderinfo file */
  650. X        bzero(&fndr_info, sizeof(FileInfo));
  651. X        bcopy(pinfo->type, &fndr_info.fndr_type, 4);
  652. X        bcopy(pinfo->auth, &fndr_info.fndr_creator, 4);
  653. X        bcopy(&pinfo->flags, &fndr_info.fndr_flags, 2);
  654. X        fndr_info.fi_magic1 = FI_MAGIC1;
  655. X        fndr_info.fi_version = FI_VERSION;
  656. X        fndr_info.fi_magic = FI_MAGIC;
  657. X        fndr_info.fi_bitmap = FI_BM_MACINTOSHFILENAME;
  658. X        bcopy(pinfo->name, fndr_info.fi_macfilename, pinfo->nlen);
  659. X
  660. X        fwrite(&fndr_info, sizeof(FileInfo), 1, fp);
  661. X    }
  662. X    else
  663. X    {   if (mode == MACBINARY) { /* convert to MacBinary header */
  664. X        /* taken from the macbin program */
  665. X        if (info[74] & 0x40) info[81] = '\1'; /* protected */
  666. X        info[74] = '\0'; /* clear zero2 */
  667. X        info[82] = '\0'; /* force zero3 clear */
  668. X        }
  669. X        fwrite(info, 1, INFOBYTES, fp);
  670. X    }
  671. X    }
  672. X
  673. X    if (f_rsrc[0] != '\0') {
  674. X    txtmode = 0;
  675. X    crc = write_file(f_rsrc, fh->compRLength,
  676. X             fh->rsrcLength, fh->compRMethod);
  677. X    if (chkcrc && fh->rsrcCRC != crc) {
  678. X        fprintf(stderr,
  679. X            "CRC error on resource fork: need 0x%04x, got 0x%04x\n",
  680. X            fh->rsrcCRC, crc);
  681. X        return(-1);
  682. X    }
  683. X    }
  684. X    else {
  685. X    fseek(infp, (long) fh->compRLength, 1);
  686. X    }
  687. X    if (f_data[0] != '\0') {
  688. X    txtmode = (mode == TEXT);
  689. X    crc = write_file(f_data, fh->compDLength,
  690. X             fh->dataLength, fh->compDMethod);
  691. X    if (chkcrc && fh->dataCRC != crc) {
  692. X        fprintf(stderr,
  693. X            "CRC error on data fork: need 0x%04x, got 0x%04x\n",
  694. X            fh->dataCRC, crc);
  695. X        return(-1);
  696. X    }
  697. X    }
  698. X    else {
  699. X    fseek(infp, (long) fh->compDLength, 1);
  700. X    }
  701. X    if (fp != NULL) {
  702. X    /* if Macbinary output, copy the data and resource forks to the
  703. X       end of the info file, and pad each to multiples of 128 bytes. */
  704. X    if (mode == MACBINARY) {
  705. X        fp1 = fopen(f_data, "r"); /* re-open the file we just wrote */
  706. X        if (fp1 == NULL) {
  707. X        perror(f_data);
  708. X        exit(1);
  709. X        }
  710. X        while ((n = fread(iobuf, 1, IOBUFSIZ, fp1)) > 0)
  711. X        fwrite(iobuf, 1, n, fp); /* append it to the info file */
  712. X        /* pad out to multiple of 128 if in MacBinary format */
  713. X        n = fh->dataLength % 128;
  714. X        if (n > 0)
  715. X        outc(zbuf, 128 - n, fp);
  716. X        fclose(fp1);
  717. X        unlink(f_data);
  718. X        fp1 = fopen(f_rsrc, "r"); /* re-open the file we just wrote */
  719. X        if (fp1 == NULL) {
  720. X        perror(f_rsrc);
  721. X        exit(1);
  722. X        }
  723. X        while ((n = fread(iobuf, 1, IOBUFSIZ, fp1)) > 0)
  724. X        fwrite(iobuf, 1, n, fp); /* append it to the info file */
  725. X        /* pad out to multiple of 128 if in MacBinary format */
  726. X        n = fh->rsrcLength % 128;
  727. X        if (n > 0)
  728. X        outc(zbuf, 128 - n, fp);
  729. X        fclose(fp1);
  730. X        unlink(f_rsrc);
  731. X    }
  732. X    fclose(fp);
  733. X    }
  734. X    return(1);
  735. X}
  736. X
  737. Xreadsithdr(s)
  738. Xstruct sitHdr *s;
  739. X{
  740. X    char temp[FILEHDRSIZE];
  741. X    int count = 0;
  742. X
  743. X    for (;;) {
  744. X    if (fread(temp, 1, SITHDRSIZE, infp) != SITHDRSIZE) {
  745. X        fprintf(stderr, "Can't read file header\n");
  746. X        return(0);
  747. X    }
  748. X        
  749. X    if (strncmp(temp + S_SIGNATURE,  "SIT!", 4) == 0 &&
  750. X        strncmp(temp + S_SIGNATURE2, "rLau", 4) == 0) {
  751. X        s->numFiles = get2(temp + S_NUMFILES);
  752. X        s->arcLength = get4(temp + S_ARCLENGTH);
  753. X        return(1);
  754. X    }
  755. X    
  756. X    if (++count == 2) {
  757. X        fprintf(stderr, "Not a StuffIt file\n");
  758. X        return(0);
  759. X    }
  760. X    
  761. X    if (fread(&temp[SITHDRSIZE], 1, FILEHDRSIZE - SITHDRSIZE, infp) !=
  762. X        FILEHDRSIZE - SITHDRSIZE) {
  763. X        fprintf(stderr, "Can't read file header\n");
  764. X        return(0);
  765. X    }
  766. X    
  767. X    if (strncmp(temp + I_TYPEOFF, "SIT!", 4) == 0 &&
  768. X        strncmp(temp + I_AUTHOFF, "SIT!", 4) == 0) {    /* MacBinary format */
  769. X        fseek(infp, (long)(INFOBYTES-FILEHDRSIZE), 1);    /* Skip over header */
  770. X    }
  771. X    }
  772. X}
  773. X
  774. X/*
  775. X  readfilehdr - reads the file header for each file and the folder start
  776. X  and end records.
  777. X
  778. X  returns: H_ERROR = error
  779. X       H_EOF   = EOF
  780. X       H_WRITE = write file/folder
  781. X       H_SKIP  = skip file/folder
  782. X*/
  783. X
  784. Xreadfilehdr(f, skip)
  785. Xstruct fileHdr *f;
  786. Xint skip;
  787. X{
  788. X    unsigned short crc;
  789. X    int i, n, write_it, isfolder;
  790. X    char hdr[FILEHDRSIZE];
  791. X    char ch, *mp, *up;
  792. X    char *tp, temp[10];
  793. X
  794. X    for (i = 0; i < INFOBYTES; i++)
  795. X    info[i] = '\0';
  796. X
  797. X    /* read in the next file header, which could be folder start/end record */
  798. X    n = fread(hdr, 1, FILEHDRSIZE, infp);
  799. X    if (n == 0)            /* return 0 on EOF */
  800. X    return(H_EOF);
  801. X    else if (n != FILEHDRSIZE) {
  802. X    fprintf(stderr, "Can't read file header\n");
  803. X    return(H_ERROR);
  804. X    }
  805. X
  806. X    /* check the CRC for the file header */
  807. X    crc = INIT_CRC;
  808. X    crc = updcrc(crc, hdr, FILEHDRSIZE - 2);
  809. X    f->hdrCRC = get2(hdr + F_HDRCRC);
  810. X    if (f->hdrCRC != crc) {
  811. X    fprintf(stderr, "Header CRC mismatch: got 0x%04x, need 0x%04x\n",
  812. X        f->hdrCRC, crc);
  813. X    return(H_ERROR);
  814. X    }
  815. X
  816. X    /* grab the name of the file or folder */
  817. X    n = hdr[F_FNAME] & BYTEMASK;
  818. X    if (n > F_NAMELEN)
  819. X    n = F_NAMELEN;
  820. X    info[I_NAMEOFF] = n;
  821. X    copy(info + I_NAMEOFF + 1, hdr + F_FNAME + 1, n);
  822. X    strncpy(mname, hdr + F_FNAME + 1, n);
  823. X    mname[n] = '\0';
  824. X    /* copy to a string with no illegal Unix characters in the file name */
  825. X    mp = mname;
  826. X    up = uname;
  827. X    while ((ch = *mp++) != '\0') {
  828. X    if (ch <= ' ' || ch > '~' || index("/!()[]*<>?\\\"$\';&`", ch) != NULL)
  829. X        ch = '_';
  830. X    *up++ = ch;
  831. X    }
  832. X    *up = '\0';
  833. X
  834. X    /* get lots of other stuff from the header */
  835. X    f->compRMethod = hdr[F_COMPRMETHOD];
  836. X    f->compDMethod = hdr[F_COMPDMETHOD];
  837. X    f->rsrcLength = get4(hdr + F_RSRCLENGTH);
  838. X    f->dataLength = get4(hdr + F_DATALENGTH);
  839. X    f->compRLength = get4(hdr + F_COMPRLENGTH);
  840. X    f->compDLength = get4(hdr + F_COMPDLENGTH);
  841. X    f->rsrcCRC = get2(hdr + F_RSRCCRC);
  842. X    f->dataCRC = get2(hdr + F_DATACRC);
  843. X
  844. X    /* if it's an end folder record, don't need to do any more */
  845. X    if (f->compRMethod == endFolder && f->compDMethod == endFolder)
  846. X    return(H_WRITE);
  847. X
  848. X    /* prepare an info file in case its needed */
  849. X
  850. X    copy(info + I_TYPEOFF, hdr + F_FTYPE, 4);
  851. X    copy(info + I_AUTHOFF, hdr + F_CREATOR, 4);
  852. X    copy(info + I_FLAGOFF, hdr + F_FNDRFLAGS, 2);
  853. X#ifdef INITED_BUG
  854. X    info[INITED_OFF] &= INITED_MASK; /* reset init bit */
  855. X#endif
  856. X    copy(info + I_DLENOFF, hdr + F_DATALENGTH, 4);
  857. X    copy(info + I_RLENOFF, hdr + F_RSRCLENGTH, 4);
  858. X    copy(info + I_CTIMOFF, hdr + F_CREATIONDATE, 4);
  859. X    copy(info + I_MTIMOFF, hdr + F_MODDATE, 4);
  860. X
  861. X    isfolder = f->compRMethod == startFolder && f->compDMethod == startFolder;
  862. X    
  863. X    /* list the file name if verbose or listonly mode, also if query mode */
  864. X    if (skip)            /* skip = 1 if skipping all in this folder */
  865. X    write_it = 0;
  866. X    else {
  867. X    write_it = 1;
  868. X    if (listonly || verbose || query) {
  869. X        for (i = 0; i < depth; i++)
  870. X        putchar(' ');
  871. X        if (isfolder)
  872. X        printf("Folder: \"%s\"", uname);
  873. X        else
  874. X        printf("name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
  875. X               uname, hdr + F_FTYPE, hdr + F_CREATOR,
  876. X               f->dataLength, f->rsrcLength);
  877. X        if (query) {    /* if querying, check with the boss */
  878. X        printf(" ? ");
  879. X        fgets(temp, sizeof(temp) - 1, stdin);
  880. X        tp = temp;
  881. X        write_it = 0;
  882. X        while (*tp != '\0') {
  883. X            if (*tp == 'y' || *tp == 'Y') {
  884. X            write_it = 1;
  885. X            break;
  886. X            }
  887. X            else
  888. X            tp++;
  889. X        }
  890. X        }
  891. X        else        /* otherwise, terminate the line */
  892. X        putchar('\n');
  893. X    }
  894. X    }
  895. X    return(write_it ? H_WRITE : H_SKIP);
  896. X}
  897. X
  898. Xcheck_access(fname)    /* return 0 if OK to write on file fname, -1 otherwise */
  899. Xchar *fname;
  900. X{
  901. X    char temp[10], *tp;
  902. X
  903. X    if (access(fname, 0) == -1) {
  904. X    return(0);
  905. X    }
  906. X    else {
  907. X    printf("%s exists.  Overwrite? ", fname);
  908. X    fgets(temp, sizeof(temp) - 1, stdin);
  909. X    tp = temp;
  910. X    while (*tp != '\0') {
  911. X        if (*tp == 'y' || *tp == 'Y') {
  912. X        return(0);
  913. X        }
  914. X        else
  915. X        tp++;
  916. X    }
  917. X    }
  918. X    return(-1);
  919. X}
  920. X
  921. Xunsigned short write_file(fname, ibytes, obytes, type)
  922. Xchar *fname;
  923. Xunsigned long ibytes, obytes;
  924. Xunsigned char type;
  925. X{
  926. X    unsigned short crc;
  927. X    int i, n, ch, lastch;
  928. X    FILE *outf;
  929. X    char temp[256];
  930. X
  931. X    crc = INIT_CRC;
  932. X    chkcrc = 1;            /* usually can check the CRC */
  933. X
  934. X    if (check_access(fname) == -1) {
  935. X    fseek(infp, ibytes, 1);
  936. X    chkcrc = 0;        /* inhibit crc check if file not written */
  937. X        return(-1);
  938. X    }
  939. X    
  940. X    switch (type) {
  941. X      case noComp:        /* no compression */
  942. X    outf = fopen(fname, "w");
  943. X    if (outf == NULL) {
  944. X        perror(fname);
  945. X        exit(1);
  946. X    }
  947. X    while (ibytes > 0) {
  948. X        n = (ibytes > IOBUFSIZ) ? IOBUFSIZ : ibytes;
  949. X        n = fread(iobuf, 1, n, infp);
  950. X        if (n == 0)
  951. X        break;
  952. X        crc = updcrc(crc, iobuf, n);
  953. X        outc(iobuf, n, outf);
  954. X        ibytes -= n;
  955. X    }
  956. X    fclose(outf);
  957. X    break;
  958. X      case rleComp:        /* run length encoding */
  959. X    outf = fopen(fname, "w");
  960. X    if (outf == NULL) {
  961. X        perror(fname);
  962. X        exit(1);
  963. X    }
  964. X    while (ibytes > 0) {
  965. X        ch = getc(infp) & 0xff;
  966. X        ibytes--;
  967. X        if (ch == 0x90) {    /* see if its the repeat marker */
  968. X        n = getc(infp) & 0xff; /* get the repeat count */
  969. X        ibytes--;
  970. X        if (n == 0) { /* 0x90 was really an 0x90 */
  971. X            iobuf[0] = 0x90;
  972. X            crc = updcrc(crc, iobuf, 1);
  973. X            outc(iobuf, 1, outf);
  974. X        }
  975. X        else {
  976. X            n--;
  977. X            for (i = 0; i < n; i++)
  978. X            iobuf[i] = lastch;
  979. X            crc = updcrc(crc, iobuf, n);
  980. X            outc(iobuf, n, outf);
  981. X        }
  982. X        }
  983. X        else {
  984. X        iobuf[0] = ch;
  985. X        crc = updcrc(crc, iobuf, 1);
  986. X        lastch = ch;
  987. X        outc(iobuf, 1, outf);
  988. X        }
  989. X    }
  990. X    fclose(outf);
  991. X    break;
  992. X      case lzwComp:        /* LZW compression */
  993. X    sprintf(temp, "%s%s", COMPRESS, " -d -c -n -b 14 ");
  994. X    if (txtmode) {
  995. X        strcat(temp, "| tr \'\\015\' \'\\012\' ");
  996. X        chkcrc = 0;        /* can't check CRC in this case */
  997. X    }
  998. X    strcat(temp, "> '");
  999. X    strcat(temp, fname);
  1000. X    strcat(temp, "'");
  1001. X    outf = popen(temp, "w");
  1002. X    if (outf == NULL) {
  1003. X        perror(fname);
  1004. X        exit(1);
  1005. X    }
  1006. X    while (ibytes > 0) {
  1007. X        n = (ibytes > IOBUFSIZ) ? IOBUFSIZ : ibytes;
  1008. X        n = fread(iobuf, 1, n, infp);
  1009. X        if (n == 0)
  1010. X        break;
  1011. X        fwrite(iobuf, 1, n, outf);
  1012. X        ibytes -= n;
  1013. X    }
  1014. X    pclose(outf);
  1015. X    if (chkcrc) {
  1016. X        outf = fopen(fname, "r"); /* read the file to get CRC value */
  1017. X        if (outf == NULL) {
  1018. X        perror(fname);
  1019. X        exit(1);
  1020. X        }
  1021. X        while (1) {
  1022. X        n = fread(iobuf, 1, IOBUFSIZ, outf);
  1023. X        if (n == 0)
  1024. X            break;
  1025. X        crc = updcrc(crc, iobuf, n);
  1026. X        }
  1027. X        fclose(outf);
  1028. X    }
  1029. X    break;
  1030. X      case hufComp:        /* Huffman compression */
  1031. X    outf = fopen(fname, "w");
  1032. X    if (outf == NULL) {
  1033. X        perror(fname);
  1034. X        exit(1);
  1035. X    }
  1036. X    nodeptr = nodelist;
  1037. X    bit = 0;        /* put us on a byte boundary */
  1038. X    read_tree();
  1039. X    while (obytes > 0) {
  1040. X        n = (obytes > IOBUFSIZ) ? IOBUFSIZ : obytes;
  1041. X        for (i = 0; i < n; i++)
  1042. X        iobuf[i] = gethuffbyte(DECODE);
  1043. X        crc = updcrc(crc, iobuf, n);
  1044. X        outc(iobuf, n, outf);
  1045. X        obytes -= n;
  1046. X    }
  1047. X    fclose(outf);
  1048. X    break;
  1049. X      default:
  1050. X    fprintf(stderr, "Unknown compression method\n");
  1051. X    chkcrc = 0;        /* inhibit crc check if file not written */
  1052. X    return(-1);
  1053. X    }
  1054. X
  1055. X    return(crc & 0xffff);
  1056. X}
  1057. X
  1058. Xoutc(p, n, fp)
  1059. Xchar *p;
  1060. Xint n;
  1061. XFILE *fp;
  1062. X{
  1063. X    register char *p1;
  1064. X    register int i;
  1065. X    if (txtmode) {
  1066. X    for (i = 0, p1 = p; i < n; i++, p1++)
  1067. X        if ((*p1 & BYTEMASK) == '\r')
  1068. X        *p1 = '\n';
  1069. X    }
  1070. X    fwrite(p, 1, n, fp);
  1071. X}
  1072. X
  1073. Xlong get4(bp)
  1074. Xchar *bp;
  1075. X{
  1076. X    register int i;
  1077. X    long value = 0;
  1078. X
  1079. X    for (i = 0; i < 4; i++) {
  1080. X    value <<= 8;
  1081. X    value |= (*bp & BYTEMASK);
  1082. X    bp++;
  1083. X    }
  1084. X    return(value);
  1085. X}
  1086. X
  1087. Xshort get2(bp)
  1088. Xchar *bp;
  1089. X{
  1090. X    register int i;
  1091. X    int value = 0;
  1092. X
  1093. X    for (i = 0; i < 2; i++) {
  1094. X    value <<= 8;
  1095. X    value |= (*bp & BYTEMASK);
  1096. X    bp++;
  1097. X    }
  1098. X    return(value);
  1099. X}
  1100. X
  1101. Xcopy(p1, p2, n)
  1102. Xchar *p1, *p2;
  1103. Xint n;
  1104. X{
  1105. X    while (n-- > 0)
  1106. X        *p1++ = *p2++;
  1107. X}
  1108. X
  1109. X/* This routine recursively reads the Huffman encoding table and builds
  1110. X   and decoding tree. */
  1111. X
  1112. Xstruct node *read_tree()
  1113. X{
  1114. X    struct node *np;
  1115. X    np = nodeptr++;
  1116. X    if (getbit() == 1) {
  1117. X        np->flag = 1;
  1118. X        np->byte = gethuffbyte(NODECODE);
  1119. X    }
  1120. X    else {
  1121. X        np->flag = 0;
  1122. X        np->zero = read_tree();
  1123. X        np->one  = read_tree();
  1124. X    }
  1125. X    return(np);
  1126. X}
  1127. X
  1128. X/* This routine returns the next bit in the input stream (MSB first) */
  1129. X
  1130. Xgetbit()
  1131. X{
  1132. X    static char b;
  1133. X    if (bit == 0) {
  1134. X        b = getc(infp) & 0xff;
  1135. X        bit = 8;
  1136. X    }
  1137. X    bit--;
  1138. X    return((b >> bit) & 1);
  1139. X}
  1140. X
  1141. X/* This routine returns the next 8 bits.  If decoding is on, it finds the
  1142. Xbyte in the decoding tree based on the bits from the input stream.  If
  1143. Xdecoding is not on, it either gets it directly from the input stream or
  1144. Xputs it together from 8 calls to getbit(), depending on whether or not we
  1145. Xare currently on a byte boundary
  1146. X*/
  1147. Xgethuffbyte(decode)
  1148. Xint decode;
  1149. X{
  1150. X    register struct node *np;
  1151. X    register int i, b;
  1152. X    if (decode == DECODE) {
  1153. X        np = nodelist;
  1154. X        while (np->flag == 0)
  1155. X            np = (getbit()) ? np->one : np->zero;
  1156. X        b = np->byte;
  1157. X    }
  1158. X    else {
  1159. X        if (bit == 0)    /* on byte boundary? */
  1160. X            b = getc(infp) & 0xff;
  1161. X        else {        /* no, put a byte together */
  1162. X            b = 0;
  1163. X            for (i = 8; i > 0; i--) {
  1164. X                b = (b << 1) + getbit();
  1165. X            }
  1166. X        }
  1167. X    }
  1168. X    return(b);
  1169. X}
  1170. END_OF_FILE
  1171. if test 31819 -ne `wc -c <'unstuffit/unsit.c'`; then
  1172.     echo shar: \"'unstuffit/unsit.c'\" unpacked with wrong size!
  1173. fi
  1174. # end of 'unstuffit/unsit.c'
  1175. fi
  1176. echo shar: End of archive 4 \(of 4\).
  1177. cp /dev/null ark4isdone
  1178. MISSING=""
  1179. for I in 1 2 3 4 ; do
  1180.     if test ! -f ark${I}isdone ; then
  1181.     MISSING="${MISSING} ${I}"
  1182.     fi
  1183. done
  1184. if test "${MISSING}" = "" ; then
  1185.     echo You have unpacked all 4 archives.
  1186.     rm -f ark[1-9]isdone
  1187. else
  1188.     echo You still need to unpack the following archives:
  1189.     echo "        " ${MISSING}
  1190. fi
  1191. ##  End of shell archive.
  1192. exit 0
  1193. --- end of part 4 ---
  1194.