home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / unzip / part03 < prev    next >
Internet Message Format  |  1994-09-19  |  72KB

  1. From: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
  2. Newsgroups: comp.sources.misc
  3. Subject: v44i068:  unzip - Info-ZIP portable UnZip, version 5.12, Part03/20
  4. Date: 18 Sep 1994 23:14:25 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <35j371$qls@sparky.sterling.com>
  9. X-Md4-Signature: 21f88c198c6b8f5182408c7bb827ba4d
  10.  
  11. Submitted-by: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
  12. Posting-number: Volume 44, Issue 68
  13. Archive-name: unzip/part03
  14. Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT, AMIGA?, ATARI TOS, SGI, DEC, Cray, Convex, Amdahl, Sun
  15. Supersedes: unzip50: Volume 31, Issue 104-117
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  unzip-5.12/version.h unzip-5.12/vms/vms.c
  22. # Wrapped by kent@sparky on Sat Sep 17 23:33:36 1994
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 3 (of 20)."'
  26. if test -f 'unzip-5.12/version.h' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'unzip-5.12/version.h'\"
  28. else
  29.   echo shar: Extracting \"'unzip-5.12/version.h'\" \(855 characters\)
  30.   sed "s/^X//" >'unzip-5.12/version.h' <<'END_OF_FILE'
  31. X/*
  32. X   version.h (for UnZip) by Info-ZIP.
  33. X
  34. X   This header file is not copyrighted and may be distributed without
  35. X   restriction.  (That's a little geek humor, heh heh.)
  36. X */
  37. X
  38. X#ifndef __version_h   /* don't include more than once */
  39. X#define __version_h
  40. X
  41. X#ifdef BETA
  42. X#  define BETALEVEL   "e"
  43. X#  define UZ_VERSION  "5.12e BETA of 25 Aug 94"   /* internal beta level */
  44. X#  define ZI_VERSION  "2.02e BETA of 25 Aug 94"
  45. X#  define D2_VERSION  "0.0 BETA of xx Xxx 94"
  46. X#else
  47. X#  define BETALEVEL   ""
  48. X#  define UZ_VERSION  "5.12 of 28 August 1994"   /* official release version */
  49. X#  define ZI_VERSION  "2.02 of 28 August 1994"
  50. X#  define D2_VERSION  "0.0 of x Xxxxxx 1994"   /* (DLL for OS/2) */
  51. X#  define RELEASE
  52. X#endif
  53. X
  54. X#define UZ_MAJORVER  5
  55. X#define UZ_MINORVER  1
  56. X
  57. X#define ZI_MAJORVER  2
  58. X#define ZI_MINORVER  0
  59. X
  60. X#define PATCHLEVEL   2
  61. X
  62. X#endif /* !__version_h */
  63. END_OF_FILE
  64.   if test 855 -ne `wc -c <'unzip-5.12/version.h'`; then
  65.     echo shar: \"'unzip-5.12/version.h'\" unpacked with wrong size!
  66.   fi
  67.   # end of 'unzip-5.12/version.h'
  68. fi
  69. if test -f 'unzip-5.12/vms/vms.c' -a "${1}" != "-c" ; then 
  70.   echo shar: Will not clobber existing file \"'unzip-5.12/vms/vms.c'\"
  71. else
  72.   echo shar: Extracting \"'unzip-5.12/vms/vms.c'\" \(66172 characters\)
  73.   sed "s/^X//" >'unzip-5.12/vms/vms.c' <<'END_OF_FILE'
  74. X/*---------------------------------------------------------------------------
  75. X
  76. X  vms.c                                        Igor Mandrichenko and others
  77. X
  78. X  This file contains routines to extract VMS file attributes from a zipfile
  79. X  extra field and create a file with these attributes.  The code was almost
  80. X  entirely written by Igor, with a couple of routines by CN.
  81. X
  82. X  ---------------------------------------------------------------------------
  83. X
  84. X     Copyright (C) 1992-93 Igor Mandrichenko.
  85. X     Permission is granted to any individual or institution to use, copy,
  86. X     or redistribute this software so long as all of the original files
  87. X     are included unmodified and that this copyright notice is retained.
  88. X
  89. X  Revision history:
  90. X
  91. X     1.x   [moved to History.510 for brevity]
  92. X     2.0   Mandrichenko    7-apr-1993
  93. X            Implement PKWARE style VMS file attributes
  94. X     2.0-1 Mandrichenko    10-apr-1993
  95. X            ACL handling code added.
  96. X     2.1   Mandrichenko    24-aug-1993
  97. X            Get both PKWARE and new INFO-ZIP signatures as equivalent
  98. X            Use vmsmunch.h instead of fatdef.h
  99. X     2.2   Cave Newt       3-oct-1993
  100. X            Merged GRR 5.1e changes with latest Igor version:  open_outfile,
  101. X            close_outfile, check_for_newer, UpdateCRC, flush, no ZIPINFO,
  102. X            ctype.h, pInfo->textmode, etc.  Also merged new do_wild/mapname/
  103. X            checkdir routines from Igor and moved VMSmunch.h into vms.h.
  104. X     2.2-1 Mandrichenko    14-dec-1993
  105. X            Bug fixes in mapname/checkdir stuff.
  106. X            _flush_stream() rewritten to fix some bugs.
  107. X     2.2-2 Goathunter      3 Jan 94
  108. X            Fixes for Alpha-VMS.
  109. X     2.2-3 Cave Newt       11 Jan 94
  110. X            Disabled version-check by default; enable with CHECK_VERSIONS.
  111. X            Installed Igor's ctrl-Z patch.
  112. X     2.2-4 Mandrichenko    18 Jan 94
  113. X            Fixed auto-appending of ".zip" and inability to create second
  114. X            level of directory structure.
  115. X     2.2-5 Cave Newt, Mike Freeman  28 Jan 94
  116. X            Changed close_outfile() to return void for compatibility;
  117. X            fixed declaration of second parameter to flush() (ulg size);
  118. X            changed str[n]icmp() to STR[N]ICMP().
  119. X     2.2-6 Christian Spieler  9 Apr 94
  120. X            Numerous bug fixes/improvements.
  121. X     2.2-7 Cave Newt       11 Apr 94
  122. X            Fixed version-number/semicolon bug.
  123. X     2.3   Cave Newt       21 Jun 94
  124. X            Added prototype version() routine.
  125. X     2.3-1 Cave Newt       1 Jul 94
  126. X            *Really* fixed version-number/semicolon bug.
  127. X     2.3-2 Rodney Brown    10 Jul 94
  128. X            Added VMS status/severity level (define RETURN_SEVERITY)
  129. X     2.3-3 Charles Bailey  10 Aug 94
  130. X            Fixed severity levels.
  131. X     2.3-4 CN, CS, IM, RB  16 Aug 94
  132. X            Further severity tweaks; do_wild() bugfix (CS)
  133. X     2.3-5 CS, CN, IM, GH  18 Aug 94
  134. X            Further do_wild() modifications and fixes.
  135. X     2.3-6 Christian Spieler  23 Aug 94
  136. X            Added lots of typecasts and fixed some initializations for DEC C.
  137. X
  138. X  ---------------------------------------------------------------------------*/
  139. X
  140. X#ifdef VMS            /*      VMS only !      */
  141. X
  142. X#include "unzip.h"
  143. X#include "vms.h"        /* now includes VMSmunch.h */
  144. X
  145. X#define BUFS512 8192*2        /* Must be a multiple of 512 */
  146. X
  147. X#define    OK(s)    ((s)&1)        /* VMS success or warning status */
  148. X#define    STRICMP(s1,s2)    STRNICMP(s1,s2,2147483647)
  149. X
  150. X/*
  151. X*   Local static storage
  152. X*/
  153. Xstatic struct FAB    fileblk;
  154. Xstatic struct XABDAT    dattim;
  155. Xstatic struct XABRDT    rdt;
  156. Xstatic struct RAB    rab;
  157. Xstatic struct NAM    nam;
  158. X
  159. Xstatic struct FAB *outfab = 0;
  160. Xstatic struct RAB *outrab = 0;
  161. Xstatic struct XABFHC *xabfhc = 0;
  162. Xstatic struct XABDAT *xabdat = 0;
  163. Xstatic struct XABRDT *xabrdt = 0;
  164. Xstatic struct XABPRO *xabpro = 0;
  165. Xstatic struct XABKEY *xabkey = 0;
  166. Xstatic struct XABALL *xaball = 0;
  167. Xstruct XAB *first_xab = 0L, *last_xab = 0L;
  168. X
  169. Xstatic char query = 0;
  170. Xstatic int  text_output = 0,
  171. X        raw_input,
  172. X        hostnum;
  173. X
  174. Xstatic uch rfm;
  175. X
  176. Xstatic uch locbuf[BUFS512];
  177. Xstatic int loccnt = 0;
  178. Xstatic uch *locptr;
  179. Xstatic char got_eol = 0;
  180. X
  181. Xstatic int  _flush_blocks(),
  182. X        _flush_stream(),
  183. X        _flush_varlen(),
  184. X        _flush_qio(),
  185. X        _close_qio(),
  186. X        _close_rms(),
  187. X        WriteRecord(),
  188. X        WriteBuffer(),
  189. X        find_eol();
  190. X
  191. Xstatic int  (*_flush_routine)(),
  192. X        (*_close_routine)();
  193. X
  194. Xstatic int get_vms_version();
  195. Xstatic int replace();
  196. Xstatic uch *extract_block();
  197. Xstatic void init_buf_ring();
  198. Xstatic void decompress_bits();
  199. Xstatic void UpdateCRC();
  200. Xstatic void message();
  201. Xstatic void free_up();
  202. X
  203. Xstruct bufdsc
  204. X{
  205. X    struct bufdsc *next;
  206. X    uch *buf;
  207. X    int bufcnt;
  208. X};
  209. X
  210. Xstatic struct bufdsc b1, b2, *curbuf;
  211. Xstatic uch buf1[BUFS512];
  212. X
  213. Xint check_format()
  214. X{
  215. X    int rtype;
  216. X    struct FAB fab;
  217. X
  218. X    fab = cc$rms_fab;
  219. X    fab.fab$l_fna = zipfn;
  220. X    fab.fab$b_fns = strlen(zipfn);
  221. X
  222. X    sys$open(&fab);
  223. X    rtype = fab.fab$b_rfm;
  224. X    sys$close(&fab);
  225. X
  226. X    if (rtype == FAB$C_VAR || rtype == FAB$C_VFC)
  227. X    {
  228. X    fprintf(stderr,
  229. X        "\n     Error:  zipfile is in variable-length record format.  Please\n\
  230. X     run \"bilf l %s\" to convert the zipfile to stream-LF\n\
  231. X     record format.  (bilf.c and make_bilf.com are included in the\n\
  232. X     VMS UnZip source distribution.)\n\n", zipfn);
  233. X    return PK_ERR;
  234. X    }
  235. X
  236. X    return PK_COOL;
  237. X}
  238. X
  239. X
  240. X
  241. X#define PRINTABLE_FORMAT(x)    ( (x) == FAB$C_VAR         \
  242. X                || (x) == FAB$C_STMLF        \
  243. X                || (x) == FAB$C_STMCR        \
  244. X                || (x) == FAB$C_STM        )
  245. X
  246. X/* VMS extra field types */
  247. X#define    VAT_NONE    0
  248. X#define    VAT_IZ        1    /* Old INFO-ZIP format */
  249. X#define VAT_PK        2    /* PKWARE format */
  250. X
  251. Xstatic int  vet;
  252. X
  253. Xstatic int  create_default_output(),
  254. X        create_rms_output(),
  255. X        create_qio_output();
  256. X
  257. X/*
  258. X *  open_outfile() assignments:
  259. X *
  260. X *  VMS attributes ?        create_xxx        _flush_xxx
  261. X *  ----------------        ----------        ----------
  262. X *  not found            'default'        text mode ?
  263. X *                        yes -> 'stream'
  264. X *                        no  -> 'block'
  265. X *
  266. X *  yes, in IZ format        'rms'        text mode ?
  267. X *                        yes -> switch(fab.rfm)
  268. X *                        VAR  -> 'varlen' 
  269. X *                        STM* -> 'stream'
  270. X *                            default -> 'block'
  271. X *                        no -> 'block'
  272. X *
  273. X *  yes, in PK format        'qio'        'qio'
  274. X *
  275. X *  "text mode" == pInfo -> text || cflag
  276. X */
  277. X
  278. Xint open_outfile()
  279. X{
  280. X    switch(vet = find_vms_attrs())
  281. X    {    case VAT_NONE:
  282. X    default:
  283. X        return  create_default_output();
  284. X    case VAT_IZ:
  285. X        return  create_rms_output();
  286. X    case VAT_PK:
  287. X        return  create_qio_output();
  288. X    }
  289. X}
  290. X
  291. Xstatic void init_buf_ring()
  292. X{
  293. X    locptr = &locbuf[0];
  294. X    loccnt = 0;
  295. X
  296. X    b1.buf = &locbuf[0];
  297. X    b1.bufcnt = 0;
  298. X    b1.next = &b2;
  299. X    b2.buf = &buf1[0];
  300. X    b2.bufcnt = 0;
  301. X    b2.next = &b1;
  302. X    curbuf = &b1;
  303. X}
  304. X
  305. X
  306. X
  307. Xstatic int create_default_output()
  308. X{
  309. X    int ierr, yr, mo, dy, hh, mm, ss;
  310. X    char timbuf[24];        /* length = first entry in "stupid" + 1 */
  311. X    int attr_given;        /* =1 if VMS attributes are present in
  312. X                 *    extra_field */
  313. X
  314. X    rab = cc$rms_rab;        /* fill FAB & RAB with default values */
  315. X    fileblk = cc$rms_fab;
  316. X
  317. X    text_output = pInfo->textmode || cflag;    /* extract the file in text
  318. X                             * (variable-length) format */
  319. X    hostnum = pInfo -> hostnum;
  320. X
  321. X    outfab = &fileblk;
  322. X    outfab->fab$l_xab = 0L;
  323. X    rfm = FAB$C_STMLF;    /* Default, stream-LF format from VMS
  324. X                *   or UNIX */
  325. X    if (text_output)
  326. X    {   /* Default format for output text file */
  327. X
  328. X    outfab->fab$b_rfm = FAB$C_VAR;    /* variable length records */
  329. X    outfab->fab$b_rat = FAB$M_CR;    /* carriage-return carriage ctrl */
  330. X    }
  331. X    else
  332. X    {   /* Default format for output binary file */
  333. X
  334. X    outfab->fab$b_rfm = FAB$C_STMLF;    /* stream-LF record format */
  335. X    outfab->fab$b_rat = FAB$M_CR;    /* carriage-return carriage ctrl */
  336. X    }
  337. X
  338. X    if (!cflag)    /* Redirect output */
  339. X    outfab->fab$l_fna = filename;
  340. X    else
  341. X    outfab->fab$l_fna = "sys$output:";
  342. X
  343. X    outfab->fab$b_fns = strlen(outfab->fab$l_fna);
  344. X
  345. X    {
  346. X    static char *month[] =
  347. X        {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
  348. X         "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
  349. X
  350. X    /*  fixed-length string descriptor: */
  351. X    struct dsc$descriptor stupid =
  352. X        {23, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};
  353. X
  354. X    yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
  355. X    mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
  356. X    dy = (lrec.last_mod_file_date & 0x1f);
  357. X    hh = (lrec.last_mod_file_time >> 11) & 0x1f;
  358. X    mm = (lrec.last_mod_file_time >> 5) & 0x3f;
  359. X    ss = (lrec.last_mod_file_time & 0x1f) * 2;
  360. X
  361. X    dattim = cc$rms_xabdat;    /* fill XABs with default values */
  362. X    rdt = cc$rms_xabrdt;
  363. X    sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", dy, month[mo], yr,
  364. X        hh, mm, ss);
  365. X    sys$bintim(&stupid, &dattim.xab$q_cdt);
  366. X    memcpy(&rdt.xab$q_rdt, &dattim.xab$q_cdt, sizeof(rdt.xab$q_rdt));
  367. X
  368. X    dattim.xab$l_nxt = outfab->fab$l_xab;
  369. X    outfab->fab$l_xab = (void *) &dattim;
  370. X    }
  371. X
  372. X    outfab->fab$w_ifi = 0;    /* Clear IFI. It may be nonzero after ZIP */
  373. X
  374. X    ierr = sys$create(outfab);
  375. X    if (ierr == RMS$_FEX)
  376. X    ierr = replace();
  377. X
  378. X    if (ierr == 0)        /* Canceled */
  379. X    return free_up(), 1;
  380. X
  381. X    if (ERR(ierr))
  382. X    {
  383. X    char buf[256];
  384. X
  385. X    sprintf(buf, "[ Cannot create output file %s ]\n", filename);
  386. X    message(buf, ierr);
  387. X    message("", outfab->fab$l_stv);
  388. X    free_up();
  389. X    return PK_WARN;
  390. X    }
  391. X
  392. X    if (!text_output)    /* Do not reopen text files and stdout
  393. X            *  Just open them in right mode         */
  394. X    {
  395. X    /*
  396. X    *       Reopen file for Block I/O with no XABs.
  397. X    */
  398. X    if ((ierr = sys$close(outfab)) != RMS$_NORMAL)
  399. X    {
  400. X#ifdef DEBUG
  401. X        message("[ create_output_file: sys$close failed ]\n", ierr);
  402. X        message("", outfab->fab$l_stv);
  403. X#endif
  404. X        fprintf(stderr, "Can't create output file:  %s\n", filename);
  405. X        free_up();
  406. X        return PK_WARN;
  407. X    }
  408. X
  409. X
  410. X    outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT;    /* Get ready for block
  411. X                             * output */
  412. X    outfab->fab$l_xab = 0L;    /* Unlink all XABs */
  413. X
  414. X    if ((ierr = sys$open(outfab)) != RMS$_NORMAL)
  415. X    {
  416. X        char buf[256];
  417. X
  418. X        sprintf(buf, "[ Cannot open output file %s ]\n", filename);
  419. X        message(buf, ierr);
  420. X        message("", outfab->fab$l_stv);
  421. X        free_up();
  422. X        return PK_WARN;
  423. X    }
  424. X    }
  425. X
  426. X    outrab = &rab;
  427. X    rab.rab$l_fab = outfab;
  428. X    if (!text_output)
  429. X    {   rab.rab$l_rop |= RAB$M_BIO;
  430. X        rab.rab$l_rop |= RAB$M_ASY;
  431. X    }
  432. X    rab.rab$b_rac = RAB$C_SEQ;
  433. X
  434. X    if ((ierr = sys$connect(outrab)) != RMS$_NORMAL)
  435. X    {
  436. X#ifdef DEBUG
  437. X    message("create_output_file: sys$connect failed.\n", ierr);
  438. X    message("", outfab->fab$l_stv);
  439. X#endif
  440. X    fprintf(stderr, "Can't create output file:  %s\n", filename);
  441. X    free_up();
  442. X    return PK_WARN;
  443. X    }
  444. X
  445. X    init_buf_ring();
  446. X
  447. X    _flush_routine = text_output? got_eol=0,_flush_stream : _flush_blocks;
  448. X    _close_routine = _close_rms;
  449. X    return PK_COOL;
  450. X}
  451. X
  452. X
  453. X
  454. Xstatic int create_rms_output()
  455. X{
  456. X    int ierr, yr, mo, dy, hh, mm, ss;
  457. X    char timbuf[24];        /* length = first entry in "stupid" + 1 */
  458. X
  459. X    rab = cc$rms_rab;        /* fill FAB & RAB with default values */
  460. X    fileblk = cc$rms_fab;
  461. X
  462. X    text_output = cflag;    /* extract the file in text (variable-length)
  463. X                 * format; ignore -a when attributes saved */
  464. X    hostnum = pInfo -> hostnum;
  465. X
  466. X    if (cflag)
  467. X    {
  468. X    if(!PRINTABLE_FORMAT(rfm=outfab->fab$b_rfm))
  469. X    {    printf("[ File %s has illegal record format to put to screen ]\n",
  470. X           filename);
  471. X        free_up();
  472. X        return PK_DISK;
  473. X    }
  474. X    }
  475. X
  476. X    if (!cflag)    /* Redirect output */
  477. X    outfab->fab$l_fna = filename;
  478. X    else
  479. X    outfab->fab$l_fna = "sys$output:";
  480. X
  481. X    outfab->fab$b_fns = strlen(outfab->fab$l_fna);
  482. X
  483. X    if (!(xabdat && xabrdt))    /* Use date/time info
  484. X                 *  from zipfile if
  485. X                 *  no attributes given
  486. X                 */
  487. X    {
  488. X    static char *month[] =
  489. X        {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
  490. X         "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
  491. X
  492. X    /*  fixed-length string descriptor: */
  493. X    struct dsc$descriptor stupid =
  494. X        {23, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};
  495. X
  496. X    yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
  497. X    mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
  498. X    dy = (lrec.last_mod_file_date & 0x1f);
  499. X    hh = (lrec.last_mod_file_time >> 11) & 0x1f;
  500. X    mm = (lrec.last_mod_file_time >> 5) & 0x3f;
  501. X    ss = (lrec.last_mod_file_time & 0x1f) * 2;
  502. X
  503. X    dattim = cc$rms_xabdat;    /* fill XABs with default values */
  504. X    rdt = cc$rms_xabrdt;
  505. X    sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", dy, month[mo], yr,
  506. X        hh, mm, ss);
  507. X    sys$bintim(&stupid, &dattim.xab$q_cdt);
  508. X    memcpy(&rdt.xab$q_rdt, &dattim.xab$q_cdt, sizeof(rdt.xab$q_rdt));
  509. X
  510. X    if (xabdat == 0L)
  511. X    {
  512. X        dattim.xab$l_nxt = outfab->fab$l_xab;
  513. X        outfab->fab$l_xab = (void *) &dattim;
  514. X    }
  515. X    }
  516. X
  517. X    outfab->fab$w_ifi = 0;    /* Clear IFI. It may be nonzero after ZIP */
  518. X
  519. X    ierr = sys$create(outfab);
  520. X    if (ierr == RMS$_FEX)
  521. X    ierr = replace();
  522. X
  523. X    if (ierr == 0)        /* Canceled */
  524. X    return free_up(), 1;
  525. X
  526. X    if (ERR(ierr))
  527. X    {
  528. X    char buf[256];
  529. X
  530. X    sprintf(buf, "[ Cannot create output file %s ]\n", filename);
  531. X    message(buf, ierr);
  532. X    message("", outfab->fab$l_stv);
  533. X    free_up();
  534. X    return PK_WARN;
  535. X    }
  536. X
  537. X    if (!text_output)    /* Do not reopen text files and stdout
  538. X            *  Just open them in right mode         */
  539. X    {
  540. X    /*
  541. X    *       Reopen file for Block I/O with no XABs.
  542. X    */
  543. X    if ((ierr = sys$close(outfab)) != RMS$_NORMAL)
  544. X    {
  545. X#ifdef DEBUG
  546. X        message("[ create_output_file: sys$close failed ]\n", ierr);
  547. X        message("", outfab->fab$l_stv);
  548. X#endif
  549. X        fprintf(stderr, "Can't create output file:  %s\n", filename);
  550. X        free_up();
  551. X        return PK_WARN;
  552. X    }
  553. X
  554. X
  555. X    outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT;    /* Get ready for block
  556. X                             * output */
  557. X    outfab->fab$l_xab = 0L;    /* Unlink all XABs */
  558. X
  559. X    if ((ierr = sys$open(outfab)) != RMS$_NORMAL)
  560. X    {
  561. X        char buf[256];
  562. X
  563. X        sprintf(buf, "[ Cannot open output file %s ]\n", filename);
  564. X        message(buf, ierr);
  565. X        message("", outfab->fab$l_stv);
  566. X        free_up();
  567. X        return PK_WARN;
  568. X    }
  569. X    }
  570. X
  571. X    outrab = &rab;
  572. X    rab.rab$l_fab = outfab;
  573. X    if (!text_output)
  574. X    {   rab.rab$l_rop |= RAB$M_BIO;
  575. X        rab.rab$l_rop |= RAB$M_ASY;
  576. X    }
  577. X    rab.rab$b_rac = RAB$C_SEQ;
  578. X
  579. X    if ((ierr = sys$connect(outrab)) != RMS$_NORMAL)
  580. X    {
  581. X#ifdef DEBUG
  582. X    message("create_output_file: sys$connect failed.\n", ierr);
  583. X    message("", outfab->fab$l_stv);
  584. X#endif
  585. X    fprintf(stderr, "Can't create output file:  %s\n", filename);
  586. X    free_up();
  587. X    return PK_WARN;
  588. X    }
  589. X
  590. X    init_buf_ring();
  591. X
  592. X    if( text_output )
  593. X    switch(rfm)
  594. X    {
  595. X        case FAB$C_VAR:
  596. X            _flush_routine = _flush_varlen;
  597. X            break;
  598. X        case FAB$C_STM:
  599. X        case FAB$C_STMCR:
  600. X        case FAB$C_STMLF:
  601. X            _flush_routine = _flush_stream;
  602. X            got_eol = 0;
  603. X            break;
  604. X        default:
  605. X            _flush_routine = _flush_blocks;
  606. X            break;
  607. X    }
  608. X    else
  609. X    _flush_routine = _flush_blocks;
  610. X    _close_routine = _close_rms;
  611. X    return PK_COOL;
  612. X}
  613. X
  614. X
  615. X
  616. Xstatic    int pka_devchn;
  617. Xstatic    int pka_vbn;
  618. X
  619. Xstatic struct
  620. X{   short   status;
  621. X    long    count;
  622. X    short   dummy;
  623. X} pka_io_sb;
  624. X
  625. Xstatic struct
  626. X{   short   status;
  627. X    short   dummy;
  628. X    void    *addr;
  629. X} pka_acp_sb;
  630. X
  631. Xstatic struct fibdef    pka_fib;
  632. Xstatic struct atrdef    pka_atr[VMS_MAX_ATRCNT];
  633. Xstatic int        pka_idx;
  634. Xstatic ulg        pka_uchar;
  635. Xstatic struct fatdef    pka_rattr;
  636. X
  637. Xstatic struct dsc$descriptor    pka_fibdsc =
  638. X{   sizeof(pka_fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (void *) &pka_fib    };
  639. X
  640. Xstatic struct dsc$descriptor_s    pka_devdsc =
  641. X{   0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &nam.nam$t_dvi[1]    };
  642. X
  643. Xstatic struct dsc$descriptor_s pka_fnam =
  644. X{   0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0    };
  645. X
  646. X
  647. X
  648. Xstatic int create_qio_output()
  649. X{   int status;
  650. X    static char exp_nam[NAM$C_MAXRSS];
  651. X    static char res_nam[NAM$C_MAXRSS];
  652. X    int    i;
  653. X
  654. X    if( cflag )
  655. X    {    fprintf(stderr,"[ Cannot put to screen ]\n");
  656. X    return PK_DISK;
  657. X    }
  658. X
  659. X    fileblk = cc$rms_fab;
  660. X    fileblk.fab$l_fna = filename;
  661. X    fileblk.fab$b_fns = strlen(filename);
  662. X
  663. X    nam = cc$rms_nam;
  664. X    fileblk.fab$l_nam = &nam;
  665. X    nam.nam$l_esa = exp_nam;
  666. X    nam.nam$b_ess = sizeof(exp_nam);
  667. X    nam.nam$l_rsa = res_nam;
  668. X    nam.nam$b_rss = sizeof(res_nam);
  669. X
  670. X    if( ERR(status = sys$parse(&fileblk)) )
  671. X    {    message("create_output_file: sys$parse failed.\n", status);
  672. X    return PK_DISK;
  673. X    }       
  674. X
  675. X    pka_devdsc.dsc$w_length = (unsigned short)nam.nam$t_dvi[0];
  676. X
  677. X    if( ERR(status = sys$assign(&pka_devdsc,&pka_devchn,0,0)) )
  678. X    {    message("sys$assign failed.\n",status);
  679. X    return PK_DISK;
  680. X    }
  681. X
  682. X    pka_fnam.dsc$a_pointer = nam.nam$l_name;
  683. X    pka_fnam.dsc$w_length  = nam.nam$b_name + nam.nam$b_type;
  684. X    if( V_flag /* keep versions */ )
  685. X    pka_fnam.dsc$w_length += nam.nam$b_ver;
  686. X
  687. X    for (i=0;i<3;i++)
  688. X    {    pka_fib.FIB$W_DID[i]=nam.nam$w_did[i];
  689. X        pka_fib.FIB$W_FID[i]=0;
  690. X    }
  691. X
  692. X    pka_fib.FIB$L_ACCTL = FIB$M_WRITE;
  693. X    /* Allocate space for the file */
  694. X    pka_fib.FIB$W_EXCTL = FIB$M_EXTEND;
  695. X    if( pka_uchar & FCH$M_CONTIG )
  696. X    pka_fib.FIB$W_EXCTL |= FIB$M_ALCON | FIB$M_FILCON;
  697. X    if( pka_uchar & FCH$M_CONTIGB )
  698. X    pka_fib.FIB$W_EXCTL |= FIB$M_ALCONB;
  699. X
  700. X#define SWAPW(x)    ( (((x)>>16)&0xFFFF) + ((x)<<16) )
  701. X
  702. X    pka_fib.fib$l_exsz = SWAPW(pka_rattr.fat$r_hiblk_overlay.fat$l_hiblk);
  703. X
  704. X    status = sys$qiow(0, pka_devchn, IO$_CREATE|IO$M_CREATE|IO$M_ACCESS,
  705. X    &pka_acp_sb, 0, 0,
  706. X    &pka_fibdsc, &pka_fnam, 0, 0, &pka_atr, 0);
  707. X
  708. X    if( !ERR(status) )
  709. X    status = pka_acp_sb.status;
  710. X
  711. X    if( ERR(status) )
  712. X    {    message("[ Create file QIO failed.\n",status);
  713. X    return PK_DISK;
  714. X    sys$dassgn(pka_devchn);
  715. X    }
  716. X
  717. X    pka_vbn = 1;
  718. X    _flush_routine = _flush_qio;
  719. X    _close_routine = _close_qio;
  720. X    return PK_COOL;
  721. X}
  722. X
  723. X
  724. X
  725. Xstatic int replace()
  726. X{            /*
  727. X            *    File exists. Inquire user about further action.
  728. X            */
  729. X    char answ[10];
  730. X    struct NAM nam;
  731. X    int ierr;
  732. X
  733. X    if (query == 0)
  734. X    {
  735. X    do
  736. X    {
  737. X        fprintf(stderr,
  738. X            "%s exists:  [o]verwrite, new [v]ersion or [n]o extract?\n\
  739. X  (uppercase response [O,V,N] = do same for all files): ",
  740. X            filename);
  741. X        fflush(stderr);
  742. X    } while (fgets(answ, 9, stderr) == NULL && !isalpha(answ[0])
  743. X         && tolower(answ[0]) != 'o'
  744. X         && tolower(answ[0]) != 'v'
  745. X         && tolower(answ[0]) != 'n');
  746. X
  747. X    if (isupper(answ[0]))
  748. X        query = answ[0] = tolower(answ[0]);
  749. X    }
  750. X    else
  751. X    answ[0] = query;
  752. X
  753. X    switch (answ[0])
  754. X    {
  755. X    case 'n':
  756. X        ierr = 0;
  757. X        break;
  758. X    case 'v':
  759. X        nam = cc$rms_nam;
  760. X        nam.nam$l_rsa = filename;
  761. X        nam.nam$b_rss = FILNAMSIZ - 1;
  762. X
  763. X        outfab->fab$l_fop |= FAB$M_MXV;
  764. X        outfab->fab$l_nam = &nam;
  765. X
  766. X        ierr = sys$create(outfab);
  767. X        if (!ERR(ierr))
  768. X        {
  769. X        outfab->fab$l_nam = 0L;
  770. X        filename[outfab->fab$b_fns = nam.nam$b_rsl] = 0;
  771. X        }
  772. X        break;
  773. X    case 'o':
  774. X        outfab->fab$l_fop |= FAB$M_SUP;
  775. X        ierr = sys$create(outfab);
  776. X        break;
  777. X    }
  778. X    return ierr;
  779. X}
  780. X
  781. X
  782. X
  783. X#define W(p)    (*(unsigned short*)(p))
  784. X#define L(p)    (*(unsigned long*)(p))
  785. X#define EQL_L(a,b)      ( L(a) == L(b) )
  786. X#define EQL_W(a,b)      ( W(a) == W(b) )
  787. X
  788. X/****************************************************************
  789. X * Function find_vms_attrs scans ZIP entry extra field if any   *
  790. X * and looks for VMS attribute records. Returns 0 if either no  *
  791. X * attributes found or no fab given.                            *
  792. X ****************************************************************/
  793. Xint find_vms_attrs()
  794. X{
  795. X    uch *scan = extra_field;
  796. X    struct  EB_header *hdr;
  797. X    int len;
  798. X    int    type=VAT_NONE;
  799. X
  800. X    outfab = NULL;
  801. X    xabfhc = NULL;
  802. X    xabdat = NULL;
  803. X    xabrdt = NULL;
  804. X    xabpro = NULL;
  805. X    first_xab = last_xab = NULL;
  806. X
  807. X    if (scan == NULL)
  808. X    return PK_COOL;
  809. X    len = lrec.extra_field_length;
  810. X
  811. X#define LINK(p) {    /* Link xaballs and xabkeys into chain */    \
  812. X                if( first_xab == 0L )                   \
  813. X                        first_xab = (void *) p;         \
  814. X                if( last_xab != 0L )                    \
  815. X                        last_xab -> xab$l_nxt = (void *) p;             \
  816. X                last_xab = (void *) p;                  \
  817. X                p -> xab$l_nxt = 0;                     \
  818. X        }
  819. X    /* End of macro LINK */
  820. X
  821. X    while (len > 0)
  822. X    {
  823. X    hdr = (struct EB_header *) scan;
  824. X    if (EQL_W(&hdr->tag, IZ_SIGNATURE))
  825. X    {
  826. X        /*
  827. X        *    INFO-ZIP style extra block decoding
  828. X        */
  829. X        struct IZ_block *blk;
  830. X        uch *block_id;
  831. X
  832. X        type = VAT_IZ;        
  833. X
  834. X        blk = (struct IZ_block *)hdr;
  835. X        block_id = (uch *) &blk->bid;
  836. X        if (EQL_L(block_id, FABSIG))
  837. X        {
  838. X        outfab = (struct FAB *) extract_block(blk, 0,
  839. X                              &cc$rms_fab, FABL);
  840. X        }
  841. X        else if (EQL_L(block_id, XALLSIG))
  842. X        {
  843. X        xaball = (struct XABALL *) extract_block(blk, 0,
  844. X                             &cc$rms_xaball, XALLL);
  845. X        LINK(xaball);
  846. X        }
  847. X        else if (EQL_L(block_id, XKEYSIG))
  848. X        {
  849. X        xabkey = (struct XABKEY *) extract_block(blk, 0,
  850. X                             &cc$rms_xabkey, XKEYL);
  851. X        LINK(xabkey);
  852. X        }
  853. X        else if (EQL_L(block_id, XFHCSIG))
  854. X        {
  855. X        xabfhc = (struct XABFHC *) extract_block(blk, 0,
  856. X                             &cc$rms_xabfhc, XFHCL);
  857. X        }
  858. X        else if (EQL_L(block_id, XDATSIG))
  859. X        {
  860. X        xabdat = (struct XABDAT *) extract_block(blk, 0,
  861. X                             &cc$rms_xabdat, XDATL);
  862. X        }
  863. X        else if (EQL_L(block_id, XRDTSIG))
  864. X        {
  865. X        xabrdt = (struct XABRDT *) extract_block(blk, 0,
  866. X                             &cc$rms_xabrdt, XRDTL);
  867. X        }
  868. X        else if (EQL_L(block_id, XPROSIG))
  869. X        {
  870. X        xabpro = (struct XABPRO *) extract_block(blk, 0,
  871. X                             &cc$rms_xabpro, XPROL);
  872. X        }
  873. X        else if (EQL_L(block_id, VERSIG))
  874. X        {
  875. X#ifdef CHECK_VERSIONS
  876. X        char verbuf[80];
  877. X        int verlen = 0;
  878. X        uch *vers;
  879. X        char *m;
  880. X
  881. X        get_vms_version(verbuf, 80);
  882. X        vers = extract_block(blk, &verlen, 0, 0);
  883. X        if ((m = strrchr((char *) vers, '-')) != NULL)
  884. X            *m = 0;    /* Cut out release number */
  885. X        if (strcmp(verbuf, (char *) vers) && qflag < 2)
  886. X        {
  887. X            printf("[ Warning: VMS version mismatch.");
  888. X
  889. X            printf("   This version %s --", verbuf);
  890. X            strncpy(verbuf, (char *) vers, verlen);
  891. X            verbuf[verlen] = 0;
  892. X            printf(" version made by %s ]\n", verbuf);
  893. X        }
  894. X        free(vers);
  895. X#endif
  896. X        }
  897. X        else
  898. X        fprintf(stderr, "[ Warning: Unknown block signature %s ]\n",
  899. X            block_id);
  900. X    }
  901. X    else if (hdr->tag == PK_SIGNATURE || hdr->tag == IZ_NEW_SIGNATURE)
  902. X    {
  903. X        /*
  904. X        *    PKWARE style extra block decoding
  905. X        */
  906. X        struct  PK_header    *blk;
  907. X        register byte   *scn;
  908. X        register int    len;
  909. X
  910. X        type = VAT_PK;        
  911. X
  912. X        blk = (struct PK_header *)hdr;
  913. X        len = blk -> size;
  914. X        scn = (byte *)(&blk->data);
  915. X        pka_idx = 0;
  916. X        
  917. X        while(len > PK_FLDHDR_SIZE)
  918. X        {    register struct  PK_field    *fld;
  919. X        int    skip=0;
  920. X
  921. X        fld = (struct PK_field *)scn;
  922. X        switch(fld->tag)
  923. X        {   case ATR$C_UCHAR:
  924. X            pka_uchar = L(&fld->value);
  925. X            break;
  926. X            case ATR$C_RECATTR:
  927. X            pka_rattr = *(struct fatdef *)(&fld->value);
  928. X            break;
  929. X            case ATR$C_UIC:
  930. X            case ATR$C_ADDACLENT:
  931. X            skip = !secinf;
  932. X            break;
  933. X        }
  934. X
  935. X        if( !skip )
  936. X        {   pka_atr[pka_idx].atr$w_size = fld->size;
  937. X            pka_atr[pka_idx].atr$w_type = fld->tag;
  938. X            pka_atr[pka_idx].atr$l_addr = &fld->value;
  939. X            ++pka_idx;
  940. X        }
  941. X        len -= fld->size + PK_FLDHDR_SIZE;
  942. X        scn += fld->size + PK_FLDHDR_SIZE;
  943. X        }
  944. X        pka_atr[pka_idx].atr$w_size = 0;    /* End of list */
  945. X        pka_atr[pka_idx].atr$w_type = 0;
  946. X        pka_atr[pka_idx].atr$l_addr = 0L;
  947. X    }
  948. X    len -= hdr->size + 4;
  949. X    scan += hdr->size + 4;
  950. X    }
  951. X
  952. X
  953. X    if( type == VAT_IZ )
  954. X    {    if (outfab != 0)
  955. X    {    /* Do not link XABPRO,XABRDT now. Leave them for sys$close() */
  956. X
  957. X        outfab->fab$l_xab = 0L;
  958. X        if (xabfhc != 0L)
  959. X        {
  960. X        xabfhc->xab$l_nxt = outfab->fab$l_xab;
  961. X        outfab->fab$l_xab = (void *) xabfhc;
  962. X        }
  963. X        if (xabdat != 0L)
  964. X        {
  965. X        xabdat->xab$l_nxt = outfab->fab$l_xab;
  966. X        outfab->fab$l_xab = (void *) xabdat;
  967. X        }
  968. X        if (first_xab != 0L)    /* Link xaball,xabkey subchain */
  969. X        {
  970. X        last_xab->xab$l_nxt = outfab->fab$l_xab;
  971. X        outfab->fab$l_xab = (void *) first_xab;
  972. X        }
  973. X    }
  974. X        else
  975. X        type = VAT_NONE;
  976. X    }
  977. X    return type;
  978. X}
  979. X
  980. X
  981. X
  982. Xstatic void free_up()
  983. X{                /*
  984. X                *    Free up all allocated xabs
  985. X                */
  986. X    if (xabdat != 0L) free(xabdat);
  987. X    if (xabpro != 0L) free(xabpro);
  988. X    if (xabrdt != 0L) free(xabrdt);
  989. X    if (xabfhc != 0L) free(xabfhc);
  990. X    while (first_xab != 0L)
  991. X    {
  992. X    struct XAB *x;
  993. X
  994. X    x = (struct XAB *) first_xab->xab$l_nxt;
  995. X    free(first_xab);
  996. X    first_xab = x;
  997. X    }
  998. X    if (outfab != 0L && outfab != &fileblk)
  999. X    free(outfab);
  1000. X}
  1001. X
  1002. X
  1003. X
  1004. X#ifdef CHECK_VERSIONS
  1005. X
  1006. Xstatic int get_vms_version(verbuf, len)
  1007. X    char *verbuf;
  1008. X    int len;
  1009. X{
  1010. X    int i = SYI$_VERSION;
  1011. X    int verlen = 0;
  1012. X    struct dsc$descriptor version;
  1013. X    char *m;
  1014. X
  1015. X    version.dsc$a_pointer = verbuf;
  1016. X    version.dsc$w_length = len - 1;
  1017. X    version.dsc$b_dtype = DSC$K_DTYPE_B;
  1018. X    version.dsc$b_class = DSC$K_CLASS_S;
  1019. X
  1020. X    if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)
  1021. X    return 0;
  1022. X
  1023. X    /* Cut out trailing spaces "V5.4-3   " -> "V5.4-3" */
  1024. X    for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)
  1025. X    --m;
  1026. X    *m = 0;
  1027. X
  1028. X    /* Cut out release number "V5.4-3" -> "V5.4" */
  1029. X    if ((m = strrchr(verbuf, '-')) != NULL)
  1030. X    *m = 0;
  1031. X    return strlen(verbuf) + 1;    /* Transmit ending 0 too */
  1032. X}
  1033. X
  1034. X#endif /* CHECK_VERSIONS */
  1035. X
  1036. X
  1037. X
  1038. X/*
  1039. X * Extracts block from p. If resulting length is less then needed, fill
  1040. X * extra space with corresponding bytes from 'init'.
  1041. X * Currently understands 3 formats of block compression:
  1042. X * - Simple storing
  1043. X * - Compression of zero bytes to zero bits
  1044. X * - Deflation (see memextract() in extract.c)
  1045. X */
  1046. Xstatic uch *extract_block(p, retlen, init, needlen)
  1047. X    struct IZ_block *p;
  1048. X    int *retlen;
  1049. X    uch *init;
  1050. X    int needlen;
  1051. X{
  1052. X    uch *block;        /* Pointer to block allocated */
  1053. X    int cmptype;
  1054. X    int usiz, csiz, max;
  1055. X
  1056. X    cmptype = p->flags & BC_MASK;
  1057. X    csiz = p->size - EXTBSL - RESL;
  1058. X    usiz = (cmptype == BC_STORED ? csiz : p->length);
  1059. X
  1060. X    if (needlen == 0)
  1061. X    needlen = usiz;
  1062. X
  1063. X    if (retlen)
  1064. X    *retlen = usiz;
  1065. X
  1066. X#ifndef MAX
  1067. X#define MAX(a,b)    ( (a) > (b) ? (a) : (b) )
  1068. X#endif
  1069. X
  1070. X    if ((block = (uch *) malloc(MAX(needlen, usiz))) == NULL)
  1071. X    return NULL;
  1072. X
  1073. X    if (init && (usiz < needlen))
  1074. X    memcpy(block, init, needlen);
  1075. X
  1076. X    switch (cmptype)
  1077. X    {
  1078. X    case BC_STORED:    /* The simplest case */
  1079. X        memcpy(block, &(p->body[0]), usiz);
  1080. X        break;
  1081. X    case BC_00:
  1082. X        decompress_bits(block, usiz, &(p->body[0]));
  1083. X        break;
  1084. X    case BC_DEFL:
  1085. X        memextract(block, usiz, &(p->body[0]), csiz);
  1086. X        break;
  1087. X    default:
  1088. X        free(block);
  1089. X        block = NULL;
  1090. X    }
  1091. X    return block;
  1092. X}
  1093. X
  1094. X
  1095. X
  1096. X/*
  1097. X *  Simple uncompression routine. The compression uses bit stream.
  1098. X *  Compression scheme:
  1099. X *
  1100. X *  if(byte!=0)
  1101. X *      putbit(1),putbyte(byte)
  1102. X *  else
  1103. X *      putbit(0)
  1104. X */
  1105. Xstatic void decompress_bits(outptr, needlen, bitptr)
  1106. X    uch *bitptr;    /* Pointer into compressed data */
  1107. X    uch *outptr;    /* Pointer into output block */
  1108. X    int needlen;    /* Size of uncompressed block */
  1109. X{
  1110. X    ulg bitbuf = 0;
  1111. X    int bitcnt = 0;
  1112. X
  1113. X#define _FILL   if(bitcnt+8 <= 32)                      \
  1114. X                {       bitbuf |= (*bitptr++) << bitcnt;\
  1115. X                        bitcnt += 8;                    \
  1116. X                }
  1117. X
  1118. X    while (needlen--)
  1119. X    {
  1120. X    if (bitcnt <= 0)
  1121. X        _FILL;
  1122. X
  1123. X    if (bitbuf & 1)
  1124. X    {
  1125. X        bitbuf >>= 1;
  1126. X        if ((bitcnt -= 1) < 8)
  1127. X        _FILL;
  1128. X        *outptr++ = (uch) bitbuf;
  1129. X        bitcnt -= 8;
  1130. X        bitbuf >>= 8;
  1131. X    }
  1132. X    else
  1133. X    {
  1134. X        *outptr++ = 0;
  1135. X        bitcnt -= 1;
  1136. X        bitbuf >>= 1;
  1137. X    }
  1138. X    }
  1139. X}
  1140. X
  1141. X
  1142. X
  1143. Xstatic void UpdateCRC(s, len)
  1144. X    register uch *s;
  1145. X    register int len;
  1146. X{
  1147. X    register ulg crcval = crc32val;
  1148. X
  1149. X    /* update running CRC calculation with contents of a buffer */
  1150. X    while (len--)
  1151. X        crcval = crc_32_tab[((uch)crcval ^ (*s++)) & 0xff] ^ (crcval >> 8);
  1152. X    crc32val = crcval;
  1153. X}
  1154. X
  1155. X
  1156. X
  1157. X/* flush contents of output buffer */
  1158. Xint flush(rawbuf, size, unshrink)    /* return PK-type error code */
  1159. X    uch *rawbuf;
  1160. X    ulg size;
  1161. X    int unshrink;
  1162. X{
  1163. X    UpdateCRC(rawbuf, size);
  1164. X    if (tflag)
  1165. X    return PK_COOL;    /* Do not output. Update CRC only */
  1166. X    else
  1167. X    return (*_flush_routine)(rawbuf, size, 0);
  1168. X}
  1169. X
  1170. X
  1171. X
  1172. Xstatic int _flush_blocks(rawbuf, size, final_flag)   /* Asynchronous version */
  1173. X    uch *rawbuf;
  1174. X    unsigned size;
  1175. X    int final_flag;   /* 1 if this is the final flushout */
  1176. X{
  1177. X    int round;
  1178. X    int rest;
  1179. X    int off = 0;
  1180. X    int status;
  1181. X
  1182. X    while (size > 0)
  1183. X    {
  1184. X    if (curbuf->bufcnt < BUFS512)
  1185. X    {
  1186. X        int ncpy;
  1187. X
  1188. X        ncpy = size > (BUFS512 - curbuf->bufcnt) ?
  1189. X                BUFS512 - curbuf->bufcnt :
  1190. X                size;
  1191. X        memcpy(curbuf->buf + curbuf->bufcnt, rawbuf + off, ncpy);
  1192. X        size -= ncpy;
  1193. X        curbuf->bufcnt += ncpy;
  1194. X        off += ncpy;
  1195. X    }
  1196. X    if (curbuf->bufcnt == BUFS512)
  1197. X    {
  1198. X        status = WriteBuffer(curbuf->buf, curbuf->bufcnt);
  1199. X        if (status)
  1200. X        return status;
  1201. X        curbuf = curbuf->next;
  1202. X        curbuf->bufcnt = 0;
  1203. X    }
  1204. X    }
  1205. X
  1206. X    return (final_flag && (curbuf->bufcnt > 0)) ?
  1207. X    WriteBuffer(curbuf->buf, curbuf->bufcnt) :
  1208. X    PK_COOL;
  1209. X}
  1210. X
  1211. X
  1212. X
  1213. Xstatic int _flush_qio(rawbuf, size, final_flag)
  1214. X    uch *rawbuf;
  1215. X    unsigned size;
  1216. X    int final_flag;   /* 1 if this is the final flushout -- currently ignored */
  1217. X{
  1218. X    int status;
  1219. X    uch    *out_ptr=rawbuf;
  1220. X
  1221. X    if( final_flag )
  1222. X    {    
  1223. X    if( loccnt > 0 )
  1224. X    {   status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK, 
  1225. X        &pka_io_sb, 0, 0,
  1226. X        locbuf, ((loccnt+1)/2)*2,   /* Round to event byte count */
  1227. X        pka_vbn,
  1228. X        0, 0, 0);
  1229. X        if(!ERR(status))        
  1230. X        status = pka_io_sb.status;
  1231. X        if(ERR(status))
  1232. X        {   message("[ Write QIO failed ]\n",status);
  1233. X        return PK_DISK;
  1234. X        }
  1235. X    }
  1236. X    return PK_COOL;    
  1237. X    }
  1238. X
  1239. X    if( loccnt > 0 )
  1240. X    {    /*
  1241. X    *   Fill local buffer upto 512 bytes then put it out
  1242. X    */
  1243. X    int ncpy;
  1244. X
  1245. X    ncpy = 512-loccnt;
  1246. X    if( ncpy > size )
  1247. X        ncpy = size;
  1248. X
  1249. X    memcpy(locptr,rawbuf,ncpy);
  1250. X    locptr += ncpy;
  1251. X    loccnt += ncpy;
  1252. X    size -= ncpy;
  1253. X    out_ptr += ncpy;
  1254. X    if( loccnt == 512 )
  1255. X    {     
  1256. X        status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK, 
  1257. X        &pka_io_sb, 0, 0,
  1258. X        locbuf, loccnt, pka_vbn,
  1259. X        0, 0, 0);
  1260. X        if(!ERR(status))        
  1261. X        status = pka_io_sb.status;
  1262. X        if(ERR(status))
  1263. X        {   message("[ Write QIO failed ]\n",status);
  1264. X        return PK_DISK;
  1265. X        }
  1266. X
  1267. X        pka_vbn++;
  1268. X        loccnt = 0;
  1269. X        locptr = locbuf;
  1270. X    }
  1271. X    }
  1272. X
  1273. X    if( size >= 512 )
  1274. X    {    int nblk,put_cnt;
  1275. X
  1276. X    /*
  1277. X    *   Put rest of buffer as a single VB
  1278. X    */
  1279. X    put_cnt = (nblk = size>>9)<<9;
  1280. X    status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK, 
  1281. X        &pka_io_sb, 0, 0,
  1282. X        out_ptr, put_cnt, pka_vbn,
  1283. X        0, 0, 0);
  1284. X    if(!ERR(status))        
  1285. X        status = pka_io_sb.status;
  1286. X    if(ERR(status))
  1287. X    {   message("[ Write QIO failed ]\n",status);
  1288. X        return PK_DISK;
  1289. X    }
  1290. X
  1291. X    pka_vbn += nblk;
  1292. X    out_ptr += put_cnt;
  1293. X    size -= put_cnt;
  1294. X    }
  1295. X
  1296. X    if( size > 0 )
  1297. X    {    memcpy(locptr,out_ptr,size);
  1298. X    loccnt += size;
  1299. X    locptr += size;
  1300. X    }
  1301. X
  1302. X
  1303. X    return PK_COOL;
  1304. X}
  1305. X
  1306. X
  1307. X
  1308. Xstatic int _flush_varlen(rawbuf, size, final_flag)
  1309. X    uch *rawbuf;
  1310. X    unsigned size;
  1311. X    int final_flag;
  1312. X{
  1313. X    ush nneed;
  1314. X    ush reclen;
  1315. X    uch *inptr=rawbuf;
  1316. X
  1317. X    /*
  1318. X    *    Flush local buffer
  1319. X    */
  1320. X
  1321. X    if( loccnt > 0 )
  1322. X    {    reclen = *(ush*)locbuf;
  1323. X        if( (nneed = reclen + 2 - loccnt) > 0 )
  1324. X        {    if( nneed > size )
  1325. X            {    if( size+loccnt > BUFS512 )
  1326. X                {    fprintf(stderr,"[ Record too long (%d bytes) ]\n",reclen );
  1327. X                    return PK_DISK;
  1328. X                }
  1329. X                memcpy(locbuf+loccnt,rawbuf,size);
  1330. X                loccnt += size;
  1331. X                size = 0;
  1332. X            }
  1333. X            else
  1334. X            {    memcpy(locbuf+loccnt,rawbuf,nneed);
  1335. X                loccnt += nneed;
  1336. X                size -= nneed;
  1337. X                inptr += nneed;
  1338. X                if( reclen & 1 )
  1339. X                {    size--;
  1340. X                    inptr++;
  1341. X                }
  1342. X                if( WriteRecord(locbuf+2,reclen) )
  1343. X                    return PK_DISK;
  1344. X                loccnt = 0;
  1345. X            }
  1346. X        }
  1347. X        else
  1348. X        {    if(WriteRecord(locbuf+2,reclen))
  1349. X                return PK_DISK;
  1350. X            loccnt -= reclen+2;
  1351. X        }
  1352. X    }
  1353. X    /*
  1354. X    *    Flush incoming records
  1355. X    */
  1356. X    while(size > 0)
  1357. X    {    reclen = *(ush*)inptr;
  1358. X        if( reclen+2 <= size )
  1359. X        {    if(WriteRecord(inptr+2,reclen))
  1360. X                return PK_DISK;
  1361. X            size -= 2+reclen;
  1362. X            inptr += 2+reclen;
  1363. X            if( reclen & 1)
  1364. X            {    --size;
  1365. X                ++inptr;
  1366. X            }
  1367. X        }
  1368. X        else
  1369. X        {    memcpy(locbuf,inptr,size);
  1370. X            loccnt = size;
  1371. X            size = 0;
  1372. X        }
  1373. X                    
  1374. X    }
  1375. X    /*
  1376. X    *    Final flush rest of local buffer
  1377. X    */
  1378. X    if( final_flag && loccnt > 0 )
  1379. X    {    fprintf(stderr,
  1380. X            "[ Warning, incomplete record of length %d ]\n",
  1381. X            *(ush*)locbuf);
  1382. X        if( WriteRecord(locbuf+2,loccnt-2) )
  1383. X            return PK_DISK;
  1384. X    }
  1385. X    return PK_COOL;
  1386. X}
  1387. X
  1388. X
  1389. X
  1390. X/*
  1391. X*   Routine _flush_stream breaks decompressed stream into records
  1392. X*   depending on format of the stream (fab->rfm, pInfo->textmode, etc.)
  1393. X*   and puts out these records. It also handles CR LF sequences.
  1394. X*   Should be used when extracting *text* files.
  1395. X*/
  1396. X
  1397. X#define VT    0x0B
  1398. X#define FF    0x0C
  1399. X
  1400. X/* The file is from MSDOS/OS2/NT -> handle CRLF as record end, throw out ^Z */
  1401. X
  1402. X/* GRR NOTES:  cannot depend on hostnum!  May have "flip'd" file or re-zipped
  1403. X * a Unix file, etc. */
  1404. X
  1405. X#ifdef    USE_ORIG_DOS
  1406. X# define ORG_DOS    (hostnum==FS_FAT_ || hostnum==FS_HPFS_ || hostnum==FS_NTFS_)
  1407. X#else
  1408. X# define ORG_DOS    1
  1409. X#endif
  1410. X
  1411. X/* Record delimiters */
  1412. X#ifdef    undef
  1413. X#define RECORD_END(c,f)                            \
  1414. X(        ( ORG_DOS || pInfo->textmode ) && c==CTRLZ            \
  1415. X    || ( f == FAB$C_STMLF && c==LF )                \
  1416. X    || ( f == FAB$C_STMCR || ORG_DOS || pInfo->textmode ) && c==CR    \
  1417. X    || ( f == FAB$C_STM && (c==CR || c==LF || c==FF || c==VT) )    \
  1418. X)
  1419. X#else
  1420. X#   define  RECORD_END(c,f)   ((c) == LF || (c) == (CR))
  1421. X#endif
  1422. X
  1423. Xstatic int  find_eol(p,n,l)
  1424. X/*
  1425. X *  Find first CR,LF,CR-LF or LF-CR in string 'p' of length 'n'.
  1426. X *  Return offset of the sequence found or 'n' if not found.
  1427. X *  If found, return in '*l' length of the sequence (1 or 2) or
  1428. X *  zero if sequence end not seen, i.e. CR or LF is last char
  1429. X *  in the buffer.
  1430. X */
  1431. Xchar    *p;
  1432. Xint    n;
  1433. Xint    *l;
  1434. X{   int    off = n;
  1435. X    char    *q;
  1436. X
  1437. X    *l = 0;
  1438. X
  1439. X    for(q=p ; n > 0 ; --n,++q)
  1440. X    if( RECORD_END(*q,rfm) )
  1441. X    {   off = q-p;
  1442. X        break;
  1443. X    }
  1444. X
  1445. X    if( n > 1 )
  1446. X    {
  1447. X    *l = 1;
  1448. X    if( ( q[0] == CR && q[1] == LF ) || ( q[0] == LF && q[1] == CR ) )
  1449. X        *l = 2;
  1450. X    }
  1451. X
  1452. X    return off;
  1453. X}
  1454. X
  1455. X/* Record delimiters that must be put out */
  1456. X#define PRINT_SPEC(c)    ( (c)==FF || (c)==VT )
  1457. X
  1458. X
  1459. X
  1460. Xstatic int _flush_stream(rawbuf, size, final_flag)
  1461. X    uch *rawbuf;
  1462. X    unsigned size;
  1463. X    int final_flag; /* 1 if this is the final flushout */
  1464. X{
  1465. X    int rest;
  1466. X    int end = 0, start = 0;
  1467. X    int off = 0;
  1468. X                 
  1469. X    if (size == 0 && loccnt == 0)
  1470. X    return PK_COOL;        /* Nothing to do ... */
  1471. X
  1472. X    if( final_flag )
  1473. X    {    int recsize;
  1474. X
  1475. X    /*
  1476. X     * This is flush only call. size must be zero now.
  1477. X     * Just eject everything we have in locbuf.
  1478. X     */
  1479. X    recsize = loccnt - (got_eol ? 1:0);
  1480. X    /*
  1481. X     *  If the last char of file was ^Z ( end-of-file in MSDOS ),
  1482. X     *  we will see it now.
  1483. X     */
  1484. X    if( recsize==1 && locbuf[0] == CTRLZ )
  1485. X        return PK_COOL;
  1486. X
  1487. X    return WriteRecord(locbuf, recsize) ? PK_DISK : PK_COOL;
  1488. X    }
  1489. X
  1490. X
  1491. X    if ( loccnt > 0 )
  1492. X    {    /* Find end of record partialy saved in locbuf */
  1493. X
  1494. X    int recsize;
  1495. X    int complete=0;
  1496. X
  1497. X    if( got_eol )
  1498. X    {   recsize = loccnt - 1;
  1499. X        complete = 1;
  1500. X
  1501. X        if( (got_eol == CR && rawbuf[0] == LF) || (got_eol == LF && rawbuf[0] == CR) )
  1502. X        end = 1;
  1503. X
  1504. X        got_eol = 0;
  1505. X    }
  1506. X    else
  1507. X    {   int    eol_len;
  1508. X        int    eol_off;
  1509. X
  1510. X        eol_off = find_eol(rawbuf,size,&eol_len);
  1511. X
  1512. X        if( loccnt+eol_off > BUFS512 )
  1513. X        {    /*
  1514. X         *  No room in locbuf. Dump it and clear
  1515. X         */
  1516. X        recsize = loccnt;
  1517. X        start = 0;
  1518. X        fprintf(stderr, "[ Warning: Record too long (%d) ]\n",
  1519. X            loccnt+eol_off);
  1520. X        complete = 1;
  1521. X        end = 0;
  1522. X        }
  1523. X        else
  1524. X        {    if( eol_off >= size )
  1525. X        {   end = size;
  1526. X            complete = 0;
  1527. X        }
  1528. X        else if( eol_len == 0 )
  1529. X        {   got_eol = rawbuf[eol_off];
  1530. X            end = size;
  1531. X            complete = 0;
  1532. X        }
  1533. X        else
  1534. X        {   memcpy(locptr, rawbuf, eol_off);
  1535. X            recsize = loccnt + eol_off;
  1536. X            locptr += eol_off;
  1537. X            loccnt += eol_off;
  1538. X            end = eol_off + eol_len;
  1539. X            complete = 1;
  1540. X        }
  1541. X        }
  1542. X    }
  1543. X
  1544. X    if( complete )
  1545. X    {   if (WriteRecord(locbuf, recsize))
  1546. X        return PK_DISK;
  1547. X        loccnt = 0;
  1548. X        locptr = locbuf;
  1549. X    }
  1550. X    }                /* end if( loccnt ) */
  1551. X
  1552. X    for(start = end; start < size && end < size; )
  1553. X    {    int eol_off,eol_len;
  1554. X
  1555. X    got_eol = 0;
  1556. X
  1557. X#ifdef undef
  1558. X        if (cflag)
  1559. X        /* skip CR's at the beginning of record */
  1560. X            while (start < size && rawbuf[start] == CR)
  1561. X                ++start;
  1562. X#endif
  1563. X
  1564. X    if( start >= size )
  1565. X        continue;
  1566. X
  1567. X    /* Find record end */
  1568. X    end = start+(eol_off = find_eol(rawbuf+start, size-start, &eol_len));
  1569. X
  1570. X        if( end >= size )
  1571. X        continue;
  1572. X
  1573. X    if( eol_len > 0 )
  1574. X    {   if( WriteRecord(rawbuf+start, end-start) )
  1575. X        return PK_DISK;
  1576. X        start = end + eol_len;
  1577. X    }
  1578. X    else
  1579. X    {   got_eol = rawbuf[end];
  1580. X        end = size;
  1581. X        continue;
  1582. X    }
  1583. X    }
  1584. X
  1585. X    rest = size - start;
  1586. X
  1587. X    if (rest > 0)
  1588. X    {    if( rest > BUFS512 )
  1589. X    {   int    recsize;
  1590. X
  1591. X        recsize = rest - (got_eol ? 1:0 );
  1592. X        fprintf(stderr, "[ Warning: Record too long (%d) ]\n", recsize);
  1593. X        got_eol = 0;
  1594. X        return WriteRecord(rawbuf+start,recsize) ? PK_DISK : PK_COOL;
  1595. X    }
  1596. X    else
  1597. X    {   memcpy(locptr, rawbuf + start, rest);
  1598. X        locptr += rest;
  1599. X        loccnt += rest;
  1600. X    }
  1601. X    }
  1602. X    return PK_COOL;
  1603. X}
  1604. X
  1605. X
  1606. X
  1607. Xstatic int WriteBuffer(buf, len)
  1608. X    unsigned char *buf;
  1609. X    int len;
  1610. X{
  1611. X    int status;
  1612. X
  1613. X    status = sys$wait(outrab);
  1614. X    if (ERR(status))
  1615. X    {
  1616. X    message("[ WriteBuffer failed ]\n", status);
  1617. X    message("", outrab->rab$l_stv);
  1618. X    }
  1619. X    outrab->rab$w_rsz = len;
  1620. X    outrab->rab$l_rbf = (char *) buf;
  1621. X
  1622. X    if (ERR(status = sys$write(outrab)))
  1623. X    {
  1624. X    message("[ WriteBuffer failed ]\n", status);
  1625. X    message("", outrab->rab$l_stv);
  1626. X    return PK_DISK;
  1627. X    }
  1628. X    return PK_COOL;
  1629. X}
  1630. X
  1631. X
  1632. X
  1633. Xstatic int WriteRecord(rec, len)
  1634. X    unsigned char *rec;
  1635. X    int len;
  1636. X{
  1637. X    int status;
  1638. X
  1639. X    if (ERR(status = sys$wait(outrab)))
  1640. X    {
  1641. X    message("[ WriteRecord failed ]\n", status);
  1642. X    message("", outrab->rab$l_stv);
  1643. X    }
  1644. X    outrab->rab$w_rsz = len;
  1645. X    outrab->rab$l_rbf = (char *) rec;
  1646. X
  1647. X    if (ERR(status = sys$put(outrab)))
  1648. X    {
  1649. X    message("[ WriteRecord failed ]\n", status);
  1650. X    message("", outrab->rab$l_stv);
  1651. X    return PK_DISK;
  1652. X    }
  1653. X    return PK_COOL;
  1654. X}
  1655. X
  1656. X
  1657. X
  1658. Xvoid close_outfile()
  1659. X{
  1660. X    int status;
  1661. X
  1662. X    status = (*_flush_routine)(0, 0, 1);     
  1663. X    if (status)
  1664. X        return /* PK_DISK */;
  1665. X    if (cflag)
  1666. X        return;         /* Don't close stdout */
  1667. X    /* return */ (*_close_routine)();
  1668. X}
  1669. X
  1670. X
  1671. X
  1672. Xstatic int _close_rms()
  1673. X{
  1674. X    int status;
  1675. X    struct XABPRO pro;
  1676. X
  1677. X    /* Link XABRDT,XABDAT and optionaly XABPRO */
  1678. X    if (xabrdt != 0L)
  1679. X    {
  1680. X    xabrdt->xab$l_nxt = 0L;
  1681. X    outfab->fab$l_xab = (void *) xabrdt;
  1682. X    }
  1683. X    else
  1684. X    {
  1685. X    rdt.xab$l_nxt = 0L;
  1686. X    outfab->fab$l_xab = (void *) &rdt;
  1687. X    }
  1688. X    if (xabdat != 0L)
  1689. X    {
  1690. X    xabdat->xab$l_nxt = outfab->fab$l_xab;
  1691. X    outfab->fab$l_xab = (void *)xabdat;
  1692. X    }
  1693. X
  1694. X    if( xabpro != 0L )
  1695. X    {
  1696. X    if( !secinf )
  1697. X        xabpro->xab$l_uic = 0;    /* Use default (user's) uic */
  1698. X    xabpro->xab$l_nxt = outfab->fab$l_xab;
  1699. X    outfab->fab$l_xab = (void *) xabpro;
  1700. X    }
  1701. X    else
  1702. X    {    pro = cc$rms_xabpro;
  1703. X    pro.xab$w_pro = pInfo->file_attr;
  1704. X    pro.xab$l_nxt = outfab->fab$l_xab;
  1705. X    outfab->fab$l_xab = (void *) &pro;
  1706. X    }
  1707. X
  1708. X    sys$wait(outrab);
  1709. X
  1710. X    status = sys$close(outfab);
  1711. X#ifdef DEBUG
  1712. X    if (ERR(status))
  1713. X    {
  1714. X    message("\r[ Warning: cannot set owner/protection/time attributes ]\n",
  1715. X      status);
  1716. X    message("", outfab->fab$l_stv);
  1717. X    }
  1718. X#endif
  1719. X    free_up();
  1720. X    return PK_COOL;
  1721. X}
  1722. X
  1723. X
  1724. X
  1725. Xstatic int _close_qio()
  1726. X{   int status;
  1727. X
  1728. X    pka_fib.FIB$L_ACCTL =
  1729. X    FIB$M_WRITE | FIB$M_NOTRUNC ;
  1730. X    pka_fib.FIB$W_EXCTL = 0;
  1731. X
  1732. X    pka_fib.FIB$W_FID[0] =
  1733. X    pka_fib.FIB$W_FID[1] =
  1734. X    pka_fib.FIB$W_FID[2] =
  1735. X    pka_fib.FIB$W_DID[0] =
  1736. X    pka_fib.FIB$W_DID[1] =
  1737. X    pka_fib.FIB$W_DID[2] = 0;
  1738. X
  1739. X    status = sys$qiow(0, pka_devchn, IO$_DEACCESS, &pka_acp_sb,
  1740. X        0, 0,
  1741. X        &pka_fibdsc, 0, 0, 0,
  1742. X        &pka_atr, 0);
  1743. X
  1744. X    sys$dassgn(pka_devchn);
  1745. X    if( !ERR(status) )
  1746. X    status = pka_acp_sb.status;
  1747. X    if( ERR(status) )
  1748. X    {    message("[ Deaccess QIO failed ]\n",status);
  1749. X    return PK_DISK;
  1750. X    }
  1751. X    return PK_COOL;
  1752. X}
  1753. X
  1754. X
  1755. X
  1756. X#ifdef DEBUG
  1757. Xdump_rms_block(p)
  1758. X    unsigned char *p;
  1759. X{
  1760. X    unsigned char bid, len;
  1761. X    int err;
  1762. X    char *type;
  1763. X    char buf[132];
  1764. X    int i;
  1765. X
  1766. X    err = 0;
  1767. X    bid = p[0];
  1768. X    len = p[1];
  1769. X    switch (bid)
  1770. X    {
  1771. X    case FAB$C_BID:
  1772. X        type = "FAB";
  1773. X        break;
  1774. X    case XAB$C_ALL:
  1775. X        type = "xabALL";
  1776. X        break;
  1777. X    case XAB$C_KEY:
  1778. X        type = "xabKEY";
  1779. X        break;
  1780. X    case XAB$C_DAT:
  1781. X        type = "xabDAT";
  1782. X        break;
  1783. X    case XAB$C_RDT:
  1784. X        type = "xabRDT";
  1785. X        break;
  1786. X    case XAB$C_FHC:
  1787. X        type = "xabFHC";
  1788. X        break;
  1789. X    case XAB$C_PRO:
  1790. X        type = "xabPRO";
  1791. X        break;
  1792. X    default:
  1793. X        type = "Unknown";
  1794. X        err = 1;
  1795. X        break;
  1796. X    }
  1797. X    printf("Block @%08X of type %s (%d).", p, type, bid);
  1798. X    if (err)
  1799. X    {
  1800. X    printf("\n");
  1801. X    return;
  1802. X    }
  1803. X    printf(" Size = %d\n", len);
  1804. X    printf(" Offset - Hex - Dec\n");
  1805. X    for (i = 0; i < len; i += 8)
  1806. X    {
  1807. X    int j;
  1808. X
  1809. X    printf("%3d - ", i);
  1810. X    for (j = 0; j < 8; j++)
  1811. X        if (i + j < len)
  1812. X        printf("%02X ", p[i + j]);
  1813. X        else
  1814. X        printf("   ");
  1815. X    printf(" - ");
  1816. X    for (j = 0; j < 8; j++)
  1817. X        if (i + j < len)
  1818. X        printf("%03d ", p[i + j]);
  1819. X        else
  1820. X        printf("    ");
  1821. X    printf("\n");
  1822. X    }
  1823. X}
  1824. X
  1825. X#endif                /* DEBUG */
  1826. X
  1827. X
  1828. X
  1829. Xstatic void message(string, status)
  1830. X    int status;
  1831. Xchar *string;
  1832. X{
  1833. X    char msgbuf[256];
  1834. X
  1835. X    $DESCRIPTOR(msgd, msgbuf);
  1836. X    int msglen = 0;
  1837. X
  1838. X    if (ERR(lib$sys_getmsg(&status, &msglen, &msgd, 0, 0)))
  1839. X    fprintf(stderr, "%s[ VMS status = %d ]\n", string, status);
  1840. X    else
  1841. X    {
  1842. X    msgbuf[msglen] = 0;
  1843. X    fprintf(stderr, "%s[ %s ]\n", string, msgbuf);
  1844. X    }
  1845. X}
  1846. X
  1847. X
  1848. X
  1849. X#ifndef SFX
  1850. X
  1851. Xchar *do_wild( wld )
  1852. X    char *wld;
  1853. X{
  1854. X    int status;
  1855. X
  1856. X    static char filename[256];
  1857. X    static char efn[256];
  1858. X    static char last_wild[256];
  1859. X    static struct FAB fab;
  1860. X    static struct NAM nam;
  1861. X    static int first_call=1;
  1862. X    static char deflt[] = "*.zip";
  1863. X
  1864. X    if( first_call || strcmp(wld, last_wild) )
  1865. X    {   /* (Re)Initialize everything */
  1866. X
  1867. X        strcpy( last_wild, wld );
  1868. X        first_call = 1;            /* New wild spec */
  1869. X
  1870. X        fab = cc$rms_fab;
  1871. X        fab.fab$l_fna = last_wild;
  1872. X        fab.fab$b_fns = strlen(last_wild);
  1873. X        fab.fab$l_dna = deflt;
  1874. X        fab.fab$b_dns = strlen(deflt);
  1875. X        fab.fab$l_nam = &nam;
  1876. X        nam = cc$rms_nam;
  1877. X        nam.nam$l_esa = efn;
  1878. X        nam.nam$b_ess = sizeof(efn)-1;
  1879. X        nam.nam$l_rsa = filename;
  1880. X        nam.nam$b_rss = sizeof(filename)-1;
  1881. X
  1882. X        if(!OK(sys$parse(&fab)))
  1883. X            return (char *)NULL;     /* Initialization failed */
  1884. X        first_call = 0;
  1885. X        if( !OK(sys$search(&fab)) )
  1886. X        {
  1887. X            strcpy( filename, wld );
  1888. X            return filename;
  1889. X        }
  1890. X    }
  1891. X    else
  1892. X    {
  1893. X        if( !OK(sys$search(&fab)) )
  1894. X        {
  1895. X            first_call = 1;        /* Reinitialize next time */
  1896. X            return (char *)NULL;
  1897. X        }
  1898. X    }
  1899. X    filename[nam.nam$b_rsl] = 0;
  1900. X    return filename;
  1901. X
  1902. X} /* end function do_wild() */
  1903. X
  1904. X#endif /* !SFX */
  1905. X
  1906. X
  1907. X
  1908. Xstatic ulg unix_to_vms[8]={ /* Map from UNIX rwx to VMS rwed */
  1909. X                /* Note that unix w bit is mapped to VMS wd bits */
  1910. X    XAB$M_NOREAD | XAB$M_NOWRITE | XAB$M_NODEL | XAB$M_NOEXE,    /* --- no access*/
  1911. X    XAB$M_NOREAD | XAB$M_NOWRITE | XAB$M_NODEL,                  /* --x */
  1912. X    XAB$M_NOREAD |                               XAB$M_NOEXE,    /* -w- */
  1913. X    XAB$M_NOREAD,                                                /* -wx */
  1914. X                   XAB$M_NOWRITE | XAB$M_NODEL | XAB$M_NOEXE,    /* r-- */
  1915. X                   XAB$M_NOWRITE | XAB$M_NODEL,                  /* r-x */
  1916. X                                                 XAB$M_NOEXE,    /* rw- */
  1917. X    0                                                            /* rwx full access*/
  1918. X};
  1919. X
  1920. X#define SETDFPROT   /* We are using undocumented VMS System Service    */
  1921. X            /* SYS$SETDFPROT here. If your version of VMS does    */
  1922. X            /* not have that service, undef SETDFPROT.        */
  1923. X            /* IM: Maybe it's better to put this to Makefile    */
  1924. X            /* and DESCRIP.MMS */
  1925. X
  1926. X
  1927. X
  1928. Xint mapattr()
  1929. X{
  1930. X    ulg  tmp=crec.external_file_attributes, theprot;
  1931. X    static ulg  defprot = -1L,
  1932. X        sysdef,owndef,grpdef,wlddef;  /* Default protection fields */
  1933. X
  1934. X
  1935. X    /* IM: The only field of XABPRO we need to set here is */
  1936. X    /*     file protection, so we need not to change type */
  1937. X    /*     of pInfo->file_attr. WORD is quite enough. */
  1938. X
  1939. X    if( defprot == -1L )
  1940. X    {
  1941. X    /*
  1942. X    * First time here -- Get user default settings
  1943. X    */
  1944. X
  1945. X#ifdef SETDFPROT    /* Undef this if linker cat't resolve SYS$SETDFPROT */
  1946. X    defprot = 0L;
  1947. X    if( !ERR(SYS$SETDFPROT(0,&defprot)) )
  1948. X    {
  1949. X        sysdef = defprot & ( (1L<<XAB$S_SYS)-1 ) << XAB$V_SYS;
  1950. X        owndef = defprot & ( (1L<<XAB$S_OWN)-1 ) << XAB$V_OWN;
  1951. X        grpdef = defprot & ( (1L<<XAB$S_GRP)-1 ) << XAB$V_GRP;
  1952. X        wlddef = defprot & ( (1L<<XAB$S_WLD)-1 ) << XAB$V_WLD;
  1953. X    }
  1954. X    else
  1955. X    {
  1956. X#endif /* ?SETDFPROT */
  1957. X        umask(defprot = umask(0));
  1958. X        defprot = ~defprot;
  1959. X        wlddef = unix_to_vms[defprot & 07] << XAB$V_WLD;
  1960. X        grpdef = unix_to_vms[(defprot>>3) & 07] << XAB$V_GRP;
  1961. X        owndef = unix_to_vms[(defprot>>6) & 07] << XAB$V_OWN;
  1962. X        sysdef = owndef << (XAB$V_SYS - XAB$V_OWN);
  1963. X        defprot = sysdef | owndef | grpdef | wlddef;
  1964. X#ifdef SETDFPROT
  1965. X    }
  1966. X#endif    /* ?SETDFPROT */
  1967. X    }
  1968. X
  1969. X    switch (pInfo->hostnum) {
  1970. X        case UNIX_:
  1971. X        case VMS_:  /*IM: ??? Does VMS Zip store protection in UNIX format ?*/
  1972. X                    /* GRR:  Yup.  Bad decision on my part... */
  1973. X            tmp = (unsigned)(tmp >> 16);  /* drwxrwxrwx */
  1974. X        theprot  = (unix_to_vms[tmp & 07] << XAB$V_WLD)
  1975. X                 | (unix_to_vms[(tmp>>3) & 07] << XAB$V_GRP)
  1976. X                 | (unix_to_vms[(tmp>>6) & 07] << XAB$V_OWN);
  1977. X
  1978. X        if( tmp & 0x4000 )
  1979. X            /* Directory -- set D bits */
  1980. X        theprot |= (XAB$M_NODEL << XAB$V_SYS)
  1981. X            | (XAB$M_NODEL << XAB$V_OWN)
  1982. X            | (XAB$M_NODEL << XAB$V_GRP)
  1983. X            | (XAB$M_NODEL << XAB$V_WLD);
  1984. X        pInfo->file_attr = theprot;
  1985. X        break;
  1986. X
  1987. X        case AMIGA_:
  1988. X            tmp = (unsigned)(tmp>>16 & 0x0f);   /* Amiga RWED bits */
  1989. X            pInfo->file_attr = (tmp << XAB$V_OWN) | grpdef | sysdef | wlddef;
  1990. X            break;
  1991. X
  1992. X        /* all remaining cases:  expand MSDOS read-only bit into write perms */
  1993. X        case FS_FAT_:
  1994. X        case FS_HPFS_:
  1995. X        case FS_NTFS_:
  1996. X        case MAC_:
  1997. X        case ATARI_:             /* (used to set = 0666) */
  1998. X        case TOPS20_:
  1999. X        default:
  2000. X        theprot = defprot;
  2001. X        if( tmp & 1 )   /* Test read-only bit */
  2002. X        {    /* Bit is set -- set bits in all fields */
  2003. X        tmp = XAB$M_NOWRITE | XAB$M_NODEL;
  2004. X        theprot |= (tmp << XAB$V_SYS) | (tmp << XAB$V_OWN) |
  2005. X               (tmp << XAB$V_GRP) | (tmp << XAB$V_WLD);
  2006. X        }
  2007. X            pInfo->file_attr = theprot;
  2008. X            break;
  2009. X    } /* end switch (host-OS-created-by) */
  2010. X
  2011. X    return 0;
  2012. X
  2013. X} /* end function mapattr() */
  2014. X
  2015. X
  2016. X
  2017. X#ifndef    EEXIST
  2018. X#  include <errno.h>    /* For mkdir() status codes */
  2019. X#endif
  2020. X
  2021. X#include <fscndef.h> /* for filescan */
  2022. X
  2023. X#   define FN_MASK   7
  2024. X#   define USE_DEFAULT    (FN_MASK+1)
  2025. X
  2026. X/*
  2027. X * Checkdir function codes:
  2028. X *    ROOT        -   set root path from unzip qq d:[dir]
  2029. X *    INIT        -   get ready for "filename"
  2030. X *    APPEND_DIR  -    append pathcomp
  2031. X *    APPEND_NAME -    append filename
  2032. X *    APPEND_NAME | USE_DEFAULT   -    expand filename using collected path
  2033. X *    GETPATH     -    return resulting filespec
  2034. X */
  2035. X
  2036. Xstatic    int created_dir;
  2037. X
  2038. Xint mapname(renamed)  /* return 0 if no error, 1 if caution (filename trunc),*/
  2039. X    int renamed;      /* 2 if warning (skip file because dir doesn't exist), */
  2040. X{                     /* 3 if error (skip file), 10 if no memory (skip file) */
  2041. X    char pathcomp[FILNAMSIZ];   /* path-component buffer */
  2042. X    char *pp, *cp=NULL;         /* character pointers */
  2043. X    char *lastsemi = NULL;      /* pointer to last semi-colon in pathcomp */
  2044. X    char *last_dot = NULL;      /* last dot not converted to underscore */
  2045. X    int quote = FALSE;          /* flag:  next char is literal */
  2046. X    int dotname = FALSE;        /* flag:  path component begins with dot */
  2047. X    int error = 0;
  2048. X    register unsigned workch;   /* hold the character being tested */
  2049. X
  2050. X    if( renamed )
  2051. X    {
  2052. X            if( !(error = checkdir(pathcomp, APPEND_NAME | USE_DEFAULT)) )
  2053. X            strcpy(filename, pathcomp);
  2054. X        return error;
  2055. X    }
  2056. X        
  2057. X/*---------------------------------------------------------------------------
  2058. X    Initialize various pointers and counters and stuff.
  2059. X  ---------------------------------------------------------------------------*/
  2060. X
  2061. X    /* can create path as long as not just freshening, or if user told us */
  2062. X    create_dirs = !fflag;
  2063. X
  2064. X    created_dir = FALSE;        /* not yet */
  2065. X
  2066. X/* GRR:  for VMS, convert to internal format now or later? or never? */
  2067. X    if (checkdir(pathcomp, INIT) == 10)
  2068. X        return 10;              /* initialize path buffer, unless no memory */
  2069. X
  2070. X    *pathcomp = '\0';           /* initialize translation buffer */
  2071. X    pp = pathcomp;              /* point to translation buffer */
  2072. X    if (jflag)              /* junking directories */
  2073. X/* GRR:  watch out for VMS version... */
  2074. X        cp = (char *)strrchr(filename, '/');
  2075. X    if (cp == NULL)             /* no '/' or not junking dirs */
  2076. X        cp = filename;          /* point to internal zipfile-member pathname */
  2077. X    else
  2078. X        ++cp;                   /* point to start of last component of path */
  2079. X
  2080. X/*---------------------------------------------------------------------------
  2081. X    Begin main loop through characters in filename.
  2082. X  ---------------------------------------------------------------------------*/
  2083. X
  2084. X    while ((workch = (uch)*cp++) != 0) {
  2085. X
  2086. X        if (quote) {              /* if character quoted, */
  2087. X            *pp++ = (char)workch; /*  include it literally */
  2088. X            quote = FALSE;
  2089. X        } else
  2090. X            switch (workch) {
  2091. X            case '/':             /* can assume -j flag not given */
  2092. X                *pp = '\0';
  2093. X                if (last_dot) {   /* one dot in directory name is legal */
  2094. X                    *last_dot = '.';
  2095. X                    last_dot = NULL;
  2096. X                }
  2097. X                if ((error = checkdir(pathcomp, APPEND_DIR)) > 1)
  2098. X                    return error;
  2099. X                pp = pathcomp;    /* reset conversion buffer for next piece */
  2100. X                lastsemi = NULL;  /* leave directory semi-colons alone */
  2101. X                break;
  2102. X
  2103. X            case ':':
  2104. X                *pp++ = '_';      /* drive names not stored in zipfile, */
  2105. X                break;            /*  so no colons allowed */
  2106. X
  2107. X            case '.':
  2108. X                if (pp == pathcomp) {     /* nothing appended yet... */
  2109. X                    if (*cp == '/') {     /* don't bother appending a "./" */
  2110. X                        ++cp;             /*  component to the path:  skip */
  2111. X                        break;            /*  to next char after the '/' */
  2112. X                    } else if (*cp == '.' && cp[1] == '/') {   /* "../" */
  2113. X                        *pp++ = '.';      /* add first dot, unchanged... */
  2114. X                        ++cp;             /* skip second dot, since it will */
  2115. X                    }                     /*  added next (as '_' for now) */
  2116. X                }
  2117. X                last_dot = pp;    /* point at last dot so far... */
  2118. X                *pp++ = '_';      /* convert dot to underscore for now */
  2119. X                break;
  2120. X
  2121. X            case ';':             /* start of VMS version? */
  2122. X                if (lastsemi)
  2123. X                    *lastsemi = '_';   /* convert previous one to underscore */
  2124. X                lastsemi = pp;
  2125. X                *pp++ = ';';      /* keep for now; remove VMS vers. later */
  2126. X                break;
  2127. X
  2128. X            case ' ':
  2129. X                *pp++ = '_';
  2130. X                break;
  2131. X
  2132. X            default:
  2133. X                if( isalpha(workch) || isdigit(workch) ||
  2134. X                    workch=='$' || workch=='-' )
  2135. X                    *pp++ = (char)workch;
  2136. X                else
  2137. X                    *pp++ = '_';  /* convert everything else to underscore */
  2138. X                break;
  2139. X            } /* end switch */
  2140. X
  2141. X    } /* end while loop */
  2142. X
  2143. X    *pp = '\0';                   /* done with pathcomp:  terminate it */
  2144. X
  2145. X    /* if not saving them, remove VMS version numbers (appended "###") */
  2146. X    if (lastsemi) {
  2147. X        pp = lastsemi + 1;        /* expect all digits after semi-colon */
  2148. X        while (isdigit((uch)(*pp)))
  2149. X            ++pp;
  2150. X        if (*pp)                  /* not version number:  convert ';' to '_' */
  2151. X            *lastsemi = '_';
  2152. X        else if (!V_flag)         /* only digits between ';' and end:  nuke */
  2153. X            *lastsemi = '\0';
  2154. X        /* else only digits and we're saving version number:  do nothing */
  2155. X    }
  2156. X
  2157. X    if (last_dot != NULL)         /* one dot is OK:  put it back in */
  2158. X        *last_dot = '.';          /* (already done for directories) */
  2159. X
  2160. X/*---------------------------------------------------------------------------
  2161. X    Report if directory was created (and no file to create:  filename ended
  2162. X    in '/'), check name to be sure it exists, and combine path and name be-
  2163. X    fore exiting.
  2164. X  ---------------------------------------------------------------------------*/
  2165. X
  2166. X    if (filename[strlen(filename) - 1] == '/') {
  2167. X        checkdir("", APPEND_NAME);   /* create directory, if not found */
  2168. X        checkdir(filename, GETPATH);
  2169. X        if (created_dir && QCOND2) {
  2170. X            fprintf(stdout, "   creating: %s\n", filename);
  2171. X            return IZ_CREATED_DIR;   /* set dir time (note trailing '/') */
  2172. X        }
  2173. X        return 2;   /* dir existed already; don't look for data to extract */
  2174. X    }
  2175. X
  2176. X    if (*pathcomp == '\0') {
  2177. X        fprintf(stderr, "mapname:  conversion of %s failed\n", filename);
  2178. X        return 3;
  2179. X    }
  2180. X
  2181. X    checkdir(pathcomp, APPEND_NAME);   /* returns 1 if truncated:  care? */
  2182. X    checkdir(filename, GETPATH);
  2183. X
  2184. X    return error;
  2185. X
  2186. X} /* end function mapname() */
  2187. X
  2188. X
  2189. X
  2190. Xint checkdir(pathcomp,fcn)
  2191. X/*
  2192. X * returns:  1 - (on APPEND_NAME) truncated filename
  2193. X *           2 - path doesn't exist, not allowed to create
  2194. X *           3 - path doesn't exist, tried to create and failed; or
  2195. X *               path exists and is not a directory, but is supposed to be
  2196. X *           4 - path is too long
  2197. X *          10 - can't allocate memory for filename buffers
  2198. X */
  2199. X    char *pathcomp;
  2200. X    int fcn;
  2201. X{
  2202. X    int function=fcn & FN_MASK;
  2203. X    static char pathbuf[FILNAMSIZ];
  2204. X    static char lastdir[FILNAMSIZ]="\t"; /* directory created last time */
  2205. X                         /* initially - impossible dir. spec. */
  2206. X    static char *pathptr=pathbuf;        /* For debugger */
  2207. X    static char *devptr, *dirptr, *namptr;
  2208. X    static int  devlen, dirlen, namlen;
  2209. X    static int  root_dirlen;
  2210. X    static char *end;
  2211. X    static int  first_comp,root_has_dir;
  2212. X    static int  rootlen=0;
  2213. X    static char *rootend;
  2214. X    static int  mkdir_failed=0;
  2215. X    int status;
  2216. X
  2217. X/************
  2218. X *** ROOT ***
  2219. X ************/
  2220. X
  2221. X#if (!defined(SFX) || defined(SFX_EXDIR))
  2222. X    if(function==ROOT)
  2223. X    {        /*  Assume VMS root spec */
  2224. X        char  *p = pathcomp;
  2225. X        char  *q;
  2226. X
  2227. X        struct
  2228. X        {   short  len;
  2229. X            short  code;
  2230. X            char   *addr;
  2231. X        } itl [4] =
  2232. X        {
  2233. X            {  0,  FSCN$_DEVICE,    0  },
  2234. X            {  0,  FSCN$_ROOT,      0  },
  2235. X            {  0,  FSCN$_DIRECTORY, 0  },
  2236. X            {  0,  0,               0  }   /* End of itemlist */
  2237. X        };
  2238. X        int fields = 0;
  2239. X        struct dsc$descriptor  pthcmp;
  2240. X
  2241. X        /*
  2242. X         *  Initialize everything
  2243. X         */
  2244. X        end = devptr = dirptr = rootend = pathbuf;
  2245. X        devlen = dirlen = rootlen = 0;
  2246. X
  2247. X        pthcmp.dsc$a_pointer = pathcomp;
  2248. X        if( (pthcmp.dsc$w_length = strlen(pathcomp)) > 255 )
  2249. X            return 4;
  2250. X
  2251. X        status = sys$filescan(&pthcmp, itl, &fields);
  2252. X        if( !OK(status) )
  2253. X            return 3;
  2254. X
  2255. X        if( fields & FSCN$M_DEVICE )
  2256. X        {   strncpy(devptr = end, itl[0].addr, itl[0].len);
  2257. X            dirptr = (end += (devlen = itl[0].len));
  2258. X        }
  2259. X
  2260. X        root_has_dir = 0;
  2261. X
  2262. X        if( fields & FSCN$M_ROOT )
  2263. X        {   int   len;
  2264. X
  2265. X            strncpy(dirptr = end, itl[1].addr,
  2266. X                len = itl[1].len - 1);        /* Cut out trailing ']' */
  2267. X            end += len;
  2268. X            root_has_dir = 1;
  2269. X        }
  2270. X
  2271. X        if( fields & FSCN$M_DIRECTORY )
  2272. X        {   char  *ptr;
  2273. X            int   len;
  2274. X
  2275. X            len = itl[2].len-1;
  2276. X            ptr = itl[2].addr;
  2277. X
  2278. X            if( root_has_dir /* i.e. root specified */ )
  2279. X            {   --len;                            /* Cut out leading dot */
  2280. X                ++ptr;                            /* ??? [a.b.c.][.d.e] */
  2281. X            }
  2282. X
  2283. X            strncpy(dirptr=end, ptr, len);  /* Replace trailing ']' */
  2284. X            *(end+=len) = '.';                    /* ... with dot */
  2285. X            ++end;
  2286. X            root_has_dir = 1;
  2287. X        }
  2288. X
  2289. X        /* When user specified "[a.b.c.]" or "[qq...]", we have too many
  2290. X        *  trailing dots. Let's cut them out. Now we surely have at least
  2291. X        *  one trailing dot and "end" points just behind it. */
  2292. X
  2293. X        dirlen = end - dirptr;
  2294. X        while( dirlen > 1 && end[-2] == '.' )
  2295. X            --dirlen,--end;
  2296. X
  2297. X        first_comp = !root_has_dir;
  2298. X        root_dirlen = end - dirptr;
  2299. X        *(rootend = end) = 0;
  2300. X        rootlen = rootend - devptr;
  2301. X        return 0;
  2302. X    }
  2303. X#endif /* !SFX || SFX_EXDIR */
  2304. X
  2305. X
  2306. X/************
  2307. X *** INIT ***
  2308. X ************/
  2309. X
  2310. X    if( function == INIT )
  2311. X    {
  2312. X        if( strlen(filename) + rootlen + 13 > 255 )
  2313. X            return 4;
  2314. X
  2315. X    if( rootlen == 0 )    /* No root given, reset everything. */
  2316. X    {   devptr = dirptr = rootend = pathbuf;
  2317. X        devlen = dirlen = 0;
  2318. X    }
  2319. X        end = rootend;
  2320. X        first_comp = !root_has_dir;
  2321. X        if( dirlen = root_dirlen )
  2322. X        end[-1] = '.';
  2323. X    *end = 0;
  2324. X        return        0;
  2325. X    }
  2326. X
  2327. X
  2328. X/******************
  2329. X *** APPEND_DIR ***
  2330. X ******************/
  2331. X    if( function == APPEND_DIR )
  2332. X    {        int cmplen;
  2333. X
  2334. X    cmplen = strlen(pathcomp);
  2335. X
  2336. X        if( first_comp )
  2337. X        {   *end++ = '[';
  2338. X        if( cmplen )
  2339. X        *end++ = '.';    /*       "dir/..." --> "[.dir...]"    */
  2340. X        /*                     else  "/dir..." --> "[dir...]"     */
  2341. X        first_comp = 0;
  2342. X    }        
  2343. X
  2344. X    if( cmplen == 1 && *pathcomp == '.' )
  2345. X            ; /* "..././..." -- ignore */
  2346. X
  2347. X        else if( cmplen == 2 && pathcomp[0] == '.' && pathcomp[1] == '.' )
  2348. X        {   /* ".../../..." -- convert to "...-..." */
  2349. X            *end++ = '-';
  2350. X            *end++ = '.';
  2351. X        }
  2352. X
  2353. X        else if( cmplen + (end-pathptr) > 255 )
  2354. X            return 4;
  2355. X
  2356. X        else
  2357. X        {   strcpy(end, pathcomp);
  2358. X            *(end+=cmplen) = '.';
  2359. X            ++end;
  2360. X        }
  2361. X        dirlen = end - dirptr;
  2362. X        *end = 0;
  2363. X        return        0;
  2364. X    }
  2365. X
  2366. X
  2367. X/*******************
  2368. X *** APPEND_NAME ***
  2369. X *******************/
  2370. X    if( function == APPEND_NAME )
  2371. X    {        if( fcn & USE_DEFAULT )
  2372. X        {   /* Expand renamed filename using collected path, return
  2373. X            *  at pathcomp */
  2374. X            struct        FAB fab;
  2375. X            struct        NAM nam;
  2376. X
  2377. X            fab = cc$rms_fab;
  2378. X            fab.fab$l_fna = filename;
  2379. X            fab.fab$b_fns = strlen(filename);
  2380. X            fab.fab$l_dna = pathptr;
  2381. X            fab.fab$b_dns = end-pathptr;
  2382. X
  2383. X            fab.fab$l_nam = &nam;
  2384. X            nam = cc$rms_nam;
  2385. X            nam.nam$l_esa = pathcomp;
  2386. X            nam.nam$b_ess = 255;            /* Assume large enaugh */
  2387. X
  2388. X            if(!OK(status = sys$parse(&fab)) && status == RMS$_DNF )    /* Directory not found: */
  2389. X            {   char    save;            /* ... try to create it */
  2390. X                char    *dirend;
  2391. X                int     mkdir_failed;
  2392. X
  2393. X                dirend = (char*)nam.nam$l_dir + nam.nam$b_dir;
  2394. X                save = *dirend;
  2395. X                *dirend = 0;
  2396. X                if( (mkdir_failed = mkdir(nam.nam$l_dev, 0)) && errno == EEXIST )
  2397. X                    mkdir_failed = 0;
  2398. X                *dirend = save;
  2399. X                if( mkdir_failed )
  2400. X                    return 3;
  2401. X                created_dir = TRUE;
  2402. X            }                                /* if (sys$parse... */
  2403. X            pathcomp[nam.nam$b_esl] = 0;
  2404. X            return 0;
  2405. X        }                                /* if (USE_DEFAULT) */
  2406. X        else
  2407. X        {
  2408. X        *end = 0;
  2409. X            if( dirlen )
  2410. X            {    dirptr[dirlen-1] = ']'; /* Close directory */
  2411. X
  2412. X        /*
  2413. X         *    Try to create the target directory.
  2414. X         *  Don't waste time creating directory that was created
  2415. X         *    last time.
  2416. X         */
  2417. X        if( STRICMP(lastdir,pathbuf) )
  2418. X        {
  2419. X            mkdir_failed = 0;
  2420. X            if( mkdir(pathbuf,0) )
  2421. X            {   if( errno != EEXIST )
  2422. X                mkdir_failed = 1;   /* Mine for GETPATH */
  2423. X            }
  2424. X            else
  2425. X            created_dir = TRUE;
  2426. X            strcpy(lastdir,pathbuf);
  2427. X        }
  2428. X        }
  2429. X        else
  2430. X        {    /*
  2431. X         * Target directory unspecified.
  2432. X         * Try to create "sys$disk:[]"
  2433. X         */
  2434. X        if( strcmp(lastdir,"sys$disk:[]") )
  2435. X        {   strcpy(lastdir,"sys$disk:[]");
  2436. X            mkdir_failed = 0;
  2437. X            if( mkdir(lastdir,0) && errno != EEXIST )
  2438. X            mkdir_failed = 1;   /* Mine for GETPATH */
  2439. X        }        
  2440. X        }
  2441. X            if( strlen(pathcomp) + (end-pathbuf) > 255 )
  2442. X                return 1;
  2443. X            strcpy(end, pathcomp);
  2444. X            end += strlen(pathcomp);
  2445. X            return 0;
  2446. X        }
  2447. X    }
  2448. X
  2449. X
  2450. X/***************
  2451. X *** GETPATH ***
  2452. X ***************/
  2453. X    if( function == GETPATH )
  2454. X    {
  2455. X        if( mkdir_failed )
  2456. X            return 3;
  2457. X        *end = 0;                        /* To be safe */
  2458. X        strcpy( pathcomp, pathbuf );
  2459. X        return 0;
  2460. X    }
  2461. X}
  2462. X
  2463. X
  2464. X
  2465. Xint check_for_newer(filename)   /* return 1 if existing file newer or equal; */
  2466. X    char *filename;             /*  0 if older; -1 if doesn't exist yet */
  2467. X{
  2468. X    unsigned short timbuf[7];
  2469. X    int dy, mo, yr, hh, mm, ss, dy2, mo2, yr2, hh2, mm2, ss2;
  2470. X    struct FAB fab;
  2471. X    struct XABDAT xdat;
  2472. X
  2473. X
  2474. X    if (stat(filename, &statbuf))
  2475. X        return DOES_NOT_EXIST;
  2476. X
  2477. X    fab  = cc$rms_fab;
  2478. X    xdat = cc$rms_xabdat;
  2479. X
  2480. X    fab.fab$l_xab = (char *) &xdat;
  2481. X    fab.fab$l_fna = filename;
  2482. X    fab.fab$b_fns = strlen(filename);
  2483. X    fab.fab$l_fop = FAB$M_GET | FAB$M_UFO;
  2484. X
  2485. X    if ((sys$open(&fab) & 1) == 0)       /* open failure:  report exists and */
  2486. X        return EXISTS_AND_OLDER;         /*  older so new copy will be made  */
  2487. X    sys$numtim(&timbuf,&xdat.xab$q_cdt);
  2488. X    fab.fab$l_xab = 0L;
  2489. X
  2490. X    sys$dassgn(fab.fab$l_stv);
  2491. X    sys$close(&fab);   /* be sure file is closed and RMS knows about it */
  2492. X
  2493. X    yr = timbuf[0];
  2494. X    yr2 = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
  2495. X    if (yr > yr2)
  2496. X        return EXISTS_AND_NEWER;
  2497. X    else if (yr < yr2)
  2498. X        return EXISTS_AND_OLDER;
  2499. X
  2500. X    mo = timbuf[1];
  2501. X    mo2 = ((lrec.last_mod_file_date >> 5) & 0x0f);
  2502. X    if (mo > mo2)
  2503. X        return EXISTS_AND_NEWER;
  2504. X    else if (mo < mo2)
  2505. X        return EXISTS_AND_OLDER;
  2506. X
  2507. X    dy = timbuf[2];
  2508. X    dy2 = (lrec.last_mod_file_date & 0x1f);
  2509. X    if (dy > dy2)
  2510. X        return EXISTS_AND_NEWER;
  2511. X    else if (dy < dy2)
  2512. X        return EXISTS_AND_OLDER;
  2513. X
  2514. X    hh = timbuf[3];
  2515. X    hh2 = (lrec.last_mod_file_time >> 11) & 0x1f;
  2516. X    if (hh > hh2)
  2517. X        return EXISTS_AND_NEWER;
  2518. X    else if (hh < hh2)
  2519. X        return EXISTS_AND_OLDER;
  2520. X
  2521. X    mm = timbuf[4];
  2522. X    mm2 = (lrec.last_mod_file_time >> 5) & 0x3f;
  2523. X    if (mm > mm2)
  2524. X        return EXISTS_AND_NEWER;
  2525. X    else if (mm < mm2)
  2526. X        return EXISTS_AND_OLDER;
  2527. X
  2528. X    /* round to nearest 2 secs--may become 60, but doesn't matter for compare */
  2529. X    ss = (int)((float)timbuf[5] + (float)timbuf[6]*.01 + 1.) & -2;
  2530. X    ss2 = (lrec.last_mod_file_time & 0x1f) * 2;
  2531. X    if (ss >= ss2)
  2532. X        return EXISTS_AND_NEWER;
  2533. X
  2534. X    return EXISTS_AND_OLDER;
  2535. X}
  2536. X
  2537. X
  2538. X
  2539. Xvoid return_VMS(ziperr)
  2540. X    int ziperr;
  2541. X{
  2542. X#ifdef RETURN_CODES
  2543. X/*---------------------------------------------------------------------------
  2544. X    Do our own, explicit processing of error codes and print message, since
  2545. X    VMS misinterprets return codes as rather obnoxious system errors ("access
  2546. X    violation," for example).
  2547. X  ---------------------------------------------------------------------------*/
  2548. X
  2549. X    switch (ziperr) {
  2550. X
  2551. X    case PK_COOL:
  2552. X        break;   /* life is fine... */
  2553. X    case PK_WARN:
  2554. X        fprintf(stderr, "\n[return-code 1:  warning error \
  2555. X(e.g., failed CRC or unknown compression method)]\n");
  2556. X        break;
  2557. X    case PK_ERR:
  2558. X    case PK_BADERR:
  2559. X        fprintf(stderr, "\n[return-code %d:  error in zipfile \
  2560. X(e.g., can't find local file header sig)]\n", ziperr);
  2561. X        break;
  2562. X    case PK_MEM:
  2563. X    case PK_MEM2:
  2564. X    case PK_MEM3:
  2565. X    case PK_MEM4:
  2566. X    case PK_MEM5:
  2567. X        fprintf(stderr, "\n[return-code %d:  insufficient memory]\n", ziperr);
  2568. X        break;
  2569. X    case PK_NOZIP:
  2570. X        fprintf(stderr, "\n[return-code 9:  zipfile not found]\n");
  2571. X        break;
  2572. X    case PK_PARAM:   /* the one that gives "access violation," I think */
  2573. X        fprintf(stderr, "\n[return-code 10:  bad or illegal parameters \
  2574. Xspecified on command line]\n");
  2575. X        break;
  2576. X    case PK_FIND:
  2577. X        fprintf(stderr,
  2578. X          "\n[return-code 11:  no files found to extract/view/etc.]\n");
  2579. X        break;
  2580. X    case PK_DISK:
  2581. X        fprintf(stderr,
  2582. X  "\n[return-code 50:  disk full or other I/O error]\n");
  2583. X        break;
  2584. X    case PK_EOF:
  2585. X        fprintf(stderr,
  2586. X          "\n[return-code 51:  unexpected EOF in zipfile (i.e., truncated)]\n");
  2587. X        break;
  2588. X    default:
  2589. X        fprintf(stderr, "\n[return-code %d:  unknown return-code (screw-up)]\n",
  2590. X          ziperr);
  2591. X        break;
  2592. X    }
  2593. X#endif /* RETURN_CODES */
  2594. X
  2595. X/*---------------------------------------------------------------------------
  2596. X    Return an intelligent status/severity level if RETURN_SEVERITY defined:
  2597. X
  2598. X    $STATUS          $SEVERITY = $STATUS & 7
  2599. X    31 .. 16 15 .. 3   2 1 0
  2600. X                       -----
  2601. X    VMS                0 0 0  0    Warning
  2602. X    FACILITY           0 0 1  1    Success
  2603. X    Number             0 1 0  2    Error
  2604. X             MESSAGE   0 1 1  3    Information
  2605. X             Number    1 0 0  4    Severe (fatal) error
  2606. X
  2607. X    0x7FFF0000 was chosen (by experimentation) to be outside the range of
  2608. X    VMS FACILITYs that have dedicated message numbers.  Hopefully this will
  2609. X    always result in silent exits--it does on VMS 5.4.  Note that the C li-
  2610. X    brary translates exit arguments of zero to a $STATUS value of 1 (i.e.,
  2611. X    exit is both silent and has a $SEVERITY of "success").
  2612. X  ---------------------------------------------------------------------------*/
  2613. X
  2614. X#ifdef RETURN_SEVERITY
  2615. X    {
  2616. X    int severity = (ziperr == 2 || (ziperr >= 9 && ziperr <= 11))? 2 : 4;
  2617. X
  2618. X    exit(                                          /* $SEVERITY:    */
  2619. X         (ziperr == PK_COOL) ? 1 :                 /*   success        */
  2620. X         (ziperr == PK_WARN) ? 0x7FFF0000 :        /*   warning        */
  2621. X         (0x7FFF0000 | (ziperr << 4) | severity)   /*   error or fatal    */
  2622. X        );
  2623. X    }
  2624. X#else
  2625. X    exit(0);   /* everything okey-dokey as far as VMS concerned */
  2626. X#endif
  2627. X
  2628. X} /* end function return_VMS() */
  2629. X
  2630. X
  2631. X
  2632. X
  2633. X
  2634. X#ifndef SFX
  2635. X
  2636. X/************************/
  2637. X/*  Function version()  */
  2638. X/************************/
  2639. X
  2640. Xvoid version()
  2641. X{
  2642. X    extern char Far  CompiledWith[];
  2643. X#ifdef VMS_VERSION
  2644. X    char buf[40];
  2645. X#endif
  2646. X
  2647. X    printf(LoadFarString(CompiledWith),
  2648. X
  2649. X#ifdef __GNUC__
  2650. X      "gcc ", __VERSION__,
  2651. X#else
  2652. X#  if 0
  2653. X      "cc ", (sprintf(buf, " version %d", _RELEASE), buf),
  2654. X#  else
  2655. X#  if defined(DECC) || defined(__DECC) || defined (__DECC__)
  2656. X      "DEC C", "",
  2657. X#  else
  2658. X#  ifdef VAXC
  2659. X      "VAX C", "",
  2660. X#  else
  2661. X      "unknown compiler", "",
  2662. X#  endif
  2663. X#  endif
  2664. X#  endif
  2665. X#endif
  2666. X
  2667. X#ifdef VMS_VERSION
  2668. X#  if defined(__alpha)
  2669. X      "OpenVMS",   /* version has trailing spaces ("V6.1   "), so truncate: */
  2670. X      (sprintf(buf, " (%.4s for Alpha)", VMS_VERSION), buf),
  2671. X#  else /* VAX */
  2672. X      (VMS_VERSION[1] >= '6')? "OpenVMS" : "VMS",
  2673. X      (sprintf(buf, " (%.4s for VAX)", VMS_VERSION), buf),
  2674. X#  endif
  2675. X#else
  2676. X      "VMS",
  2677. X      "",
  2678. X#endif /* ?VMS_VERSION */
  2679. X
  2680. X#ifdef __DATE__
  2681. X      " on ", __DATE__
  2682. X#else
  2683. X      "", ""
  2684. X#endif
  2685. X      );
  2686. X
  2687. X} /* end function version() */
  2688. X
  2689. X#endif /* !SFX */
  2690. X#endif /* VMS */
  2691. END_OF_FILE
  2692.   if test 66172 -ne `wc -c <'unzip-5.12/vms/vms.c'`; then
  2693.     echo shar: \"'unzip-5.12/vms/vms.c'\" unpacked with wrong size!
  2694.   fi
  2695.   # end of 'unzip-5.12/vms/vms.c'
  2696. fi
  2697. echo shar: End of archive 3 \(of 20\).
  2698. cp /dev/null ark3isdone
  2699. MISSING=""
  2700. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
  2701.     if test ! -f ark${I}isdone ; then
  2702.     MISSING="${MISSING} ${I}"
  2703.     fi
  2704. done
  2705. if test "${MISSING}" = "" ; then
  2706.     echo You have unpacked all 20 archives.
  2707.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2708. else
  2709.     echo You still must unpack the following archives:
  2710.     echo "        " ${MISSING}
  2711. fi
  2712. exit 0
  2713. exit 0 # Just in case...
  2714.