Annotation of pgp/src/pgp.c, revision 1.1.1.10

1.1.1.10! root        1: /* #define TEMP_VERSION /* if defined, temporary experimental
        !             2:                            version of PGP */
        !             3: /* pgp.c -- main module for PGP.
        !             4:    PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
        !             5: 
        !             6:    Synopsis:  PGP uses public-key encryption to protect E-mail. 
        !             7:    Communicate securely with people you've never met, with no secure
        !             8:    channels needed for prior exchange of keys.  PGP is well featured and
        !             9:    fast, with sophisticated key management, digital signatures, data
        !            10:    compression, and good ergonomic design.
        !            11: 
        !            12:    The original PGP version 1.0 was written by Philip Zimmermann, of
        !            13:    Phil's Pretty Good(tm) Software.  Many parts of later versions of 
        !            14:    PGP were developed by an international collaborative effort, 
        !            15:    involving a number of contributors, including major efforts by:
        !            16:    Branko Lankester <[email protected]>
        !            17:    Hal Finney <[email protected]>
        !            18:    Peter Gutmann <[email protected]>
        !            19:    Other contributors who ported or translated or otherwise helped include:
        !            20:    Jean-loup Gailly in France
        !            21:    Hugh Kennedy in Germany
        !            22:    Lutz Frank in Germany
        !            23:    Cor Bosman in The Netherlands
        !            24:    Felipe Rodriquez Svensson in The Netherlands
        !            25:    Armando Ramos in Spain
        !            26:    Miguel Angel Gallardo Ortiz in Spain
        !            27:    Harry Bush and Maris Gabalins in Latvia
        !            28:    Zygimantas Cepaitis in Lithuania
        !            29:    Alexander Smishlajev
        !            30:    Peter Suchkow and Andrew Chernov in Russia
        !            31:    David Vincenzetti in Italy
        !            32:    ...and others.
        !            33: 
        !            34: 
        !            35:    (c) Copyright 1990-1996 by Philip Zimmermann.  All rights reserved.
        !            36:    The author assumes no liability for damages resulting from the use
        !            37:    of this software, even if the damage results from defects in this
        !            38:    software.  No warranty is expressed or implied.
        !            39: 
        !            40:    Note that while most PGP source modules bear Philip Zimmermann's
        !            41:    copyright notice, many of them have been revised or entirely written
        !            42:    by contributors who frequently failed to put their names in their
        !            43:    code.  Code that has been incorporated into PGP from other authors
        !            44:    was either originally published in the public domain or is used with
        !            45:    permission from the various authors.
        !            46: 
        !            47:    PGP is available for free to the public under certain restrictions.
        !            48:    See the PGP User's Guide (included in the release package) for
        !            49:    important information about licensing, patent restrictions on
        !            50:    certain algorithms, trademarks, copyrights, and export controls.
        !            51: 
        !            52: 
        !            53:    Philip Zimmermann may be reached at:
        !            54:    Boulder Software Engineering
        !            55:    3021 Eleventh Street
        !            56:    Boulder, Colorado 80304  USA
        !            57:    (303) 541-0140  (voice or FAX)
        !            58:    email:  [email protected]
        !            59: 
        !            60: 
        !            61:    PGP will run on MSDOS, Sun Unix, VAX/VMS, Ultrix, Atari ST, 
        !            62:    Commodore Amiga, and OS/2.  Note:  Don't try to do anything with 
        !            63:    this source code without looking at the PGP User's Guide.
        !            64: 
        !            65:    PGP combines the convenience of the Rivest-Shamir-Adleman (RSA)
        !            66:    public key cryptosystem with the speed of fast conventional
        !            67:    cryptographic algorithms, fast message digest algorithms, data
        !            68:    compression, and sophisticated key management.  And PGP performs 
        !            69:    the RSA functions faster than most other software implementations.  
        !            70:    PGP is RSA public key cryptography for the masses.
        !            71: 
        !            72:    Uses RSA Data Security, Inc. MD5 Message Digest Algorithm
        !            73:    as a hash for signatures.  Uses the ZIP algorithm for compression.
        !            74:    Uses the ETH IPES/IDEA algorithm for conventional encryption.
        !            75: 
        !            76:    PGP generally zeroes its used stack and memory areas before exiting.
        !            77:    This avoids leaving sensitive information in RAM where other users
        !            78:    could find it later.  The RSA library and keygen routines also
        !            79:    sanitize their own stack areas.  This stack sanitizing has not been
        !            80:    checked out under all the error exit conditions, when routines exit
        !            81:    abnormally.  Also, we must find a way to clear the C I/O library
        !            82:    file buffers, the disk buffers, and cache buffers.
        !            83: 
        !            84:    Revisions:
        !            85:    Version 1.0 -  5 Jun 91
        !            86:    Version 1.4 - 19 Jan 92
        !            87:    Version 1.5 - 12 Feb 92
        !            88:    Version 1.6 - 24 Feb 92
        !            89:    Version 1.7 - 29 Mar 92
        !            90:    Version 1.8 - 23 May 92
        !            91:    Version 2.0 -  2 Sep 92
        !            92:    Version 2.1 -  6 Dec 92
        !            93:    Version 2.2 -  6 Mar 93
        !            94:    Version 2.3 - 13 Jun 93
        !            95:    Version 2.3a-  1 Jul 93
        !            96:    Version 2.4 -  6 Nov 93
        !            97:    Version 2.5 -  5 May 94
        !            98:    Version 2.6 - 22 May 94
        !            99:    Version 2.6.1 - 29 Aug 94
        !           100:    Version 2.6.2 - 11 Oct 94
        !           101:    Version 2.6.2i - 7 May 95
        !           102:    Version 2.6.3(i) - 18 Jan 96
        !           103: 
        !           104:  */
        !           105: 
        !           106: 
        !           107: #include <ctype.h>
        !           108: #ifndef AMIGA
        !           109: #include <signal.h>
        !           110: #endif
        !           111: #include <stdio.h>
        !           112: #include <stdlib.h>
        !           113: #include <string.h>
        !           114: 
        !           115: /* Hack to get strncasecmp to work */
        !           116: #if defined(WIN32)
        !           117: #define strncasecmp _strnicmp
        !           118: #elif defined(AMIGA) || defined(OS2) || defined(__PUREC__)
        !           119: #define strncasecmp strnicmp
        !           120: #elif defined(MSDOS)
        !           121: #  if defined(__TURBOC__)
        !           122: #  define strncasecmp strncmpi
        !           123: #  else /* MSC */
        !           124: #  define strncasecmp strnicmp
        !           125: #  endif
        !           126: #endif
        !           127: 
        !           128: #ifdef UNIX
        !           129: #include <sys/stat.h>
        !           130: #endif
        !           131: 
        !           132: #include "system.h"
        !           133: #include "mpilib.h"
        !           134: #include "random.h"
        !           135: #include "crypto.h"
        !           136: #include "fileio.h"
        !           137: #include "keymgmt.h"
        !           138: #include "language.h"
        !           139: #include "pgp.h"
        !           140: #include "exitpgp.h"
        !           141: #include "charset.h"
        !           142: #include "getopt.h"
        !           143: #include "config.h"
        !           144: #include "keymaint.h"
        !           145: #include "keyadd.h"
        !           146: #include "rsaglue.h"
        !           147: #include "noise.h"
        !           148: 
        !           149: #ifdef MACTC5
        !           150: #include "Macutil.h"
        !           151: #include "Macutil2.h"
        !           152: #include "Macutil3.h"
        !           153: #include "Macutil4.h"
        !           154: #include "Macbinary.h"
        !           155: #include "Binhex.h"
        !           156: #include "MacPGP.h"
        !           157: #include "mystr.h"
        !           158: void AddOutputFiles(char *filepath);
        !           159: void ReInitKeyMaint(void);
        !           160: extern char appPathName[];
        !           161: void           ReInitGlobals(void);
        !           162: extern int level,method;
        !           163: extern Boolean explicit_plainfile;
        !           164: extern long infile_line;
        !           165: extern int eofonce;
        !           166: extern boolean savedwashed;
        !           167: extern char *special;
        !           168: char *Outputfile = NULL;
        !           169: void check_expiration_date(void);
        !           170: #define BEST -1
        !           171: #define strncasecmp strncmpi
        !           172: #define exit Exit
        !           173: void Exit(int x);
        !           174: #endif
        !           175: 
        !           176: #ifdef  M_XENIX
        !           177: char *strstr();
        !           178: long time();
        !           179: #endif
        !           180: 
        !           181: #ifdef MSDOS
        !           182: #ifdef __ZTC__                 /* Extend stack for Zortech C */
        !           183: unsigned _stack_ = 24 * 1024;
        !           184: #endif
        !           185: #ifdef __TURBOC__
        !           186: unsigned _stklen = 24 * 1024;
        !           187: #endif
        !           188: #endif
        !           189: #define        STACK_WIPE      4096
        !           190: 
        !           191: #ifdef AMIGA
        !           192: #ifdef __SASC_60
        !           193: /* Let the compiler allocate us an appropriate stack. */
        !           194: extern long __stack = 32768L;
        !           195: #endif
        !           196: 
        !           197:  /* Add the appropriate AmigaOS version string, depending on the
        !           198:   * compiler flags.
        !           199:   */
        !           200: #ifdef USA
        !           201: static const char __DOSVer[] = "$VER: PGP 2.6.3 (18.01.96)"
        !           202: #  ifdef _M68020
        !           203:         " Amiga 68020 version by Rob Knop <[email protected]>";
        !           204: #  else
        !           205:         " Amiga 68000 version by Rob Knop <[email protected]>";
        !           206: #  endif
        !           207: #else
        !           208: static const char __DOSVer[] = "$VER: PGP 2.6.3i (18.01.96)"
        !           209: #  ifdef _M68020
        !           210:         " Amiga 68020 version by Peter Simons <[email protected]>";
        !           211: #  else
        !           212:         " Amiga 68000 version by Peter Simons <[email protected]>";
        !           213: #  endif
        !           214: #endif /* USA */
        !           215: #endif /* AMIGA */
        !           216: 
        !           217: /* Global filenames and system-wide file extensions... */
        !           218: #ifdef USA
        !           219: char rel_version[] = _LANG("2.6.3");   /* release version */
        !           220: #else
        !           221: char rel_version[] = _LANG("2.6.3i");  /* release version */
        !           222: #endif
        !           223: char rel_date[] = "1996-01-18";                /* release date */
        !           224: char PGP_EXTENSION[] = ".pgp";
        !           225: char ASC_EXTENSION[] = ".asc";
        !           226: char SIG_EXTENSION[] = ".sig";
        !           227: char BAK_EXTENSION[] = ".bak";
        !           228: static char HLP_EXTENSION[] = ".hlp";
        !           229: char CONSOLE_FILENAME[] = "_CONSOLE";
        !           230: #ifdef MACTC5
        !           231: char HELP_FILENAME[256] = "pgp.hlp";
        !           232: #else
        !           233: static char HELP_FILENAME[] = "pgp.hlp";
        !           234: #endif
        !           235: 
        !           236: /* These files use the environmental variable PGPPATH as a default path: */
        !           237: char globalPubringName[MAX_PATH];
        !           238: char globalSecringName[MAX_PATH];
        !           239: char globalRandseedName[MAX_PATH];
        !           240: char globalCommentString[128];
        !           241: 
        !           242: /* Flags which are global across the driver code files */
        !           243: boolean verbose = FALSE;       /* -l option: display maximum information */
        !           244: FILE *pgpout;                  /* Place for routine messages */
        !           245: 
        !           246: static void usage(void);
        !           247: static void key_usage(void);
        !           248: static void arg_error(void);
        !           249: static void initsigs(void);
        !           250: static int do_keyopt(char);
        !           251: static int do_decrypt(char *);
        !           252: static void do_armorfile(char *);
        !           253: char ** ParseRecipients(char **);
        !           254: void hashpass (char *keystring, int keylen, byte *hash);
        !           255: 
        !           256: /* Various compression signatures: PKZIP, Zoo, GIF, Arj, and HPACK.
        !           257:    Lha(rc) is handled specially in the code; it is missing from the
        !           258:    compressSig structure intentionally.  If more formats are added,
        !           259:    put them before lharc to keep the code consistent.
        !           260: 
        !           261:    27-Jun-95 [email protected] (Peter Simons)
        !           262:    Added support for lh5 archive as generated by Lha. Unfortunately,
        !           263:    Lha requires special treatment also. I inserted the check right
        !           264:    _before_ lharc, because lh5/lha is a special type of an lharc
        !           265:    archive.
        !           266:  */
        !           267: static char *compressSig[] =
        !           268: {"PK\03\04", "ZOO ", "GIF8", "\352\140",
        !           269:  "HPAK", "\037\213", "\037\235", "\032\013", "\032HP%"
        !           270:        /* lharc is special, must be last */ };
        !           271: static char *compressName[] =
        !           272: {"PKZIP", "Zoo", "GIF", "Arj",
        !           273:  "Hpack", "gzip", "compressed", "PAK", "Hyper",
        !           274:  "Lha", "Lharc"};
        !           275: static char *compressExt[] =
        !           276: {".zip", ".zoo", ".gif", ".arj",
        !           277:  ".hpk", ".gz", ".Z", ".pak", ".hyp",
        !           278:  ".lha", ".lzh"};
        !           279: 
        !           280: /* "\032\0??", "ARC", ".arc" */
        !           281: 
        !           282: /* Returns file signature type from a number of popular compression formats
        !           283:    or -1 if no match */
        !           284: int compressSignature(byte * header)
        !           285: {
        !           286:     int i;
        !           287: 
        !           288:     for (i = 0; i < sizeof(compressSig) / sizeof(*compressSig); i++)
        !           289:        if (!strncmp((char *) header, compressSig[i], strlen(compressSig[i])))
        !           290:            return i;
        !           291: 
        !           292:     /* Special check for lha files */
        !           293:     if (!strncmp((char *)header+2, "-lh5-", 5))
        !           294:       return i;
        !           295: 
        !           296:     /* Special check for lharc files */
        !           297:     if (header[2] == '-' && header[3] == 'l' &&
        !           298:        (header[4] == 'z' || header[4] == 'h') &&
        !           299:        header[6] == '-')
        !           300:        return i+1;
        !           301:     return -1;
        !           302: }                              /* compressSignature */
        !           303: 
        !           304: /* returns TRUE if file is likely to be compressible */
        !           305: static boolean file_compressible(char *filename)
        !           306: {
        !           307:     byte header[8];
        !           308:     get_header_info_from_file(filename, header, 8);
        !           309:     if (compressSignature(header) >= 0)
        !           310:        return FALSE;           /* probably not compressible */
        !           311:     return TRUE;               /* possibly compressible */
        !           312: }                              /* compressible */
        !           313: 
        !           314: 
        !           315: /* Possible error exit codes - not all of these are used.  Note that we
        !           316:    don't use the ANSI EXIT_SUCCESS and EXIT_FAILURE.  To make things
        !           317:    easier for compilers which don't support enum we use #defines */
        !           318: 
        !           319: #define EXIT_OK                                0
        !           320: #define INVALID_FILE_ERROR             1
        !           321: #define FILE_NOT_FOUND_ERROR           2
        !           322: #define UNKNOWN_FILE_ERROR             3
        !           323: #define NO_BATCH                       4
        !           324: #define BAD_ARG_ERROR                  5
        !           325: #define INTERRUPT                      6
        !           326: #define OUT_OF_MEM                     7
        !           327: 
        !           328: /* Keyring errors: Base value = 10 */
        !           329: #define KEYGEN_ERROR                   10
        !           330: #define NONEXIST_KEY_ERROR             11
        !           331: #define KEYRING_ADD_ERROR              12
        !           332: #define KEYRING_EXTRACT_ERROR          13
        !           333: #define KEYRING_EDIT_ERROR             14
        !           334: #define KEYRING_VIEW_ERROR             15
        !           335: #define KEYRING_REMOVE_ERROR           16
        !           336: #define KEYRING_CHECK_ERROR            17
        !           337: #define KEY_SIGNATURE_ERROR            18
        !           338: #define KEYSIG_REMOVE_ERROR            19
        !           339: 
        !           340: /* Encode errors: Base value = 20 */
        !           341: #define SIGNATURE_ERROR                        20
        !           342: #define RSA_ENCR_ERROR                 21
        !           343: #define ENCR_ERROR                     22
        !           344: #define COMPRESS_ERROR                 23
        !           345: 
        !           346: /* Decode errors: Base value = 30 */
        !           347: #define SIGNATURE_CHECK_ERROR          30
        !           348: #define RSA_DECR_ERROR                 31
        !           349: #define DECR_ERROR                     32
        !           350: #define DECOMPRESS_ERROR               33
        !           351: 
        !           352: 
        !           353: #ifdef SIGINT
        !           354: 
        !           355: /* This function is called if a BREAK signal is sent to the program.  In this
        !           356:    case we zap the temporary files.
        !           357:  */
        !           358: void breakHandler(int sig)
        !           359: {
        !           360: #ifdef UNIX
        !           361:     if (sig == SIGPIPE) {
        !           362:        signal(SIGPIPE, SIG_IGN);
        !           363:        exitPGP(INTERRUPT);
        !           364:     }
        !           365:     if (sig != SIGINT)
        !           366:        fprintf(stderr, "\nreceived signal %d\n", sig);
        !           367:     else
        !           368: #endif
        !           369:        fprintf(pgpout, LANG("\nStopped at user request\n"));
        !           370:     exitPGP(INTERRUPT);
        !           371: }
        !           372: #endif
        !           373: 
        !           374: /* Clears screen and homes the cursor. */
        !           375: static void clearscreen(void)
        !           376: {
        !           377:     fprintf(pgpout, "\n\033[0;0H\033[J\r           \r");  /* ANSI sequence. */
        !           378:     fflush(pgpout);
        !           379: }
        !           380: 
        !           381: /* We had to process the config file first to possibly select the 
        !           382:    foreign language to translate the sign-on line that follows... */
        !           383: static void signon_msg(void)
        !           384: {    
        !           385:     word32 tstamp;
        !           386:     /* display message only once to allow calling multiple times */
        !           387:     static boolean printed = FALSE;
        !           388: 
        !           389:     if (quietmode || printed)
        !           390:        return;
        !           391:     printed = TRUE;
        !           392:     fprintf(stderr,
        !           393: LANG("Pretty Good Privacy(tm) %s - Public-key encryption for the masses.\n"),
        !           394:            rel_version);
        !           395: #ifdef TEMP_VERSION
        !           396:     fputs(
        !           397: "Internal development version only - not for general release.\n", stderr);
        !           398: #endif
        !           399:     fputs(LANG("(c) 1990-96 Philip Zimmermann, Phil's Pretty Good Software."),
        !           400:     stderr);
        !           401:     fprintf(stderr, " %s\n",LANG(rel_date));
        !           402: #ifdef USA
        !           403:     fputs(LANG(signon_legalese), stderr);
        !           404: #endif
        !           405:     fputs(
        !           406: #ifdef USA
        !           407: LANG("Export of this software may be restricted by the U.S. government.\n"),
        !           408: #else
        !           409: LANG("International version - not for use in the USA. Does not use RSAREF.\n"),
        !           410: #endif
        !           411:          stderr);
        !           412: 
        !           413:     get_timestamp((byte *) & tstamp);  /* timestamp points to tstamp */
        !           414:     fprintf(pgpout, LANG("Current time: %s\n"), ctdate(&tstamp));
        !           415: }
        !           416: 
        !           417: 
        !           418: #ifdef TEMP_VERSION            /* temporary experimental version of PGP */
        !           419: #include <time.h>
        !           420: #define CREATION_DATE 0x30FE3640ul
        !           421:                                /* CREATION_DATE is
        !           422:                                   Thu Jan 18, 1996 1200 hours UTC */
        !           423: #define LIFESPAN       ((unsigned long) 60L * (unsigned long) 86400L)
        !           424:                                /* LIFESPAN is 60 days */
        !           425: 
        !           426: /* If this is an experimental version of PGP, cut its life short */
        !           427: void check_expiration_date(void)
        !           428: {
        !           429:     if (get_timestamp(NULL) > (CREATION_DATE + LIFESPAN)) {
        !           430:        fprintf(stderr,
        !           431:                "\n\007This experimental version of PGP has expired.\n");
        !           432:        exit(-1);               /* error exit */
        !           433:     }
        !           434: }                              /* check_expiration_date */
        !           435: #else                          /* no expiration date */
        !           436: #define check_expiration_date()        /* null statement */
        !           437: #endif                         /* TEMP_VERSION */
        !           438: 
        !           439: /* -f means act as a unix-style filter */
        !           440: /* -i means internalize extended file attribute information, only supported
        !           441:  *          between like (or very compatible) operating systems. */
        !           442: /* -l means show longer more descriptive diagnostic messages */
        !           443: /* -m means display plaintext output on screen, like unix "more" */
        !           444: /* -d means decrypt only, leaving inner signature wrapping intact */
        !           445: /* -t means treat as pure text and convert to canonical text format */
        !           446: 
        !           447: /* Used by getopt function... */
        !           448: #define OPTIONS "abcdefghiklmo:prstu:vwxz:ABCDEFGHIKLMO:PRSTU:VWX?"
        !           449: extern int optind;
        !           450: extern char *optarg;
        !           451: 
        !           452: #define INCLUDE_MARK "-@"
        !           453: #define INCLUDE_MARK_LEN sizeof(INCLUDE_MARK)-1        /* skip the \0 */
        !           454: 
        !           455: boolean emit_radix_64 = FALSE; /* set by config file */
        !           456: static boolean sign_flag = FALSE;
        !           457: boolean moreflag = FALSE;
        !           458: boolean filter_mode = FALSE;
        !           459: static boolean preserve_filename = FALSE;
        !           460: static boolean decrypt_only_flag = FALSE;
        !           461: static boolean de_armor_only = FALSE;
        !           462: static boolean strip_sig_flag = FALSE;
        !           463: boolean clear_signatures = TRUE;
        !           464: boolean strip_spaces;
        !           465: static boolean c_flag = FALSE;
        !           466: static boolean u_flag = FALSE;         /* Did I get my_name from -u? */
        !           467: boolean encrypt_to_self = FALSE; /* should I encrypt messages to myself? */
        !           468: boolean sign_new_userids = TRUE;
        !           469: boolean batchmode = FALSE;     /* if TRUE: don't ask questions */
        !           470: boolean quietmode = FALSE;
        !           471: boolean force_flag = FALSE;    /* overwrite existing file without asking */
        !           472: #ifdef VMS                     /* kludge for those stupid VMS variable-length
        !           473:                                   text records */
        !           474: char literal_mode = MODE_TEXT; /* MODE_TEXT or MODE_BINARY for literal
        !           475:                                   packet */
        !           476: #else                          /* not VMS */
        !           477: char literal_mode = MODE_BINARY; /* MODE_TEXT or MODE_BINARY for literal
        !           478:                                    packet */
        !           479: #endif                         /* not VMS */
        !           480: /* my_name is substring of default userid for secret key to make signatures */
        !           481: char my_name[256] = "\0";      /* null my_name means take first userid
        !           482:                                   in ring */
        !           483: boolean keepctx = FALSE;       /* TRUE means keep .ctx file on decrypt */
        !           484: /* Ask for each key separately if it should be added to the keyring */
        !           485: boolean interactive_add = FALSE;
        !           486: boolean compress_enabled = TRUE; /* attempt compression before encryption */
        !           487: long timeshift = 0L;           /* seconds from GMT timezone */
        !           488: int version_byte = VERSION_BYTE_NEW;
        !           489: boolean nomanual = 0;
        !           490: /* If non-zero, initialize file to this many random bytes */
        !           491: int makerandom = 0;
        !           492: 
        !           493: 
        !           494: static char *outputfile = NULL;
        !           495: #ifndef MACTC5
        !           496: static int errorLvl = EXIT_OK;
        !           497: #else
        !           498: int errorLvl = EXIT_OK;
        !           499: #endif
        !           500: static char mcguffin[256];     /* userid search tag */
        !           501: boolean signature_checked = FALSE;
        !           502: int checksig_pass = 0;
        !           503: boolean use_charset_header;
        !           504: char charset_header[16] = "";
        !           505: char plainfile[MAX_PATH];
        !           506: int myArgc = 2;
        !           507: char **myArgv;
        !           508: struct hashedpw *passwds = 0, *keypasswds = 0;
        !           509: static struct hashedpw **passwdstail = &passwds;
        !           510: 
        !           511: #ifdef MACTC5
        !           512: extern unsigned long PGPStart, WNECalls;
        !           513: 
        !           514: void ReInitGlobals()
        !           515: {
        !           516:        int i;
        !           517:     char scratch[64];
        !           518:     WNECalls = 0;
        !           519:     if (verbose)
        !           520:        PGPStart = TickCount();
        !           521:     else
        !           522:        PGPStart = 0;
        !           523:     Abort = FALSE;
        !           524:        BreakCntl = 0;
        !           525:        pgpout = stderr;
        !           526:     optind = 1;
        !           527:        errorLvl = EXIT_OK;
        !           528:     myArgc = 2;
        !           529:     myArgv = nil;
        !           530:     emit_radix_64 = FALSE;             /* set by config file */
        !           531:     sign_flag = FALSE;
        !           532:     moreflag = FALSE;
        !           533:     filter_mode = FALSE;
        !           534:     preserve_filename = FALSE;
        !           535:     decrypt_only_flag = FALSE;
        !           536:     de_armor_only = FALSE;
        !           537:     strip_sig_flag = FALSE;
        !           538:     u_flag = FALSE;
        !           539:        c_flag = FALSE;
        !           540:     signature_checked = FALSE;
        !           541:        literal_mode = MODE_BINARY;     /* MODE_TEXT or MODE_BINARY for literal packet */
        !           542:     errorLvl = EXIT_OK;
        !           543:     outputfile = Outputfile;
        !           544:     method = BEST;     /* one of BEST, DEFLATE (only), or STORE (only) */
        !           545:     level = 9;         /* 0=fastest compression, 9=best compression */
        !           546:     special = NULL;    /* List of special suffixes */
        !           547:     infile_line = 0;
        !           548:        eofonce = 0;
        !           549:        savedwashed = FALSE;
        !           550:        ReInitKeyMaint();
        !           551:        settmpdir(nil);
        !           552:        setoutdir(nil);
        !           553:        makerandom = 0;
        !           554:        if (xcli_opt[0]) {
        !           555:        if (argv[argc] == nil)
        !           556:                argv[argc] = malloc((size_t) 80);
        !           557:                if (argv[argc] == nil) {
        !           558:                        BailoutAlert(LANG("Out of memory"));
        !           559:                        ExitToShell();
        !           560:                }
        !           561:                strcpy(argv[argc], xcli_opt);
        !           562:                argc++;
        !           563:                fprintf(pgpout, "         %s\n", xcli_opt);
        !           564:        }
        !           565:        for (i = 0; i <= 63; i++)
        !           566:                scratch[i] = to_upper(xcli_opt[i]);
        !           567:        if (strcmp(xcli_opt, "+NOMANUAL=ON")==0) nomanual = true;
        !           568:        else nomanual = false;
        !           569:  }
        !           570: 
        !           571: int init_pgp()
        !           572: {
        !           573:        int err=0;
        !           574:        pgpout=stderr;
        !           575:        /* Process the config file first.  Any command-line arguments will
        !           576:           override the config file settings */
        !           577:        buildfilename( mcguffin, "config.txt");
        !           578:        if ( processConfigFile( mcguffin ) < 0 )
        !           579:                err=BAD_ARG_ERROR;
        !           580:        init_charset();
        !           581:        signon_msg();
        !           582:        g_armor_flag=emit_radix_64;
        !           583:        g_text_mode=(literal_mode == MODE_TEXT);
        !           584:        g_clear_signatures=clear_signatures;
        !           585:        PGPSetFinfo(globalRandseedName,'RSed','MPGP');
        !           586:        set_precision(MAX_UNIT_PRECISION);
        !           587:        return err;
        !           588: }
        !           589: 
        !           590: 
        !           591: void Exit(int x) {
        !           592: 
        !           593:        errorLvl = x;
        !           594:        if (myArgv)
        !           595:                free(myArgv);
        !           596:        if (mcguffins)
        !           597:                free(mcguffins);
        !           598:        mac_cleanup_tmpf();
        !           599:        longjmp(jmp_env,5);
        !           600: }
        !           601: 
        !           602: 
        !           603: int pgp_dispatch(int argc, char *argv[])
        !           604: {
        !           605:        int status, opt;
        !           606:        char *inputfile = NULL;
        !           607:        char **recipient = NULL;
        !           608: /*     char **mcguffins;   zigf made global so we can free */
        !           609:        boolean macbin_flag = FALSE;
        !           610: #else
        !           611: 
        !           612: int main(int argc, char *argv[])
        !           613: {
        !           614:     int status, opt;
        !           615:     char *inputfile = NULL;
        !           616:     char **recipient = NULL;
        !           617:     char **mcguffins;
        !           618: #endif /* MACTC5 */
        !           619:     char *workfile, *tempf;
        !           620:     boolean nestflag = FALSE;
        !           621:     boolean decrypt_mode = FALSE;
        !           622:     boolean wipeflag = FALSE;
        !           623:     boolean armor_flag = FALSE;        /* -a option */
        !           624:     boolean separate_signature = FALSE;
        !           625:     boolean keyflag = FALSE;
        !           626:     boolean encrypt_flag = FALSE;
        !           627:     boolean conventional_flag = FALSE;
        !           628:     boolean attempt_compression; /* attempt compression before encryption */
        !           629:     boolean output_stdout;     /* Output goes to stdout */
        !           630:     char *clearfile = NULL;
        !           631:     char *literal_file = NULL;
        !           632:     char literal_file_name[MAX_PATH];
        !           633:     char cipherfile[MAX_PATH];
        !           634:     char keychar = '\0';
        !           635:     char *p;
        !           636:     byte ctb;
        !           637:     struct hashedpw *hpw;
        !           638: 
        !           639:     /* Initial messages to stderr */
        !           640:     pgpout = stderr;
        !           641: 
        !           642: #ifdef MACTC5
        !           643:        ReInitGlobals();
        !           644: #endif
        !           645: #ifdef DEBUG1
        !           646:     verbose = TRUE;
        !           647: #endif
        !           648:     /* The various places one can get passwords from.
        !           649:      * We accumulate them all into two lists.  One is
        !           650:      * to try on keys only, and is stored in no particular
        !           651:      * order, while the other is of unknown purpose so
        !           652:      * far (they may be used for conventional encryption
        !           653:      * or decryption as well), and are kept in a specific
        !           654:      * order.  If any password in the general list is found
        !           655:      * to decode a key, it is moved to the key list.
        !           656:      * The general list is not grown after initialization,
        !           657:      * so the tail pointer is not used after this.
        !           658:      */
        !           659: 
        !           660: #ifndef MACTC5
        !           661:     if ((p = getenv("PGPPASS")) != NULL) {
        !           662:        hpw = xmalloc(sizeof(struct hashedpw));
        !           663:        hashpass(p, strlen(p), hpw->hash);
        !           664:        /* Add to linked list of key passwords */
        !           665:        hpw->next = keypasswds;
        !           666:        keypasswds = hpw;
        !           667:     }
        !           668:     /* The -z "password" option should be used instead of PGPPASS if
        !           669:      * the environment can be displayed with the ps command (eg. BSD).
        !           670:      * If the system does not allow overwriting of the command line
        !           671:      * argument list but if it has a "hidden" environment, PGPPASS
        !           672:      * should be used.
        !           673:      */
        !           674:     for (opt = 1; opt < argc; ++opt) {
        !           675:        p = argv[opt];
        !           676:        if (p[0] != '-' || p[1] != 'z')
        !           677:            continue;
        !           678:        /* Accept either "-zpassword" or "-z password" */
        !           679:        p += 2;
        !           680:        if (!*p)
        !           681:            p = argv[++opt];
        !           682:        /* p now points to password */
        !           683:        if (!p)
        !           684:            break;              /* End of arg list - ignore */
        !           685:        hpw = xmalloc(sizeof(struct hashedpw));
        !           686:        hashpass(p, strlen(p), hpw->hash);
        !           687:        /* Wipe password */
        !           688:        while (*p)
        !           689:            *p++ = ' ';
        !           690:        /* Add to tail of linked list of passwords */
        !           691:        hpw->next = 0;
        !           692:        *passwdstail = hpw;
        !           693:        passwdstail = &hpw->next;
        !           694:     }
        !           695:     /*
        !           696:      * If PGPPASSFD is set in the environment try to read the password
        !           697:      * from this file descriptor.  If you set PGPPASSFD to 0 pgp will
        !           698:      * use the first line read from stdin as password.
        !           699:      */
        !           700:     if ((p = getenv("PGPPASSFD")) != NULL) {
        !           701:        int passfd;
        !           702:        if (*p && (passfd = atoi(p)) >= 0) {
        !           703:            char pwbuf[256];
        !           704:            p = pwbuf;
        !           705:            while (read(passfd, p, 1) == 1 && *p != '\n')
        !           706:                ++p;
        !           707:            hpw = xmalloc(sizeof(struct hashedpw));
        !           708:            hashpass(pwbuf, p - pwbuf, hpw->hash);
        !           709:            memset(pwbuf, 0, p - pwbuf);
        !           710:            /* Add to tail of linked list of passwords */
        !           711:            hpw->next = 0;
        !           712:            *passwdstail = hpw;
        !           713:            passwdstail = &hpw->next;
        !           714:        }
        !           715:     }
        !           716:     /* Process the config file.  The following override each other:
        !           717:        - Hard-coded defaults
        !           718:        - The system config file
        !           719:        - Hard-coded defaults for security-critical things
        !           720:        - The user's config file
        !           721:        - Environment variables
        !           722:        - Command-line options.
        !           723:      */
        !           724:     opt = 0;                   /* Number of config files read */
        !           725: #ifdef PGP_SYSTEM_DIR
        !           726:     strcpy(mcguffin, PGP_SYSTEM_DIR);
        !           727:     strcat(mcguffin, "config.txt");
        !           728:     if (access(mcguffin, 0) == 0) {
        !           729:        opt++;
        !           730:        /*
        !           731:         * Note: errors here are NOT fatal, so that people
        !           732:         * can use PGP with a corrputed system file.
        !           733:         */
        !           734:        processConfigFile(mcguffin);
        !           735:     }
        !           736: #endif
        !           737: 
        !           738:     /*
        !           739:      * These must be personal; the system config file may not
        !           740:      * influence them.
        !           741:      */
        !           742:     buildfilename(globalPubringName, "pubring.pgp");
        !           743:     buildfilename(globalSecringName, "secring.pgp");
        !           744:     buildfilename(globalRandseedName, "randseed.bin");
        !           745:     my_name[0] = '\0';
        !           746: 
        !           747:     /* Process the config file first.  Any command-line arguments will
        !           748:        override the config file settings */
        !           749: #if defined(UNIX) || defined(MSDOS) || defined(OS2) || defined (WIN32)
        !           750:     /* Try "pgp.ini" on MS-DOS or ".pgprc" on Unix */
        !           751: #ifdef UNIX
        !           752:     buildfilename(mcguffin, ".pgprc");
        !           753: #else
        !           754:     buildfilename(mcguffin, "pgp.ini");
        !           755: #endif
        !           756:     if (access(mcguffin, 0) != 0)
        !           757:        buildfilename(mcguffin, "config.txt");
        !           758: #else
        !           759:     buildfilename(mcguffin, "config.txt");
        !           760: #endif
        !           761:     if (access(mcguffin, 0) == 0) {
        !           762:        opt++;
        !           763:        if (processConfigFile(mcguffin) < 0)
        !           764:            exit(BAD_ARG_ERROR);
        !           765:     }
        !           766:     if (!opt)
        !           767:        fprintf(pgpout, LANG("\007No configuration file found.\n"));
        !           768: 
        !           769:     init_charset();
        !           770: #endif /* MACTC5 */
        !           771: 
        !           772: #ifdef MSDOS                   /* only on MSDOS systems */
        !           773:     if ((p = getenv("TZ")) == NULL || *p == '\0') {
        !           774:        fprintf(pgpout,LANG("\007WARNING: Environmental variable TZ is not \
        !           775: defined, so GMT timestamps\n\
        !           776: may be wrong.  See the PGP User's Guide to properly define TZ\n\
        !           777: in AUTOEXEC.BAT file.\n"));
        !           778:     }
        !           779: #endif                         /* MSDOS */
        !           780: 
        !           781: #ifdef VMS
        !           782: #define TEMP "SYS$SCRATCH"
        !           783: #else
        !           784: #define TEMP "TMP"
        !           785: #endif                         /* VMS */
        !           786:     if ((p = getenv(TEMP)) != NULL && *p != '\0')
        !           787:        settmpdir(p);
        !           788: 
        !           789:     if ((myArgv = (char **) malloc((argc + 2) * sizeof(char **))) == NULL) {
        !           790:        fprintf(stderr, LANG("\n\007Out of memory.\n"));
        !           791:        exitPGP(7);
        !           792:     }
        !           793:     myArgv[0] = NULL;
        !           794:     myArgv[1] = NULL;
        !           795: 
        !           796:     /* Process all the command-line option switches: */
        !           797:     while (optind < argc) {
        !           798:        /*
        !           799:         * Allow random order of options and arguments (like GNU getopt)
        !           800:         * NOTE: this does not work with GNU getopt, use getopt.c from
        !           801:         * the PGP distribution.
        !           802:         */
        !           803:        if ((!strncasecmp(argv[optind], INCLUDE_MARK, INCLUDE_MARK_LEN)) ||
        !           804:            ((opt = pgp_getopt(argc, argv, OPTIONS)) == EOF)) {
        !           805:            if (optind == argc) /* -- at end */
        !           806:                break;
        !           807:            myArgv[myArgc++] = argv[optind++];
        !           808:            continue;
        !           809:        }
        !           810:        opt = to_lower(opt);
        !           811:        if (keyflag && (keychar == '\0' || (keychar == 'v' && opt == 'v'))) {
        !           812:            if (keychar == 'v')
        !           813:                keychar = 'V';
        !           814:            else
        !           815:                keychar = opt;
        !           816:            continue;
        !           817:        }
        !           818:        switch (opt) {
        !           819:        case 'a':
        !           820:            armor_flag = TRUE;
        !           821:            emit_radix_64 = 1;
        !           822:            break;
        !           823:        case 'b':
        !           824:            separate_signature = strip_sig_flag = TRUE;
        !           825:            break;
        !           826:        case 'c':
        !           827:            encrypt_flag = conventional_flag = TRUE;
        !           828:            c_flag = TRUE;
        !           829:            break;
        !           830:        case 'd':
        !           831:            decrypt_only_flag = TRUE;
        !           832:            break;
        !           833:        case 'e':
        !           834:            encrypt_flag = TRUE;
        !           835:            break;
        !           836: #ifdef MACTC5
        !           837:        case 'f':
        !           838:                if (macbin_flag == FALSE) filter_mode = TRUE;
        !           839:                break;
        !           840: #else
        !           841:        case 'f':
        !           842:            filter_mode = TRUE;
        !           843:            break;
        !           844: #endif
        !           845:        case '?':
        !           846:        case 'h':
        !           847:            usage();
        !           848:            break;
        !           849: #ifdef VMS
        !           850:        case 'i':
        !           851:            literal_mode = MODE_LOCAL;
        !           852:            break;
        !           853: #else
        !           854: #ifdef MACTC5
        !           855:        case 'i':
        !           856:                macbin_flag = TRUE;
        !           857:                moreflag = FALSE;
        !           858:                literal_mode = MODE_BINARY;
        !           859:                filter_mode = FALSE;
        !           860:                break;
        !           861: #endif /* MACTC5 */
        !           862: #endif                         /* VMS */
        !           863:        case 'k':
        !           864:            keyflag = TRUE;
        !           865:            break;
        !           866:        case 'l':
        !           867:            verbose = TRUE;
        !           868:            break;
        !           869: #ifdef MACTC5
        !           870:        case 'm':
        !           871:                if( macbin_flag == FALSE )
        !           872:                        moreflag = TRUE;
        !           873:                break;
        !           874: #else
        !           875:        case 'm':
        !           876:            moreflag = TRUE;
        !           877:            break;
        !           878: #endif
        !           879:        case 'p':
        !           880:            preserve_filename = TRUE;
        !           881:            break;
        !           882:        case 'o':
        !           883:            outputfile = optarg;
        !           884:            break;
        !           885:        case 's':
        !           886:            sign_flag = TRUE;
        !           887:            break;
        !           888: #ifdef MACTC5
        !           889:        case 't':
        !           890:                if( macbin_flag == FALSE )
        !           891:                        literal_mode = MODE_TEXT;
        !           892:                break;
        !           893: #else
        !           894:        case 't':
        !           895:            literal_mode = MODE_TEXT;
        !           896:            break;
        !           897: #endif
        !           898:        case 'u':
        !           899:            strncpy(my_name, optarg, sizeof(my_name) - 1);
        !           900:            CONVERT_TO_CANONICAL_CHARSET(my_name);
        !           901:            u_flag = TRUE;
        !           902:            break;
        !           903:        case 'w':
        !           904:            wipeflag = TRUE;
        !           905:            break;
        !           906:        case 'z':
        !           907:            break;
        !           908:            /* '+' special option: does not require - */
        !           909:        case '+':
        !           910:            if (processConfigLine(optarg) == 0) {
        !           911:                 if (!strncasecmp(optarg,"charset",7))
        !           912:                     init_charset();
        !           913:                break;
        !           914:            }
        !           915:            fprintf(stderr, "\n");
        !           916:            /* fallthrough */
        !           917:        default:
        !           918:            arg_error();
        !           919:        }
        !           920:     }
        !           921:     myArgv[myArgc] = NULL;     /* Just to make it NULL terminated */
        !           922: 
        !           923:     if (keyflag && keychar == '\0')
        !           924:        key_usage();
        !           925: 
        !           926:     signon_msg();
        !           927:     check_expiration_date();   /* hobble any experimental version */
        !           928: 
        !           929:     /*
        !           930:      * Write to stdout if explicitly asked to, or in filter mode and
        !           931:      * no explicit file name was given.
        !           932:      */
        !           933:     output_stdout = outputfile ? strcmp(outputfile, "-")  == 0 : filter_mode;
        !           934: 
        !           935: #if 1
        !           936:     /* At request of Peter Simons, use stderr always. Sounds reasonable. */
        !           937:     /* JIS: Put this code back in... removing it broke too many things */
        !           938:     if (!output_stdout)
        !           939:        pgpout = stdout;
        !           940: #endif
        !           941: 
        !           942: 
        !           943: #if defined(UNIX) || defined(VMS)
        !           944:     umask(077);                        /* Make files default to private */
        !           945: #endif
        !           946: 
        !           947:     initsigs();                        /* Catch signals */
        !           948:     noise();                   /* Start random number generation */
        !           949: 
        !           950:     if (keyflag) {
        !           951:        status = do_keyopt(keychar);
        !           952:        if (status < 0)
        !           953:            user_error();
        !           954:        exitPGP(status);
        !           955:     }
        !           956:     /* -db means break off signature certificate into separate file */
        !           957:     if (decrypt_only_flag && strip_sig_flag)
        !           958:        decrypt_only_flag = FALSE;
        !           959: 
        !           960:     if (decrypt_only_flag && armor_flag)
        !           961:        decrypt_mode = de_armor_only = TRUE;
        !           962: 
        !           963:     if (outputfile != NULL)
        !           964:        preserve_filename = FALSE;
        !           965: 
        !           966:     if (!sign_flag && !encrypt_flag && !conventional_flag && !armor_flag) {
        !           967:        if (wipeflag) {         /* wipe only */
        !           968:            if (myArgc != 3)
        !           969:                arg_error();    /* need one argument */
        !           970:            if (wipefile(myArgv[2]) == 0 && remove(myArgv[2]) == 0) {
        !           971:                fprintf(pgpout,
        !           972:                        LANG("\nFile %s wiped and deleted. "), myArgv[2]);
        !           973:                fprintf(pgpout, "\n");
        !           974:                exitPGP(EXIT_OK);
        !           975:            } else if (file_exists(myArgv[2]))
        !           976:                fprintf(pgpout,
        !           977: LANG("\n\007Error: Can't wipe out file '%s' - read only, maybe?\n"),
        !           978:                         myArgv[2]);
        !           979:             else {
        !           980:                fprintf(pgpout,
        !           981:                        LANG("\n\007File '%s' does not exist.\n"), myArgv[2]);
        !           982:            }
        !           983:            exitPGP(UNKNOWN_FILE_ERROR);
        !           984:        }
        !           985:        /* decrypt if none of the -s -e -c -a -w options are specified */
        !           986:        decrypt_mode = TRUE;
        !           987:     }
        !           988:     if (myArgc == 2) {         /* no arguments */
        !           989: #ifdef UNIX
        !           990:        if (!filter_mode && !isatty(fileno(stdin))) {
        !           991:            /* piping to pgp without arguments and no -f:
        !           992:             * switch to filter mode but don't write output to stdout
        !           993:             * if it's a tty, use the preserved filename */
        !           994:            if (!moreflag)
        !           995:                pgpout = stderr;
        !           996:            filter_mode = TRUE;
        !           997:            if (isatty(fileno(stdout)) && !moreflag)
        !           998:                preserve_filename = TRUE;
        !           999:        }
        !          1000: #endif
        !          1001:        if (!filter_mode) {
        !          1002:            if (quietmode) {
        !          1003:                quietmode = FALSE;
        !          1004:                signon_msg();
        !          1005:            }
        !          1006:            fprintf(pgpout,
        !          1007: LANG("\nFor details on licensing and distribution, see the PGP User's Guide.\
        !          1008: \nFor other cryptography products and custom development services, contact:\
        !          1009: \nPhilip Zimmermann, 3021 11th St, Boulder CO 80304 USA, \
        !          1010: phone +1 303 541-0140\n"));
        !          1011:            if (strcmp((p = LANG("@translator@")), "@translator@"))
        !          1012:                fprintf(pgpout, p);
        !          1013:            fprintf(pgpout, LANG("\nFor a usage summary, type:  pgp -h\n"));
        !          1014: #ifdef MACTC5
        !          1015:                exitPGP(BAD_ARG_ERROR);
        !          1016: #else
        !          1017:            exit(BAD_ARG_ERROR);        /* error exit */
        !          1018: #endif
        !          1019:        }
        !          1020:     } else {
        !          1021:        if (filter_mode) {
        !          1022:            recipient = &myArgv[2];
        !          1023:        } else {
        !          1024:            inputfile = myArgv[2];
        !          1025:            recipient = &myArgv[3];
        !          1026:        }
        !          1027:        recipient = ParseRecipients(recipient);
        !          1028:     }
        !          1029: 
        !          1030: 
        !          1031:     if (filter_mode) {
        !          1032:        inputfile = "stdin";
        !          1033:     } else if (makerandom > 0) {       /* Create the input file */
        !          1034:        /*
        !          1035:         * +makerandom=<bytes>: Create an input file consisting of <bytes>
        !          1036:         * cryptographically strong random bytes, before applying the
        !          1037:         * encryption options of PGP.  This is an advanced option, so
        !          1038:         * assume the user knows what he's doing and don't bother about
        !          1039:         * overwriting questions.  E.g.
        !          1040:         * pgp +makerandom=24 foofile
        !          1041:         *      Create "foofile" with 24 random bytes in it.
        !          1042:         * pgp +makerandom=24 -ea foofile recipient
        !          1043:         *      The same, but also encrypt it to "recipient", creating
        !          1044:         *      foofile.asc as well.
        !          1045:         * This feature was created to allow PGP to create and send keys
        !          1046:         * around for other applications to use.
        !          1047:         */
        !          1048:        status = cryptRandWriteFile(inputfile, (struct IdeaCfbContext *)0,
        !          1049:                               (unsigned)makerandom);
        !          1050:        if (status < 0) {
        !          1051:                fprintf(stderr,"Error writing file \"%s\"\n",inputfile);
        !          1052:                exitPGP(INVALID_FILE_ERROR);
        !          1053:        }
        !          1054:        fprintf(pgpout, LANG("File %s created containing %d random bytes.\n"),
        !          1055:                inputfile, makerandom);
        !          1056:        /* If we aren't encrypting, don't bother trying to decrypt this! */
        !          1057:        if (decrypt_mode)
        !          1058:                exitPGP(EXIT_OK);
        !          1059: 
        !          1060:        /* This is obviously NOT a text file */
        !          1061:        literal_mode = MODE_BINARY;
        !          1062:     } else {
        !          1063:        if (decrypt_mode && no_extension(inputfile)) {
        !          1064:            strcpy(cipherfile, inputfile);
        !          1065:            force_extension(cipherfile, ASC_EXTENSION);
        !          1066:            if (file_exists(cipherfile)) {
        !          1067:                inputfile = cipherfile;
        !          1068:            } else {
        !          1069:                force_extension(cipherfile, PGP_EXTENSION);
        !          1070:                if (file_exists(cipherfile)) {
        !          1071:                    inputfile = cipherfile;
        !          1072:                } else {
        !          1073:                    force_extension(cipherfile, SIG_EXTENSION);
        !          1074:                    if (file_exists(cipherfile))
        !          1075:                        inputfile = cipherfile;
        !          1076:                }
        !          1077:            }
        !          1078:        }
        !          1079:        if (!file_exists(inputfile)) {
        !          1080:            fprintf(pgpout,
        !          1081:                    LANG("\n\007File '%s' does not exist.\n"), inputfile);
        !          1082:            errorLvl = FILE_NOT_FOUND_ERROR;
        !          1083:            user_error();
        !          1084:        }
        !          1085:     }
        !          1086: 
        !          1087:     if (strlen(inputfile) >= (unsigned) MAX_PATH - 4) {
        !          1088:        fprintf(pgpout, 
        !          1089:                LANG("\007Invalid filename: '%s' too long\n"), inputfile);
        !          1090:        errorLvl = INVALID_FILE_ERROR;
        !          1091:        user_error();
        !          1092:     }
        !          1093:     strcpy(plainfile, inputfile);
        !          1094: 
        !          1095:     if (filter_mode) {
        !          1096:        setoutdir(NULL);        /* NULL means use tmpdir */
        !          1097:     } else {
        !          1098:        if (outputfile)
        !          1099:            setoutdir(outputfile);
        !          1100:        else
        !          1101:            setoutdir(inputfile);
        !          1102:     }
        !          1103: 
        !          1104:     if (filter_mode) {
        !          1105:        workfile = tempfile(TMP_WIPE | TMP_TMPDIR);
        !          1106:        readPhantomInput(workfile);
        !          1107:     } else {
        !          1108:        workfile = inputfile;
        !          1109:     }
        !          1110: 
        !          1111:     get_header_info_from_file(workfile, &ctb, 1);
        !          1112:     if (decrypt_mode) {
        !          1113:        strip_spaces = FALSE;
        !          1114:        if (!is_ctb(ctb) && is_armor_file(workfile, 0L))
        !          1115:            do_armorfile(workfile);
        !          1116:        else if (do_decrypt(workfile) < 0)
        !          1117:            user_error();
        !          1118: #ifdef MACTC5
        !          1119:        if (verbose) fprintf(stderr, "Final file = %s.\n", plainfile);
        !          1120:        /* Allow for overide of auto-unmacbin : 205b */
        !          1121:        if( (macbin_flag == FALSE) && is_macbin(plainfile) ) 
        !          1122:                bin2mac(plainfile,TRUE);
        !          1123:        else {
        !          1124:                AddOutputFiles(plainfile);
        !          1125:                PGPSetFinfo(plainfile,FType,FCreator);
        !          1126:        }
        !          1127:        if (use_clipboard) File2Scrap(plainfile);
        !          1128: #endif
        !          1129:        if (batchmode && !signature_checked)
        !          1130:            exitPGP(1);         /* alternate success, file did not have sig. */
        !          1131:        else
        !          1132:            exitPGP(EXIT_OK);
        !          1133:     }
        !          1134:     /*
        !          1135:      * See if plaintext input file was actually created by PGP earlier--
        !          1136:      * If it was, maybe we should NOT encapsulate it in a literal packet.
        !          1137:      * (nestflag = TRUE).  Otherwise, always encapsulate it (default).
        !          1138:      * (Why test for filter_mode???)
        !          1139:      */
        !          1140:     if (!batchmode && !filter_mode && legal_ctb(ctb)) {
        !          1141:        /*      Special case--may be a PGP-created packet, so
        !          1142:           do we inhibit encapsulation in literal packet? */
        !          1143:        fprintf(pgpout,
        !          1144: LANG("\n\007Input file '%s' looks like it may have been created by PGP. "),
        !          1145:                inputfile);
        !          1146:        fprintf(pgpout,
        !          1147: LANG("\nIs it safe to assume that it was created by PGP (y/N)? "));
        !          1148:        nestflag = getyesno('n');
        !          1149:     } else if (force_flag && makerandom == 0 && legal_ctb(ctb)) {
        !          1150:        nestflag = TRUE;
        !          1151:     }
        !          1152: 
        !          1153:     if (moreflag && makerandom == 0) {
        !          1154:        /* special name to cause printout on decrypt */
        !          1155:        strcpy(literal_file_name, CONSOLE_FILENAME);
        !          1156:        literal_mode = MODE_TEXT;       /* will check for text file later */
        !          1157:     } else {
        !          1158:        strcpy(literal_file_name, file_tail(inputfile));
        !          1159: #ifdef MSDOS
        !          1160:        strlwr(literal_file_name);
        !          1161: #endif
        !          1162:     }
        !          1163:     literal_file = literal_file_name;
        !          1164: 
        !          1165:     /*      Make sure non-text files are not accidentally converted 
        !          1166:        to canonical text.  This precaution should only be followed 
        !          1167:        for US ASCII text files, since European text files may have 
        !          1168:        8-bit character codes and still be legitimate text files 
        !          1169:        suitable for conversion to canonical (CR/LF-terminated) 
        !          1170:        text format. */
        !          1171:     if (literal_mode == MODE_TEXT && !is_text_file(workfile)) {
        !          1172:        fprintf(pgpout,
        !          1173: LANG("\nNote: '%s' is not a pure text file.\n\
        !          1174: File will be treated as binary data.\n"),
        !          1175:                workfile);
        !          1176:        literal_mode = MODE_BINARY;     /* now expect straight binary */
        !          1177:     }
        !          1178:     if (moreflag && literal_mode == MODE_BINARY) {
        !          1179:        /* For eyes only?  Can't display binary file. */
        !          1180:        fprintf(pgpout,
        !          1181: LANG("\n\007Error: Only text files may be sent as display-only.\n"));
        !          1182:        errorLvl = INVALID_FILE_ERROR;
        !          1183:        user_error();
        !          1184:     }
        !          1185: 
        !          1186:     /*  
        !          1187:      * See if plainfile looks like it might be incompressible, 
        !          1188:      * by examining its contents for compression headers for 
        !          1189:      * commonly-used compressed file formats like PKZIP, etc.
        !          1190:      * Remember this information for later, when we are deciding
        !          1191:      * whether to attempt compression before encryption.
        !          1192:      *
        !          1193:      * Naturally, don't bother if we are making a separate signature or
        !          1194:      * clear-signed message.  Also, don't bother trying to compress a
        !          1195:      * PGP message, as it's probably already compressed.
        !          1196:      */
        !          1197:     attempt_compression = compress_enabled && !separate_signature &&
        !          1198:                           !nestflag && !clearfile && makerandom == 0 &&
        !          1199:                           file_compressible(plainfile);
        !          1200: 
        !          1201: #ifdef MACTC5
        !          1202:        if(( macbin_flag == TRUE ) && (nestflag==FALSE)) {
        !          1203:                char *saveworkfile;
        !          1204:                nestflag = false;
        !          1205:                saveworkfile = workfile;
        !          1206:                workfile = tempfile(TMP_WIPE|TMP_TMPDIR);
        !          1207:                if (mac2bin(saveworkfile, workfile)!=0) {
        !          1208:                        fprintf(pgpout, LANG("\n\007Error: MacBinary failed!\n"));
        !          1209:                        errorLvl = INVALID_FILE_ERROR;
        !          1210:                        rmtemp(workfile);
        !          1211:                        exitPGP(errorLvl);
        !          1212:                }
        !          1213:        }
        !          1214: #endif
        !          1215:     if (sign_flag) {
        !          1216:        if (!filter_mode && !quietmode)
        !          1217:            fprintf(pgpout,
        !          1218: LANG("\nA secret key is required to make a signature. "));
        !          1219:        if (!quietmode && my_name[0] == '\0') {
        !          1220:            fprintf(pgpout,
        !          1221: LANG("\nYou specified no user ID to select your secret key,\n\
        !          1222: so the default user ID and key will be the most recently\n\
        !          1223: added key on your secret keyring.\n"));
        !          1224:        }
        !          1225:        strip_spaces = FALSE;
        !          1226:        clearfile = NULL;
        !          1227:        if (literal_mode == MODE_TEXT) {
        !          1228:            /* Text mode requires becoming canonical */
        !          1229:            tempf = tempfile(TMP_WIPE | TMP_TMPDIR);
        !          1230:            /* +clear means output file with signature in the clear,
        !          1231:               only in combination with -t and -a, not with -e or -b */
        !          1232:            if (!encrypt_flag && !separate_signature &&
        !          1233:                emit_radix_64 && clear_signatures) {
        !          1234:                clearfile = workfile;
        !          1235:                strip_spaces = TRUE;
        !          1236:            }
        !          1237:            make_canonical(workfile, tempf);
        !          1238:            if (!clearfile)
        !          1239:                rmtemp(workfile);
        !          1240:            workfile = tempf;
        !          1241:        }
        !          1242:        if (attempt_compression || encrypt_flag || emit_radix_64 ||
        !          1243:            output_stdout)
        !          1244:            tempf = tempfile(TMP_WIPE | TMP_TMPDIR);
        !          1245:        else
        !          1246:            tempf = tempfile(TMP_WIPE);
        !          1247:        /* for clear signatures we create a separate signature */
        !          1248:        status = signfile(nestflag, separate_signature || (clearfile != NULL),
        !          1249:                   my_name, workfile, tempf, literal_mode, literal_file);
        !          1250:        rmtemp(workfile);
        !          1251:        workfile = tempf;
        !          1252: 
        !          1253:        if (status < 0) {       /* signfile failed */
        !          1254:            fprintf(pgpout, LANG("\007Signature error\n"));
        !          1255:            errorLvl = SIGNATURE_ERROR;
        !          1256:            user_error();
        !          1257:        }
        !          1258:     } else if (!nestflag) {    /* !sign_file */
        !          1259:        /*      Prepend CTB_LITERAL byte to plaintext file.
        !          1260:           --sure wish this pass could be optimized away. */
        !          1261:        if (attempt_compression || encrypt_flag || emit_radix_64 ||
        !          1262:            output_stdout)
        !          1263:            tempf = tempfile(TMP_WIPE | TMP_TMPDIR);
        !          1264:        else
        !          1265:            tempf = tempfile(TMP_WIPE);
        !          1266:        /* for clear signatures we create a separate signature */
        !          1267:        status = make_literal(workfile, tempf, literal_mode, literal_file);
        !          1268:        rmtemp(workfile);
        !          1269:        workfile = tempf;
        !          1270:     }
        !          1271: 
        !          1272:     if (encrypt_flag) {
        !          1273:         if (emit_radix_64 || output_stdout)
        !          1274:            tempf = tempfile(TMP_WIPE | TMP_TMPDIR);
        !          1275:        else
        !          1276:            tempf = tempfile(TMP_WIPE);
        !          1277:        if (!conventional_flag) {
        !          1278:            if (!filter_mode && !quietmode)
        !          1279:                fprintf(pgpout,
        !          1280: LANG("\n\nRecipients' public key(s) will be used to encrypt. "));
        !          1281:            if (recipient == NULL || *recipient == NULL ||
        !          1282:                **recipient == '\0') {
        !          1283:                /* no recipient specified on command line */
        !          1284:                fprintf(pgpout,
        !          1285: LANG("\nA user ID is required to select the recipient's public key. "));
        !          1286:                fprintf(pgpout, LANG("\nEnter the recipient's user ID: "));
        !          1287: #ifdef AMIGA
        !          1288:                 requesterdesc=LANG("\nEnter the recipient's user ID: ");
        !          1289: #endif
        !          1290:                getstring(mcguffin, 255, TRUE);         /* echo keyboard */
        !          1291:                if ((mcguffins = (char **) malloc(2 * sizeof(char *))) == NULL)
        !          1292:                {
        !          1293:                    fprintf(stderr, LANG("\n\007Out of memory.\n"));
        !          1294:                    exitPGP(7);
        !          1295:                }
        !          1296:                mcguffins[0] = mcguffin;
        !          1297:                mcguffins[1] = "";
        !          1298:            } else {
        !          1299:                /* recipient specified on command line */
        !          1300:                mcguffins = recipient;
        !          1301:            }
        !          1302:            for (recipient = mcguffins; *recipient != NULL &&
        !          1303:                 **recipient != '\0'; recipient++) {
        !          1304:                CONVERT_TO_CANONICAL_CHARSET(*recipient);
        !          1305:            }
        !          1306:            status = encryptfile(mcguffins, workfile, tempf,
        !          1307:                                 attempt_compression);
        !          1308:        } else {
        !          1309:            status = idea_encryptfile(workfile, tempf, attempt_compression);
        !          1310:        }
        !          1311: 
        !          1312:        rmtemp(workfile);
        !          1313:        workfile = tempf;
        !          1314: 
        !          1315:        if (status < 0) {
        !          1316:            fprintf(pgpout, LANG("\007Encryption error\n"));
        !          1317:            errorLvl = (conventional_flag ? ENCR_ERROR : RSA_ENCR_ERROR);
        !          1318:            user_error();
        !          1319:        } 
        !          1320:     } else if (attempt_compression && !separate_signature && !clearfile) {
        !          1321:        /*
        !          1322:         * PGP used to be parsimonious about compression; originally, it only
        !          1323:         * did it for files that were being encrypted (to reduce the
        !          1324:         * redundancy in the plaintext), but it should really do it for
        !          1325:         * anything where it's not a bad idea.
        !          1326:         */
        !          1327:         if (emit_radix_64 || output_stdout)
        !          1328:            tempf = tempfile(TMP_WIPE | TMP_TMPDIR);
        !          1329:        else
        !          1330:            tempf = tempfile(TMP_WIPE);
        !          1331:        squish_file(workfile, tempf);
        !          1332:        rmtemp(workfile);
        !          1333:        workfile = tempf;
        !          1334:     }
        !          1335: 
        !          1336:     /*
        !          1337:      * Write to stdout if explicitly asked to, or in filter mode and
        !          1338:      * no explicit file name was given.
        !          1339:      */
        !          1340:     if (output_stdout) {
        !          1341:        if (emit_radix_64) {
        !          1342:            /* NULL for outputfile means write to stdout */
        !          1343:            if (armor_file(workfile, NULL, inputfile, clearfile, FALSE) != 0) {
        !          1344:                errorLvl = UNKNOWN_FILE_ERROR;
        !          1345:                user_error();
        !          1346:            }
        !          1347:            if (clearfile)
        !          1348:                rmtemp(clearfile);
        !          1349:        } else {
        !          1350:            if (writePhantomOutput(workfile) < 0) {
        !          1351:                errorLvl = UNKNOWN_FILE_ERROR;
        !          1352:                user_error();
        !          1353:            }
        !          1354:        }
        !          1355:        rmtemp(workfile);
        !          1356:     } else {
        !          1357:        char name[MAX_PATH];
        !          1358:         char *t;
        !          1359:        if (outputfile) {
        !          1360:            strcpy(name, outputfile);
        !          1361:        } else {
        !          1362:            strcpy(name, inputfile);
        !          1363:            drop_extension(name);
        !          1364:        }
        !          1365:         do {
        !          1366:            if (!outputfile && no_extension(name)) {
        !          1367:                if (emit_radix_64)
        !          1368:                    force_extension(name, ASC_EXTENSION);
        !          1369:                else if (sign_flag && separate_signature)
        !          1370:                    force_extension(name, SIG_EXTENSION);
        !          1371:                else
        !          1372:                    force_extension(name, PGP_EXTENSION);
        !          1373: #ifdef MACTC5
        !          1374:                        if (addresfork) {
        !          1375:                                drop_extension(name);
        !          1376:                                force_extension(name, ".sdf");
        !          1377:                        }
        !          1378: #endif
        !          1379:            }
        !          1380:             if (!file_exists(name)) break;
        !          1381:             t=ck_dup_output(name, TRUE, !clearfile);
        !          1382:             if (t==NULL) user_error();
        !          1383:             if (clearfile && !strcmp(t,name)) break;
        !          1384:             strcpy(name,t);
        !          1385:         } while (TRUE);
        !          1386:        if (emit_radix_64) {
        !          1387:            if (armor_file(workfile, name, inputfile, clearfile, FALSE) != 0) {
        !          1388:                errorLvl = UNKNOWN_FILE_ERROR;
        !          1389:                user_error();
        !          1390:            }
        !          1391:            if (clearfile)
        !          1392:                rmtemp(clearfile);
        !          1393:        } else {
        !          1394:            if ((outputfile = savetemp(workfile, name)) == NULL) {
        !          1395:                errorLvl = UNKNOWN_FILE_ERROR;
        !          1396:                user_error();
        !          1397:            }
        !          1398:            if (!quietmode) {
        !          1399:                if (encrypt_flag)
        !          1400:                    fprintf(pgpout,
        !          1401:                            LANG("\nCiphertext file: %s\n"), outputfile);
        !          1402:                else if (sign_flag)
        !          1403:                    fprintf(pgpout,
        !          1404:                            LANG("\nSignature file: %s\n"), outputfile);
        !          1405:            }
        !          1406:        }
        !          1407: #ifdef MACTC5
        !          1408:                AddOutputFiles(name);
        !          1409:                if (addresfork) {
        !          1410:                        if(!AddResourceFork(name)) {
        !          1411:                                short frefnum,len,i;
        !          1412:                                char *p,*q;
        !          1413:                                Handle h;
        !          1414:                                c2pstr(name);
        !          1415:                                q=file_tail(argv[2]);
        !          1416:                                len=strlen(q);
        !          1417:                                frefnum=OpenResFile((uchar *)name);
        !          1418:                                h=NewHandle(len+1);
        !          1419:                                HLock(h);
        !          1420:                                p=*h;
        !          1421:                                *p++=len;
        !          1422:                                for (i=0; i<len; i++) *p++=*q++;
        !          1423:                                AddResource(h,'STR ',500,(uchar *)"");
        !          1424:                                ChangedResource(h);
        !          1425:                                WriteResource(h);
        !          1426:                                UpdateResFile(frefnum);
        !          1427:                                CloseResFile(frefnum);
        !          1428:                                p2cstr((uchar *)name);
        !          1429:                        } else {
        !          1430:                                BailoutAlert("AddResFork failed!");
        !          1431:                                exitPGP(-1);
        !          1432:                        }
        !          1433:                }       
        !          1434:                if (binhex_flag) {
        !          1435:                        if (binhex(name)) {
        !          1436:                                BailoutAlert("BinHex failed!");
        !          1437:                                exitPGP(-1);
        !          1438:                        }
        !          1439:                        remove(name);
        !          1440:                }
        !          1441:                if (use_clipboard) File2Scrap(name);
        !          1442: #endif /* MACTC5 */
        !          1443:     }
        !          1444: 
        !          1445:     if (wipeflag) {
        !          1446:        /* destroy every trace of plaintext */
        !          1447:        if (wipefile(inputfile) == 0) {
        !          1448:            remove(inputfile);
        !          1449:            fprintf(pgpout, LANG("\nFile %s wiped and deleted. "), inputfile);
        !          1450:            fprintf(pgpout, "\n");
        !          1451:        }
        !          1452:     }
        !          1453: 
        !          1454: #ifdef MACTC5
        !          1455:        if(!addresfork && !use_clipboard)
        !          1456:                if (!emit_radix_64) PGPSetFinfo(outputfile,'Cryp','MPGP');
        !          1457: #endif
        !          1458: 
        !          1459:     exitPGP(EXIT_OK);
        !          1460:     return 0;                  /* to shut up lint and some compilers */
        !          1461: #ifdef MACTC5
        !          1462: }                              /* pgp_dispatch */
        !          1463: #else
        !          1464: }                              /* main */
        !          1465: #endif
        !          1466: 
        !          1467: #ifdef MSDOS
        !          1468: #include <dos.h>
        !          1469: static char *dos_errlst[] =
        !          1470: {
        !          1471:     "Write protect error",     /* LANG ("Write protect error") */
        !          1472:     "Unknown unit",
        !          1473:     "Drive not ready",         /* LANG ("Drive not ready") */
        !          1474:     "3", "4", "5", "6", "7", "8", "9",
        !          1475:     "Write error",             /* LANG ("Write error") */
        !          1476:     "Read error",              /* LANG ("Read error") */
        !          1477:     "General failure",
        !          1478: };
        !          1479: 
        !          1480: /* handler for msdos 'harderrors' */
        !          1481: #ifndef OS2
        !          1482: #ifdef __TURBOC__              /* Turbo C 2.0 */
        !          1483: static int dostrap(int errval)
        !          1484: #else
        !          1485: static void dostrap(unsigned deverr, unsigned errval)
        !          1486: #endif
        !          1487: {
        !          1488:     char errbuf[64];
        !          1489:     int i;
        !          1490:     sprintf(errbuf, "\r\nDOS error: %s\r\n", dos_errlst[errval]);
        !          1491:     i = 0;
        !          1492:     do
        !          1493:        bdos(2, (unsigned int) errbuf[i], 0);
        !          1494:     while (errbuf[++i]);
        !          1495: #ifdef __TURBOC__
        !          1496:     return 0;                  /* ignore (fopen will return NULL) */
        !          1497: #else
        !          1498:     return;
        !          1499: #endif
        !          1500: }
        !          1501: #endif                         /* MSDOS */
        !          1502: #endif
        !          1503: 
        !          1504: static void initsigs()
        !          1505: {
        !          1506: #ifdef MSDOS
        !          1507: #ifndef OS2
        !          1508: #ifdef __TURBOC__
        !          1509:     harderr(dostrap);
        !          1510: #else                          /* MSC */
        !          1511: #ifndef __GNUC__               /* DJGPP's not MSC */
        !          1512:     _harderr(dostrap);
        !          1513: #endif
        !          1514: #endif
        !          1515: #endif
        !          1516: #endif                         /* MSDOS */
        !          1517: #ifdef SIGINT
        !          1518:     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
        !          1519:        signal(SIGINT, breakHandler);
        !          1520: #if defined(UNIX) || defined(VMS) || defined(ATARI)
        !          1521: #ifndef __PUREC__ /* PureC doesn't recognise all signals */
        !          1522:     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
        !          1523:        signal(SIGHUP, breakHandler);
        !          1524:     if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
        !          1525:        signal(SIGQUIT, breakHandler);
        !          1526: #endif
        !          1527: #ifdef UNIX
        !          1528:     signal(SIGPIPE, breakHandler);
        !          1529: #endif
        !          1530:     signal(SIGTERM, breakHandler);
        !          1531: #ifdef MACTC5
        !          1532:        signal(SIGABRT,breakHandler);
        !          1533:        signal(SIGTERM,breakHandler);
        !          1534: #ifndef DEBUG
        !          1535:     signal(SIGTRAP, breakHandler);
        !          1536:     signal(SIGSEGV, breakHandler);
        !          1537:     signal(SIGILL, breakHandler);
        !          1538: #ifdef SIGBUS
        !          1539:     signal(SIGBUS, breakHandler);
        !          1540: #endif
        !          1541: #endif                         /* DEBUG */
        !          1542: #endif                         /* MACTC5 */
        !          1543: #endif                         /* UNIX */
        !          1544: #endif                         /* SIGINT */
        !          1545: }                              /* initsigs */
        !          1546: 
        !          1547: 
        !          1548: static void do_armorfile(char *armorfile)
        !          1549: {
        !          1550:     char *tempf;
        !          1551:     char cipherfile[MAX_PATH];
        !          1552:     long lastpos, linepos = 0;
        !          1553:     int status;
        !          1554:     int success = 0;
        !          1555: 
        !          1556:     for (;;) {
        !          1557:        /* Handle transport armor stripping */
        !          1558:        tempf = tempfile(0);
        !          1559:        strip_spaces = FALSE;   /* de_armor_file() sets
        !          1560:                                   this for clear signature files */
        !          1561:         use_charset_header = TRUE;
        !          1562:         lastpos = linepos;
        !          1563:        status = de_armor_file(armorfile, tempf, &linepos);
        !          1564:        if (status) {
        !          1565:            fprintf(pgpout,
        !          1566: LANG("\n\007Error: Transport armor stripping failed for file %s\n"),
        !          1567:                    armorfile);
        !          1568:            errorLvl = INVALID_FILE_ERROR;
        !          1569:            user_error();       /* Bad file */
        !          1570:        }
        !          1571:        if (keepctx || de_armor_only) {
        !          1572:            if (outputfile && de_armor_only) {
        !          1573:                if (strcmp(outputfile, "-") == 0) {
        !          1574:                    writePhantomOutput(tempf);
        !          1575:                    rmtemp(tempf);
        !          1576:                    return;
        !          1577:                }
        !          1578:                strcpy(cipherfile, outputfile);
        !          1579:            } else {
        !          1580:                strcpy(cipherfile, file_tail(armorfile));
        !          1581:                force_extension(cipherfile, PGP_EXTENSION);
        !          1582:            }
        !          1583:            if ((tempf = savetemp(tempf, cipherfile)) == NULL) {
        !          1584:                errorLvl = UNKNOWN_FILE_ERROR;
        !          1585:                user_error();
        !          1586:            }
        !          1587:            if (!quietmode)
        !          1588:                fprintf(pgpout,
        !          1589: LANG("Stripped transport armor from '%s', producing '%s'.\n"),
        !          1590:                        armorfile, tempf);
        !          1591:            /* -da flag: don't decrypt */
        !          1592:            if (de_armor_only || do_decrypt(tempf) >= 0)
        !          1593:                ++success;
        !          1594:        } else {
        !          1595:            if (charset_header[0])        /* Check signature with charset from Charset: header */
        !          1596:                checksig_pass = 1;
        !          1597:            if (do_decrypt(tempf) >= 0)
        !          1598:                ++success;
        !          1599:            rmtemp(tempf);
        !          1600:            if (charset_header[0]) {
        !          1601:                if (checksig_pass == 2) { /* Sigcheck failed: try again with local charset */
        !          1602:                    tempf = tempfile(0);
        !          1603:                    use_charset_header = FALSE;
        !          1604:                    linepos = lastpos;
        !          1605:                    de_armor_file(armorfile, tempf, &linepos);
        !          1606:                    if (do_decrypt(tempf) >= 0)
        !          1607:                        ++success;
        !          1608:                    rmtemp(tempf);
        !          1609:                }
        !          1610:                checksig_pass = 0;
        !          1611:            }
        !          1612:        }
        !          1613: 
        !          1614:        if (!is_armor_file(armorfile, linepos)) {
        !          1615:            if (!success)       /* print error msg if we didn't
        !          1616:                                   decrypt anything */
        !          1617:                user_error();
        !          1618:            return;
        !          1619:        }
        !          1620:        fprintf(pgpout,
        !          1621:                LANG("\nLooking for next packet in '%s'...\n"), armorfile);
        !          1622:     }
        !          1623: }                              /* do_armorfile */
        !          1624: 
        !          1625: 
        !          1626: static int do_decrypt(char *cipherfile)
        !          1627: {
        !          1628:     char *outfile = NULL;
        !          1629:     int status, i;
        !          1630:     boolean nested_info = FALSE;
        !          1631:     char ringfile[MAX_PATH];
        !          1632:     byte ctb;
        !          1633:     byte header[8];            /* used to classify file type at the end. */
        !          1634:     char preserved_name[MAX_PATH];
        !          1635:     char *newname;
        !          1636: 
        !          1637:     /* will be set to the original file name after processing a
        !          1638:        literal packet */
        !          1639:     preserved_name[0] = '\0';
        !          1640: 
        !          1641:     do {                       /* while nested parsable info present */
        !          1642:        if (nested_info) {
        !          1643:            rmtemp(cipherfile); /* never executed on first pass */
        !          1644:            cipherfile = outfile;
        !          1645:        }
        !          1646:        if (get_header_info_from_file(cipherfile, &ctb, 1) < 0) {
        !          1647:            fprintf(pgpout,
        !          1648: LANG("\n\007Can't open ciphertext file '%s'\n"), cipherfile);
        !          1649:            errorLvl = FILE_NOT_FOUND_ERROR;
        !          1650:            return -1;
        !          1651:        }
        !          1652:        if (!is_ctb(ctb))       /* not a real CTB -- complain */
        !          1653:            break;
        !          1654: 
        !          1655:        if (moreflag)
        !          1656:            outfile = tempfile(TMP_WIPE | TMP_TMPDIR);
        !          1657:        else
        !          1658:            outfile = tempfile(TMP_WIPE);
        !          1659: 
        !          1660:        /* PKE is Public Key Encryption */
        !          1661:        if (is_ctb_type(ctb, CTB_PKE_TYPE)) {
        !          1662: 
        !          1663:            if (!quietmode)
        !          1664:                fprintf(pgpout,
        !          1665: LANG("\nFile is encrypted.  Secret key is required to read it. "));
        !          1666: 
        !          1667:            /* Decrypt to scratch file since we may have a LITERAL2 */
        !          1668:            status = decryptfile(cipherfile, outfile);
        !          1669: 
        !          1670:            if (status < 0) {   /* error return */
        !          1671:                errorLvl = RSA_DECR_ERROR;
        !          1672:                return -1;
        !          1673:            }
        !          1674:            nested_info = (status > 0);
        !          1675: 
        !          1676:        } else if (is_ctb_type(ctb, CTB_SKE_TYPE)) {
        !          1677: 
        !          1678:            if (decrypt_only_flag) {
        !          1679:                /* swap file names instead of just copying the file */
        !          1680:                rmtemp(outfile);
        !          1681:                outfile = cipherfile;
        !          1682:                cipherfile = NULL;
        !          1683:                if (!quietmode)
        !          1684:                    fprintf(pgpout,
        !          1685: LANG("\nThis file has a signature, which will be left in place.\n"));
        !          1686:                nested_info = FALSE;
        !          1687:                break;          /* Do no more */
        !          1688:            }
        !          1689:            if (!quietmode && checksig_pass<=1)
        !          1690:                fprintf(pgpout,
        !          1691: LANG("\nFile has signature.  Public key is required to check signature.\n"));
        !          1692: 
        !          1693:            status = check_signaturefile(cipherfile, outfile,
        !          1694:                                         strip_sig_flag, preserved_name);
        !          1695: 
        !          1696:            if (status < 0) {   /* error return */
        !          1697:                errorLvl = SIGNATURE_CHECK_ERROR;
        !          1698:                return -1;
        !          1699:            }
        !          1700:            nested_info = (status > 0);
        !          1701: 
        !          1702:            if (strcmp(preserved_name, "/dev/null") == 0) {
        !          1703:                rmtemp(outfile);
        !          1704:                fprintf(pgpout, "\n");
        !          1705:                return 0;
        !          1706:            }
        !          1707:        } else if (is_ctb_type(ctb, CTB_CKE_TYPE)) {
        !          1708: 
        !          1709:            /* Conventional Key Encrypted ciphertext. */
        !          1710:            /* Tell user it's encrypted here, and prompt for
        !          1711:               password in subroutine. */
        !          1712:            if (!quietmode)
        !          1713:                fprintf(pgpout, LANG("\nFile is conventionally encrypted.  "));
        !          1714:            /* Decrypt to scratch file since it may be a LITERAL2 */
        !          1715:            status = idea_decryptfile(cipherfile, outfile);
        !          1716:            if (status < 0) {   /* error return */
        !          1717:                errorLvl = DECR_ERROR;
        !          1718:                return -1;      /* error exit status */
        !          1719:            }
        !          1720:            nested_info = (status > 0);
        !          1721: 
        !          1722:        } else if (is_ctb_type(ctb, CTB_COMPRESSED_TYPE)) {
        !          1723: 
        !          1724:            /* Compressed text. */
        !          1725:            status = decompress_file(cipherfile, outfile);
        !          1726:            if (status < 0) {   /* error return */
        !          1727:                errorLvl = DECOMPRESS_ERROR;
        !          1728:                return -1;
        !          1729:            }
        !          1730:            /* Always assume nested information... */
        !          1731:            nested_info = TRUE;
        !          1732: 
        !          1733:        } else if (is_ctb_type(ctb, CTB_LITERAL_TYPE) ||
        !          1734:                   is_ctb_type(ctb, CTB_LITERAL2_TYPE)) { /* Raw plaintext.
        !          1735:                                                             Just copy it.
        !          1736:                                                             No more nesting.
        !          1737:                                                           */
        !          1738: 
        !          1739:            /* Strip off CTB_LITERAL prefix byte from file: */
        !          1740:            /* strip_literal may alter plainfile; will set mode */
        !          1741:            status = strip_literal(cipherfile, outfile,
        !          1742:                                   preserved_name, &literal_mode);
        !          1743:            if (status < 0) {   /* error return */
        !          1744:                errorLvl = UNKNOWN_FILE_ERROR;
        !          1745:                return -1;
        !          1746:            }
        !          1747:            nested_info = FALSE;
        !          1748:        } else if (ctb == CTB_CERT_SECKEY || ctb == CTB_CERT_PUBKEY) {
        !          1749: 
        !          1750:            rmtemp(outfile);
        !          1751:            if (decrypt_only_flag) {
        !          1752:                /* swap file names instead of just copying the file */
        !          1753:                outfile = cipherfile;
        !          1754:                cipherfile = NULL;
        !          1755:                nested_info = FALSE;    /* No error */
        !          1756:                break;          /* no further processing */
        !          1757:            }
        !          1758:            /* Key ring.  View it. */
        !          1759:            fprintf(pgpout,
        !          1760: LANG("\nFile contains key(s).  Contents follow..."));
        !          1761:            if (view_keyring(NULL, cipherfile, TRUE, FALSE) < 0) {
        !          1762:                errorLvl = KEYRING_VIEW_ERROR;
        !          1763:                return -1;
        !          1764:            }
        !          1765:            /* filter mode explicit requested with -f */
        !          1766:            if (filter_mode && !preserve_filename)
        !          1767:                return 0;       /*    No output file */
        !          1768:            if (batchmode)
        !          1769:                return 0;
        !          1770:            if (ctb == CTB_CERT_SECKEY)
        !          1771:                strcpy(ringfile, globalSecringName);
        !          1772:            else
        !          1773:                strcpy(ringfile, globalPubringName);
        !          1774:            /*      Ask if it should be put on key ring */
        !          1775:            fprintf(pgpout,
        !          1776: LANG("\nDo you want to add this keyfile to keyring '%s' (y/N)? "), ringfile);
        !          1777:            if (!getyesno('n'))
        !          1778:                return 0;
        !          1779:            status = addto_keyring(cipherfile, ringfile);
        !          1780:            if (status < 0) {
        !          1781:                fprintf(pgpout, LANG("\007Keyring add error. "));
        !          1782:                errorLvl = KEYRING_ADD_ERROR;
        !          1783:                return -1;
        !          1784:            }
        !          1785:            return 0;           /*    No output file */
        !          1786: 
        !          1787:        } else {                /* Unrecognized CTB */
        !          1788:            break;
        !          1789:        }
        !          1790: 
        !          1791:     } while (nested_info);
        !          1792:     /* No more nested parsable information */
        !          1793: 
        !          1794:     /* Stopped early due to error */
        !          1795:     if (nested_info) {
        !          1796:        fprintf(pgpout,
        !          1797: "\7\nERROR: Nested data has unexpected format.  CTB=0x%02X\n", ctb);
        !          1798:        if (outfile)
        !          1799:            rmtemp(outfile);
        !          1800:        if (cipherfile)
        !          1801:            rmtemp(cipherfile);
        !          1802:        errorLvl = UNKNOWN_FILE_ERROR;
        !          1803:        return -1;
        !          1804:     }
        !          1805:     if (outfile == NULL) {     /* file was not encrypted */
        !          1806:        if (!filter_mode && !moreflag) {
        !          1807:            fprintf(pgpout,
        !          1808: LANG("\007\nError: '%s' is not a ciphertext, signature, or key file.\n"),
        !          1809:                    cipherfile);
        !          1810:            errorLvl = UNKNOWN_FILE_ERROR;
        !          1811:            return -1;
        !          1812:        }
        !          1813:        outfile = cipherfile;
        !          1814:     } else {
        !          1815:        if (cipherfile)
        !          1816:            rmtemp(cipherfile);
        !          1817:     }
        !          1818: 
        !          1819:     if (moreflag || (strcmp(preserved_name, CONSOLE_FILENAME) == 0)) {
        !          1820:        /* blort to screen */
        !          1821:        if (strcmp(preserved_name, CONSOLE_FILENAME) == 0) {
        !          1822:            fprintf(pgpout,
        !          1823: LANG("\n\nThis message is marked \"For your eyes only\".  Display now \
        !          1824: (Y/n)? "));
        !          1825:            if (batchmode
        !          1826: #ifdef UNIX
        !          1827:             || !isatty(fileno(stdout)) /* stdout is redirected! */
        !          1828: #endif
        !          1829:             || filter_mode || !getyesno('y')) {
        !          1830:                /* no -- abort display, and clean up */
        !          1831:                 fprintf(pgpout, "\n");
        !          1832:                rmtemp(outfile);
        !          1833:                return 0;
        !          1834:            }
        !          1835:        }
        !          1836:        if (!quietmode)
        !          1837:            fprintf(pgpout, LANG("\n\nPlaintext message follows...\n"));
        !          1838:        else
        !          1839:            putc('\n', pgpout);
        !          1840:        fprintf(pgpout, "------------------------------\n");
        !          1841:        more_file(outfile, strcmp(preserved_name, CONSOLE_FILENAME) == 0);
        !          1842:        /* Disallow saving to disk if outfile is console-only: */
        !          1843:        if (strcmp(preserved_name, CONSOLE_FILENAME) == 0) {
        !          1844:            clearscreen();      /* remove all evidence */
        !          1845:        } else if (!quietmode && !batchmode) {
        !          1846:            fprintf(pgpout, LANG("Save this file permanently (y/N)? "));
        !          1847:            if (getyesno('n')) {
        !          1848:                char moreFilename[256];
        !          1849:                fprintf(pgpout, LANG("Enter filename to save file as: "));
        !          1850: #ifdef AMIGA
        !          1851:                 requesterdesc=LANG("Enter filename to save file as: ");
        !          1852: #endif
        !          1853:                 if (preserved_name[0]) {
        !          1854:                    fprintf(pgpout, "[%s]: ", file_tail(preserved_name));
        !          1855: #ifdef AMIGA
        !          1856:                     strcat(requesterdesc, "[");
        !          1857:                     strcat(requesterdesc, file_tail(preserved_name));
        !          1858:                     strcat(requesterdesc, "]:");
        !          1859: #endif
        !          1860:                 }
        !          1861: #ifdef MACTC5
        !          1862:                if(!GetFilePath(LANG("Enter filename to save file as:"),moreFilename,PUTFILE))
        !          1863:                        strcpy(moreFilename,"");
        !          1864:                else
        !          1865:                        fprintf(pgpout, "%s\n",moreFilename);
        !          1866: #else
        !          1867:                getstring(moreFilename, 255, TRUE);
        !          1868: #endif
        !          1869:                if (*moreFilename == '\0') {
        !          1870:                    if (*preserved_name != '\0')
        !          1871:                        savetemp(outfile, file_tail(preserved_name));
        !          1872:                    else
        !          1873:                        rmtemp(outfile);
        !          1874:                } else
        !          1875:                    savetemp(outfile, moreFilename);
        !          1876:                return 0;
        !          1877:            }
        !          1878:        }
        !          1879:        rmtemp(outfile);
        !          1880:        return 0;
        !          1881:     }                          /* blort to screen */
        !          1882:     if (outputfile) {
        !          1883:        if (!strcmp(outputfile, "/dev/null")) {
        !          1884:            rmtemp(outfile);
        !          1885:            return 0;
        !          1886:        }
        !          1887:        filter_mode = (strcmp(outputfile, "-") == 0);
        !          1888:        strcpy(plainfile, outputfile);
        !          1889:     } else {
        !          1890: #ifdef VMS
        !          1891:        /* VMS null extension has to be ".", not "" */
        !          1892:        force_extension(plainfile, ".");
        !          1893: #else                          /* not VMS */
        !          1894:        drop_extension(plainfile);
        !          1895: #endif                         /* not VMS */
        !          1896:     }
        !          1897: 
        !          1898:     if (!preserve_filename && filter_mode) {
        !          1899:        if (writePhantomOutput(outfile) < 0) {
        !          1900:            errorLvl = UNKNOWN_FILE_ERROR;
        !          1901:            return -1;
        !          1902:        }
        !          1903:        rmtemp(outfile);
        !          1904:        return 0;
        !          1905:     }
        !          1906:     if (preserve_filename && preserved_name[0] != '\0')
        !          1907:        strcpy(plainfile, file_tail(preserved_name));
        !          1908: 
        !          1909:     if (quietmode) {
        !          1910:        if (savetemp(outfile, plainfile) == NULL) {
        !          1911:            errorLvl = UNKNOWN_FILE_ERROR;
        !          1912:            return -1;
        !          1913:        }
        !          1914:        return 0;
        !          1915:     }
        !          1916:     if (!verbose)             /* if other filename messages were suppressed */
        !          1917:        fprintf(pgpout, LANG("\nPlaintext filename: %s"), plainfile);
        !          1918: 
        !          1919: 
        !          1920: /*---------------------------------------------------------*/
        !          1921: 
        !          1922:     /*      One last thing-- let's attempt to classify some of the more
        !          1923:        frequently occurring cases of plaintext output files, as an
        !          1924:        aid to the user.
        !          1925: 
        !          1926:        For example, if output file is a public key, it should have
        !          1927:        the right extension on the filename.
        !          1928: 
        !          1929:        Also, it will likely be common to encrypt files created by
        !          1930:        various archivers, so they should be renamed with the archiver
        !          1931:        extension.
        !          1932:      */
        !          1933:     get_header_info_from_file(outfile, header, 8);
        !          1934: 
        !          1935:     newname = NULL;
        !          1936: #ifdef MACTC5
        !          1937:        if (header[0] == CTB_CERT_SECKEY)
        !          1938:                PGPSetFinfo(plainfile,'SKey','MPGP');
        !          1939: #endif
        !          1940:     if (header[0] == CTB_CERT_PUBKEY) {
        !          1941:        /* Special case--may be public key, worth renaming */
        !          1942: #ifdef MACTC5
        !          1943:                PGPSetFinfo(plainfile,'PKey','MPGP');
        !          1944: #endif
        !          1945:        fprintf(pgpout,
        !          1946: LANG("\nPlaintext file '%s' looks like it contains a public key."),
        !          1947:                plainfile);
        !          1948:        newname = maybe_force_extension(plainfile, PGP_EXTENSION);
        !          1949:     }
        !          1950:     /* Possible public key output file */ 
        !          1951:     else if ((i = compressSignature(header)) >= 0) {
        !          1952:        /*      Special case--may be an archived/compressed file,
        !          1953:                worth renaming
        !          1954:        */
        !          1955:        fprintf(pgpout, LANG("\nPlaintext file '%s' looks like a %s file."),
        !          1956:                plainfile, compressName[i]);
        !          1957:        newname = maybe_force_extension(plainfile, compressExt[i]);
        !          1958:     } else if (is_ctb(header[0]) &&
        !          1959:               (is_ctb_type(header[0], CTB_PKE_TYPE)
        !          1960:                || is_ctb_type(header[0], CTB_SKE_TYPE)
        !          1961:                || is_ctb_type(header[0], CTB_CKE_TYPE))) {
        !          1962:        /* Special case--may be another ciphertext file, worth renaming */
        !          1963:        fprintf(pgpout,
        !          1964: LANG("\n\007Output file '%s' may contain more ciphertext or signature."),
        !          1965:                plainfile);
        !          1966:        newname = maybe_force_extension(plainfile, PGP_EXTENSION);
        !          1967:     }                          /* Possible ciphertext output file */
        !          1968: #ifdef MACTC5
        !          1969:        if( (newname = savetemp(outfile, (newname ? newname : plainfile))) == NULL) {
        !          1970: #else
        !          1971:     if (savetemp(outfile, (newname ? newname : plainfile)) == NULL) {
        !          1972: #endif
        !          1973:        errorLvl = UNKNOWN_FILE_ERROR;
        !          1974:        return -1;
        !          1975:     }
        !          1976: #ifdef MACTC5
        !          1977:        else if( strcmp(newname, plainfile) != 0 )      /* 203a */
        !          1978:                strcpy(plainfile, newname);
        !          1979: #endif
        !          1980:     fprintf(pgpout, "\n");
        !          1981:     return 0;
        !          1982: }                              /* do_decrypt */
        !          1983: 
        !          1984: static int do_keyopt(char keychar)
        !          1985: {
        !          1986:     char keyfile[MAX_PATH];
        !          1987:     char ringfile[MAX_PATH];
        !          1988:     char *workfile;
        !          1989:     int status;
        !          1990: 
        !          1991:     if ((filter_mode || batchmode)
        !          1992:        && (keychar == 'g' || keychar == 'e' || keychar == 'd'
        !          1993:            || (keychar == 'r' && sign_flag))) {
        !          1994:        errorLvl = NO_BATCH;
        !          1995:        arg_error();            /* interactive process, no go in batch mode */
        !          1996:     }
        !          1997:     /*
        !          1998:      * If we're not doing anything that uses stdout, produce output there,
        !          1999:      * in case user wants to redirect it.
        !          2000:      */
        !          2001:     if (!filter_mode)
        !          2002:        pgpout = stdout;
        !          2003: 
        !          2004:     switch (keychar) {
        !          2005: 
        !          2006: /*-------------------------------------------------------*/
        !          2007:     case 'g':
        !          2008:        {               /*      Key generation
        !          2009:                           Arguments: bitcount, bitcount
        !          2010:                         */
        !          2011:            char keybits[6], ebits[6], *username = NULL;
        !          2012: 
        !          2013:            /* 
        !          2014:             * Why all this code?
        !          2015:             * 
        !          2016:             * Some people may object to PGP insisting on finding the
        !          2017:             * manual somewhere in the neighborhood to generate a key.
        !          2018:             * They bristle against this seemingly authoritarian
        !          2019:             * attitude.  Some people have even modified PGP to defeat
        !          2020:             * this feature, and redistributed their hotwired version to
        !          2021:             * others.  That creates problems for me (PRZ).
        !          2022:             * 
        !          2023:             * Here is the problem.  Before I added this feature, there
        !          2024:             * were maimed versions of the PGP distribution package
        !          2025:             * floating around that lacked the manual.  One of them was
        !          2026:             * uploaded to Compuserve, and was distributed to countless
        !          2027:             * users who called me on the phone to ask me why such a
        !          2028:             * complicated program had no manual.  It spread out to BBS
        !          2029:             * systems around the country.  And a freeware distributor got
        !          2030:             * hold of the package from Compuserve and enshrined it on
        !          2031:             * CD-ROM, distributing thousands of copies without the
        !          2032:             * manual.  What a mess.
        !          2033:             * 
        !          2034:             * Please don't make my life harder by modifying PGP to
        !          2035:             * disable this feature so that others may redistribute PGP
        !          2036:             * without the manual.  If you run PGP on a palmtop with no
        !          2037:             * memory for the manual, is it too much to ask that you type
        !          2038:             * one little extra word on the command line to do a key
        !          2039:             * generation, a command that is seldom used by people who
        !          2040:             * already know how to use PGP?  If you can't stand even this
        !          2041:             * trivial inconvenience, can you suggest a better method of
        !          2042:             * reducing PGP's distribution without the manual?
        !          2043:             * 
        !          2044:             * PLEASE DO NOT DISABLE THIS CHECK IN THE SOURCE CODE
        !          2045:             * WITHOUT AT LEAST CALLING PHILIP ZIMMERMANN 
        !          2046:             * (+1 303 541-0140, or [email protected]) TO DISCUSS IT. 
        !          2047:             */
        !          2048:            if (!nomanual && manuals_missing()) {
        !          2049:                char const *const *dir;
        !          2050:                fputs(LANG("\a\nError: PGP User's Guide not found.\n\
        !          2051: PGP looked for it in the following directories:\n"), pgpout);
        !          2052: #ifdef MACTC5
        !          2053:                fprintf(pgpout, "\t\"%s\"\n", appPathName);
        !          2054: #else
        !          2055:                for (dir = manual_dirs; *dir; dir++)
        !          2056:                    fprintf(pgpout, "\t\"%s\"\n", *dir);
        !          2057: #endif /* MACTC5 */
        !          2058:                fputs(
        !          2059: LANG("and the doc subdirectory of each of the above.  Please put a copy of\n\
        !          2060: both volumes of the User's Guide in one of these directories.\n\
        !          2061: \n\
        !          2062: Under NO CIRCUMSTANCES should PGP ever be distributed without the PGP\n\
        !          2063: User's Guide, which is included in the standard distribution package.\n\
        !          2064: If you got a copy of PGP without the manual, please inform whomever you\n\
        !          2065: got it from that this is an incomplete package that should not be\n\
        !          2066: distributed further.\n\
        !          2067: \n\
        !          2068: PGP will not generate a key without finding the User's Guide.\n\
        !          2069: There is a simple way to override this restriction.  See the\n\
        !          2070: PGP User's Guide for details on how to do it.\n\
        !          2071: \n"), pgpout);
        !          2072:                return KEYGEN_ERROR;
        !          2073:            }
        !          2074:            if (myArgc > 2)
        !          2075:                strncpy(keybits, myArgv[2], sizeof(keybits) - 1);
        !          2076:            else
        !          2077:                keybits[0] = '\0';
        !          2078: 
        !          2079:            if (myArgc > 3)
        !          2080:                strncpy(ebits, myArgv[3], sizeof(ebits) - 1);
        !          2081:            else
        !          2082:                ebits[0] = '\0';
        !          2083: 
        !          2084:            /* If the -u option is given, use that username */
        !          2085:            if (u_flag && my_name != NULL && *my_name != '\0')
        !          2086:                username = my_name;
        !          2087: 
        !          2088:            /* dokeygen writes the keys out to the key rings... */
        !          2089:            status = dokeygen(keybits, ebits, username);
        !          2090: 
        !          2091:            if (status < 0) {
        !          2092:                fprintf(pgpout, LANG("\007Keygen error. "));
        !          2093:                errorLvl = KEYGEN_ERROR;
        !          2094:            }
        !          2095: #ifdef MACTC5
        !          2096:                else  {
        !          2097:                        strcpy(ringfile, globalPubringName );
        !          2098:                        PGPSetFinfo(ringfile,'PKey','MPGP');
        !          2099:                        strcpy(ringfile, globalSecringName  );
        !          2100:                        PGPSetFinfo(ringfile,'SKey','MPGP');                
        !          2101:                }
        !          2102: #endif              
        !          2103:            return status;
        !          2104:        }                       /* Key generation */
        !          2105: 
        !          2106: /*-------------------------------------------------------*/
        !          2107:     case 'c':
        !          2108:        {                       /*      Key checking
        !          2109:                                   Arguments: userid, ringfile
        !          2110:                                 */
        !          2111: 
        !          2112:            if (myArgc < 3) {   /* Default to all user ID's */
        !          2113:                mcguffin[0] = '\0';
        !          2114:            } else {
        !          2115:                strcpy(mcguffin, myArgv[2]);
        !          2116:                if (strcmp(mcguffin, "*") == 0)
        !          2117:                    mcguffin[0] = '\0';
        !          2118:            }
        !          2119:            CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          2120: 
        !          2121:            if (myArgc < 4)     /* default key ring filename */
        !          2122:                strcpy(ringfile, globalPubringName);
        !          2123:            else
        !          2124:                strncpy(ringfile, myArgv[3], sizeof(ringfile) - 1);
        !          2125: 
        !          2126:            if ((myArgc < 4 && myArgc > 2)     /* Allow just key file as arg */
        !          2127:                &&has_extension(myArgv[2], PGP_EXTENSION)) {
        !          2128:                strcpy(ringfile, myArgv[2]);
        !          2129:                mcguffin[0] = '\0';
        !          2130:            }
        !          2131:            status = dokeycheck(mcguffin, ringfile, CHECK_ALL);
        !          2132: 
        !          2133:            if (status < 0) {
        !          2134:                fprintf(pgpout, LANG("\007Keyring check error.\n"));
        !          2135:                errorLvl = KEYRING_CHECK_ERROR;
        !          2136:            }
        !          2137:            if (status >= 0 && mcguffin[0] != '\0')
        !          2138:                return status;  /* just checking a single user,
        !          2139:                                   dont do maintenance */
        !          2140: 
        !          2141:            if ((status = maint_check(ringfile, 0)) < 0 && status != -7) {
        !          2142:                fprintf(pgpout, LANG("\007Maintenance pass error. "));
        !          2143:                errorLvl = KEYRING_CHECK_ERROR;
        !          2144:            }
        !          2145: #ifdef MACTC5
        !          2146:                {   
        !          2147:                byte ctb;
        !          2148:                get_header_info_from_file(ringfile, &ctb, 1);
        !          2149:                if (ctb == CTB_CERT_SECKEY)
        !          2150:                        PGPSetFinfo(ringfile,'SKey','MPGP');
        !          2151:                else if (ctb == CTB_CERT_PUBKEY)
        !          2152:                PGPSetFinfo(ringfile,'PKey','MPGP');
        !          2153:                }
        !          2154: #endif
        !          2155:            return status == -7 ? 0 : status;
        !          2156:        }                       /* Key check */
        !          2157: 
        !          2158: /*-------------------------------------------------------*/
        !          2159:     case 'm':
        !          2160:        {                       /*      Maintenance pass
        !          2161:                                   Arguments: ringfile
        !          2162:                                 */
        !          2163: 
        !          2164:            if (myArgc < 3)     /* default key ring filename */
        !          2165:                strcpy(ringfile, globalPubringName);
        !          2166:            else
        !          2167:                strcpy(ringfile, myArgv[2]);
        !          2168: 
        !          2169: #ifdef MSDOS
        !          2170:            strlwr(ringfile);
        !          2171: #endif
        !          2172:            if (!file_exists(ringfile))
        !          2173:                default_extension(ringfile, PGP_EXTENSION);
        !          2174: 
        !          2175:            if ((status = maint_check(ringfile,
        !          2176:                      MAINT_VERBOSE | (c_flag ? MAINT_CHECK : 0))) < 0) {
        !          2177:                if (status == -7)
        !          2178:                    fprintf(pgpout,
        !          2179:                            LANG("File '%s' is not a public keyring\n"),
        !          2180:                            ringfile);
        !          2181:                fprintf(pgpout, LANG("\007Maintenance pass error. "));
        !          2182:                errorLvl = KEYRING_CHECK_ERROR;
        !          2183:            }
        !          2184: #ifdef MACTC5
        !          2185:                PGPSetFinfo(ringfile,'PKey','MPGP');
        !          2186: #endif
        !          2187:            return status;
        !          2188:        }                       /* Maintenance pass */
        !          2189: 
        !          2190: /*-------------------------------------------------------*/
        !          2191:     case 's':
        !          2192:        {                       /*      Key signing
        !          2193:                                   Arguments: her_id, keyfile
        !          2194:                                 */
        !          2195: 
        !          2196:            if (myArgc >= 4)
        !          2197:                strncpy(keyfile, myArgv[3], sizeof(keyfile) - 1);
        !          2198:            else
        !          2199:                strcpy(keyfile, globalPubringName);
        !          2200: 
        !          2201:            if (myArgc >= 3) {
        !          2202:                strcpy(mcguffin, myArgv[2]);    /* Userid to sign */
        !          2203:            } else {
        !          2204:                fprintf(pgpout,
        !          2205: LANG("\nA user ID is required to select the public key you want to sign. "));
        !          2206:                if (batchmode)  /* not interactive, userid
        !          2207:                                   must be on command line */
        !          2208:                    return -1;
        !          2209:                fprintf(pgpout, LANG("\nEnter the public key's user ID: "));
        !          2210: #ifdef AMIGA
        !          2211:                 requesterdesc=LANG("\nEnter the public key's user ID: ");
        !          2212: #endif
        !          2213:                getstring(mcguffin, 255, TRUE);         /* echo keyboard */
        !          2214:            }
        !          2215:            CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          2216: 
        !          2217:            if (my_name[0] == '\0') {
        !          2218:                fprintf(pgpout,
        !          2219: LANG("\nA secret key is required to make a signature. "));
        !          2220:                fprintf(pgpout,
        !          2221: LANG("\nYou specified no user ID to select your secret key,\n\
        !          2222: so the default user ID and key will be the most recently\n\
        !          2223: added key on your secret keyring.\n"));
        !          2224:            }
        !          2225:            status = signkey(mcguffin, my_name, keyfile);
        !          2226: 
        !          2227:            if (status >= 0) {
        !          2228:                status = maint_update(keyfile, 0);
        !          2229:                if (status == -7) { /* ringfile is a keyfile or
        !          2230:                                       secret keyring */
        !          2231:                    fprintf(pgpout,
        !          2232:                            "Warning: '%s' is not a public keyring\n",
        !          2233:                            keyfile);
        !          2234:                    return 0;
        !          2235:                }
        !          2236:                if (status < 0)
        !          2237:                    fprintf(pgpout, LANG("\007Maintenance pass error. "));
        !          2238:            }
        !          2239:            if (status < 0) {
        !          2240:                fprintf(pgpout, LANG("\007Key signature error. "));
        !          2241:                errorLvl = KEY_SIGNATURE_ERROR;
        !          2242:            }
        !          2243: #ifdef MACTC5
        !          2244:                PGPSetFinfo(keyfile,'PKey','MPGP');
        !          2245: #endif
        !          2246:            return status;
        !          2247:        }                       /* Key signing */
        !          2248: 
        !          2249: 
        !          2250: /*-------------------------------------------------------*/
        !          2251:     case 'd':
        !          2252:        {                       /*      disable/revoke key
        !          2253:                                   Arguments: userid, keyfile
        !          2254:                                 */
        !          2255: 
        !          2256:            if (myArgc >= 4)
        !          2257:                strncpy(keyfile, myArgv[3], sizeof(keyfile) - 1);
        !          2258:            else
        !          2259:                strcpy(keyfile, globalPubringName);
        !          2260: 
        !          2261:            if (myArgc >= 3) {
        !          2262:                strcpy(mcguffin, myArgv[2]);    /* Userid to sign */
        !          2263:            } else {
        !          2264:                fprintf(pgpout,
        !          2265: LANG("\nA user ID is required to select the key you want to revoke or \
        !          2266: disable. "));
        !          2267:                fprintf(pgpout, LANG("\nEnter user ID: "));
        !          2268: #ifdef AMIGA
        !          2269:                 requesterdesc=LANG("\nEnter user ID: ");
        !          2270: #endif
        !          2271:                getstring(mcguffin, 255, TRUE);         /* echo keyboard */
        !          2272:            }
        !          2273:            CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          2274: 
        !          2275:            status = disable_key(mcguffin, keyfile);
        !          2276: 
        !          2277:            if (status >= 0) {
        !          2278:                status = maint_update(keyfile, 0);
        !          2279:                if (status == -7) { /* ringfile is a keyfile or
        !          2280:                                       secret keyring */
        !          2281:                    fprintf(pgpout, "Warning: '%s' is not a public keyring\n",
        !          2282:                            keyfile);
        !          2283:                    return 0;
        !          2284:                }
        !          2285:                if (status < 0)
        !          2286:                    fprintf(pgpout, LANG("\007Maintenance pass error. "));
        !          2287:            }
        !          2288:            if (status < 0)
        !          2289:                errorLvl = KEY_SIGNATURE_ERROR;
        !          2290: #ifdef MACTC5
        !          2291:                PGPSetFinfo(keyfile,'PKey','MPGP');
        !          2292: #endif
        !          2293:            return status;
        !          2294:        }                       /* Key compromise */
        !          2295: 
        !          2296: /*-------------------------------------------------------*/
        !          2297:     case 'e':
        !          2298:        {                       /*      Key editing
        !          2299:                                   Arguments: userid, ringfile
        !          2300:                                 */
        !          2301: 
        !          2302:            if (myArgc >= 4)
        !          2303:                strncpy(ringfile, myArgv[3], sizeof(ringfile) - 1);
        !          2304:            else                /* default key ring filename */
        !          2305:                strcpy(ringfile, globalPubringName);
        !          2306: 
        !          2307:            if (myArgc >= 3) {
        !          2308:                strcpy(mcguffin, myArgv[2]);    /* Userid to edit */
        !          2309:            } else {
        !          2310:                fprintf(pgpout,
        !          2311: LANG("\nA user ID is required to select the key you want to edit. "));
        !          2312:                fprintf(pgpout, LANG("\nEnter the key's user ID: "));
        !          2313: #ifdef AMIGA
        !          2314:                 requesterdesc=LANG("\nEnter the key's user ID: ");
        !          2315: #endif
        !          2316:                getstring(mcguffin, 255, TRUE);         /* echo keyboard */
        !          2317:            }
        !          2318:            CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          2319: 
        !          2320:            status = dokeyedit(mcguffin, ringfile);
        !          2321: 
        !          2322:            if (status >= 0) {
        !          2323:                status = maint_update(ringfile, 0);
        !          2324:                if (status == -7)
        !          2325:                    status = 0; /* ignore "not a public keyring" error */
        !          2326:                if (status < 0)
        !          2327:                    fprintf(pgpout, LANG("\007Maintenance pass error. "));
        !          2328:            }
        !          2329:            if (status < 0) {
        !          2330:                fprintf(pgpout, LANG("\007Keyring edit error. "));
        !          2331:                errorLvl = KEYRING_EDIT_ERROR;
        !          2332:            }
        !          2333: #ifdef MACTC5
        !          2334:                {   
        !          2335:                byte ctb;
        !          2336:                get_header_info_from_file(ringfile, &ctb, 1);
        !          2337:                if (ctb == CTB_CERT_SECKEY)
        !          2338:                        PGPSetFinfo(ringfile,'SKey','MPGP');
        !          2339:                else if (ctb == CTB_CERT_PUBKEY)
        !          2340:                PGPSetFinfo(ringfile,'PKey','MPGP');
        !          2341:                }
        !          2342: #endif
        !          2343:            return status;
        !          2344:        }                       /* Key edit */
        !          2345: 
        !          2346: /*-------------------------------------------------------*/
        !          2347:     case 'a':
        !          2348:        {                       /*      Add key to key ring
        !          2349:                                   Arguments: keyfile, ringfile
        !          2350:                                 */
        !          2351: 
        !          2352:            if (myArgc < 3 && !filter_mode)
        !          2353:                arg_error();
        !          2354: 
        !          2355:            if (!filter_mode) { /* Get the keyfile from args */
        !          2356:                strncpy(keyfile, myArgv[2], sizeof(keyfile) - 1);
        !          2357: 
        !          2358: #ifdef MSDOS
        !          2359:                strlwr(keyfile);
        !          2360: #endif
        !          2361:                if (!file_exists(keyfile))
        !          2362:                    default_extension(keyfile, PGP_EXTENSION);
        !          2363: 
        !          2364:                if (!file_exists(keyfile)) {
        !          2365:                    fprintf(pgpout,
        !          2366:                            LANG("\n\007Key file '%s' does not exist.\n"),
        !          2367:                            keyfile);
        !          2368:                    errorLvl = NONEXIST_KEY_ERROR;
        !          2369:                    return -1;
        !          2370:                }
        !          2371:                workfile = keyfile;
        !          2372: 
        !          2373:            } else {
        !          2374:                workfile = tempfile(TMP_WIPE | TMP_TMPDIR);
        !          2375:                readPhantomInput(workfile);
        !          2376:            }
        !          2377: 
        !          2378:            if (myArgc < (filter_mode ? 3 : 4)) { /* default key ring
        !          2379:                                                     filename */
        !          2380:                byte ctb;
        !          2381:                get_header_info_from_file(workfile, &ctb, 1);
        !          2382:                if (ctb == CTB_CERT_SECKEY)
        !          2383:                    strcpy(ringfile, globalSecringName);
        !          2384:                else
        !          2385:                    strcpy(ringfile, globalPubringName);
        !          2386:            } else {
        !          2387:                strncpy(ringfile, myArgv[(filter_mode ? 2 : 3)],
        !          2388:                        sizeof(ringfile) - 1);
        !          2389:                default_extension(ringfile, PGP_EXTENSION);
        !          2390:            }
        !          2391: #ifdef MSDOS
        !          2392:            strlwr(ringfile);
        !          2393: #endif
        !          2394: 
        !          2395:            status = addto_keyring(workfile, ringfile);
        !          2396: 
        !          2397:            if (filter_mode)
        !          2398:                rmtemp(workfile);
        !          2399: 
        !          2400:            if (status < 0) {
        !          2401:                fprintf(pgpout, LANG("\007Keyring add error. "));
        !          2402:                errorLvl = KEYRING_ADD_ERROR;
        !          2403:            }
        !          2404: #ifdef MACTC5
        !          2405:                {   
        !          2406:                byte ctb;
        !          2407:                get_header_info_from_file(ringfile, &ctb, 1);
        !          2408:                if (ctb == CTB_CERT_SECKEY)
        !          2409:                        PGPSetFinfo(ringfile,'SKey','MPGP');
        !          2410:                else if (ctb == CTB_CERT_PUBKEY)
        !          2411:                PGPSetFinfo(ringfile,'PKey','MPGP');
        !          2412:                }
        !          2413: #endif
        !          2414:            return status;
        !          2415:        }                       /* Add key to key ring */
        !          2416: 
        !          2417: /*-------------------------------------------------------*/
        !          2418:     case 'x':
        !          2419:        {                       /*      Extract key from key ring
        !          2420:                                   Arguments: mcguffin, keyfile, ringfile
        !          2421:                                 */
        !          2422: 
        !          2423:            if (myArgc >= (filter_mode ? 4 : 5)) /* default key ring
        !          2424:                                                    filename */
        !          2425:                strncpy(ringfile, myArgv[(filter_mode ? 3 : 4)],
        !          2426:                        sizeof(ringfile) - 1);
        !          2427:            else
        !          2428:                strcpy(ringfile, globalPubringName);
        !          2429: 
        !          2430:            if (myArgc >= (filter_mode ? 2 : 3)) {
        !          2431:                if (myArgv[2])
        !          2432:                    /* Userid to extract */
        !          2433:                    strcpy(mcguffin, myArgv[2]);
        !          2434:                else
        !          2435:                    strcpy(mcguffin, "");
        !          2436:            } else {
        !          2437:                fprintf(pgpout,
        !          2438: LANG("\nA user ID is required to select the key you want to extract. "));
        !          2439:                if (batchmode)  /* not interactive, userid
        !          2440:                                   must be on command line */
        !          2441:                    return -1;
        !          2442:                fprintf(pgpout, LANG("\nEnter the key's user ID: "));
        !          2443: #ifdef AMIGA
        !          2444:                 requesterdesc=LANG("\nEnter the key's user ID: ");
        !          2445: #endif
        !          2446:                getstring(mcguffin, 255, TRUE);         /* echo keyboard */
        !          2447:            }
        !          2448:            CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          2449: 
        !          2450:            if (!filter_mode) {
        !          2451:                if (myArgc >= 4)
        !          2452:                    strncpy(keyfile, myArgv[3], sizeof(keyfile) - 1);
        !          2453:                else
        !          2454:                    keyfile[0] = '\0';
        !          2455: 
        !          2456:                workfile = keyfile;
        !          2457:            } else {
        !          2458:                workfile = tempfile(TMP_WIPE | TMP_TMPDIR);
        !          2459:            }
        !          2460: 
        !          2461: #ifdef MSDOS
        !          2462:            strlwr(workfile);
        !          2463:            strlwr(ringfile);
        !          2464: #endif
        !          2465: 
        !          2466:            default_extension(ringfile, PGP_EXTENSION);
        !          2467: 
        !          2468:            status = extract_from_keyring(mcguffin, workfile,
        !          2469:                                          ringfile, (filter_mode ? FALSE :
        !          2470:                                                     emit_radix_64));
        !          2471: 
        !          2472:            if (status < 0) {
        !          2473:                fprintf(pgpout, LANG("\007Keyring extract error. "));
        !          2474:                errorLvl = KEYRING_EXTRACT_ERROR;
        !          2475:                if (filter_mode)
        !          2476:                    rmtemp(workfile);
        !          2477:                return status;
        !          2478:            }
        !          2479:            if (filter_mode && !status) {
        !          2480:                if (emit_radix_64) {
        !          2481:                    /* NULL for outputfile means write to stdout */
        !          2482:                    if (armor_file(workfile, NULL, NULL, NULL, FALSE) != 0) {
        !          2483:                        errorLvl = UNKNOWN_FILE_ERROR;
        !          2484:                        return -1;
        !          2485:                    }
        !          2486:                } else {
        !          2487:                    if (writePhantomOutput(workfile) < 0) {
        !          2488:                        errorLvl = UNKNOWN_FILE_ERROR;
        !          2489:                        return -1;
        !          2490:                    }
        !          2491:                }
        !          2492:                rmtemp(workfile);
        !          2493:            }
        !          2494: #ifdef MACTC5
        !          2495:                if (status)
        !          2496:                        return KEYRING_EXTRACT_ERROR;
        !          2497:                if ((!emit_radix_64)&&(strlen(keyfile)>0)) {
        !          2498:                byte ctb;
        !          2499:                get_header_info_from_file(keyfile, &ctb, 1);
        !          2500:                if (ctb == CTB_CERT_SECKEY)
        !          2501:                        PGPSetFinfo(ringfile,'SKey','MPGP');
        !          2502:                else if (ctb == CTB_CERT_PUBKEY)
        !          2503:                        PGPSetFinfo(ringfile,'PKey','MPGP');
        !          2504:                }
        !          2505: #endif
        !          2506:            return 0;
        !          2507:        }                       /* Extract key from key ring */
        !          2508: 
        !          2509: /*-------------------------------------------------------*/
        !          2510:     case 'r':
        !          2511:        {       /*      Remove keys or selected key signatures from userid keys
        !          2512:                        Arguments: userid, ringfile
        !          2513:                 */
        !          2514: 
        !          2515:            if (myArgc >= 4)
        !          2516:                strcpy(ringfile, myArgv[3]);
        !          2517:            else                /* default key ring filename */
        !          2518:                strcpy(ringfile, globalPubringName);
        !          2519: 
        !          2520:            if (myArgc >= 3) {
        !          2521:                strcpy(mcguffin, myArgv[2]);    /* Userid to work on */
        !          2522:            } else {
        !          2523:                if (sign_flag) {
        !          2524:                    fprintf(pgpout,
        !          2525: LANG("\nA user ID is required to select the public key you want to\n\
        !          2526: remove certifying signatures from. "));
        !          2527:                } else {
        !          2528:                    fprintf(pgpout,
        !          2529: LANG("\nA user ID is required to select the key you want to remove. "));
        !          2530:                }
        !          2531:                if (batchmode)  /* not interactive, userid must be on
        !          2532:                                   command line */
        !          2533:                    return -1;
        !          2534:                fprintf(pgpout, LANG("\nEnter the key's user ID: "));
        !          2535: #ifdef AMIGA
        !          2536:                 requesterdesc=LANG("\nEnter the key's user ID: ");
        !          2537: #endif
        !          2538:                getstring(mcguffin, 255, TRUE);         /* echo keyboard */
        !          2539:            }
        !          2540:            CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          2541: 
        !          2542: #ifdef MSDOS
        !          2543:            strlwr(ringfile);
        !          2544: #endif
        !          2545:            if (!file_exists(ringfile))
        !          2546:                default_extension(ringfile, PGP_EXTENSION);
        !          2547: 
        !          2548:            if (sign_flag) {    /* Remove signatures */
        !          2549:                if (remove_sigs(mcguffin, ringfile) < 0) {
        !          2550:                    fprintf(pgpout, LANG("\007Key signature remove error. "));
        !          2551:                    errorLvl = KEYSIG_REMOVE_ERROR;
        !          2552:                    return -1;
        !          2553:                }
        !          2554:            } else {            /* Remove keyring */
        !          2555: #ifdef MACTC5
        !          2556:                        if (remove_from_keyring( NULL, mcguffin, ringfile,
        !          2557:                                        (boolean)!strcmp(ringfile, globalPubringName))) {
        !          2558: #else
        !          2559:                if (remove_from_keyring(NULL, mcguffin, ringfile,
        !          2560:                                        (boolean) (myArgc < 4)) < 0) {
        !          2561: #endif
        !          2562:                    fprintf(pgpout, LANG("\007Keyring remove error. "));
        !          2563:                    errorLvl = KEYRING_REMOVE_ERROR;
        !          2564:                    return -1;
        !          2565:                }
        !          2566:            }
        !          2567: #ifdef MACTC5
        !          2568:                {   
        !          2569:                byte ctb;
        !          2570:                get_header_info_from_file(ringfile, &ctb, 1);
        !          2571:                if (ctb == CTB_CERT_SECKEY)
        !          2572:                        PGPSetFinfo(ringfile,'SKey','MPGP');
        !          2573:                else if (ctb == CTB_CERT_PUBKEY)
        !          2574:                PGPSetFinfo(ringfile,'PKey','MPGP');
        !          2575:                PGPSetFinfo(globalPubringName,'PKey','MPGP');
        !          2576:                }
        !          2577: #endif
        !          2578:            return 0;
        !          2579:        }                       /* remove key signatures from userid */
        !          2580: 
        !          2581: /*-------------------------------------------------------*/
        !          2582:     case 'v':
        !          2583:     case 'V':                  /* -kvv */
        !          2584:        {                       /* View or remove key ring entries,
        !          2585:                                   with userid match
        !          2586:                                   Arguments: userid, ringfile
        !          2587:                                 */
        !          2588: 
        !          2589:            if (myArgc < 4)     /* default key ring filename */
        !          2590:                strcpy(ringfile, globalPubringName);
        !          2591:            else
        !          2592:                strcpy(ringfile, myArgv[3]);
        !          2593: 
        !          2594:            if (myArgc > 2) {
        !          2595:                strcpy(mcguffin, myArgv[2]);
        !          2596:                if (strcmp(mcguffin, "*") == 0)
        !          2597:                    mcguffin[0] = '\0';
        !          2598:            } else {
        !          2599:                *mcguffin = '\0';
        !          2600:            }
        !          2601: 
        !          2602:            if ((myArgc == 3) && has_extension(myArgv[2], PGP_EXTENSION)) {
        !          2603:                strcpy(ringfile, myArgv[2]);
        !          2604:                mcguffin[0] = '\0';
        !          2605:            }
        !          2606:            CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          2607: 
        !          2608: #ifdef MSDOS
        !          2609:            strlwr(ringfile);
        !          2610: #endif
        !          2611:            if (!file_exists(ringfile))
        !          2612:                default_extension(ringfile, PGP_EXTENSION);
        !          2613: 
        !          2614:            /* If a second 'v' (keychar = V), show signatures too */
        !          2615:            status = view_keyring(mcguffin, ringfile,
        !          2616:                                  (boolean) (keychar == 'V'), c_flag);
        !          2617:            if (status < 0) {
        !          2618:                fprintf(pgpout, LANG("\007Keyring view error. "));
        !          2619:                errorLvl = KEYRING_VIEW_ERROR;
        !          2620:            }
        !          2621: #ifdef MACTC5
        !          2622:                {   
        !          2623:                byte ctb;
        !          2624:                get_header_info_from_file(ringfile, &ctb, 1);
        !          2625:                if (ctb == CTB_CERT_SECKEY)
        !          2626:                        PGPSetFinfo(ringfile,'SKey','MPGP');
        !          2627:                else if (ctb == CTB_CERT_PUBKEY)
        !          2628:                PGPSetFinfo(ringfile,'PKey','MPGP');
        !          2629:                }
        !          2630: #endif
        !          2631:            return status;
        !          2632:        }                       /* view key ring entries, with userid match */
        !          2633: 
        !          2634:     default:
        !          2635:        arg_error();
        !          2636:     }
        !          2637:     return 0;
        !          2638: }                              /* do_keyopt */
        !          2639: 
        !          2640: /* comes here if user made a boo-boo. */
        !          2641: void user_error()
        !          2642: {
        !          2643:     fprintf(pgpout, LANG("\nFor a usage summary, type:  pgp -h\n"));
        !          2644:     fprintf(pgpout,
        !          2645:            LANG("For more detailed help, consult the PGP User's Guide.\n"));
        !          2646:     exitPGP(errorLvl ? errorLvl : 127);                /* error exit */
        !          2647: }
        !          2648: 
        !          2649: #if defined(DEBUG) && defined(linux)
        !          2650: #include <malloc.h>
        !          2651: #endif
        !          2652: 
        !          2653: /*
        !          2654:  * exitPGP: wipes and removes temporary files, also tries to wipe
        !          2655:  * the stack.
        !          2656:  */
        !          2657: void exitPGP(int returnval)
        !          2658: {
        !          2659:     char buf[STACK_WIPE];
        !          2660:     struct hashedpw *hpw;
        !          2661: 
        !          2662:     if (verbose)
        !          2663:        fprintf(pgpout, "exitPGP: exitcode = %d\n", returnval);
        !          2664:     for (hpw = passwds; hpw; hpw = hpw->next)
        !          2665:        memset(hpw->hash, 0, sizeof(hpw->hash));
        !          2666:     for (hpw = keypasswds; hpw; hpw = hpw->next)
        !          2667:        memset(hpw->hash, 0, sizeof(hpw->hash));
        !          2668: #ifdef MACTC5
        !          2669:        mac_cleanup_tmpf();
        !          2670: #else
        !          2671:     cleanup_tmpf();
        !          2672: #endif
        !          2673:     /* Merge any entropy we collected into the randseed.bin file */
        !          2674:     if (cryptRandOpen((struct IdeaCfbContext *)0) >= 0)
        !          2675:            cryptRandSave((struct IdeaCfbContext *)0);
        !          2676: #if defined(DEBUG) && defined(linux)
        !          2677:     if (verbose) {
        !          2678:        struct mstats mstat;
        !          2679:        mstat = mstats();
        !          2680:        printf("%d chunks used (%d bytes)  %d bytes total\n",
        !          2681:               mstat.chunks_used, mstat.bytes_used, mstat.bytes_total);
        !          2682:     }
        !          2683: #endif
        !          2684:     memset(buf, 0, sizeof(buf));       /* wipe stack */
        !          2685: #ifdef VMS
        !          2686: /*
        !          2687:  * Fake VMS style error returns with severity in bottom 3 bits
        !          2688:  */
        !          2689:     if (returnval)
        !          2690:        returnval = (returnval << 3) | 0x10000002;
        !          2691:     else
        !          2692:        returnval = 0x10000001;
        !          2693: #endif                         /* VMS */
        !          2694:     exit(returnval);
        !          2695: }
        !          2696: 
        !          2697: static void arg_error()
        !          2698: {
        !          2699:     signon_msg();
        !          2700:     fprintf(pgpout, LANG("\nInvalid arguments.\n"));
        !          2701:     errorLvl = BAD_ARG_ERROR;
        !          2702:     user_error();
        !          2703: }
        !          2704: 
        !          2705: /*
        !          2706:  * Check for language specific help files in PGPPATH, then the system
        !          2707:  * directory.  If that fails, check for the default pgp.hlp, again
        !          2708:  * first a private copy, then the system-wide one.
        !          2709:  *
        !          2710:  * System-wide copies currently only exist on Unix.
        !          2711:  */
        !          2712: static void build_helpfile(char *helpfile, char const *extra)
        !          2713: {
        !          2714:     if (strcmp(language, "en")) {
        !          2715:        buildfilename(helpfile, language);
        !          2716:        strcat(helpfile, extra);
        !          2717:        force_extension(helpfile, HLP_EXTENSION);
        !          2718:        if (file_exists(helpfile))
        !          2719:            return;
        !          2720: #ifdef PGP_SYSTEM_DIR
        !          2721:        strcpy(helpfile, PGP_SYSTEM_DIR);
        !          2722:        strcat(helpfile, language);
        !          2723:        strcat(helpfile, extra);
        !          2724:        force_extension(helpfile, HLP_EXTENSION);
        !          2725:        if (file_exists(helpfile))
        !          2726:            return;
        !          2727: #endif
        !          2728:     }
        !          2729:     buildfilename(helpfile, "pgp");
        !          2730:     strcat(helpfile, extra);
        !          2731:     force_extension(helpfile, HLP_EXTENSION);
        !          2732: #ifdef PGP_SYSTEM_DIR
        !          2733:     if (file_exists(helpfile))
        !          2734:        return;
        !          2735:     strcpy(helpfile, PGP_SYSTEM_DIR);
        !          2736:     strcat(helpfile, "pgp");
        !          2737:     strcat(helpfile, extra);
        !          2738:     force_extension(helpfile, HLP_EXTENSION);
        !          2739: #endif
        !          2740: }
        !          2741: 
        !          2742: static void usage()
        !          2743: {
        !          2744:     char helpfile[MAX_PATH];
        !          2745:     char *tmphelp = helpfile;
        !          2746:     extern unsigned char *ext_c_ptr;
        !          2747: 
        !          2748:     signon_msg();
        !          2749:     build_helpfile(helpfile, "");
        !          2750: 
        !          2751:     if (ext_c_ptr) {
        !          2752:        /* conversion to external format necessary */
        !          2753:        tmphelp = tempfile(TMP_TMPDIR);
        !          2754:        CONVERSION = EXT_CONV;
        !          2755:        if (copyfiles_by_name(helpfile, tmphelp) < 0) {
        !          2756:            rmtemp(tmphelp);
        !          2757:            tmphelp = helpfile;
        !          2758:        }
        !          2759:        CONVERSION = NO_CONV;
        !          2760:     }
        !          2761:     /* built-in help if pgp.hlp is not available */
        !          2762:     if (more_file(tmphelp, FALSE) < 0)
        !          2763:        fprintf(pgpout, LANG("\nUsage summary:\
        !          2764: \nTo encrypt a plaintext file with recipent's public key, type:\
        !          2765: \n   pgp -e textfile her_userid [other userids] (produces textfile.pgp)\
        !          2766: \nTo sign a plaintext file with your secret key:\
        !          2767: \n   pgp -s textfile [-u your_userid]           (produces textfile.pgp)\
        !          2768: \nTo sign a plaintext file with your secret key, and then encrypt it\
        !          2769: \n   with recipent's public key, producing a .pgp file:\
        !          2770: \n   pgp -es textfile her_userid [other userids] [-u your_userid]\
        !          2771: \nTo encrypt with conventional encryption only:\
        !          2772: \n   pgp -c textfile\
        !          2773: \nTo decrypt or check a signature for a ciphertext (.pgp) file:\
        !          2774: \n   pgp ciphertextfile [-o plaintextfile]\
        !          2775: \nTo produce output in ASCII for email, add the -a option to other options.\
        !          2776: \nTo generate your own unique public/secret key pair:  pgp -kg\
        !          2777: \nFor help on other key management functions, type:   pgp -k\n"));
        !          2778:     if (ext_c_ptr)
        !          2779:        rmtemp(tmphelp);
        !          2780:     exit(BAD_ARG_ERROR);       /* error exit */
        !          2781: }
        !          2782: 
        !          2783: static void key_usage()
        !          2784: {
        !          2785:     char helpfile[MAX_PATH];
        !          2786:     char *tmphelp = helpfile;
        !          2787:     extern unsigned char *ext_c_ptr;
        !          2788: 
        !          2789:     signon_msg();
        !          2790:     build_helpfile(helpfile, "key");
        !          2791: 
        !          2792:     if (ext_c_ptr) {
        !          2793:        /* conversion to external format necessary */
        !          2794:        tmphelp = tempfile(TMP_TMPDIR);
        !          2795:        CONVERSION = EXT_CONV;
        !          2796:        if (copyfiles_by_name(helpfile, tmphelp) < 0) {
        !          2797:            rmtemp(tmphelp);
        !          2798:            tmphelp = helpfile;
        !          2799:        }
        !          2800:        CONVERSION = NO_CONV;
        !          2801:     }
        !          2802:     /* built-in help if key.hlp is not available */
        !          2803:     if (more_file(tmphelp, FALSE) < 0)
        !          2804:        /* only use built-in help if there is no helpfile */
        !          2805:        fprintf(pgpout, LANG("\nKey management functions:\
        !          2806: \nTo generate your own unique public/secret key pair:\
        !          2807: \n   pgp -kg\
        !          2808: \nTo add a key file's contents to your public or secret key ring:\
        !          2809: \n   pgp -ka keyfile [keyring]\
        !          2810: \nTo remove a key or a user ID from your public or secret key ring:\
        !          2811: \n   pgp -kr userid [keyring]\
        !          2812: \nTo edit your user ID or pass phrase:\
        !          2813: \n   pgp -ke your_userid [keyring]\
        !          2814: \nTo extract (copy) a key from your public or secret key ring:\
        !          2815: \n   pgp -kx userid keyfile [keyring]\
        !          2816: \nTo view the contents of your public key ring:\
        !          2817: \n   pgp -kv[v] [userid] [keyring]\
        !          2818: \nTo check signatures on your public key ring:\
        !          2819: \n   pgp -kc [userid] [keyring]\
        !          2820: \nTo sign someone else's public key on your public key ring:\
        !          2821: \n   pgp -ks her_userid [-u your_userid] [keyring]\
        !          2822: \nTo remove selected signatures from a userid on a keyring:\
        !          2823: \n   pgp -krs userid [keyring]\
        !          2824: \n"));
        !          2825:     if (ext_c_ptr)
        !          2826:        rmtemp(tmphelp);
        !          2827:     exit(BAD_ARG_ERROR);       /* error exit */
        !          2828: }
        !          2829: 
        !          2830: char **ParseRecipients(char **recipients)
        !          2831: {
        !          2832:        /*
        !          2833:         * ParseRecipients() expects an array of pointers to
        !          2834:         * characters, usually the array returned by the C startup
        !          2835:         * code. Then it will look for entries beginning with the
        !          2836:         * string "-@" followed by a filename, which may be appended
        !          2837:         * directly or seperated by a blank.
        !          2838:         *
        !          2839:         * If the file exists and is readable, the routine will load
        !          2840:         * the contents and insert it into the command line as if the
        !          2841:         * names had been specified there.
        !          2842:         *
        !          2843:         * Each entry in the file consists of one line. The file line
        !          2844:         * will be treated as one argument, no matter whether it
        !          2845:         * contains spaces or not. Lines beginning with "#" will be
        !          2846:         * ignored and treated as comments. Empty lines will be ignored
        !          2847:         * also. Trailing white spaces will be removed.
        !          2848:         *
        !          2849:         * Currently, ParseRecipients() uses one fixed buffer, meaning,
        !          2850:         * that one single line must not be longer than 255 characters.
        !          2851:         * The number of included lines is unlimited.
        !          2852:         *
        !          2853:         * When any kind of problem occurs, PGP will terminate and do
        !          2854:         * nothing. No need to test for an error, the result is always
        !          2855:         * correct.
        !          2856:         *
        !          2857:         *             21-Sep-95, Peter Simons <[email protected]>
        !          2858:         */
        !          2859: 
        !          2860:        char **backup = recipients, **new;
        !          2861:        int entrynum;
        !          2862:        int MAX_RECIPIENTS = 128;   /* The name is somewhat wrong. of
        !          2863:                                     * course the memory handling is
        !          2864:                                     * dynamic.
        !          2865:                                     */
        !          2866: 
        !          2867:        /* Check whether we need to do something or not. */
        !          2868:        while(*recipients) {
        !          2869:                if (!strncasecmp(*recipients, INCLUDE_MARK, INCLUDE_MARK_LEN))
        !          2870:                    break;
        !          2871:                recipients++;
        !          2872:        }
        !          2873:        if (!*recipients)
        !          2874:          return backup;        /* nothin' happened */
        !          2875: 
        !          2876:        recipients=backup;
        !          2877:        if (!(new = malloc(MAX_RECIPIENTS * sizeof(char *))))
        !          2878:          exitPGP(OUT_OF_MEM);
        !          2879:        entrynum = 0;
        !          2880: 
        !          2881:        while(*recipients) {
        !          2882:                if (strncasecmp(*recipients, INCLUDE_MARK, INCLUDE_MARK_LEN))
        !          2883:                 {
        !          2884:                        new[entrynum++] = *recipients++;
        !          2885:                        if (entrynum == MAX_RECIPIENTS) {
        !          2886:                                /* Current buffer is too small.
        !          2887:                                 * Use realloc() to largen itt.
        !          2888:                                 */
        !          2889:                                MAX_RECIPIENTS += 128;
        !          2890:                                if (!(new = realloc(new,
        !          2891:                                  MAX_RECIPIENTS * sizeof(char *))))
        !          2892:                                  exitPGP(OUT_OF_MEM);
        !          2893:                        }
        !          2894:                }
        !          2895:                else {
        !          2896:                        /* We got a hit! Load the file and parse it. */
        !          2897:                        FILE *fh;
        !          2898:                        char *filename, tempbuf[256];
        !          2899: 
        !          2900:                        if (strlen(*recipients) == INCLUDE_MARK_LEN)
        !          2901:                          filename = *++recipients;
        !          2902:                        else
        !          2903:                          filename = *recipients+INCLUDE_MARK_LEN;
        !          2904:                        fprintf(pgpout, LANG("\nIncluding \"%s\"...\n"), filename);
        !          2905:                        if (!(fh = fopen(filename, "r"))) {
        !          2906:                                perror("PGP");
        !          2907:                                exitPGP(UNKNOWN_FILE_ERROR);
        !          2908:                        }
        !          2909:                        while(fgets(tempbuf, sizeof(tempbuf)-1, fh)) {
        !          2910:                                int i = strlen(tempbuf);
        !          2911: 
        !          2912:                                /* Test for comments or empty lines. */
        !          2913:                                if (!i || *tempbuf == '#')
        !          2914:                                  continue;
        !          2915: 
        !          2916:                                /* Remove trailing blanks. */
        !          2917:                                while (isspace(tempbuf[i-1]))
        !          2918:                                  i--;
        !          2919:                                tempbuf[i] = '\0';
        !          2920: 
        !          2921:                                /* Copy new entry to new */
        !          2922:                                if (!(new[entrynum++] = strdup(tempbuf)))
        !          2923:                                  exitPGP(OUT_OF_MEM);
        !          2924:                                if (entrynum == MAX_RECIPIENTS) {
        !          2925:                                        /* Current buffer is too small.
        !          2926:                                         * Use realloc() to largen itt.
        !          2927:                                         */
        !          2928:                                        MAX_RECIPIENTS += 128;
        !          2929:                                        if (!(new = realloc(new,
        !          2930:                                          MAX_RECIPIENTS * sizeof(char *))))
        !          2931:                                          exitPGP(OUT_OF_MEM);
        !          2932:                                }
        !          2933:                        }
        !          2934:                        if (ferror(fh)) {
        !          2935:                                perror("PGP");
        !          2936:                                exitPGP(UNKNOWN_FILE_ERROR);
        !          2937:                        }
        !          2938:                        fclose(fh);
        !          2939:                        recipients++;
        !          2940:                }
        !          2941:        }
        !          2942: 
        !          2943:        /*
        !          2944:         * We have to write one trailing NULL pointer.
        !          2945:         * Check array size first.
        !          2946:         */
        !          2947:        if (entrynum == MAX_RECIPIENTS) {
        !          2948:                if (!(new = realloc(new, (MAX_RECIPIENTS+1) * sizeof(char *))))
        !          2949:                  exitPGP(OUT_OF_MEM);
        !          2950:        }
        !          2951:        new[entrynum] = NULL;
        !          2952:        return new;
        !          2953: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.