1 /*
2 Copyright (c) 1990-2007 Info-ZIP. All rights reserved.
3
4 See the accompanying file LICENSE, version 2007-Mar-4 or later
5 (the contents of which are also included in zip.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 /*
11 Test procedure:
12
13 Compile and link (in [.VMS] directory):
14
15 define vms SYS$DISK:[]
16 set command /object ZIP_CLI.CLD
17 cc /define = (TEST, VMSCLI) /include = [-] CMDLINE
18 link link CMDLINE.OBJ, ZIP_CLI.OBJ
19
20 Run:
21
22 exec*ute == "$SYS$DISK:[]'"
23 exec cmdline [options ...]
24
25 */
26
27 /* 2004-12-13 SMS.
28 * Disabled the module name macro to accommodate old GNU C which didn't
29 * obey the directive, and thus confused MMS/MMK where the object
30 * library dependencies need to have the correct module name.
31 */
32 #if 0
33 # define module_name VMS_ZIP_CMDLINE
34 # define module_ident "02-006"
35 #endif /* 0 */
36
37 /*
38 **
39 ** Facility: ZIP
40 **
41 ** Module: VMS_ZIP_CMDLINE
42 **
43 ** Author: Hunter Goatley <goathunter@MadGoat.com>
44 **
45 ** Date: July 30, 1993
46 **
47 ** Abstract: Routines to handle a VMS CLI interface for Zip. The CLI
48 ** command line is parsed and a new argc/argv are built and
49 ** returned to Zip.
50 **
51 ** Modified by:
52 **
53 ** 02-007 Steven Schweda 09-FEB-2005
54 ** Added /PRESERVE_CASE.
55 ** 02-006 Onno van der Linden,
56 ** Christian Spieler 07-JUL-1998 23:03
57 ** Support GNU CC 2.8 on Alpha AXP (vers-num unchanged).
58 ** 02-006 Johnny Lee 25-JUN-1998 07:40
59 ** Fixed typo (superfluous ';') (vers-num unchanged).
60 ** 02-006 Christian Spieler 12-SEP-1997 23:17
61 ** Fixed bugs in /BEFORE and /SINCE handlers (vers-num unchanged).
62 ** 02-006 Christian Spieler 12-JUL-1997 02:05
63 ** Complete revision of the argv strings construction.
64 ** Added handling of "-P pwd", "-R", "-i@file", "-x@file" options.
65 ** 02-005 Patrick Ellis 09-MAY-1996 22:25
66 ** Show UNIX style help screen when UNIX style options are used.
67 ** 02-004 Onno van der Linden,
68 ** Christian Spieler 13-APR-1996 20:05
69 ** Removed /ENCRYPT=VERIFY ("-ee" option).
70 ** 02-003 Christian Spieler 11-FEB-1996 23:05
71 ** Added handling of /EXTRAFIELDS qualifier ("-X" option).
72 ** 02-002 Christian Spieler 09-JAN-1996 22:25
73 ** Added "#include crypt.h", corrected typo.
74 ** 02-001 Christian Spieler 04-DEC-1995 16:00
75 ** Fixed compilation in DEC CC's ANSI mode.
76 ** 02-000 Christian Spieler 10-OCT-1995 17:54
77 ** Modified for Zip v2.1, added several new options.
78 ** 01-000 Hunter Goatley 30-JUL-1993 07:54
79 ** Original version (for Zip v1.9p1).
80 **
81 */
82
83
84 /* 2004-12-13 SMS.
85 * Disabled the module name macro to accommodate old GNU C which didn't
86 * obey the directive, and thus confused MMS/MMK where the object
87 * library dependencies need to have the correct module name.
88 */
89 #if 0
90 # if defined(__DECC) || defined(__GNUC__)
91 # pragma module module_name module_ident
92 # else
93 # module module_name module_ident
94 # endif
95 #endif /* 0 */
96
97 /* Accomodation for /NAMES = AS_IS with old header files. */
98
99 #define lib$establish LIB$ESTABLISH
100 #define lib$get_foreign LIB$GET_FOREIGN
101 #define lib$get_input LIB$GET_INPUT
102 #define lib$sig_to_ret LIB$SIG_TO_RET
103 #define ots$cvt_tu_l OTS$CVT_TU_L
104 #define str$concat STR$CONCAT
105 #define str$find_first_substring STR$FIND_FIRST_SUBSTRING
106 #define str$free1_dx STR$FREE1_DX
107
108 #include "zip.h"
109 #ifndef TEST
110 #include "crypt.h" /* for VMSCLI_help() */
111 #include "revision.h" /* for VMSCLI_help() */
112 #endif /* !TEST */
113
114 #include <ssdef.h>
115 #include <descrip.h>
116 #include <climsgdef.h>
117 #include <clidef.h>
118 #include <lib$routines.h>
119 #include <ots$routines.h>
120 #include <str$routines.h>
121
122 #ifndef CLI$_COMMA
123 globalvalue CLI$_COMMA;
124 #endif
125
126 /*
127 ** "Macro" to initialize a dynamic string descriptor.
128 */
129 #define init_dyndesc(dsc) {\
130 dsc.dsc$w_length = 0;\
131 dsc.dsc$b_dtype = DSC$K_DTYPE_T;\
132 dsc.dsc$b_class = DSC$K_CLASS_D;\
133 dsc.dsc$a_pointer = NULL;}
134
135 /*
136 ** Memory allocation step for argv string buffer.
137 */
138 #define ARGBSIZE_UNIT 256
139
140 /*
141 ** Memory reallocation macro for argv string buffer.
142 */
143 #define CHECK_BUFFER_ALLOCATION(buf, reserved, requested) { \
144 if ((requested) > (reserved)) { \
145 char *save_buf = (buf); \
146 (reserved) += ARGBSIZE_UNIT; \
147 if (((buf) = (char *) realloc((buf), (reserved))) == NULL) { \
148 if (save_buf != NULL) free(save_buf); \
149 return (SS$_INSFMEM); \
150 } \
151 } \
152 }
153
154 /*
155 ** Define descriptors for all of the CLI parameters and qualifiers.
156 */
157 $DESCRIPTOR(cli_delete, "DELETE"); /* -d */
158 $DESCRIPTOR(cli_freshen, "FRESHEN"); /* -f */
159 $DESCRIPTOR(cli_move, "MOVE"); /* -m */
160 $DESCRIPTOR(cli_update, "UPDATE"); /* -u */
161 $DESCRIPTOR(cli_exclude, "EXCLUDE"); /* -x */
162 $DESCRIPTOR(cli_include, "INCLUDE"); /* -i */
163 $DESCRIPTOR(cli_exlist, "EXLIST"); /* -x@ */
164 $DESCRIPTOR(cli_inlist, "INLIST"); /* -i@ */
165 $DESCRIPTOR(cli_adjust, "ADJUST_OFFSETS"); /* -A */
166 $DESCRIPTOR(cli_append, "APPEND"); /* -g */
167 $DESCRIPTOR(cli_batch, "BATCH"); /* -@ */
168 $DESCRIPTOR(cli_before, "BEFORE"); /* -tt */
169 $DESCRIPTOR(cli_comments, "COMMENTS"); /* -c,-z */
170 $DESCRIPTOR(cli_comment_archive,"COMMENTS.ARCHIVE"); /* -z */
171 $DESCRIPTOR(cli_comment_zipfile,"COMMENTS.ZIP_FILE"); /* -z */
172 $DESCRIPTOR(cli_comment_files, "COMMENTS.FILES"); /* -c */
173 $DESCRIPTOR(cli_compression, "COMPRESSION"); /* -Z */
174 $DESCRIPTOR(cli_compression_b, "COMPRESSION.BZIP2"); /* -Zb */
175 $DESCRIPTOR(cli_compression_d, "COMPRESSION.DEFLATE"); /* -Zd */
176 $DESCRIPTOR(cli_compression_s, "COMPRESSION.STORE"); /* -Zs */
177 $DESCRIPTOR(cli_copy_entries, "COPY_ENTRIES"); /* -U */
178 $DESCRIPTOR(cli_descriptors, "DESCRIPTORS"); /* -fd */
179 $DESCRIPTOR(cli_difference, "DIFFERENCE"); /* -DF */
180 $DESCRIPTOR(cli_dirnames, "DIRNAMES"); /* -D */
181 $DESCRIPTOR(cli_display, "DISPLAY"); /* -d? */
182 $DESCRIPTOR(cli_display_bytes, "DISPLAY.BYTES"); /* -db */
183 $DESCRIPTOR(cli_display_counts, "DISPLAY.COUNTS"); /* -dc */
184 $DESCRIPTOR(cli_display_dots, "DISPLAY.DOTS"); /* -dd,-ds */
185 $DESCRIPTOR(cli_display_globaldots, "DISPLAY.GLOBALDOTS"); /* -dg */
186 $DESCRIPTOR(cli_display_usize, "DISPLAY.USIZE"); /* -du */
187 $DESCRIPTOR(cli_display_volume, "DISPLAY.VOLUME"); /* -dv */
188 $DESCRIPTOR(cli_dot_version, "DOT_VERSION"); /* -ww */
189 $DESCRIPTOR(cli_encrypt, "ENCRYPT"); /* -e,-P */
190 $DESCRIPTOR(cli_extra_fields, "EXTRA_FIELDS"); /* -X [/NO] */
191 $DESCRIPTOR(cli_extra_fields_normal, "EXTRA_FIELDS.NORMAL"); /* no -X */
192 $DESCRIPTOR(cli_extra_fields_keep, "EXTRA_FIELDS.KEEP_EXISTING"); /* -X- */
193 $DESCRIPTOR(cli_filesync, "FILESYNC"); /* -FS */
194 $DESCRIPTOR(cli_fix_archive, "FIX_ARCHIVE"); /* -F[F] */
195 $DESCRIPTOR(cli_fix_normal, "FIX_ARCHIVE.NORMAL"); /* -F */
196 $DESCRIPTOR(cli_fix_full, "FIX_ARCHIVE.FULL"); /* -FF */
197 $DESCRIPTOR(cli_full_path, "FULL_PATH"); /* -p */
198 $DESCRIPTOR(cli_grow, "GROW"); /* -g */
199 $DESCRIPTOR(cli_help, "HELP"); /* -h */
200 $DESCRIPTOR(cli_help_normal, "HELP.NORMAL"); /* -h */
201 $DESCRIPTOR(cli_help_extended, "HELP.EXTENDED"); /* -h2 */
202 $DESCRIPTOR(cli_junk, "JUNK"); /* -j */
203 $DESCRIPTOR(cli_keep_version, "KEEP_VERSION"); /* -w */
204 $DESCRIPTOR(cli_latest, "LATEST"); /* -o */
205 $DESCRIPTOR(cli_level, "LEVEL"); /* -[0-9] */
206 $DESCRIPTOR(cli_license, "LICENSE"); /* -L */
207 $DESCRIPTOR(cli_log_file, "LOG_FILE"); /* -la,-lf,-li */
208 $DESCRIPTOR(cli_log_file_append, "LOG_FILE.APPEND"); /* -la */
209 $DESCRIPTOR(cli_log_file_file, "LOG_FILE.FILE"); /* -lf */
210 $DESCRIPTOR(cli_log_file_info, "LOG_FILE.INFORMATIONAL"); /* -li */
211 $DESCRIPTOR(cli_must_match, "MUST_MATCH"); /* -MM */
212 $DESCRIPTOR(cli_output, "OUTPUT"); /* -O */
213 $DESCRIPTOR(cli_patt_case, "PATTERN_CASE"); /* -ic[-] */
214 $DESCRIPTOR(cli_patt_case_blind, "PATTERN_CASE.BLIND"); /* -ic */
215 $DESCRIPTOR(cli_patt_case_sensitive, "PATTERN_CASE.SENSITIVE"); /* -ic- */
216 $DESCRIPTOR(cli_pkzip, "PKZIP"); /* -k */
217 $DESCRIPTOR(cli_pres_case, "PRESERVE_CASE"); /* -C */
218 $DESCRIPTOR(cli_pres_case_no2, "PRESERVE_CASE.NOODS2");/* -C2- */
219 $DESCRIPTOR(cli_pres_case_no5, "PRESERVE_CASE.NOODS5");/* -C5- */
220 $DESCRIPTOR(cli_pres_case_ods2, "PRESERVE_CASE.ODS2"); /* -C2 */
221 $DESCRIPTOR(cli_pres_case_ods5, "PRESERVE_CASE.ODS5"); /* -C5 */
222 $DESCRIPTOR(cli_quiet, "QUIET"); /* -q */
223 $DESCRIPTOR(cli_recurse, "RECURSE"); /* -r,-R */
224 $DESCRIPTOR(cli_recurse_path, "RECURSE.PATH"); /* -r */
225 $DESCRIPTOR(cli_recurse_fnames, "RECURSE.FILENAMES"); /* -R */
226 $DESCRIPTOR(cli_show, "SHOW"); /* -s? */
227 $DESCRIPTOR(cli_show_command, "SHOW.COMMAND"); /* -sc */
228 $DESCRIPTOR(cli_show_debug, "SHOW.DEBUG"); /* -sd */
229 $DESCRIPTOR(cli_show_files, "SHOW.FILES"); /* -sf */
230 $DESCRIPTOR(cli_show_options, "SHOW.OPTIONS"); /* -so */
231 $DESCRIPTOR(cli_since, "SINCE"); /* -t */
232 $DESCRIPTOR(cli_split, "SPLIT"); /* -s,-sb,-sp,-sv */
233 $DESCRIPTOR(cli_split_bell, "SPLIT.BELL"); /* -sb */
234 $DESCRIPTOR(cli_split_pause, "SPLIT.PAUSE"); /* -sp */
235 $DESCRIPTOR(cli_split_size, "SPLIT.SIZE"); /* -s */
236 $DESCRIPTOR(cli_split_verbose, "SPLIT.VERBOSE"); /* -sv */
237 $DESCRIPTOR(cli_store_types, "STORE_TYPES"); /* -n */
238 $DESCRIPTOR(cli_sverbose, "SVERBOSE"); /* -sv */
239 $DESCRIPTOR(cli_symlinks, "SYMLINKS"); /* -y */
240 $DESCRIPTOR(cli_temp_path, "TEMP_PATH"); /* -b */
241 $DESCRIPTOR(cli_test, "TEST"); /* -T */
242 $DESCRIPTOR(cli_test_unzip, "TEST.UNZIP"); /* -TT */
243 $DESCRIPTOR(cli_translate_eol, "TRANSLATE_EOL"); /* -l[l] */
244 $DESCRIPTOR(cli_transl_eol_lf, "TRANSLATE_EOL.LF"); /* -l */
245 $DESCRIPTOR(cli_transl_eol_crlf,"TRANSLATE_EOL.CRLF"); /* -ll */
246 $DESCRIPTOR(cli_unsfx, "UNSFX"); /* -J */
247 $DESCRIPTOR(cli_verbose, "VERBOSE"); /* -v (?) */
248 $DESCRIPTOR(cli_verbose_normal, "VERBOSE.NORMAL"); /* -v */
249 $DESCRIPTOR(cli_verbose_more, "VERBOSE.MORE"); /* -vv */
250 $DESCRIPTOR(cli_verbose_debug, "VERBOSE.DEBUG"); /* -vvv */
251 $DESCRIPTOR(cli_verbose_command,"VERBOSE.COMMAND"); /* (none) */
252 $DESCRIPTOR(cli_vms, "VMS"); /* -V */
253 $DESCRIPTOR(cli_vms_all, "VMS.ALL"); /* -VV */
254 $DESCRIPTOR(cli_wildcard, "WILDCARD"); /* -nw */
255 $DESCRIPTOR(cli_wildcard_nospan,"WILDCARD.NOSPAN"); /* -W */
256
257 $DESCRIPTOR(cli_yyz, "YYZ_ZIP");
258
259 $DESCRIPTOR(cli_zip64, "ZIP64"); /* -fz */
260 $DESCRIPTOR(cli_zipfile, "ZIPFILE");
261 $DESCRIPTOR(cli_infile, "INFILE");
262 $DESCRIPTOR(zip_command, "zip ");
263
264 static int show_VMSCLI_help;
265
266 #if !defined(zip_clitable)
267 # define zip_clitable ZIP_CLITABLE
268 #endif
269 #if defined(__DECC) || defined(__GNUC__)
270 extern void *zip_clitable;
271 #else
272 globalref void *zip_clitable;
273 #endif
274
275 /* extern unsigned long LIB$GET_INPUT(void), LIB$SIG_TO_RET(void); */
276
277 #ifndef __STARLET_LOADED
278 #ifndef sys$bintim
279 # define sys$bintim SYS$BINTIM
280 #endif
281 #ifndef sys$numtim
282 # define sys$numtim SYS$NUMTIM
283 #endif
284 extern int sys$bintim ();
285 extern int sys$numtim ();
286 #endif /* !__STARLET_LOADED */
287 #ifndef cli$dcl_parse
288 # define cli$dcl_parse CLI$DCL_PARSE
289 #endif
290 #ifndef cli$present
291 # define cli$present CLI$PRESENT
292 #endif
293 #ifndef cli$get_value
294 # define cli$get_value CLI$GET_VALUE
295 #endif
296 extern unsigned long cli$dcl_parse ();
297 extern unsigned long cli$present ();
298 extern unsigned long cli$get_value ();
299
300 unsigned long vms_zip_cmdline (int *, char ***);
301 static unsigned long get_list (struct dsc$descriptor_s *,
302 struct dsc$descriptor_d *, int,
303 char **, unsigned long *, unsigned long *);
304 static unsigned long get_time (struct dsc$descriptor_s *qual, char *timearg);
305 static unsigned long check_cli (struct dsc$descriptor_s *);
306 static int verbose_command = 0;
307
308
309 #ifdef TEST
310
311 char errbuf[ FNMAX+ 81]; /* Error message buffer. */
312
ziperr(int c,char * h)313 void ziperr( int c, char *h) /* Error message display function. */
314 {
315 /* int c: error code from the ZE_ class */
316 /* char *h: message about how it happened */
317
318 printf( "%d: %s\n", c, h);
319 }
320
321 int
main(int argc,char ** argv)322 main(int argc, char **argv) /* Main program. */
323 {
324 return (vms_zip_cmdline(&argc, &argv));
325 }
326
327 #endif /* def TEST */
328
329
330 unsigned long
vms_zip_cmdline(int * argc_p,char *** argv_p)331 vms_zip_cmdline (int *argc_p, char ***argv_p)
332 {
333 /*
334 ** Routine: vms_zip_cmdline
335 **
336 ** Function:
337 **
338 ** Parse the DCL command line and create a fake argv array to be
339 ** handed off to Zip.
340 **
341 ** NOTE: the argv[] is built as we go, so all the parameters are
342 ** checked in the appropriate order!!
343 **
344 ** Formal parameters:
345 **
346 ** argc_p - Address of int to receive the new argc
347 ** argv_p - Address of char ** to receive the argv address
348 **
349 ** Calling sequence:
350 **
351 ** status = vms_zip_cmdline (&argc, &argv);
352 **
353 ** Returns:
354 **
355 ** SS$_NORMAL - Success.
356 ** SS$_INSFMEM - A malloc() or realloc() failed
357 ** SS$_ABORT - Bad time value
358 **
359 */
360 register unsigned long status;
361 char options[ 64];
362 char *the_cmd_line; /* buffer for argv strings */
363 unsigned long cmdl_size; /* allocated size of buffer */
364 unsigned long cmdl_len; /* used size of buffer */
365 char *ptr;
366 int x, len;
367
368 int new_argc;
369 char **new_argv;
370
371 struct dsc$descriptor_d work_str;
372 struct dsc$descriptor_d foreign_cmdline;
373
374 init_dyndesc(work_str);
375 init_dyndesc(foreign_cmdline);
376
377 /*
378 ** See if the program was invoked by the CLI (SET COMMAND) or by
379 ** a foreign command definition. Check for /YYZ_ZIP, which is a
380 ** valid default qualifier solely for this test.
381 */
382 show_VMSCLI_help = TRUE;
383 status = check_cli(&cli_yyz);
384 if (!(status & 1)) {
385 lib$get_foreign(&foreign_cmdline);
386 /*
387 ** If nothing was returned or the first character is a "-", then
388 ** assume it's a UNIX-style command and return.
389 */
390 if (foreign_cmdline.dsc$w_length == 0)
391 return (SS$_NORMAL);
392 if ((*(foreign_cmdline.dsc$a_pointer) == '-') ||
393 ((foreign_cmdline.dsc$w_length > 1) &&
394 (*(foreign_cmdline.dsc$a_pointer) == '"') &&
395 (*(foreign_cmdline.dsc$a_pointer + 1) == '-'))) {
396 show_VMSCLI_help = FALSE;
397 return (SS$_NORMAL);
398 }
399
400 str$concat(&work_str, &zip_command, &foreign_cmdline);
401 status = cli$dcl_parse(&work_str, &zip_clitable, lib$get_input,
402 lib$get_input, 0);
403 if (!(status & 1)) return (status);
404 }
405
406 /*
407 ** There's always going to be a new_argv[] because of the image name.
408 */
409 if ((the_cmd_line = (char *) malloc(cmdl_size = ARGBSIZE_UNIT)) == NULL)
410 return (SS$_INSFMEM);
411
412 strcpy(the_cmd_line, "zip");
413 cmdl_len = sizeof("zip");
414
415 /*
416 ** First, check to see if any of the regular options were specified.
417 */
418
419 options[0] = '-';
420 ptr = &options[1]; /* Point to temporary buffer */
421
422 /*
423 ** Copy entries.
424 */
425 status = cli$present(&cli_copy_entries);
426 if (status & 1)
427 /* /COPY_ENTRIES */
428 *ptr++ = 'U';
429
430 /*
431 ** Delete the specified files from the zip file?
432 */
433 status = cli$present(&cli_delete);
434 if (status & 1)
435 /* /DELETE */
436 *ptr++ = 'd';
437
438 /*
439 ** Freshen (only changed files).
440 */
441 status = cli$present(&cli_freshen);
442 if (status & 1)
443 /* /FRESHEN */
444 *ptr++ = 'f';
445
446 /*
447 ** Delete the files once they've been added to the zip file.
448 */
449 status = cli$present(&cli_move);
450 if (status & 1)
451 /* /MOVE */
452 *ptr++ = 'm';
453
454 /*
455 ** Add changed and new files.
456 */
457 status = cli$present(&cli_update);
458 if (status & 1)
459 /* /UPDATE */
460 *ptr++ = 'u';
461
462 /*
463 ** Check for the compression level (-0 through -9).
464 */
465 status = cli$present(&cli_level);
466 if (status & 1) {
467 /* /LEVEL = value */
468
469 unsigned long binval;
470
471 status = cli$get_value(&cli_level, &work_str);
472 status = ots$cvt_tu_l(&work_str, &binval);
473 if (!(status & 1) || (binval > 9)) {
474 return (SS$_ABORT);
475 }
476 *ptr++ = binval + '0';
477 }
478
479 /*
480 ** Adjust offsets of zip archive entries.
481 */
482 status = cli$present(&cli_adjust);
483 if (status & 1)
484 /* /ADJUST_OFFSETS */
485 *ptr++ = 'A';
486
487 /*
488 ** Add comments?
489 */
490 status = cli$present(&cli_comments);
491 if (status & 1)
492 {
493 int archive_or_zip_file = 0;
494
495 if ((status = cli$present(&cli_comment_archive)) & 1)
496 /* /COMMENTS = ARCHIVE */
497 archive_or_zip_file = 1;
498 if ((status = cli$present(&cli_comment_zipfile)) & 1)
499 /* /COMMENTS = ZIP_FILE */
500 archive_or_zip_file = 1;
501 if (archive_or_zip_file != 0)
502 /* /COMMENTS = ARCHIVE */
503 *ptr++ = 'z';
504 if ((status = cli$present(&cli_comment_files)) & 1)
505 /* /COMMENTS = FILES */
506 *ptr++ = 'c';
507 }
508
509 /*
510 ** Preserve case in file names.
511 */
512 #define OPT_C "-C" /* Preserve case all. */
513 #define OPT_CN "-C-" /* Down-case all. */
514 #define OPT_C2 "-C2" /* Preserve case ODS2. */
515 #define OPT_C2N "-C2-" /* Down-case ODS2. */
516 #define OPT_C5 "-C5" /* Preserve case ODS5. */
517 #define OPT_C5N "-C5-" /* Down-case ODS5. */
518
519 status = cli$present( &cli_pres_case);
520 if ((status & 1) || (status == CLI$_NEGATED))
521 {
522 /* /[NO]PRESERVE_CASE */
523 char *opt;
524 int ods2 = 0;
525 int ods5 = 0;
526
527 if (status == CLI$_NEGATED)
528 {
529 x = cmdl_len;
530 cmdl_len += strlen( OPT_CN)+ 1;
531 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
532 strcpy( &the_cmd_line[ x], OPT_CN);
533 }
534 else
535 {
536 if (cli$present( &cli_pres_case_no2) & 1)
537 {
538 /* /PRESERVE_CASE = NOODS2 */
539 ods2 = -1;
540 }
541 if (cli$present( &cli_pres_case_no5) & 1)
542 {
543 /* /PRESERVE_CASE = NOODS5 */
544 ods5 = -1;
545 }
546 if (cli$present( &cli_pres_case_ods2) & 1)
547 {
548 /* /PRESERVE_CASE = ODS2 */
549 ods2 = 1;
550 }
551 if (cli$present( &cli_pres_case_ods5) & 1)
552 {
553 /* /PRESERVE_CASE = ODS5 */
554 ods5 = 1;
555 }
556
557 if (ods2 == ods5)
558 {
559 /* Plain "-C[-]". */
560 if (ods2 < 0)
561 opt = OPT_CN;
562 else
563 opt = OPT_C;
564
565 x = cmdl_len;
566 cmdl_len += strlen( opt)+ 1;
567 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
568 strcpy( &the_cmd_line[ x], opt);
569 }
570 else
571 {
572 if (ods2 != 0)
573 {
574 /* "-C2[-]". */
575 if (ods2 < 0)
576 opt = OPT_C2N;
577 else
578 opt = OPT_C2;
579
580 x = cmdl_len;
581 cmdl_len += strlen( opt)+ 1;
582 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
583 strcpy( &the_cmd_line[ x], opt);
584 }
585
586 if (ods5 != 0)
587 {
588 /* "-C5[-]". */
589 if (ods5 < 0)
590 opt = OPT_C5N;
591 else
592 opt = OPT_C5;
593
594 x = cmdl_len;
595 cmdl_len += strlen( opt)+ 1;
596 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
597 strcpy( &the_cmd_line[ x], opt);
598 }
599 }
600 }
601 }
602
603 /*
604 ** Pattern case sensitivity.
605 */
606 #define OPT_IC "-ic" /* Case-insensitive pattern matching. */
607 #define OPT_ICN "-ic-" /* Case-sensitive pattern matching. */
608
609 status = cli$present( &cli_patt_case);
610 if (status & 1)
611 {
612 if (cli$present( &cli_patt_case_blind) & 1)
613 {
614 /* "-ic". */
615 x = cmdl_len;
616 cmdl_len += strlen( OPT_IC)+ 1;
617 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
618 strcpy( &the_cmd_line[ x], OPT_IC);
619 }
620 else if (cli$present( &cli_patt_case_sensitive) & 1)
621 {
622 /* "-ic-". */
623 x = cmdl_len;
624 cmdl_len += strlen( OPT_ICN)+ 1;
625 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
626 strcpy( &the_cmd_line[ x], OPT_ICN);
627 }
628 }
629
630 /*
631 ** Data descriptors.
632 */
633 #define OPT_FD "-fd"
634
635 status = cli$present( &cli_descriptors);
636 if (status & 1)
637 {
638 /* /DESCRIPTORS */
639 x = cmdl_len;
640 cmdl_len += strlen( OPT_FD)+ 1;
641 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
642 strcpy( &the_cmd_line[ x], OPT_FD);
643 }
644
645 /*
646 ** Difference archive. Add only new or changed files.
647 */
648 #define OPT_DF "-DF" /* Difference archive. */
649
650 if ((status = cli$present( &cli_difference)) & 1)
651 {
652 /* /DIFFERENCE */
653 x = cmdl_len;
654 cmdl_len += strlen( OPT_DF)+ 1;
655 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
656 strcpy( &the_cmd_line[ x], OPT_DF);
657 }
658
659 /*
660 ** Do not add/modify directory entries.
661 */
662 status = cli$present(&cli_dirnames);
663 if (!(status & 1))
664 /* /DIRNAMES */
665 *ptr++ = 'D';
666
667 /*
668 ** Encrypt?
669 */
670 status = cli$present(&cli_encrypt);
671 if (status & 1)
672 if ((status = cli$get_value(&cli_encrypt, &work_str)) & 1) {
673 /* /ENCRYPT = value */
674 x = cmdl_len;
675 cmdl_len += work_str.dsc$w_length + 4;
676 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
677 strcpy(&the_cmd_line[x], "-P");
678 strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,
679 work_str.dsc$w_length);
680 the_cmd_line[cmdl_len-1] = '\0';
681 } else {
682 /* /ENCRYPT */
683 *ptr++ = 'e';
684 }
685
686 /*
687 ** Fix the zip archive structure.
688 */
689 status = cli$present(&cli_fix_archive);
690 if (status & 1) {
691 *ptr++ = 'F';
692 /* /FIX_ARCHIVE = NORMAL */
693 if ((status = cli$present(&cli_fix_full)) & 1) {
694 /* /FIX_ARCHIVE = FULL */
695 *ptr++ = 'F';
696 }
697 }
698
699 /*
700 ** Filesync. Delete archive entry if no such file.
701 */
702 #define OPT_FS "-FS" /* Filesync. */
703
704 if ((status = cli$present( &cli_filesync)) & 1)
705 {
706 /* /FILESYNC */
707 x = cmdl_len;
708 cmdl_len += strlen( OPT_FS)+ 1;
709 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
710 strcpy( &the_cmd_line[ x], OPT_FS);
711 }
712
713 /*
714 ** Append (allow growing of existing zip file).
715 */
716 status = cli$present(&cli_append);
717 if (status & 1)
718 /* /APPEND */
719 *ptr++ = 'g';
720
721 status = cli$present(&cli_grow);
722 if (status & 1)
723 /* /GROW */
724 *ptr++ = 'g';
725
726 /*
727 ** Show the help.
728 */
729 #define OPT_H2 "-h2"
730
731 status = cli$present(&cli_help);
732 if (status & 1)
733 {
734 status = cli$present( &cli_help_normal);
735 if (status & 1)
736 {
737 /* /HELP [= NORMAL] */
738 *ptr++ = 'h';
739 }
740 status = cli$present( &cli_help_extended);
741 if (status & 1)
742 {
743 /* /HELP = EXTENDED */
744 x = cmdl_len;
745 cmdl_len += strlen( OPT_H2)+ 1;
746 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
747 strcpy( &the_cmd_line[ x], OPT_H2);
748 }
749 }
750
751 /*
752 ** Junk path names (directory specs).
753 */
754 status = cli$present(&cli_junk);
755 if (status & 1)
756 /* /JUNK */
757 *ptr++ = 'j';
758
759 /*
760 ** Simulate zip file made by PKZIP.
761 */
762 status = cli$present(&cli_pkzip);
763 if (status & 1)
764 /* /KEEP_VERSION */
765 *ptr++ = 'k';
766
767 /*
768 ** Translate end-of-line.
769 */
770 status = cli$present(&cli_translate_eol);
771 if (status & 1) {
772 /* /TRANSLATE_EOL [= LF]*/
773 *ptr++ = 'l';
774 if ((status = cli$present(&cli_transl_eol_crlf)) & 1) {
775 /* /TRANSLATE_EOL = CRLF */
776 *ptr++ = 'l';
777 }
778 }
779
780 /*
781 ** Show the software license.
782 */
783 status = cli$present(&cli_license);
784 if (status & 1)
785 /* /LICENSE */
786 *ptr++ = 'L';
787
788 /*
789 ** Set zip file time to time of latest file in it.
790 */
791 status = cli$present(&cli_latest);
792 if (status & 1)
793 /* /LATEST */
794 *ptr++ = 'o';
795
796 /*
797 ** Store full path (default).
798 */
799 status = cli$present(&cli_full_path);
800 if (status == CLI$_PRESENT)
801 /* /FULL_PATH */
802 *ptr++ = 'p';
803 else if (status == CLI$_NEGATED)
804 /* /NOFULL_PATH */
805 *ptr++ = 'j';
806
807 /*
808 ** Junk Zipfile prefix (SFX stub etc.).
809 */
810 status = cli$present(&cli_unsfx);
811 if (status & 1)
812 /* /UNSFX */
813 *ptr++ = 'J';
814
815 /*
816 ** Recurse through subdirectories.
817 */
818 status = cli$present(&cli_recurse);
819 if (status & 1) {
820 if ((status = cli$present(&cli_recurse_fnames)) & 1)
821 /* /RECURSE [= PATH] */
822 *ptr++ = 'R';
823 else
824 /* /RECURSE [= FILENAMES] */
825 *ptr++ = 'r';
826 }
827
828 /*
829 ** Test Zipfile.
830 */
831 status = cli$present(&cli_test);
832 if (status & 1) {
833 /* /TEST */
834 *ptr++ = 'T';
835 }
836
837 /*
838 ** Be verbose.
839 */
840 status = cli$present(&cli_verbose);
841 if (status & 1) {
842 int i;
843 int verbo = 0;
844
845 /* /VERBOSE */
846 if ((status = cli$present(&cli_verbose_command)) & 1)
847 {
848 /* /VERBOSE = COMMAND */
849 verbose_command = 1;
850 }
851
852 /* Note that any or all of the following options may be
853 specified, and the maximum one is used.
854 */
855 if ((status = cli$present(&cli_verbose_normal)) & 1)
856 /* /VERBOSE [ = NORMAL ] */
857 verbo = 1;
858 if ((status = cli$present(&cli_verbose_more)) & 1)
859 /* /VERBOSE = MORE */
860 verbo = 2;
861 if ((status = cli$present(&cli_verbose_debug)) & 1) {
862 /* /VERBOSE = DEBUG */
863 verbo = 3;
864 }
865 for (i = 0; i < verbo; i++)
866 *ptr++ = 'v';
867 }
868
869 /*
870 ** Quiet mode.
871 ** (Quiet mode is processed after verbose, because a "-v" modifier
872 ** resets "noisy" to 1.)
873 */
874 status = cli$present(&cli_quiet);
875 if (status & 1)
876 /* /QUIET */
877 *ptr++ = 'q';
878
879 /*
880 ** Save the VMS file attributes (and all allocated blocks?).
881 */
882 status = cli$present(&cli_vms);
883 if (status & 1) {
884 /* /VMS */
885 *ptr++ = 'V';
886 if ((status = cli$present(&cli_vms_all)) & 1) {
887 /* /VMS = ALL */
888 *ptr++ = 'V';
889 }
890 }
891
892 /*
893 ** Keep the VMS version number as part of the file name when stored.
894 */
895 status = cli$present(&cli_keep_version);
896 if (status & 1)
897 /* /KEEP_VERSION */
898 *ptr++ = 'w';
899
900 /*
901 ** Store symlinks as symlinks.
902 */
903 status = cli$present(&cli_symlinks);
904 if (status & 1)
905 /* /SYMLINKS */
906 *ptr++ = 'y';
907
908 /*
909 ** `Batch' processing: read filenames to archive from stdin
910 ** or the specified file.
911 */
912 status = cli$present(&cli_batch);
913 if (status & 1) {
914 /* /BATCH */
915 status = cli$get_value(&cli_batch, &work_str);
916 if (status & 1) {
917 /* /BATCH = value */
918 work_str.dsc$a_pointer[work_str.dsc$w_length] = '\0';
919 if ((stdin = freopen(work_str.dsc$a_pointer, "r", stdin)) == NULL)
920 {
921 sprintf(errbuf, "could not open list file: %s",
922 work_str.dsc$a_pointer);
923 ziperr(ZE_PARMS, errbuf);
924 }
925 }
926 *ptr++ = '@';
927 }
928
929 /*
930 ** Now copy the final options string to the_cmd_line.
931 */
932 len = ptr - &options[0];
933 if (len > 1) {
934 options[len] = '\0';
935 x = cmdl_len;
936 cmdl_len += len + 1;
937 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
938 strcpy(&the_cmd_line[x], options);
939 }
940
941 /*
942 **
943 ** OK. We've done all the regular options, so check for -b (temporary
944 ** file path), -n (special suffixes), -O (output atchive file),
945 ** -t (exclude before time), -Z (compression method), zipfile,
946 ** files to zip, and exclude list.
947 **
948 */
949 status = cli$present(&cli_temp_path);
950 if (status & 1) {
951 /* /TEMP_PATH = value */
952 status = cli$get_value(&cli_temp_path, &work_str);
953 x = cmdl_len;
954 cmdl_len += work_str.dsc$w_length + 4;
955 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
956 strcpy(&the_cmd_line[x], "-b");
957 strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,
958 work_str.dsc$w_length);
959 the_cmd_line[cmdl_len-1] = '\0';
960 }
961
962 status = cli$present(&cli_output);
963 if (status & 1) {
964 /* /OUTPUT = value */
965 status = cli$get_value(&cli_output, &work_str);
966 x = cmdl_len;
967 cmdl_len += work_str.dsc$w_length + 4;
968 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
969 strcpy(&the_cmd_line[x], "-O");
970 strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,
971 work_str.dsc$w_length);
972 the_cmd_line[cmdl_len-1] = '\0';
973 }
974
975 /*
976 ** Handle "-db", "-dc", "-dd", "-ds".
977 */
978 #define OPT_DB "-db"
979 #define OPT_DC "-dc"
980 #define OPT_DD "-dd"
981 #define OPT_DG "-dg"
982 #define OPT_DS "-ds="
983 #define OPT_DU "-du"
984 #define OPT_DV "-dv"
985
986 status = cli$present( &cli_display);
987 if (status & 1)
988 {
989 if ((status = cli$present( &cli_display_bytes)) & 1)
990 {
991 /* /DISPLAY = BYTES */
992 x = cmdl_len;
993 cmdl_len += strlen( OPT_DB)+ 1;
994 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
995 strcpy( &the_cmd_line[ x], OPT_DB);
996 }
997
998 if ((status = cli$present( &cli_display_counts)) & 1)
999 {
1000 /* /DISPLAY = COUNTS */
1001 x = cmdl_len;
1002 cmdl_len += strlen( OPT_DC)+ 1;
1003 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1004 strcpy( &the_cmd_line[ x], OPT_DC);
1005 }
1006
1007 if ((status = cli$present( &cli_display_dots)) & 1)
1008 {
1009 /* /DISPLAY = DOTS [= value] */
1010 status = cli$get_value( &cli_display_dots, &work_str);
1011
1012 x = cmdl_len;
1013 cmdl_len += strlen( OPT_DD)+ 1;
1014 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1015 strcpy( &the_cmd_line[ x], OPT_DD);
1016
1017 /* -dd[=value] now -dd -ds=value - 5/8/05 EG */
1018 if (work_str.dsc$w_length > 0) {
1019 x = cmdl_len;
1020 cmdl_len += strlen( OPT_DS);
1021 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1022 strcpy( &the_cmd_line[ x], OPT_DS);
1023
1024 x = cmdl_len;
1025 cmdl_len += work_str.dsc$w_length+ 1;
1026 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1027 strncpy( &the_cmd_line[ x],
1028 work_str.dsc$a_pointer, work_str.dsc$w_length);
1029 }
1030 }
1031
1032 if ((status = cli$present( &cli_display_globaldots)) & 1)
1033 {
1034 /* /DISPLAY = GLOBALDOTS */
1035 x = cmdl_len;
1036 cmdl_len += strlen( OPT_DG)+ 1;
1037 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1038 strcpy( &the_cmd_line[ x], OPT_DG);
1039 }
1040
1041 if ((status = cli$present( &cli_display_usize)) & 1)
1042 {
1043 /* /DISPLAY = USIZE */
1044 x = cmdl_len;
1045 cmdl_len += strlen( OPT_DU)+ 1;
1046 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1047 strcpy( &the_cmd_line[ x], OPT_DU);
1048 }
1049
1050 if ((status = cli$present( &cli_display_volume)) & 1)
1051 {
1052 /* /DISPLAY = VOLUME */
1053 x = cmdl_len;
1054 cmdl_len += strlen( OPT_DV)+ 1;
1055 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1056 strcpy( &the_cmd_line[ x], OPT_DV);
1057 }
1058 }
1059
1060 /*
1061 ** Handle "-la", "-lf", "-li".
1062 */
1063 #define OPT_LA "-la"
1064 #define OPT_LF "-lf"
1065 #define OPT_LI "-li"
1066
1067 status = cli$present( &cli_log_file);
1068 if (status & 1)
1069 {
1070 /* /SHOW */
1071 if ((status = cli$present( &cli_log_file_append)) & 1)
1072 {
1073 /* /LOG_FILE = APPEND */
1074 x = cmdl_len;
1075 cmdl_len += strlen( OPT_LA)+ 1;
1076 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1077 strcpy( &the_cmd_line[ x], OPT_LA);
1078 }
1079
1080 status = cli$present(&cli_log_file_file);
1081 if (status & 1) {
1082 /* /LOG_FILE = FILE = file */
1083 status = cli$get_value(&cli_log_file_file, &work_str);
1084 x = cmdl_len;
1085 cmdl_len += strlen( OPT_LF)+ 2+ work_str.dsc$w_length;
1086 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1087 strcpy(&the_cmd_line[x], OPT_LF);
1088 strncpy(&the_cmd_line[x+strlen( OPT_LF)+ 1], work_str.dsc$a_pointer,
1089 work_str.dsc$w_length);
1090 the_cmd_line[cmdl_len-1] = '\0';
1091 }
1092
1093 if ((status = cli$present( &cli_log_file_info)) & 1)
1094 {
1095 /* /LOG = INFO */
1096 x = cmdl_len;
1097 cmdl_len += strlen( OPT_LI)+ 1;
1098 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1099 strcpy( &the_cmd_line[ x], OPT_LI);
1100 }
1101 }
1102
1103 /*
1104 ** Handle "-s", "-sb", "-sp", "-sv".
1105 */
1106 #define OPT_S "-s"
1107 #define OPT_SB "-sb"
1108 #define OPT_SP "-sp"
1109 #define OPT_SV "-sv"
1110
1111 status = cli$present( &cli_split);
1112 if (status & 1)
1113 {
1114 status = cli$present( &cli_split_bell);
1115 if (status & 1)
1116 {
1117 /* /SPLIT = BELL */
1118 x = cmdl_len;
1119 cmdl_len += strlen( OPT_SB)+ 1;
1120 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1121 strcpy( &the_cmd_line[ x], OPT_SB);
1122 }
1123
1124 status = cli$present( &cli_split_pause);
1125 if (status & 1)
1126 {
1127 /* /SPLIT = PAUSE */
1128 x = cmdl_len;
1129 cmdl_len += strlen( OPT_SP)+ 1;
1130 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1131 strcpy( &the_cmd_line[ x], OPT_SP);
1132 }
1133
1134 status = cli$present( &cli_split_size);
1135 if (status & 1)
1136 {
1137 /* /SPLIT = SIZE = size */
1138 status = cli$get_value( &cli_split_size, &work_str);
1139
1140 x = cmdl_len;
1141 cmdl_len += strlen( OPT_S)+ 1;
1142 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1143 strcpy( &the_cmd_line[ x], OPT_S);
1144
1145 x = cmdl_len;
1146 cmdl_len += work_str.dsc$w_length+ 1;
1147 strncpy( &the_cmd_line[ x],
1148 work_str.dsc$a_pointer, work_str.dsc$w_length);
1149 }
1150
1151 status = cli$present( &cli_split_verbose);
1152 if (status & 1)
1153 {
1154 /* /SPLIT = VERBOSE */
1155 x = cmdl_len;
1156 cmdl_len += strlen( OPT_SV)+ 1;
1157 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1158 strcpy( &the_cmd_line[ x], OPT_SV);
1159 }
1160 }
1161
1162 /*
1163 ** Handle "-sc", "-sd", "-sf", "-so".
1164 */
1165 #define OPT_SC "-sc"
1166 #define OPT_SD "-sd"
1167 #define OPT_SF "-sf"
1168 #define OPT_SO "-so"
1169
1170 status = cli$present( &cli_show);
1171 if (status & 1)
1172 {
1173 /* /SHOW */
1174 if ((status = cli$present( &cli_show_command)) & 1)
1175 {
1176 /* /SHOW = COMMAND */
1177 x = cmdl_len;
1178 cmdl_len += strlen( OPT_SC)+ 1;
1179 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1180 strcpy( &the_cmd_line[ x], OPT_SC);
1181 }
1182
1183 if ((status = cli$present( &cli_show_debug)) & 1)
1184 {
1185 /* /SHOW = DEBUG */
1186 x = cmdl_len;
1187 cmdl_len += strlen( OPT_SD)+ 1;
1188 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1189 strcpy( &the_cmd_line[ x], OPT_SD);
1190 }
1191
1192 if ((status = cli$present( &cli_show_files)) & 1)
1193 {
1194 /* /SHOW = FILES */
1195 x = cmdl_len;
1196 cmdl_len += strlen( OPT_SF)+ 1;
1197 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1198 strcpy( &the_cmd_line[ x], OPT_SF);
1199 }
1200
1201 if ((status = cli$present( &cli_show_options)) & 1)
1202 {
1203 /* /SHOW = OPTIONS */
1204 x = cmdl_len;
1205 cmdl_len += strlen( OPT_SO)+ 1;
1206 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1207 strcpy( &the_cmd_line[ x], OPT_SO);
1208 }
1209 }
1210
1211 /*
1212 ** Handle "-fz".
1213 */
1214 #define OPT_FZ "-fz"
1215
1216 status = cli$present( &cli_zip64);
1217 if (status & 1)
1218 {
1219 /* /ZIP64 */
1220 x = cmdl_len;
1221 cmdl_len += strlen( OPT_FZ)+ 1;
1222 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1223 strcpy( &the_cmd_line[ x], OPT_FZ);
1224 }
1225
1226 /*
1227 ** Handle "-nw" and "-W".
1228 */
1229 #define OPT_NW "-nw"
1230 #define OPT_W "-W"
1231
1232 status = cli$present( &cli_wildcard);
1233 if (status & 1)
1234 {
1235 if ((status = cli$present( &cli_wildcard_nospan)) & 1)
1236 {
1237 /* /WILDCARD = NOSPAN */
1238 x = cmdl_len;
1239 cmdl_len += strlen( OPT_W)+ 1;
1240 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1241 strcpy( &the_cmd_line[ x], OPT_W);
1242 }
1243 }
1244 else if (status == CLI$_NEGATED)
1245 {
1246 /* /NOWILDCARD */
1247 x = cmdl_len;
1248 cmdl_len += strlen( OPT_NW)+ 1;
1249 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1250 strcpy( &the_cmd_line[ x], OPT_NW);
1251 }
1252
1253 /*
1254 ** Handle "-MM".
1255 */
1256 #define OPT_MM "-MM"
1257
1258 status = cli$present( &cli_must_match);
1259 if (status & 1)
1260 {
1261 /* /MUST_MATCH */
1262 x = cmdl_len;
1263 cmdl_len += strlen( OPT_MM)+ 1;
1264 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1265 strcpy( &the_cmd_line[ x], OPT_MM);
1266 }
1267
1268 /*
1269 ** UnZip command for archive test.
1270 */
1271 #define OPT_TT "-TT"
1272
1273 status = cli$present(&cli_test);
1274 if (status & 1) {
1275 /* /TEST */
1276 status = cli$present(&cli_test_unzip);
1277 if (status & 1) {
1278 /* /TEST = UNZIP = value */
1279 status = cli$get_value(&cli_test_unzip, &work_str);
1280 x = cmdl_len;
1281 cmdl_len += strlen( OPT_TT)+ 2+ work_str.dsc$w_length;
1282 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1283 strcpy(&the_cmd_line[x], OPT_TT);
1284 strncpy(&the_cmd_line[x+strlen( OPT_TT)+ 1], work_str.dsc$a_pointer,
1285 work_str.dsc$w_length);
1286 the_cmd_line[cmdl_len-1] = '\0';
1287 }
1288 }
1289
1290 /*
1291 ** Handle "-Z".
1292 */
1293 #define OPT_ZB "-Zb"
1294 #define OPT_ZD "-Zd"
1295 #define OPT_ZS "-Zs"
1296
1297 status = cli$present( &cli_compression);
1298 if (status & 1)
1299 {
1300 if ((status = cli$present( &cli_compression_b)) & 1)
1301 {
1302 /* /COMPRESSION = BZIP2 */
1303 x = cmdl_len;
1304 cmdl_len += strlen( OPT_ZB)+ 1;
1305 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1306 strcpy( &the_cmd_line[ x], OPT_ZB);
1307 }
1308
1309 if ((status = cli$present( &cli_compression_d)) & 1)
1310 {
1311 /* /COMPRESSION = DEFLATE */
1312 x = cmdl_len;
1313 cmdl_len += strlen( OPT_ZD)+ 1;
1314 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1315 strcpy( &the_cmd_line[ x], OPT_ZD);
1316 }
1317
1318 if ((status = cli$present( &cli_compression_s)) & 1)
1319 {
1320 /* /COMPRESSION = STORE */
1321 x = cmdl_len;
1322 cmdl_len += strlen( OPT_ZS)+ 1;
1323 CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)
1324 strcpy( &the_cmd_line[ x], OPT_ZS);
1325 }
1326 }
1327
1328 /*
1329 ** Handle "-t mmddyyyy".
1330 */
1331 status = cli$present(&cli_since);
1332 if (status & 1) {
1333 /* /SINCE = value */
1334 char since_time[9];
1335
1336 status = get_time(&cli_since, &since_time[0]);
1337 if (!(status & 1)) return (status);
1338
1339 /*
1340 ** Now let's add the option "-t mmddyyyy" to the new command line.
1341 */
1342 x = cmdl_len;
1343 cmdl_len += (3 + 9);
1344 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1345 strcpy(&the_cmd_line[x], "-t");
1346 strcpy(&the_cmd_line[x+3], since_time);
1347 }
1348
1349 /*
1350 ** Handle "-tt mmddyyyy".
1351 */
1352 status = cli$present(&cli_before);
1353 if (status & 1) {
1354 /* /BEFORE = value */
1355 char before_time[9];
1356
1357 status = get_time(&cli_before, &before_time[0]);
1358 if (!(status & 1)) return (status);
1359
1360 /*
1361 ** Now let's add the option "-tt mmddyyyy" to the new command line.
1362 */
1363 x = cmdl_len;
1364 cmdl_len += (4 + 9);
1365 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1366 strcpy(&the_cmd_line[x], "-tt");
1367 strcpy(&the_cmd_line[x+4], before_time);
1368 }
1369
1370 /*
1371 ** Handle "-n suffix:suffix:...". (File types to store only.)
1372 */
1373 status = cli$present(&cli_store_types);
1374 if (status & 1) {
1375 /* /STORE_TYPES = value_list */
1376 x = cmdl_len;
1377 cmdl_len += 3;
1378 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1379 strcpy(&the_cmd_line[x], "-n");
1380
1381 status = get_list(&cli_store_types, &foreign_cmdline, ':',
1382 &the_cmd_line, &cmdl_size, &cmdl_len);
1383 if (!(status & 1)) return (status);
1384 }
1385
1386 /*
1387 ** Handle "-X", keep or strip extra fields.
1388 */
1389 #define OPT_X "-X"
1390 #define OPT_XN "-X-"
1391
1392 status = cli$present(&cli_extra_fields);
1393 if (status & 1) {
1394 /* /EXTRA_FIELDS */
1395 if ((status = cli$present( &cli_extra_fields_keep)) & 1) {
1396 /* /EXTRA_FIELDS = KEEP_EXISTING */
1397 x = cmdl_len;
1398 cmdl_len += strlen( OPT_XN)+ 1;
1399 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1400 strcpy( &the_cmd_line[ x], OPT_XN);
1401 }
1402 }
1403 else if (status == CLI$_NEGATED) {
1404 /* /NOEXTRA_FIELDS */
1405 x = cmdl_len;
1406 cmdl_len += strlen( OPT_X)+ 1;
1407 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1408 strcpy( &the_cmd_line[ x], OPT_X);
1409 }
1410
1411 /*
1412 ** Now get the specified zip file name.
1413 */
1414 status = cli$present(&cli_zipfile);
1415 /* zipfile */
1416 if (status & 1) {
1417 status = cli$get_value(&cli_zipfile, &work_str);
1418
1419 x = cmdl_len;
1420 cmdl_len += work_str.dsc$w_length + 1;
1421 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1422 strncpy(&the_cmd_line[x], work_str.dsc$a_pointer,
1423 work_str.dsc$w_length);
1424 the_cmd_line[cmdl_len-1] = '\0';
1425
1426 }
1427
1428 /*
1429 ** Run through the list of input files.
1430 */
1431 status = cli$present(&cli_infile);
1432 if (status & 1) {
1433 /* infile_list */
1434 status = get_list(&cli_infile, &foreign_cmdline, '\0',
1435 &the_cmd_line, &cmdl_size, &cmdl_len);
1436 if (!(status & 1)) return (status);
1437 }
1438
1439 /*
1440 ** List file containing exclude patterns present? ("-x@exclude.lst")
1441 */
1442 status = cli$present(&cli_exlist);
1443 if (status & 1) {
1444 /* /EXLIST = list */
1445 status = cli$get_value(&cli_exlist, &work_str);
1446 x = cmdl_len;
1447 cmdl_len += work_str.dsc$w_length + 4;
1448 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1449 strncpy(&the_cmd_line[x], "-x@", 3);
1450 strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,
1451 work_str.dsc$w_length);
1452 the_cmd_line[cmdl_len-1] = '\0';
1453 }
1454
1455 /*
1456 ** Any files to exclude? ("-x file file")
1457 */
1458 status = cli$present(&cli_exclude);
1459 if (status & 1) {
1460 /* /EXCLUDE = list */
1461 x = cmdl_len;
1462 cmdl_len += 3;
1463 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1464 strcpy(&the_cmd_line[x], "-x");
1465
1466 status = get_list(&cli_exclude, &foreign_cmdline, '\0',
1467 &the_cmd_line, &cmdl_size, &cmdl_len);
1468 if (!(status & 1)) return (status);
1469 }
1470
1471 /*
1472 ** List file containing include patterns present? ("-x@exclude.lst")
1473 */
1474 status = cli$present(&cli_inlist);
1475 if (status & 1) {
1476 /* /INLIST = list */
1477 status = cli$get_value(&cli_inlist, &work_str);
1478 x = cmdl_len;
1479 cmdl_len += work_str.dsc$w_length + 4;
1480 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1481 strncpy(&the_cmd_line[x], "-i@", 3);
1482 strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,
1483 work_str.dsc$w_length);
1484 the_cmd_line[cmdl_len-1] = '\0';
1485 }
1486
1487 /*
1488 ** Any files to include? ("-i file file")
1489 */
1490 status = cli$present(&cli_include);
1491 if (status & 1) {
1492 /* /INCLUDE = list */
1493 x = cmdl_len;
1494 cmdl_len += 3;
1495 CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)
1496 strcpy(&the_cmd_line[x], "-i");
1497
1498 status = get_list(&cli_exclude, &foreign_cmdline, '\0',
1499 &the_cmd_line, &cmdl_size, &cmdl_len);
1500 if (!(status & 1)) return (status);
1501 }
1502
1503
1504 /*
1505 ** We have finished collecting the strings for the argv vector,
1506 ** release unused space.
1507 */
1508 if ((the_cmd_line = (char *) realloc(the_cmd_line, cmdl_len)) == NULL)
1509 return (SS$_INSFMEM);
1510
1511 /*
1512 ** Now that we've built our new UNIX-like command line, count the
1513 ** number of args and build an argv array.
1514 */
1515 for (new_argc = 0, x = 0; x < cmdl_len; x++)
1516 if (the_cmd_line[x] == '\0')
1517 new_argc++;
1518
1519 /*
1520 ** Allocate memory for the new argv[]. The last element of argv[]
1521 ** is supposed to be NULL, so allocate enough for new_argc+1.
1522 */
1523 if ((new_argv = (char **) calloc(new_argc+1, sizeof(char *))) == NULL)
1524 return (SS$_INSFMEM);
1525
1526 /*
1527 ** For each option, store the address in new_argv[] and convert the
1528 ** separating blanks to nulls so each argv[] string is terminated.
1529 */
1530 for (ptr = the_cmd_line, x = 0; x < new_argc; x++) {
1531 new_argv[x] = ptr;
1532 ptr += strlen(ptr) + 1;
1533 }
1534 new_argv[new_argc] = NULL;
1535
1536 #if defined(TEST) || defined(DEBUG)
1537 printf("new_argc = %d\n", new_argc);
1538 for (x = 0; x < new_argc; x++)
1539 printf("new_argv[%d] = %s\n", x, new_argv[x]);
1540 #endif /* TEST || DEBUG */
1541
1542 /* Show the complete UNIX command line, if requested. */
1543 if (verbose_command != 0)
1544 {
1545 printf( " UNIX command line args (argc = %d):\n", new_argc);
1546 for (x = 0; x < new_argc; x++)
1547 printf( "%s\n", new_argv[ x]);
1548 printf( "\n");
1549 }
1550
1551 /*
1552 ** All finished. Return the new argc and argv[] addresses to Zip.
1553 */
1554 *argc_p = new_argc;
1555 *argv_p = new_argv;
1556
1557 return (SS$_NORMAL);
1558 }
1559
1560
1561
1562 static unsigned long
get_list(struct dsc$descriptor_s * qual,struct dsc$descriptor_d * rawtail,int delim,char ** p_str,unsigned long * p_size,unsigned long * p_end)1563 get_list (struct dsc$descriptor_s *qual, struct dsc$descriptor_d *rawtail,
1564 int delim, char **p_str, unsigned long *p_size, unsigned long *p_end)
1565 {
1566 /*
1567 ** Routine: get_list
1568 **
1569 ** Function: This routine runs through a comma-separated CLI list
1570 ** and copies the strings to the argv buffer. The
1571 ** specified separation character is used to separate
1572 ** the strings in the argv buffer.
1573 **
1574 ** All unquoted strings are converted to lower-case.
1575 **
1576 ** Formal parameters:
1577 **
1578 ** qual - Address of descriptor for the qualifier name
1579 ** rawtail - Address of descriptor for the full command line tail
1580 ** delim - Character to use to separate the list items
1581 ** p_str - Address of pointer pointing to output buffer (argv strings)
1582 ** p_size - Address of number containing allocated size for output string
1583 ** p_end - Address of number containing used length in output buf
1584 **
1585 */
1586
1587 register unsigned long status;
1588 struct dsc$descriptor_d work_str;
1589
1590 init_dyndesc(work_str);
1591
1592 status = cli$present(qual);
1593 if (status & 1) {
1594
1595 unsigned long len, old_len;
1596 long ind, sind;
1597 int keep_case;
1598 char *src, *dst; int x;
1599
1600 /*
1601 ** Just in case the string doesn't exist yet, though it does.
1602 */
1603 if (*p_str == NULL) {
1604 *p_size = ARGBSIZE_UNIT;
1605 if ((*p_str = (char *) malloc(*p_size)) == NULL)
1606 return (SS$_INSFMEM);
1607 len = 0;
1608 } else {
1609 len = *p_end;
1610 }
1611
1612 while ((status = cli$get_value(qual, &work_str)) & 1) {
1613 old_len = len;
1614 len += work_str.dsc$w_length + 1;
1615 CHECK_BUFFER_ALLOCATION(*p_str, *p_size, len)
1616
1617 /*
1618 ** Look for the filename in the original foreign command
1619 ** line to see if it was originally quoted. If so, then
1620 ** don't convert it to lowercase.
1621 */
1622 keep_case = FALSE;
1623 str$find_first_substring(rawtail, &ind, &sind, &work_str);
1624 if ((ind > 1 && *(rawtail->dsc$a_pointer + ind - 2) == '"') ||
1625 (ind == 0))
1626 keep_case = TRUE;
1627
1628 /*
1629 ** Copy the string to the buffer, converting to lowercase.
1630 */
1631 src = work_str.dsc$a_pointer;
1632 dst = *p_str+old_len;
1633 for (x = 0; x < work_str.dsc$w_length; x++) {
1634 if (!keep_case && ((*src >= 'A') && (*src <= 'Z')))
1635 *dst++ = *src++ + 32;
1636 else
1637 *dst++ = *src++;
1638 }
1639 if (status == CLI$_COMMA)
1640 (*p_str)[len-1] = (char)delim;
1641 else
1642 (*p_str)[len-1] = '\0';
1643 }
1644 *p_end = len;
1645 }
1646
1647 return (SS$_NORMAL);
1648
1649 }
1650
1651
1652 static unsigned long
get_time(struct dsc$descriptor_s * qual,char * timearg)1653 get_time (struct dsc$descriptor_s *qual, char *timearg)
1654 {
1655 /*
1656 ** Routine: get_time
1657 **
1658 ** Function: This routine reads the argument string of the qualifier
1659 ** "qual" that should be a VMS syntax date-time string. The
1660 ** date-time string is converted into the standard format
1661 ** "mmddyyyy", specifying an absolute date. The converted
1662 ** string is written into the 9 bytes wide buffer "timearg".
1663 **
1664 ** Formal parameters:
1665 **
1666 ** qual - Address of descriptor for the qualifier name
1667 ** timearg - Address of a buffer carrying the 8-char time string returned
1668 **
1669 */
1670
1671 register unsigned long status;
1672 struct dsc$descriptor_d time_str;
1673 struct quadword {
1674 long high;
1675 long low;
1676 } bintimbuf = {0,0};
1677 #ifdef __DECC
1678 #pragma member_alignment save
1679 #pragma nomember_alignment
1680 #endif /* __DECC */
1681 struct tim {
1682 short year;
1683 short month;
1684 short day;
1685 short hour;
1686 short minute;
1687 short second;
1688 short hundred;
1689 } numtimbuf;
1690 #ifdef __DECC
1691 #pragma member_alignment restore
1692 #endif
1693
1694 init_dyndesc(time_str);
1695
1696 status = cli$get_value(qual, &time_str);
1697 /*
1698 ** If a date is given, convert it to 64-bit binary.
1699 */
1700 if (time_str.dsc$w_length) {
1701 status = sys$bintim(&time_str, &bintimbuf);
1702 if (!(status & 1)) return (status);
1703 str$free1_dx(&time_str);
1704 }
1705 /*
1706 ** Now call $NUMTIM to get the month, day, and year.
1707 */
1708 status = sys$numtim(&numtimbuf, (bintimbuf.low ? &bintimbuf : NULL));
1709 /*
1710 ** Write the "mmddyyyy" string to the return buffer.
1711 */
1712 if (!(status & 1)) {
1713 *timearg = '\0';
1714 } else {
1715 sprintf(timearg, "%02d%02d%04d", numtimbuf.month,
1716 numtimbuf.day, numtimbuf.year);
1717 }
1718 return (status);
1719 }
1720
1721
1722 static unsigned long
check_cli(struct dsc$descriptor_s * qual)1723 check_cli (struct dsc$descriptor_s *qual)
1724 {
1725 /*
1726 ** Routine: check_cli
1727 **
1728 ** Function: Check to see if a CLD was used to invoke the program.
1729 **
1730 ** Formal parameters:
1731 **
1732 ** qual - Address of descriptor for qualifier name to check.
1733 **
1734 */
1735 lib$establish(lib$sig_to_ret); /* Establish condition handler */
1736 return (cli$present(qual)); /* Just see if something was given */
1737 }
1738
1739
1740 #ifndef TEST
1741
VMSCLI_help(void)1742 void VMSCLI_help(void) /* VMSCLI version */
1743 /* Print help (along with license info) to stdout. */
1744 {
1745 extent i; /* counter for help array */
1746
1747 /* help array */
1748 static char *text[] = {
1749 "Zip %s (%s). Usage: (zip :== $ dev:[dir]zip_cli.exe)",
1750 "zip archive[.zip] [list] [/EXCL=(xlist)] /options /modifiers",
1751 " The default action is to add or replace archive entries from list, except",
1752 " those in xlist. The include file list may contain the special name \"-\" to",
1753 " compress standard input. If both archive and list are omitted, Zip",
1754 " compresses stdin to stdout.",
1755 " Type zip -h for Unix-style flags.",
1756 " Major options include:",
1757 " /COPY, /DELETE, /DIFFERENCE, /FILESYNC, /FRESHEN, /GROW, /MOVE, /UPDATE,",
1758 " /ADJUST_OFFSETS, /FIX_ARCHIVE[={NORMAL|FULL}], /TEST[=UNZIP=cmd], /UNSFX,",
1759 " Modifiers include:",
1760 " /BATCH[=list_file], /BEFORE=creation_time, /COMMENTS[={ARCHIVE|FILES}],",
1761 " /EXCLUDE=(file_list), /EXLIST=file, /INCLUDE=(file_list), /INLIST=file,",
1762 " /LATEST, /OUTPUT=out_archive, /SINCE=creation_time, /TEMP_PATH=directory,",
1763 " /LOG_FILE=(FILE=log_file[,APPEND][,INFORMATIONAL]), /MUST_MATCH,",
1764 " /PATTERN_CASE={BLIND|SENSITIVE}, /NORECURSE|/RECURSE[={PATH|FILENAMES}],",
1765 " /STORE_TYPES=(type_list),",
1766 #if CRYPT
1767 "\
1768 /QUIET, /VERBOSE[={MORE|DEBUG}], /[NO]DIRNAMES, /JUNK, /ENCRYPT[=\"pwd\"],\
1769 ",
1770 #else /* !CRYPT */
1771 " /QUIET, /VERBOSE[={MORE|DEBUG}], /[NO]DIRNAMES, /JUNK,",
1772 #endif /* ?CRYPT */
1773 " /COMPRESSION = {BZIP2|DEFLATE|STORE}, /LEVEL=[0-9], /NOVMS|/VMS[=ALL],",
1774 " /STORE_TYPES=(type_list), /[NO]PRESERVE_CASE[=([NO]ODS{2|5}[,...])],",
1775 " /[NO]PKZIP, /[NO]KEEP_VERSION, /DOT_VERSION, /TRANSLATE_EOL[={LF|CRLF}],",
1776 " /DISPLAY=([BYTES][,COUNTS][,DOTS=mb_per_dot][,GLOBALDOTS][,USIZE]",
1777 " [,VOLUME]), /DESCRIPTORS, /[NO]EXTRA_FIELDS, /ZIP64,",
1778 #ifdef S_IFLNK
1779 " /SPLIT = (SIZE=ssize [,BELL] [,PAUSE] [,VERBOSE]), /SYMLINKS"
1780 #else /* S_IFLNK */
1781 " /SPLIT = (SIZE=ssize [,BELL] [,PAUSE] [,VERBOSE])"
1782 #endif /* S_IFLNK [else] */
1783 };
1784
1785 if (!show_VMSCLI_help) {
1786 help();
1787 return;
1788 }
1789
1790 for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
1791 {
1792 printf(copyright[i], "zip");
1793 putchar('\n');
1794 }
1795 for (i = 0; i < sizeof(text)/sizeof(char *); i++)
1796 {
1797 printf(text[i], VERSION, REVDATE);
1798 putchar('\n');
1799 }
1800 } /* end function VMSCLI_help() */
1801
1802 #endif /* !TEST */
1803