home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip52.zip / vms / cmdline.c next >
C/C++ Source or Header  |  1996-02-17  |  25KB  |  814 lines

  1. #define module_name VMS_UNZIP_CMDLINE
  2. #define module_ident "02-004"
  3. /*
  4. **
  5. **  Facility:   UNZIP
  6. **
  7. **  Module:     VMS_UNZIP_CMDLINE
  8. **
  9. **  Author:     Hunter Goatley <goathunter@wkuvx1.wku.edu>
  10. **
  11. **  Date:       12 Jul 94 (orig. Zip version, 30 Jul 93)
  12. **
  13. **  Abstract:   Routines to handle a VMS CLI interface for UnZip.  The CLI
  14. **              command line is parsed and a new argc/argv are built and
  15. **              returned to UnZip.
  16. **
  17. **  Modified by:
  18. **
  19. **      02-004          Christian Spieler       06-FEB-1996 02:20
  20. **              Added /HELP qualifier.
  21. **      02-003          Christian Spieler       23-DEC-1995 17:20
  22. **              Adapted to UnZip 5.2.
  23. **      02-002          Hunter Goatley          16-JUL-1994 10:20
  24. **              Fixed some typos.
  25. **      02-001          Cave Newt               14-JUL-1994 15:18
  26. **              Removed obsolete /EXTRACT option; fixed /*TEXT options;
  27. **              wrote VMSCLI usage() function
  28. **      02-000          Hunter Goatley          12-JUL-1994 00:00
  29. **              Original UnZip version (v5.11).
  30. **      01-000          Hunter Goatley          30-JUL-1993 07:54
  31. **              Original version (for Zip v1.9p1).
  32. **
  33. */
  34.  
  35.  
  36. #ifdef __DECC
  37. #pragma module module_name module_ident
  38. #else
  39. #module module_name module_ident
  40. #endif
  41.  
  42. #define UNZIP_INTERNAL
  43. #include "unzip.h"
  44. #include "version.h"    /* for usage() */
  45.  
  46. #include <ssdef.h>
  47. #include <descrip.h>
  48. #include <climsgdef.h>
  49. #include <clidef.h>
  50. #include <lib$routines.h>
  51. #include <str$routines.h>
  52.  
  53. #ifndef CLI$_COMMA
  54. globalvalue CLI$_COMMA;
  55. #endif
  56.  
  57. /*
  58. **  "Macro" to initialize a dynamic string descriptor.
  59. */
  60. #define init_dyndesc(dsc) {\
  61.         dsc.dsc$w_length = 0;\
  62.         dsc.dsc$b_dtype = DSC$K_DTYPE_T;\
  63.         dsc.dsc$b_class = DSC$K_CLASS_D;\
  64.         dsc.dsc$a_pointer = NULL;}
  65.  
  66. /*
  67. **  Define descriptors for all of the CLI parameters and qualifiers.
  68. */
  69. #if 0
  70. $DESCRIPTOR(cli_extract,        "EXTRACT");     /* obsolete */
  71. #endif
  72. $DESCRIPTOR(cli_text,           "TEXT");        /* -a[a] */
  73. $DESCRIPTOR(cli_text_auto,      "TEXT.AUTO");   /* -a */
  74. $DESCRIPTOR(cli_text_all,       "TEXT.ALL");    /* -aa */
  75. $DESCRIPTOR(cli_text_none,      "TEXT.NONE");   /* ---a */
  76. $DESCRIPTOR(cli_binary,         "BINARY");      /* -b[b] */
  77. $DESCRIPTOR(cli_binary_auto,    "BINARY.AUTO"); /* -b */
  78. $DESCRIPTOR(cli_binary_all,     "BINARY.ALL");  /* -bb */
  79. $DESCRIPTOR(cli_binary_none,    "BINARY.NONE"); /* ---b */
  80. $DESCRIPTOR(cli_case_insensitive,"CASE_INSENSITIVE");   /* -C */
  81. $DESCRIPTOR(cli_screen,         "SCREEN");      /* -c */
  82. $DESCRIPTOR(cli_directory,      "DIRECTORY");   /* -d */
  83. $DESCRIPTOR(cli_freshen,        "FRESHEN");     /* -f */
  84. $DESCRIPTOR(cli_help,           "HELP");        /* -h */
  85. $DESCRIPTOR(cli_junk,           "JUNK");        /* -j */
  86. $DESCRIPTOR(cli_lowercase,      "LOWERCASE");   /* -L */
  87. $DESCRIPTOR(cli_list,           "LIST");        /* -l */
  88. $DESCRIPTOR(cli_brief,          "BRIEF");       /* -l */
  89. $DESCRIPTOR(cli_full,           "FULL");        /* -v */
  90. $DESCRIPTOR(cli_overwrite,      "OVERWRITE");   /* -o, -n */
  91. $DESCRIPTOR(cli_quiet,          "QUIET");       /* -q */
  92. $DESCRIPTOR(cli_super_quiet,    "QUIET.SUPER"); /* -qq */
  93. $DESCRIPTOR(cli_test,           "TEST");        /* -t */
  94. $DESCRIPTOR(cli_type,           "TYPE");        /* -c */
  95. $DESCRIPTOR(cli_pipe,           "PIPE");        /* -p */
  96. $DESCRIPTOR(cli_uppercase,      "UPPERCASE");   /* -U */
  97. $DESCRIPTOR(cli_update,         "UPDATE");      /* -u */
  98. $DESCRIPTOR(cli_version,        "VERSION");     /* -V */
  99. $DESCRIPTOR(cli_restore,        "RESTORE");     /* -X */
  100. $DESCRIPTOR(cli_comment,        "COMMENT");     /* -z */
  101. $DESCRIPTOR(cli_exclude,        "EXCLUDE");     /* -x */
  102.  
  103. $DESCRIPTOR(cli_information,    "ZIPINFO");     /* -Z */
  104. $DESCRIPTOR(cli_short,          "SHORT");       /* -Zs */
  105. $DESCRIPTOR(cli_medium,         "MEDIUM");      /* -Zm */
  106. $DESCRIPTOR(cli_long,           "LONG");        /* -Zl */
  107. $DESCRIPTOR(cli_verbose,        "VERBOSE");     /* -Zv */
  108. $DESCRIPTOR(cli_header,         "HEADER");      /* -Zh */
  109. $DESCRIPTOR(cli_totals,         "TOTALS");      /* -Zt */
  110. $DESCRIPTOR(cli_times,          "TIMES");       /* -ZT */
  111. $DESCRIPTOR(cli_one_line,       "ONE_LINE");    /* -Z2 */
  112.  
  113. $DESCRIPTOR(cli_page,           "PAGE");        /* -M , -ZM */
  114.  
  115. $DESCRIPTOR(cli_yyz,            "YYZ_UNZIP");
  116.  
  117. $DESCRIPTOR(cli_zipfile,        "ZIPFILE");
  118. $DESCRIPTOR(cli_infile,         "INFILE");
  119. $DESCRIPTOR(unzip_command,      "unzip ");
  120. $DESCRIPTOR(blank,              " ");
  121.  
  122. #ifdef __DECC
  123. extern void *vms_unzip_cld;
  124. #else
  125. globalref void *vms_unzip_cld;
  126. #endif
  127.  
  128. /* extern unsigned long LIB$GET_INPUT(void), LIB$SIG_TO_RET(void); */
  129.  
  130. extern unsigned long cli$dcl_parse ();
  131. extern unsigned long cli$present ();
  132. extern unsigned long cli$get_value ();
  133.  
  134. unsigned long vms_unzip_cmdline (int *, char ***);
  135. unsigned long get_list (struct dsc$descriptor_s *, char **,
  136.                         struct dsc$descriptor_d *, char);
  137. unsigned long check_cli (struct dsc$descriptor_s *);
  138.  
  139.  
  140. #ifdef TEST
  141. unsigned long
  142. main(int argc, char **argv)
  143. {
  144.     register status;
  145.     return (vms_unzip_cmdline(&argc, &argv));
  146. }
  147. #endif /* TEST */
  148.  
  149.  
  150. unsigned long
  151. vms_unzip_cmdline (int *argc_p, char ***argv_p)
  152. {
  153. /*
  154. **  Routine:    vms_unzip_cmdline
  155. **
  156. **  Function:
  157. **
  158. **      Parse the DCL command line and create a fake argv array to be
  159. **      handed off to Zip.
  160. **
  161. **      NOTE: the argv[] is built as we go, so all the parameters are
  162. **      checked in the appropriate order!!
  163. **
  164. **  Formal parameters:
  165. **
  166. **      argc_p          - Address of int to receive the new argc
  167. **      argv_p          - Address of char ** to receive the argv address
  168. **
  169. **  Calling sequence:
  170. **
  171. **      status = vms_unzip_cmdline (&argc, &argv);
  172. **
  173. **  Returns:
  174. **
  175. **      SS$_NORMAL      - Success.
  176. **      SS$_INSFMEM     - A malloc() or realloc() failed
  177. **      SS$_ABORT       - Bad time value
  178. **
  179. */
  180.     register status;
  181.     char options[256];
  182.     char *the_cmd_line;
  183.     char *ptr;
  184.     int  x, len, zipinfo, exclude_list;
  185.  
  186.     int new_argc;
  187.     char **new_argv;
  188.  
  189.     struct dsc$descriptor_d work_str;
  190.     struct dsc$descriptor_d foreign_cmdline;
  191.     struct dsc$descriptor_d output_directory;
  192.  
  193.     init_dyndesc (work_str);
  194.     init_dyndesc (foreign_cmdline);
  195.     init_dyndesc (output_directory);
  196.  
  197.     /*
  198.     **  See if the program was invoked by the CLI (SET COMMAND) or by
  199.     **  a foreign command definition.  Check for /YYZ_UNZIP, which is a
  200.     **  valid default qualifier solely for this test.
  201.     */
  202.     status = check_cli (&cli_yyz);
  203.     if (!(status & 1)) {
  204.         lib$get_foreign (&foreign_cmdline);
  205.         /*
  206.         **  If nothing was returned or the first character is a "-", then
  207.         **  assume it's a UNIX-style command and return.
  208.         */
  209.         if ((foreign_cmdline.dsc$w_length == 0) ||
  210.             (*(foreign_cmdline.dsc$a_pointer) == '-'))
  211.             return(SS$_NORMAL);
  212.  
  213.         str$concat (&work_str, &unzip_command, &foreign_cmdline);
  214.         status = cli$dcl_parse(&work_str, &vms_unzip_cld, lib$get_input,
  215.                         lib$get_input, 0);
  216.         if (!(status & 1)) return(status);
  217.     }
  218.  
  219.     /*
  220.     **  There's always going to be a new_argv[] because of the image name.
  221.     */
  222.     if ((the_cmd_line = (char *) malloc (sizeof("unzip")+1)) == NULL)
  223.         return(SS$_INSFMEM);
  224.  
  225.     strcpy (the_cmd_line, "unzip");
  226.  
  227.     /*
  228.     **  First, check to see if any of the regular options were specified.
  229.     */
  230.  
  231.     options[0] = '-';
  232.     ptr = &options[1];          /* Point to temporary buffer */
  233.  
  234.     /*
  235.     **  Is it Zipinfo??
  236.     */
  237.     zipinfo = 0;
  238.     status = cli$present (&cli_information);
  239.     if (status & 1) {
  240.  
  241.         zipinfo = 1;
  242.  
  243.         *ptr++ = 'Z';
  244.  
  245.         if (cli$present(&cli_one_line) & 1)
  246.             *ptr++ = '2';
  247.         if (cli$present(&cli_short) & 1)
  248.             *ptr++ = 's';
  249.         if (cli$present(&cli_medium) & 1)
  250.             *ptr++ = 'm';
  251.         if (cli$present(&cli_long) & 1)
  252.             *ptr++ = 'l';
  253.         if (cli$present(&cli_verbose) & 1)
  254.             *ptr++ = 'v';
  255.         if (cli$present(&cli_header) & 1)
  256.             *ptr++ = 'h';
  257.         if (cli$present(&cli_comment) & 1)
  258.             *ptr++ = 'c';
  259.         if (cli$present(&cli_totals) & 1)
  260.             *ptr++ = 't';
  261.         if (cli$present(&cli_times) & 1)
  262.             *ptr++ = 'T';
  263.  
  264.     }
  265.     else {
  266.  
  267. #if 0
  268.     /*
  269.     **  Extract files?
  270.     */
  271.     status = cli$present (&cli_extract);
  272.     if (status == CLI$_NEGATED)
  273.         *ptr++ = '-';
  274.     if (status != CLI$_ABSENT)
  275.         *ptr++ = 'x';
  276. #endif
  277.  
  278.     /*
  279.     **  Write binary files in VMS binary (fixed lenght 512 byte records,
  280.     **  record attributes: none) format
  281.     **  (auto-convert, or force to convert all files)
  282.     */
  283.     status = cli$present (&cli_binary);
  284.     if (status != CLI$_ABSENT) {
  285.         *ptr++ = '-';
  286.         *ptr++ = '-';
  287.         *ptr++ = 'b';
  288.         if ((status & 1) &&
  289.             !((status = cli$present (&cli_binary_none)) & 1)) {
  290.             *ptr++ = 'b';
  291.             if ((status = cli$present (&cli_binary_all)) & 1)
  292.                 *ptr++ = 'b';
  293.         }
  294.     }
  295.  
  296.     /*
  297.     **  Convert files as text (CR LF -> LF, etc.)
  298.     **  (auto-convert, or force to convert all files)
  299.     */
  300.     status = cli$present (&cli_text);
  301.     if (status != CLI$_ABSENT) {
  302.         *ptr++ = '-';
  303.         *ptr++ = '-';
  304.         *ptr++ = 'a';
  305.         if ((status & 1) &&
  306.             !((status = cli$present (&cli_text_none)) & 1)) {
  307.             *ptr++ = 'a';
  308.             if ((status = cli$present (&cli_text_all)) & 1)
  309.                 *ptr++ = 'a';
  310.         }
  311.     }
  312.  
  313.     /*
  314.     **  Extract files to screen?
  315.     */
  316.     status = cli$present (&cli_screen);
  317.     if (status == CLI$_NEGATED)
  318.         *ptr++ = '-';
  319.     if (status != CLI$_ABSENT)
  320.         *ptr++ = 'c';
  321.  
  322.     /*
  323.     **  Re-create directory structure?  (default)
  324.     */
  325.     status = cli$present (&cli_directory);
  326.     if (status == CLI$_PRESENT) {
  327.         status = cli$get_value (&cli_directory, &output_directory);
  328.     }
  329.  
  330.     /*
  331.     **  Freshen existing files, create none
  332.     */
  333.     status = cli$present (&cli_freshen);
  334.     if (status == CLI$_NEGATED)
  335.         *ptr++ = '-';
  336.     if (status != CLI$_ABSENT)
  337.         *ptr++ = 'f';
  338.  
  339.     /*
  340.     **  Show the help.
  341.     */
  342.     status = cli$present (&cli_help);
  343.     if (status & 1)
  344.         *ptr++ = 'h';
  345.  
  346.     /*
  347.     **  Junk stored directory names on unzip
  348.     */
  349.     status = cli$present (&cli_junk);
  350.     if (status == CLI$_NEGATED)
  351.         *ptr++ = '-';
  352.     if (status != CLI$_ABSENT)
  353.         *ptr++ = 'j';
  354.  
  355.     /*
  356.     **  List contents (/BRIEF or /FULL (default))
  357.     */
  358.     status = cli$present (&cli_list);
  359.     if (status & 1) {
  360.         if (cli$present(&cli_full) & 1)
  361.            *ptr++ = 'v';
  362.         else
  363.            *ptr++ = 'l';
  364.     }
  365.  
  366.     /*
  367.     **  Overwrite files?
  368.     */
  369.     status = cli$present (&cli_overwrite);
  370.     if (status == CLI$_NEGATED)
  371.         *ptr++ = 'n';
  372.     else if (status != CLI$_ABSENT)
  373.         *ptr++ = 'o';
  374.  
  375.     /*
  376.     **  Pipe files to SYS$OUTPUT with no informationals?
  377.     */
  378.     status = cli$present (&cli_pipe);
  379.     if (status != CLI$_ABSENT)
  380.         *ptr++ = 'p';
  381.  
  382.     /*
  383.     **  Quiet
  384.     */
  385.     status = cli$present (&cli_quiet);
  386.     if (status & 1) {
  387.         *ptr++ = 'q';
  388.         if ((status = cli$present (&cli_super_quiet)) & 1)
  389.             *ptr++ = 'q';
  390.     }
  391.  
  392.     /*
  393.     **  Test archive integrity
  394.     */
  395.     status = cli$present (&cli_test);
  396.     if (status == CLI$_NEGATED)
  397.         *ptr++ = '-';
  398.     if (status != CLI$_ABSENT)
  399.         *ptr++ = 't';
  400.  
  401.     /*
  402.     **  Match filenames case-insensitively (-C)
  403.     */
  404.     status = cli$present (&cli_case_insensitive);
  405.     if (status == CLI$_NEGATED)
  406.         *ptr++ = '-';
  407.     if (status != CLI$_ABSENT)
  408.         *ptr++ = 'C';
  409.  
  410.     /*
  411.     **  Make (some) names lowercase
  412.     */
  413.     status = cli$present (&cli_lowercase);
  414.     if (status == CLI$_NEGATED)
  415.         *ptr++ = '-';
  416.     if (status != CLI$_ABSENT)
  417.         *ptr++ = 'L';
  418.  
  419.     /*
  420.     **  Uppercase (don't convert to lower)
  421.     */
  422.     status = cli$present (&cli_uppercase);
  423.     if (status == CLI$_NEGATED)
  424.         *ptr++ = '-';
  425.     if (status != CLI$_ABSENT)
  426.         *ptr++ = 'U';
  427.  
  428.     /*
  429.     **  Update (extract only new and newer files)
  430.     */
  431.     status = cli$present (&cli_update);
  432.     if (status == CLI$_NEGATED)
  433.         *ptr++ = '-';
  434.     if (status != CLI$_ABSENT)
  435.         *ptr++ = 'u';
  436.  
  437.     /*
  438.     **  Version (retain VMS/DEC-20 file versions)
  439.     */
  440.     status = cli$present (&cli_version);
  441.     if (status == CLI$_NEGATED)
  442.         *ptr++ = '-';
  443.     if (status != CLI$_ABSENT)
  444.         *ptr++ = 'V';
  445.  
  446.     /*
  447.     **  Restore owner/protection info
  448.     */
  449.     status = cli$present (&cli_restore);
  450.     if (status == CLI$_NEGATED)
  451.         *ptr++ = '-';
  452.     if (status != CLI$_ABSENT)
  453.         *ptr++ = 'X';
  454.  
  455.     /*
  456.     **  Display only the archive comment
  457.     */
  458.     status = cli$present (&cli_comment);
  459.     if (status == CLI$_NEGATED)
  460.         *ptr++ = '-';
  461.     if (status != CLI$_ABSENT)
  462.         *ptr++ = 'z';
  463.  
  464.     }   /* Zipinfo check way up there.... */
  465.  
  466.     /* The following options are common to both Unzip and Zipinfo mode. */
  467.  
  468.     /*
  469.     **  Use builtin pager for all screen output
  470.     */
  471.     status = cli$present (&cli_page);
  472.     if (status == CLI$_NEGATED)
  473.         *ptr++ = '-';
  474.     if (status != CLI$_ABSENT)
  475.         *ptr++ = 'M';
  476.  
  477.     /*
  478.     **  Check existence of a list of files to exclude, fetch is done later.
  479.     */
  480.     status = cli$present (&cli_exclude);
  481.     exclude_list = ((status & 1) != 0);
  482.  
  483.     /*
  484.     **  If the user didn't give any DCL qualifier, assume he wants the
  485.     **  Un*x interface.
  486.     if ( (ptr == &options[1]) &&
  487.          (output_directory.dsc$w_length == 0) &&
  488.          (!exclude_list)  )
  489.       return(SS$_NORMAL);
  490.     */
  491.  
  492.     /*
  493.     **  Now copy the final options string to the_cmd_line.
  494.     */
  495.     x = ptr - &options[0];
  496.     if (x > 1) {
  497.         options[x] = '\0';
  498.         len = strlen(the_cmd_line) + x + 2;
  499.         if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
  500.             return(SS$_INSFMEM);
  501.         strcat (the_cmd_line, " ");
  502.         strcat (the_cmd_line, options);
  503.     }
  504.  
  505.     /*
  506.     **  Now get the specified zip file name.
  507.     */
  508.     status = cli$present (&cli_zipfile);
  509.     if (status & 1) {
  510.         status = cli$get_value (&cli_zipfile, &work_str);
  511.  
  512.         len = strlen(the_cmd_line) + work_str.dsc$w_length + 2;
  513.         if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
  514.             return(SS$_INSFMEM);
  515.         strcat (the_cmd_line, " ");
  516.         x = strlen(the_cmd_line);
  517.         strncpy(&the_cmd_line[x], work_str.dsc$a_pointer,
  518.                 work_str.dsc$w_length);
  519.         the_cmd_line[len] = '\0';
  520.  
  521.     }
  522.  
  523.     /*
  524.     **  Get the output directory, for UnZip.
  525.     **/
  526.     if (output_directory.dsc$w_length != 0) {
  527.         len = strlen(the_cmd_line) + output_directory.dsc$w_length + 5;
  528.         if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
  529.             return(SS$_INSFMEM);
  530.         strcat (the_cmd_line, " -d ");
  531.         x = strlen(the_cmd_line);
  532.         strncpy(&the_cmd_line[x], output_directory.dsc$a_pointer,
  533.                 output_directory.dsc$w_length);
  534.         the_cmd_line[len] = '\0';
  535.     }
  536.  
  537.     /*
  538.     **  Run through the list of files to unzip.
  539.     */
  540.     status = cli$present (&cli_infile);
  541.     if (status & 1) {
  542.         len = strlen(the_cmd_line) + 2;
  543.         if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
  544.             return(SS$_INSFMEM);
  545.         strcat (the_cmd_line, " ");
  546.         status = get_list (&cli_infile, &the_cmd_line, &foreign_cmdline, ' ');
  547.         if (!(status & 1)) return (status);
  548.     }
  549.  
  550.     /*
  551.     **  Get the list of files to exclude, if there are any.
  552.     */
  553.     if (exclude_list) {
  554.         len = strlen(the_cmd_line) + 5;
  555.         if ((the_cmd_line = (char *) realloc (the_cmd_line, len)) == NULL)
  556.             return(SS$_INSFMEM);
  557.         strcat (the_cmd_line, " -x ");
  558.         status = get_list (&cli_exclude, &the_cmd_line, &foreign_cmdline, ' ');
  559.         if (!(status & 1)) return (status);
  560.     }
  561.  
  562.     /*
  563.     **  Now that we've built our new UNIX-like command line, count the
  564.     **  number of args and build an argv array.
  565.     */
  566.  
  567. #if defined(TEST) || defined(DEBUG)
  568.     printf("%s\n",the_cmd_line);
  569. #endif /* TEST || DEBUG */
  570.  
  571.     new_argc = 1;
  572.     for (ptr = the_cmd_line;
  573.          (ptr = strchr(ptr,' ')) != NULL;
  574.          ptr++, new_argc++);
  575.  
  576.     /*
  577.     **  Allocate memory for the new argv[].  The last element of argv[]
  578.     **  is supposed to be NULL, so allocate enough for new_argc+1.
  579.     */
  580.     if ((new_argv = (char **) calloc (new_argc+1, sizeof(char *))) == NULL)
  581.         return(SS$_INSFMEM);
  582.  
  583.     /*
  584.     **  For each option, store the address in new_argv[] and convert the
  585.     **  separating blanks to nulls so each argv[] string is terminated.
  586.     */
  587.     for (ptr = the_cmd_line, x = 0; x < new_argc; x++) {
  588.         new_argv[x] = ptr;
  589.         if ((ptr = strchr (ptr, ' ')) != NULL)
  590.             *ptr++ = '\0';
  591.     }
  592.     new_argv[new_argc] = NULL;
  593.  
  594. #if defined(TEST) || defined(DEBUG)
  595.     printf("new_argc    = %d\n", new_argc);
  596.     for (x = 0; x < new_argc; x++)
  597.         printf("new_argv[%d] = %s\n", x, new_argv[x]);
  598. #endif /* TEST || DEBUG */
  599.  
  600.     /*
  601.     **  All finished.  Return the new argc and argv[] addresses to Zip.
  602.     */
  603.     *argc_p = new_argc;
  604.     *argv_p = new_argv;
  605.  
  606.     return(SS$_NORMAL);
  607. }
  608.  
  609.  
  610.  
  611. unsigned long
  612. get_list (struct dsc$descriptor_s *qual, char **str,
  613.           struct dsc$descriptor_d *cmdline, char c)
  614. {
  615. /*
  616. **  Routine:    get_list
  617. **
  618. **  Function:   This routine runs through a comma-separated CLI list
  619. **              and copies the strings to the command line.  The
  620. **              specified separation character is used to separate
  621. **              the strings on the command line.
  622. **
  623. **              All unquoted strings are converted to lower-case.
  624. **
  625. **  Formal parameters:
  626. **
  627. **      qual    - Address of descriptor for the qualifier name
  628. **      str     - Address of pointer pointing to string (command line)
  629. **      cmdline - Address of descriptor for the full command line tail
  630. **      c       - Character to use to separate the list items
  631. **
  632. */
  633.  
  634.     register status;
  635.     struct dsc$descriptor_d work_str;
  636.  
  637.     init_dyndesc(work_str);
  638.  
  639.     status = cli$present (qual);
  640.     if (status & 1) {
  641.  
  642.         unsigned long len, old_len, lower_it, ind, sind;
  643.  
  644.         len = strlen(*str);
  645.         while ((status = cli$get_value (qual, &work_str)) & 1) {
  646.             /*
  647.             **  Just in case the string doesn't exist yet, though it does.
  648.             */
  649.             if (*str == NULL) {
  650.                 len = work_str.dsc$w_length + 1;
  651.                 if ((*str = (char *) malloc (work_str.dsc$w_length)) == NULL)
  652.                     return(SS$_INSFMEM);
  653.                 strncpy(*str,work_str.dsc$a_pointer,len);
  654.             } else {
  655.                 char *src, *dst; int x;
  656.                 old_len = len;
  657.                 len += work_str.dsc$w_length + 1;
  658.                 if ((*str = (char *) realloc (*str, len)) == NULL)
  659.                     return(SS$_INSFMEM);
  660.  
  661.                 /*
  662.                 **  Look for the filename in the original foreign command
  663.                 **  line to see if it was originally quoted.  If so, then
  664.                 **  don't convert it to lowercase.
  665.                 */
  666.                 lower_it = 0;
  667.                 str$find_first_substring (cmdline, &ind, &sind, &work_str);
  668.                 if (*(cmdline->dsc$a_pointer + ind - 2) == '"')
  669.                     lower_it = 1;
  670.  
  671.                 /*
  672.                 **  Copy the string to the buffer, converting to lowercase.
  673.                 */
  674.                 src = work_str.dsc$a_pointer;
  675.                 dst = *str+old_len;
  676.                 for (x = 0; x < work_str.dsc$w_length; x++) {
  677.                     if (!lower_it && ((*src >= 'A') && (*src <= 'Z')))
  678.                         *dst++ = *src++ + 32;
  679.                     else
  680.                         *dst++ = *src++;
  681.                 }
  682.             }
  683.             if (status == CLI$_COMMA)
  684.                 (*str)[len-1] = c;
  685.             else
  686.                 (*str)[len-1] = '\0';
  687.         }
  688.     }
  689.  
  690.     return (SS$_NORMAL);
  691.  
  692. }
  693.  
  694.  
  695. unsigned long
  696. check_cli (struct dsc$descriptor_s *qual)
  697. {
  698. /*
  699. **  Routine:    check_cli
  700. **
  701. **  Function:   Check to see if a CLD was used to invoke the program.
  702. **
  703. **  Formal parameters:
  704. **
  705. **      qual    - Address of descriptor for qualifier name to check.
  706. **
  707. */
  708.     lib$establish(lib$sig_to_ret);      /* Establish condition handler */
  709.     return (cli$present(qual));         /* Just see if something was given */
  710. }
  711.  
  712.  
  713. #ifndef SFX
  714.  
  715. int usage(__GPRO__ int error)  /* VMSCLI version; returns PK-type error code */
  716. {
  717.     extern char UnzipUsageLine1[];
  718.  
  719. /*---------------------------------------------------------------------------
  720.     If user requested usage, send it to stdout; else send to stderr.
  721.   ---------------------------------------------------------------------------*/
  722.  
  723.     int flag = (error? 1 : 0);
  724.  
  725.  
  726. /*---------------------------------------------------------------------------
  727.     Print either ZipInfo usage or UnZip usage, depending on incantation.
  728.   ---------------------------------------------------------------------------*/
  729.  
  730.     if (G.zipinfo_mode) {
  731.  
  732. #ifndef NO_ZIPINFO
  733.  
  734.         Info(slide, flag, ((char *)slide, "\
  735. ZipInfo %d.%d%d%s %s, by Newtware and the fine folks at Info-ZIP.\n\n\
  736. List name, date/time, attribute, size, compression method, etc., about files\n\
  737. in list (excluding those in xlist) contained in the specified .zip archive(s).\
  738. \n\"file[.zip]\" may be a wildcard name containing * or % (e.g., \"*font-%.zip\
  739. \").\n", ZI_MAJORVER, ZI_MINORVER, PATCHLEVEL, BETALEVEL, VERSION_DATE));
  740.  
  741.         Info(slide, flag, ((char *)slide, "\
  742.    usage:  zipinfo file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options\n\
  743.    or:  unzip /ZIPINFO file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options\
  744. \n\nmain\
  745.  listing-format options:              /SHORT   short \"ls -l\" format (def.)\n\
  746.   /ONE_LINE  just filenames, one/line     /MEDIUM  medium Unix \"ls -l\" format\n\
  747.   /VERBOSE   verbose, multi-page format   /LONG    long Unix \"ls -l\" format\n\
  748.         "));
  749.  
  750.         Info(slide, flag, ((char *)slide, "\
  751. miscellaneous options:\n  \
  752. /HEADER   print header line       /TOTALS  totals for listed files or for all\n\
  753.   /COMMENT  print zipfile comment   /TIMES   times in sortable decimal format\n\
  754.   /[NO]PAGE page output through built-in \"more\"\n\
  755.   /EXCLUDE=(file-spec1,etc.)  exclude file-specs from listing\n"));
  756.  
  757.         Info(slide, flag, ((char *)slide, "\n\
  758. Remember that non-lowercase filespecs must be\
  759.  quoted in VMS (e.g., \"Makefile\").\n"));
  760.  
  761. #endif /* !NO_ZIPINFO */
  762.  
  763.     } else {   /* UnZip mode */
  764.  
  765.         Info(slide, flag, ((char *)slide, UnzipUsageLine1,
  766.           UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL, VERSION_DATE));
  767.  
  768. #ifdef BETA
  769.         Info(slide, flag, ((char *)slide, "\
  770.       THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n",
  771.           "", ""));
  772. #endif
  773.  
  774.         Info(slide, flag, ((char *)slide, "\
  775. Usage: unzip file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options /modifiers\
  776. \n  Default action is to extract files in list, except those in xlist, to exdir\
  777. ;\n  file[.zip] may be a wildcard.  %s\n\n",
  778. #ifdef NO_ZIPINFO
  779.           "(ZipInfo mode is disabled in this version.)"
  780. #else
  781.           "Type \"unzip /ZIPINFO\" for ZipInfo-mode usage."
  782. #endif
  783.           ));
  784.  
  785.         Info(slide, flag, ((char *)slide, "\
  786. Major options include:\n\
  787.    /[NO]TEST, /LIST, /[NO]SCREEN, /PIPE, /[NO]FRESHEN, /[NO]UPDATE,\n\
  788.    /[NO]COMMENT, /DIRECTORY=directory-spec, /EXCLUDE=(file-spec1,etc.)\n\n\
  789. Modifiers include:\n\
  790.    /BRIEF, /FULL, /[NO]TEXT[=NONE|AUTO|ALL], /[NO]BINARY[=NONE|AUTO|ALL],\n\
  791.    /[NO]OVERWRITE, /[NO]JUNK, /QUIET, /QUIET[=SUPER], /[NO]PAGE,\n\
  792.    /[NO]CASE_INSENSITIVE, /[NO]LOWERCASE, /[NO]VERSION, /[NO]RESTORE\n\n"));
  793.  
  794.         Info(slide, flag, ((char *)slide, "\
  795. Examples (see unzip.doc or \"HELP UNZIP\" for more info):\n   \
  796. unzip edit1 /EXCL=joe.jou /CASE_INSENSITIVE    => extract all files except\n   \
  797.    joe.jou (or JOE.JOU, or any combination of case) from zipfile edit1.zip\n   \
  798. unzip zip201 \"Makefile.VMS\" vms/*.[ch]         => extract VMS Makefile and\n\
  799.       *.c and *.h files; must quote uppercase names if /CASE_INSENS not used\n\
  800.    unzip foo /DIR=tmp:[.test] /JUNK /AUTO /OVER   => extract all files to temp.\
  801. \n      directory without paths, auto-converting text files and overwriting\
  802. \n"));
  803.  
  804.     } /* end if (zipinfo_mode) */
  805.  
  806.     if (error)
  807.         return PK_PARAM;
  808.     else
  809.         return PK_COOL;     /* just wanted usage screen: no error */
  810.  
  811. } /* end function usage() */
  812.  
  813. #endif /* !SFX */
  814.