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