Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6725 siemargl 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 
37
#include 
38
#include 
39
#include 
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.    *
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..                                  *
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 */