Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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