home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume23 / zip / part08 < prev    next >
Encoding:
Text File  |  1991-10-21  |  54.4 KB  |  1,815 lines

  1. Newsgroups: comp.sources.misc
  2. From: kirsch@usasoc.soc.mil (David Kirschbaum)
  3. Subject:  v23i095:  zip - Portable zip v1.0, Part08/09
  4. Message-ID: <1991Oct21.042237.8253@sparky.imd.sterling.com>
  5. X-Md4-Signature: bc22c8cab548726210a525d01abcccad
  6. Date: Mon, 21 Oct 1991 04:22:37 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: kirsch@usasoc.soc.mil (David Kirschbaum)
  10. Posting-number: Volume 23, Issue 95
  11. Archive-name: zip/part08
  12. Environment: UNIX, Minix, MSDOS, OS/2, VMS
  13.  
  14. #! /bin/sh
  15. # into a shell via "sh file" or similar.  To overwrite existing files,
  16. # type "sh file -c".
  17. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  18. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  19. # Contents:  im_bits.c im_lm.asm implode.c implode.h makefile.os2
  20. #   ship.def zip.h zipnote.c
  21. # Wrapped by kent@sparky on Sun Oct 20 22:58:56 1991
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 8 (of 9)."'
  25. if test -f 'im_bits.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'im_bits.c'\"
  27. else
  28.   echo shar: Extracting \"'im_bits.c'\" \(4743 characters\)
  29.   sed "s/^X//" >'im_bits.c' <<'END_OF_FILE'
  30. X/*
  31. X
  32. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  33. X Permission is granted to any individual or institution to use, copy, or
  34. X redistribute this software so long as all of the original files are included
  35. X unmodified, that it is not sold for profit, and that this copyright notice
  36. X is retained.
  37. X
  38. X*/
  39. X
  40. X/*
  41. X *  im_bits.c by Richard B. Wales & Jean-loup Gailly.
  42. X *
  43. X *  PURPOSE
  44. X *
  45. X *      Output variable-length bit strings.
  46. X *
  47. X *  DISCUSSION
  48. X *
  49. X *      The PKZIP "imploded" file format interprets compressed file data
  50. X *      as a sequence of bits.  Multi-bit strings in the file may cross
  51. X *      byte boundaries without restriction.
  52. X *
  53. X *      The first bit of each byte is the low-order bit.
  54. X *
  55. X *      The routines in this file allow a variable-length bit value to
  56. X *      be output right-to-left (useful for literal values). For
  57. X *      left-to-right output (useful for code strings from the tree routines),
  58. X *      the bits must have been reversed first with bi_reverse().
  59. X *
  60. X *  INTERFACE
  61. X *
  62. X *      ImpErr bi_init (FILE *fp)
  63. X *          Initialize the bit string routines and specify the output
  64. X *          file to be written to in subsequent calls.
  65. X *
  66. X *      ImpErr bi_rlout (int value, int length)
  67. X *          Write out a bit string, taking the source bits right to
  68. X *          left.
  69. X *
  70. X *      int bi_reverse (int value, int length)
  71. X *          Reverse the bits of a bit string, taking the source bits left to
  72. X *          right and emitting them right to left.
  73. X *
  74. X *      ImpErr bi_windup (void)
  75. X *          Write out any remaining bits in an incomplete byte.
  76. X */
  77. X
  78. X
  79. X#include "implode.h"
  80. X
  81. X
  82. X/***********************************************************************
  83. X *
  84. X * Local data used by the "bit string" routines.
  85. X */
  86. X
  87. X
  88. X/* Current file stream pointer. */
  89. Xlocal   FILE *  bi_fp;
  90. X
  91. Xlocal unsigned short bi_buf;
  92. X/* Output buffer. bits are inserted starting at the bottom (least significant
  93. X * bits).
  94. X */
  95. X
  96. X#define Buf_size (8 * 2*sizeof(char))
  97. X/* Number of bits used within bi_buf. (bi_buf might be implemented on
  98. X * more than 16 bits on some systems.)
  99. X */
  100. X
  101. Xlocal int bi_valid;                  /* number of valid bits in bi_buf */
  102. X/* All bits above the last valid bit are always zero.
  103. X */
  104. X
  105. X/* Output a 16 bit value to the bit stream, lower (oldest) byte first */
  106. X#define PUTSHORT(w) \
  107. X{  (void) zputc ((char)((w) & 0xff), bi_fp); \
  108. X   (void) zputc ((char)((US_INT)(w) >> 8), bi_fp); \
  109. X   if (ferror (bi_fp)) return IM_IOERR; \
  110. X}
  111. X
  112. X/* Output an 8 bit value to the bit stream, bits right to left */
  113. X#define PUTBYTE(w) \
  114. X{  (void) zputc ((char)((w) & 0xff), bi_fp); \
  115. X   if (ferror (bi_fp)) return IM_IOERR; \
  116. X}
  117. X
  118. X/***********************************************************************
  119. X *
  120. X * Initialize the bit string routines.
  121. X */
  122. X
  123. XImpErr
  124. Xbi_init (fp)
  125. X    FILE *fp;
  126. X{   if (fp == NULL)
  127. X    {   fprintf (stderr, "\nError in bi_init: null file pointer");
  128. X        return IM_LOGICERR;
  129. X    }
  130. X    bi_fp   = fp;
  131. X    bi_buf = 0;
  132. X    bi_valid = 0;
  133. X    return IM_OK;
  134. X}
  135. X
  136. X
  137. X/***********************************************************************
  138. X *
  139. X * Output bits from right to left.
  140. X */
  141. X
  142. XImpErr
  143. Xbi_rlout (value, length)
  144. X    int value;
  145. X    int length; /* must be <= 16 */
  146. X{
  147. X    /* Send value on length bits. If not enough room in bi_buf, use
  148. X     * (valid) bits from bi_buf and (16 - bi_valid) bits from value, leaving
  149. X     * (width - (16-bi_valid)) unused bits in value.
  150. X     */
  151. X    if (bi_valid > Buf_size - length) {
  152. X        bi_buf |= (value << bi_valid);
  153. X        PUTSHORT(bi_buf);
  154. X        bi_buf = (unsigned short)value >> (Buf_size - bi_valid);
  155. X        bi_valid += length - Buf_size;
  156. X    } else {
  157. X        bi_buf |= value << bi_valid;
  158. X        bi_valid += length;
  159. X    }
  160. X#ifdef  IMPDEBUG
  161. X    fprintf (stderr, " / ");
  162. X    while (length-- > 0)
  163. X    {
  164. X        putc ((value & 1) ? '1' : '0', stderr);
  165. X        value >>= 1;
  166. X    }
  167. X#endif  /* IMPDEBUG */
  168. X    return IM_OK;
  169. X}
  170. X
  171. X
  172. X/***********************************************************************
  173. X *
  174. X * Reverse the bits of a bit string, taking the source bits left to
  175. X * right (starting at 2^15) and emitting them right to left.
  176. X */
  177. X
  178. Xint
  179. Xbi_reverse (value, length)
  180. X    int value;
  181. X    int length;
  182. X{
  183. X    int result = 0;
  184. X    unsigned short lbit = 0x8000;
  185. X    unsigned short rbit = 1;
  186. X    while (length-- > 0) {
  187. X       if (value & lbit) result |= rbit;
  188. X       lbit >>= 1, rbit <<= 1;
  189. X    }
  190. X    return result;
  191. X}
  192. X
  193. X
  194. X/***********************************************************************
  195. X *
  196. X * Flush any remaining bits.
  197. X */
  198. X
  199. XImpErr
  200. Xbi_windup ()
  201. X{
  202. X    if (bi_valid > 8) {
  203. X        PUTSHORT(bi_buf);
  204. X    } else if (bi_valid > 0) {
  205. X        PUTBYTE(bi_buf);
  206. X    }
  207. X    bi_buf = 0;
  208. X    bi_valid = 0;
  209. X    return IM_OK;
  210. X}
  211. X
  212. X
  213. X/**********************************************************************/
  214. END_OF_FILE
  215.   if test 4743 -ne `wc -c <'im_bits.c'`; then
  216.     echo shar: \"'im_bits.c'\" unpacked with wrong size!
  217.   fi
  218.   # end of 'im_bits.c'
  219. fi
  220. if test -f 'im_lm.asm' -a "${1}" != "-c" ; then 
  221.   echo shar: Will not clobber existing file \"'im_lm.asm'\"
  222. else
  223.   echo shar: Extracting \"'im_lm.asm'\" \(9944 characters\)
  224.   sed "s/^X//" >'im_lm.asm' <<'END_OF_FILE'
  225. X;
  226. X; Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  227. X; Permission is granted to any individual or institution to use, copy, or
  228. X; redistribute this software so long as all of the original files are included
  229. X; unmodified, that it is not sold for profit, and that this copyright notice
  230. X; is retained.
  231. X;
  232. X
  233. X; im_lm.asm by Jean-loup Gailly.
  234. X
  235. X;im_lm.asm, optimized version of longest_match() and lm_process() in im_lmat.c
  236. X; Must be assembled with masm -ml. To be used only with C small model or
  237. X; compact model. This file is only optional. If you don't have masm, use the
  238. X; C version (add -DNO_ASM to CFLAGS in makefile.dos and remove im_lm.obj
  239. X; from OBJI).
  240. X;
  241. X; Turbo C 2.0 does not support static allocation of far data in
  242. X; the small model. So TC 2.0 users must assemble this with:
  243. X;   tasm -ml -DDYN_ALLOC im_lm;
  244. X; OS/2 users must assemble this with -DOS2 -ml. To simplify the code,
  245. X; the option -DDYN_ALLOC is not supported for OS/2.
  246. X        name    im_lm
  247. X
  248. Xifndef DYN_ALLOC
  249. X        extrn   _prev         : word
  250. X        extrn   _next         : word
  251. X        prev    equ  _prev
  252. X        next    equ  _next
  253. Xload_es_prev macro
  254. X        mov     cx,seg _prev
  255. X        mov     es,cx
  256. Xendm
  257. Xload_ds_next macro
  258. X        mov     si,seg _next
  259. X        mov     ds,si
  260. Xendm
  261. Xendif
  262. X
  263. X_BSS    segment  word public 'BSS'
  264. X        extrn   _window       : byte
  265. X        extrn   _match_length : word
  266. X        extrn   _start_length : word
  267. X        extrn   _strstart     : word
  268. X        extrn   _strsize      : word
  269. X        extrn   _ins_h        : word
  270. X        extrn   _h_shift      : byte
  271. X        extrn   _checkpoint   : word
  272. X        extrn   _bufsize      : word
  273. X        extrn   _max_chain_length : word
  274. X        extrn   _min_match_length : word
  275. Xifdef DYN_ALLOC
  276. X        extrn   _prev         : word
  277. X        extrn   _next         : word
  278. X        prev    equ 0         ; offset normalized to zero (except for OS/2)
  279. X        next    equ 0         ; offset normalized to zero (except for OS/2)
  280. Xload_es_prev macro
  281. X        mov     es,_prev[2]   ; warning: the offset should be added under OS/2
  282. Xendm
  283. Xload_ds_next macro
  284. X        mov     ds,_next[2]   ; warning: the offset should be added under OS/2
  285. Xendm
  286. Xendif
  287. X        cur_best dw 1 dup(?)  ; best match within longest_match
  288. X_BSS    ends
  289. X
  290. XDGROUP  group _BSS
  291. X
  292. X_TEXT   segment word public 'CODE'
  293. X        assume  cs: _TEXT, ds: DGROUP, ss: DGROUP
  294. X
  295. X        extrn   _write_match : near
  296. X
  297. X        BSZ          equ 4096           ; keep consistent with tailor.h
  298. X        WSIZE        equ 8192           ; keep consistent with im_lmat.c
  299. X        NIL          equ (WSIZE+BSZ)
  300. X        MAX_DIST     equ NIL
  301. X        MAX_LENGTH   equ 320            ; keep consistent with im_lmat.c
  302. X        HASH_MASK    equ 16383          ; (1<<14)-1
  303. X
  304. X; Process a block of characters already inserted in the window
  305. X; IN assertion: count > 0
  306. X        public _lm_process
  307. X_lm_process  proc near
  308. X        push    bp
  309. X        mov     bp,sp
  310. X        push    di
  311. X        push    si
  312. X
  313. X        count   equ word ptr [bp+4]
  314. X;       delete_point equ ax
  315. X;       ins_h        equ bx
  316. X;       h_shift      equ cl
  317. X;       count        equ dx
  318. X;       cur_match    equ si
  319. X;       strstart     equ di
  320. X;       min_match_length equ bp
  321. X
  322. X        mov     dx,count
  323. X        mov     bx,_ins_h
  324. X        mov     di,_strstart
  325. X        lea     ax,[di+MAX_LENGTH-1]
  326. X        sub     ax,_bufsize
  327. X        jae     del_ok
  328. X        add     ax,MAX_DIST
  329. Xdel_ok: shl     ax,1                    ;delete_point as word index
  330. X        load_es_prev
  331. X        mov     cl,_h_shift
  332. X        load_ds_next
  333. X        assume  ds: nothing
  334. X        jmp     short insert
  335. X
  336. Xstart_overflow:
  337. X        sub     di,di                   ;strstart = 0
  338. X        sub     ss:_checkpoint,MAX_DIST
  339. X        jmp     short check_count
  340. Xdel_overflow:
  341. X        mov     ax,-2                   ;delete_point = 0
  342. Xmain_loop:
  343. X        add     ax,2                    ;delete_point++ (word index)
  344. X        cmp     ax,2*MAX_DIST
  345. X        je      del_overflow
  346. X        xchg    ax,si                   ;si=2*delete_point
  347. X        mov     bp,next[si]
  348. X        shl     bp,1
  349. X        mov     es:prev[bp],NIL
  350. X        xchg    ax,si                   ;ax=2*delete_point
  351. X
  352. X        inc     di                      ;strstart++
  353. X        cmp     di,MAX_DIST
  354. X        je      start_overflow
  355. Xcheck_count:
  356. X        dec     dx                      ;count--
  357. X        jz      end_proc_ok
  358. Xinsert:
  359. X        shl     bx,cl                   ;ins_h <<= h_shift
  360. X        mov     bp,ss:_min_match_length
  361. X        xor     bl,_window[di+bp-1]     ;ins_h ^= window[s+min_match_length-1]
  362. X        and     bx,HASH_MASK
  363. X        add     bx,MAX_DIST+1
  364. X        shl     bx,1                    ;word index
  365. X        mov     si,es:prev[bx]          ;cur_match = match_head[ins_h]
  366. X        mov     es:prev[bx],di          ;prev[ins_h+MAX_DIST+1] = strstart
  367. X        shr     bx,1                    ;bx = ins_h + MAX_DIST + 1
  368. X        shl     di,1                    ;di = strstart as word index
  369. X        mov     next[di],bx
  370. X        sub     bx,MAX_DIST+1           ;bx = ins_h
  371. X        mov     es:prev[di],si          ;prev[s] = cur_match
  372. X        shr     di,1                    ;di = strstart
  373. X        shl     si,1
  374. X        mov     next[si],di             ;next[cur_match] = strstart
  375. X        cmp     di,ss:_checkpoint
  376. X        jne     main_loop
  377. X
  378. X        push    ax
  379. X        push    bx
  380. X        push    dx
  381. X        mov     ax,ss
  382. X        mov     ds,ax
  383. X        assume  ds: DGROUP
  384. X        mov     _match_length,0
  385. X        mov     _strstart,di
  386. X        shr     si,1                    ;si = cur_match
  387. X        cmp     si,NIL                  ;cur_match == NIL ?
  388. X        je      call_write
  389. X        call    _longest_match          ;returns best_match in si
  390. Xcall_write:
  391. X        push    _match_length
  392. X        push    si                      ;best_match or NIL
  393. X        call    _write_match
  394. X        add     sp,4
  395. X        pop     dx
  396. X        pop     bx
  397. X        or      al,al
  398. X        jnz     failure
  399. X        pop     ax
  400. X        load_es_prev
  401. X        mov     cl,_h_shift
  402. X        load_ds_next
  403. X        assume  ds: nothing
  404. X        jmp     main_loop
  405. Xend_proc_ok:
  406. X        mov     ax,ss
  407. X        mov     ds,ax
  408. X        assume  ds: DGROUP
  409. X        sub     ax,ax
  410. X        mov     _strstart,di
  411. Xend_proc:
  412. X        mov     _ins_h,bx
  413. X        pop     si
  414. X        pop     di
  415. X        pop     bp
  416. X        ret
  417. Xfailure:
  418. X        add     sp,2                    ;skip pushed ax
  419. X        jmp     short end_proc
  420. X
  421. X_lm_process  endp
  422. X
  423. X; Find the longest match starting at the given string. Return its position
  424. X; and set its length in match_length. Matches shorter or equal to
  425. X; start_length are discarded, in which case match_length is unchanged
  426. X; and the result position is NIL.
  427. X; IN assertions: cur_match is the head of the hash chain for the current
  428. X;    string (strstart) and is not NIL, start_length >= 1.
  429. X;    registers: es points to the base of the prev array (preserved)
  430. X;               si = cur_match and return value
  431. X;               di = strstart
  432. X
  433. X; IPos longest_match(cur_match)
  434. X
  435. X        public _longest_match
  436. X_longest_match  proc near
  437. X
  438. X        push    bp
  439. X        push    di
  440. X
  441. X;       match        equ si
  442. X;       scan         equ di
  443. X;       chain_count  equ bp
  444. X;       ma_length    equ bx
  445. X
  446. X        lea     di,_window[di+2]        ; di = window + strstart + 2
  447. X        mov     cur_best,NIL
  448. X        mov     bp,_max_chain_length    ; chain_count = max_chain_length
  449. X        mov     bx,_start_length        ; ma_length = start_length
  450. X        mov     ax,[bx+di-3]            ; ax = scan[ma_length-1..ma_length]
  451. X        mov     cx,[di-2]               ; cx = scan[0..1]
  452. X        jmp     short do_scan
  453. X
  454. X        even                            ; align destination of branch
  455. Xlong_loop:
  456. X; at this point, di == scan+2, si = cur_match
  457. X        mov     ax,[bx+di-3]            ; ax = scan[ma_length-1..ma_length]
  458. X        mov     cx,[di-2]               ; cx = scan[0..1]
  459. Xshort_loop:
  460. X        dec     bp                      ; --chain_count
  461. X        jz      the_end
  462. X; at this point, di == scan+2, si = cur_match,
  463. X; ax = scan[ma_length-1..ma_length] and cx = scan[0..1]
  464. X        shl     si,1                    ; cur_match as word index
  465. X        mov     si,es:prev[si]          ; cur_match = prev[cur_match]
  466. X        cmp     si,NIL
  467. X        je      the_end
  468. Xdo_scan:
  469. X        cmp     ax,word ptr _window[bx+si-1] ; check match at ma_length-1
  470. X        jne     short_loop
  471. X        cmp     cx,word ptr _window[si]      ; check min_match_length match
  472. X        jne     short_loop
  473. X        mov     dx,si                   ; dx = cur_match
  474. X        lea     si,_window[si+2]        ; si = match
  475. X        mov     ax,di                   ; ax = scan+2
  476. X        mov     cx,ds
  477. X        mov     es,cx
  478. X        mov     cx,(MAX_LENGTH-2)/2     ; scan for at most MAX_LENGTH bytes
  479. X        repe    cmpsw                   ; loop until mismatch
  480. X        load_es_prev                    ; reset es to address the prev array
  481. X        mov     cl,[di-2]               ; mismatch on first or second byte?
  482. X        sub     cl,[si-2]               ; dl = 0 if first bytes equal
  483. X        xchg    ax,di                   ; di = scan+2, ax = end of scan
  484. X        sub     ax,di                   ; ax = len
  485. X        sub     cl,1                    ; set carry if cl == 0 (can't use DEC)
  486. X        adc     ax,0                    ; ax = carry ? len+1 : len
  487. X        mov     si,dx                   ; si = cur_match
  488. X        cmp     ax,bx                   ; len > ma_length ?
  489. X        jle     long_loop
  490. X        mov     cur_best,si             ; cur_best = cur_match
  491. X        mov     bx,ax                   ; bx = ma_length = len
  492. X        cmp     ax,_strsize             ; len >= strsize ?
  493. X        jle     long_loop
  494. Xthe_end:
  495. X        cmp     bx,_start_length        ; ma_length > start_length ?
  496. X        jle     return
  497. X        mov     _match_length,bx        ; match_length = ma_length
  498. Xreturn:
  499. X        mov     si,cur_best             ; result = cur_best
  500. X        pop     di
  501. X        pop     bp
  502. X        ret
  503. X
  504. X_longest_match  endp
  505. X
  506. X_TEXT   ends
  507. Xend
  508. END_OF_FILE
  509.   if test 9944 -ne `wc -c <'im_lm.asm'`; then
  510.     echo shar: \"'im_lm.asm'\" unpacked with wrong size!
  511.   fi
  512.   # end of 'im_lm.asm'
  513. fi
  514. if test -f 'implode.c' -a "${1}" != "-c" ; then 
  515.   echo shar: Will not clobber existing file \"'implode.c'\"
  516. else
  517.   echo shar: Extracting \"'implode.c'\" \(8838 characters\)
  518.   sed "s/^X//" >'implode.c' <<'END_OF_FILE'
  519. X/*
  520. X
  521. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  522. X Permission is granted to any individual or institution to use, copy, or
  523. X redistribute this software so long as all of the original files are included
  524. X unmodified, that it is not sold for profit, and that this copyright notice
  525. X is retained.
  526. X
  527. X*/
  528. X
  529. X/*
  530. X *  implode.c by Richard B. Wales.
  531. X *
  532. X *  PURPOSE
  533. X *
  534. X *      Compress an input file using the ZIP "implosion" method.
  535. X *
  536. X *  DISCUSSION
  537. X *
  538. X *      The "implosion" algorithm is a composite of (1) OPM/L compres-
  539. X *      sion within a sliding window, and (2) variable-length binary
  540. X *      encoding of various parts of the OPM/L output.
  541. X *
  542. X *      For a detailed treatment of OPM/L compression, see the source
  543. X *      file "im_lmat.c".
  544. X *
  545. X *      For a detailed treatment of variable-length binary encoding,
  546. X *      see the source file "im_ctree.c".
  547. X *
  548. X *      Since Pass Two (binary encoding) depends on a statistical anal-
  549. X *      ysis of the entire output of Pass One (OPM/L compression), the
  550. X *      Pass One output is saved in a temporary file and re-read for
  551. X *      Pass Two.  Implosion is thus a two-pass algorithm.
  552. X *
  553. X *      An outline of the algorithm follows:
  554. X *
  555. X *      (1) The entire input file is read and compressed via the OPM/L
  556. X *          technique.  The OPM/L output is saved in a temporary file.
  557. X *
  558. X *      (2) The compressed info from (1) is analyzed, and various fre-
  559. X *          quency counts are tallied.
  560. X *
  561. X *      (3) Based on the frequency counts, a decision is made as to
  562. X *          whether or not the "literal" characters (those not matched
  563. X *          in earlier parts of the input) should be represented via a
  564. X *          binary code tree or left "as is".  If there are not very
  565. X *          many literal characters, or if their frequency distribution
  566. X *          is fairly even, the number of bits saved through coding may
  567. X *          be exceeded by the amount of info which must be included to
  568. X *          describe the tree.
  569. X *
  570. X *      (4) The temporary file from (1) is re-read.  The information is
  571. X *          further compressed via the binary code trees, and the result
  572. X *          is sent to the ZIP output file.
  573. X *
  574. X *  REFERENCES
  575. X *
  576. X *      APPNOTE.TXT documentation file in PKZIP 1.10 distribution.
  577. X *
  578. X *      See also references in the "im_lmat.c" and "im_ctree.c" source
  579. X *      files.
  580. X *
  581. X *  INTERFACE
  582. X *
  583. X *      int imp_setup (long filesize, int pack_level)
  584. X *          Initialize the "implode" routines for a new file.
  585. X *
  586. X *      int imp_p1 (char *buf, int count)
  587. X *          Process "count" input characters pointed to by "buf".  This
  588. X *          routine is called as many times as needed to process the
  589. X *          entire input file.  There is no upper limit on "count".
  590. X *
  591. X *      int imp_size (long *size, char *opts)
  592. X *          Terminate processing of the input file, and return the com-
  593. X *          pressed size ("size") and implosion option flags ("opts").
  594. X *
  595. X *      int imp_p2 (FILE *outfp)
  596. X *          Output the entire compressed file -- including S-F trees and
  597. X *          data -- to the ZIP output file "outfp".
  598. X *
  599. X *      int imp_clear (void)
  600. X *          Clean up after processing and outputting a file.  This rou-
  601. X *          tine may be called at any time to abort further processing.
  602. X *
  603. X *      All the above routines return zero if successful, or a non-zero
  604. X *      value if there was an error.
  605. X */
  606. X
  607. X#include "implode.h"
  608. X#include "ziperr.h"
  609. X
  610. X
  611. X/***********************************************************************
  612. X *
  613. X * Error return codes for the main ZIP program.
  614. X * Most of these are in "ziperr.h".
  615. X */
  616. X
  617. X#define ZE_MAP(err) \
  618. X        ( ((err) == IM_OK)      ? ZE_OK \
  619. X        : ((err) == IM_NOMEM)   ? ZE_MEM \
  620. X        : ((err) == IM_IOERR)   ? ZE_TEMP \
  621. X                                : (fprintf(stderr,"\nZE_MAP(%d)",(err)), \
  622. X                                    ZE_LOGIC))
  623. X
  624. X
  625. X/***********************************************************************
  626. X *
  627. X * State variable for the implosion routines.
  628. X */
  629. X
  630. X#define IMP_SETUP       0       /* need to do "imp_setup" */
  631. X#define IMP_P1          1       /* setup done, ready for Pass 1 */
  632. X#define IMP_P2          2       /* Pass 1 done, ready for Pass 2 */
  633. X#define IMP_CLEAR       3       /* Pass 2 done, ready for "imp_clear" */
  634. X
  635. Xlocal int imp_state = IMP_SETUP;
  636. X
  637. X
  638. X/***********************************************************************
  639. X *
  640. X * Global variables.
  641. X */
  642. X
  643. XFDATA fd;
  644. X
  645. X
  646. X/***********************************************************************
  647. X *
  648. X * Set up for performing implosion on a new file.
  649. X */
  650. X
  651. Xint
  652. Ximp_setup (filesize, pack_level)
  653. X    long filesize;  /* input file size */
  654. X    int pack_level; /* 0 = best speed, 9 = best compression, other = default */
  655. X{
  656. X    ImpErr retcode;
  657. X    extern char *tempname();
  658. X
  659. X    if (imp_state != IMP_SETUP)
  660. X    {   fprintf (stderr, "\nimp_setup called with wrong state %d",
  661. X                 imp_state);
  662. X        return ZE_LOGIC;
  663. X    }
  664. X    imp_state = IMP_P1;
  665. X
  666. X    /* Set up the initial parameters. Use an 8K window if the input
  667. X     * file is greater than or equal to 5.5K, a 4K window otherwise.
  668. X     */
  669. X    fd.fd_bufsize = 8192;
  670. X    if (filesize < 5632) fd.fd_bufsize = 4096;
  671. X
  672. X    fd.fd_strsize = 320;
  673. X    fd.fd_nbits   = (fd.fd_bufsize == 4096) ? 6 : 7;
  674. X
  675. X    /* Create a temporary file for the Pass One output. */
  676. X    fd.fd_temp = topen ('I');
  677. X    if (fd.fd_temp == NULL)
  678. X        return ZE_MEM;
  679. X
  680. X    /*
  681. X     * Initialize the "longest match" routines.
  682. X     * "ct_init" is called at this point because the "lm_input" routine
  683. X     * (called in "imp_p1") calls the "ct_tally" routine.
  684. X     */
  685. X    retcode = lm_init (pack_level);
  686. X    if (retcode != IM_OK) return ZE_MAP (retcode);
  687. X    retcode = ct_init ();
  688. X    return ZE_MAP (retcode);
  689. X}
  690. X
  691. X
  692. X/***********************************************************************
  693. X *
  694. X * Feed characters to the implosion computation.
  695. X * This routine is called as many times as needed, until the entire
  696. X * input file has been processed.
  697. X */
  698. X
  699. Xint
  700. Ximp_p1 (buf, count)
  701. X    char *buf;                  /* input characters */
  702. X    int   count;                /* character count */
  703. X{   ImpErr retcode;
  704. X
  705. X    if (imp_state != IMP_P1)
  706. X    {   fprintf (stderr, "\nimp_p1 called with wrong state %d",
  707. X                 imp_state);
  708. X        return ZE_LOGIC;
  709. X    }
  710. X
  711. X    if (buf == NULL || count < 0)
  712. X    {   fprintf (stderr, "\nimp_p1 called with bad arguments");
  713. X        return ZE_LOGIC;
  714. X    }
  715. X    retcode = lm_input ((U_CHAR *) buf, (U_INT) count);
  716. X    return ZE_MAP (retcode);
  717. X}
  718. X
  719. X
  720. X/***********************************************************************
  721. X *
  722. X * Terminate processing of input for this file, and determine the size
  723. X * this file will have if it is imploded.  Also, find out whether two
  724. X * or three S-F trees will be used (needed for directory entries).
  725. X */
  726. X
  727. Xint
  728. Ximp_size (size, opts)
  729. X    long *size;                 /* imploded size */
  730. X    char *opts;                 /* implosion option info */
  731. X{   ImpErr retcode;
  732. X
  733. X    if (imp_state != IMP_P1)
  734. X    {   fprintf (stderr, "\nimp_size called with wrong state %d",
  735. X                 imp_state);
  736. X        return ZE_LOGIC;
  737. X    }
  738. X    imp_state = IMP_P2;
  739. X
  740. X    if (size == NULL || opts == NULL)
  741. X    {   fprintf (stderr, "\nimp_size called with bad arguments");
  742. X        return ZE_LOGIC;
  743. X    }
  744. X    retcode = lm_windup ();
  745. X    if (retcode != IM_OK) return ZE_MAP (retcode);
  746. X    retcode = ct_mktrees ();
  747. X    if (retcode != IM_OK) return ZE_MAP (retcode);
  748. X    *size = fd.fd_clen;
  749. X    *opts = (char)(((fd.fd_bufsize == 8192) ? 0x02 : 0)
  750. X          | ((fd.fd_method == LITERAL_TREE) ? 0x04 : 0));
  751. X    return ZE_OK;
  752. X}
  753. X
  754. X
  755. X/***********************************************************************
  756. X *
  757. X * Output the imploded version of the file (but not the file directory
  758. X * info) to the ZIP file.
  759. X */
  760. X
  761. Xint
  762. Ximp_p2 (outfp)
  763. X    FILE *outfp;                        /* output (ZIP) file */
  764. X{   ImpErr retcode;
  765. X
  766. X    if (imp_state != IMP_P2)
  767. X    {   fprintf (stderr, "\nimp_p2 called with wrong state %d",
  768. X                 imp_state);
  769. X        return ZE_LOGIC;
  770. X    }
  771. X    imp_state = IMP_CLEAR;
  772. X
  773. X    if (outfp == NULL)
  774. X    {   fprintf (stderr, "\nimp_p2 called with bad arguments");
  775. X        return ZE_LOGIC;
  776. X    }
  777. X    retcode = ct_wrtrees (outfp);
  778. X    if (retcode != IM_OK) return ZE_MAP (retcode);
  779. X    retcode = ct_wrdata (outfp);
  780. X    if (retcode != IM_OK) return ZE_MAP (retcode);
  781. X    fflush (outfp);
  782. X    if (ferror (outfp)) return ZE_TEMP;
  783. X    return ZE_OK;
  784. X}
  785. X
  786. X
  787. X/***********************************************************************
  788. X *
  789. X * Clean up after doing an implosion.
  790. X * This routine may also be called at any time to abort an implosion.
  791. X */
  792. X
  793. Xint
  794. Ximp_clear ()
  795. X{   (void) lm_windup ();
  796. X    if (fd.fd_temp != NULL)
  797. X        (void) tclose (fd.fd_temp);
  798. X    (void) ct_windup ();
  799. X    imp_state = IMP_SETUP;
  800. X    return ZE_OK;
  801. X}
  802. X
  803. X
  804. X/**********************************************************************/
  805. END_OF_FILE
  806.   if test 8838 -ne `wc -c <'implode.c'`; then
  807.     echo shar: \"'implode.c'\" unpacked with wrong size!
  808.   fi
  809.   # end of 'implode.c'
  810. fi
  811. if test -f 'implode.h' -a "${1}" != "-c" ; then 
  812.   echo shar: Will not clobber existing file \"'implode.h'\"
  813. else
  814.   echo shar: Extracting \"'implode.h'\" \(4579 characters\)
  815.   sed "s/^X//" >'implode.h' <<'END_OF_FILE'
  816. X/*
  817. X
  818. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  819. X Permission is granted to any individual or institution to use, copy, or
  820. X redistribute this software so long as all of the original files are included
  821. X unmodified, that it is not sold for profit, and that this copyright notice
  822. X is retained.
  823. X
  824. X*/
  825. X
  826. X/*
  827. X * implode.h by Richard B. Wales.
  828. X */
  829. X
  830. X#include "crypt.h"
  831. X#include "tempf.h"
  832. X#include <errno.h>
  833. X
  834. X
  835. X/***********************************************************************
  836. X *
  837. X * Type definitions.
  838. X */
  839. X
  840. X
  841. Xtypedef long  L_INT;
  842. Xtypedef int   INT;
  843. Xtypedef short S_INT;
  844. X
  845. Xtypedef unsigned long  UL_INT;
  846. Xtypedef unsigned int   U_INT;
  847. Xtypedef unsigned short US_INT;
  848. X
  849. Xtypedef unsigned char  U_CHAR;
  850. X
  851. Xtypedef unsigned long  CRC;
  852. X
  853. X#define VOID void
  854. X
  855. X#define local static            /* More meaningful outside functions */
  856. X/* #define local */
  857. X
  858. X#define TRUE  1
  859. X#define FALSE 0
  860. X
  861. X/* Error return codes. */
  862. Xtypedef
  863. Xenum
  864. X    {   IM_OK,                  /* all OK */
  865. X        IM_EOF,                 /* end of file on input */
  866. X        IM_IOERR,               /* I/O error */
  867. X        IM_BADARG,              /* invalid procedure argument */
  868. X        IM_NOMEM,               /* out of memory */
  869. X        IM_LOGICERR,            /* logic error */
  870. X        IM_NOCTBLS              /* no more code tables */
  871. X    }
  872. X    ImpErr;
  873. X
  874. X/* The different possible compression methods. */
  875. Xtypedef
  876. Xenum
  877. X    {   NO_LITERAL_TREE,        /* use only two trees */
  878. X        LITERAL_TREE            /* use all three trees */
  879. X    }
  880. X    Method;
  881. X
  882. X/* File data structure. */
  883. Xtypedef
  884. Xstruct  fdata
  885. X    {   L_INT    fd_len;        /* # of bytes in file */
  886. X        L_INT    fd_clen;       /* compressed length */
  887. X        tFILE    *fd_temp;      /* temporary file stream pointer */
  888. X        U_INT    fd_bufsize;    /* size of sliding dictionary */
  889. X        U_INT    fd_strsize;    /* max string match length */
  890. X        U_INT    fd_nbits;      /* # distance bits to write literally */
  891. X        Method   fd_method;     /* compression method */
  892. X    }
  893. X    FDATA;
  894. X
  895. X/* Data structure for string matches. */
  896. Xtypedef
  897. Xstruct  match
  898. X    {   S_INT       ma_dist;    /* distance back into buffer */
  899. X        union {
  900. X           US_INT   ma_length;  /* length of matched string */
  901. X           U_CHAR   ma_litc[2]; /* literal characters matched */
  902. X        } l;
  903. X        /* l is ma_litc if ma_dist <= 0. If ma_dist < 0, the length is
  904. X         * 2 and the distance is -ma_dist.
  905. X         */
  906. X    }
  907. X    MATCH;
  908. X
  909. X
  910. X/***********************************************************************
  911. X *
  912. X * External variable declarations.
  913. X */
  914. X
  915. Xextern FDATA fd;                /* file data */
  916. X#ifndef MSDOS
  917. Xextern int errno;               /* system error code */
  918. X#endif  /* MSDOS */
  919. X
  920. Xextern MATCH *ma_buf;           /* match info buffer */
  921. X#define MA_BUFSIZE 512
  922. X/* MA_BUFSIZE must be such that
  923. X *     256*sizeof(TRDATA) <= MA_BUFSIZE*sizeof(MATCH)
  924. X * since the same buffer is used for both purposes at different times.
  925. X */
  926. X
  927. X/***********************************************************************
  928. X *
  929. X * External procedure declarations.
  930. X */
  931. X
  932. X
  933. X#ifdef  MODERN
  934. X#include <string.h>
  935. X#else
  936. Xvoidp *malloc();
  937. Xchar  *strcpy();
  938. Xchar  *strcat();
  939. X#endif  /* MODERN */
  940. X
  941. X
  942. X/***********************************************************************
  943. X *
  944. X * Routines in "im_lmat.c" source file.
  945. X */
  946. X
  947. X
  948. XImpErr  lm_init
  949. X        OF ((int pack_level));
  950. X
  951. XImpErr  lm_input
  952. X        OF ((U_CHAR *block, U_INT count));
  953. X
  954. XImpErr  lm_windup
  955. X        OF ((void));
  956. X
  957. X
  958. X/***********************************************************************
  959. X *
  960. X * Routines in "im_ctree.c" source file.
  961. X */
  962. X
  963. XImpErr ct_init
  964. X        OF ((void));
  965. X
  966. XImpErr ct_tally
  967. X        OF ((MATCH *ma));
  968. X
  969. XImpErr ct_mktrees
  970. X        OF ((void));
  971. X
  972. XImpErr ct_wrtrees
  973. X        OF ((FILE *outfp));
  974. X
  975. XImpErr ct_wrdata
  976. X        OF ((FILE *outfp));
  977. X
  978. XImpErr ct_windup
  979. X        OF ((void));
  980. X
  981. X
  982. X/***********************************************************************
  983. X *
  984. X * Routines in "im_bits.c" source file.
  985. X */
  986. X
  987. XImpErr bi_init
  988. X        OF ((FILE *fp));
  989. X
  990. XImpErr bi_rlout
  991. X        OF ((int value, int length));
  992. X
  993. Xint bi_reverse
  994. X        OF ((int value, int length));
  995. X
  996. XImpErr bi_windup
  997. X        OF ((void));
  998. X
  999. X
  1000. X/***********************************************************************
  1001. X *
  1002. X * Routines in "implode.c" source file.
  1003. X */
  1004. X
  1005. Xint imp_setup
  1006. X        OF ((long filesize, int pack_level));
  1007. X
  1008. Xint imp_p1
  1009. X        OF ((char *buf, int count));
  1010. X
  1011. Xint imp_size
  1012. X        OF ((long *size, char *opts));
  1013. X
  1014. Xint imp_p2
  1015. X        OF ((FILE *outfp));
  1016. X
  1017. Xint imp_clear
  1018. X        OF ((void));
  1019. X
  1020. X
  1021. X/**********************************************************************/
  1022. END_OF_FILE
  1023.   if test 4579 -ne `wc -c <'implode.h'`; then
  1024.     echo shar: \"'implode.h'\" unpacked with wrong size!
  1025.   fi
  1026.   # end of 'implode.h'
  1027. fi
  1028. if test -f 'makefile.os2' -a "${1}" != "-c" ; then 
  1029.   echo shar: Will not clobber existing file \"'makefile.os2'\"
  1030. else
  1031.   echo shar: Extracting \"'makefile.os2'\" \(3393 characters\)
  1032.   sed "s/^X//" >'makefile.os2' <<'END_OF_FILE'
  1033. X# Makefile for Zip, ZipNote, ZipSplit, and Ship
  1034. X# for Microsoft C 6.00 and MASM 6.00 under OS/2.
  1035. X
  1036. X# To use, enter "nmake -f makefile.os2".
  1037. X
  1038. X# The resulting programs can be used under OS/2 protected
  1039. X# and real mode as well as under MS-DOS!
  1040. X# A larger stack has to be used for OS/2 because system calls
  1041. X# use more stack than under DOS, 8k is recommended by Microsoft.
  1042. X
  1043. X# Note that __STDC__ has to be defined explicitly with C 6.00 when -Ze
  1044. X# is given, because Microsoft disables __STDC__ when their extensions
  1045. X# are enabled. This is different to the C 5.10 behaviour.
  1046. X
  1047. X# If you do not have masm, then add -DNO_ASM to CFLAGS and remove
  1048. X# im_lm.obj from OBJI
  1049. X
  1050. XMODEL=-AC
  1051. X# change this to -AS to use the small model
  1052. XDEFINES=-D__STDC__ -DOS2 -DEXPORT
  1053. X
  1054. X# Loop optimization -Ol with C 6.00A is sometimes not safe.
  1055. X# Use it only for time-critical modules.
  1056. X
  1057. XCC=cl -nologo
  1058. XCFLAGS=$(MODEL) -W1 -Zep1 -J -G2s -Ocegit $(DEFINES)
  1059. XXFLAGS=-Oxaz
  1060. XLDFLAGS=$(MODEL) -Lp -F 2000
  1061. XAS=ml -nologo
  1062. XAFLAGS=-W2 -Zm -Cp $(DEFINES)
  1063. X
  1064. X# For protect-mode only programs use rem
  1065. XSTRIP=bind -nologo
  1066. X# STRIP=rem
  1067. X
  1068. X# variables
  1069. X# remove im_lm.obj in OBJI if you do not have masm
  1070. XOBJZ = zip.obj zipfile.obj zipup.obj fileio.obj util.obj tempf.obj \
  1071. X       shrink.obj globals.obj dir_os2.obj
  1072. XOBJI = implode.obj im_lmat.obj im_ctree.obj im_bits.obj im_lm.obj
  1073. X
  1074. XOBJN = zipnote.obj zipfile_.obj zipup_.obj fileio_.obj globals.obj
  1075. XOBJS = zipsplit.obj zipfile_.obj zipup_.obj fileio_.obj globals.obj
  1076. X
  1077. Xzips:    zip.exe zipnote.exe zipsplit.exe ship.exe
  1078. X
  1079. Xzip.obj:    zip.h ziperr.h tailor.h revision.h zip.c
  1080. X    $(CC) -c $(CFLAGS) $*.c
  1081. X
  1082. Xzipfile.obj:    zip.h ziperr.h tailor.h zipfile.c
  1083. X    $(CC) -c $(CFLAGS) $*.c
  1084. X
  1085. Xzipup.obj:    zip.h ziperr.h tailor.h revision.h zipup.c
  1086. X    $(CC) -c $(CFLAGS) $*.c
  1087. X
  1088. Xfileio.obj:    zip.h ziperr.h tailor.h fileio.c
  1089. X    $(CC) -c $(CFLAGS) $*.c
  1090. X
  1091. Xutil.obj:    zip.h ziperr.h tailor.h util.c
  1092. X    $(CC) -c $(CFLAGS) $*.c
  1093. X
  1094. Xtempf.obj:    tempf.h tailor.h tempf.c
  1095. X    $(CC) -c $(CFLAGS) $*.c
  1096. X
  1097. Xshrink.obj:    zip.h ziperr.h tempf.h tailor.h shrink.c
  1098. X    $(CC) -c $(CFLAGS) $(XFLAGS) $*.c
  1099. X
  1100. Xglobals.obj:    zip.h ziperr.h tailor.h globals.c
  1101. X    $(CC) -c $(CFLAGS) $*.c
  1102. X
  1103. Xdir_os2.obj: dir_os2.c dir_os2.h
  1104. X    $(CC) -c $(CFLAGS) dir_os2.c
  1105. X
  1106. Xzipnote.obj:    zip.h ziperr.h tailor.h revision.h zipnote.c
  1107. X    $(CC) -c $(CFLAGS) $*.c
  1108. X
  1109. Xzipsplit.obj: zipsplit.c zip.h ziperr.h tailor.h revision.h
  1110. X    $(CC) -c $(CFLAGS) $*.c
  1111. X
  1112. Ximplode.obj:    implode.h crypt.h ziperr.h tempf.h tailor.h implode.c
  1113. X    $(CC) -c $(CFLAGS) $(XFLAGS) $*.c
  1114. X
  1115. Xim_lmat.obj:    implode.h crypt.h ziperr.h tempf.h tailor.h im_lmat.c
  1116. X    $(CC) -c $(CFLAGS) $(XFLAGS) $*.c
  1117. X
  1118. Xim_lm.obj:    im_lm.asm
  1119. X    $(AS) -c $(AFLAGS) $*.asm
  1120. X#    masm -ml -t -DOS2 im_lm.asm;   # use this for 5.10
  1121. X
  1122. Xim_ctree.obj:    implode.h crypt.h ziperr.h tempf.h tailor.h im_ctree.c
  1123. X    $(CC) -c $(CFLAGS) $(XFLAGS) $*.c
  1124. X
  1125. Xim_bits.obj:    implode.h crypt.h ziperr.h tempf.h tailor.h im_bits.c
  1126. X    $(CC) -c $(CFLAGS) $(XFLAGS) $*.c
  1127. X
  1128. Xzipfile_.obj: zipfile.c zip.h
  1129. X    $(CC) -c $(CFLAGS) -DUTIL -Fo$@ zipfile.c
  1130. X
  1131. Xzipup_.obj: zipup.c zip.h
  1132. X    $(CC) -c $(CFLAGS) -DUTIL -Fo$@ zipup.c
  1133. X
  1134. Xfileio_.obj: fileio.c zip.h
  1135. X    $(CC) -c $(CFLAGS) -DUTIL -Fo$@ fileio.c
  1136. X
  1137. Xzip.exe: $(OBJZ) $(OBJI) zip.def
  1138. X    $(CC) $(LDFLAGS) $** -o $@
  1139. X        $(STRIP) $@ -n DOSQFSATTACH
  1140. X
  1141. Xzipnote.exe: $(OBJN) zip.def
  1142. X    $(CC) $(LDFLAGS) $** -o $@
  1143. X        $(STRIP) $@
  1144. X
  1145. Xzipsplit.exe: $(OBJS) zip.def
  1146. X    $(CC) $(LDFLAGS) $** -o $@
  1147. X        $(STRIP) $@
  1148. X
  1149. Xship.exe: ship.c ship.def
  1150. X    $(CC) $(CFLAGS) $(LDFLAGS) $** -o $@
  1151. X        $(STRIP) $@
  1152. END_OF_FILE
  1153.   if test 3393 -ne `wc -c <'makefile.os2'`; then
  1154.     echo shar: \"'makefile.os2'\" unpacked with wrong size!
  1155.   fi
  1156.   # end of 'makefile.os2'
  1157. fi
  1158. if test -f 'ship.def' -a "${1}" != "-c" ; then 
  1159.   echo shar: Will not clobber existing file \"'ship.def'\"
  1160. else
  1161.   echo shar: Extracting \"'ship.def'\" \(74 characters\)
  1162.   sed "s/^X//" >'ship.def' <<'END_OF_FILE'
  1163. XNAME WINDOWCOMPAT NEWFILES
  1164. XDESCRIPTION 'encode/split/mail & decode files'
  1165. END_OF_FILE
  1166.   if test 74 -ne `wc -c <'ship.def'`; then
  1167.     echo shar: \"'ship.def'\" unpacked with wrong size!
  1168.   fi
  1169.   # end of 'ship.def'
  1170. fi
  1171. if test -f 'zip.h' -a "${1}" != "-c" ; then 
  1172.   echo shar: Will not clobber existing file \"'zip.h'\"
  1173. else
  1174.   echo shar: Extracting \"'zip.h'\" \(8017 characters\)
  1175.   sed "s/^X//" >'zip.h' <<'END_OF_FILE'
  1176. X/*
  1177. X
  1178. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  1179. X Permission is granted to any individual or institution to use, copy, or
  1180. X redistribute this software so long as all of the original files are included
  1181. X unmodified, that it is not sold for profit, and that this copyright notice
  1182. X is retained.
  1183. X
  1184. X*/
  1185. X
  1186. X/*
  1187. X *  zip.h by Mark Adler.
  1188. X */
  1189. X
  1190. X
  1191. X/* Set up portability */
  1192. X#include "tailor.h"
  1193. X
  1194. X/* Define malloc() and string functions */
  1195. X#ifdef MODERN
  1196. X#  include <string.h>
  1197. X#else /* !MODERN */
  1198. X   voidp *malloc();
  1199. X   char *getenv();
  1200. X   long atol();
  1201. X   char *strcpy();
  1202. X   char *strcat();
  1203. X   char *strchr();
  1204. X   char *strrchr();
  1205. X#  ifndef ZMEM
  1206. X     char *memset();
  1207. X     char *memcpy();
  1208. X#  endif /* !ZMEM */
  1209. X#endif /* ?MODERN */
  1210. X
  1211. X
  1212. X/* Define fseek() commands */
  1213. X#ifndef SEEK_SET
  1214. X#  define SEEK_SET 0
  1215. X#endif /* !SEEK_SET */
  1216. X
  1217. X#ifndef SEEK_CUR
  1218. X#  define SEEK_CUR 1
  1219. X#endif /* !SEEK_CUR */
  1220. X
  1221. X
  1222. X/* Forget FILENAME_MAX (incorrectly = 14 on some System V) */
  1223. X#ifdef MSDOS
  1224. X#  define FNMAX 256
  1225. X#else /* !MSDOS */
  1226. X#  define FNMAX 1024
  1227. X#endif /* ?MSDOS */
  1228. X
  1229. X
  1230. X/* Types centralized here for easy modification */
  1231. X#define local static            /* More meaningful outside functions */
  1232. Xtypedef unsigned char uch;      /* unsigned 8-bit value */
  1233. Xtypedef unsigned short ush;     /* unsigned 16-bit value */
  1234. Xtypedef unsigned long ulg;      /* unsigned 32-bit value */
  1235. X
  1236. X
  1237. X/* Lengths of headers after signatures in bytes */
  1238. X#define LOCHEAD 26
  1239. X#define CENHEAD 42
  1240. X#define ENDHEAD 18
  1241. X
  1242. X
  1243. X/* Structures for in-memory file information */
  1244. Xstruct zlist {
  1245. X  /* See central header in zipfile.c for what vem..off are */
  1246. X  ush vem, ver, flg, how;
  1247. X  ulg tim, crc, siz, len;
  1248. X  extent nam, ext, cext, com;   /* offset of ext must be >= LOCHEAD */
  1249. X  ush dsk, att, lflg;           /* offset of lflg must be >= LOCHEAD */
  1250. X  ulg atx, off;
  1251. X  char *name;                   /* File name in zip file */
  1252. X  char *extra;                  /* Extra field (set only if ext != 0) */
  1253. X  char *cextra;                 /* Extra in central (set only if cext != 0) */
  1254. X  char *comment;                /* Comment (set only if com != 0) */
  1255. X  char *zname;                  /* Name for new zip file header */
  1256. X  int mark;                     /* Marker for files to operate on */
  1257. X  int trash;                    /* Marker for files to delete */
  1258. X  struct zlist far *nxt;        /* Pointer to next header in list */
  1259. X};
  1260. Xstruct flist {
  1261. X  char *name;                   /* Pointer to zero-delimited name */
  1262. X  char *zname;                  /* Name used for zip file headers */
  1263. X  struct flist far * far *lst;  /* Pointer to link pointing here */
  1264. X  struct flist far *nxt;        /* Link to next name */
  1265. X};
  1266. X
  1267. X
  1268. X/* Error return codes and PERR macro */
  1269. X#include "ziperr.h"
  1270. X
  1271. X
  1272. X/* Public globals */
  1273. Xextern char errbuf[];           /* Handy place to build error messages */
  1274. Xextern int recurse;             /* Recurse into directories encountered */
  1275. Xextern int pathput;             /* Store path with name */
  1276. X#define BEST -1                 /* Use best method */
  1277. X#define STORE 0                 /* Store method */
  1278. X#define SHRINK 1                /* Use shrink or store only */
  1279. X#define IMPLODE 6               /* Use implode or store only */
  1280. Xextern int method;              /* Restriction on compression method */
  1281. Xextern int dosify;              /* Make new entries look like MSDOS */
  1282. Xextern char *special;           /* Don't compress special suffixes */
  1283. Xextern int verbose;             /* Report oddities in zip file structure */
  1284. Xextern int level;               /* Compression level */
  1285. X#ifdef VMS
  1286. X   extern int vmsver;           /* Append VMS version number to file names */
  1287. X#endif /* VMS */
  1288. Xextern int linkput;             /* Store symbolic links as such */
  1289. Xextern int noisy;               /* False for quiet operation */
  1290. Xextern char *key;               /* Scramble password or NULL */
  1291. Xextern char *tempath;           /* Path for temporary files */
  1292. Xextern char *zipfile;           /* New or existing zip archive (zip file) */
  1293. Xextern ulg zipbeg;              /* Starting offset of zip structures */
  1294. Xextern ulg cenbeg;              /* Starting offset of central directory */
  1295. Xextern struct zlist far *zfiles;/* Pointer to list of files in zip file */
  1296. Xextern extent zcount;           /* Number of files in zip file */
  1297. Xextern extent zcomlen;          /* Length of zip file comment */
  1298. Xextern char *zcomment;          /* Zip file comment (not zero-terminated) */
  1299. Xextern struct zlist far **zsort;/* List of files sorted by name */
  1300. Xextern struct flist far *found; /* List of names found */
  1301. Xextern struct flist far * far *fnxt;    /* Where to put next in found list */
  1302. Xextern extent fcount;           /* Count of names in found list */
  1303. Xextern int shract;              /* Shrink active */
  1304. Xextern int impact;              /* Implosion active */
  1305. X
  1306. X
  1307. X/* Diagnostic function */
  1308. X#ifdef DEBUG
  1309. X#  define diag(where) fprintf(stderr, "zip diagnostic: %s\n", where)
  1310. X#else /* !DEBUG */
  1311. X#  define diag(where)
  1312. X#endif /* ?DEBUG */
  1313. X
  1314. X
  1315. X/* Public function prototypes */
  1316. X
  1317. X        /* in zip.c, zipcloak.c, or zipsplit.c */
  1318. Xvoid warn OF((char *, char *));
  1319. X
  1320. X        /* in zipup.c */
  1321. Xint zipcopy OF((struct zlist far *, FILE *, FILE *));
  1322. X#ifndef UTIL
  1323. X   int percent OF((ulg, ulg));
  1324. X   int zipup OF((struct zlist far *, FILE *));
  1325. X#endif /* !UTIL */
  1326. X
  1327. X        /* in zipfile.c */
  1328. X#ifndef UTIL
  1329. X   struct zlist far *zsearch OF((char *));
  1330. X   int trash OF((void));
  1331. X#endif /* !UTIL */
  1332. Xchar *ziptyp OF((char *));
  1333. Xint readzipfile OF((void));
  1334. Xint putlocal OF((struct zlist far *, FILE *));
  1335. Xint putcentral OF((struct zlist far *, FILE *));
  1336. Xint putend OF((int, ulg, ulg, extent, char *, FILE *));
  1337. X
  1338. X        /* in fileio.c */
  1339. X#ifndef UTIL
  1340. X#  ifdef MSDOS
  1341. X     int wild OF((char *));
  1342. X#  endif /* MSDOS */
  1343. X   char *getnam OF((char *));
  1344. X   struct flist far *fexpel OF((struct flist far *));
  1345. X   char *in2ex OF((char *));
  1346. X   int exclude OF((void));
  1347. X   int procname OF((char *));
  1348. X   void stamp OF((char *, ulg));
  1349. X   ulg dostime OF((int, int, int, int, int, int));
  1350. X   ulg filetime OF((char *, ulg *, long *));
  1351. X   int issymlnk OF((ulg a));
  1352. X#  ifdef S_IFLNK
  1353. X#    define rdsymlnk(p,b,n) readlink(p,b,n)
  1354. X     extern int readlink OF((char *, char *, int));
  1355. X#  else /* !S_IFLNK */
  1356. X#    define rdsymlnk(p,b,n) (0)
  1357. X#  endif /* !S_IFLNK */
  1358. X   int deletedir OF((char *));
  1359. X#endif /* !UTIL */
  1360. Xint destroy OF((char *));
  1361. Xint replace OF((char *, char *));
  1362. Xint getfileattr OF((char *));
  1363. Xint setfileattr OF((char *, int));
  1364. Xchar *tempname OF((int));
  1365. Xint fcopy OF((FILE *, FILE *, ulg));
  1366. X#ifndef EXPORT
  1367. X#  ifndef MSVMS
  1368. X     void echoff OF((int));
  1369. X     void echon OF((void));
  1370. X#  endif /* !MSVMS */
  1371. X   char *getp OF((char *, char *, int));
  1372. X#endif /* !EXPORT */
  1373. X#ifdef ZMEM
  1374. X   char *memset OF((char *, int, unsigned int));
  1375. X   char *memcpy OF((char *, char *, unsigned int));
  1376. X   int memcmp OF((char *, char *, unsigned int));
  1377. X#endif /* ZMEM */
  1378. X
  1379. X        /* in crypt.c */
  1380. X#ifdef EXPORT
  1381. X#  define zfwrite fwrite
  1382. X#else /* !EXPORT */
  1383. X   void crypthead OF((char *, ulg, FILE *));
  1384. X#  ifdef UTIL
  1385. X     int zipcloak OF ((struct zlist far *, FILE *, FILE *, char *));
  1386. X     int zipbare OF ((struct zlist far *, FILE *, FILE *, char *));
  1387. X#  else /* !UTIL */
  1388. X     int zfwrite OF((voidp *, extent, extent, FILE *));
  1389. X     int zfputc OF((int, FILE *));
  1390. X#  endif /* ?UTIL */
  1391. X#endif /* ?EXPORT */
  1392. X
  1393. X        /* in util.c */
  1394. Xchar *isshexp OF((char *));
  1395. Xint shmatch OF((char *, char *));
  1396. X#ifdef MSDOS
  1397. X   int dosmatch OF((char *, char *));
  1398. X#endif /* MSDOS */
  1399. Xvoidp far **search OF((voidp *, voidp far **, extent,
  1400. X                       int (*)(voidp *, voidp far *)));
  1401. Xulg crc32 OF((ulg, int));
  1402. Xulg updcrc OF((char *, extent));
  1403. X
  1404. X        /* in shrink.c */
  1405. X#ifndef UTIL
  1406. X   int shr_setup OF((void));
  1407. X   int shr_p1 OF((uch *, extent));
  1408. X   int shr_size OF((ulg *));
  1409. X   int shr_p2 OF((FILE *));
  1410. X   int shr_clear OF((void));
  1411. X  
  1412. X        /* in implode.c */
  1413. X#  ifndef NOIMPLODE
  1414. X     int imp_setup OF((long, int));
  1415. X     int imp_p1 OF((char *, int));
  1416. X     int imp_size OF((ulg *, uch *));
  1417. X     int imp_p2 OF((FILE *));
  1418. X     int imp_clear OF((void));
  1419. X#  endif /* !NOIMPLODE */
  1420. X#endif /* !UTIL */
  1421. X
  1422. X
  1423. X/* end of zip.h */
  1424. END_OF_FILE
  1425.   if test 8017 -ne `wc -c <'zip.h'`; then
  1426.     echo shar: \"'zip.h'\" unpacked with wrong size!
  1427.   fi
  1428.   # end of 'zip.h'
  1429. fi
  1430. if test -f 'zipnote.c' -a "${1}" != "-c" ; then 
  1431.   echo shar: Will not clobber existing file \"'zipnote.c'\"
  1432. else
  1433.   echo shar: Extracting \"'zipnote.c'\" \(9810 characters\)
  1434.   sed "s/^X//" >'zipnote.c' <<'END_OF_FILE'
  1435. X/*
  1436. X
  1437. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  1438. X Permission is granted to any individual or institution to use, copy, or
  1439. X redistribute this software so long as all of the original files are included
  1440. X unmodified, that it is not sold for profit, and that this copyright notice
  1441. X is retained.
  1442. X
  1443. X*/
  1444. X
  1445. X/*
  1446. X *  zipnote.c by Mark Adler.
  1447. X */
  1448. X
  1449. X#define UTIL
  1450. X#include "revision.h"
  1451. X#include "zip.h"
  1452. X#include <signal.h>
  1453. X
  1454. X
  1455. X/* Character to mark zip entry names in the comment file */
  1456. X#define MARK '@'
  1457. X
  1458. X/* Temporary zip file name and file pointer */
  1459. Xlocal char *tempzip;
  1460. Xlocal FILE *tempzf;
  1461. X
  1462. X
  1463. X/* Local functions */
  1464. X#ifdef PROTO
  1465. X   local void err(int, char *);
  1466. X   local void handler(int);
  1467. X   local void license(void);
  1468. X   local void help(void);
  1469. X   local void putclean(char *);
  1470. X   local int catalloc(char * far *, char *);
  1471. X   void main(int, char **);
  1472. X#endif /* PROTO */
  1473. X
  1474. X
  1475. X
  1476. Xlocal void err(c, h)
  1477. Xint c;                  /* error code from the ZE_ class */
  1478. Xchar *h;                /* message about how it happened */
  1479. X/* Issue a message for the error, clean up files and memory, and exit. */
  1480. X{
  1481. X  if (PERR(c))
  1482. X    perror("zipnote error");
  1483. X  fprintf(stderr, "zipnote error: %s (%s)\n", errors[c-1], h);
  1484. X  if (tempzf != NULL)
  1485. X    fclose(tempzf);
  1486. X  if (tempzip != NULL)
  1487. X  {
  1488. X    destroy(tempzip);
  1489. X    free((voidp *)tempzip);
  1490. X  }
  1491. X  if (zipfile != NULL)
  1492. X    free((voidp *)zipfile);
  1493. X#ifdef VMS
  1494. X  exit(0);
  1495. X#else /* !VMS */
  1496. X  exit(c);
  1497. X#endif /* ?VMS */
  1498. X}
  1499. X
  1500. X
  1501. Xlocal void handler(s)
  1502. Xint s;                  /* signal number (ignored) */
  1503. X/* Upon getting a user interrupt, abort cleanly using err(). */
  1504. X{
  1505. X#ifndef MSDOS
  1506. X  putc('\n', stderr);
  1507. X#endif /* !MSDOS */
  1508. X  err(ZE_ABORT, "aborting");
  1509. X  s++;                                  /* keep some compilers happy */
  1510. X}
  1511. X
  1512. X
  1513. Xvoid warn(a, b)
  1514. Xchar *a, *b;            /* message strings juxtaposed in output */
  1515. X/* Print a warning message to stderr and return. */
  1516. X{
  1517. X  fprintf(stderr, "zipnote warning: %s%s\n", a, b);
  1518. X}
  1519. X
  1520. X
  1521. Xlocal void license()
  1522. X/* Print license information to stdout. */
  1523. X{
  1524. X  extent i;             /* counter for copyright array */
  1525. X
  1526. X  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
  1527. X    puts(copyright[i]);
  1528. X  for (i = 0; i < sizeof(disclaimer)/sizeof(char *); i++)
  1529. X    puts(disclaimer[i]);
  1530. X}
  1531. X
  1532. X
  1533. Xlocal void help()
  1534. X/* Print help (along with license info) to stdout. */
  1535. X{
  1536. X  extent i;             /* counter for help array */
  1537. X
  1538. X  /* help array */
  1539. X  static char *text[] = {
  1540. X"",
  1541. X"ZipNote %d.%d (%s)",
  1542. X"Usage:  zipnote [-w] [-b path] zipfile",
  1543. X"  the default action is to write the comments in zipfile to stdout",
  1544. X"  -w   write the zipfile comments from stdin",
  1545. X"  -b   use \"path\" for the temporary zip file",
  1546. X"  -h   show this help               -l   show software license",
  1547. X"",
  1548. X"Example:",
  1549. X#ifdef VMS
  1550. X"     define/user sys$output foo.tmp",
  1551. X"     zipnote foo.zip",
  1552. X"     edit foo.tmp",
  1553. X"     ... then you edit the comments, save, and exit ...",
  1554. X"     define/user sys$input foo.tmp",
  1555. X"     zipnote -w foo.zip"
  1556. X#else /* !VMS */
  1557. X"     zipnote foo.zip > foo.tmp",
  1558. X"     ed foo.tmp",
  1559. X"     ... then you edit the comments, save, and exit ...",
  1560. X"     zipnote -w foo.zip < foo.tmp"
  1561. X#endif /* ?VMS */
  1562. X  };
  1563. X
  1564. X  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
  1565. X    puts(copyright[i]);
  1566. X  for (i = 0; i < sizeof(text)/sizeof(char *); i++)
  1567. X  {
  1568. X    printf(text[i], REVISION / 10, REVISION % 10, REVDATE);
  1569. X    putchar('\n');
  1570. X  }
  1571. X}
  1572. X
  1573. X
  1574. Xlocal void putclean(s)
  1575. Xchar *s;                /* string to write to stdout */
  1576. X/* Write the string s to stdout, filtering out control characters that are
  1577. X   not tab or newline (mainly to remove carriage returns), and prefix MARK's
  1578. X   and backslashes with a backslash.  Also, terminate with a newline if
  1579. X   needed. */
  1580. X{
  1581. X  int c;                /* next character in string */
  1582. X  int e;                /* last character written */
  1583. X
  1584. X  e = '\n';                     /* if empty, write nothing */
  1585. X  while ((c = *s++) != 0)
  1586. X  {
  1587. X    if (c == MARK || c == '\\')
  1588. X      putchar('\\');
  1589. X    if (c >= ' ' || c == '\t' || c == '\n')
  1590. X      putchar(e = c);
  1591. X  }
  1592. X  if (e != '\n')
  1593. X    putchar('\n');
  1594. X}
  1595. X
  1596. X
  1597. Xlocal int catalloc(a, s)
  1598. Xchar * far *a;          /* pointer to a pointer to a malloc'ed string */
  1599. Xchar *s;                /* string to concatenate on a */
  1600. X/* Concatentate the string s to the malloc'ed string pointed to by a.
  1601. X   Preprocess s by removing backslash escape characters. */
  1602. X{
  1603. X  char *p;              /* temporary pointer */
  1604. X  char *q;              /* temporary pointer */
  1605. X
  1606. X  for (p = q = s; *q; *p++ = *q++)
  1607. X    if (*q == '\\' && *(q+1))
  1608. X      q++;
  1609. X  *p = 0;
  1610. X  if ((p = malloc(strlen(*a) + strlen(s) + 3)) == NULL)
  1611. X    return ZE_MEM;
  1612. X  strcat(strcat(strcpy(p, *a), **a ? "\r\n" : ""), s);
  1613. X  free((voidp *)*a);
  1614. X  *a = p;
  1615. X  return ZE_OK;
  1616. X}
  1617. X
  1618. X
  1619. Xvoid main(argc, argv)
  1620. Xint argc;               /* number of tokens in command line */
  1621. Xchar **argv;            /* command line tokens */
  1622. X/* Write the comments in the zipfile to stdout, or read them from stdin. */
  1623. X{
  1624. X  char a[FNMAX+1];      /* input line buffer */
  1625. X  ulg c;                /* start of central directory */
  1626. X  int k;                /* next argument type */
  1627. X  char *q;              /* steps through option arguments */
  1628. X  int r;                /* arg counter, temporary variable */
  1629. X  ulg s;                /* length of central directory */
  1630. X  int t;                /* attributes of zip file */
  1631. X  int w;                /* true if updating zip file from stdin */
  1632. X  FILE *x, *y;          /* input and output zip files */
  1633. X  struct zlist far *z;  /* steps through zfiles linked list */
  1634. X
  1635. X
  1636. X  /* If no args, show help */
  1637. X  if (argc == 1)
  1638. X  {
  1639. X    help();
  1640. X    exit(0);
  1641. X  }
  1642. X
  1643. X  /* Go through args */
  1644. X  zipfile = tempzip = NULL;
  1645. X  tempzf = NULL;
  1646. X  signal(SIGINT, handler);
  1647. X  signal(SIGTERM, handler);
  1648. X  k = w = 0;
  1649. X  for (r = 1; r < argc; r++)
  1650. X    if (*argv[r] == '-')
  1651. X      if (argv[r][1])
  1652. X        for (q = argv[r]+1; *q; q++)
  1653. X          switch(*q)
  1654. X          {
  1655. X            case 'b':   /* Specify path for temporary file */
  1656. X              if (k)
  1657. X                err(ZE_PARMS, "use -b before zip file name");
  1658. X              else
  1659. X                k = 1;          /* Next non-option is path */
  1660. X              break;
  1661. X            case 'h':   /* Show help */
  1662. X              help();  exit(0);
  1663. X            case 'l':   /* Show copyright and disclaimer */
  1664. X              license();  exit(0);
  1665. X            case 'w':
  1666. X              w = 1;  break;
  1667. X            default:
  1668. X              err(ZE_PARMS, "unknown option");
  1669. X          }
  1670. X      else
  1671. X        err(ZE_PARMS, "zip file cannot be stdin");
  1672. X    else
  1673. X      if (k == 0)
  1674. X        if (zipfile == NULL)
  1675. X        {
  1676. X          if ((zipfile = ziptyp(argv[r])) == NULL)
  1677. X            err(ZE_MEM, "was processing arguments");
  1678. X        }
  1679. X        else
  1680. X          err(ZE_PARMS, "can only specify one zip file");
  1681. X      else
  1682. X      {
  1683. X        tempath = argv[r];
  1684. X        k = 0;
  1685. X      }
  1686. X  if (zipfile == NULL)
  1687. X    err(ZE_PARMS, "need to specify zip file");
  1688. X
  1689. X  /* Read zip file */
  1690. X  if ((r = readzipfile()) != ZE_OK)
  1691. X    err(r, zipfile);
  1692. X  if (zfiles == NULL)
  1693. X    err(ZE_NAME, zipfile);
  1694. X
  1695. X  /* Put comments to stdout, if not -u */
  1696. X  if (!w)
  1697. X  {
  1698. X    for (z = zfiles; z != NULL; z = z->nxt)
  1699. X    {
  1700. X      printf("%c %s\n", MARK, z->zname);
  1701. X      if (z->com)
  1702. X        putclean(z->comment);
  1703. X      putchar(MARK);  putchar('\n');
  1704. X    }
  1705. X    putchar(MARK);  putchar('\n');
  1706. X    if (zcomlen)
  1707. X      putclean(zcomment);
  1708. X    exit(ZE_OK);
  1709. X  }
  1710. X
  1711. X  /* If updating comments, make sure zip file is writeable */
  1712. X  if ((x = fopen(zipfile, "a")) == NULL)
  1713. X    err(ZE_CREAT, zipfile);
  1714. X  fclose(x);
  1715. X  t = getfileattr(zipfile);
  1716. X
  1717. X  /* Process stdin, replacing comments */
  1718. X  for (z = zfiles; z != NULL; z = z->nxt)
  1719. X  {
  1720. X    if (gets(a) == NULL || a[0] != MARK || a[1] != ' ' ||
  1721. X        strcmp(a + 2, z->zname))
  1722. X      err(ZE_NOTE, "missing entry name");
  1723. X    if (z->com)
  1724. X      free((voidp *)z->comment);
  1725. X    z->comment = malloc(1);  *(z->comment) = 0;
  1726. X    while (gets(a) != NULL && *a != MARK)
  1727. X      if ((r = catalloc(&(z->comment), a)) != ZE_OK)
  1728. X        err(r, "was building new comments");
  1729. X    if (a[1])
  1730. X      err(ZE_NOTE, "missing comment end line");
  1731. X    z->com = strlen(z->comment);
  1732. X  }
  1733. X  if (gets(a) == NULL || a[0] != MARK || a[1])
  1734. X    err(ZE_NOTE, "missing zip file comment marker line");
  1735. X  zcomment = malloc(1);  *zcomment = 0;
  1736. X  while (gets(a) != NULL)
  1737. X    if ((r = catalloc(&zcomment, a)) != ZE_OK)
  1738. X      err(r, "was building new comments");
  1739. X  zcomlen = strlen(zcomment);
  1740. X
  1741. X  /* Open output zip file for writing */
  1742. X  if ((tempzf = y = fopen(tempzip = tempname('Z'), FOPW)) == NULL)
  1743. X    err(ZE_TEMP, tempzip);
  1744. X
  1745. X  /* Open input zip file again, copy preamble if any */
  1746. X  if ((x = fopen(zipfile, FOPR)) == NULL)
  1747. X    err(ZE_NAME, zipfile);
  1748. X  if (zipbeg && (r = fcopy(x, y, zipbeg)) != ZE_OK)
  1749. X    err(r, r == ZE_TEMP ? tempzip : zipfile);
  1750. X
  1751. X  /* Go through local entries, copying them over as is */
  1752. X  for (z = zfiles; z != NULL; z = z->nxt)
  1753. X    if ((r = zipcopy(z, x, y)) != ZE_OK)
  1754. X      err(r, "was copying an entry");
  1755. X  fclose(x);
  1756. X
  1757. X  /* Write central directory and end of central directory with new comments */
  1758. X  if ((c = ftell(y)) == -1L)    /* get start of central */
  1759. X    err(ZE_TEMP, tempzip);
  1760. X  for (z = zfiles; z != NULL; z = z->nxt)
  1761. X    if ((r = putcentral(z, y)) != ZE_OK)
  1762. X      err(r, tempzip);
  1763. X  if ((s = ftell(y)) == -1L)    /* get end of central */
  1764. X    err(ZE_TEMP, tempzip);
  1765. X  s -= c;                       /* compute length of central */
  1766. X  if ((r = putend((int)zcount, s, c, zcomlen, zcomment, y)) != ZE_OK)
  1767. X    err(r, tempzip);
  1768. X  tempzf = NULL;
  1769. X  if (fclose(y))
  1770. X    err(ZE_TEMP, tempzip);
  1771. X  if ((r = replace(zipfile, tempzip)) != ZE_OK)
  1772. X  {
  1773. X    warn("new zip file left as: ", tempzip);
  1774. X    free((voidp *)tempzip);
  1775. X    tempzip = NULL;
  1776. X    err(r, "was replacing the original zip file");
  1777. X  }
  1778. X  free((voidp *)tempzip);
  1779. X  tempzip = NULL;
  1780. X  setfileattr(zipfile, t);
  1781. X  free((voidp *)zipfile);
  1782. X  zipfile = NULL;
  1783. X
  1784. X  /* Done! */
  1785. X  exit(ZE_OK);
  1786. X}
  1787. END_OF_FILE
  1788.   if test 9810 -ne `wc -c <'zipnote.c'`; then
  1789.     echo shar: \"'zipnote.c'\" unpacked with wrong size!
  1790.   fi
  1791.   # end of 'zipnote.c'
  1792. fi
  1793. echo shar: End of archive 8 \(of 9\).
  1794. cp /dev/null ark8isdone
  1795. MISSING=""
  1796. for I in 1 2 3 4 5 6 7 8 9 ; do
  1797.     if test ! -f ark${I}isdone ; then
  1798.     MISSING="${MISSING} ${I}"
  1799.     fi
  1800. done
  1801. if test "${MISSING}" = "" ; then
  1802.     echo You have unpacked all 9 archives.
  1803.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1804. else
  1805.     echo You still must unpack the following archives:
  1806.     echo "        " ${MISSING}
  1807. fi
  1808. exit 0
  1809. exit 0 # Just in case...
  1810. -- 
  1811. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1812. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1813. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1814. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1815.