home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume11 / zoo / part02 < prev    next >
Internet Message Format  |  1987-08-16  |  52KB

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v11i011:  File archive program, Part02/07
  5. Message-ID: <966@uunet.UU.NET>
  6. Date: 18 Aug 87 02:00:22 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 1910
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: iuvax!bsu-cs!dhesi@seismo.CSS.GOV (Rahul Dhesi)
  12. Posting-number: Volume 11, Issue 11
  13. Archive-name: zoo/Part02
  14.  
  15. #! /bin/sh
  16. #
  17. # This is a shell archive, meaning:
  18. # 1. Remove everything above the #! /bin/sh line.
  19. # 2. Save the resulting text in a file.
  20. # 3. Execute the file with /bin/sh (not csh) to create:
  21. #    lzc.c
  22. #    lzconst.h
  23. #    lzd.c
  24. #    machine.c
  25. #    machine.h
  26. #    makefile
  27. #    makelist.c
  28. #    misc.c
  29. #    misc2.c
  30. #    mkbsd
  31. #    mkgenric
  32. #    mksysv
  33. #    mksysvsh
  34. #    mkuport
  35. #    mkx68
  36. #    mkx86
  37. #    mstime.i
  38. export PATH; PATH=/bin:/usr/bin:$PATH
  39. if test -f 'lzc.c'
  40. then
  41.     echo shar: "will not over-write existing file 'lzc.c'"
  42. else
  43. sed 's/^X//' << \SHAR_EOF > 'lzc.c'
  44. X#ifndef LINT
  45. Xstatic char sccsid[]="@(#) lzc.c 1.4 87/05/29 12:53:58";
  46. X#endif /* LINT */
  47. X
  48. X#include "options.h"
  49. X/*
  50. XLempel-Ziv compression.  Mostly based on Tom Pfau's assembly language
  51. Xcode. 
  52. X
  53. XThe contents of this file are hereby released to the public domain.
  54. X
  55. X                                    -- Rahul Dhesi  1986/12/31
  56. X*/
  57. X
  58. X#include <stdio.h>            /* just to define NULL */
  59. X#include "various.h"
  60. X#include "zoofns.h"           /* function definitions */
  61. X/* zoomem.h defines IN_BUF_SIZE & OUT_BUF_SIZE */
  62. X#include "zoomem.h"
  63. X#include "debug.h"
  64. X#include "assert.h"
  65. X/* lzconst.h contains constants for lzd() and lzc() */
  66. X#include "lzconst.h"
  67. X
  68. X/* interval at which to check ratio */
  69. X#define CHECKGAP 4000
  70. X#define NEXT_USE  1
  71. X#define FIRST_USE 2
  72. X#define FOUND 0
  73. X
  74. Xstruct   tabentry {
  75. X   int first;
  76. X   int next;
  77. X   char z_ch;
  78. X};
  79. X
  80. Xvoid init_ctab();
  81. Xvoid wr_ccode();
  82. Xint rd_cch();
  83. Xint lukup_ccode();
  84. Xvoid ad_ccode();
  85. Xvoid check_ratio();
  86. Xvoid flush_c();
  87. Xextern char *out_buf_adr;
  88. Xextern char *in_buf_adr;
  89. Xextern char memflag;                    /* memory allocated? */
  90. Xstruct tabentry *table;                 /* this table also used by lzd.c */
  91. Xstatic unsigned int free_code;
  92. Xstatic int nbits;
  93. Xstatic unsigned int max_code;
  94. Xstatic unsigned int bitsout;
  95. Xstatic int bit_interval;
  96. Xstatic unsigned int bytesin, ratio, ratflag;
  97. Xstatic unsigned int in_offset, in_size;
  98. Xstatic unsigned int bit_offset;
  99. Xstatic int in_han, out_han;
  100. X
  101. Xint lzc(input_handle, output_handle)
  102. Xint input_handle, output_handle;
  103. X{
  104. X   int nextch, prefix_code, k;
  105. X   int status;
  106. X   int where;
  107. X
  108. X   in_han = input_handle;
  109. X   out_han = output_handle;
  110. X
  111. X   bit_offset = in_offset = in_size = 0;
  112. X
  113. X   if (memflag == 0) {
  114. X     table = (struct tabentry *) emalloc((MAXMAX+10) * sizeof(struct tabentry));
  115. X     memflag++;
  116. X   }
  117. X
  118. X
  119. X   init_ctab();
  120. X   wr_ccode(CLEAR);
  121. X   nextch = rd_cch();
  122. X   if (nextch == EOF) {                  /* note real EOF, not Z_EOF */
  123. X      wr_ccode (Z_EOF);
  124. X      return (0);                         /* normal return from compress */
  125. X   }
  126. X
  127. X   /* compression loop begins here with nextch holding the next input char */
  128. Xloop1:
  129. X   if (ratflag != 0)
  130. X      check_ratio();
  131. X   nextch &= 0xff;                       /* turn character to code */
  132. X   assert(nextch < 256);
  133. Xloop2:
  134. X   prefix_code = nextch;
  135. X   nextch = rd_cch();
  136. X   if (nextch == EOF) {                  /* note real EOF, not Z_EOF */
  137. X      wr_ccode (prefix_code);
  138. X      wr_ccode (Z_EOF);
  139. X      if (bit_offset != 0)
  140. X         flush_c ((int) (bit_offset / 8 + 1));
  141. X      return (0);                         /* normal return from compress */
  142. X   }
  143. X   nextch &= 0xff;                        /* force to 8 bits */
  144. X   assert(nextch < 256);
  145. X
  146. X   k = nextch;
  147. X   status = lukup_ccode (prefix_code, nextch, &where);
  148. X   if (status == FOUND) {
  149. X      nextch = where;                     /* where found */
  150. X      goto loop2;
  151. X   }
  152. X   assert(status == FIRST_USE || status == NEXT_USE);
  153. X
  154. X   /* reach here with status = FIRST_USE or NEXT_USE */
  155. X   ad_ccode (status, nextch, where);
  156. X
  157. X   wr_ccode (prefix_code);
  158. X   nextch = k;
  159. X
  160. X   if (free_code <= max_code)
  161. X      goto loop1;
  162. X   assert(nbits >= 9 && nbits <= MAXBITS);
  163. X   if (nbits >= MAXBITS) {
  164. X   /* To continue using table after it is full, remove next two lines */
  165. X      wr_ccode (CLEAR);
  166. X      init_ctab();
  167. X
  168. X      goto loop1;
  169. X   }
  170. X
  171. X   nbits++;
  172. X   assert(nbits >= 9 && nbits <= MAXBITS);
  173. X   max_code = max_code << 1;
  174. X   goto loop1;
  175. X} /* end lzc() */
  176. X
  177. Xvoid wr_ccode (code)
  178. Xint code;
  179. X{
  180. X   unsigned int ofs_inbyte, hibits;
  181. X   int byte_offset;
  182. X
  183. X#ifdef DEBUG
  184. Xif (code == CLEAR)
  185. X   printf(" CLEAR\n");
  186. X#endif
  187. X
  188. X   assert(nbits >= 9 && nbits <= MAXBITS);
  189. X   bitsout += nbits;                /* total number of bits written */
  190. X   bit_interval -= nbits;
  191. X   if (bit_interval < 0)
  192. X      ratflag = 1;                  /* time to check ratio */
  193. X
  194. X   byte_offset = bit_offset / 8;
  195. X   ofs_inbyte = bit_offset % 8;     /* offset within byte */
  196. X   bit_offset += nbits;             /* allowing for new code */
  197. X
  198. X   if (byte_offset >= OUTBUFSIZ - 4) {
  199. X      flush_c (byte_offset);
  200. X      bit_offset = ofs_inbyte + nbits;
  201. X      out_buf_adr[0] = out_buf_adr [byte_offset];
  202. X      byte_offset = 0;
  203. X   }
  204. X
  205. X   code = code & 0xffff;            /* force to 16 bits */
  206. X
  207. X   if (ofs_inbyte == 0)
  208. X      out_buf_adr[byte_offset]  = code & 0xff;
  209. X   else
  210. X      out_buf_adr[byte_offset] |= (code << ofs_inbyte) & 0xff;
  211. X
  212. X   hibits = ((unsigned int) code) >> (8 - ofs_inbyte);
  213. X   out_buf_adr[byte_offset+1] = hibits & 0xff;
  214. X   out_buf_adr[byte_offset+2] = (((unsigned int) hibits) >> 8) & 0xff;
  215. X
  216. X   assert(nbits >= 9 && nbits <= MAXBITS);
  217. X} /* end wr_ccode() */
  218. X
  219. Xvoid init_ctab()
  220. X{
  221. X   int i;
  222. X   bytesin = bitsout = ratio = ratflag = 0;
  223. X   bit_interval = CHECKGAP;
  224. X   nbits = 9;
  225. X   max_code = 512;
  226. X#ifdef COMMENT
  227. X   for (i = 0; i < 256; i++) {
  228. X#endif
  229. X   for (i = 0; i < MAXMAX+1; i++) {
  230. X      table[i].z_ch = table[i].first = table[i].next = -1;
  231. X   }
  232. X#ifdef COMMENT
  233. X   /*DEBUG*/ table[MAXMAX].first   = table[MAXMAX].next = -1;
  234. X   /*DEBUG*/ table[MAXMAX-1].first = table[MAXMAX-1].next = -1;
  235. X#endif
  236. X   free_code = FIRST_FREE;
  237. X} /* end init_ctab() */
  238. X
  239. Xint rd_cch()
  240. X{
  241. X   int count;
  242. X   bytesin++;
  243. X   if (in_offset == in_size) {
  244. X      count = read (in_han, in_buf_adr, INBUFSIZ);
  245. X      if (count == -1)
  246. X         prterror ('f', "Error reading input file during compression.\n");
  247. X      addbfcrc (in_buf_adr, count);
  248. X      if (count == 0) {
  249. X         debug((printf("\nEOF on input\n")))
  250. X         return (EOF);              /* real EOF, not Z_EOF */
  251. X      }
  252. X      in_size = count;
  253. X      debug((printf("\ninput %d chars\n", count)))
  254. X      in_offset = 0;
  255. X   }
  256. X   in_offset++;
  257. X   return (in_buf_adr[in_offset-1] & 0xff);
  258. X} /* end rd_cch () */
  259. X
  260. Xvoid check_ratio()
  261. X{
  262. X#ifdef COMMENT
  263. X   int rat;
  264. X   if (bitsout > 16383) {     /* avoid overflow */
  265. X      bitsout /= 4;
  266. X      bytesin /= 4;
  267. X   }
  268. X   rat = (2 * bitsout) / bytesin;
  269. X   if (1.1 * rat < ratio) {
  270. X      printf("#");
  271. X      wr_ccode (CLEAR);
  272. X      init_ctab();
  273. X      bit_interval = CHECKGAP;
  274. X      bitsout = 0;
  275. X      bytesin = 0;
  276. X      ratio = 0;
  277. X   } else
  278. X      ratio = ((ratio << 2) + ((2 * bitsout) / bytesin)) / 5;
  279. X#else
  280. X   bit_interval = CHECKGAP;
  281. X   bitsout = 0;
  282. X   bytesin = 0;
  283. X#endif
  284. X} /* end check_ratio() */
  285. X
  286. Xvoid ad_ccode (status, ch, index)
  287. Xint status, index, ch;
  288. X{
  289. X   assert(status == FIRST_USE || status == NEXT_USE);
  290. X#ifdef COMMENT
  291. X   if (free_code >= MAXMAX)      /* to fix apparent bug in original */
  292. X      return;
  293. X#endif
  294. X#ifdef COMMENT
  295. X   if (status == NEXT_USE)
  296. X      table[index].next = free_code;
  297. X   else                 /* else must be FIRST_USE */
  298. X      table[index].first = free_code;
  299. X#endif
  300. X   if (status == NEXT_USE)
  301. X      table[index].next = (free_code >= MAXMAX ? -1 : free_code);
  302. X   else                 /* else must be FIRST_USE */
  303. X      table[index].first = (free_code >= MAXMAX ? -1 : free_code);
  304. X
  305. X#ifdef COMMENT
  306. X   if (free_code < MAXMAX) {
  307. X#endif
  308. X   if (free_code <= MAXMAX) {
  309. X      table[free_code].first = table[free_code].next = -1;
  310. X      table[free_code].z_ch = ch & 0xff;
  311. X      free_code++;
  312. X   }
  313. X} /* end ad_ccode() */
  314. X
  315. Xint lukup_ccode (index, ch, where)
  316. Xint index;                        /* where to start looking */
  317. Xint ch;                             /* char to look for */
  318. Xint *where;                       /* last entry looked at */
  319. X{
  320. X   *where = index;
  321. X   index = table[index].first;
  322. X   if (index == -1) {
  323. X      return (FIRST_USE);           /* not found, first use */
  324. X   } else {
  325. X      while (1) {
  326. X         if ((table[index].z_ch & 0xff) == (ch & 0xff)) {
  327. X            *where = index;
  328. X            return (FOUND);
  329. X         }
  330. X         *where = index;
  331. X         index = table[index].next;
  332. X         if (index == -1) {
  333. X            return (NEXT_USE);
  334. X         }
  335. X      } /* end while */
  336. X   } /* end else */
  337. X} /* end lukup_ccode() */
  338. X
  339. Xvoid flush_c (count)
  340. Xint count;
  341. X{
  342. X   int status;
  343. X#ifdef DEBUG
  344. Xprintf(" <flushed %d bytes> ", count);
  345. X#endif
  346. X   status = write (out_han, out_buf_adr, count);
  347. X   if (status == -1)
  348. X      prterror ('f', "Error writing during compression.\n");
  349. X}
  350. SHAR_EOF
  351. fi
  352. if test -f 'lzconst.h'
  353. then
  354.     echo shar: "will not over-write existing file 'lzconst.h'"
  355. else
  356. sed 's/^X//' << \SHAR_EOF > 'lzconst.h'
  357. X/* @(#) lzconst.h 1.2 87/05/03 16:01:07 */
  358. X
  359. X/*
  360. XThe contents of this file are hereby released to the public domain.
  361. X
  362. X                                    -- Rahul Dhesi  1986/12/31
  363. X*/
  364. X
  365. X#define  INBUFSIZ    (IN_BUF_SIZE - 10)   /* avoid obo errors */
  366. X#define  OUTBUFSIZ   (OUT_BUF_SIZE - 10)
  367. X#define  MEMERR      2
  368. X#define  IOERR       1
  369. X#define  MAXBITS     13
  370. X#define  CLEAR       256         /* clear code */
  371. X#define  Z_EOF       257         /* end of file marker */
  372. X#define  FIRST_FREE  258         /* first free code */
  373. X#define  MAXMAX      8192        /* max code + 1 */
  374. SHAR_EOF
  375. fi
  376. if test -f 'lzd.c'
  377. then
  378.     echo shar: "will not over-write existing file 'lzd.c'"
  379. else
  380. sed 's/^X//' << \SHAR_EOF > 'lzd.c'
  381. X#ifndef LINT
  382. X/* @(#) lzd.c 1.5 87/05/29 12:54:10 */
  383. Xstatic char sccsid[]="@(#) lzd.c 1.5 87/05/29 12:54:10";
  384. X#endif /* LINT */
  385. X
  386. X#include "options.h"
  387. X/*
  388. XLempel-Ziv decompression.  Mostly based on Tom Pfau's assembly language
  389. Xcode.  The contents of this file are hereby released to the public domain.
  390. X                                 -- Rahul Dhesi 1986/11/14
  391. X*/
  392. X
  393. X#include <stdio.h>            /* just to define NULL */
  394. X#include "various.h"
  395. X#include "zoofns.h"           /* function definitions */
  396. X/* zoomem.h defines IN_BUF_SIZE & OUT_BUF_SIZE */
  397. X#include "zoomem.h"
  398. X#include "debug.h"
  399. X#include "assert.h"
  400. X/* lzconst.h contains constants for lzd() and lzc() */
  401. X#include "lzconst.h"
  402. X
  403. X#define  STACKSIZE   4000
  404. X
  405. Xstruct tabentry {
  406. X   unsigned next;
  407. X   char z_ch;
  408. X};
  409. X
  410. Xvoid init_dtab();
  411. Xunsigned rd_dcode();
  412. X
  413. X#ifdef LINT_ARGS
  414. Xvoid wr_dchar (char);
  415. X#else
  416. Xvoid wr_dchar();
  417. X#endif
  418. X
  419. Xvoid ad_dcode();
  420. X
  421. Xstatic unsigned stack_pointer = 0;
  422. Xstatic unsigned *stack;
  423. X
  424. X#define  push(x)  {  \
  425. X                     stack[stack_pointer++] = (x);                   \
  426. X                     if (stack_pointer >= STACKSIZE)                 \
  427. X                        prterror ('f', "Stack overflow in lzd().\n");\
  428. X                  }
  429. X#define  pop()    (stack[--stack_pointer])
  430. X
  431. Xextern char *out_buf_adr;        /* output buffer */
  432. Xextern char *in_buf_adr;         /* input buffer */
  433. X
  434. Xchar memflag = 0;                /* memory allocated? flag */
  435. Xextern struct tabentry *table;   /* hash table from lzc.c */
  436. Xstatic unsigned cur_code;
  437. Xstatic unsigned old_code;
  438. Xstatic unsigned in_code;
  439. X
  440. Xstatic unsigned free_code;
  441. Xstatic int nbits;
  442. Xstatic unsigned max_code;
  443. X
  444. Xstatic char fin_char;
  445. Xstatic char k;
  446. Xstatic unsigned masks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
  447. X                        0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff };
  448. Xstatic unsigned bit_offset;
  449. Xstatic unsigned output_offset;
  450. Xstatic int in_han, out_han; 
  451. X
  452. Xint lzd(input_handle, output_handle)
  453. Xint input_handle, output_handle;          /* input & output file handles */
  454. X{
  455. X   in_han = input_handle;                 /* make it avail to other fns */
  456. X   out_han = output_handle;               /* ditto */
  457. X   nbits = 9;
  458. X   max_code = 512;
  459. X   free_code = FIRST_FREE;
  460. X   stack_pointer = 0;
  461. X   bit_offset = 0;
  462. X   output_offset = 0;
  463. X
  464. X   if (read(in_han, in_buf_adr, INBUFSIZ) == -1)
  465. X      return(IOERR);
  466. X   if (memflag == 0) {
  467. X     table = (struct tabentry *) emalloc((MAXMAX+10) * sizeof(struct tabentry));
  468. X     stack = (unsigned *) emalloc (sizeof (unsigned) * STACKSIZE + 20);
  469. X     memflag++;
  470. X   }
  471. X
  472. X   init_dtab();             /* initialize table */
  473. X
  474. Xloop:
  475. X   cur_code = rd_dcode();
  476. X   if (cur_code == Z_EOF) {
  477. X      debug((printf ("lzd: Z_EOF\n")))
  478. X      if (output_offset != 0) {
  479. X         if (out_han != -2) {
  480. X            if (write(out_han, out_buf_adr, output_offset) != output_offset)
  481. X               prterror ('f', "Output error in lzd().\n");
  482. X         }
  483. X         addbfcrc(out_buf_adr, output_offset);
  484. X      }
  485. X      return (0);
  486. X   }
  487. X
  488. X   assert(nbits >= 9 && nbits <= 13);
  489. X
  490. X   if (cur_code == CLEAR) {
  491. X      debug((printf ("lzd: CLEAR\n")))
  492. X      init_dtab();
  493. X      fin_char = k = old_code = cur_code = rd_dcode();
  494. X      wr_dchar(k);
  495. X      goto loop;
  496. X   }
  497. X
  498. X   in_code = cur_code;
  499. X   if (cur_code >= free_code) {        /* if code not in table (k<w>k<w>k) */
  500. X      cur_code = old_code;             /* previous code becomes current */
  501. X      push(fin_char);
  502. X   }
  503. X
  504. X   while (cur_code > 255) {               /* if code, not character */
  505. X      push(table[cur_code].z_ch);         /* push suffix char */
  506. X      cur_code = table[cur_code].next;    /* <w> := <w>.code */
  507. X   }
  508. X
  509. X   assert(nbits >= 9 && nbits <= 13);
  510. X
  511. X   k = fin_char = cur_code;
  512. X   push(k);
  513. X   while (stack_pointer != 0) {
  514. X      wr_dchar(pop());
  515. X   }
  516. X   assert(nbits >= 9 && nbits <= 13);
  517. X   ad_dcode();
  518. X   old_code = in_code;
  519. X
  520. X   assert(nbits >= 9 && nbits <= 13);
  521. X
  522. X   goto loop;
  523. X} /* lzd() */
  524. X
  525. X/* rd_dcode() reads a code from the input (compressed) file and returns
  526. Xits value. */
  527. Xunsigned rd_dcode()
  528. X{
  529. X   register char *ptra, *ptrb;    /* miscellaneous pointers */
  530. X   unsigned word;                     /* first 16 bits in buffer */
  531. X   unsigned byte_offset;
  532. X   char nextch;                           /* next 8 bits in buffer */
  533. X   unsigned ofs_inbyte;               /* offset within byte */
  534. X
  535. X   ofs_inbyte = bit_offset % 8;
  536. X   byte_offset = bit_offset / 8;
  537. X   bit_offset = bit_offset + nbits;
  538. X
  539. X   assert(nbits >= 9 && nbits <= 13);
  540. X
  541. X   if (byte_offset >= INBUFSIZ - 5) {
  542. X      int space_left;
  543. X
  544. X      assert(byte_offset >= INBUFSIZ - 5);
  545. X      debug((printf ("lzd: byte_offset near end of buffer\n")))
  546. X
  547. X      bit_offset = ofs_inbyte + nbits;
  548. X      space_left = INBUFSIZ - byte_offset;
  549. X      ptrb = byte_offset + in_buf_adr;          /* point to char */
  550. X      ptra = in_buf_adr;
  551. X      /* we now move the remaining characters down buffer beginning */
  552. X      debug((printf ("rd_dcode: space_left = %d\n", space_left)))
  553. X      while (space_left > 0) {
  554. X         *ptra++ = *ptrb++;
  555. X         space_left--;
  556. X      }
  557. X      assert(ptra - in_buf_adr == ptrb - (in_buf_adr + byte_offset));
  558. X      assert(space_left == 0);
  559. X      if (read(in_han, ptra, byte_offset) == -1)
  560. X         prterror ('f', "I/O error in lzd:rd_dcode.\n");
  561. X      byte_offset = 0;
  562. X   }
  563. X   ptra = byte_offset + in_buf_adr;
  564. X   /* NOTE:  "word = *((int *) ptra)" would not be independent of byte order. */
  565. X   word = (unsigned char) *ptra; ptra++;
  566. X   word = word | ((unsigned char) *ptra) << 8; ptra++;
  567. X
  568. X   nextch = *ptra;
  569. X   if (ofs_inbyte != 0) {
  570. X      /* shift nextch right by ofs_inbyte bits */
  571. X      /* and shift those bits right into word; */
  572. X      word = (word >> ofs_inbyte) | (((unsigned)nextch) << (16-ofs_inbyte));
  573. X   }
  574. X   return (word & masks[nbits]); 
  575. X} /* rd_dcode() */
  576. X
  577. Xvoid init_dtab()
  578. X{
  579. X   nbits = 9;
  580. X   max_code = 512;
  581. X   free_code = FIRST_FREE;
  582. X}
  583. X
  584. Xvoid wr_dchar (ch)
  585. Xchar ch;
  586. X{
  587. X   if (output_offset >= OUTBUFSIZ) {      /* if buffer full */
  588. X      if (out_han != -2) {
  589. X         if (write(out_han, out_buf_adr, output_offset) != output_offset)
  590. X            prterror ('f', "Write error in lzd:wr_dchar.\n");
  591. X      }
  592. X      addbfcrc(out_buf_adr, output_offset);     /* update CRC */
  593. X      output_offset = 0;                  /* restore empty buffer */
  594. X   }
  595. X   assert(output_offset < OUTBUFSIZ);
  596. X   out_buf_adr[output_offset++] = ch;        /* store character */
  597. X} /* wr_dchar() */
  598. X
  599. X/* adds a code to table */
  600. Xvoid ad_dcode()
  601. X{
  602. X   assert(nbits >= 9 && nbits <= 13);
  603. X   assert(free_code <= MAXMAX+1);
  604. X   table[free_code].z_ch = k;                /* save suffix char */
  605. X   table[free_code].next = old_code;         /* save prefix code */
  606. X   free_code++;
  607. X   assert(nbits >= 9 && nbits <= 13);
  608. X   if (free_code >= max_code) {
  609. X      if (nbits < MAXBITS) {
  610. X         debug((printf("lzd: nbits was %d\n", nbits)))
  611. X         nbits++;
  612. X         assert(nbits >= 9 && nbits <= 13);
  613. X         debug((printf("lzd: nbits now %d\n", nbits)))
  614. X         max_code = max_code << 1;        /* double max_code */
  615. X         debug((printf("lzd: max_code now %d\n", max_code)))
  616. X      }
  617. X   }
  618. X}
  619. SHAR_EOF
  620. fi
  621. if test -f 'machine.c'
  622. then
  623.     echo shar: "will not over-write existing file 'machine.c'"
  624. else
  625. sed 's/^X//' << \SHAR_EOF > 'machine.c'
  626. X#ifndef LINT
  627. X/* @(#) machine.c 1.3 87/05/03 15:59:18 */
  628. Xstatic char sccsid[]="@(#) machine.c 1.3 87/05/03 15:59:18";
  629. X#endif /* LINT */
  630. X
  631. X/*
  632. XThe contents of this file are hereby released to the public domain.
  633. X
  634. X                                    -- Rahul Dhesi  1986/12/31
  635. X*/
  636. X
  637. X#include "options.h"
  638. X#ifdef SYS_V
  639. X#include "zoo.h"
  640. X#include "sysv.c"
  641. X#endif
  642. X
  643. X#ifdef GENERIC
  644. X#include "zoo.h"
  645. X#include <stdio.h>
  646. X#include "generic.c"
  647. X#endif
  648. X
  649. X#ifdef BSD4_3
  650. X#include "bsd.c"
  651. X#endif
  652. X
  653. X#ifdef DLC
  654. X#include <stdio.h>
  655. X#include "zoo.h"
  656. X#include "generic.c"
  657. X#endif
  658. X
  659. X#ifdef MSC
  660. X#ifdef PORTABLE
  661. X#include <stdio.h>
  662. X#include "zoo.h"
  663. X#include "zoofns.h"
  664. X#include "generic.c"
  665. X#else
  666. X#include <stdio.h>
  667. X#include "zoo.h"
  668. X#include "zoofns.h"
  669. X#include "msc.c"
  670. X#endif
  671. X#endif
  672. SHAR_EOF
  673. fi
  674. if test -f 'machine.h'
  675. then
  676.     echo shar: "will not over-write existing file 'machine.h'"
  677. else
  678. sed 's/^X//' << \SHAR_EOF > 'machine.h'
  679. X/* @(#) machine.h 1.2 87/05/03 15:59:21 */
  680. X
  681. X/*
  682. XThe contents of this file are hereby released to the public domain.
  683. X
  684. X                           -- Rahul Dhesi 1986/11/14
  685. X*/
  686. X
  687. X/* 
  688. XThis file holds definitions that usually do not change
  689. Xbetween different systems, except when using REALLY strange systems.  But
  690. Xoptions.h and machine.c hold stuff that does change quite a bit.
  691. X*/
  692. X
  693. X/* 
  694. XMAXLONG is the maximum size of a long integer.  Right now it doesn't have to
  695. Xbe accurate since it's only used within zooext() to fake infinite disk space.
  696. X*/
  697. X#define  MAXLONG  ((unsigned long) (~0L))
  698. X
  699. X/* 
  700. XType BYTE must hold exactly 8 bits.  The code will collapse badly if BYTE is
  701. Xanything other than exactly 8 bits. To avoid sign extension when casting
  702. XBYTE to a longer size, it must be declared unsigned.  For machine-
  703. Xindependence, Zoo does all I/O of archive headers and directory entries 
  704. Xin units of BYTE.  The actual file data are not written in units of
  705. XBYTE, however, so portability may not be absolute.
  706. X*/
  707. Xtypedef  unsigned char BYTE;  /* type corresponding to an 8-bit byte */
  708. X
  709. SHAR_EOF
  710. fi
  711. if test -f 'makefile'
  712. then
  713.     echo shar: "will not over-write existing file 'makefile'"
  714. else
  715. sed 's/^X//' << \SHAR_EOF > 'makefile'
  716. X# @(#) makefile 1.6 87/05/03 15:59:23 
  717. X#Make Zoo
  718. X#
  719. X#The contents of this makefile are hereby released to the public domain.
  720. X#                                  -- Rahul Dhesi 1986/12/31
  721. X#
  722. X#This makefile should not be invoked directly, because different 
  723. X#targets require different compilation switches.  The standard make
  724. X#utility does not allow different switches to be specified for each target
  725. X#(except through recursive invocation, which takes more memory than 
  726. X#some systems have).  Invoke this makefile through one of the several
  727. X#shell scripts supplied.  For non *NIX systems, convert the appropriate
  728. X#shell script to one accepted by your system.
  729. X#
  730. X#This makefile expects two macro names, `cswitch' and `extra', to hold
  731. X#all the switches to be supplied to the C compiler.  It also expects
  732. X#a macro `ldswitch' to hold the switch for the loader when invoked.
  733. X
  734. X#Destination directory where `make install' will put the programs.
  735. XDESTDIR = ../bin
  736. X
  737. XCC = cc
  738. Xcswitch =
  739. Xextra = -DBIG_MEM -DNDEBUG
  740. X
  741. X#List of all object files created for Zoo
  742. XZOOOBJS =     addbfcrc.o addfname.o basename.o comment.o crcdefs.o \
  743. X        getfile.o lzc.o lzd.o machine.o makelist.o misc.o misc2.o \
  744. X        nextfile.o needed.o options.o parse.o portable.o prterror.o \
  745. X        version.o zoo.o zooadd.o zooadd2.o zoodel.o zooext.o zoolist.o \
  746. X        zoopack.o
  747. X
  748. XFIZOBJS = fiz.o addbfcrc.o portable.o crcdefs.o
  749. X
  750. X.c.o :
  751. X    $(CC) $(cswitch) $(extra) $*.c
  752. X
  753. X.c~.c:
  754. X    get .z/s.$*.c
  755. X
  756. Xall : ERROR
  757. X
  758. Xlint: $(ZOOOBJS)
  759. X    lint $(ZOOOBJS)
  760. X
  761. Xzoo: $(ZOOOBJS)
  762. X    $(CC) $(ldswitch) $(ZOOOBJS)
  763. X
  764. Xfiz: $(FIZOBJS)
  765. X    $(CC) $(ldswitch) $(FIZOBJS)
  766. X
  767. X#Install executable code into destination directory.  If your system
  768. X#has the `install' program invoke it as:  install -s zoo $(DESTDIR)/zoo
  769. X#
  770. Xinstall : 
  771. X    mv zoo $(DESTDIR)/zoo
  772. X    mv fiz $(DESTDIR)/fiz
  773. X
  774. Xclean :
  775. X    /bin/rm -f core a.out $(ZOOOBJS) $(FIZOBJS)
  776. X
  777. Xlzd.o : lzd.c zoomem.h
  778. X    $(CC) $(cswitch) $(extra) $*.c
  779. X
  780. Xlzc.o : lzc.c zoomem.h
  781. X    $(CC) $(cswitch) $(extra) $*.c
  782. X
  783. Xaddbfcrc.o : addbfcrc.c
  784. X
  785. Xaddfname.o : addfname.c
  786. X
  787. Xbasename.o : basename.c
  788. X
  789. Xcomment.o : comment.c 
  790. X
  791. Xcrcdefs.o : crcdefs.c
  792. X
  793. Xgetfile.o : getfile.c zoomem.h
  794. X    $(CC) $(cswitch) $(extra) $*.c
  795. X
  796. Xmachine.o : machine.c nixtime.i
  797. X    $(CC) $(cswitch) $(extra) $*.c
  798. X
  799. Xmakelist.o : makelist.c
  800. X
  801. Xmisc.o : misc.c 
  802. X
  803. Xmisc2.o : misc2.c zoomem.h
  804. X    $(CC) $(cswitch) $(extra) $*.c
  805. X
  806. Xoptions.o : options.c
  807. X
  808. Xnextfile.o :  nextfile.c
  809. X
  810. Xneeded.o : needed.c
  811. X
  812. Xparse.o : parse.c
  813. X
  814. Xportable.o : portable.c
  815. X
  816. Xprterror.o : prterror.c
  817. X
  818. Xzoo.o :   zoo.c zoomem.h errors.i
  819. X    $(CC) $(cswitch) $(extra) $*.c
  820. X
  821. Xzooadd.o : zooadd.c 
  822. X
  823. Xzooadd2.o : zooadd2.c
  824. X
  825. Xzoodel.o : zoodel.c 
  826. X
  827. Xzooext.o : zooext.c  errors.i
  828. X    $(CC) $(cswitch) $(extra) $*.c
  829. X
  830. Xzoolist.o : zoolist.c 
  831. X
  832. Xzoopack.o : zoopack.c 
  833. SHAR_EOF
  834. fi
  835. if test -f 'makelist.c'
  836. then
  837.     echo shar: "will not over-write existing file 'makelist.c'"
  838. else
  839. sed 's/^X//' << \SHAR_EOF > 'makelist.c'
  840. X#ifndef LINT
  841. X/* @(#) makelist.c 1.21 87/05/30 18:50:05 */
  842. Xstatic char sccsid[]="@(#) makelist.c 1.21 87/05/30 18:50:05";
  843. X#endif /* LINT */
  844. X
  845. X/*
  846. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  847. X*/
  848. X
  849. X#include "options.h"
  850. X#include "portable.h"
  851. X#include "errors.i"
  852. X
  853. X/* for low-level I/O */
  854. X#ifdef NOFCNTL
  855. X#include <file.h>
  856. X#else
  857. X#include <fcntl.h>
  858. X#endif
  859. X
  860. X#ifdef FLAT
  861. X#include <types.h>
  862. X#include <stat.h>
  863. X#else
  864. X#include <sys/types.h>
  865. X#include <sys/stat.h>
  866. X#endif
  867. X
  868. X#include "zoo.h"
  869. X#include <stdio.h>
  870. X#include "various.h"
  871. X
  872. X#include "zoofns.h"
  873. X#include "assert.h"
  874. X#include "debug.h"
  875. X
  876. X#ifdef LINT_ARGS
  877. Xchar *nameptr (char *);
  878. X#else
  879. Xchar *nameptr();
  880. X#endif
  881. X
  882. X/*******************/
  883. X/*
  884. Xmakelist() gets all pathnames corresponding to a set of filespecs and
  885. Xadds them to a list.  Not more than "flistsize" pathnames are added.
  886. XInto `longest' it returns the length of the longest name added, or
  887. Xzero if none added.
  888. X
  889. XFiles ignore1, ignore2, and ignore3 are not added to the list.
  890. XA file that is a device/directory is also not added to the list.
  891. X
  892. XHowever, if ignore1 is NULL, both these tests are skipped and all files
  893. Xwill be added to the list.
  894. X*/
  895. X
  896. Xvoid makelist (argc, argv, flist, flistsize, ignore1, ignore2, ignore3, longest)
  897. Xint argc;               /* number of filespec supplied */
  898. Xchar *argv[];           /* array of pointers to supplied filespecs */
  899. Xregister char *flist[]; /* array of pointers to filenames we will add */
  900. Xint flistsize;          /* home many names we can use */
  901. Xchar *ignore1, *ignore2, *ignore3; /* files to exclude from list */
  902. Xint *longest;        /* length of longest name in list */
  903. X{
  904. X   char *this_path;        /* current pathname */
  905. X   int fptr;               /* pointer to within flist */
  906. X   register int i, j;      /* loop counters */
  907. X   char *pat_name;         /* filename part of pattern */
  908. X   int gap;                /* for Shell sort */
  909. X   
  910. X   flistsize--;            /* allow for one terminating NULL entry */
  911. X   fptr = *longest = 0;
  912. X
  913. X   assert(argc > 0);
  914. X
  915. X#define WCLEN    4    /* length needed for wildcard, and a little extra */
  916. X
  917. X   while (argc > 0) {
  918. X#ifdef WILDCARD
  919. X        int argok = 0;                                            /* arg not matched yet */
  920. X#endif
  921. X      char *this_arg;
  922. X        this_arg = emalloc (strlen (*argv) + WCLEN);
  923. X        strcpy (this_arg, *argv);
  924. X
  925. X      /* Initialize fileset 0.  Select all files -- we will later
  926. X             filter out the ones wanted */
  927. X#ifdef FOLD
  928. X      strlwr (this_arg);
  929. X#endif
  930. X      pat_name = strdup (nameptr (this_arg));        /* pattern without path */
  931. X
  932. X#ifdef WILDCARD
  933. X        /* 
  934. X        replace filename by wildcard;  however, if argument ends in slash, 
  935. X        then simply append wildcard so we get all files in that directory
  936. X        */
  937. X#ifdef FORCESLASH
  938. X            fixslash (this_arg);                /* convert backslashes to slashes */
  939. X#endif
  940. X
  941. X        if (*lastptr(this_arg) == *PATH_CH) {
  942. X            strcat (this_arg, WILDCARD);
  943. X            pat_name = "*";                    /* and select all files */
  944. X        } else
  945. X          strcpy (nameptr (this_arg), WILDCARD);
  946. X#endif
  947. X
  948. X      nextfile (0, this_arg, 0);
  949. X      while (fptr < flistsize && 
  950. X            (this_path = nextfile(1, (char *) NULL, 0)) != NULL) {
  951. X         char *this_name = nameptr (this_path);
  952. X            modpath (this_path);                    /* do any needed changes to path */
  953. X
  954. X#ifdef IGNORECASE
  955. X#define    COMPARE    strcmpi
  956. X#else
  957. X#define    COMPARE    strcmp
  958. X#endif
  959. X            if (ignore1 != NULL) {
  960. X                if (!COMPARE(this_name,ignore1)  ||    /* exclude ignored files */
  961. X                     !COMPARE(this_name,ignore2)  ||
  962. X                     !COMPARE(this_name,ignore3))
  963. X                    continue;
  964. X#ifdef CHEKDIR
  965. X                {
  966. X                    int skip, han;  
  967. X                    han=OPEN(this_path, F_READ);
  968. X                    skip = isadir(han);  close(han);
  969. X                    if (skip)
  970. X                        continue;
  971. X                }
  972. X#endif
  973. X      
  974. X#ifdef CHEKUDIR
  975. X                if (isuadir(this_path))
  976. X                    continue;
  977. X#endif
  978. X            } /* end if ignore1 ! = NULL */
  979. X
  980. X/* 
  981. XIf WILDCARD is defined (e.g. AmigaDOS, MS-DOS), then nextfile() returns 
  982. Xall filenames and we must now select the ones we need by pattern matching.  
  983. XIf WILDCARD is not defined (e.g. **IX), filenames have already been selected 
  984. Xby the shell and need not be tested again.
  985. X*/
  986. X#ifdef WILDCARD
  987. X            if (match_half (this_name,pat_name) ||
  988. X                match_half (pat_name, "?-?") &&     /* character range */
  989. X                    *this_name >= *pat_name && *this_name <= pat_name[2])
  990. X#endif
  991. X            {
  992. X#ifdef WILDCARD
  993. X                argok = 1;                                    /* remember arg matched */
  994. X#endif
  995. X                flist[fptr++] = strdup (this_path);
  996. X                if (*longest < strlen(this_path))
  997. X                    *longest = strlen(this_path);
  998. X            }
  999. X
  1000. X        } /* end while */
  1001. X#ifdef WILDCARD
  1002. X        if (argok == 0) {                                    /* no match for argument */
  1003. X            prterror ('e', "Could not open %s\n", *argv);
  1004. X        }
  1005. X#endif
  1006. X      argc--;
  1007. X      argv++;
  1008. X   }
  1009. X   /* fptr is now 1 + index of last item in array */
  1010. X
  1011. X   if (this_path != NULL && fptr >= flistsize)
  1012. X      prterror ('w', too_many_files, flistsize);
  1013. X#ifndef  DONT_SORT
  1014. X   /* Shell sort -- K&R p. 58 */
  1015. X   for (gap = fptr/2; gap > 0; gap /= 2)
  1016. X      for (i = gap; i < fptr; i++)
  1017. X         for (j = i - gap; j >= 0 && 
  1018. X            strcmp(flist[j],flist[j+gap]) > 0; j -= gap) {
  1019. X            char *t = flist[j]; flist[j] = flist[j+gap]; flist[j+gap] = t;
  1020. X         }
  1021. X#endif /* DONT_SORT */
  1022. X
  1023. X   fptr--;     /* fptr is now index of last item in array */
  1024. X
  1025. X   /* Remove duplicates */
  1026. X   for (i = 0; i < fptr; i++) {
  1027. X      while (i<fptr && COMPARE(flist[i],flist[i+1]) == 0) {
  1028. X         for (j = i; j < fptr; j++)
  1029. X            flist[j] = flist[j+1];
  1030. X         fptr--;
  1031. X      }
  1032. X   }
  1033. X
  1034. X   flist[++fptr] = NULL;      /* NULL entry terminates list */
  1035. X}
  1036. X
  1037. X/*******
  1038. Xmodpath() makes any changes needed before pathname is stored;
  1039. Xcurrently these could involve folding it to lower case and
  1040. Xconverting backslashes to forward slashes
  1041. X*/
  1042. X
  1043. Xmodpath (path)
  1044. Xchar *path;
  1045. X{
  1046. X#ifdef FOLD
  1047. X    strlwr (path);
  1048. X#endif
  1049. X
  1050. X#ifdef FORCESLASH
  1051. X    fixslash (path);                /* convert backslashes to slashes */
  1052. X#endif
  1053. X}
  1054. SHAR_EOF
  1055. fi
  1056. if test -f 'misc.c'
  1057. then
  1058.     echo shar: "will not over-write existing file 'misc.c'"
  1059. else
  1060. sed 's/^X//' << \SHAR_EOF > 'misc.c'
  1061. X#ifndef LINT
  1062. X/* @(#) misc.c 1.7 87/05/03 15:59:33 */
  1063. Xstatic char sccsid[]="@(#) misc.c 1.7 87/05/03 15:59:33";
  1064. X#endif /* LINT */
  1065. X
  1066. X/*
  1067. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  1068. X*/
  1069. X#include "options.h"
  1070. X/* Miscellaneous functions needed by Zoo but not by Ooz */
  1071. X
  1072. X#include "zoo.h"
  1073. X#include <stdio.h>
  1074. X#include "various.h"
  1075. X
  1076. X#include "errors.i"
  1077. X#include "zoofns.h"
  1078. X#ifndef NOSIGNAL
  1079. X#include <signal.h>
  1080. X#endif
  1081. X
  1082. X#ifdef NEEDCTYP
  1083. X#include <ctype.h>
  1084. X#endif
  1085. X
  1086. X/*
  1087. Xcalc_ofs() is given a string that (supposedly) begins with a string
  1088. Xof digits.  It returns a corresponding numeric value.  If no such
  1089. Xstring, it returns zero.
  1090. X*/
  1091. Xlong calc_ofs(str)
  1092. Xchar *str;
  1093. X{
  1094. X   long retval;
  1095. X   int status;
  1096. X   char *p;
  1097. X   retval = 0L;
  1098. X   p = str; /* save for error message */
  1099. X   while (isdigit(*str)) {
  1100. X      retval = retval * 10L + (*str-'0');
  1101. X      str++;
  1102. X   }
  1103. X   if (*str != '\0')
  1104. X      prterror ('f', "Invalid number %s\n", p);
  1105. X   return (retval);
  1106. X}
  1107. X
  1108. X/*
  1109. Xchoosefname() decides which filename to use.  If a long filename is present,
  1110. Xand if the syntax is that of UNIX, MS-DOS or the portable form, we use it;
  1111. Xelse we use the short filename. 
  1112. X*/
  1113. X
  1114. Xchar *choosefname(direntry)
  1115. Xstruct direntry *direntry;
  1116. X{
  1117. X   char *retptr;                 /* pointer to name that we will return */
  1118. X   switch (direntry->system_id) {
  1119. X      case SYSID_NIX:
  1120. X      case SYSID_PORTABLE:
  1121. X      case SYSID_MS:
  1122. X         retptr = (direntry->namlen > 0) ? direntry->lfname : direntry->fname;
  1123. X         break;
  1124. X      default:
  1125. X         retptr = direntry->fname;
  1126. X         break;
  1127. X   }
  1128. X   return (retptr);
  1129. X} /* choosefname() */
  1130. X
  1131. X/* 
  1132. Xcombine() combines a directory name and a filename, making sure the
  1133. Xtwo are separated by a path separator 
  1134. X*/
  1135. Xchar *combine(result, dirname, fname)
  1136. Xchar result[], *dirname, *fname;
  1137. X{
  1138. X   *result = '\0';
  1139. X   if (*dirname != '\0') {
  1140. X      strcpy(result, dirname);
  1141. X      if (*lastptr(result) != *PATH_CH)
  1142. X         strcat(result, PATH_CH);
  1143. X   }
  1144. X   strcat(result, fname);
  1145. X   return (result);
  1146. X}
  1147. X
  1148. X/*
  1149. Xfullpath() accepts a pointer to a directory entry and returns the
  1150. Xcombined directory name + filename.  The long filename is used
  1151. Xif available, else the short filename is used.
  1152. X*/
  1153. Xchar *fullpath (direntry)
  1154. Xstruct direntry *direntry;
  1155. X{
  1156. X    static char result[PATHSIZE];
  1157. X    combine (result,
  1158. X                direntry->dirlen > 0 ? direntry->dirname : "", 
  1159. X                (direntry->namlen > 0) ? direntry->lfname : direntry->fname
  1160. X              );
  1161. X    return (result);
  1162. X}
  1163. X
  1164. X/* 
  1165. Xver_too_high returns true if version of provided archive header is
  1166. Xtoo high for us to manipulate archive 
  1167. X*/
  1168. X
  1169. Xint ver_too_high (header)
  1170. Xstruct zoo_header *header;
  1171. X{
  1172. X   return (header->major_ver > MAJOR_VER ||
  1173. X            (header->major_ver == MAJOR_VER &&
  1174. X             header->minor_ver > MINOR_VER));
  1175. X}
  1176. X
  1177. X/* 
  1178. Xrwheader() reads archive header, checks consistency, makes sure its
  1179. Xversion number is not too high, updates it if too low, and seeks to
  1180. Xbeginning of first directory entry 
  1181. X*/
  1182. X
  1183. Xrwheader (header, zoo_file)
  1184. Xregister struct zoo_header *header;
  1185. XFILE *zoo_file;
  1186. X{
  1187. X
  1188. X   frd_zooh (header, zoo_file);
  1189. X
  1190. X   if ((header->zoo_start + header->zoo_minus) != 0L)
  1191. X      prterror ('f', failed_consistency);
  1192. X   if (ver_too_high (header))
  1193. X      prterror ('f', wrong_version, header->major_ver, header->minor_ver);
  1194. X
  1195. X   /* We reach here if the archive version is not too high.  Now, if it
  1196. X   isn't the same as ours, we bring it up to ours so the modified archive 
  1197. X   will be safe from previous versions of Zoo */
  1198. X
  1199. X   if (header->major_ver != MAJOR_VER || header->minor_ver != MINOR_VER) {
  1200. X      header->major_ver = MAJOR_VER;
  1201. X      header->minor_ver = MINOR_VER;
  1202. X      fseek (zoo_file, 0L, 0);            /* seek to beginning */
  1203. X      fwr_zooh (header, zoo_file);
  1204. X   }
  1205. X   fseek (zoo_file, header->zoo_start, 0); /* seek to where data begins */
  1206. X} /* rwheader */
  1207. X
  1208. X/*
  1209. Xwritedir() write a directory entry with keyboard interrupt disabled
  1210. X*/
  1211. Xvoid writedir (direntry, zoo_file)
  1212. Xstruct direntry *direntry;
  1213. XFILE *zoo_file;
  1214. X{
  1215. X#ifndef NOSIGNAL  
  1216. X   int (*oldsignal)();
  1217. X   oldsignal = signal (SIGINT, SIG_IGN);
  1218. X#endif
  1219. X   if (fwr_dir (direntry, zoo_file) == -1)
  1220. X      prterror ('f', disk_full);
  1221. X#ifndef NOSIGNAL
  1222. X   signal (SIGINT, oldsignal);
  1223. X#endif
  1224. X}
  1225. X
  1226. X/* 
  1227. Xreaddir() reads a directory entry from an archive.  If the directory
  1228. Xentry is invalid and if fail is 1, it causes a fatal error;
  1229. Xelse it returns.  Return value is 0 if no error else -1;
  1230. X*/
  1231. X
  1232. Xint readdir (direntry, zoo_file, fail)    /* read directory entry */
  1233. Xregister struct direntry *direntry;
  1234. XFILE *zoo_file;
  1235. Xint fail;                              /* 0 -> return, 1 -> abort on error */
  1236. X{
  1237. X   if (frd_dir (direntry, zoo_file) < 0) {
  1238. X      if (fail)
  1239. X         prterror ('f', bad_directory);
  1240. X      else
  1241. X         return (-1);
  1242. X   }
  1243. X   if (direntry->zoo_tag != ZOO_TAG) {
  1244. X      if (fail)
  1245. X         prterror ('f', bad_directory);
  1246. X      else
  1247. X         return (-1);
  1248. X   }
  1249. X   return (0);
  1250. X}
  1251. X
  1252. X/* use pointer version below */
  1253. X#ifdef COMMENT
  1254. X/* instr() searches a string for a substring */
  1255. Xinstr (s, t)      /* return index of string t in string s, -1 if none */
  1256. Xchar s[], t[];    /*  .. from K&R page 67 */
  1257. X{
  1258. X   int i;
  1259. X   register int j, k;
  1260. X   for (i = 0; s[i] != '\0'; i++) {
  1261. X      for (j = i, k = 0; t[k] != '\0' && s[j]==t[k]; j++, k++)
  1262. X         ;
  1263. X      if (t[k] == '\0')
  1264. X         return (i);
  1265. X   }
  1266. X   return (-1);
  1267. X}
  1268. X#endif COMMENT
  1269. X
  1270. X/* instr() searches a string for a substring */
  1271. X/* from J. Brian Waters */
  1272. Xint instr (s, t)           /* return the position of t in s, -1 if none */
  1273. Xchar *s, *t;                /*  a pointer version of K&R index function p.67 */
  1274. X{               /* renamed to instr() to avoid conflicts with C RTL - JBW */
  1275. X
  1276. X   register char *i, *j, *k;
  1277. X
  1278. X   for (i = s; *i; i++) {
  1279. X      for (j = i, k = t; (*k) && (*j++ == *k); k++)
  1280. X         ;
  1281. X       if (!*k)
  1282. X         return ((int) (i - s));
  1283. X   }
  1284. X   return(-1);
  1285. X}
  1286. X
  1287. X/* cfactor() calculates the compression factor given a directory entry */
  1288. Xint cfactor (org_size, size_now)
  1289. Xlong org_size, size_now;
  1290. X{
  1291. X   register int size_factor;
  1292. X   if ((unsigned long) org_size > 1000000) { /* avoid later overflow */
  1293. X      org_size = (unsigned long) org_size / 1024;
  1294. X      size_now = (unsigned long) size_now / 1024;
  1295. X   }
  1296. X   if (org_size == 0)         /* avoid division by zero */
  1297. X      size_factor = 0;
  1298. X   else {
  1299. X      size_factor = 
  1300. X         (
  1301. X            (1000 * 
  1302. X               ((unsigned long) org_size - (unsigned long) size_now)
  1303. X            ) / org_size + 5
  1304. X         ) / 10;
  1305. X   }
  1306. X   return (size_factor);
  1307. X}
  1308. X
  1309. X#ifndef STRDUP
  1310. X/***********
  1311. Xstrdup() duplicates a string using dynamic memory.
  1312. X*/
  1313. X
  1314. Xchar *strdup (str)
  1315. Xregister char *str;
  1316. X{
  1317. X   return (strcpy (emalloc (strlen(str)+1), str));
  1318. X}
  1319. X#endif /* STRDUP */
  1320. X
  1321. X/**************
  1322. Xcmpnum() compares two pairs of unsigned integers and returns a negative,
  1323. Xzero, or positive value as the comparison yields less than, equal, or
  1324. Xgreater than result.  Each pair of unsigned integers is considered to be the
  1325. Xmore significant and the less significant half of a longer unsigned number.
  1326. X
  1327. XNote:  cmpnum is used to compare dates and times.
  1328. X*/
  1329. X
  1330. Xint cmpnum (hi1, lo1, hi2, lo2)
  1331. Xregister unsigned int hi1, hi2;
  1332. Xunsigned int lo1, lo2;
  1333. X{
  1334. X   if (hi1 != hi2)
  1335. X      return ((int) hi1 - hi2);
  1336. X   else
  1337. X      return ((int) lo1 - lo2);
  1338. X}
  1339. X
  1340. X/*******************/
  1341. X/* writenull() */
  1342. X/* writes a null directory entry to the archive whose handle is supplied */
  1343. Xvoid writenull(handle, length)
  1344. Xint handle, length;
  1345. X{
  1346. X#ifndef NOSIGNAL
  1347. X   int (*oldsignal)();
  1348. X#endif
  1349. X   struct direntry newentry;
  1350. X   memset ((char *) &newentry, 0, sizeof (newentry));
  1351. X   newentry.zoo_tag = ZOO_TAG;
  1352. X   newentry.type = 2;
  1353. X   /* Force entry to be the required length plus possibly 2 stray bytes
  1354. X   by dividing up the needed padding into dirlen and namlen. */
  1355. X   if (length > SIZ_DIRL)
  1356. X      newentry.dirlen = newentry.namlen = (length-SIZ_DIRL)/2 + 2;
  1357. X   else
  1358. X      newentry.dirlen = newentry.namlen = 0;
  1359. X#ifndef NOSIGNAL
  1360. X   oldsignal = signal (SIGINT, SIG_IGN);
  1361. X#endif
  1362. X   if (wr_dir (&newentry, handle) == -1)
  1363. X      prterror ('f', disk_full);
  1364. X#ifndef NOSIGNAL
  1365. X   signal (SIGINT, oldsignal);
  1366. X#endif
  1367. X}
  1368. X
  1369. X#ifdef FORCESLASH
  1370. X/*******************/
  1371. X/*
  1372. Xfixslash() changes all "\" characters in the supplied string to "/".
  1373. X*/
  1374. X
  1375. Xvoid fixslash (str)
  1376. Xchar *str;
  1377. X{
  1378. X   register char *p;
  1379. X   for (p = str; *p != '\0'; p++)
  1380. X      if (*p == '\\')
  1381. X         *p = '/';
  1382. X}
  1383. X#endif /* FORCESLASH */
  1384. X
  1385. X/* Currently using portable directory I/O for MSC also */
  1386. X#ifdef COMMENT
  1387. X#ifndef PORTABLE  
  1388. X/* portable implementations are elsewhere */
  1389. X/***********************
  1390. XFunction fwr_dir() writes a directory entry to a FILE.  Return value is -1 on
  1391. Xerror, else 0.
  1392. X*/
  1393. Xint fwr_dir(direntry, zoo_file)
  1394. Xstruct direntry *direntry;
  1395. XFILE *zoo_file;
  1396. X{
  1397. X   if (fwrite ((char *) direntry, SIZ_DIR, 1, zoo_file) != 1)
  1398. X      return (-1);
  1399. X   else
  1400. X      return (0);
  1401. X}
  1402. X
  1403. X/***********************
  1404. XFunction wr_dir() writes a directory entry to a handle.  Return value is -1
  1405. Xon error else 0.
  1406. X*/
  1407. Xint wr_dir(direntry, zoo_han)
  1408. Xstruct direntry *direntry;
  1409. Xint zoo_han;
  1410. X{
  1411. X   if (write (zoo_han, (char *) direntry, SIZ_DIR) != SIZ_DIR)
  1412. X      return (-1);
  1413. X   else
  1414. X      return (0);
  1415. X}
  1416. X
  1417. X/***********************
  1418. XFunction wr_zooh() writes an archive header to a handle.  Return value -1 if
  1419. Xerror else 0.
  1420. X*/
  1421. Xint wr_zooh(zoo_header, zoo_han)
  1422. Xstruct zoo_header *zoo_header;
  1423. Xint zoo_han;
  1424. X{
  1425. X   if (write (zoo_han, (char *) zoo_header, SIZ_ZOOH) != SIZ_ZOOH)
  1426. X      return (-1);
  1427. X   else
  1428. X      return (0);
  1429. X}
  1430. X
  1431. X/***********************
  1432. XFunction fwr_zooh() writes an archive header to a FILE.  Return value is -1
  1433. Xif error else 0.
  1434. X*/
  1435. Xint fwr_zooh(zoo_header, zoo_file)
  1436. Xstruct zoo_header *zoo_header;
  1437. XFILE *zoo_file;
  1438. X{
  1439. X   if (fwrite ((char *) zoo_header, SIZ_ZOOH, 1, zoo_file) != 1)
  1440. X      return (-1);
  1441. X   else
  1442. X      return (0);
  1443. X}
  1444. X#endif /* end of not PORTABLE */
  1445. X#endif /* COMMENT */
  1446. X
  1447. SHAR_EOF
  1448. fi
  1449. if test -f 'misc2.c'
  1450. then
  1451.     echo shar: "will not over-write existing file 'misc2.c'"
  1452. else
  1453. sed 's/^X//' << \SHAR_EOF > 'misc2.c'
  1454. X#ifndef LINT
  1455. Xstatic char sccsid[]="@(#) misc2.c 1.8 87/05/29 12:54:33";
  1456. X#endif /* LINT */
  1457. X
  1458. X/*
  1459. XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  1460. X*/
  1461. X#include "options.h"
  1462. X/* Miscellaneous routines needed by both Zoo and Ooz */
  1463. X#ifdef NOFCNTL
  1464. X#include <file.h>
  1465. X#else
  1466. X#include <fcntl.h>
  1467. X#endif
  1468. X
  1469. X#ifdef FLAT
  1470. X#include <types.h>
  1471. X#include <stat.h>
  1472. X#else
  1473. X#include <sys/types.h>
  1474. X#include <sys/stat.h>
  1475. X#endif
  1476. X
  1477. X#include "portable.h"
  1478. X#include <stdio.h>
  1479. X#include "various.h"
  1480. X#include "zoofns.h"     /* only for malloc */
  1481. X#include "errors.i"
  1482. X#include "zoomem.h"
  1483. X#include "zoo.h"
  1484. X
  1485. X/**********************/
  1486. X/* memerr() */
  1487. X/* Give error message on memory error and abort */
  1488. Xvoid memerr()
  1489. X{
  1490. X#ifdef OOZ
  1491. X   prterror ('f', no_memory, "", "");
  1492. X#else
  1493. X   prterror ('f', no_memory);
  1494. X#endif
  1495. X}
  1496. X
  1497. X/**********************/
  1498. X/*
  1499. Xemalloc() allocates memory like malloc() does, except that it automatically
  1500. Xcalls the error function memerr() if memory couldn't be allocated.  It also
  1501. Xassumes (unless small memory allocation is being done) that memory will
  1502. Xnever be freed and conserves it by allocating memory in large chunks
  1503. Xand then partitioning it out with no administrative overhead.
  1504. X*/
  1505. X
  1506. Xchar *emalloc (size)
  1507. Xunsigned int size;
  1508. X{
  1509. X#define  BLOCK_SIZE  512      /* memory allocation granularity */
  1510. X
  1511. X#ifdef USE_MALLOC
  1512. X/* Pass on memory requests to malloc() */
  1513. X   char *ptr;
  1514. X   if ((ptr = malloc (size)) == NULL)
  1515. X      memerr();
  1516. X   return (ptr);
  1517. X#else
  1518. X   static char *memptr;
  1519. X   static unsigned avail = 0;
  1520. X   unsigned malloc_incr;
  1521. X   char *retval;
  1522. X
  1523. X   if (size == 0)
  1524. X      return (NULL);
  1525. X
  1526. X   /* if not enough space avail get some more */
  1527. X   if (avail < size) {
  1528. X      malloc_incr = BLOCK_SIZE;
  1529. X      if (malloc_incr < size)
  1530. X         malloc_incr = size;
  1531. X      while (malloc_incr >= size && (memptr = malloc (malloc_incr)) == NULL)
  1532. X         malloc_incr = (malloc_incr / 6) * 5;
  1533. X      avail = malloc_incr;
  1534. X   }
  1535. X
  1536. X   if (avail < size)
  1537. X      memerr();
  1538. X   else {
  1539. X      retval = memptr;
  1540. X      memptr += size;
  1541. X      avail -= size;
  1542. X      return (retval);
  1543. X   }
  1544. X#endif  /* end of not USE_MALLOC */
  1545. X}
  1546. X
  1547. X/**********************/
  1548. X/* putstr()
  1549. XThis function prints a string to standard output without using printf().
  1550. XIf a null string, nothing is printed (not even the null character).
  1551. X*/
  1552. Xputstr (str)
  1553. Xregister char *str;
  1554. X{
  1555. X   if (str == NULL)
  1556. X      return;
  1557. X   while (*str) {
  1558. X      fputchar (*str++);
  1559. X   }
  1560. X}
  1561. X
  1562. X/**********************/
  1563. X/* exists()
  1564. XThis function checks the existence of a file.  
  1565. X
  1566. XIf the symbol EXISTS is defined, that is called as a macro and
  1567. Xsupplied the filename.  It must return 1 if the file exists and
  1568. X0 if it does not.
  1569. X
  1570. XIf EXISTS is not defined, exists() tests to see if the file can be 
  1571. Xopened for either reading or writing;  if so, it returns 1 else it 
  1572. Xreturns 0. 
  1573. X
  1574. XBecause of the delay between the time existence is checked and the time Zoo
  1575. Xcreates a files, a race condition exists.  It would be better to
  1576. Xuse open() with the O_EXCL flag but that will not work for many
  1577. Xsystems.
  1578. X*/
  1579. X
  1580. Xint exists (fname)
  1581. Xchar *fname;
  1582. X{
  1583. X#ifdef EXISTS
  1584. X    return EXISTS(fname);
  1585. X#else
  1586. X   int han;
  1587. X
  1588. X#ifdef PORTABLE
  1589. X   if ((han = OPEN(fname,F_READ)) != -1 || (han = OPEN(fname,F_WRITE)) != -1)
  1590. X#else
  1591. X   /* Under MS-DOS, all files are readable */
  1592. X   if ((han = OPEN(fname,F_READ)) != -1)
  1593. X#endif /* ifdef PORTABLE */
  1594. X    {
  1595. X      close (han);
  1596. X      return (1);
  1597. X   } else
  1598. X      return (0);
  1599. X#endif /* ifdef EXISTS */
  1600. X}
  1601. X
  1602. X/************************************************************************
  1603. XThe following MS-DOS-specific functions read directory entries and zoo
  1604. Xheaders.  Portable versions are elsewhere.
  1605. X
  1606. XNote:  At some future time, it will be better to make the MS-DOS versions
  1607. Xof these into macros.
  1608. X*/
  1609. X
  1610. X/* Currently using portable I/O for MSC too */
  1611. X#ifdef COMMENT
  1612. X#ifndef PORTABLE
  1613. X/**********************
  1614. XFunction frd_zooh() reads the header of a Zoo archive from a FILE.
  1615. X*/
  1616. Xint frd_zooh(zoo_header, zoo_file)
  1617. Xstruct zoo_header *zoo_header;
  1618. XFILE *zoo_file;
  1619. X{
  1620. X   if (fread ((char *) zoo_header, SIZ_ZOOH, 1, zoo_file) != 1)
  1621. X      return (-1);
  1622. X   else
  1623. X      return (0);
  1624. X}
  1625. X
  1626. X/**********************
  1627. XFunction frd_dir() reads a directory entry from a FILE.
  1628. X*/
  1629. Xint frd_dir(direntry, zoo_file)
  1630. Xstruct direntry *direntry;
  1631. XFILE *zoo_file;
  1632. X{
  1633. X   if (fread ((char *) direntry, SIZ_DIR, 1, zoo_file) != 1)
  1634. X      return (-1);
  1635. X   else
  1636. X      return (0);
  1637. X}
  1638. X
  1639. X/**********************
  1640. XFunction rd_zooh() reads a Zoo archive header from a file handle.
  1641. X*/
  1642. Xint rd_zooh (header, zoo_han)
  1643. Xstruct zoo_header *header;
  1644. Xint zoo_han;
  1645. X{
  1646. X   return (read (zoo_han, (char *) header, SIZ_ZOOH));
  1647. X}
  1648. X
  1649. X/**********************
  1650. XFunction rd_dir() reads a directory entry from a file handle */
  1651. Xint rd_dir(direntry, zoo_han)
  1652. Xstruct direntry *direntry;
  1653. Xint zoo_han;
  1654. X{
  1655. X   return (read (zoo_han, (char *) direntry, SIZ_DIR));
  1656. X}
  1657. X
  1658. X#endif /* end of not PORTABLE */
  1659. X#endif /* COMMENT */
  1660. X
  1661. X/****************
  1662. Xnewcat() allocates enough space to concatenate two strings then returns
  1663. Xa pointer to the concatenated result */
  1664. X
  1665. Xchar *newcat (r, s)
  1666. Xchar *r, *s;
  1667. X{
  1668. X   char *temp = emalloc (strlen (r) + strlen (s) + 2); /* 1 spare */
  1669. X   strcpy (temp, r);
  1670. X   strcat (temp, s);
  1671. X   return (temp);
  1672. X}
  1673. X
  1674. X
  1675. X/* Creates a path */
  1676. Xint makepath(path)
  1677. Xchar *path;
  1678. X{
  1679. X   char tmppath[PATHSIZE];
  1680. X   char *slashpos;
  1681. X   if (path == NULL)
  1682. X      return;
  1683. X   while (*lastptr(path) == *PATH_CH)     /* remove trailing slashes */
  1684. X      *lastptr(path) = '\0';
  1685. X   if (*path == '\0')
  1686. X      return;
  1687. X
  1688. X   slashpos = findlast(path, PATH_CH);    /* find last slash */
  1689. X   if (slashpos == NULL) {                /* if not, just create dir. */
  1690. X      MKDIR(path);
  1691. X      return;
  1692. X   } else {                               /* otherwise...         */
  1693. X      if (slashpos == path) {             /* if leading slash */
  1694. X         MKDIR(slashpos);                 /* make that directory */
  1695. X         return;                          /* and done */
  1696. X      } else {
  1697. X         strcpy(tmppath,path);            /* save path */
  1698. X         *slashpos = '\0';                /* split into prefix & suffix */
  1699. X#ifdef DEBUG
  1700. X         printf("making path from [%s]\n", path);
  1701. X#endif
  1702. X         makepath(path);                     /* make path from prefix */
  1703. X#ifdef DEBUG
  1704. X         printf("making dir from [%s]\n", tmppath);
  1705. X#endif
  1706. X         MKDIR(tmppath);                  /* make dir from suffix */
  1707. X      }
  1708. X   }
  1709. X} /* makepath() */
  1710. X
  1711. X/*
  1712. XIf no extension in filename add supplied extension
  1713. X*/
  1714. Xchar *addext (fname, ext)
  1715. Xchar *fname;
  1716. Xchar *ext;
  1717. X{
  1718. X   if (strchr (nameptr (fname), EXT_CH) == NULL)
  1719. X      return (newcat (fname, ext));
  1720. X   else
  1721. X      return (fname);
  1722. X}
  1723. SHAR_EOF
  1724. fi
  1725. if test -f 'mkbsd'
  1726. then
  1727.     echo shar: "will not over-write existing file 'mkbsd'"
  1728. else
  1729. sed 's/^X//' << \SHAR_EOF > 'mkbsd'
  1730. X# @(#) mkbsd 1.2 87/05/03 15:59:46
  1731. X#4.3BSD -- make Zoo and Fiz
  1732. Xmake "cswitch=-c -O -DBSD4_3" "ldswitch = -o zoo" zoo
  1733. Xmake "cswitch=-c -O -DBSD4_3" "ldswitch = -o fiz" fiz
  1734. SHAR_EOF
  1735. fi
  1736. if test -f 'mkgenric'
  1737. then
  1738.     echo shar: "will not over-write existing file 'mkgenric'"
  1739. else
  1740. sed 's/^X//' << \SHAR_EOF > 'mkgenric'
  1741. X# @(#) mkgenric 1.2 87/05/03 15:59:48
  1742. X#Generic Zoo and Fiz
  1743. Xmake "cswitch=-c -O -DGENERIC" "ldswitch = -o zoo" zoo
  1744. Xmake "cswitch=-c -O -DGENERIC" "ldswitch = -o fiz" fiz
  1745. SHAR_EOF
  1746. fi
  1747. if test -f 'mksysv'
  1748. then
  1749.     echo shar: "will not over-write existing file 'mksysv'"
  1750. else
  1751. sed 's/^X//' << \SHAR_EOF > 'mksysv'
  1752. X# @(#) mksysv 1.2 87/05/03 15:59:51
  1753. X#System V
  1754. Xmake "cswitch=-c -O -DSYS_V" "ldswitch=-s -o zoo" zoo
  1755. Xmake "cswitch=-c -O -DSYS_V" "ldswitch=-s -o fiz" fiz
  1756. SHAR_EOF
  1757. fi
  1758. if test -f 'mksysvsh'
  1759. then
  1760.     echo shar: "will not over-write existing file 'mksysvsh'"
  1761. else
  1762. sed 's/^X//' << \SHAR_EOF > 'mksysvsh'
  1763. X# @(#) mksysvsh 1.3 87/06/04 12:38:45
  1764. X#This script first calls `mksysvsh' to build zoo and fiz without
  1765. X#the shared libraries.  Then it deletes zoo and fiz and reloads
  1766. X#them with the shared libraries.
  1767. Xsh mksysv
  1768. X/bin/rm -f zoo fiz
  1769. Xmake CC=ld ldswitch="/lib/crt0s.o /lib/shlib.ifile -o zoo" zoo
  1770. Xmake CC=ld ldswitch="/lib/crt0s.o /lib/shlib.ifile -o fiz" fiz
  1771. SHAR_EOF
  1772. fi
  1773. if test -f 'mkuport'
  1774. then
  1775.     echo shar: "will not over-write existing file 'mkuport'"
  1776. else
  1777. sed 's/^X//' << \SHAR_EOF > 'mkuport'
  1778. X# @(#) mkuport 1.3 87/05/03 15:59:55
  1779. X#Microport UNIX on AT.  -Ml = large memory model.
  1780. Xmake "cswitch = -O -c -Ml -DSYS_V" "ldswitch = -Ml -o zoo" zoo
  1781. Xmake "cswitch = -O -c -Ml -DSYS_V" "ldswitch = -Ml -o fiz" fiz
  1782. SHAR_EOF
  1783. fi
  1784. if test -f 'mkx68'
  1785. then
  1786.     echo shar: "will not over-write existing file 'mkx68'"
  1787. else
  1788. sed 's/^X//' << \SHAR_EOF > 'mkx68'
  1789. X# @(#) mkx68 1.2 87/05/03 15:59:58
  1790. X#Radio Shack Model 16 with Xenix/68000 3.01.01. "-DM_VOID" tells not 
  1791. X#to try to do a typedef of `void'. "-Dvoid=int" because compiler doesn't 
  1792. X#know about `void'.  `-s -n' strips and makes it shareable.
  1793. Xmake "cswitch=-c -O -DSYS_V -DM_VOID -Dvoid=int" "ldswitch=-s -n -o zoo" zoo
  1794. Xmake "cswitch=-c -O -DSYS_V -DM_VOID -Dvoid=int" "ldswitch=-s -n -o fiz" fiz
  1795. SHAR_EOF
  1796. fi
  1797. if test -f 'mkx86'
  1798. then
  1799.     echo shar: "will not over-write existing file 'mkx86'"
  1800. else
  1801. sed 's/^X//' << \SHAR_EOF > 'mkx86'
  1802. X# @(#) mkx86 1.4 87/06/04 12:33:47
  1803. X# Make Zoo and Fiz
  1804. X# This script is believed to work on:
  1805. X#    Xenix 3.4 on Greg Laskin's Intel 310/286
  1806. X#    SCO Xenix 2.2 on Robert Cliff's AT.
  1807. X#`-Ml' for large memory model, `-M2' to generate code for 80286 cpu,
  1808. X#`-F 8000' for 0x8000 bytes of stack space
  1809. Xmake "cswitch=-c -O -DSYS_V -Ml -M2" "ldswitch=-Ml -o zoo -F 8000" zoo
  1810. Xmake "cswitch=-c -O -DSYS_V -Ml -M2" "ldswitch=-Ml -o fiz" fiz
  1811. SHAR_EOF
  1812. fi
  1813. if test -f 'mstime.i'
  1814. then
  1815.     echo shar: "will not over-write existing file 'mstime.i'"
  1816. else
  1817. sed 's/^X//' << \SHAR_EOF > 'mstime.i'
  1818. X#ifndef LINT
  1819. Xstatic char mstimeid[]="@(#) mstime.i 1.2 87/05/03 16:00:02";
  1820. X#endif /* LINT */
  1821. X
  1822. X#define BASEYEAR 1970
  1823. X
  1824. X/****************
  1825. XFunction mstime() converts time in seconds since January 1 of BASEYEAR
  1826. Xto MS-DOS format date and time.
  1827. X*/
  1828. Xmstime(longtime, date, time)
  1829. Xlong longtime;       /* input:  seconds since Jan 1, BASEYEAR   */
  1830. Xint *date, *time;    /* output: MS-DOS format date and time */
  1831. X
  1832. X{
  1833. X   static int daysinmo[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  1834. X#define FEBRUARY 1
  1835. X   int year, month, day, hour, min, sec;
  1836. X   long secsinhour, secsinday, secsinyear, secsinleapyear;
  1837. X
  1838. X   int leapyear;                             /* is this a leap year? */
  1839. X   int done;                                 /* control variable */
  1840. X
  1841. X   secsinhour = (long) (60 * 60);            /* seconds in an hour */
  1842. X   secsinday  = 24 * secsinhour;             /* seconds in a day */
  1843. X   secsinyear = 365 * secsinday;             /* seconds in a year */
  1844. X   secsinleapyear = secsinyear + secsinday;  /* seconds in a leap year */
  1845. X
  1846. X#ifdef DEBUG
  1847. Xprintf("mstime:  input longtime = %ld\n", longtime);
  1848. X#endif
  1849. X
  1850. X   /* We can't handle dates before 1970 so force longtime positive */
  1851. X   if (longtime < 0)
  1852. X      longtime = 0;
  1853. X
  1854. X   /* 
  1855. X   Step through years from BASEYEAR onwards, subtracting number of
  1856. X   seconds in each, stopping just before longtime would become negative.
  1857. X   */
  1858. X   year = BASEYEAR;
  1859. X   done = 0;
  1860. X   while (!done) {
  1861. X      long yearlength;
  1862. X      leapyear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
  1863. X      if (leapyear)
  1864. X         yearlength = secsinleapyear;
  1865. X      else
  1866. X         yearlength = secsinyear;
  1867. X
  1868. X      if (longtime >= yearlength) {
  1869. X         longtime -= yearlength;
  1870. X         year++;
  1871. X      } else
  1872. X         done++;
  1873. X   }
  1874. X
  1875. X   /* Now `year' contains year and longtime contains remaining seconds */
  1876. X   daysinmo[FEBRUARY] = leapyear ? 29 : 28;
  1877. X
  1878. X   month = 0; /* range is 0:11 */
  1879. X   while (longtime > daysinmo[month] * secsinday) {
  1880. X      longtime = longtime - daysinmo[month] * secsinday;
  1881. X      month++;
  1882. X   }
  1883. X   month++; /* range now 1:12 */
  1884. X
  1885. X   day = longtime / secsinday;     /* day of month, range 0:30 */
  1886. X   longtime = longtime % secsinday;
  1887. X   day++;                         /* day of month, range 1:31 */
  1888. X
  1889. X   hour = longtime / secsinhour;       /* hours, range 0:23 */
  1890. X   longtime = longtime % secsinhour;
  1891. X
  1892. X   min = longtime / 60L;               /* minutes, range 0:59 */
  1893. X   longtime = longtime % 60L;
  1894. X
  1895. X   sec = longtime;                     /* seconds, range 0:59 */
  1896. X
  1897. X#ifdef DEBUG
  1898. Xprintf("mstime:  date = %4d/%02d/%02d   time = %02d:%02d:%02d\n",
  1899. X      year, month, day, hour, min, sec);
  1900. Xif (leapyear)
  1901. X   printf("(leap year)\n");
  1902. X#endif
  1903. X
  1904. X   if (year < 1980)
  1905. X      year = 1980;
  1906. X   *date = day + (month << 5) + ((year - 1980) << 9);
  1907. X   *time = (sec / 2) + (min << 5) + (hour << 11);
  1908. X}
  1909. SHAR_EOF
  1910. fi
  1911. exit 0
  1912. #    End of shell archive
  1913. -- 
  1914. Rahul Dhesi         UUCP:  {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi
  1915.  
  1916. -- 
  1917.  
  1918. Rich $alz
  1919. Cronus Project, BBN Labs            rsalz@bbn.com
  1920. Moderator, comp.sources.unix            sources@uunet.uu.net
  1921.