home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip540.zip / os2 / rexxapi.c < prev    next >
C/C++ Source or Header  |  1998-04-29  |  33KB  |  887 lines

  1. /**********************************************************************
  2. *   REXXAPI.C                                                         *
  3. *                                                                     *
  4. *   This program adds a ZIP engine directly to the REXX language.     *
  5. *   The functions are:                                                *
  6. *       UZDropFuncs         -- Makes all functions in this package    *
  7. *                              unknown to REXX.                       *
  8. *       UZLoadFuncs         -- Makes all functions in this package    *
  9. *                              known to REXX so REXX programs may     *
  10. *                              call them.                             *
  11. *       UZFileTree          -- Searches for files matching a given    *
  12. *                              filespec, including files in           *
  13. *                              subdirectories.                        *
  14. *       UZUnZip             -- Unzip command-line entry point.        *
  15. *                              This is functionally equivalent to     *
  16. *                              using Unzip as an external program.    *
  17. *       UZUnZipToVar            -- Unzip one file to a variable       *
  18. *       UZUnZipToStem       -- Unzip files to a variable array        *
  19. *       UZVer               -- Returns the Unzip version number       *
  20. *                                                                     *
  21. **********************************************************************/
  22. /* Include files */
  23.  
  24. #ifdef OS2DLL
  25.  
  26. #define  INCL_DOS
  27. #define  INCL_DOSMEMMGR
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <stdarg.h>
  32.  
  33. #define UNZIP_INTERNAL
  34. #include "../unzip.h"
  35. #include "../version.h"
  36.  
  37.  
  38. /*********************************************************************/
  39. /*  Various definitions used by various functions.                   */
  40. /*********************************************************************/
  41.  
  42. RexxFunctionHandler UZDropFuncs;
  43. RexxFunctionHandler UZLoadFuncs;
  44. RexxFunctionHandler UZFileTree;
  45. RexxFunctionHandler UZUnZip;
  46. RexxFunctionHandler UZUnZipToVar;
  47. RexxFunctionHandler UZUnZipToStem;
  48. RexxFunctionHandler UZVer;
  49. RexxFunctionHandler UZAPIVer;
  50.  
  51.  
  52. int SetOutputVar(__GPRO__ const char *name);
  53. int SetOutputVarStem(__GPRO__ const char *name);
  54. int SetOutputVarLength(__GPRO);
  55. int WriteToVariable(__GPRO__ const char *name, char *buffer, int len);
  56. int PrintToSubVariable(__GPRO__ int idx, const char *format,...);
  57. int PrintToVariable(__GPRO__ const char *name, const char *format,...);
  58. int _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr);
  59. int TextSetNext(__GPRO__ char *format, int len, int all);
  60.  
  61. #define EZRXSTRING(r,p)  {(r).strptr=(PCH)p;(r).strlength=(ULONG)strlen((r).strptr);}
  62.  
  63.  
  64. /*********************************************************************/
  65. /* RxFncTable                                                        */
  66. /*   Array of names of the UNZIPAPI functions.                       */
  67. /*   This list is used for registration and deregistration.          */
  68. /*********************************************************************/
  69.  
  70. static PSZ  RxFncTable[] =
  71.    {
  72.       "UZDropFuncs",
  73.       "UZLoadFuncs",
  74.       "UZFileSearch",
  75.       "UZFileTree",
  76.       "UZUnZip",
  77.       "UZUnZipToVar",
  78.       "UZUnZipToStem",
  79.       "UZVer",
  80.    };
  81.  
  82. /*********************************************************************/
  83. /* Numeric Error Return Strings                                      */
  84. /*********************************************************************/
  85.  
  86. #define  NO_UTIL_ERROR    "0"          /* No error whatsoever        */
  87. #define  ERROR_NOMEM      "2"          /* Insufficient memory        */
  88.  
  89. /*********************************************************************/
  90. /* Numeric Return calls                                              */
  91. /*********************************************************************/
  92.  
  93. #define  INVALID_ROUTINE 40            /* Raise Rexx error           */
  94. #define  VALID_ROUTINE    0            /* Successful completion      */
  95.  
  96. /*********************************************************************/
  97. /* Some useful macros                                                */
  98. /*********************************************************************/
  99.  
  100. #define BUILDRXSTRING(t, s) { \
  101.   strcpy((t)->strptr,(s));\
  102.   (t)->strlength = strlen((s)); \
  103. }
  104.  
  105.  
  106. /*********************************************************************/
  107. /****************  UNZIPAPI Supporting Functions  ********************/
  108. /****************  UNZIPAPI Supporting Functions  ********************/
  109. /****************  UNZIPAPI Supporting Functions  ********************/
  110. /*********************************************************************/
  111.  
  112.  
  113. int RexxReturn(__GPRO__ int nodefault, RXSTRING *retstr)
  114. {
  115.   int ret = G.os2.rexx_error;
  116.   if (G.filenotfound)
  117.     G.os2.rexx_mes = "file not found";
  118.   if (*G.os2.rexx_mes != '0') {
  119.     if (retstr->strlength > 255) {
  120.       DosFreeMem(retstr->strptr);
  121.       retstr->strptr = NULL;
  122.     }
  123.   } else if (nodefault)
  124.     goto noBuild;
  125.   BUILDRXSTRING(retstr, G.os2.rexx_mes);
  126.  noBuild:
  127.   DESTROYGLOBALS();
  128.   return ret;
  129. }
  130.  
  131. /* Get a variable from REXX, return 0 if OK */
  132. int GetVariable(__GPRO__ const char *name)
  133. {
  134.   G.os2.request.shvnext = NULL;
  135.   EZRXSTRING(G.os2.request.shvname, name);
  136.   G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
  137.   G.os2.request.shvvalue.strptr = G.os2.buffer;
  138.   G.os2.request.shvvalue.strlength = IBUF_LEN;
  139.   G.os2.request.shvvaluelen = IBUF_LEN;
  140.   G.os2.request.shvcode = RXSHV_SYFET;
  141.   G.os2.request.shvret = 0;
  142.   switch (RexxVariablePool(&G.os2.request)) {
  143.   case RXSHV_MEMFL:
  144.     G.os2.rexx_mes = ERROR_NOMEM;
  145.     break;
  146.   case RXSHV_BADN:
  147.   case RXSHV_NEWV:
  148.     G.os2.request.shvvaluelen = 0;
  149.   case RXSHV_OK:
  150.     *(G.os2.buffer+G.os2.request.shvvaluelen) = 0;
  151.     return G.os2.request.shvvaluelen;
  152.   }
  153.   return 0;
  154. }
  155.  
  156.  
  157. /* Get REXX compound variable */
  158. /* Stem must exist in G.os2.getvar_buf w/ length in G.os2.getvar_len */
  159. int GetVariableIndex(__GPRO__ int index)
  160. {
  161.   sprintf(G.os2.getvar_buf+G.os2.getvar_len,"%d",index);
  162.   return GetVariable(__G__ G.os2.getvar_buf);
  163. }
  164.  
  165.  
  166. /* Transfer REXX array to standard C string array */
  167. /* Returns number of elements */
  168. /* User is responsible for calling KillStringArray */
  169.  
  170. int CompoundToStringArray(__GPRO__ char ***pointer, const char *name)
  171. {
  172.   int count;
  173.   int total;
  174.   char **trav;
  175.  
  176.   G.os2.getvar_len = strlen(name);
  177.   memcpy(G.os2.getvar_buf,name,G.os2.getvar_len+1);
  178.   if (*(G.os2.getvar_buf+G.os2.getvar_len-1) != '.')
  179.     *(G.os2.getvar_buf+G.os2.getvar_len++) = '.', *(G.os2.getvar_buf+G.os2.getvar_len) = 0;
  180.  
  181.   if (GetVariableIndex(__G__ 0))
  182.     return 0;
  183.  
  184.   total = atoi(G.os2.buffer);
  185.   *pointer = (char **)malloc((total+1)<<2);
  186.   trav = *pointer;
  187.   for (count = 1; count <= total; count++) {
  188.     GetVariableIndex(__G__ count);
  189.     trav[count-1] = (char *)malloc(strlen(G.os2.buffer)+1);
  190.     strcpy(trav[count-1],G.os2.buffer);
  191.   }
  192.   trav[count-1] = NULL;
  193.   return total;
  194. }
  195.  
  196.  
  197. /* Kill string array created by CompoundToStringArray */
  198.  
  199. void KillStringArray(char **pointer)
  200. {
  201.   char **trav=pointer;
  202.   while (*trav != NULL) {
  203.     free(*trav);
  204.     trav++;
  205.   }
  206.   free(pointer);
  207. }
  208.  
  209.  
  210. /*************************************************************************
  211. * Function:  UZDropFuncs                                                 *
  212. *                                                                        *
  213. * Syntax:    call UZDropFuncs                                            *
  214. *                                                                        *
  215. * Return:    NO_UTIL_ERROR - Successful.                                 *
  216. *************************************************************************/
  217.  
  218. ULONG UZDropFuncs(CHAR *name, ULONG numargs, RXSTRING args[],
  219.                   CHAR *queuename, RXSTRING *retstr)
  220. {
  221.   INT     entries;                     /* Num of entries             */
  222.   INT     j;                           /* Counter                    */
  223.  
  224.   if (numargs != 0)                    /* no arguments for this      */
  225.     return INVALID_ROUTINE;            /* raise an error             */
  226.  
  227.   retstr->strlength = 0;               /* return a null string result*/
  228.  
  229.   entries = sizeof(RxFncTable)/sizeof(PSZ);
  230.  
  231.   for (j = 0; j < entries; j++)
  232.     RexxDeregisterFunction(RxFncTable[j]);
  233.  
  234.   return VALID_ROUTINE;                /* no error on call           */
  235. }
  236.  
  237.  
  238. /*************************************************************************
  239. * Function:  UZFileTree                                                  *
  240. *                                                                        *
  241. * Syntax:    call UZFileTree zipfile, stem[, include-filespec]           *
  242. *                                [, exclude-filespec][, options]         *
  243. *                                                                        *
  244. * Params:    zipfile  - Name of zip file to search.                      *
  245. *            stem     - Name of stem var to store results in.            *
  246. *            include  - Filespec to search for (may include * and ?).    *
  247. *            exclude  - Filespec to exclude (may include * and ?).       *
  248. *            options  - Either of the following:                         *
  249. *                       'F' - Give file statistics.                      *
  250. *                          Length Date Time Name                         *
  251. *                       'Z' - Give zip statistics, too.                  *
  252. *                          Length Method Size Ratio Date Time CRC-32 Name*
  253. *                       Default is to return only filenames              *
  254. *                                                                        *
  255. * Return:    NO_UTIL_ERROR   - Successful.                               *
  256. *            ERROR_NOMEM     - Out of memory.                            *
  257. *************************************************************************/
  258.  
  259. ULONG UZFileTree(CHAR *name, ULONG numargs, RXSTRING args[],
  260.                  CHAR *queuename, RXSTRING *retstr)
  261. {
  262.                                        /* validate arguments         */
  263.   char *incname[2];
  264.   char *excname[2];
  265.   CONSTRUCTGLOBALS();
  266.  
  267.   if (numargs < 2 || numargs > 5 ||
  268.       !RXVALIDSTRING(args[0]) ||
  269.       !RXVALIDSTRING(args[1]) ||
  270.       args[0].strlength > 255) {
  271.     DESTROYGLOBALS();
  272.     return INVALID_ROUTINE;            /* Invalid call to routine    */
  273.   }
  274.                                        /* initialize data area       */
  275.   SetOutputVarStem(__G__ args[1].strptr);
  276.   G.wildzipfn = args[0].strptr;
  277.   G.process_all_files = TRUE;
  278.  
  279.   uO.lflag = 1;
  280.   uO.zipinfo_mode = TRUE;
  281.   uO.C_flag = 1;
  282.   G.extract_flag = FALSE;
  283.   uO.qflag = 2;
  284.  
  285.   if (numargs >= 3 &&                  /* check third option         */
  286.       !RXNULLSTRING(args[2]) &&
  287.       args[2].strlength > 0) {            /* a zero length string isn't */
  288.     if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) {
  289.       G.pfnames = incname;
  290.       incname[0] = args[2].strptr;
  291.       incname[1] = NULL;
  292.       G.filespecs = 1;
  293.     }
  294.     G.process_all_files = FALSE;
  295.   }
  296.  
  297.   if (numargs >= 4 &&                  /* check third option         */
  298.       !RXNULLSTRING(args[3]) &&
  299.       args[3].strlength > 0) {            /* a zero length string isn't */
  300.     if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) {
  301.       G.pxnames = excname;
  302.       excname[0] = args[3].strptr;
  303.       excname[1] = NULL;
  304.       G.xfilespecs = 1;
  305.     }
  306.     G.process_all_files = FALSE;
  307.   }
  308.  
  309.   if (numargs == 5 &&                  /* check third option         */
  310.       !RXNULLSTRING(args[4]) &&
  311.       args[4].strlength > 0) {            /* a zero length string isn't */
  312.     int first = *args[4].strptr & 0x5f;
  313.  
  314.     if (first == 'Z')
  315.       uO.vflag = 2, uO.lflag = 0, uO.zipinfo_mode = FALSE;
  316.     else if (first == 'F')
  317.       uO.vflag = 1, uO.lflag = 0, uO.zipinfo_mode = FALSE;
  318.   }
  319.  
  320.   process_zipfiles(__G);
  321.   SetOutputVarLength(__G);
  322.   if (G.filespecs > 0 && G.pfnames != incname)
  323.     KillStringArray(G.pfnames);
  324.   if (G.xfilespecs > 0 && G.pxnames != excname)
  325.     KillStringArray(G.pxnames);
  326.   return RexxReturn(__G__ 0,retstr);        /* no error on call           */
  327. }
  328.  
  329.  
  330. /*************************************************************************
  331. * Function:  UZUnZipToVar                                                *
  332. *                                                                        *
  333. * Syntax:    call UZUnZipToVar zipfile, filespec [, stem]                *
  334. *                                                                        *
  335. * Params:    zipfile  - Name of zip file to search.                      *
  336. *            filespec - File to extract                                  *
  337. *            stem     - If you specify a stem variable, the file will be *
  338. *                       extracted to the variable, one line per index    *
  339. *                       In this case, 0 will be returned                 *
  340. *                                                                        *
  341. * Return:    Extracted file                                              *
  342. *            ERROR_NOMEM     - Out of memory.                            *
  343. *************************************************************************/
  344.  
  345. ULONG UZUnZipToVar(CHAR *name, ULONG numargs, RXSTRING args[],
  346.                           CHAR *queuename, RXSTRING *retstr)
  347. {
  348.   CONSTRUCTGLOBALS();
  349.   UzpBuffer *ub = (UzpBuffer *)retstr;
  350.                                        /* validate arguments         */
  351.   if (numargs < 2 || numargs > 3 ||
  352.       !RXVALIDSTRING(args[0]) ||
  353.       !RXVALIDSTRING(args[1]) ||
  354.       args[0].strlength == 0 ||
  355.       args[1].strlength == 0) {
  356.     DESTROYGLOBALS();
  357.     return INVALID_ROUTINE;            /* Invalid call to routine    */
  358.   }
  359.  
  360.   uO.C_flag = 1;
  361.   G.redirect_data=1;
  362.   if (numargs == 3) {
  363.     if (!RXVALIDSTRING(args[2]) ||
  364.         RXNULLSTRING(args[1]) ||
  365.         args[2].strlength == 0) {
  366.       DESTROYGLOBALS();
  367.       return INVALID_ROUTINE;            /* Invalid call to routine    */
  368.     }
  369.     SetOutputVarStem(__G__ args[2].strptr);
  370.     G.redirect_text = 0;
  371.     G.redirect_data++;
  372.   }
  373.   unzipToMemory(__G__ args[0].strptr, args[1].strptr,
  374.                 G.redirect_data==1 ? ub : NULL);
  375.   return RexxReturn(__G__ G.redirect_data==1,retstr);
  376. }
  377.  
  378.  
  379. /*************************************************************************
  380. * Function:  UZUnZipToStem                                               *
  381. *                                                                        *
  382. * Syntax:    call UZUnZipToStem zipfile, stem[, include-filespec]        *
  383. *                                [, exclude-filespec][, mode]            *
  384. *                                                                        *
  385. * Params:    zipfile  - Name of zip file to search.                      *
  386. *            stem     - Name of stem var to store files in.              *
  387. *            include  - Filespec to search for (may include * and ?).    *
  388. *            exclude  - Filespec to exclude (may include * and ?).       *
  389. *            mode     - Specifies 'F'lat or 'T'ree mode.  Umm, this is   *
  390. *                        hard to explain so I'll give an example, too.   *
  391. *                       Assuming a file unzip.zip containing:            *
  392. *                               unzip.c                                  *
  393. *                               unshrink.c                               *
  394. *                               extract.c                                *
  395. *                               os2/makefile.os2                         *
  396. *                               os2/os2.c                                *
  397. *                               os2/dll/dll.def                          *
  398. *                               os2/dll/unzipapi.c                       *
  399. *                                                                        *
  400. *                       -- In flat mode, each file is stored in          *
  401. *                          stem.fullname i.e. stem."os2/dll/unzipapi.c"  *
  402. *                          A list of files is created in stem.<index>    *
  403. *                                                                        *
  404. *                       Flat mode returns:                               *
  405. *                               stem.0 = 7                               *
  406. *                               stem.1 = unzip.c                         *
  407. *                               stem.2 = unshrink.c                      *
  408. *                               stem.3 = extract.c                       *
  409. *                               stem.4 = os2/makefile.os2                *
  410. *                               stem.5 = os2/os2.c                       *
  411. *                               stem.6 = os2/dll/dll.def                 *
  412. *                               stem.7 = os2/dll/unzipapi.c              *
  413. *                                                                        *
  414. *                       And the following contain the contents of the    *
  415. *                       various programs:                                *
  416. *                               stem.unzip.c                             *
  417. *                               stem.unshrink.c                          *
  418. *                               stem.extract.c                           *
  419. *                               stem.os2/makefile.os2                    *
  420. *                               stem.os2/os2.c                           *
  421. *                               stem.os2/dll/dll.def                     *
  422. *                               stem.os2/dll/unzipapi.c                  *
  423. *                                                                        *
  424. *                       -- In tree mode, slashes are converted to periods*
  425. *                          in the pathname thus the above file would have*
  426. *                          been stored in stem.os2.dll.unzipapi.c        *
  427. *                          The index would then be stored in stem.OS2.   *
  428. *                          DLL.<index>.                                  *
  429. *                                                                        *
  430. *                       NOTE: All path names are converted to uppercase  *
  431. *                                                                        *
  432. *                       Tree mode returns:                               *
  433. *                               stem.0 = 4                               *
  434. *                               stem.1 = unzip.c                         *
  435. *                               stem.2 = unshrink.c                      *
  436. *                               stem.3 = extract.c                       *
  437. *                               stem.4 = OS2/                            *
  438. *                                                                        *
  439. *                               stem.OS2.0 = 3                           *
  440. *                               stem.OS2.1 = makefile.os2                *
  441. *                               stem.OS2.2 = os2.c                       *
  442. *                               stem.OS2.3 = DLL/                        *
  443. *                                                                        *
  444. *                               stem.OS2.DLL.0 = 2                       *
  445. *                               stem.OS2.DLL.1 = def                     *
  446. *                               stem.OS2.DLL.2 = unzipapi.c              *
  447. *                                                                        *
  448. *                       And the following contain the contents of the    *
  449. *                       various programs:                                *
  450. *                               stem.unzip.c                             *
  451. *                               stem.unshrink.c                          *
  452. *                               stem.extract.c                           *
  453. *                               stem.OS2.makefile.os2                    *
  454. *                               stem.OS2.os2.c                           *
  455. *                               stem.OS2.DLL.dll.def                     *
  456. *                               stem.OS2.DLL.unzipapi.c                  *
  457. *                                                                        *
  458. *                                                                        *
  459. * Return:    NO_UTIL_ERROR   - Successful.                               *
  460. *            ERROR_NOMEM     - Out of memory.                            *
  461. *************************************************************************/
  462.  
  463. ULONG UZUnZipToStem(CHAR *name, ULONG numargs, RXSTRING args[],
  464.                           CHAR *queuename, RXSTRING *retstr)
  465. {
  466.   char *incname[2];
  467.   char *excname[2];
  468.   CONSTRUCTGLOBALS();
  469.                                        /* validate arguments         */
  470.   if (numargs < 2 || numargs > 5 ||
  471.       !RXVALIDSTRING(args[0]) ||
  472.       !RXVALIDSTRING(args[1]) ||
  473.       args[0].strlength > 255) {
  474.     DESTROYGLOBALS();
  475.     return INVALID_ROUTINE;            /* Invalid call to routine    */
  476.   }
  477.                                        /* initialize data area       */
  478.   G.wildzipfn = args[0].strptr;
  479.   G.process_all_files = TRUE;
  480.  
  481.   uO.C_flag = 1;
  482.   G.extract_flag = TRUE;
  483.   SetOutputVarStem(__G__ args[1].strptr);
  484.   G.redirect_data = 3;
  485.   G.redirect_text = 0;
  486.  
  487.   if (numargs >= 3 &&                  /* check third option         */
  488.       !RXNULLSTRING(args[2]) &&
  489.       args[2].strlength > 0) {            /* a zero length string isn't */
  490.     if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) {
  491.       G.pfnames = incname;
  492.       incname[0] = args[2].strptr;
  493.       incname[1] = NULL;
  494.       G.filespecs = 1;
  495.     }
  496.     G.process_all_files = FALSE;
  497.   }
  498.  
  499.   if (numargs >= 4 &&                  /* check third option         */
  500.       !RXNULLSTRING(args[3]) &&
  501.       args[3].strlength > 0) {            /* a zero length string isn't */
  502.     if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) {
  503.       G.pxnames = excname;
  504.       excname[0] = args[3].strptr;
  505.       excname[1] = NULL;
  506.       G.xfilespecs = 1;
  507.     }
  508.     G.process_all_files = FALSE;
  509.   }
  510.  
  511.   if (numargs == 5 &&                  /* check third option         */
  512.       !RXNULLSTRING(args[4]) &&
  513.       (*args[4].strptr & 0x5f) == 'T') {
  514.     G.redirect_data++;
  515.     G.os2.request.shvnext = NULL;
  516.     EZRXSTRING(G.os2.request.shvname, args[4].strptr);
  517.     G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
  518.     G.os2.request.shvcode = RXSHV_SYDRO;
  519.     G.os2.request.shvret = 0;
  520.     RexxVariablePool(&G.os2.request);
  521.   }
  522.  
  523.  
  524.   uO.qflag = 2;
  525.  
  526.   process_zipfiles(__G);
  527.   if (G.filespecs > 0 && G.pfnames != incname)
  528.     KillStringArray(G.pfnames);
  529.   if (G.xfilespecs > 0 && G.pxnames != excname)
  530.     KillStringArray(G.pxnames);
  531.   if (G.redirect_data == 3)
  532.     SetOutputVarLength(__G);
  533.   return RexxReturn(__G__ 0,retstr);            /* no error on call           */
  534. }
  535.  
  536.  
  537. /*************************************************************************
  538. * Function:  UZLoadFuncs                                                 *
  539. *                                                                        *
  540. * Syntax:    call UZLoadFuncs [option]                                   *
  541. *                                                                        *
  542. * Params:    none                                                        *
  543. *                                                                        *
  544. * Return:    null string                                                 *
  545. *************************************************************************/
  546.  
  547. ULONG UZLoadFuncs(CHAR *name, ULONG numargs, RXSTRING args[],
  548.                            CHAR *queuename, RXSTRING *retstr)
  549. {
  550.   INT    entries;                      /* Num of entries             */
  551.   INT    j;                            /* Counter                    */
  552.  
  553.   retstr->strlength = 0;               /* set return value           */
  554.                                        /* check arguments            */
  555.   if (numargs > 0)
  556.     return INVALID_ROUTINE;
  557.  
  558.   entries = sizeof(RxFncTable)/sizeof(PSZ);
  559.  
  560.   for (j = 0; j < entries; j++) {
  561.     RexxRegisterFunctionDll(RxFncTable[j],
  562.           "UNZIP32", RxFncTable[j]);
  563.   }
  564.   return VALID_ROUTINE;
  565. }
  566.  
  567.  
  568.  
  569. /*************************************************************************
  570. * Function:  UZVer                                                       *
  571. *                                                                        *
  572. * Syntax:    call UZVer                                                  *
  573. *                                                                        *
  574. * Return:    Version of Unzip                                            *
  575. *************************************************************************/
  576.  
  577. ULONG UZVer(CHAR *name, ULONG numargs, RXSTRING args[],
  578.                         CHAR *queuename, RXSTRING *retstr)
  579. {
  580.   if (numargs > 1)                    /* validate arg count         */
  581.     return INVALID_ROUTINE;
  582.  
  583.   if (numargs == 0 || (*args[0].strptr & 0x5f) != 'L')
  584.     /* strcpy( retstr->strptr, UZ_VERNUM );    "5.13a BETA" */
  585.     sprintf( retstr->strptr, "%d.%d%d%s", UZ_MAJORVER, UZ_MINORVER,
  586.       PATCHLEVEL, BETALEVEL );
  587.   else
  588.     /* strcpy( retstr->strptr, UZ_VERSION );   UZ_VERNUM" of 26 Sep 94" */
  589.     sprintf( retstr->strptr, "%d.%d%d%s of %s", UZ_MAJORVER, UZ_MINORVER,
  590.       PATCHLEVEL, BETALEVEL, VERSION_DATE );
  591.   retstr->strlength = strlen(retstr->strptr);
  592.   return VALID_ROUTINE;
  593. }
  594.  
  595.  
  596. /*************************************************************************
  597. * Function:  UZUnZip                                                     *
  598. *                                                                        *
  599. * Syntax:    call UZUnZip                                                *
  600. *                                                                        *
  601. * Return:    Unzip return code                                           *
  602. *************************************************************************/
  603.  
  604. ULONG UZUnZip(CHAR *name, ULONG numargs, RXSTRING args[],
  605.                         CHAR *queuename, RXSTRING *retstr)
  606. {
  607.   char *argv[30];
  608.   char *scan;
  609.   int argc=0;
  610.   int idx;
  611.   CONSTRUCTGLOBALS();
  612.  
  613.   if (numargs < 1 || numargs > 2 ||
  614.       args[0].strlength > 255) {
  615.     DESTROYGLOBALS();
  616.     return INVALID_ROUTINE;            /* Invalid call to routine    */
  617.   }
  618.                                        /* initialize data area       */
  619.   if (numargs == 2)
  620.     SetOutputVarStem(__G__ args[1].strptr);
  621.  
  622.   scan = args[0].strptr;
  623.   argv[argc++] = "";         /* D:\\SOURCECODE\\UNZIP51S\\UNZIP.COM"; */
  624.   while (*scan == ' ')
  625.     scan++;
  626.   argv[argc++] = scan;
  627.   while ( (scan = strchr(scan,' ')) != NULL) {
  628.     *scan++ = 0;
  629.     while (*scan == ' ')
  630.       scan++;
  631.     argv[argc++] = scan;
  632.   }
  633.   if (*argv[argc-1] == 0)
  634.     argc--;
  635.   argv[argc] = 0;
  636.  
  637.          /* GRR:  should resetMainFlags() be called in here somewhere? */
  638.  
  639.   sprintf(retstr->strptr, "%d", unzip(__G__ argc, argv));   /* a.k.a. MAIN() */
  640.   if (numargs == 2)
  641.     SetOutputVarLength(__G);
  642.   retstr->strlength = strlen(retstr->strptr);
  643.   return RexxReturn(__G__ 1,retstr);
  644. }
  645.  
  646. int varmessage(__GPRO__ uch *buf, ulg size)
  647. {
  648.   if (size > 0)
  649.     memcpy(G.os2.buffer+G.os2.putchar_idx,buf,size);
  650.     G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, size+G.os2.putchar_idx,0);
  651.   return 0;
  652. }
  653.  
  654. int varputchar(__GPRO__ int c)
  655. {
  656.   G.os2.buffer[G.os2.putchar_idx++] = c;
  657.   if (c == '\n') {
  658.     G.os2.buffer[G.os2.putchar_idx] = 0;
  659.     if (G.os2.output_var[0])
  660.       G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, G.os2.putchar_idx,0);
  661.     else {
  662.       G.os2.buffer[--G.os2.putchar_idx] = 0;
  663.       puts(G.os2.buffer);
  664.       G.os2.putchar_idx = 0;
  665.     }
  666.   }
  667.   return 1;
  668. }
  669.  
  670.  
  671.  
  672. int SetOutputVarStem(__GPRO__ const char *name)
  673. {
  674.   int len=strlen(name);
  675.   G.redirect_text=1;
  676.   G.os2.output_idx = 0;
  677.   strcpy(G.os2.output_var, name);
  678.   if (len) {
  679.     strupr(G.os2.output_var);                 /* uppercase the name         */
  680.     if (*(G.os2.output_var+len-1) != '.') {
  681.       *(G.os2.output_var+len) = '.';
  682.       len++;
  683.       *(G.os2.output_var+len) = 0;
  684.     }
  685.     WriteToVariable(__G__ G.os2.output_var,"",0);
  686.   }
  687.   G.os2.stem_len = len;
  688.   return G.os2.stem_len;
  689. }
  690.  
  691. int SetOutputVar(__GPRO__ const char *name)
  692. {
  693.   int len=strlen(name);
  694.   G.redirect_text=1;
  695.   G.os2.output_idx = 0;
  696.   strcpy(G.os2.output_var, name);
  697.   strupr(G.os2.output_var);                 /* uppercase the name         */
  698.   if (*(name+len-1) == '.')
  699.     G.os2.stem_len = len;
  700.   else
  701.     G.os2.stem_len = 0;
  702.   return G.os2.stem_len;
  703. }
  704.  
  705. int SetOutputVarLength(__GPRO)
  706. {
  707.   if (G.os2.stem_len > 0) {
  708.     if (G.os2.putchar_idx)
  709.       TextSetNext(__G__ G.os2.buffer,G.os2.putchar_idx,1);
  710.     return PrintToSubVariable(__G__ 0,"%d",G.os2.output_idx);
  711.   }
  712.   return 0;
  713. }
  714.  
  715. int PrintToVariable(__GPRO__ const char *name, const char *format,...)
  716. {
  717.   va_list arg_ptr;
  718.   int ret;
  719.  
  720.   va_start(arg_ptr, format);
  721.   ret = _PrintToVariable(__G__ name, format, arg_ptr);
  722.   va_end(arg_ptr);
  723.   return ret;
  724. }
  725.  
  726. int WriteToVariable(__GPRO__ const char *name, char *buffer, int len)
  727. {
  728.   G.os2.request.shvnext = NULL;
  729.   EZRXSTRING(G.os2.request.shvname, name);
  730.   G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
  731.   G.os2.request.shvvalue.strptr = buffer;
  732.   G.os2.request.shvvalue.strlength = len;
  733.   G.os2.request.shvvaluelen = len;
  734.   G.os2.request.shvcode = RXSHV_SET;
  735.   G.os2.request.shvret = 0;
  736.   switch (RexxVariablePool(&G.os2.request)) {
  737.   case RXSHV_BADN:
  738.     G.os2.rexx_error = INVALID_ROUTINE;
  739.     break;
  740.   case RXSHV_MEMFL:
  741.     G.os2.rexx_mes = ERROR_NOMEM;
  742.     break;
  743.   case RXSHV_OK:
  744.     return 0;
  745.   }
  746.   return INVALID_ROUTINE;      /* error on non-zero          */
  747. }
  748.  
  749. int _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr)
  750. {
  751.   int ret = vsprintf(G.os2.buffer, format, arg_ptr);
  752.   WriteToVariable(__G__ name, G.os2.buffer, strlen(G.os2.buffer));
  753.   return ret;
  754. }
  755.  
  756. int PrintToSubVariable(__GPRO__ int idx, const char *format, ...)
  757. {
  758.   va_list arg_ptr;
  759.   int ret;
  760.  
  761.   if (G.os2.stem_len == 0)
  762.     return INVALID_ROUTINE;      /* error on non-zero          */
  763.   sprintf(G.os2.output_var+G.os2.stem_len,"%d",idx);
  764.  
  765.   va_start(arg_ptr, format);
  766.   ret = _PrintToVariable(__G__ G.os2.output_var, format, arg_ptr);
  767.   va_end(arg_ptr);
  768.   return ret;
  769. }
  770.  
  771.  
  772. int WriteToNextVariable(__GPRO__ char *buffer, int len)
  773. {
  774.   if (G.os2.stem_len > 0) {
  775.     G.os2.output_idx++;
  776.     sprintf(G.os2.output_var+G.os2.stem_len,"%d",G.os2.output_idx);
  777.   }
  778.   return WriteToVariable(__G__ G.os2.output_var, buffer, len);
  779. }
  780.  
  781.  
  782. int TextSetNext(__GPRO__ char *buffer, int len, int all)
  783. {
  784.   char *scan = buffer, *next, *base=buffer;
  785.   int remaining=len;
  786.   int ret;
  787.  
  788.   while ((next = strchr(scan,'\n')) != NULL && remaining > 0) {
  789.     if (next > scan && *(next-1) == 0xd)
  790.       *(next-1) = 0;
  791.     else
  792.       *next = 0;
  793.     if (WriteToNextVariable(__G__ scan,strlen(scan)))
  794.       return 0;
  795.     next++;
  796.     remaining -= (next-scan);
  797.     scan = next;
  798.   }
  799.   if (remaining > 0)
  800.     if (all) {
  801.       *(scan+remaining) = 0;
  802.       WriteToNextVariable(__G__ scan,remaining);
  803.     } else {
  804.       memcpy(buffer,scan,remaining);
  805.       return remaining;
  806.     }
  807.  
  808.   return 0;
  809. }
  810.  
  811. int finish_REXX_redirect(__GPRO)
  812. {
  813.   char *scan, *ptr;
  814.   int idx=0, first=1, offset;
  815.  
  816.   if (!G.redirect_size)
  817.     return 0;
  818.   switch(G.redirect_data) {
  819.   case 1:
  820.     break;
  821.   case 2:
  822.     TextSetNext(__G__ G.redirect_buffer, G.redirect_size, 1);
  823.     SetOutputVarLength(__G);
  824.     DosFreeMem(G.redirect_buffer);
  825.     G.redirect_buffer = NULL;
  826.     G.redirect_size = 0;
  827.     break;
  828.   case 3:
  829.     WriteToNextVariable(__G__ G.filename,strlen(G.filename));
  830.     sprintf(G.os2.output_var+G.os2.stem_len,G.filename);
  831.     WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size);
  832.     DosFreeMem(G.redirect_buffer);
  833.     G.redirect_buffer = NULL;
  834.     G.redirect_size = 0;
  835.     break;
  836.   case 4:
  837.     if ((scan = strrchr(G.filename,'/')) != NULL) {
  838.       idx = *scan;
  839.       *scan = 0;
  840.       strupr(G.filename);
  841.       *scan = idx;
  842.     }
  843.     scan = G.os2.output_var+G.os2.stem_len;
  844.     strcpy(scan,G.filename);
  845.     while ((scan = strchr(scan,'/')) != NULL)
  846.       *scan = '.';
  847.     WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size);
  848.     DosFreeMem(G.redirect_buffer);
  849.     G.redirect_buffer = NULL;
  850.     G.redirect_size = 0;
  851.     strcpy(G.os2.getvar_buf, G.os2.output_var);
  852.     do {
  853.       if ((scan = strrchr(G.filename,'/')) == NULL)
  854.         offset = 0;
  855.       else
  856.         offset = scan-G.filename+1;
  857.       if (first || !GetVariable(__G__ G.os2.output_var)) {
  858.         ptr = G.os2.getvar_buf+offset+G.os2.stem_len;
  859.         *ptr = '0';
  860.         *(ptr+1) = 0;
  861.         if (!GetVariable(__G__ G.os2.getvar_buf))
  862.           idx = 1;
  863.         else
  864.           idx = atoi(G.os2.buffer)+1;
  865.         PrintToVariable(__G__ G.os2.getvar_buf,"%d",idx);
  866.         sprintf(ptr,"%d",idx);
  867.         if (!first) {
  868.           PrintToVariable(__G__ G.os2.output_var,"%d",idx);
  869.           idx = strlen(G.filename);
  870.           *(G.filename+idx)   = '/';
  871.           *(G.filename+idx+1) = 0;
  872.         }
  873.         WriteToVariable(__G__ G.os2.getvar_buf,G.filename+offset,strlen(G.filename+offset));
  874.         first=0;
  875.       }
  876.       if (offset) {
  877.         *(G.os2.output_var+G.os2.stem_len+offset-1)   = 0;
  878.         *scan = 0;
  879.       }
  880.     } while (offset);
  881.     break;
  882.   }
  883.   return 0;
  884. }
  885.  
  886. #endif /* OS2DLL */
  887.