home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume31 / unzip50 / part03 < prev    next >
Encoding:
Text File  |  1992-08-22  |  58.0 KB  |  1,828 lines

  1. Newsgroups: comp.sources.misc
  2. From: zip-bugs@cs.ucla.edu (Info-ZIP group)
  3. Subject:  v31i106:  unzip50 - Info-ZIP portable UnZip, version 5.0, Part03/14
  4. Message-ID: <1992Aug24.025251.24218@sparky.imd.sterling.com>
  5. X-Md4-Signature: fabdf9c0a06a78514d0221842abb608b
  6. Date: Mon, 24 Aug 1992 02:52:51 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: zip-bugs@cs.ucla.edu (Info-ZIP group)
  10. Posting-number: Volume 31, Issue 106
  11. Archive-name: unzip50/part03
  12. Supersedes: unzip: Volume 29, Issue 31-42
  13. Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT AMIGA?, !ATARI, symlink, SGI, DEC, Cray, Convex, Amdahl, Sun
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  MAC/Contents file_io.c match.c
  22. # Wrapped by kent@sparky on Sun Aug 23 21:09:31 1992
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 3 (of 14)."'
  26. if test -f 'MAC/Contents' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'MAC/Contents'\"
  28. else
  29.   echo shar: Extracting \"'MAC/Contents'\" \(1275 characters\)
  30.   sed "s/^X//" >'MAC/Contents' <<'END_OF_FILE'
  31. XContents of the MAC sub-archive for UnZip 5.0 and later:
  32. X
  33. X  Contents                this file
  34. X  macfile.c               Macintosh filesystem code
  35. X  macstat.c               Macintosh stat() emulation
  36. X  macstat.h               header file for stat() emulation
  37. X  aztec.make              MPW makefile for Aztec C (binary)
  38. X  mpw.make                MPW makefile for MPW C (binary)
  39. X  thinkc.hqx              Think C project file (BinHex)
  40. X  thinkc.rsrc.hqx         resource file for Macintosh unzip (BinHex)
  41. X
  42. XThe makefiles are marked "binary" because they contain a few special
  43. Xcharacters (which look a lot like D's and 6's under Unix).  They're
  44. Xbasically readable, but e-mailing them without protection is likely
  45. Xto strip the high bit off these characters, rendering the makefiles
  46. Xless than useful.  Be forewarned...
  47. X
  48. XThe Think C files are BinHexed because they contain Mac resource forks
  49. Xin addition to the ordinary data forks (or maybe they only contain re-
  50. Xsource forks...whatever).  While Zip 1.9 and UnZip 5.0 can save/restore
  51. Xsuch information, it's not too helpful to make use of this feature until
  52. Xeveryone *has* UnZip 5.0.  Also, there's no way to store such information
  53. Xin a .tar.Z file, for instance.  Both of the .hqx files must be converted
  54. Xwith BinHex 4.0 (or later).
  55. END_OF_FILE
  56.   if test 1275 -ne `wc -c <'MAC/Contents'`; then
  57.     echo shar: \"'MAC/Contents'\" unpacked with wrong size!
  58.   fi
  59.   # end of 'MAC/Contents'
  60. fi
  61. if test -f 'file_io.c' -a "${1}" != "-c" ; then 
  62.   echo shar: Will not clobber existing file \"'file_io.c'\"
  63. else
  64.   echo shar: Extracting \"'file_io.c'\" \(34380 characters\)
  65.   sed "s/^X//" >'file_io.c' <<'END_OF_FILE'
  66. X/*---------------------------------------------------------------------------
  67. X
  68. X  file_io.c
  69. X
  70. X  This file contains routines for doing direct input/output, file-related
  71. X  sorts of things.  Most of the system-specific code for unzip is contained
  72. X  here, including the non-echoing password code for decryption (bottom).
  73. X
  74. X  ---------------------------------------------------------------------------*/
  75. X
  76. X
  77. X#ifndef __GO32__
  78. X#  define const
  79. X#endif
  80. X
  81. X#define FILE_IO_C
  82. X#include "unzip.h"
  83. X
  84. X#ifdef  MSWIN
  85. X#  include "wizunzip.h"
  86. X#endif
  87. X
  88. X
  89. X/************************************/
  90. X/*  File_IO Local Prototypes, etc.  */
  91. X/************************************/
  92. X
  93. X#if (!defined(DOS_OS2) || defined(MSWIN))
  94. X   static int dos2unix __((unsigned char *buf, int len));
  95. X   int CR_flag = 0;      /* when last char of buffer == CR (for dos2unix()) */
  96. X#endif
  97. X
  98. X#ifdef OS2
  99. X   extern int   longname;          /* set in mapname.c */
  100. X   extern char  longfilename[];
  101. X#endif
  102. X
  103. X#ifdef CRYPT
  104. X#  if (defined(DOS_OS2) || defined(VMS))
  105. X#    define MSVMS
  106. X#    ifdef DOS_OS2
  107. X#      ifdef __EMX__
  108. X#        define getch() _read_kbd(0, 1, 0)
  109. X#      else
  110. X#        ifdef __GO32__
  111. X#          include <pc.h>
  112. X#          define getch() getkey()
  113. X#        else /* !__GO32__ */
  114. X#          include <conio.h>
  115. X#        endif /* ?__GO32__ */
  116. X#      endif
  117. X#    else /* !DOS_OS2 */
  118. X#      define getch() getc(stderr)
  119. X#      define OFF 0   /* for echo control */
  120. X#      define ON 1
  121. X#      define echoff(f) echo(OFF)
  122. X#      define echon()   echo(ON)
  123. X#      include <descrip.h>
  124. X#      include <iodef.h>
  125. X#      include <ttdef.h>
  126. X#      if !defined(SS$_NORMAL)
  127. X#        define SS$_NORMAL 1   /* only thing we need from <ssdef.h> */
  128. X#      endif
  129. X#    endif /* ?DOS_OS2 */
  130. X#  else /* !(DOS_OS2 || VMS) */
  131. X#    ifdef TERMIO       /* Amdahl, Cray, all SysV? */
  132. X#      ifdef CONVEX
  133. X#        include <sys/termios.h>
  134. X#        include <sgtty.h>
  135. X#      else /* !CONVEX */
  136. X#        ifdef LINUX
  137. X#          include <termios.h>
  138. X#        else /* !LINUX */
  139. X#          include <sys/termio.h>
  140. X#        endif /* ?LINUX */
  141. X#        define sgttyb termio
  142. X#        define sg_flags c_lflag
  143. X#      endif /* ?CONVEX */
  144. X       int ioctl OF((int, int, voidp *));
  145. X#      define GTTY(f,s) ioctl(f,TCGETA,(voidp *)s)
  146. X#      define STTY(f,s) ioctl(f,TCSETAW,(voidp *)s)
  147. X#    else /* !TERMIO */
  148. X#      if (!defined(MINIX) && !defined(__386BSD__))
  149. X#        include <sys/ioctl.h>
  150. X#      endif /* !MINIX && !__386BSD__ */
  151. X#      include <sgtty.h>
  152. X#      ifdef __386BSD__
  153. X#        define GTTY(f, s) ioctl(f, TIOCGETP, (voidp *) s)
  154. X#        define STTY(f, s) ioctl(f, TIOCSETP, (voidp *) s)
  155. X#      else /* !__386BSD__ */
  156. X#        define GTTY gtty
  157. X#        define STTY stty
  158. X         int gtty OF((int, struct sgttyb *));
  159. X         int stty OF((int, struct sgttyb *));
  160. X#      endif /* ?__386BSD__ */
  161. X#    endif /* ?TERMIO */
  162. X     int isatty OF((int));
  163. X     char *ttyname OF((int));
  164. X#    if (defined(PROTO) && !defined(__GNUC__) && !defined(_AIX))
  165. X       int open (char *, int, ...);
  166. X#    endif
  167. X     int close OF((int));
  168. X     int read OF((int, voidp *, int));
  169. X#  endif /* ?(DOS_OS2 || VMS) */
  170. X#endif /* CRYPT */
  171. X
  172. X
  173. X
  174. X
  175. X
  176. X/******************************/
  177. X/* Function open_input_file() */
  178. X/******************************/
  179. X
  180. Xint open_input_file()    /* return non-zero if open failed */
  181. X{
  182. X    /*
  183. X     *  open the zipfile for reading and in BINARY mode to prevent cr/lf
  184. X     *  translation, which would corrupt the bitstreams
  185. X     */
  186. X
  187. X#ifdef VMS
  188. X    zipfd = open(zipfn, O_RDONLY, 0, "ctx=stm");
  189. X#else /* !VMS */
  190. X#ifdef UNIX
  191. X    zipfd = open(zipfn, O_RDONLY);
  192. X#else /* !UNIX */
  193. X#ifdef MACOS
  194. X    zipfd = open(zipfn, 0);
  195. X#else /* !MACOS */
  196. X    zipfd = open(zipfn, O_RDONLY | O_BINARY);
  197. X#endif /* ?MACOS */
  198. X#endif /* ?UNIX */
  199. X#endif /* ?VMS */
  200. X    if (zipfd < 1) {
  201. X        fprintf(stderr, "error:  can't open zipfile [ %s ]\n", zipfn);
  202. X        return (1);
  203. X    }
  204. X    return 0;
  205. X}
  206. X
  207. X
  208. X
  209. X
  210. X
  211. X/**********************/
  212. X/* Function readbuf() */
  213. X/**********************/
  214. X
  215. Xint readbuf(buf, size)
  216. X    char *buf;
  217. X    register unsigned size;
  218. X{                               /* return number of bytes read into buf */
  219. X    register int count;
  220. X    int n;
  221. X
  222. X    n = size;
  223. X    while (size) {
  224. X        if (incnt == 0) {
  225. X            if ((incnt = read(zipfd, (char *)inbuf, INBUFSIZ)) <= 0)
  226. X                return (n-size);
  227. X            /* buffer ALWAYS starts on a block boundary:  */
  228. X            cur_zipfile_bufstart += INBUFSIZ;
  229. X            inptr = inbuf;
  230. X        }
  231. X        count = MIN(size, (unsigned)incnt);
  232. X        memcpy(buf, inptr, count);
  233. X        buf += count;
  234. X        inptr += count;
  235. X        incnt -= count;
  236. X        size -= count;
  237. X    }
  238. X    return (n);
  239. X}
  240. X
  241. X
  242. X
  243. X
  244. X
  245. X#ifndef VMS   /* for VMS use code in vms.c (old VMS code below is retained
  246. X               * in case of problems...will be removed in a later release) */
  247. X
  248. X/*********************************/
  249. X/* Function create_output_file() */
  250. X/*********************************/
  251. X
  252. Xint create_output_file()         /* return non-0 if creat failed */
  253. X{
  254. X/*---------------------------------------------------------------------------
  255. X    Create the output file with appropriate permissions.  If we've gotten to
  256. X    this point and the file still exists, we have permission to blow it away.
  257. X  ---------------------------------------------------------------------------*/
  258. X
  259. X#if (!defined(DOS_OS2) || defined(MSWIN))
  260. X    CR_flag = 0;   /* hack to get CR at end of buffer working */
  261. X#endif
  262. X
  263. X#if (defined(UNIX) && !defined(AMIGA))
  264. X    {
  265. X        int mask;
  266. X
  267. X#ifndef VMS
  268. X        if (!stat(filename, &statbuf) && (unlink(filename) < 0)) {
  269. X            fprintf(stderr, "\n%s:  cannot delete old copy\n", filename);
  270. X            return 1;
  271. X        }
  272. X#       define EXTRA_ARGS
  273. X#else /* VMS */
  274. X#       define EXTRA_ARGS   ,"rfm=stmlf","rat=cr"
  275. X#endif /* ?VMS */
  276. X
  277. X        mask = umask(0);   /* now know that we own it */
  278. X        outfd = creat(filename, 0xffff & pInfo->unix_attr  EXTRA_ARGS);
  279. X        umask(mask);                                            /* VMS, Unix */
  280. X    }
  281. X#else /* !UNIX || AMIGA */  /* file permissions set after file closed */
  282. X#ifndef MACOS
  283. X    outfd = creat(filename, S_IWRITE | S_IREAD);     /* DOS, OS2, Mac, Amiga */
  284. X#else /* MACOS */
  285. X    {
  286. X        short fDataFork=TRUE;
  287. X        MACINFO mi;
  288. X        OSErr err;
  289. X
  290. X        fMacZipped = FALSE;
  291. X        CtoPstr(filename);
  292. X        if (extra_field &&
  293. X            (lrec.extra_field_length > sizeof(MACINFOMIN)) &&
  294. X            (lrec.extra_field_length <= sizeof(MACINFO))) {
  295. X            BlockMove(extra_field, &mi, lrec.extra_field_length);
  296. X            if ((makeword((byte *)&mi.header) == 1992) &&
  297. X                (makeword((byte *)&mi.data) ==
  298. X                  lrec.extra_field_length-sizeof(ZIP_EXTRA_HEADER)) &&
  299. X                (mi.signature == 'JLEE')) {
  300. X                gostCreator = mi.finfo.fdCreator;
  301. X                gostType = mi.finfo.fdType;
  302. X                fDataFork = (mi.flags & 1) ? TRUE : FALSE;
  303. X                fMacZipped = true;
  304. X                /* If it was Zipped w/Mac version, the filename has either */
  305. X                /* a 'd' or 'r' appended.  Remove the d/r when unzipping */
  306. X                filename[0]-=1;
  307. X            }
  308. X        }
  309. X        if (!fMacZipped) {
  310. X            if (!aflag)
  311. X                gostType = gostCreator = '\?\?\?\?';
  312. X            else {
  313. X#ifdef THINK_C
  314. X                gostCreator = 'KAHL';
  315. X#else
  316. X#ifdef MCH_MACINTOSH
  317. X                gostCreator = 'Manx';
  318. X#else
  319. X                gostCreator = 'MPS ';
  320. X#endif
  321. X#endif
  322. X                gostType = 'TEXT';
  323. X            }
  324. X        }
  325. X        PtoCstr(filename);
  326. X
  327. X        outfd = creat(filename, 0);
  328. X        if (fMacZipped) {
  329. X            CtoPstr(filename);
  330. X            if (hfsflag) {
  331. X                HParamBlockRec   hpbr;
  332. X    
  333. X                hpbr.fileParam.ioNamePtr = (StringPtr)filename;
  334. X                hpbr.fileParam.ioVRefNum = gnVRefNum;
  335. X                hpbr.fileParam.ioDirID = glDirID;
  336. X                hpbr.fileParam.ioFlFndrInfo = mi.finfo;
  337. X                hpbr.fileParam.ioFlCrDat = mi.lCrDat;
  338. X                hpbr.fileParam.ioFlMdDat = mi.lMdDat;
  339. X                err = PBHSetFInfo(&hpbr, 0);
  340. X            } else {
  341. X                err = SetFInfo((StringPtr)filename , 0, &mi.finfo);
  342. X            }
  343. X            PtoCstr(filename);
  344. X        }
  345. X        if (outfd != -1)
  346. X            outfd = open(filename, (fDataFork)? 1 : 2);
  347. X    }
  348. X#endif /* ?MACOS */
  349. X#endif /* ?(UNIX && !AMIGA) */
  350. X
  351. X    if (outfd < 1) {
  352. X        fprintf(stderr, "\n%s:  cannot create\n", filename);
  353. X        return 1;
  354. X    }
  355. X
  356. X/*---------------------------------------------------------------------------
  357. X    If newly created file is in text mode and should be binary (to disable
  358. X    automatic CR/LF translations), either close it and reopen as binary or
  359. X    else change the mode to binary (DOS, OS/2).
  360. X  ---------------------------------------------------------------------------*/
  361. X
  362. X#if (!defined(UNIX) && !defined(MACOS))
  363. X    if (!aflag) {
  364. X#ifdef DOS_OS2
  365. X        if (setmode(outfd, O_BINARY) == -1) {
  366. X#else /* !DOS_OS2 */
  367. X        close(outfd);
  368. X        if ((outfd = open(filename, O_RDWR | O_BINARY)) < 1) {
  369. X#endif /* ?DOS_OS2 */
  370. X            fprintf(stderr, "Can't make output file binary:  %s\n", filename);
  371. X            return 1;
  372. X        }
  373. X    }
  374. X#endif /* !UNIX && !MACOS */
  375. X
  376. X    return 0;
  377. X}
  378. X
  379. X#endif /* !VMS */
  380. X
  381. X
  382. X
  383. X
  384. X
  385. X/****************************/
  386. X/* Function FillBitBuffer() */
  387. X/****************************/
  388. X
  389. Xint FillBitBuffer()
  390. X{
  391. X    /*
  392. X     * Fill bitbuf, which is 32 bits.  This function is only used by the
  393. X     * READBIT and PEEKBIT macros (which are used by all of the uncompression
  394. X     * routines).
  395. X     */
  396. X    UWORD temp;
  397. X
  398. X    zipeof = 1;
  399. X    while (bits_left < 25 && ReadByte(&temp) == 8)
  400. X    {
  401. X      bitbuf |= (ULONG)temp << bits_left;
  402. X      bits_left += 8;
  403. X      zipeof = 0;
  404. X    }
  405. X    return 0;
  406. X}
  407. X
  408. X
  409. X
  410. X
  411. X
  412. X/***********************/
  413. X/* Function ReadByte() */
  414. X/***********************/
  415. X
  416. Xint ReadByte(x)
  417. X    UWORD *x;
  418. X{
  419. X    /*
  420. X     * read a byte; return 8 if byte available, 0 if not
  421. X     */
  422. X
  423. X    if (mem_mode)
  424. X        return ReadMemoryByte(x);
  425. X
  426. X    if (csize-- <= 0)
  427. X        return 0;
  428. X
  429. X    if (incnt == 0) {
  430. X        if ((incnt = read(zipfd, (char *)inbuf, INBUFSIZ)) <= 0)
  431. X            return 0;
  432. X        /* buffer ALWAYS starts on a block boundary:  */
  433. X        cur_zipfile_bufstart += INBUFSIZ;
  434. X        inptr = inbuf;
  435. X#ifdef CRYPT
  436. X        if (pInfo->encrypted) {
  437. X            byte *p;
  438. X            int n, t;
  439. X
  440. X            for (n = (longint)incnt > csize + 1 ? (int)csize + 1 : incnt,
  441. X                 p = inptr; n--; p++)
  442. X                *p = (byte) DECRYPT(*p);
  443. X        }
  444. X#endif /* CRYPT */
  445. X    }
  446. X    *x = *inptr++;
  447. X    --incnt;
  448. X    return 8;
  449. X}
  450. X
  451. X
  452. X
  453. X
  454. X
  455. X#ifndef VMS   /* for VMS use code in vms.c */
  456. X
  457. X/**************************/
  458. X/* Function FlushOutput() */
  459. X/**************************/
  460. X
  461. Xint FlushOutput()
  462. X{
  463. X    /*
  464. X     * flush contents of output buffer; return PK-type error code
  465. X     */
  466. X#if (!defined(DOS_OS2) || defined(MSWIN))
  467. X    int saved_ctrlZ = FALSE;
  468. X#endif
  469. X    int len;
  470. X
  471. X
  472. X    if (mem_mode) {
  473. X        int rc = FlushMemory();
  474. X        outpos += outcnt;
  475. X        outcnt = 0;
  476. X        outptr = outbuf;
  477. X        return rc;
  478. X    }
  479. X
  480. X    if (disk_full) {
  481. X        outpos += outcnt;   /* fake emptied buffer */
  482. X        outcnt = 0;
  483. X        outptr = outbuf;
  484. X        return 50;          /* ignore rest of this file */
  485. X    }
  486. X
  487. X    if (outcnt) {
  488. X        UpdateCRC(outbuf, outcnt);
  489. X
  490. X        if (!tflag) {
  491. X#if (!defined(DOS_OS2) || defined(MSWIN))
  492. X            if (aflag) {
  493. X                if (outbuf[outcnt-1] == CTRLZ) {
  494. X                    --outcnt;
  495. X                    saved_ctrlZ = TRUE;
  496. X                }
  497. X                len = dos2unix(outbuf, outcnt);
  498. X            } else
  499. X#endif /* !DOS_OS2 || MSWIN */
  500. X                len = outcnt;
  501. X#ifdef MACOS
  502. X            if ((giCursor+1) >> 2 != (giCursor>>2))
  503. X                SetCursor( *rghCursor[((giCursor+1)>>2)&0x03] );
  504. X            giCursor = (giCursor+1) & 15;
  505. X#endif /* MACOS */
  506. X#ifdef MSWIN
  507. X            /* if writing to console vs. actual file, write to Msg Window */
  508. X            if (cflag)
  509. X                WriteBufferToMsgWin(outout, len, FALSE);
  510. X            else if (_lwrite(outfd, outout, len) != (UINT)len)
  511. X#else /* !MSWIN */
  512. X            if (write(outfd, (char *)outout, len) != len)
  513. X#endif /* ?MSWIN */
  514. X#ifdef DOS_OS2
  515. X                if (!cflag)           /* ^Z treated as EOF, removed with -c */
  516. X#else /* !DOS_OS2 */
  517. X#ifdef MINIX
  518. X                if (errno == EFBIG)
  519. X                    if (write(fd, outout, len/2) != len/2  ||
  520. X                        write(fd, outout+len/2, len/2) != len/2)
  521. X#endif /* MINIX */
  522. X#endif /* ?DOS_OS2 */
  523. X                {
  524. X                    /* GRR: add test for force_flag when has its own switch */
  525. X                    fprintf(stderr,
  526. X                      "\n%s:  write error (disk full?).  Continue? (y/n/^C) ",
  527. X                      filename);
  528. X                    FFLUSH   /* for Amiga and Mac MPW */
  529. X#ifdef MSWIN
  530. X                    disk_full = 2;
  531. X#else /* !MSWIN */
  532. X                    fgets(answerbuf, 9, stdin);
  533. X                    if (*answerbuf == 'y')   /* stop writing to this file */
  534. X                        disk_full = 1;       /*  (outfd bad?), but new OK */
  535. X                    else
  536. X                        disk_full = 2;       /* no:  exit program */
  537. X#endif /* ?MSWIN */
  538. X                    return 50;    /* 50:  disk full */
  539. X                }
  540. X        }
  541. X        outpos += outcnt;
  542. X        outcnt = 0;
  543. X        outptr = outbuf;
  544. X#if (!defined(DOS_OS2) || defined(MSWIN))
  545. X        if (saved_ctrlZ) {
  546. X            *outptr++ = CTRLZ;
  547. X            ++outcnt;
  548. X        }
  549. X#endif /* !DOS_OS2 || MSWIN */
  550. X    }
  551. X    return 0;                   /* 0:  no error */
  552. X}
  553. X
  554. X#endif /* !VMS */
  555. X
  556. X
  557. X
  558. X
  559. X
  560. X#if (!defined(DOS_OS2) || defined(MSWIN))
  561. X
  562. X/***********************/
  563. X/* Function dos2unix() */
  564. X/***********************/
  565. X
  566. Xstatic int dos2unix(buf, len)   /* GRR:  rewrite for generic text conversions */
  567. X    unsigned char *buf;
  568. X    int len;
  569. X{
  570. X    int new_len;
  571. X    int i;
  572. X#ifdef MSWIN
  573. X    unsigned char __far *walker;
  574. X#else /* !MSWIN */
  575. X    unsigned char *walker;
  576. X#endif /* ?MSWIN */
  577. X
  578. X    new_len = len;
  579. X    walker = outout;
  580. X#ifdef MACOS
  581. X    /*
  582. X     * Mac wants to strip LFs instead CRs from CRLF pairs
  583. X     */
  584. X    if (CR_flag && *buf == LF) {
  585. X        buf++;
  586. X        new_len--;
  587. X        len--;
  588. X        CR_flag = buf[len] == CR;
  589. X    }
  590. X    else
  591. X        CR_flag = buf[len - 1] == CR;
  592. X    for (i = 0; i < len; i += 1) {
  593. X        *walker++ = ascii_to_native(*buf);
  594. X        if (*buf == LF) walker[-1] = CR;
  595. X        if (*buf++ == CR && *buf == LF) {
  596. X            new_len--;
  597. X            buf++;
  598. X            i++;
  599. X        }
  600. X    }
  601. X#else /* !MACOS */
  602. X    if (CR_flag && *buf != LF)
  603. X        *walker++ = ascii_to_native(CR);
  604. X    CR_flag = buf[len - 1] == CR;
  605. X    for (i = 0; i < len; i += 1) {
  606. X        *walker++ = ascii_to_native(*buf);
  607. X        if (*buf++ == CR && *buf == LF) {
  608. X            new_len--;
  609. X            walker[-1] = ascii_to_native(*buf++);
  610. X            i++;
  611. X        }
  612. X    }
  613. X    /*
  614. X     * If the last character is a CR, then "ignore it" for now...
  615. X     */
  616. X    if (walker[-1] == ascii_to_native(CR))
  617. X        new_len--;
  618. X#endif /* ?MACOS */
  619. X    return new_len;
  620. X}
  621. X
  622. X#endif /* !DOS_OS2 || MSWIN */
  623. X
  624. X
  625. X
  626. X
  627. X
  628. X#ifdef __GO32__
  629. X
  630. Xvoid _dos_setftime(int fd, UWORD dosdate, UWORD dostime)
  631. X{
  632. X    asm("pushl %ebx");
  633. X    asm("movl %0, %%ebx": : "g" (fd));
  634. X    asm("movl %0, %%ecx": : "g" (dostime));
  635. X    asm("movl %0, %%edx": : "g" (dosdate));
  636. X    asm("movl $0x5701, %eax");
  637. X    asm("int $0x21");
  638. X    asm("popl %ebx");
  639. X}
  640. X
  641. Xvoid _dos_setfileattr(char *name, int attr)
  642. X{
  643. X    asm("movl %0, %%edx": : "g" (name));
  644. X    asm("movl %0, %%ecx": : "g" (attr));
  645. X    asm("movl $0x4301, %eax");
  646. X    asm("int $0x21");
  647. X}
  648. X
  649. X#endif /* __GO32__ */
  650. X
  651. X
  652. X
  653. X
  654. X
  655. X#ifdef DOS_OS2
  656. X
  657. X/**************************************/
  658. X/* Function set_file_time_and_close() */
  659. X/**************************************/
  660. X
  661. Xvoid set_file_time_and_close()
  662. X /*
  663. X  * MS-DOS AND OS/2 VERSION (Mac, Unix/VMS versions are below)
  664. X  *
  665. X  * Set the output file date/time stamp according to information from the
  666. X  * zipfile directory record for this member, then close the file and set
  667. X  * its permissions (archive, hidden, read-only, system).  Aside from closing
  668. X  * the file, this routine is optional (but most compilers support it).
  669. X  */
  670. X{
  671. X/*---------------------------------------------------------------------------
  672. X    Allocate local variables needed by OS/2 and Turbo C.
  673. X  ---------------------------------------------------------------------------*/
  674. X
  675. X#ifdef __TURBOC__
  676. X
  677. X    union {
  678. X        struct ftime ft;        /* system file time record */
  679. X        struct {
  680. X            UWORD ztime;        /* date and time words */
  681. X            UWORD zdate;        /* .. same format as in .ZIP file */
  682. X        } zt;
  683. X    } td;
  684. X
  685. X#endif                          /* __TURBOC__ */
  686. X
  687. X/*---------------------------------------------------------------------------
  688. X     Do not attempt to set the time stamp on standard output.
  689. X  ---------------------------------------------------------------------------*/
  690. X
  691. X    if (cflag) {
  692. X        close(outfd);
  693. X        return;
  694. X    }
  695. X
  696. X/*---------------------------------------------------------------------------
  697. X    Copy and/or convert time and date variables, if necessary; then set the
  698. X    file time/date.
  699. X  ---------------------------------------------------------------------------*/
  700. X
  701. X#ifndef OS2
  702. X#ifdef __TURBOC__
  703. X    td.zt.ztime = lrec.last_mod_file_time;
  704. X    td.zt.zdate = lrec.last_mod_file_date;
  705. X    setftime(outfd, &td.ft);
  706. X#else /* !__TURBOC__ */
  707. X#ifdef WIN32
  708. X    {
  709. X        FILETIME ft;     /* 64-bit value made up of two 32 bit [low & high] */
  710. X        WORD wDOSDate;   /* for vconvertin from DOS date to Windows NT */
  711. X        WORD wDOSTime;
  712. X        HANDLE hFile;    /* file handle (defined in Windows NT) */
  713. X
  714. X        wDOSTime = (WORD) lrec.last_mod_file_time;
  715. X        wDOSDate = (WORD) lrec.last_mod_file_date;
  716. X
  717. X        /* The DosDateTimeToFileTime() function converts a DOS date/time
  718. X         * into a 64 bit Windows NT file time */
  719. X        DosDateTimeToFileTime(wDOSDate, wDOSTime, &ft);
  720. X
  721. X        /* Close the file and then re-open it using the Win32
  722. X         * CreateFile call, so that the file can be created
  723. X         * with GENERIC_WRITE access, otherwise the SetFileTime
  724. X         * call will fail. */
  725. X        close(outfd);
  726. X
  727. X        hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
  728. X             FILE_ATTRIBUTE_NORMAL, NULL);
  729. X
  730. X        if (!SetFileTime(hFile, NULL, NULL, &ft))
  731. X            printf("\nSetFileTime failed: %d\n", GetLastError());
  732. X        CloseHandle(hFile);
  733. X        return;
  734. X    }
  735. X#else /* !WIN32 */
  736. X    _dos_setftime(outfd, lrec.last_mod_file_date, lrec.last_mod_file_time);
  737. X#endif /* ?WIN32 */
  738. X#endif /* ?__TURBOC__ */
  739. X#endif /* ?OS2 */
  740. X
  741. X/*---------------------------------------------------------------------------
  742. X    And finally we can close the file...at least everybody agrees on how to
  743. X    do *this*.  I think...  Oh yeah, also change the mode according to the
  744. X    stored file attributes, since we didn't do that when we opened the dude.
  745. X  ---------------------------------------------------------------------------*/
  746. X
  747. X    close(outfd);
  748. X
  749. X#ifdef OS2
  750. X    SetPathInfo(filename, lrec.last_mod_file_date,
  751. X                          lrec.last_mod_file_time, pInfo->dos_attr);
  752. X    if (extra_field)
  753. X        SetEAs(filename, extra_field);
  754. X    if (longname)
  755. X        SetLongNameEA(filename, longfilename);
  756. X#else /* !OS2 */
  757. X#ifdef __TURBOC__
  758. X    if (_chmod(filename, 1, pInfo->dos_attr) != pInfo->dos_attr)
  759. X        fprintf(stderr, "\nwarning:  file attributes may not be correct\n");
  760. X#else /* !__TURBOC__ */
  761. X#ifdef WIN32
  762. X    /* Attempt to set the file attributes.  SetFileAttributes returns
  763. X     * FALSE (0) if unsucessful, in which case print an error message,
  764. X     * with error value returned from GetLastError call. */
  765. X    pInfo->dos_attr = pInfo->dos_attr & 0x7F;
  766. X
  767. X    if (!(SetFileAttributes(filename, pInfo->dos_attr)))
  768. X        fprintf(stderr, "\nwarning (%d): could not set file attributes\n",
  769. X          GetLastError());
  770. X#else /* !WIN32 */
  771. X    _dos_setfileattr(filename, pInfo->dos_attr);
  772. X#endif /* ?WIN32 */
  773. X#endif /* ?__TURBOC__ */
  774. X#endif /* ?OS2 */
  775. X
  776. X} /* end function set_file_time_and_close() (DOS, OS/2) */
  777. X
  778. X
  779. X
  780. X
  781. X
  782. X#else                           /* !DOS_OS2 */
  783. X#ifdef MACOS                    /* Mac */
  784. X
  785. X/**************************************/
  786. X/* Function set_file_time_and_close() */
  787. X/**************************************/
  788. X
  789. Xvoid set_file_time_and_close()
  790. X /*
  791. X  * MAC VERSION
  792. X  */
  793. X{
  794. X    long m_time;
  795. X    DateTimeRec dtr;
  796. X    ParamBlockRec pbr;
  797. X    HParamBlockRec hpbr;
  798. X    OSErr err;
  799. X
  800. X    if (outfd != 1) {
  801. X        close(outfd);
  802. X
  803. X        /*
  804. X         * Macintosh bases all file modification times on the number of seconds
  805. X         * elapsed since Jan 1, 1904, 00:00:00.  Therefore, to maintain
  806. X         * compatibility with MS-DOS archives, which date from Jan 1, 1980,
  807. X         * with NO relation to GMT, the following conversions must be made:
  808. X         *      the Year (yr) must be incremented by 1980;
  809. X         *      and converted to seconds using the Mac routine Date2Secs(),
  810. X         *      almost similar in complexity to the Unix version :-)
  811. X         *                                     J. Lee
  812. X         */
  813. X
  814. X        dtr.year = (((lrec.last_mod_file_date >> 9) & 0x7f) + 1980);
  815. X        dtr.month = ((lrec.last_mod_file_date >> 5) & 0x0f);
  816. X        dtr.day = (lrec.last_mod_file_date & 0x1f);
  817. X
  818. X        dtr.hour = ((lrec.last_mod_file_time >> 11) & 0x1f);
  819. X        dtr.minute = ((lrec.last_mod_file_time >> 5) & 0x3f);
  820. X        dtr.second = ((lrec.last_mod_file_time & 0x1f) * 2);
  821. X
  822. X        Date2Secs(&dtr, (unsigned long *)&m_time);
  823. X        CtoPstr(filename);
  824. X        if (hfsflag) {
  825. X            hpbr.fileParam.ioNamePtr = (StringPtr)filename;
  826. X            hpbr.fileParam.ioVRefNum = gnVRefNum;
  827. X            hpbr.fileParam.ioDirID = glDirID;
  828. X            hpbr.fileParam.ioFDirIndex = 0;
  829. X            err = PBHGetFInfo(&hpbr, 0L);
  830. X            hpbr.fileParam.ioFlMdDat = m_time;
  831. X            if ( !fMacZipped )
  832. X                hpbr.fileParam.ioFlCrDat = m_time;
  833. X            hpbr.fileParam.ioDirID = glDirID;
  834. X            if (err == noErr)
  835. X                err = PBHSetFInfo(&hpbr, 0L);
  836. X            if (err != noErr)
  837. X                printf("error:  can't set the time for %s\n", filename);
  838. X        } else {
  839. X            pbr.fileParam.ioNamePtr = (StringPtr)filename;
  840. X            pbr.fileParam.ioVRefNum = pbr.fileParam.ioFVersNum =
  841. X              pbr.fileParam.ioFDirIndex = 0;
  842. X            err = PBGetFInfo(&pbr, 0L);
  843. X            pbr.fileParam.ioFlMdDat = pbr.fileParam.ioFlCrDat = m_time;
  844. X            if (err == noErr)
  845. X                err = PBSetFInfo(&pbr, 0L);
  846. X            if (err != noErr)
  847. X                printf("error:  can't set the time for %s\n", filename);
  848. X        }
  849. X
  850. X        /* set read-only perms if needed */
  851. X        if ((err == noErr) && !(pInfo->unix_attr & S_IWRITE)) {
  852. X            if (hfsflag) {
  853. X                hpbr.fileParam.ioNamePtr = (StringPtr)filename;
  854. X                hpbr.fileParam.ioVRefNum = gnVRefNum;
  855. X                hpbr.fileParam.ioDirID = glDirID;
  856. X                err = PBHSetFLock(&hpbr, 0);
  857. X            } else
  858. X                err = SetFLock((ConstStr255Param)filename, 0);
  859. X        }
  860. X        PtoCstr(filename);
  861. X    }
  862. X}
  863. X
  864. X
  865. X
  866. X
  867. X
  868. X#else /* !MACOS... */
  869. X#if (!defined(MTS) && !defined(VMS))   /* && !MTS (can't do) && !VMS: only one
  870. X                                  * left is UNIX (for VMS use code in vms.c) */
  871. X
  872. X/**************************************/
  873. X/* Function set_file_time_and_close() */
  874. X/**************************************/
  875. X
  876. Xvoid set_file_time_and_close()
  877. X /*
  878. X  * UNIX VERSION (MS-DOS & OS/2, Mac versions are above)
  879. X  */
  880. X{
  881. X    static short yday[]={0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  882. X    long m_time;
  883. X    int yr, mo, dy, hh, mm, ss, leap, days=0;
  884. X    struct utimbuf {
  885. X        time_t actime;          /* new access time */
  886. X        time_t modtime;         /* new modification time */
  887. X    } tp;
  888. X#ifdef AMIGA
  889. X#   define YRBASE  1978         /* in AmigaDos, counting begins 01-Jan-1978 */
  890. X    struct DateStamp myadate;
  891. X/*  extern char *_TZ;   no longer used? */
  892. X#else /* !AMIGA */
  893. X#   define YRBASE  1970
  894. X#ifdef BSD
  895. X#ifndef __386BSD__
  896. X    static struct timeb tbp;
  897. X#endif /* !__386BSD__ */
  898. X#else /* !BSD */
  899. X    extern long timezone;
  900. X#endif /* ?BSD */
  901. X#endif /* ?AMIGA */
  902. X
  903. X
  904. X    /*
  905. X     * Close the file *before* setting its time under Unix and AmigaDos.
  906. X     */
  907. X#ifdef AMIGA
  908. X    if (cflag)                  /* can't set time on stdout */
  909. X        return;
  910. X    close(outfd);
  911. X#else /* !AMIGA */
  912. X    close(outfd);
  913. X    if (cflag)                  /* can't set time on stdout */
  914. X        return;
  915. X#endif /* ?AMIGA */
  916. X
  917. X    /*
  918. X     * These date conversions look a little weird, so I'll explain.
  919. X     * UNIX bases all file modification times on the number of seconds
  920. X     * elapsed since Jan 1, 1970, 00:00:00 GMT.  Therefore, to maintain
  921. X     * compatibility with MS-DOS archives, which date from Jan 1, 1980,
  922. X     * with NO relation to GMT, the following conversions must be made:
  923. X     *      the Year (yr) must be incremented by 10;
  924. X     *      the Date (dy) must be decremented by 1;
  925. X     *      and the whole mess must be adjusted by TWO factors:
  926. X     *          relationship to GMT (ie.,Pacific Time adds 8 hrs.),
  927. X     *          and whether or not it is Daylight Savings Time.
  928. X     * Also, the usual conversions must take place to account for leap years,
  929. X     * etc.
  930. X     *                                     C. Seaman
  931. X     */
  932. X
  933. X    /* dissect date */
  934. X    yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + (1980 - YRBASE);
  935. X    mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
  936. X    dy = (lrec.last_mod_file_date & 0x1f) - 1;
  937. X
  938. X    /* dissect time */
  939. X    hh = (lrec.last_mod_file_time >> 11) & 0x1f;
  940. X    mm = (lrec.last_mod_file_time >> 5) & 0x3f;
  941. X    ss = (lrec.last_mod_file_time & 0x1f) * 2;
  942. X
  943. X    /* leap = # of leap years from BASE up to but not including current year */
  944. X    leap = ((yr + YRBASE - 1) / 4);   /* leap year base factor */
  945. X
  946. X    /* How many days from BASE to this year? (& add expired days this year) */
  947. X    days = (yr * 365) + (leap - 492) + yday[mo];
  948. X
  949. X    /* if year is a leap year and month is after February, add another day */
  950. X    if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
  951. X        ++days;                 /* OK through 2199 */
  952. X
  953. X#ifdef AMIGA
  954. X/*  _TZ = getenv("TZ"); does Amiga not have TZ and tzset() after all? */
  955. X    myadate.ds_Days   =   days+dy-2;   /* off by one? */
  956. X    myadate.ds_Minute =   hh*60+mm;
  957. X    myadate.ds_Tick   =   ss*TICKS_PER_SECOND;
  958. X
  959. X    if (!(SetFileDate(filename, &myadate)))
  960. X        fprintf(stderr, "error:  can't set the time for %s\n", filename);
  961. X
  962. X#else /* !AMIGA */
  963. X    /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
  964. X    m_time = ((days + dy) * 86400) + (hh * 3600) + (mm * 60) + ss;
  965. X
  966. X#ifdef BSD
  967. X#ifndef __386BSD__
  968. X    ftime(&tbp);
  969. X    m_time += tbp.timezone * 60L;
  970. X#endif
  971. X/* #elif WIN32
  972. X * don't do anything right now (esp. since "elif" is not legal for old cc's */
  973. X#else /* !BSD */
  974. X    tzset();                    /* set `timezone' */
  975. X    m_time += timezone;         /* account for timezone differences */
  976. X#endif /* ?BSD */
  977. X
  978. X#ifdef __386BSD__
  979. X    m_time += localtime(&m_time)->tm_gmtoff;
  980. X#else
  981. X    if (localtime(&m_time)->tm_isdst)
  982. X        m_time -= 60L * 60L;    /* adjust for daylight savings time */
  983. X#endif
  984. X
  985. X    tp.actime = m_time;         /* set access time */
  986. X    tp.modtime = m_time;        /* set modification time */
  987. X
  988. X    /* set the time stamp on the file */
  989. X    if (utime(filename, &tp))
  990. X        fprintf(stderr, "error:  can't set the time for %s\n", filename);
  991. X#endif /* ?AMIGA */
  992. X}
  993. X
  994. X#endif /* !MTS && !VMS */
  995. X#endif /* ?MACOS */
  996. X#endif /* ?DOS_OS2 */
  997. X
  998. X
  999. X
  1000. X
  1001. X
  1002. X/************************/
  1003. X/*  Function handler()  */
  1004. X/************************/
  1005. X
  1006. Xvoid handler(signal)   /* upon interrupt, turn on echo and exit cleanly */
  1007. X    int signal;
  1008. X{
  1009. X#if (defined(SIGBUS) || defined(SIGSEGV))
  1010. X    static char *corrupt = "error:  zipfile probably corrupt\n";
  1011. X#endif
  1012. X
  1013. X#ifndef DOS_OS2
  1014. X#ifdef CRYPT
  1015. X    echon();
  1016. X#endif /* CRYPT */
  1017. X    putc('\n', stderr);
  1018. X#endif /* !DOS_OS2 */
  1019. X#ifdef SIGBUS
  1020. X    if (signal == SIGBUS) {
  1021. X        fprintf(stderr, corrupt);
  1022. X        exit(3);
  1023. X    }
  1024. X#endif /* SIGBUS */
  1025. X#ifdef SIGSEGV
  1026. X    if (signal == SIGSEGV) {
  1027. X        fprintf(stderr, corrupt);
  1028. X        exit(3);
  1029. X    }
  1030. X#endif /* SIGSEGV */
  1031. X    exit(0);
  1032. X}
  1033. X
  1034. X
  1035. X
  1036. X
  1037. X
  1038. X/*******************************/
  1039. X/*  Non-echoing password code  */
  1040. X/*******************************/
  1041. X
  1042. X#ifdef CRYPT
  1043. X#ifndef DOS_OS2
  1044. X#ifdef VMS
  1045. X
  1046. Xint echo(opt)
  1047. X    int opt;
  1048. X{
  1049. X/*---------------------------------------------------------------------------
  1050. X    Based on VMSmunch.c, which in turn was based on Joe Meadows' file.c code.
  1051. X  ---------------------------------------------------------------------------
  1052. X     * For VMS v5.x:
  1053. X     *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,
  1054. X     *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
  1055. X     *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,
  1056. X     *     System Services Reference Manual, pp. sys-23, sys-379
  1057. X     *   fixed-length descriptor info:  Programming, Vol. 3, System Services,
  1058. X     *     Intro to System Routines, sec. 2.9.2
  1059. X     * GRR, 15 Aug 91
  1060. X  ---------------------------------------------------------------------------*/
  1061. X    static struct dsc$descriptor_s DevDesc =
  1062. X        {9, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$INPUT"};
  1063. X     /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
  1064. X    static short           DevChan, iosb[4];
  1065. X    static long            i, status;
  1066. X    static unsigned long   oldmode[2], newmode[2];   /* each = 8 bytes */
  1067. X  
  1068. X
  1069. X/*---------------------------------------------------------------------------
  1070. X    Assign a channel to standard input.
  1071. X  ---------------------------------------------------------------------------*/
  1072. X
  1073. X    status = sys$assign(&DevDesc, &DevChan, 0, 0);
  1074. X    if (!(status & 1))
  1075. X        return status;
  1076. X
  1077. X/*---------------------------------------------------------------------------
  1078. X    Use sys$qio and the IO$_SENSEMODE function to determine the current tty
  1079. X    status (for password reading, could use IO$_READVBLK function instead,
  1080. X    but echo on/off will be more general).
  1081. X  ---------------------------------------------------------------------------*/
  1082. X
  1083. X    status = sys$qio(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
  1084. X                     oldmode, 8, 0, 0, 0, 0);
  1085. X    if (!(status & 1))
  1086. X        return status;
  1087. X    status = iosb[0];
  1088. X    if (!(status & 1))
  1089. X        return status;
  1090. X
  1091. X/*---------------------------------------------------------------------------
  1092. X    Copy old mode into new-mode buffer, then modify to be either NOECHO or
  1093. X    ECHO (depending on function argument opt).
  1094. X  ---------------------------------------------------------------------------*/
  1095. X
  1096. X    newmode[0] = oldmode[0];
  1097. X    newmode[1] = oldmode[1];
  1098. X    if (opt == OFF)
  1099. X        newmode[1] |= TT$M_NOECHO;                      /* set NOECHO bit */
  1100. X    else
  1101. X        newmode[1] &= ~((unsigned long) TT$M_NOECHO);   /* clear NOECHO bit */
  1102. X
  1103. X/*---------------------------------------------------------------------------
  1104. X    Use the IO$_SETMODE function to change the tty status.
  1105. X  ---------------------------------------------------------------------------*/
  1106. X
  1107. X    status = sys$qio(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
  1108. X                     newmode, 8, 0, 0, 0, 0);
  1109. X    if (!(status & 1))
  1110. X        return status;
  1111. X    status = iosb[0];
  1112. X    if (!(status & 1))
  1113. X        return status;
  1114. X
  1115. X/*---------------------------------------------------------------------------
  1116. X    Deassign the sys$input channel by way of clean-up, then exit happily.
  1117. X  ---------------------------------------------------------------------------*/
  1118. X
  1119. X    status = sys$dassgn(DevChan);
  1120. X    if (!(status & 1))
  1121. X        return status;
  1122. X
  1123. X    return SS$_NORMAL;   /* we be happy */
  1124. X
  1125. X} /* end function echo() */
  1126. X
  1127. X
  1128. X
  1129. X
  1130. X
  1131. X#else /* !VMS */
  1132. X
  1133. Xstatic int echofd=(-1);       /* file descriptor whose echo is off */
  1134. X
  1135. Xvoid echoff(f)
  1136. X    int f;                    /* file descriptor for which to turn echo off */
  1137. X/* Turn echo off for file descriptor f.  Assumes that f is a tty device. */
  1138. X{
  1139. X    struct sgttyb sg;         /* tty device structure */
  1140. X
  1141. X    echofd = f;
  1142. X    GTTY(f, &sg);             /* get settings */
  1143. X    sg.sg_flags &= ~ECHO;     /* turn echo off */
  1144. X    STTY(f, &sg);
  1145. X}
  1146. X
  1147. X
  1148. X
  1149. Xvoid echon()
  1150. X/* Turn echo back on for file descriptor echofd. */
  1151. X{
  1152. X    struct sgttyb sg;         /* tty device structure */
  1153. X
  1154. X    if (echofd != -1) {
  1155. X        GTTY(echofd, &sg);    /* get settings */
  1156. X        sg.sg_flags |= ECHO;  /* turn echo on */
  1157. X        STTY(echofd, &sg);
  1158. X        echofd = -1;
  1159. X    }
  1160. X}
  1161. X
  1162. X#endif /* ?VMS */
  1163. X#endif /* !DOS_OS2 */
  1164. X
  1165. X
  1166. X
  1167. X
  1168. X
  1169. Xchar *getp(m, p, n)
  1170. X    char *m;                  /* prompt for password */
  1171. X    char *p;                  /* return value: line input */
  1172. X    int n;                    /* bytes available in p[] */
  1173. X/* Get a password of length n-1 or less into *p using the prompt *m.
  1174. X   The entered password is not echoed.  Return p on success, NULL on
  1175. X   failure (can't get controlling tty). */
  1176. X{
  1177. X    char c;                   /* one-byte buffer for read() to use */
  1178. X    int i;                    /* number of characters input */
  1179. X    char *w;                  /* warning on retry */
  1180. X
  1181. X#ifndef DOS_OS2
  1182. X#ifndef VMS
  1183. X    int f;                    /* file decsriptor for tty device */
  1184. X
  1185. X    /* turn off echo on tty */
  1186. X    if (!isatty(2))
  1187. X        return NULL;          /* error if not tty */
  1188. X    if ((f = open(ttyname(2), 0, 0)) == -1)
  1189. X        return NULL;
  1190. X#endif /* !VMS */
  1191. X    echoff(f);                /* turn echo off */
  1192. X#endif /* !DOS_OS2 */
  1193. X
  1194. X    /* get password */
  1195. X    w = "";
  1196. X    do {
  1197. X#ifdef VMS   /* bug:  VMS adds '\n' to NULL fputs (apparently) */
  1198. X        if (*w)
  1199. X#endif /* VMS */
  1200. X            fputs(w, stderr); /* warning if back again */
  1201. X        fputs(m, stderr);     /* prompt */
  1202. X        fflush(stderr);
  1203. X        i = 0;
  1204. X        do {                  /* read line, keeping n */
  1205. X#ifdef MSVMS
  1206. X            if ((c = (char)getch()) == '\r')
  1207. X                c = '\n';
  1208. X#else /* !MSVMS */
  1209. X            read(f, &c, 1);
  1210. X#endif /* ?MSVMS */
  1211. X            if (i < n)
  1212. X                p[i++] = c;
  1213. X        } while (c != '\n');
  1214. X        putc('\n', stderr);  fflush(stderr);
  1215. X        w = "(line too long--try again)\n";
  1216. X    } while (p[i-1] != '\n');
  1217. X    p[i-1] = 0;               /* terminate at newline */
  1218. X
  1219. X#ifndef DOS_OS2
  1220. X    echon();                  /* turn echo back on */
  1221. X#ifndef VMS
  1222. X    close(f);
  1223. X#endif /* !VMS */
  1224. X#endif /* !DOS_OS2 */
  1225. X
  1226. X    /* return pointer to password */
  1227. X    return p;
  1228. X}
  1229. X
  1230. X#endif /* CRYPT */
  1231. END_OF_FILE
  1232.   if test 34380 -ne `wc -c <'file_io.c'`; then
  1233.     echo shar: \"'file_io.c'\" unpacked with wrong size!
  1234.   fi
  1235.   # end of 'file_io.c'
  1236. fi
  1237. if test -f 'match.c' -a "${1}" != "-c" ; then 
  1238.   echo shar: Will not clobber existing file \"'match.c'\"
  1239. else
  1240.   echo shar: Extracting \"'match.c'\" \(19243 characters\)
  1241.   sed "s/^X//" >'match.c' <<'END_OF_FILE'
  1242. X/*---------------------------------------------------------------------------
  1243. X
  1244. X  match.c
  1245. X
  1246. X  The match() routine recursively compares a string to a "pattern" (regular
  1247. X  expression), returning TRUE if a match is found or FALSE if not.  This
  1248. X  version is specifically for use with unzip.c:  as did the previous match()
  1249. X  from SEA, it leaves the case (upper, lower, or mixed) of the string alone,
  1250. X  but converts any uppercase characters in the pattern to lowercase if indi-
  1251. X  cated by the global var pInfo->lcflag (which is to say, string is assumed
  1252. X  to have been converted to lowercase already, if such was necessary).
  1253. X
  1254. X  ---------------------------------------------------------------------------*/
  1255. X
  1256. X
  1257. X#ifdef ZIPINFO
  1258. X#  undef ZIPINFO   /* make certain there is only one version of match.o */
  1259. X#endif /* ZIPINFO */
  1260. X#include "unzip.h"
  1261. X
  1262. Xstatic int  matche              __((register char *p, register char *t));
  1263. Xstatic int  matche_after_star   __((register char *p, register char *t));
  1264. X
  1265. X/* #include "filmatch.h": */
  1266. X#ifndef BOOLEAN
  1267. X#  define BOOLEAN short int      /* v1.2 made it short */
  1268. X#endif
  1269. X
  1270. X/* match defines */
  1271. X#define MATCH_PATTERN  6    /* bad pattern */
  1272. X#define MATCH_LITERAL  5    /* match failure on literal match */
  1273. X#define MATCH_RANGE    4    /* match failure on [..] construct */
  1274. X#define MATCH_ABORT    3    /* premature end of text string */
  1275. X#define MATCH_END      2    /* premature end of pattern string */
  1276. X#define MATCH_VALID    1    /* valid match */
  1277. X
  1278. X/* pattern defines */
  1279. X#define PATTERN_VALID  0    /* valid pattern */
  1280. X#define PATTERN_ESC   -1    /* literal escape at end of pattern */
  1281. X#define PATTERN_RANGE -2    /* malformed range in [..] construct */
  1282. X#define PATTERN_CLOSE -3    /* no end bracket in [..] construct */
  1283. X#define PATTERN_EMPTY -4    /* [..] contstruct is empty */
  1284. X
  1285. X/*----------------------------------------------------------------------------
  1286. X*
  1287. X*  Match the pattern PATTERN against the string TEXT;
  1288. X*
  1289. X*       match() returns TRUE if pattern matches, FALSE otherwise.
  1290. X*       matche() returns MATCH_VALID if pattern matches, or an errorcode
  1291. X*           as follows otherwise:
  1292. X*
  1293. X*            MATCH_PATTERN  - bad pattern
  1294. X*            MATCH_RANGE    - match failure on [..] construct
  1295. X*            MATCH_ABORT    - premature end of text string
  1296. X*            MATCH_END      - premature end of pattern string
  1297. X*            MATCH_VALID    - valid match
  1298. X*
  1299. X*
  1300. X*  A match means the entire string TEXT is used up in matching.
  1301. X*
  1302. X*  In the pattern string:
  1303. X*       `*' matches any sequence of characters (zero or more)
  1304. X*       `?' matches any character
  1305. X*       [SET] matches any character in the specified set,
  1306. X*       [!SET] or [^SET] matches any character not in the specified set.
  1307. X*
  1308. X*  A set is composed of characters or ranges; a range looks like
  1309. X*  character hyphen character (as in 0-9 or A-Z).  [0-9a-zA-Z_] is the
  1310. X*  minimal set of characters allowed in the [..] pattern construct.
  1311. X*  Other characters are allowed (ie. 8 bit characters) if your system
  1312. X*  will support them.
  1313. X*
  1314. X*  To suppress the special syntactic significance of any of `[]*?!^-\',
  1315. X*  in a [..] construct and match the character exactly, precede it
  1316. X*  with a `\'.
  1317. X*
  1318. X----------------------------------------------------------------------------*/
  1319. X
  1320. X/*----------------------------------------------------------------------------
  1321. X*
  1322. X*  Match the pattern PATTERN against the string TEXT;
  1323. X*
  1324. X*  returns MATCH_VALID if pattern matches, or an errorcode as follows
  1325. X*  otherwise:
  1326. X*
  1327. X*            MATCH_PATTERN  - bad pattern
  1328. X*            MATCH_RANGE    - match failure on [..] construct
  1329. X*            MATCH_ABORT    - premature end of text string
  1330. X*            MATCH_END      - premature end of pattern string
  1331. X*            MATCH_VALID    - valid match
  1332. X*
  1333. X*
  1334. X*  A match means the entire string TEXT is used up in matching.
  1335. X*
  1336. X*  In the pattern string:
  1337. X*       `*' matches any sequence of characters (zero or more)
  1338. X*       `?' matches any character
  1339. X*       [SET] matches any character in the specified set,
  1340. X*       [!SET] or [^SET] matches any character not in the specified set.
  1341. X*       \ is allowed within a set to escape a character like ']' or '-'
  1342. X*
  1343. X*  A set is composed of characters or ranges; a range looks like
  1344. X*  character hyphen character (as in 0-9 or A-Z).  [0-9a-zA-Z_] is the
  1345. X*  minimal set of characters allowed in the [..] pattern construct.
  1346. X*  Other characters are allowed (ie. 8 bit characters) if your system
  1347. X*  will support them.
  1348. X*
  1349. X*  To suppress the special syntactic significance of any of `[]*?!^-\',
  1350. X*  within a [..] construct and match the character exactly, precede it
  1351. X*  with a `\'.
  1352. X*
  1353. X----------------------------------------------------------------------------*/
  1354. X
  1355. Xstatic int matche(p, t)
  1356. Xregister char *p;
  1357. Xregister char *t;
  1358. X{
  1359. X    register char range_start, range_end;  /* start and end in range */
  1360. X
  1361. X    BOOLEAN invert;             /* is this [..] or [!..] */
  1362. X    BOOLEAN member_match;       /* have I matched the [..] construct? */
  1363. X    BOOLEAN loop;               /* should I terminate? */
  1364. X
  1365. X    for (;  *p;  p++, t++) {
  1366. X
  1367. X        /* if this is the end of the text then this is the end of the match */
  1368. X        if (!*t)
  1369. X            return ((*p == '*') && (*++p == '\0'))?  MATCH_VALID : MATCH_ABORT;
  1370. X
  1371. X        /* determine and react to pattern type */
  1372. X        switch (*p) {
  1373. X
  1374. X            /* single any character match */
  1375. X            case '?':
  1376. X                break;
  1377. X
  1378. X            /* multiple any character match */
  1379. X            case '*':
  1380. X                return matche_after_star (p, t);
  1381. X
  1382. X            /* [..] construct, single member/exclusion character match */
  1383. X            case '[': {
  1384. X
  1385. X                /* move to beginning of range */
  1386. X                p++;
  1387. X
  1388. X                /* check if this is a member match or exclusion match */
  1389. X                invert = FALSE;
  1390. X                if ((*p == '!') || (*p == '^')) {
  1391. X                    invert = TRUE;
  1392. X                    p++;
  1393. X                }
  1394. X
  1395. X                /* if closing bracket here or at range start then we have a
  1396. X                   malformed pattern */
  1397. X                if (*p == ']')
  1398. X                    return MATCH_PATTERN;
  1399. X
  1400. X                member_match = FALSE;
  1401. X                loop = TRUE;
  1402. X
  1403. X                while (loop) {
  1404. X
  1405. X                    /* if end of construct then loop is done */
  1406. X                    if (*p == ']') {
  1407. X                        loop = FALSE;
  1408. X                        continue;
  1409. X                    }
  1410. X
  1411. X                    /* matching a '!', '^', '-', '\' or a ']' */
  1412. X                    if (*p == '\\')
  1413. X                        range_start = range_end = *++p;
  1414. X                    else
  1415. X                        range_start = range_end = *p;
  1416. X
  1417. X                    /* if end of pattern then bad pattern (Missing ']') */
  1418. X                    if (!*p)
  1419. X                        return MATCH_PATTERN;
  1420. X
  1421. X                    /* check for range bar */
  1422. X                    if (*++p == '-') {
  1423. X
  1424. X                        /* get the range end */
  1425. X                        range_end = *++p;
  1426. X
  1427. X                        /* if end of pattern or construct then bad pattern */
  1428. X                        if ((range_end == '\0') || (range_end == ']'))
  1429. X                            return MATCH_PATTERN;
  1430. X
  1431. X                        /* special character range end */
  1432. X                        if (range_end == '\\') {
  1433. X                            range_end = *++p;
  1434. X
  1435. X                            /* if end of text then we have a bad pattern */
  1436. X                            if (!range_end)
  1437. X                                return MATCH_PATTERN;
  1438. X                        }
  1439. X
  1440. X                        /* move just beyond this range */
  1441. X                        p++;
  1442. X                    }
  1443. X
  1444. X                    /* if the text character is in range then match found.
  1445. X                     * make sure the range letters have the proper
  1446. X                     * relationship to one another before comparison
  1447. X                     */
  1448. X                    if (range_start < range_end) {
  1449. X                        if ((*t >= range_start) && (*t <= range_end)) {
  1450. X                            member_match = TRUE;
  1451. X                            loop = FALSE;
  1452. X                        }
  1453. X                    } else {
  1454. X                        if ((*t >= range_end) && (*t <= range_start)) {
  1455. X                            member_match = TRUE;
  1456. X                            loop = FALSE;
  1457. X                        }
  1458. X                    }
  1459. X                }
  1460. X
  1461. X                /* if there was a match in an exclusion set then no match */
  1462. X                /* if there was no match in a member set then no match */
  1463. X                if ((invert && member_match) ||
  1464. X                   !(invert || member_match))
  1465. X                    return MATCH_RANGE;
  1466. X
  1467. X                /* if this is not an exclusion then skip the rest of the [...]
  1468. X                    construct that already matched. */
  1469. X                if (member_match) {
  1470. X                    while (*p != ']') {
  1471. X
  1472. X                        /* bad pattern (Missing ']') */
  1473. X                        if (!*p)
  1474. X                            return MATCH_PATTERN;
  1475. X
  1476. X                        /* skip exact match */
  1477. X                        if (*p == '\\') {
  1478. X                            p++;
  1479. X
  1480. X                            /* if end of text then we have a bad pattern */
  1481. X                            if (!*p)
  1482. X                                return MATCH_PATTERN;
  1483. X                        }
  1484. X
  1485. X                        /* move to next pattern char */
  1486. X                        p++;
  1487. X                    }
  1488. X                }
  1489. X
  1490. X                break;
  1491. X            }  /* switch '[' */
  1492. X
  1493. X            /* must match this character exactly */
  1494. X            default:
  1495. X#ifdef OLDSTUFF
  1496. X                if (*p != *t)
  1497. X#else /* !OLDSTUFF */
  1498. X                /* do it like arcmatch() (old unzip) did it (v1.2) */
  1499. X                if (*t != (char) ((pInfo->lcflag && isupper((int)(*p)))?
  1500. X                    tolower((int)(*p)) : *p))
  1501. X#endif /* ?OLDSTUFF */
  1502. X                    return MATCH_LITERAL;
  1503. X
  1504. X        }  /* switch */
  1505. X    }  /* for */
  1506. X
  1507. X        /* if end of text not reached then the pattern fails */
  1508. X    if (*t)
  1509. X        return MATCH_END;
  1510. X    else
  1511. X        return MATCH_VALID;
  1512. X}
  1513. X
  1514. X
  1515. X/*----------------------------------------------------------------------------
  1516. X*
  1517. X* recursively call matche() with final segment of PATTERN and of TEXT.
  1518. X*
  1519. X----------------------------------------------------------------------------*/
  1520. X
  1521. Xstatic int matche_after_star (p,t)
  1522. Xregister char *p;
  1523. Xregister char *t;
  1524. X{
  1525. X    register int match = 0;
  1526. X    register int nextp;
  1527. X
  1528. X    /* pass over existing ? and * in pattern */
  1529. X    while ((*p == '?') || (*p == '*')) {
  1530. X
  1531. X        /* take one char for each ? and +; if end of text then no match */
  1532. X        if ((*p == '?') && (!*t++))
  1533. X                return MATCH_ABORT;
  1534. X
  1535. X        /* move to next char in pattern */
  1536. X        p++;
  1537. X    }
  1538. X
  1539. X    /* if end of pattern we have matched regardless of text left */
  1540. X    if (!*p)
  1541. X        return MATCH_VALID;
  1542. X
  1543. X    /* get the next character to match which must be a literal or '[' */
  1544. X    nextp = *p;
  1545. X
  1546. X    /* Continue until we run out of text or definite result seen */
  1547. X    do {
  1548. X        /* a precondition for matching is that the next character
  1549. X         * in the pattern match the next character in the text or that
  1550. X         * the next pattern char is the beginning of a range.  Increment
  1551. X         * text pointer as we go here.
  1552. X         */
  1553. X        if ((nextp == *t) || (nextp == '['))
  1554. X            match = matche(p, t);
  1555. X
  1556. X        /* if the end of text is reached then no match */
  1557. X        if (!*t++)
  1558. X            match = MATCH_ABORT;
  1559. X
  1560. X    } while ((match != MATCH_VALID) &&
  1561. X             (match != MATCH_ABORT) &&
  1562. X             (match != MATCH_PATTERN));
  1563. X
  1564. X    /* return result */
  1565. X    return match;
  1566. X}
  1567. X
  1568. X
  1569. X/*----------------------------------------------------------------------------
  1570. X*
  1571. X* match() is a shell to matche() to return only BOOLEAN values.
  1572. X*
  1573. X----------------------------------------------------------------------------*/
  1574. X
  1575. Xint match(string,pattern)
  1576. Xchar *string;
  1577. Xchar *pattern;
  1578. X{
  1579. X    int error_type;
  1580. X    error_type = matche(pattern,string);
  1581. X    return (error_type == MATCH_VALID ) ? TRUE : FALSE;
  1582. X}
  1583. X
  1584. X
  1585. X#ifdef TEST_MATCH
  1586. X
  1587. X/*----------------------------------------------------------------------------
  1588. X*
  1589. X* Return TRUE if PATTERN has any special wildcard characters
  1590. X*
  1591. X----------------------------------------------------------------------------*/
  1592. X
  1593. XBOOLEAN is_pattern (char *pattern);
  1594. X
  1595. X/*----------------------------------------------------------------------------
  1596. X*
  1597. X* Return TRUE if PATTERN has is a well formed regular expression according
  1598. X* to the above syntax
  1599. X*
  1600. X* error_type is a return code based on the type of pattern error.  Zero is
  1601. X* returned in error_type if the pattern is a valid one.  error_type return
  1602. X* values are as follows:
  1603. X*
  1604. X*   PATTERN_VALID - pattern is well formed
  1605. X*   PATTERN_RANGE - [..] construct has a no end range in a '-' pair (ie [a-])
  1606. X*   PATTERN_CLOSE - [..] construct has no end bracket (ie [abc-g )
  1607. X*   PATTERN_EMPTY - [..] construct is empty (ie [])
  1608. X*
  1609. X----------------------------------------------------------------------------*/
  1610. X
  1611. XBOOLEAN is_valid_pattern (char *pattern, int *error_type);
  1612. Xint fast_match_after_star (register char *pattern, register char *text);
  1613. X
  1614. X/*----------------------------------------------------------------------------
  1615. X*
  1616. X* Return TRUE if PATTERN has any special wildcard characters
  1617. X*
  1618. X----------------------------------------------------------------------------*/
  1619. X
  1620. XBOOLEAN is_pattern (char *p)
  1621. X{
  1622. X    while (*p)
  1623. X        switch (*p++) {
  1624. X            case '?':
  1625. X            case '*':
  1626. X            case '[':
  1627. X                return TRUE;
  1628. X        }
  1629. X    return FALSE;
  1630. X}
  1631. X
  1632. X
  1633. X/*----------------------------------------------------------------------------
  1634. X*
  1635. X* Return TRUE if PATTERN has is a well formed regular expression according
  1636. X* to the above syntax
  1637. X*
  1638. X* error_type is a return code based on the type of pattern error.  Zero is
  1639. X* returned in error_type if the pattern is a valid one.  error_type return
  1640. X* values are as follows:
  1641. X*
  1642. X*   PATTERN_VALID - pattern is well formed
  1643. X*   PATTERN_RANGE - [..] construct has a no end range in a '-' pair (ie [a-])
  1644. X*   PATTERN_CLOSE - [..] construct has no end bracket (ie [abc-g )
  1645. X*   PATTERN_EMPTY - [..] construct is empty (ie [])
  1646. X*
  1647. X----------------------------------------------------------------------------*/
  1648. X
  1649. XBOOLEAN is_valid_pattern (char *p, int *error_type)
  1650. X{
  1651. X    /* init error_type */
  1652. X    *error_type = PATTERN_VALID;
  1653. X
  1654. X    /* loop through pattern to EOS */
  1655. X    while (*p) {
  1656. X
  1657. X        /* determine pattern type */
  1658. X        switch (*p) {
  1659. X
  1660. X            /* the [..] construct must be well formed */
  1661. X            case '[':
  1662. X                p++;
  1663. X
  1664. X                /* if the next character is ']' then bad pattern */
  1665. X                if (*p == ']') {
  1666. X                    *error_type = PATTERN_EMPTY;
  1667. X                    return FALSE;
  1668. X                }
  1669. X
  1670. X                /* if end of pattern here then bad pattern */
  1671. X                if (!*p) {
  1672. X                    *error_type = PATTERN_CLOSE;
  1673. X                    return FALSE;
  1674. X                }
  1675. X
  1676. X                /* loop to end of [..] construct */
  1677. X                while (*p != ']') {
  1678. X
  1679. X                    /* check for literal escape */
  1680. X                    if (*p == '\\') {
  1681. X                        p++;
  1682. X
  1683. X                        /* if end of pattern here then bad pattern */
  1684. X                        if (!*p++) {
  1685. X                            *error_type = PATTERN_ESC;
  1686. X                            return FALSE;
  1687. X                        }
  1688. X                    } else
  1689. X                        p++;
  1690. X
  1691. X                    /* if end of pattern here then bad pattern */
  1692. X                    if (!*p) {
  1693. X                        *error_type = PATTERN_CLOSE;
  1694. X                        return FALSE;
  1695. X                    }
  1696. X
  1697. X                    /* if this a range */
  1698. X                    if (*p == '-') {
  1699. X
  1700. X                        /* we must have an end of range */
  1701. X                        if (!*++p || (*p == ']')) {
  1702. X                            *error_type = PATTERN_RANGE;
  1703. X                            return FALSE;
  1704. X                        } else {
  1705. X
  1706. X                            /* check for literal escape */
  1707. X                            if (*p == '\\')
  1708. X                                p++;
  1709. X
  1710. X                            /* if end of pattern here then bad pattern */
  1711. X                            if (!*p++) {
  1712. X                                *error_type = PATTERN_ESC;
  1713. X                                return FALSE;
  1714. X                            }
  1715. X                        }
  1716. X                    }
  1717. X                }
  1718. X                break;
  1719. X
  1720. X            /* all other characters are valid pattern elements */
  1721. X            case '*':
  1722. X            case '?':
  1723. X            default:
  1724. X                p++;                /* "normal" character */
  1725. X                break;
  1726. X        }    /* switch */
  1727. X    }
  1728. X
  1729. X    return TRUE;
  1730. X}
  1731. X
  1732. X
  1733. X    /*
  1734. X    * This test main expects as first arg the pattern and as second arg
  1735. X    * the match string.  Output is yay or nay on match.  If nay on
  1736. X    * match then the error code is parsed and written.
  1737. X    */
  1738. X
  1739. X#include <stdio.h>
  1740. X
  1741. Xint main(int argc, char *argv[])
  1742. X{
  1743. X    int error;
  1744. X    int is_valid_error;
  1745. X
  1746. X    if (argc != 3)
  1747. X        printf("Usage:  MATCH Pattern Text\n");
  1748. X    else {
  1749. X        printf("Pattern: %s\n", argv[1]);
  1750. X        printf("Text   : %s\n", argv[2]);
  1751. X
  1752. X        if (!is_pattern(argv[1]))
  1753. X            printf("    First Argument Is Not A Pattern\n");
  1754. X        else {
  1755. X            match(argv[1],argv[2]) ? printf("TRUE") : printf("FALSE");
  1756. X            error = matche(argv[1],argv[2]);
  1757. X            is_valid_pattern(argv[1],&is_valid_error);
  1758. X
  1759. X            switch (error) {
  1760. X                case MATCH_VALID:
  1761. X                    printf("    Match Successful");
  1762. X                    if (is_valid_error != PATTERN_VALID)
  1763. X                        printf(" -- is_valid_pattern() is complaining\n");
  1764. X                    else
  1765. X                        printf("\n");
  1766. X                    break;
  1767. X                case MATCH_RANGE:
  1768. X                    printf("    Match Failed on [..]\n");
  1769. X                    break;
  1770. X                case MATCH_ABORT:
  1771. X                    printf("    Match Failed on Early Text Termination\n");
  1772. X                    break;
  1773. X                case MATCH_END:
  1774. X                    printf("    Match Failed on Early Pattern Termination\n");
  1775. X                    break;
  1776. X                case MATCH_PATTERN:
  1777. X                    switch (is_valid_error) {
  1778. X                        case PATTERN_VALID:
  1779. X                            printf("    Internal Disagreement On Pattern\n");
  1780. X                            break;
  1781. X                        case PATTERN_RANGE:
  1782. X                            printf("    No End of Range in [..] Construct\n");
  1783. X                            break;
  1784. X                        case PATTERN_CLOSE:
  1785. X                            printf("    [..] Construct is Open\n");
  1786. X                            break;
  1787. X                        case PATTERN_EMPTY:
  1788. X                            printf("    [..] Construct is Empty\n");
  1789. X                            break;
  1790. X                        default:
  1791. X                            printf("    Internal Error in is_valid_pattern()\n");
  1792. X                    }
  1793. X                    break;
  1794. X                default:
  1795. X                    printf("    Internal Error in matche()\n");
  1796. X                    break;
  1797. X            } /* switch */
  1798. X        }
  1799. X
  1800. X    }
  1801. X    return(0);
  1802. X}
  1803. X
  1804. X#endif  /* TEST_MATCH */
  1805. END_OF_FILE
  1806.   if test 19243 -ne `wc -c <'match.c'`; then
  1807.     echo shar: \"'match.c'\" unpacked with wrong size!
  1808.   fi
  1809.   # end of 'match.c'
  1810. fi
  1811. echo shar: End of archive 3 \(of 14\).
  1812. cp /dev/null ark3isdone
  1813. MISSING=""
  1814. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1815.     if test ! -f ark${I}isdone ; then
  1816.     MISSING="${MISSING} ${I}"
  1817.     fi
  1818. done
  1819. if test "${MISSING}" = "" ; then
  1820.     echo You have unpacked all 14 archives.
  1821.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1822. else
  1823.     echo You still must unpack the following archives:
  1824.     echo "        " ${MISSING}
  1825. fi
  1826. exit 0
  1827. exit 0 # Just in case...
  1828.