1/*
2  zipcloak.c - Zip 3
3
4  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.
5
6  See the accompanying file LICENSE, version 2007-Mar-4 or later
7  (the contents of which are also included in zip.h) for terms of use.
8  If, for some reason, all these files are missing, the Info-ZIP license
9  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
10*/
11/*
12   This code was originally written in Europe and could be freely distributed
13   from any country except the U.S.A. If this code was imported into the U.S.A,
14   it could not be re-exported from the U.S.A to another country. (This
15   restriction might seem curious but this is what US law required.)
16
17   Now this code can be freely exported and imported.  See README.CR.
18 */
19#define __ZIPCLOAK_C
20
21#ifndef UTIL
22# define UTIL
23#endif
24#include "zip.h"
25#define DEFCPYRT        /* main module: enable copyright string defines! */
26#include "revision.h"
27#include "crc32.h"
28#include "crypt.h"
29#include "ttyio.h"
30#include <signal.h>
31#ifndef NO_STDLIB_H
32#  include <stdlib.h>
33#endif
34
35#if CRYPT       /* defined (as TRUE or FALSE) in crypt.h */
36
37int main OF((int argc, char **argv));
38
39local void handler OF((int sig));
40local void license OF((void));
41local void help OF((void));
42local void version_info OF((void));
43
44/* Temporary zip file pointer */
45local FILE *tempzf;
46
47/* Pointer to CRC-32 table (used for decryption/encryption) */
48#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
49ZCONST ulg near *crc_32_tab;
50#else
51ZCONST uLongf *crc_32_tab;
52#endif
53
54int set_filetype(out_path)
55  char *out_path;
56{
57#ifdef __BEOS__
58  /* Set the filetype of the zipfile to "application/zip" */
59  setfiletype( out_path, "application/zip" );
60#endif
61
62#ifdef __ATHEOS__
63  /* Set the filetype of the zipfile to "application/x-zip" */
64  setfiletype(out_path, "application/x-zip");
65#endif
66
67#ifdef MACOS
68  /* Set the Creator/Type of the zipfile to 'IZip' and 'ZIP ' */
69  setfiletype(out_path, 'IZip', 'ZIP ');
70#endif
71
72#ifdef RISCOS
73  /* Set the filetype of the zipfile to &DDC */
74  setfiletype(out_path, 0xDDC);
75#endif
76  return ZE_OK;
77}
78
79/* rename a split
80 * A split has a tempfile name until it is closed, then
81 * here rename it as out_path the final name for the split.
82 */
83int rename_split(temp_name, out_path)
84  char *temp_name;
85  char *out_path;
86{
87  int r;
88  /* Replace old zip file with new zip file, leaving only the new one */
89  if ((r = replace(out_path, temp_name)) != ZE_OK)
90  {
91    zipwarn("new zip file left as: ", temp_name);
92    free((zvoid *)tempzip);
93    tempzip = NULL;
94    ZIPERR(r, "was replacing split file");
95  }
96  if (zip_attributes) {
97    setfileattr(out_path, zip_attributes);
98  }
99  return ZE_OK;
100}
101
102void zipmessage_nl(a, nl)
103ZCONST char *a;     /* message string to output */
104int nl;             /* 1 = add nl to end */
105/* If nl false, print a message to mesg without new line.
106   If nl true, print and add new line. */
107{
108  if (noisy) {
109    fprintf(mesg, "%s", a);
110    if (nl) {
111      fprintf(mesg, "\n");
112      mesg_line_started = 0;
113    } else {
114      mesg_line_started = 1;
115    }
116    fflush(mesg);
117  }
118}
119
120void zipmessage(a, b)
121ZCONST char *a, *b;     /* message strings juxtaposed in output */
122/* Print a message to mesg and flush.  Write new line first
123   if current line has output already. */
124{
125  if (noisy) {
126    if (mesg_line_started)
127      fprintf(mesg, "\n");
128    fprintf(mesg, "%s%s\n", a, b);
129    mesg_line_started = 0;
130    fflush(mesg);
131  }
132}
133
134/***********************************************************************
135 * Issue a message for the error, clean up files and memory, and exit.
136 */
137void ziperr(code, msg)
138    int code;               /* error code from the ZE_ class */
139    ZCONST char *msg;       /* message about how it happened */
140{
141    if (PERR(code)) perror("zipcloak error");
142    fprintf(mesg, "zipcloak error: %s (%s)\n", ZIPERRORS(code), msg);
143    if (tempzf != NULL) fclose(tempzf);
144    if (tempzip != NULL) {
145        destroy(tempzip);
146        free((zvoid *)tempzip);
147    }
148    if (zipfile != NULL) free((zvoid *)zipfile);
149    EXIT(code);
150}
151
152/***********************************************************************
153 * Print a warning message to mesg (usually stderr) and return.
154 */
155void zipwarn(msg1, msg2)
156    ZCONST char *msg1, *msg2;   /* message strings juxtaposed in output */
157{
158    fprintf(mesg, "zipcloak warning: %s%s\n", msg1, msg2);
159}
160
161
162/***********************************************************************
163 * Upon getting a user interrupt, turn echo back on for tty and abort
164 * cleanly using ziperr().
165 */
166local void handler(sig)
167    int sig;                  /* signal number (ignored) */
168{
169#if (!defined(MSDOS) && !defined(__human68k__) && !defined(RISCOS))
170    echon();
171    putc('\n', mesg);
172#endif
173    ziperr(ZE_ABORT +sig-sig, "aborting");
174    /* dummy usage of sig to avoid compiler warnings */
175}
176
177
178static ZCONST char *public[] = {
179"The encryption code of this program is not copyrighted and is",
180"put in the public domain. It was originally written in Europe",
181"and can be freely distributed in both source and object forms",
182"from any country, including the USA under License Exception",
183"TSU of the U.S. Export Administration Regulations (section",
184"740.13(e)) of 6 June 2002.  (Prior to January 2000, re-export",
185"from the US was a violation of US law.)"
186};
187
188/***********************************************************************
189 * Print license information to stdout.
190 */
191local void license()
192{
193    extent i;             /* counter for copyright array */
194
195    for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++) {
196        puts(swlicense[i]);
197    }
198    putchar('\n');
199    printf("Export notice:\n");
200    for (i = 0; i < sizeof(public)/sizeof(char *); i++) {
201        puts(public[i]);
202    }
203}
204
205
206static ZCONST char *help_info[] = {
207"",
208"ZipCloak %s (%s)",
209#ifdef VM_CMS
210"Usage:  zipcloak [-dq] [-b fm] zipfile",
211#else
212"Usage:  zipcloak [-dq] [-b path] zipfile",
213#endif
214"  the default action is to encrypt all unencrypted entries in the zip file",
215"",
216"  -d  --decrypt      decrypt encrypted entries (copy if given wrong password)",
217#ifdef VM_CMS
218"  -b  --temp-mode    use \"fm\" as the filemode for the temporary zip file",
219#else
220"  -b  --temp-path    use \"path\" for the temporary zip file",
221#endif
222"  -O  --output-file  write output to new zip file",
223"  -q  --quiet        quiet operation, suppress some informational messages",
224"  -h  --help         show this help",
225"  -v  --version      show version info",
226"  -L  --license      show software license"
227  };
228
229/***********************************************************************
230 * Print help (along with license info) to stdout.
231 */
232local void help()
233{
234    extent i;             /* counter for help array */
235
236    for (i = 0; i < sizeof(help_info)/sizeof(char *); i++) {
237        printf(help_info[i], VERSION, REVDATE);
238        putchar('\n');
239    }
240}
241
242
243local void version_info()
244/* Print verbose info about program version and compile time options
245   to stdout. */
246{
247  extent i;             /* counter in text arrays */
248
249  /* Options info array */
250  static ZCONST char *comp_opts[] = {
251#ifdef DEBUG
252    "DEBUG",
253#endif
254#if CRYPT && defined(PASSWD_FROM_STDIN)
255    "PASSWD_FROM_STDIN",
256#endif /* CRYPT && PASSWD_FROM_STDIN */
257    NULL
258  };
259
260  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
261  {
262    printf(copyright[i], "zipcloak");
263    putchar('\n');
264  }
265  putchar('\n');
266
267  for (i = 0; i < sizeof(versinfolines)/sizeof(char *); i++)
268  {
269    printf(versinfolines[i], "ZipCloak", VERSION, REVDATE);
270    putchar('\n');
271  }
272
273  version_local();
274
275  puts("ZipCloak special compilation options:");
276  for (i = 0; (int)i < (int)(sizeof(comp_opts)/sizeof(char *) - 1); i++)
277  {
278    printf("\t%s\n",comp_opts[i]);
279  }
280  printf("\t[encryption, version %d.%d%s of %s]\n",
281            CR_MAJORVER, CR_MINORVER, CR_BETA_VER, CR_VERSION_DATE);
282}
283
284/* options for zipcloak - 3/5/2004 EG */
285struct option_struct far options[] = {
286  /* short longopt        value_type        negatable        ID    name */
287#ifdef VM_CMS
288    {"b",  "temp-mode",   o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'b',  "temp file mode"},
289#else
290    {"b",  "temp-path",   o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'b',  "path for temp file"},
291#endif
292    {"d",  "decrypt",     o_NO_VALUE,       o_NOT_NEGATABLE, 'd',  "decrypt"},
293    {"h",  "help",        o_NO_VALUE,       o_NOT_NEGATABLE, 'h',  "help"},
294    {"L",  "license",     o_NO_VALUE,       o_NOT_NEGATABLE, 'L',  "license"},
295    {"l",  "",            o_NO_VALUE,       o_NOT_NEGATABLE, 'L',  "license"},
296    {"O",  "output-file", o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'O',  "output to new archive"},
297    {"v",  "version",     o_NO_VALUE,       o_NOT_NEGATABLE, 'v',  "version"},
298    /* the end of the list */
299    {NULL, NULL,          o_NO_VALUE,       o_NOT_NEGATABLE, 0,    NULL} /* end has option_ID = 0 */
300  };
301
302
303/***********************************************************************
304 * Encrypt or decrypt all of the entries in a zip file.  See the command
305 * help in help() above.
306 */
307
308int main(argc, argv)
309    int argc;                   /* number of tokens in command line */
310    char **argv;                /* command line tokens */
311{
312    int attr;                   /* attributes of zip file */
313    zoff_t start_offset;        /* start of central directory */
314    int decrypt;                /* decryption flag */
315    int temp_path;              /* 1 if next argument is path for temp files */
316    char passwd[IZ_PWLEN+1];    /* password for encryption or decryption */
317    char verify[IZ_PWLEN+1];    /* password for encryption or decryption */
318#if 0
319    char *q;                    /* steps through option arguments */
320    int r;                      /* arg counter */
321#endif
322    int res;                    /* result code */
323    zoff_t length;              /* length of central directory */
324    FILE *inzip, *outzip;       /* input and output zip files */
325    struct zlist far *z;        /* steps through zfiles linked list */
326    /* used by get_option */
327    unsigned long option; /* option ID returned by get_option */
328    int argcnt = 0;       /* current argcnt in args */
329    int argnum = 0;       /* arg number */
330    int optchar = 0;      /* option state */
331    char *value = NULL;   /* non-option arg, option value or NULL */
332    int negated = 0;      /* 1 = option negated */
333    int fna = 0;          /* current first non-opt arg */
334    int optnum = 0;       /* index in table */
335
336    char **args;               /* copy of argv that can be freed */
337
338#ifdef THEOS
339    setlocale(LC_CTYPE, "I");
340#endif
341
342#ifdef UNICODE_SUPPORT
343# ifdef UNIX
344  /* For Unix, set the locale to UTF-8.  Any UTF-8 locale is
345     OK and they should all be the same.  This allows seeing,
346     writing, and displaying (if the fonts are loaded) all
347     characters in UTF-8. */
348  {
349    char *loc;
350
351    /*
352      loc = setlocale(LC_CTYPE, NULL);
353      printf("  Initial language locale = '%s'\n", loc);
354    */
355
356    loc = setlocale(LC_CTYPE, "en_US.UTF-8");
357
358    /*
359      printf("langinfo %s\n", nl_langinfo(CODESET));
360    */
361
362    if (loc != NULL) {
363      /* using UTF-8 character set so can set UTF-8 GPBF bit 11 */
364      using_utf8 = 1;
365      /*
366        printf("  Locale set to %s\n", loc);
367      */
368    } else {
369      /*
370        printf("  Could not set Unicode UTF-8 locale\n");
371      */
372    }
373  }
374# endif
375#endif
376
377    /* If no args, show help */
378    if (argc == 1) {
379        help();
380        EXIT(ZE_OK);
381    }
382
383    /* Informational messages are written to stdout. */
384    mesg = stdout;
385
386    init_upper();               /* build case map table */
387
388    crc_32_tab = get_crc_table();
389                                /* initialize crc table for crypt */
390
391    /* Go through args */
392    zipfile = tempzip = NULL;
393    tempzf = NULL;
394#ifdef SIGINT
395    signal(SIGINT, handler);
396#endif
397#ifdef SIGTERM                  /* Some don't have SIGTERM */
398    signal(SIGTERM, handler);
399#endif
400#ifdef SIGABRT
401    signal(SIGABRT, handler);
402#endif
403#ifdef SIGBREAK
404    signal(SIGBREAK, handler);
405#endif
406#ifdef SIGBUS
407    signal(SIGBUS, handler);
408#endif
409#ifdef SIGILL
410    signal(SIGILL, handler);
411#endif
412#ifdef SIGSEGV
413    signal(SIGSEGV, handler);
414#endif
415    temp_path = decrypt = 0;
416#if 0
417    /* old command line */
418    for (r = 1; r < argc; r++) {
419        if (*argv[r] == '-') {
420            if (!argv[r][1]) ziperr(ZE_PARMS, "zip file cannot be stdin");
421            for (q = argv[r]+1; *q; q++) {
422                switch (*q) {
423                case 'b':   /* Specify path for temporary file */
424                    if (temp_path) {
425                        ziperr(ZE_PARMS, "use -b before zip file name");
426                    }
427                    temp_path = 1;          /* Next non-option is path */
428                    break;
429                case 'd':
430                    decrypt = 1;  break;
431                case 'h':   /* Show help */
432                    help();
433                    EXIT(ZE_OK);
434                case 'l': case 'L':  /* Show copyright and disclaimer */
435                    license();
436                    EXIT(ZE_OK);
437                case 'q':   /* Quiet operation, suppress info messages */
438                    noisy = 0;  break;
439                case 'v':   /* Show version info */
440                    version_info();
441                    EXIT(ZE_OK);
442                default:
443                    ziperr(ZE_PARMS, "unknown option");
444                } /* switch */
445            } /* for */
446
447        } else if (temp_path == 0) {
448            if (zipfile != NULL) {
449                ziperr(ZE_PARMS, "can only specify one zip file");
450
451            } else if ((zipfile = ziptyp(argv[r])) == NULL) {
452                ziperr(ZE_MEM, "was processing arguments");
453            }
454        } else {
455            tempath = argv[r];
456            temp_path = 0;
457        } /* if */
458    } /* for */
459
460#else
461
462    /* new command line */
463
464    zipfile = NULL;
465    out_path = NULL;
466
467    /* make copy of args that can use with insert_arg() */
468    args = copy_args(argv, 0);
469
470    /*
471    -------------------------------------------
472    Process command line using get_option
473    -------------------------------------------
474
475    Each call to get_option() returns either a command
476    line option and possible value or a non-option argument.
477    Arguments are permuted so that all options (-r, -b temp)
478    are returned before non-option arguments (zipfile).
479    Returns 0 when nothing left to read.
480    */
481
482    /* set argnum = 0 on first call to init get_option */
483    argnum = 0;
484
485    /* get_option returns the option ID and updates parameters:
486           args    - usually same as argv if no argument file support
487           argcnt  - current argc for args
488           value   - char* to value (free() when done with it) or NULL if no value
489           negated - option was negated with trailing -
490    */
491
492    while ((option = get_option(&args, &argcnt, &argnum,
493                                &optchar, &value, &negated,
494                                &fna, &optnum, 0)))
495    {
496      switch (option)
497      {
498        case 'b':   /* Specify path for temporary file */
499          if (temp_path) {
500            ziperr(ZE_PARMS, "more than one temp_path");
501          }
502          temp_path = 1;
503          tempath = value;
504          break;
505        case 'd':
506          decrypt = 1;  break;
507        case 'h':   /* Show help */
508          help();
509          EXIT(ZE_OK);
510        case 'l': case 'L':  /* Show copyright and disclaimer */
511          license();
512          EXIT(ZE_OK);
513        case 'O':   /* Output to new zip file instead of updating original zip file */
514          if ((out_path = ziptyp(value)) == NULL) {
515            ziperr(ZE_MEM, "was processing arguments");
516          }
517          free(value);
518          break;
519        case 'q':   /* Quiet operation, suppress info messages */
520          noisy = 0;  break;
521        case 'v':   /* Show version info */
522          version_info();
523          EXIT(ZE_OK);
524        case o_NON_OPTION_ARG:
525          /* not an option */
526          /* no more options as permuting */
527          /* just dash also ends up here */
528
529          if (strcmp(value, "-") == 0) {
530            ziperr(ZE_PARMS, "zip file cannot be stdin");
531          } else if (zipfile != NULL) {
532            ziperr(ZE_PARMS, "can only specify one zip file");
533          }
534
535          if ((zipfile = ziptyp(value)) == NULL) {
536            ziperr(ZE_MEM, "was processing arguments");
537          }
538          free(value);
539          break;
540
541        default:
542          ziperr(ZE_PARMS, "unknown option");
543      }
544    }
545
546    free_args(args);
547
548#endif
549
550    if (zipfile == NULL) ziperr(ZE_PARMS, "need to specify zip file");
551
552    /* in_path is the input zip file */
553    if ((in_path = malloc(strlen(zipfile) + 1)) == NULL) {
554      ziperr(ZE_MEM, "input");
555    }
556    strcpy(in_path, zipfile);
557
558    /* out_path defaults to in_path */
559    if (out_path == NULL) {
560      if ((out_path = malloc(strlen(zipfile) + 1)) == NULL) {
561        ziperr(ZE_MEM, "output");
562      }
563      strcpy(out_path, zipfile);
564    }
565
566    /* Read zip file */
567    if ((res = readzipfile()) != ZE_OK) ziperr(res, zipfile);
568    if (zfiles == NULL) ziperr(ZE_NAME, zipfile);
569
570    /* Check for something to do */
571    for (z = zfiles; z != NULL; z = z->nxt) {
572        if (decrypt ? z->flg & 1 : !(z->flg & 1)) break;
573    }
574    if (z == NULL) {
575        ziperr(ZE_NONE, decrypt ? "no encrypted files"
576                       : "all files encrypted already");
577    }
578
579    /* Before we get carried away, make sure zip file is writeable */
580    if ((inzip = fopen(zipfile, "a")) == NULL) ziperr(ZE_CREAT, zipfile);
581    fclose(inzip);
582    attr = getfileattr(zipfile);
583
584    /* Open output zip file for writing */
585#if defined(UNIX) && !defined(NO_MKSTEMP)
586    {
587      int yd;
588      int i;
589
590      /* use mkstemp to avoid race condition and compiler warning */
591
592      if (tempath != NULL)
593      {
594        /* if -b used to set temp file dir use that for split temp */
595        if ((tempzip = malloc(strlen(tempath) + 12)) == NULL) {
596          ZIPERR(ZE_MEM, "allocating temp filename");
597        }
598        strcpy(tempzip, tempath);
599        if (lastchar(tempzip) != '/')
600          strcat(tempzip, "/");
601      }
602      else
603      {
604        /* create path by stripping name and appending template */
605        if ((tempzip = malloc(strlen(zipfile) + 12)) == NULL) {
606        ZIPERR(ZE_MEM, "allocating temp filename");
607        }
608        strcpy(tempzip, zipfile);
609        for(i = strlen(tempzip); i > 0; i--) {
610          if (tempzip[i - 1] == '/')
611            break;
612        }
613        tempzip[i] = '\0';
614      }
615      strcat(tempzip, "ziXXXXXX");
616
617      if ((yd = mkstemp(tempzip)) == EOF) {
618        ZIPERR(ZE_TEMP, tempzip);
619      }
620      if ((y = tempzf = outzip = fdopen(yd, FOPW_TMP)) == NULL) {
621        ZIPERR(ZE_TEMP, tempzip);
622      }
623    }
624#else
625    if ((y = tempzf = outzip = fopen(tempzip = tempname(zipfile), FOPW)) == NULL) {
626        ziperr(ZE_TEMP, tempzip);
627    }
628#endif
629
630    /* Get password */
631    if (getp("Enter password: ", passwd, IZ_PWLEN+1) == NULL)
632        ziperr(ZE_PARMS,
633               "stderr is not a tty (you may never see this message!)");
634
635    if (decrypt == 0) {
636        if (getp("Verify password: ", verify, IZ_PWLEN+1) == NULL)
637               ziperr(ZE_PARMS,
638                      "stderr is not a tty (you may never see this message!)");
639
640        if (strcmp(passwd, verify))
641               ziperr(ZE_PARMS, "password verification failed");
642
643        if (*passwd == '\0')
644               ziperr(ZE_PARMS, "zero length password not allowed");
645    }
646
647    /* Open input zip file again, copy preamble if any */
648    if ((in_file = fopen(zipfile, FOPR)) == NULL) ziperr(ZE_NAME, zipfile);
649
650    if (zipbeg && (res = bfcopy(zipbeg)) != ZE_OK)
651    {
652        ziperr(res, res == ZE_TEMP ? tempzip : zipfile);
653    }
654    tempzn = zipbeg;
655
656    /* Go through local entries, copying, encrypting, or decrypting */
657    for (z = zfiles; z != NULL; z = z->nxt) {
658        if (decrypt && (z->flg & 1)) {
659            printf("decrypting: %s", z->zname);
660            fflush(stdout);
661            if ((res = zipbare(z, passwd)) != ZE_OK)
662            {
663                if (res != ZE_MISS) ziperr(res, "was decrypting an entry");
664                printf(" (wrong password--just copying)");
665                fflush(stdout);
666            }
667            putchar('\n');
668
669        } else if ((!decrypt) && !(z->flg & 1)) {
670            printf("encrypting: %s\n", z->zname);
671            fflush(stdout);
672            if ((res = zipcloak(z, passwd)) != ZE_OK)
673            {
674                ziperr(res, "was encrypting an entry");
675            }
676        } else {
677            printf("   copying: %s\n", z->zname);
678            fflush(stdout);
679            if ((res = zipcopy(z)) != ZE_OK)
680            {
681                ziperr(res, "was copying an entry");
682            }
683        } /* if */
684    } /* for */
685
686    fclose(in_file);
687
688
689    /* Write central directory and end of central directory */
690
691    /* get start of central */
692    if ((start_offset = zftello(outzip)) == (zoff_t)-1)
693        ziperr(ZE_TEMP, tempzip);
694
695    for (z = zfiles; z != NULL; z = z->nxt) {
696        if ((res = putcentral(z)) != ZE_OK) ziperr(res, tempzip);
697    }
698
699    /* get end of central */
700    if ((length = zftello(outzip)) == (zoff_t)-1)
701        ziperr(ZE_TEMP, tempzip);
702
703    length -= start_offset;               /* compute length of central */
704    if ((res = putend((zoff_t)zcount, length, start_offset, zcomlen,
705                      zcomment)) != ZE_OK) {
706        ziperr(res, tempzip);
707    }
708    tempzf = NULL;
709    if (fclose(outzip)) ziperr(ZE_TEMP, tempzip);
710    if ((res = replace(out_path, tempzip)) != ZE_OK) {
711        zipwarn("new zip file left as: ", tempzip);
712        free((zvoid *)tempzip);
713        tempzip = NULL;
714        ziperr(res, "was replacing the original zip file");
715    }
716    free((zvoid *)tempzip);
717    tempzip = NULL;
718    setfileattr(zipfile, attr);
719#ifdef RISCOS
720    /* Set the filetype of the zipfile to &DDC */
721    setfiletype(zipfile, 0xDDC);
722#endif
723    free((zvoid *)in_path);
724    free((zvoid *)out_path);
725
726    free((zvoid *)zipfile);
727    zipfile = NULL;
728
729    /* Done! */
730    RETURN(0);
731}
732#else /* !CRYPT */
733
734
735/* below is only used if crypt is not enabled */
736
737struct option_struct far options[] = {
738  /* short longopt        value_type        negatable        ID    name */
739    {"h",  "help",        o_NO_VALUE,       o_NOT_NEGATABLE, 'h',  "help"},
740    /* the end of the list */
741    {NULL, NULL,          o_NO_VALUE,       o_NOT_NEGATABLE, 0,    NULL} /* end has option_ID = 0 */
742  };
743
744
745int main OF((void));
746
747void zipwarn(msg1, msg2)
748ZCONST char  *msg1, *msg2;
749{
750    /* Tell picky compilers to shut up about unused variables */
751    msg1 = msg1; msg2 = msg2;
752}
753
754void ziperr(c, h)
755int  c;
756ZCONST char *h;
757{
758    /* Tell picky compilers to shut up about unused variables */
759    c = c; h = h;
760}
761
762int main()
763{
764    fprintf(mesg, "\
765This version of ZipCloak does not support encryption.  Get the current Zip\n\
766source distribution and recompile ZipCloak after you have added an option to\n\
767define the symbol USE_CRYPT to the C compiler's command arguments.\n");
768    RETURN(1);
769}
770
771#endif /* ?CRYPT */
772