home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / sources / misc / 3856 < prev    next >
Encoding:
Text File  |  1992-08-23  |  58.2 KB  |  1,834 lines

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