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

1.1.1.7 ! root        1: /* #define TEMP_VERSION        / * if defined, temporary experimental version of PGP */
        !             2: /*     pgp.c -- main module for PGP.
        !             3:        PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
        !             4: 
        !             5:        Synopsis:  PGP uses public-key encryption to protect E-mail. 
        !             6:        Communicate securely with people you've never met, with no secure
        !             7:        channels needed for prior exchange of keys.  PGP is well featured and
        !             8:        fast, with sophisticated key management, digital signatures, data
        !             9:        compression, and good ergonomic design.
        !            10: 
        !            11:        The original PGP version 1.0 was written by Philip Zimmermann, of
        !            12:        Phil's Pretty Good(tm) Software.  Many parts of later versions of 
        !            13:        PGP were developed by an international collaborative effort, 
        !            14:        involving a number of contributors, including major efforts by:
        !            15:                Branko Lankester <[email protected]>
        !            16:                Hal Finney <[email protected]>
        !            17:                Peter Gutmann <[email protected]>
        !            18:        Other contributors who ported or translated or otherwise helped include:
        !            19:                Jean-loup Gailly in France
        !            20:                Hugh Kennedy in Germany
        !            21:                Lutz Frank in Germany
        !            22:                Cor Bosman in The Netherlands
        !            23:                Felipe Rodriquez Svensson in The Netherlands
        !            24:                Armando Ramos in Spain
        !            25:                Miguel Angel Gallardo Ortiz in Spain
        !            26:                Harry Bush and Maris Gabalins in Latvia
        !            27:                Zygimantas Cepaitis in Lithuania
        !            28:                Alexander Smishlajev
        !            29:                Peter Suchkow and Andrew Chernov in Russia
        !            30:                David Vincenzetti in Italy
        !            31:                ...and others.
        !            32: 
        !            33: 
        !            34:        (c) Copyright 1990-1994 by Philip Zimmermann.  All rights reserved.
        !            35:        The author assumes no liability for damages resulting from the use
        !            36:        of this software, even if the damage results from defects in this
        !            37:        software.  No warranty is expressed or implied.
        !            38: 
        !            39:        Note that while most PGP source modules bear Philip Zimmermann's
        !            40:        copyright notice, many of them have been revised or entirely written
        !            41:        by contributors who frequently failed to put their names in their
        !            42:        code.  Code that has been incorporated into PGP from other authors
        !            43:        was either originally published in the public domain or is used with
        !            44:        permission from the various authors.
        !            45: 
        !            46:        PGP is available for free to the public under certain restrictions.
        !            47:        See the PGP User's Guide (included in the release package) for
        !            48:        important information about licensing, patent restrictions on
        !            49:        certain algorithms, trademarks, copyrights, and export controls.
        !            50: 
        !            51: 
        !            52:        Philip Zimmermann may be reached at:
        !            53:                Boulder Software Engineering
        !            54:                3021 Eleventh Street
        !            55:                Boulder, Colorado 80304  USA
        !            56:                (303) 541-0140  (voice or FAX)
        !            57:                email:  [email protected]
        !            58: 
        !            59: 
        !            60:        PGP will run on MSDOS, Sun Unix, VAX/VMS, Ultrix, Atari ST, 
        !            61:        Commodore Amiga, and OS/2.  Note:  Don't try to do anything with 
        !            62:        this source code without looking at the PGP User's Guide.
        !            63: 
        !            64:        PGP combines the convenience of the Rivest-Shamir-Adleman (RSA)
        !            65:        public key cryptosystem with the speed of fast conventional
        !            66:        cryptographic algorithms, fast message digest algorithms, data
        !            67:        compression, and sophisticated key management.  And PGP performs 
        !            68:        the RSA functions faster than most other software implementations.  
        !            69:        PGP is RSA public key cryptography for the masses.
        !            70: 
        !            71:        Uses RSA Data Security, Inc. MD5 Message Digest Algorithm
        !            72:        as a hash for signatures.  Uses the ZIP algorithm for compression.
        !            73:        Uses the ETH IPES/IDEA algorithm for conventional encryption.
        !            74: 
        !            75:        PGP generally zeroes its used stack and memory areas before exiting.
        !            76:        This avoids leaving sensitive information in RAM where other users
        !            77:        could find it later.  The RSA library and keygen routines also
        !            78:        sanitize their own stack areas.  This stack sanitizing has not been
        !            79:        checked out under all the error exit conditions, when routines exit
        !            80:        abnormally.  Also, we must find a way to clear the C I/O library
        !            81:        file buffers, the disk buffers, and and cache buffers.
        !            82: 
        !            83:        Revisions:
        !            84:                Version 1.0 -  5 Jun 91
        !            85:                Version 1.4 - 19 Jan 92
        !            86:                Version 1.5 - 12 Feb 92
        !            87:                Version 1.6 - 24 Feb 92
        !            88:                Version 1.7 - 29 Mar 92
        !            89:                Version 1.8 - 23 May 92
        !            90:                Version 2.0 -  2 Sep 92
        !            91:                Version 2.1 -  6 Dec 92
        !            92:                Version 2.2 -  6 Mar 93
        !            93:                Version 2.3 - 13 Jun 93
        !            94:                Version 2.3a-  1 Jul 93
        !            95:                Version 2.4 -  6 Nov 93
        !            96:                Version 2.5 -  5 May 94
        !            97:                Version 2.6 - 22 May 94
        !            98: 
        !            99:        Modified: 12-Nov-92 HAJK
        !           100:        Add FDL stuff for VAX/VMS local mode. 
        !           101: */
        !           102: 
        !           103: 
        !           104: #include <ctype.h>
        !           105: #ifndef AMIGA
        !           106: #include <signal.h>
        !           107: #endif
        !           108: #include <stdio.h>
        !           109: #include <stdlib.h>
        !           110: #include <string.h>
        !           111: #include "system.h"
        !           112: #include "mpilib.h"
        !           113: #include "random.h"
        !           114: #include "crypto.h"
        !           115: #include "fileio.h"
        !           116: #include "keymgmt.h"
        !           117: #include "language.h"
        !           118: #include "pgp.h"
        !           119: #include "exitpgp.h"
        !           120: #include "charset.h"
        !           121: #include "getopt.h"
        !           122: #include "config.h"
        !           123: #include "keymaint.h"
        !           124: #include "keyadd.h"
        !           125: #include "rsaglue.h"
        !           126: #ifdef  M_XENIX
        !           127: char *strstr();
        !           128: long time();
        !           129: #endif
        !           130: 
        !           131: #ifdef MSDOS
        !           132: #ifdef __ZTC__ /* Extend stack for Zortech C */
        !           133: unsigned _stack_ = 24*1024;
        !           134: #endif
        !           135: #ifdef __TURBOC__
        !           136: unsigned _stklen = 24*1024;
        !           137: #endif
        !           138: #endif
        !           139: #define        STACK_WIPE      4096
        !           140: 
        !           141: /* Global filenames and system-wide file extensions... */
        !           142: char rel_version[] = _LANG("2.6");     /* release version */
        !           143: static char rel_date[] = "23 May 94";  /* release date */
        !           144: char PGP_EXTENSION[] = ".pgp";
        !           145: char ASC_EXTENSION[] = ".asc";
        !           146: char SIG_EXTENSION[] = ".sig";
        !           147: char BAK_EXTENSION[] = ".bak";
        !           148: static char HLP_EXTENSION[] = ".hlp";
        !           149: char CONSOLE_FILENAME[] = "_CONSOLE";
        !           150: static char HELP_FILENAME[] = "pgp.hlp";
        !           151: 
        !           152: /* These files use the environmental variable PGPPATH as a default path: */
        !           153: char globalPubringName[MAX_PATH];
        !           154: char globalSecringName[MAX_PATH];
        !           155: char globalRandseedName[MAX_PATH];
        !           156: char globalCommentString[128];
        !           157: 
        !           158: /* Flags which are global across the driver code files */
        !           159: boolean verbose = FALSE;       /* -l option: display maximum information */
        !           160: FILE   *pgpout;                        /* Place for routine messages */
        !           161: 
        !           162: static void usage(void);
        !           163: static void key_usage(void);
        !           164: static void arg_error(void);
        !           165: static void initsigs(void);
        !           166: static int do_keyopt(char);
        !           167: static int do_decrypt(char *);
        !           168: static void do_armorfile(char *);
        !           169: 
        !           170: 
        !           171: /*     Various compression signatures: PKZIP, Zoo, GIF, Arj, and HPACK.
        !           172:        Lha(rc) is handled specially in the code; it is missing from the
        !           173:        compressSig structure intentionally.  If more formats are added,
        !           174:        put them before lharc to keep the code consistent.
        !           175: */
        !           176: static char *compressSig[] =  { "PK\03\04", "ZOO ", "GIF8", "\352\140",
        !           177:        "HPAK", "\037\213", "\037\235", "\032\013", "\032HP%"
        !           178:        /* lharc is special, must be last */ };
        !           179: static char *compressName[] = { "PKZIP",   "Zoo",  "GIF",  "Arj",
        !           180:        "Hpack", "gzip", "compressed", "PAK", "Hyper",
        !           181:        "LHarc" };
        !           182: static char *compressExt[] =  { ".zip",  ".zoo",  ".gif",  ".arj",
        !           183:        ".hpk", ".z", ".Z", ".pak", ".hyp",
        !           184:        ".lzh" };
        !           185: 
        !           186: /* "\032\0??", "ARC", ".arc" */
        !           187: 
        !           188: int compressSignature(byte *header)
        !           189: /* Returns file signature type from a number of popular compression formats
        !           190:    or -1 if no match */
        !           191: {
        !           192:        int i;
        !           193: 
        !           194:        for (i=0; i<sizeof(compressSig)/sizeof(*compressSig); i++)
        !           195:                if (!strncmp((char *)header, compressSig[i], strlen(compressSig[i])))
        !           196:                        return i;
        !           197:        /* Special check for lharc files */
        !           198:        if (header[2]=='-' && header[3]=='l' && (header[4]=='z'||header[4]=='h') &&
        !           199:                header[6]=='-')
        !           200:                return i;
        !           201:        return -1;
        !           202: }      /* compressSignature */
        !           203: 
        !           204: 
        !           205: static boolean file_compressible(char *filename)
        !           206: /* returns TRUE iff file is likely to be compressible */
        !           207: {
        !           208:        byte header[8];
        !           209:        get_header_info_from_file( filename, header, 8 );
        !           210:        if (compressSignature( header ) >= 0)
        !           211:                return FALSE;   /* probably not compressible */
        !           212:        return TRUE;    /* possibly compressible */
        !           213: }      /* compressible */
        !           214: 
        !           215: 
        !           216: /* Possible error exit codes - not all of these are used.  Note that we
        !           217:    don't use the ANSI EXIT_SUCCESS and EXIT_FAILURE.  To make things
        !           218:    easier for compilers which don't support enum we use #defines */
        !           219: 
        !           220: #define EXIT_OK                                0
        !           221: #define INVALID_FILE_ERROR             1
        !           222: #define FILE_NOT_FOUND_ERROR           2
        !           223: #define UNKNOWN_FILE_ERROR             3
        !           224: #define NO_BATCH                       4
        !           225: #define BAD_ARG_ERROR                  5
        !           226: #define INTERRUPT                      6
        !           227: #define OUT_OF_MEM                     7
        !           228: 
        !           229: /* Keyring errors: Base value = 10 */
        !           230: #define KEYGEN_ERROR                   10
        !           231: #define NONEXIST_KEY_ERROR             11
        !           232: #define KEYRING_ADD_ERROR              12
        !           233: #define KEYRING_EXTRACT_ERROR          13
        !           234: #define KEYRING_EDIT_ERROR             14
        !           235: #define KEYRING_VIEW_ERROR             15
        !           236: #define KEYRING_REMOVE_ERROR           16
        !           237: #define KEYRING_CHECK_ERROR            17
        !           238: #define KEY_SIGNATURE_ERROR            18
        !           239: #define KEYSIG_REMOVE_ERROR            19
        !           240: 
        !           241: /* Encode errors: Base value = 20 */
        !           242: #define SIGNATURE_ERROR                        20
        !           243: #define RSA_ENCR_ERROR                 21
        !           244: #define ENCR_ERROR                     22
        !           245: #define COMPRESS_ERROR                 23
        !           246: 
        !           247: /* Decode errors: Base value = 30 */
        !           248: #define SIGNATURE_CHECK_ERROR          30
        !           249: #define RSA_DECR_ERROR                 31
        !           250: #define DECR_ERROR                     32
        !           251: #define DECOMPRESS_ERROR               33
        !           252: 
        !           253: 
        !           254: #ifdef SIGINT
        !           255: void breakHandler(int sig)
        !           256: /* This function is called if a BREAK signal is sent to the program.  In this
        !           257:    case we zap the temporary files.
        !           258: */
        !           259: {
        !           260: #ifdef UNIX
        !           261:        if (sig == SIGPIPE) {
        !           262:                signal(SIGPIPE, SIG_IGN);
        !           263:                exitPGP(INTERRUPT);
        !           264:        }
        !           265:        if (sig != SIGINT)
        !           266:                fprintf(stderr, "\nreceived signal %d\n", sig);
        !           267:        else
        !           268: #endif
        !           269:                fprintf(pgpout,LANG("\nStopped at user request\n"));
        !           270:        exitPGP(INTERRUPT);
        !           271: }
        !           272: #endif
        !           273: 
        !           274: 
        !           275: static void clearscreen(void)
        !           276: {      /* Clears screen and homes the cursor. */
        !           277:        fprintf(pgpout,"\n\033[0;0H\033[J\r           \r");     /* ANSI sequence. */
        !           278:        fflush(pgpout);
        !           279: }
        !           280: 
        !           281: static void signon_msg(void)
        !           282: {      /*      We had to process the config file first to possibly select the 
        !           283:                foreign language to translate the sign-on line that follows... */
        !           284:        word32 tstamp;
        !           285:                /* display message only once to allow calling multiple times */
        !           286:        static boolean printed = FALSE;
        !           287: 
        !           288:        if (quietmode || printed)
        !           289:                return;
        !           290:        printed = TRUE;
        !           291:        fprintf(stderr,LANG("Pretty Good Privacy(tm) %s - Public-key encryption for the masses.\n"),
        !           292:                rel_version);
        !           293: #ifdef TEMP_VERSION
        !           294:        fputs("Internal development version only - not for general release.\n", stderr);
        !           295: #endif
        !           296:        fprintf(stderr, LANG("(c) 1990-1994 Philip Zimmermann, Phil's Pretty Good Software. %s\n"),
        !           297:                rel_date);
        !           298:        fputs(LANG (signon_legalese), stderr);
        !           299:         fputs(LANG("Export of this software may be restricted by the U.S. government.\n"),stderr);
        !           300: 
        !           301:        get_timestamp((byte *)&tstamp); /* timestamp points to tstamp */
        !           302:        fprintf(pgpout,"Current time: %s\n",ctdate(&tstamp));
        !           303: }
        !           304: 
        !           305: 
        !           306: #ifdef TEMP_VERSION    /* temporary experimental version of PGP */
        !           307: #include <time.h>
        !           308: #define CREATION_DATE 0x2DC079A4ul
        !           309:   /* CREATION_DATE is Fri Apr 29 03:06:12 1994 UTC */
        !           310: #define LIFESPAN       ((unsigned long) 60L * (unsigned long) 86400L)
        !           311:        /* LIFESPAN is 60 days */
        !           312: void check_expiration_date(void)
        !           313: /* If this is an experimental version of PGP, cut its life short */
        !           314: {
        !           315:        if (get_timestamp(NULL) > (CREATION_DATE + LIFESPAN)) {
        !           316:                fprintf(stderr,"\n\007This experimental version of PGP has expired.\n");
        !           317:                exit(-1);       /* error exit */
        !           318:        }
        !           319: }      /* check_expiration_date */
        !           320: #else  /* no expiration date */
        !           321: #define check_expiration_date() /* null statement */
        !           322: #endif /* TEMP_VERSION */
        !           323: 
        !           324: 
        !           325: 
        !           326: /* -f means act as a unix-style filter */
        !           327: /* -i means internalize extended file attribute information, only supported
        !           328:  *          between like (or very compatible) operating systems. */
        !           329: /* -l means show longer more descriptive diagnostic messages */
        !           330: /* -m means display plaintext output on screen, like unix "more" */
        !           331: /* -d means decrypt only, leaving inner signature wrapping intact */
        !           332: /* -t means treat as pure text and convert to canonical text format */
        !           333: 
        !           334: /* Used by getopt function... */
        !           335: #define OPTIONS "abcdefghiklmo:prstu:vwxz:ABCDEFGHIKLMO:PRSTU:VWX?"
        !           336: extern int optind;
        !           337: extern char *optarg;
        !           338: 
        !           339: boolean emit_radix_64 = FALSE;         /* set by config file */
        !           340: static boolean sign_flag = FALSE;
        !           341: boolean moreflag = FALSE;
        !           342: boolean filter_mode = FALSE;
        !           343: static boolean preserve_filename = FALSE;
        !           344: static boolean decrypt_only_flag = FALSE;
        !           345: static boolean de_armor_only = FALSE;
        !           346: static boolean strip_sig_flag = FALSE;
        !           347: boolean clear_signatures = TRUE;
        !           348: boolean strip_spaces;
        !           349: static boolean c_flag = FALSE;
        !           350: boolean encrypt_to_self = FALSE; /* should I encrypt messages to myself? */
        !           351: boolean batchmode = FALSE;     /* if TRUE: don't ask questions */
        !           352: boolean quietmode = FALSE;
        !           353: boolean force_flag = FALSE;    /* overwrite existing file without asking */
        !           354: boolean pkcs_compat = 1;
        !           355: #ifdef VMS     /* kludge for those stupid VMS variable-length text records */
        !           356: char literal_mode = MODE_TEXT; /* MODE_TEXT or MODE_BINARY for literal packet */
        !           357: #else  /* not VMS */
        !           358: char literal_mode = MODE_BINARY;       /* MODE_TEXT or MODE_BINARY for literal packet */
        !           359: #endif /* not VMS */
        !           360: /* my_name is substring of default userid for secret key to make signatures */
        !           361: char my_name[256] = "\0"; /* null my_name means take first userid in ring */
        !           362: boolean keepctx = FALSE;       /* TRUE means keep .ctx file on decrypt */
        !           363: /* Ask for each key separately if it should be added to the keyring */
        !           364: boolean interactive_add = FALSE;
        !           365: boolean compress_enabled = TRUE;       /* attempt compression before encryption */
        !           366: long timeshift = 0L;   /* seconds from GMT timezone */
        !           367: boolean legal_kludge;
        !           368: int version_byte = VERSION_BYTE_OLD;
        !           369: boolean nomanual = 0;
        !           370: 
        !           371: 
        !           372: static boolean attempt_compression; /* attempt compression before encryption */
        !           373: static char *outputfile = NULL;
        !           374: static int errorLvl = EXIT_OK;
        !           375: static char mcguffin[256]; /* userid search tag */
        !           376: boolean signature_checked = FALSE;
        !           377: char plainfile[MAX_PATH];
        !           378: int myArgc = 2;
        !           379: char **myArgv;
        !           380: struct hashedpw *passwds = 0, *keypasswds = 0;
        !           381: static struct hashedpw **passwdstail = &passwds;
        !           382: 
        !           383: int main(int argc, char *argv[])
        !           384: {
        !           385:        int status, opt;
        !           386:        char *inputfile = NULL;
        !           387:        char **recipient = NULL;
        !           388:        char **mcguffins;
        !           389:        char *workfile, *tempf;
        !           390:        boolean nestflag = FALSE;
        !           391:        boolean decrypt_mode = FALSE;
        !           392:        boolean wipeflag = FALSE;
        !           393:        boolean armor_flag = FALSE;             /* -a option */
        !           394:        boolean separate_signature = FALSE;
        !           395:        boolean keyflag = FALSE;
        !           396:        boolean encrypt_flag = FALSE;
        !           397:        boolean conventional_flag = FALSE;
        !           398:        char *clearfile = NULL;
        !           399:        char *literal_file = NULL;
        !           400:        char literal_file_name[MAX_PATH];
        !           401:        char cipherfile[MAX_PATH];
        !           402:        char keychar = '\0';
        !           403:     char *p;
        !           404:        byte ctb;
        !           405:        struct hashedpw *hpw;
        !           406: 
        !           407:        /* Initial messages to stderr */
        !           408:        pgpout = stderr;
        !           409: 
        !           410: #ifdef DEBUG1
        !           411:        verbose = TRUE;
        !           412: #endif
        !           413:        /* The various places one can get passwords from.
        !           414:         * We accumulate them all into two lists.  One is
        !           415:         * to try on keys only, and is stored in no particular
        !           416:         * order, while the other is of unknown purpose so
        !           417:         * far (they may be used for conventional encryption
        !           418:         * or decryption as well), and are kept in a specific
        !           419:         * order.  If any password in the general list is found
        !           420:         * to decode a key, it is moved to the key list.
        !           421:         * The general list is not grown after initialization,
        !           422:         * so the tail pointer is not used after this.
        !           423:         */
        !           424: 
        !           425:        if ((p = getenv("PGPPASS")) != NULL) {
        !           426:                hpw = xmalloc(sizeof(struct hashedpw));
        !           427:                hashpass(p, strlen(p), hpw->hash);
        !           428:                /* Add to linked list of key passwords */
        !           429:                hpw->next = keypasswds;
        !           430:                keypasswds = hpw;
        !           431:        }
        !           432: 
        !           433:        /* The -z "password" option should be used instead of PGPPASS if
        !           434:         * the environment can be displayed with the ps command (eg. BSD).
        !           435:         * If the system does not allow overwriting of the command line
        !           436:         * argument list but if it has a "hidden" environment, PGPPASS
        !           437:         * should be used.
        !           438:         */
        !           439:        for (opt = 1; opt < argc; ++opt) {
        !           440:                p = argv[opt];
        !           441:                if (p[0] != '-' || p[1] != 'z')
        !           442:                        continue;
        !           443:                /* Accept either "-zpassword" or "-z password" */
        !           444:                p += 2;
        !           445:                if (!*p)
        !           446:                        p = argv[++opt];
        !           447:                /* p now points to password */
        !           448:                if (!p)
        !           449:                        break;  /* End of arg list - ignore */
        !           450:                hpw = xmalloc(sizeof(struct hashedpw));
        !           451:                hashpass(p, strlen(p), hpw->hash);
        !           452:                /* Wipe password */
        !           453:                while (*p)
        !           454:                        *p++ = ' ';
        !           455:                /* Add to tail of linked list of passwords */
        !           456:                hpw->next = 0;
        !           457:                *passwdstail = hpw;
        !           458:                passwdstail = &hpw->next;
        !           459:        }
        !           460:        /*
        !           461:         * If PGPPASSFD is set in the environment try to read the password
        !           462:         * from this file descriptor.  If you set PGPPASSFD to 0 pgp will
        !           463:         * use the first line read from stdin as password.
        !           464:         */
        !           465:        if ((p = getenv("PGPPASSFD")) != NULL)
        !           466:        {
        !           467:                int passfd;
        !           468:                if (*p && (passfd = atoi(p)) >= 0)
        !           469:                {
        !           470:                        char pwbuf[256];
        !           471:                        p = pwbuf;
        !           472:                        while (read(passfd, p, 1) == 1 && *p != '\n')
        !           473:                                ++p;
        !           474:                        hpw = xmalloc(sizeof(struct hashedpw));
        !           475:                        hashpass(pwbuf, p-pwbuf, hpw->hash);
        !           476:                        memset(pwbuf, 0, p-pwbuf);
        !           477:                        /* Add to tail of linked list of passwords */
        !           478:                        hpw->next = 0;
        !           479:                        *passwdstail = hpw;
        !           480:                        passwdstail = &hpw->next;
        !           481:                }
        !           482:        }
        !           483: 
        !           484:        /* Process the config file.  The following override each other:
        !           485:           - Hard-coded defualts
        !           486:           - The system config file
        !           487:           - Hard-coded defaults for security-critical things
        !           488:           - The user's config file
        !           489:           - Environment variables
        !           490:           - Command-line options.
        !           491:         */
        !           492:        opt = 0;        /* Number of config files read */
        !           493: #ifdef PGP_SYSTEM_DIR
        !           494:        strcpy(mcguffin, PGP_SYSTEM_DIR);
        !           495:        strcat(mcguffin, "config.txt");
        !           496:        if (access(mcguffin, 0) == 0) {
        !           497:                opt++;
        !           498:                /*
        !           499:                 * Note: errors here are NOT fatal, so that people
        !           500:                 * can use PGP with a corrputed system file.
        !           501:                 */
        !           502:                processConfigFile(mcguffin);
        !           503:        }
        !           504: #endif
        !           505: 
        !           506:        /*
        !           507:         * These must be personal; the system config file may not
        !           508:         * influence them.
        !           509:         */
        !           510:        buildfilename(globalPubringName, "pubring.pgp");
        !           511:        buildfilename(globalSecringName, "secring.pgp");
        !           512:        buildfilename(globalRandseedName, "randseed.bin");
        !           513:        my_name[0] = '\0';
        !           514:        
        !           515:        /* Process the config file first.  Any command-line arguments will
        !           516:           override the config file settings */
        !           517:        buildfilename( mcguffin, "config.txt" );
        !           518:        if (access(mcguffin, 0) == 0) {
        !           519:                opt++;
        !           520:                if ( processConfigFile( mcguffin ) < 0 )
        !           521:                        exit(BAD_ARG_ERROR);
        !           522:        }
        !           523:        if (!opt)
        !           524:                fprintf(pgpout, LANG("\007No configuration file found.\n"));
        !           525:        
        !           526:        init_charset();
        !           527: 
        !           528: #ifdef MSDOS   /* only on MSDOS systems */
        !           529:        if ((p = getenv("TZ")) == NULL || *p == '\0') {
        !           530:                fprintf(pgpout,LANG("\007WARNING: Environmental variable TZ is not defined, so GMT timestamps\n\
        !           531: may be wrong.  See the PGP User's Guide to properly define TZ\n\
        !           532: in AUTOEXEC.BAT file.\n"));
        !           533:        }
        !           534: #endif /* MSDOS */
        !           535: 
        !           536: #ifdef VMS
        !           537: #define TEMP "SYS$SCRATCH"
        !           538: #else
        !           539: #define TEMP "TMP"
        !           540: #endif /* VMS */
        !           541:        if ((p = getenv(TEMP)) != NULL && *p != '\0')
        !           542:                settmpdir(p);
        !           543: 
        !           544:        /* Turn on incompatibility as of 1 September 1994 (GMT) */
        !           545:        legal_kludge = (get_timestamp(NULL) >= 0x2e651980);
        !           546: 
        !           547:        if ((myArgv = (char **) malloc((argc + 2) * sizeof(char **))) == NULL) {
        !           548:                fprintf(stderr, LANG("\n\007Out of memory.\n"));
        !           549:                exitPGP(7);
        !           550:        }
        !           551:        myArgv[0] = NULL;
        !           552:        myArgv[1] = NULL;
        !           553: 
        !           554:        /* Process all the command-line option switches: */
        !           555:        while (optind < argc) {
        !           556:                /*
        !           557:                 * Allow random order of options and arguments (like GNU getopt)
        !           558:                 * NOTE: this does not work with GNU getopt, use getopt.c from
        !           559:                 * the PGP distribution.
        !           560:                 */
        !           561:                if ((opt = pgp_getopt(argc, argv, OPTIONS)) == EOF) {
        !           562:                        if (optind == argc)             /* -- at end */
        !           563:                                break;
        !           564:                        myArgv[myArgc++] = argv[optind++];
        !           565:                        continue;
        !           566:                }
        !           567:                opt = to_lower(opt);
        !           568:                if (keyflag && (keychar == '\0' || (keychar == 'v' && opt == 'v')))
        !           569:                {
        !           570:                        if (keychar == 'v')
        !           571:                                keychar = 'V';
        !           572:                        else
        !           573:                                keychar = opt;
        !           574:                        continue;
        !           575:                }
        !           576:                switch (opt) {
        !           577:                case 'a': armor_flag = TRUE; emit_radix_64 = 1; break;
        !           578:                case 'b': separate_signature = strip_sig_flag = TRUE; break;
        !           579:                case 'c': encrypt_flag = conventional_flag = TRUE;
        !           580:                                  c_flag = TRUE; break;
        !           581:                case 'd': decrypt_only_flag = TRUE; break;
        !           582:                case 'e': encrypt_flag = TRUE; break;
        !           583:                case 'f': filter_mode = TRUE; break;
        !           584:                case '?':
        !           585:                case 'h': usage(); break;
        !           586: #ifdef VMS
        !           587:                case 'i': literal_mode = MODE_LOCAL; break;
        !           588: #endif /* VMS */
        !           589:                case 'k': keyflag = TRUE; break;
        !           590:                case 'l': verbose = TRUE; break;
        !           591:                case 'm': moreflag = TRUE; break;
        !           592:                case 'p': preserve_filename = TRUE; break;
        !           593:                case 'o': outputfile = optarg; break;
        !           594:                case 's': sign_flag = TRUE; break;
        !           595:                case 't': literal_mode = MODE_TEXT; break;
        !           596:                case 'u': strncpy(my_name, optarg, sizeof(my_name)-1);
        !           597:                          CONVERT_TO_CANONICAL_CHARSET(my_name);
        !           598:                          break;
        !           599:                case 'w': wipeflag = TRUE; break;
        !           600:                case 'z': break;
        !           601:                /* '+' special option: does not require - */
        !           602:                case '+':
        !           603:                        if (processConfigLine(optarg) == 0)
        !           604:                                break;
        !           605:                        fprintf(stderr, "\n");
        !           606:                        /* fallthrough */
        !           607:                default:
        !           608:                        arg_error();
        !           609:                }
        !           610:        }
        !           611:        myArgv[myArgc] = NULL;  /* Just to make it NULL terminated */
        !           612: 
        !           613:        if (keyflag && keychar == '\0')
        !           614:                key_usage();
        !           615: 
        !           616:        signon_msg();
        !           617:        check_expiration_date();        /* hobble any experimental version */
        !           618: 
        !           619:        if (legal_kludge)
        !           620:                version_byte = VERSION_BYTE_KLUDGE;
        !           621: 
        !           622: #if 1
        !           623:        /* At request of Peter Simons, use stderr always. Sounds reasonable. */
        !           624:        /* JIS: Put this code back in... removing it broke too many things */
        !           625:        if (!filter_mode && (outputfile == NULL || strcmp(outputfile, "-")))
        !           626:                pgpout = stdout;
        !           627: #endif
        !           628: 
        !           629: #if 0
        !           630:        /* Check for the existence of the manual */
        !           631:        /* Commented out to make PGP less facist */
        !           632:        if (manuals_missing()) {
        !           633:                fputs(LANG("\nWARNING: PGP User's Guide not found.  PGP should not be\n\
        !           634: distributed without the User's Guide.\n"), pgpout);
        !           635:        }
        !           636: #endif
        !           637:        
        !           638: 
        !           639: #if defined(UNIX) || defined(VMS)
        !           640:        umask(077); /* Make files default to private */
        !           641: #endif
        !           642: 
        !           643:        initsigs();     /* Catch signals */
        !           644:        noise();        /* Start random number generation */
        !           645: 
        !           646:        if (keyflag) {
        !           647:                status = do_keyopt(keychar);
        !           648:                if (status < 0)
        !           649:                        user_error();
        !           650:                exitPGP(status);
        !           651:        }
        !           652: 
        !           653:        /* -db means break off signature certificate into separate file */
        !           654:        if (decrypt_only_flag && strip_sig_flag)
        !           655:                decrypt_only_flag = FALSE;
        !           656: 
        !           657:        if (decrypt_only_flag && armor_flag)
        !           658:                decrypt_mode = de_armor_only = TRUE;
        !           659: 
        !           660:        if (outputfile != NULL)
        !           661:                preserve_filename = FALSE;
        !           662: 
        !           663:        if (!sign_flag && !encrypt_flag && !conventional_flag && !armor_flag)
        !           664:        {
        !           665:                if (wipeflag) { /* wipe only */
        !           666:                        if (myArgc != 3)
        !           667:                                arg_error();    /* need one argument */
        !           668:                        if (wipefile(myArgv[2]) == 0 && remove(myArgv[2]) == 0)
        !           669:                        {
        !           670:                                fprintf(pgpout,LANG("\nFile %s wiped and deleted. "),myArgv[2]);
        !           671:                                fprintf(pgpout, "\n");
        !           672:                                exitPGP(EXIT_OK);
        !           673:                        }
        !           674:                        exitPGP(UNKNOWN_FILE_ERROR);
        !           675:                }
        !           676:                /* decrypt if none of the -s -e -c -a -w options are specified */
        !           677:                decrypt_mode = TRUE;
        !           678:        }
        !           679: 
        !           680:        if (myArgc == 2)                /* no arguments */
        !           681:        {
        !           682: #ifdef UNIX
        !           683:                if (!filter_mode && !isatty(fileno(stdin))) {
        !           684:                        /* piping to pgp without arguments and no -f:
        !           685:                         * switch to filter mode but don't write output to stdout
        !           686:                         * if it's a tty, use the preserved filename */
        !           687:                        if (!moreflag)
        !           688:                                pgpout = stderr;
        !           689:                        filter_mode = TRUE;
        !           690:                        if (isatty(fileno(stdout)) && !moreflag)
        !           691:                                preserve_filename = TRUE;
        !           692:                }
        !           693: #endif
        !           694:                if (!filter_mode) {
        !           695:                        if (quietmode) {
        !           696:                                quietmode = FALSE;
        !           697:                                signon_msg();
        !           698:                        }
        !           699:                        fprintf(pgpout,LANG("\nFor details on licensing and distribution, see the PGP User's Guide.\
        !           700: \nFor other cryptography products and custom development services, contact:\
        !           701: \nPhilip Zimmermann, 3021 11th St, Boulder CO 80304 USA, phone +1 303 541-0140\n"));
        !           702:                        if (strcmp((p = LANG("@translator@")), "@translator@"))
        !           703:                                fprintf(pgpout, p);
        !           704:                        fprintf(pgpout,LANG("\nFor a usage summary, type:  pgp -h\n"));
        !           705:                        exit(BAD_ARG_ERROR);            /* error exit */
        !           706:                }
        !           707:        } else {
        !           708:                if (filter_mode) {
        !           709:                        recipient = &myArgv[2];
        !           710:                } else {
        !           711:                        inputfile = myArgv[2];
        !           712:                        recipient = &myArgv[3];
        !           713:                }
        !           714:        }
        !           715: 
        !           716: 
        !           717:        if (filter_mode) {
        !           718:                inputfile = "stdin";
        !           719:        } else {
        !           720:                if (decrypt_mode && no_extension(inputfile)) {
        !           721:                        strcpy(cipherfile, inputfile);
        !           722:                        force_extension( cipherfile, ASC_EXTENSION );
        !           723:                        if (file_exists (cipherfile)) {
        !           724:                                inputfile = cipherfile;
        !           725:                        } else {
        !           726:                                force_extension( cipherfile, PGP_EXTENSION );
        !           727:                                if (file_exists (cipherfile)) {
        !           728:                                        inputfile = cipherfile;
        !           729:                                } else {
        !           730:                                        force_extension( cipherfile, SIG_EXTENSION );
        !           731:                                        if (file_exists (cipherfile))
        !           732:                                                inputfile = cipherfile;
        !           733:                                }
        !           734:                        }
        !           735:                }
        !           736:                if (! file_exists( inputfile )) {
        !           737:                        fprintf(pgpout, LANG("\007File [%s] does not exist.\n"), inputfile);
        !           738:                        errorLvl = FILE_NOT_FOUND_ERROR;
        !           739:                        user_error();
        !           740:                }
        !           741:        }
        !           742: 
        !           743:        if (strlen(inputfile) >= (unsigned) MAX_PATH-4) {
        !           744:                fprintf(pgpout, LANG("\007Invalid filename: [%s] too long\n"), inputfile );
        !           745:                errorLvl = INVALID_FILE_ERROR;
        !           746:                user_error();
        !           747:        }
        !           748:        strcpy(plainfile, inputfile);
        !           749: 
        !           750:        if (filter_mode) {
        !           751:                setoutdir(NULL);        /* NULL means use tmpdir */
        !           752:        } else {
        !           753:                if (outputfile)
        !           754:                        setoutdir(outputfile);
        !           755:                else
        !           756:                        setoutdir(inputfile);
        !           757:        }
        !           758: 
        !           759:        if (filter_mode) {
        !           760:                workfile = tempfile(TMP_WIPE|TMP_TMPDIR);
        !           761:                readPhantomInput(workfile);
        !           762:        } else {
        !           763:                workfile = inputfile;
        !           764:        }
        !           765: 
        !           766:        get_header_info_from_file( workfile, &ctb, 1 );
        !           767:        if (decrypt_mode) {
        !           768:                strip_spaces = FALSE;
        !           769:                if (!is_ctb(ctb) && is_armor_file(workfile, 0L))
        !           770:                        do_armorfile(workfile);
        !           771:                else
        !           772:                        if (do_decrypt(workfile) < 0)
        !           773:                                user_error();
        !           774:                if (batchmode && !signature_checked)
        !           775:                        exitPGP(1);     /* alternate success, file did not have sig. */
        !           776:                else
        !           777:                        exitPGP(EXIT_OK);
        !           778:        }
        !           779: 
        !           780:        /*
        !           781:         * See if plaintext input file was actually created by PGP earlier--
        !           782:         * If it was, maybe we should NOT encapsulate it in a literal packet.
        !           783:         * Otherwise, always encapsulate it.
        !           784:         */
        !           785:        if (force_flag) /* for use with batchmode, force nesting */
        !           786:                nestflag = legal_ctb(ctb);
        !           787:        else
        !           788:                nestflag = FALSE; /* First assume we will encapsulate it. */
        !           789: 
        !           790:        if (!batchmode && !filter_mode && legal_ctb(ctb)) {
        !           791:                /*      Special case--may be a PGP-created packet, so
        !           792:                        do we inhibit encapsulation in literal packet? */
        !           793:                fprintf(pgpout, LANG("\n\007Input file '%s' looks like it may have been created by PGP. "),
        !           794:                        inputfile );
        !           795:                fprintf(pgpout, LANG("\nIs it safe to assume that it was created by PGP (y/N)? "));
        !           796:                nestflag = getyesno('n');
        !           797:        }       /* Possible ciphertext input file */
        !           798: 
        !           799:        if (moreflag) {         /* special name to cause printout on decrypt */
        !           800:                strcpy (literal_file_name, CONSOLE_FILENAME);
        !           801:                literal_mode = MODE_TEXT;       /* will check for text file later */
        !           802:        } else {
        !           803:                strcpy (literal_file_name, inputfile);
        !           804: #ifdef MSDOS
        !           805:                strlwr (literal_file_name);
        !           806: #endif
        !           807:        }
        !           808:        literal_file = literal_file_name;
        !           809: 
        !           810:        /*      Make sure non-text files are not accidentally converted 
        !           811:                to canonical text.  This precaution should only be followed 
        !           812:                for US ASCII text files, since European text files may have 
        !           813:                8-bit character codes and still be legitimate text files 
        !           814:                suitable for conversion to canonical (CR/LF-terminated) 
        !           815:                text format. */
        !           816:        if (literal_mode==MODE_TEXT && !is_text_file(workfile)) {
        !           817:                fprintf(pgpout, 
        !           818: LANG("\nNote: '%s' is not a pure text file.\nFile will be treated as binary data.\n"), 
        !           819:                        workfile);
        !           820:                literal_mode = MODE_BINARY; /* now expect straight binary */
        !           821:        }
        !           822: 
        !           823:        if (moreflag && literal_mode==MODE_BINARY) {    /* For eyes only?  Can't display binary file. */
        !           824:                fprintf(pgpout, 
        !           825:                LANG("\n\007Error: Only text files may be sent as display-only.\n"));
        !           826:                errorLvl = INVALID_FILE_ERROR;
        !           827:                user_error();
        !           828:        }               
        !           829: 
        !           830: 
        !           831:        /*      See if plainfile looks like it might be incompressible, 
        !           832:                by examining its contents for compression headers for 
        !           833:                commonly-used compressed file formats like PKZIP, etc.
        !           834:                Remember this information for later, when we are deciding
        !           835:                whether to attempt compression before encryption.
        !           836:        */
        !           837:        attempt_compression = compress_enabled && file_compressible(plainfile);
        !           838: 
        !           839: 
        !           840:        if (sign_flag) {
        !           841:                if (!filter_mode && !quietmode)
        !           842:                        fprintf(pgpout, LANG("\nA secret key is required to make a signature. "));
        !           843:                if (!quietmode && my_name[0] == '\0') {
        !           844:                        fprintf(pgpout, LANG("\nYou specified no user ID to select your secret key,\n\
        !           845: so the default user ID and key will be the most recently\n\
        !           846: added key on your secret keyring.\n"));
        !           847:                }
        !           848: 
        !           849:                strip_spaces = FALSE;
        !           850:                clearfile = NULL;
        !           851:                if (literal_mode==MODE_TEXT) {
        !           852:                        /* Text mode requires becoming canonical */
        !           853:                        tempf = tempfile(TMP_WIPE|TMP_TMPDIR);
        !           854:                        /* +clear means output file with signature in the clear,
        !           855:                           only in combination with -t and -a, not with -e or -b */
        !           856:                        if (!encrypt_flag && !separate_signature &&
        !           857:                                        emit_radix_64 && clear_signatures) {
        !           858:                                clearfile = workfile;
        !           859:                                strip_spaces = TRUE;
        !           860:                        }
        !           861:                        make_canonical( workfile, tempf );
        !           862:                        if (!clearfile)
        !           863:                                rmtemp(workfile);
        !           864:                        workfile = tempf;
        !           865:                }
        !           866:                if ((emit_radix_64 || encrypt_flag) && !separate_signature)
        !           867:                        tempf = tempfile(TMP_WIPE|TMP_TMPDIR);
        !           868:                else
        !           869:                        tempf = tempfile(TMP_WIPE);
        !           870:                /* for clear signatures we create a separate signature */
        !           871:                status = signfile(nestflag, separate_signature || (clearfile != NULL),
        !           872:                                                        my_name, workfile, tempf, literal_mode, literal_file );
        !           873:                rmtemp(workfile);
        !           874:                workfile = tempf;
        !           875: 
        !           876:                if (status < 0) { /* signfile failed */
        !           877:                        fprintf(pgpout, LANG("\007Signature error\n") );
        !           878:                        errorLvl = SIGNATURE_ERROR;
        !           879:                        user_error();
        !           880:                }
        !           881:                /*
        !           882:                 *  We used to compress signed files only if they were also
        !           883:                 * armored.  Now that we have clear signatures it makes more
        !           884:                 * sense to always compress signature files.
        !           885:                 */
        !           886:                if (attempt_compression && !separate_signature && !encrypt_flag
        !           887:                                && !clearfile)
        !           888:                {
        !           889:                        tempf = tempfile(TMP_WIPE|TMP_TMPDIR);
        !           890:                        squish_file(workfile, tempf);
        !           891:                        rmtemp(workfile);
        !           892:                        workfile = tempf;
        !           893:                }
        !           894: 
        !           895:        } else if (!nestflag) { /* !sign_file */
        !           896:                /*      Prepend CTB_LITERAL byte to plaintext file.
        !           897:                        --sure wish this pass could be optimized away. */
        !           898:                tempf = tempfile(TMP_WIPE);
        !           899:                status = make_literal( workfile, tempf, literal_mode, literal_file );
        !           900:                rmtemp(workfile);
        !           901:                workfile = tempf;
        !           902:        }
        !           903: 
        !           904:        if (encrypt_flag) {
        !           905:                tempf = tempfile(TMP_WIPE);
        !           906:                if (!conventional_flag) {
        !           907:                        if (!filter_mode && !quietmode)
        !           908:                                fprintf(pgpout, LANG("\n\nRecipients' public key(s) will be used to encrypt. "));
        !           909:                        if (recipient == NULL || *recipient == NULL || **recipient == '\0')
        !           910:                        {
        !           911:                                /* no recipient specified on command line */
        !           912:                                fprintf(pgpout, LANG("\nA user ID is required to select the recipient's public key. "));
        !           913:                                fprintf(pgpout, LANG("\nEnter the recipient's user ID: "));
        !           914:                                getstring( mcguffin, 255, TRUE );       /* echo keyboard */
        !           915:                                if ((mcguffins = (char **) malloc (2 * sizeof(char *))) == NULL) {
        !           916:                                        fprintf(stderr, LANG("\n\007Out of memory.\n"));
        !           917:                                        exitPGP(7);
        !           918:                                }
        !           919:                                mcguffins[0] = mcguffin;
        !           920:                                mcguffins[1] = "";
        !           921:                        } else {
        !           922:                                /* recipient specified on command line */
        !           923:                                mcguffins = recipient;
        !           924:                        }
        !           925:                        for (recipient = mcguffins; *recipient != NULL && 
        !           926:                             **recipient != '\0'; recipient++) {
        !           927:                                CONVERT_TO_CANONICAL_CHARSET(*recipient);
        !           928:                        }
        !           929:                        status = encryptfile( mcguffins, workfile, tempf, attempt_compression);
        !           930:                } else {
        !           931:                        status = idea_encryptfile( workfile, tempf, attempt_compression);
        !           932:                }
        !           933: 
        !           934:                rmtemp(workfile);
        !           935:                workfile = tempf;
        !           936: 
        !           937:                if (status < 0) {
        !           938:                        fprintf(pgpout, LANG("\007Encryption error\n") );
        !           939:                        errorLvl = (conventional_flag ? ENCR_ERROR : RSA_ENCR_ERROR);
        !           940:                        user_error();
        !           941:                }
        !           942:        }       /* encrypt file */
        !           943: 
        !           944:        if (outputfile)         /* explicit output file overrides filter mode */
        !           945:                filter_mode = (strcmp(outputfile, "-") == 0);
        !           946: 
        !           947:        if (filter_mode) {
        !           948:                if (emit_radix_64) {
        !           949:                        /* NULL for outputfile means write to stdout */
        !           950:                        if (armor_file(workfile, NULL, inputfile, clearfile) != 0)
        !           951:                        {
        !           952:                                errorLvl = UNKNOWN_FILE_ERROR;
        !           953:                                user_error();
        !           954:                        }
        !           955:                        if (clearfile)
        !           956:                                rmtemp(clearfile);
        !           957:                } else {
        !           958:                        if (writePhantomOutput(workfile) < 0) {
        !           959:                                errorLvl = UNKNOWN_FILE_ERROR;
        !           960:                                user_error();
        !           961:                        }
        !           962:                }
        !           963:                rmtemp(workfile);
        !           964:        } else {
        !           965:                char name[MAX_PATH];
        !           966:                if (outputfile) {
        !           967:                        strcpy(name, outputfile);
        !           968:                } else {
        !           969:                        strcpy(name, inputfile);
        !           970:                        drop_extension(name);
        !           971:                }
        !           972:                if (no_extension(name)) {
        !           973:                        if (emit_radix_64)
        !           974:                                force_extension(name, ASC_EXTENSION);
        !           975:                        else if (sign_flag && separate_signature)
        !           976:                                force_extension(name, SIG_EXTENSION);
        !           977:                        else
        !           978:                                force_extension(name, PGP_EXTENSION);
        !           979:                }
        !           980:                if (emit_radix_64) {
        !           981:                        if (armor_file(workfile, name, inputfile, clearfile) != 0)
        !           982:                        {
        !           983:                                errorLvl = UNKNOWN_FILE_ERROR;
        !           984:                                user_error();
        !           985:                        }
        !           986:                        if (clearfile)
        !           987:                                rmtemp(clearfile);
        !           988:                } else {
        !           989:                        if ((outputfile = savetemp(workfile, name)) == NULL) {
        !           990:                                errorLvl = UNKNOWN_FILE_ERROR;
        !           991:                                user_error();
        !           992:                        }
        !           993:                        if (!quietmode) {
        !           994:                                if (encrypt_flag)
        !           995:                                        fprintf(pgpout, LANG("\nCiphertext file: %s\n"), outputfile);
        !           996:                                else if (sign_flag)
        !           997:                                        fprintf(pgpout, LANG("\nSignature file: %s\n"), outputfile);
        !           998:                        }
        !           999:                }
        !          1000:        }
        !          1001: 
        !          1002:        if (wipeflag) {
        !          1003:                /* destroy every trace of plaintext */
        !          1004:                if (wipefile(inputfile) == 0) {
        !          1005:                        remove(inputfile);
        !          1006:                        fprintf(pgpout,LANG("\nFile %s wiped and deleted. "),inputfile);
        !          1007:                        fprintf(pgpout, "\n");
        !          1008:                }
        !          1009:        }
        !          1010: 
        !          1011:        exitPGP(EXIT_OK);
        !          1012:        return 0;       /* to shut up lint and some compilers */
        !          1013: }      /* main */
        !          1014: 
        !          1015: #ifdef MSDOS
        !          1016: #include <dos.h>
        !          1017: static char *dos_errlst[] = {
        !          1018:        "Write protect error",          /* LANG ("Write protect error") */
        !          1019:        "Unknown unit",
        !          1020:        "Drive not ready",                      /* LANG ("Drive not ready") */
        !          1021:        "3", "4", "5", "6", "7", "8", "9",
        !          1022:        "Write error",                          /* LANG ("Write error") */
        !          1023:        "Read error",                           /* LANG ("Read error") */
        !          1024:        "General failure",
        !          1025: };
        !          1026: 
        !          1027: /* handler for msdos 'harderrors' */
        !          1028: #ifndef OS2
        !          1029: #ifdef __TURBOC__      /* Turbo C 2.0 */
        !          1030: static int dostrap(int errval)
        !          1031: #else
        !          1032: static void dostrap(unsigned deverr, unsigned errval)
        !          1033: #endif
        !          1034: {
        !          1035:        char errbuf[64];
        !          1036:        int i;
        !          1037:        sprintf(errbuf, "\r\nDOS error: %s\r\n", dos_errlst[errval]);
        !          1038:        i = 0;
        !          1039:        do
        !          1040:                bdos(2,(unsigned int)errbuf[i],0);
        !          1041:        while (errbuf[++i]);
        !          1042: #ifdef __TURBOC__
        !          1043:        return 0;       /* ignore (fopen will return NULL) */
        !          1044: #else
        !          1045:        return;
        !          1046: #endif
        !          1047: }
        !          1048: #endif /* MSDOS */
        !          1049: #endif
        !          1050: 
        !          1051: static void initsigs()
        !          1052: {
        !          1053: #ifdef MSDOS
        !          1054: #ifndef OS2
        !          1055: #ifdef __TURBOC__
        !          1056:        harderr(dostrap);
        !          1057: #else /* MSC */
        !          1058: #ifndef __GNUC__ /* DJGPP's not MSC */
        !          1059:        _harderr(dostrap);
        !          1060: #endif
        !          1061: #endif
        !          1062: #endif
        !          1063: #endif /* MSDOS */
        !          1064: #ifdef SIGINT
        !          1065: #ifdef ATARI
        !          1066:        signal(SIGINT,(sigfunc_t) breakHandler);
        !          1067: #else
        !          1068:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
        !          1069:                signal(SIGINT,breakHandler);
        !          1070: #if defined(UNIX) || defined(VMS)
        !          1071:        if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
        !          1072:                signal(SIGHUP,breakHandler);
        !          1073:        if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
        !          1074:                signal(SIGQUIT,breakHandler);
        !          1075: #ifdef UNIX
        !          1076:        signal(SIGPIPE,breakHandler);
        !          1077: #endif
        !          1078:        signal(SIGTERM,breakHandler);
        !          1079: #ifndef DEBUG
        !          1080:        signal(SIGTRAP,breakHandler);
        !          1081:        signal(SIGSEGV,breakHandler);
        !          1082:        signal(SIGILL,breakHandler);
        !          1083: #ifdef SIGBUS
        !          1084:        signal(SIGBUS,breakHandler);
        !          1085: #endif
        !          1086: #endif /* DEBUG */
        !          1087: #endif /* UNIX */
        !          1088: #endif /* not Atari */
        !          1089: #endif /* SIGINT */
        !          1090: }      /* initsigs */
        !          1091: 
        !          1092: 
        !          1093: static void do_armorfile(char *armorfile)
        !          1094: {
        !          1095:        char *tempf;
        !          1096:        char cipherfile[MAX_PATH];
        !          1097:        long linepos = 0;
        !          1098:        int status;
        !          1099:        int success = 0;
        !          1100: 
        !          1101:        for (;;) {
        !          1102:                /* Handle transport armor stripping */
        !          1103:                tempf = tempfile(0);
        !          1104:                strip_spaces = FALSE;   /* de_armor_file() sets this for clear signature files */
        !          1105:                status = de_armor_file(armorfile,tempf,&linepos);
        !          1106:                if (status) {
        !          1107:                        fprintf(pgpout,LANG("\n\007Error: Transport armor stripping failed for file %s\n"),armorfile);
        !          1108:                        errorLvl = INVALID_FILE_ERROR;
        !          1109:                        user_error();    /* Bad file */
        !          1110:                }
        !          1111:                if (keepctx || de_armor_only) {
        !          1112:                        if (outputfile && de_armor_only) {
        !          1113:                                if (strcmp(outputfile, "-") == 0) {
        !          1114:                                        writePhantomOutput(tempf);
        !          1115:                                        rmtemp(tempf);
        !          1116:                                        return;
        !          1117:                                }
        !          1118:                                strcpy(cipherfile, outputfile);
        !          1119:                        } else {
        !          1120:                                strcpy(cipherfile, file_tail(armorfile));
        !          1121:                                force_extension(cipherfile, PGP_EXTENSION);
        !          1122:                        }
        !          1123:                        if ((tempf = savetemp(tempf, cipherfile)) == NULL) {
        !          1124:                                errorLvl = UNKNOWN_FILE_ERROR;
        !          1125:                                user_error();
        !          1126:                        }
        !          1127:                        if (!quietmode)
        !          1128:                                fprintf(pgpout,LANG("Stripped transport armor from '%s', producing '%s'.\n"),
        !          1129:                                        armorfile, tempf);
        !          1130:                        /* -da flag: don't decrypt */
        !          1131:                        if (de_armor_only || do_decrypt(tempf) >= 0)
        !          1132:                                ++success;
        !          1133:                } else {
        !          1134:                        if (do_decrypt(tempf) >= 0)
        !          1135:                                ++success;
        !          1136:                        rmtemp(tempf);
        !          1137:                }
        !          1138: 
        !          1139:                if (!is_armor_file(armorfile, linepos)) {
        !          1140:                        if (!success)   /* print error msg if we didn't decrypt anything */
        !          1141:                                user_error();
        !          1142:                        return;
        !          1143:                }
        !          1144: 
        !          1145:                fprintf (pgpout, LANG("\nLooking for next packet in '%s'...\n"), armorfile);
        !          1146:        }
        !          1147: }      /* do_armorfile */
        !          1148: 
        !          1149: 
        !          1150: static int do_decrypt(char *cipherfile)
        !          1151: {
        !          1152:        char *outfile = NULL;
        !          1153:        int status, i;
        !          1154:        boolean nested_info = FALSE;
        !          1155:        char ringfile[MAX_PATH];
        !          1156:        byte ctb;
        !          1157:        byte header[8]; /* used to classify file type at the end. */
        !          1158:        char preserved_name[MAX_PATH];
        !          1159:        char *newname;
        !          1160: 
        !          1161:        /* will be set to the original file name after processing a literal packet */
        !          1162:        preserved_name[0] = '\0';
        !          1163: 
        !          1164:        do {    /* while nested parsable info present */
        !          1165:                if (nested_info) {
        !          1166:                        rmtemp(cipherfile);             /* never executed on first pass */
        !          1167:                        cipherfile = outfile;
        !          1168:                }
        !          1169:                if (get_header_info_from_file( cipherfile, &ctb, 1) < 0)
        !          1170:                {
        !          1171:                        fprintf(pgpout,LANG("\n\007Can't open ciphertext file '%s'\n"),cipherfile);
        !          1172:                        errorLvl = FILE_NOT_FOUND_ERROR;
        !          1173:                        return -1;
        !          1174:                }
        !          1175: 
        !          1176:                if (!is_ctb(ctb))               /* not a real CTB -- complain */
        !          1177:                        break;
        !          1178: 
        !          1179:                if (moreflag)
        !          1180:                        outfile = tempfile(TMP_WIPE|TMP_TMPDIR);
        !          1181:                else
        !          1182:                        outfile = tempfile(TMP_WIPE);
        !          1183: 
        !          1184:                /* PKE is Public Key Encryption */
        !          1185:                if (is_ctb_type( ctb, CTB_PKE_TYPE )) {
        !          1186: 
        !          1187:                        if (!quietmode)
        !          1188:                                fprintf(pgpout,LANG("\nFile is encrypted.  Secret key is required to read it. "));
        !          1189: 
        !          1190:                        /* Decrypt to scratch file since we may have a LITERAL2 */
        !          1191:                        status = decryptfile( cipherfile, outfile );
        !          1192: 
        !          1193:                        if (status < 0) { /* error return */
        !          1194:                                errorLvl = RSA_DECR_ERROR;
        !          1195:                                return -1;
        !          1196:                        }
        !          1197:                        nested_info = (status > 0);
        !          1198: 
        !          1199:                } else if (is_ctb_type( ctb, CTB_SKE_TYPE )) {
        !          1200: 
        !          1201:                        if (decrypt_only_flag) {
        !          1202:                                /* swap file names instead of just copying the file */
        !          1203:                                rmtemp(outfile);
        !          1204:                                outfile = cipherfile;
        !          1205:                                cipherfile = NULL;
        !          1206:                                if (!quietmode)
        !          1207:                                        fprintf(pgpout,LANG("\nThis file has a signature, which will be left in place.\n"));
        !          1208:                                break;  /* Do no more */
        !          1209:                        }
        !          1210:                        if (!quietmode)
        !          1211:                                fprintf(pgpout,LANG("\nFile has signature.  Public key is required to check signature. "));
        !          1212: 
        !          1213:                        status = check_signaturefile( cipherfile, outfile, strip_sig_flag, preserved_name );
        !          1214: 
        !          1215:                        if (status < 0) { /* error return */
        !          1216:                                errorLvl = SIGNATURE_CHECK_ERROR;
        !          1217:                                return -1;
        !          1218:                        }
        !          1219:                        nested_info = (status > 0);
        !          1220: 
        !          1221:                        if (strcmp(preserved_name, "/dev/null") == 0) {
        !          1222:                                rmtemp(outfile);
        !          1223:                                fprintf(pgpout, "\n");
        !          1224:                                return 0;
        !          1225:                        }
        !          1226: 
        !          1227:                } else if (is_ctb_type( ctb, CTB_CKE_TYPE )) {
        !          1228: 
        !          1229:                        /* Conventional Key Encrypted ciphertext. */
        !          1230:                        /* Tell user it's encrypted here, and prompt for password in subroutine. */
        !          1231:                        if (!quietmode)
        !          1232:                                fprintf(pgpout,LANG("\nFile is conventionally encrypted.  "));
        !          1233:                        /* Decrypt to scratch file since it may be a LITERAL2 */
        !          1234:                        status = idea_decryptfile( cipherfile, outfile );
        !          1235:                        if (status < 0) /* error return */
        !          1236:                        {       errorLvl = DECR_ERROR;
        !          1237:                                return -1;      /* error exit status */
        !          1238:                        }
        !          1239:                        nested_info = (status > 0);
        !          1240: 
        !          1241:                } else if (is_ctb_type( ctb, CTB_COMPRESSED_TYPE )) {
        !          1242: 
        !          1243:                        /* Compressed text. */
        !          1244:                        status = decompress_file( cipherfile, outfile );
        !          1245:                        if (status < 0) { /* error return */
        !          1246:                                errorLvl = DECOMPRESS_ERROR;
        !          1247:                                return -1;
        !          1248:                        }
        !          1249:                        /* Always assume nested information... */
        !          1250:                        nested_info = TRUE;
        !          1251: 
        !          1252:                } else if (is_ctb_type( ctb, CTB_LITERAL_TYPE ) ||
        !          1253:                           is_ctb_type( ctb, CTB_LITERAL2_TYPE))
        !          1254:                {               /* Raw plaintext.  Just copy it.  No more nesting. */
        !          1255: 
        !          1256:                        /* Strip off CTB_LITERAL prefix byte from file: */
        !          1257:                        /* strip_literal may alter plainfile; will set mode */
        !          1258:                        status = strip_literal( cipherfile, outfile,
        !          1259:                                        preserved_name, &literal_mode);
        !          1260:                        if (status < 0) { /* error return */
        !          1261:                                errorLvl = UNKNOWN_FILE_ERROR;
        !          1262:                                return -1;
        !          1263:                        }
        !          1264:                        nested_info = FALSE;
        !          1265:                } else if (ctb==CTB_CERT_SECKEY || ctb==CTB_CERT_PUBKEY) {
        !          1266: 
        !          1267:                        rmtemp(outfile);
        !          1268:                        if (decrypt_only_flag) {
        !          1269:                                /* swap file names instead of just copying the file */
        !          1270:                                outfile = cipherfile;
        !          1271:                                cipherfile = NULL;
        !          1272:                                break;  /* no further processing */
        !          1273:                        }
        !          1274:                                /* Key ring.  View it. */
        !          1275:                        fprintf(pgpout, LANG("\nFile contains key(s).  Contents follow...") );
        !          1276:                        if (view_keyring( NULL, cipherfile, TRUE, FALSE ) < 0)
        !          1277:                        {
        !          1278:                                errorLvl = KEYRING_VIEW_ERROR;
        !          1279:                                return -1;
        !          1280:                        }
        !          1281:                        /* filter mode explicit requested with -f */
        !          1282:                        if (filter_mode && !preserve_filename)
        !          1283:                                return 0; /*    No output file */
        !          1284:                        if (batchmode)
        !          1285:                                return 0;
        !          1286:                        if (ctb == CTB_CERT_SECKEY)
        !          1287:                                strcpy(ringfile, globalSecringName);
        !          1288:                        else
        !          1289:                                strcpy(ringfile, globalPubringName);
        !          1290:                        /*      Ask if it should be put on key ring */
        !          1291:                        fprintf(pgpout, LANG("\nDo you want to add this keyfile to keyring '%s' (y/N)? "), ringfile);
        !          1292:                        if (!getyesno('n'))
        !          1293:                                return 0;
        !          1294:                        status = addto_keyring(cipherfile,ringfile);
        !          1295:                        if (status < 0) {
        !          1296:                                fprintf(pgpout, LANG("\007Keyring add error. ") );
        !          1297:                                errorLvl = KEYRING_ADD_ERROR;
        !          1298:                                return -1;
        !          1299:                        }
        !          1300:                        return 0; /*    No output file */
        !          1301: 
        !          1302:                } else {        /* Unrecognized CTB */
        !          1303:                        break;
        !          1304:                }
        !          1305: 
        !          1306:        } while (nested_info);
        !          1307:        /* No more nested parsable information */
        !          1308: 
        !          1309:        /* Stopped early due to error */
        !          1310:        if (nested_info) {
        !          1311:                fprintf(pgpout, "\7\nERROR: Nested data has unexpected format.  CTB=0x%02X\n", ctb);
        !          1312:                if (outfile)
        !          1313:                        rmtemp(outfile);
        !          1314:                if (cipherfile)
        !          1315:                        rmtemp(cipherfile);
        !          1316:                errorLvl = UNKNOWN_FILE_ERROR;
        !          1317:                return -1;
        !          1318:        }
        !          1319: 
        !          1320:        if (outfile == NULL) {  /* file was not encrypted */
        !          1321:                if (!filter_mode && !moreflag) {
        !          1322:                        fprintf(pgpout,LANG("\007\nError: '%s' is not a ciphertext, signature, or key file.\n"),
        !          1323:                                cipherfile);
        !          1324:                        errorLvl = UNKNOWN_FILE_ERROR;
        !          1325:                        return -1;
        !          1326:                }
        !          1327:                outfile = cipherfile;
        !          1328:        } else {
        !          1329:                if (cipherfile)
        !          1330:                        rmtemp(cipherfile);
        !          1331:        }
        !          1332: 
        !          1333:        if (moreflag || (strcmp(preserved_name,CONSOLE_FILENAME) == 0)) {
        !          1334:                /* blort to screen */
        !          1335:                if (strcmp(preserved_name,CONSOLE_FILENAME) == 0) {
        !          1336:                        fprintf(pgpout,
        !          1337:                        LANG("\n\nThis message is marked \"For your eyes only\".  Display now (Y/n)? "));
        !          1338:                        if (batchmode || !getyesno('y')) {
        !          1339:                                /* no -- abort display, and clean up */
        !          1340:                                rmtemp(outfile);
        !          1341:                                return 0;
        !          1342:                        }
        !          1343:                }
        !          1344:                if (!quietmode)
        !          1345:                        fprintf(pgpout, LANG("\n\nPlaintext message follows...\n"));
        !          1346:                else
        !          1347:                        putc('\n', pgpout);
        !          1348:                fprintf(pgpout, "------------------------------\n");
        !          1349:                more_file(outfile);
        !          1350:                /* Disallow saving to disk if outfile is console-only: */
        !          1351:                if (strcmp(preserved_name,CONSOLE_FILENAME) == 0) {
        !          1352:                        clearscreen();  /* remove all evidence */
        !          1353:                } else if (!quietmode && !batchmode) {
        !          1354:                        fprintf(pgpout, LANG("Save this file permanently (y/N)? "));
        !          1355:                        if (getyesno('n')) {
        !          1356:                                char moreFilename[256];
        !          1357:                                fprintf(pgpout,LANG("Enter filename to save file as: "));
        !          1358:                                if (preserved_name[0])
        !          1359:                                        fprintf(pgpout, "[%s]: ", file_tail(preserved_name));
        !          1360:                                getstring( moreFilename, 255, TRUE );
        !          1361:                                if (*moreFilename == '\0') {
        !          1362:                                        if (*preserved_name != '\0')
        !          1363:                                                savetemp (outfile, file_tail(preserved_name));
        !          1364:                                        else
        !          1365:                                                rmtemp(outfile);
        !          1366:                                }
        !          1367:                                else
        !          1368:                                        savetemp (outfile, moreFilename);
        !          1369:                                return 0;
        !          1370:                        }
        !          1371:                }
        !          1372:                rmtemp(outfile);
        !          1373:                return 0;
        !          1374:        }       /* blort to screen */
        !          1375: 
        !          1376:        if (outputfile) {
        !          1377:                if (!strcmp(outputfile, "/dev/null")) {
        !          1378:                        rmtemp(outfile);
        !          1379:                        return 0;
        !          1380:                }
        !          1381:                filter_mode = (strcmp(outputfile, "-") == 0);
        !          1382:                strcpy(plainfile, outputfile);
        !          1383:        } else {
        !          1384: #ifdef VMS
        !          1385:                /* VMS null extension has to be ".", not "" */
        !          1386:                force_extension(plainfile, ".");
        !          1387: #else  /* not VMS */
        !          1388:                drop_extension(plainfile);
        !          1389: #endif /* not VMS */
        !          1390:        }
        !          1391: 
        !          1392:        if (!preserve_filename && filter_mode) {
        !          1393:                if (writePhantomOutput(outfile) < 0) {
        !          1394:                        errorLvl = UNKNOWN_FILE_ERROR;
        !          1395:                        return -1;
        !          1396:                }
        !          1397:                rmtemp(outfile);
        !          1398:                return 0;
        !          1399:        }
        !          1400: 
        !          1401:        if (preserve_filename && preserved_name[0] != '\0')
        !          1402:                strcpy(plainfile, file_tail(preserved_name));
        !          1403: 
        !          1404:        if (quietmode) {
        !          1405:                if (savetemp(outfile, plainfile) == NULL) {
        !          1406:                        errorLvl = UNKNOWN_FILE_ERROR;
        !          1407:                        return -1;
        !          1408:                }
        !          1409:                return 0;
        !          1410:        }
        !          1411:        if (!verbose)   /* if other filename messages were suppressed */
        !          1412:                fprintf(pgpout,LANG("\nPlaintext filename: %s"), plainfile);
        !          1413: 
        !          1414: 
        !          1415:        /*---------------------------------------------------------*/
        !          1416: 
        !          1417:        /*      One last thing-- let's attempt to classify some of the more
        !          1418:                frequently occurring cases of plaintext output files, as an
        !          1419:                aid to the user.
        !          1420: 
        !          1421:                For example, if output file is a public key, it should have
        !          1422:                the right extension on the filename.
        !          1423: 
        !          1424:                Also, it will likely be common to encrypt files created by
        !          1425:                various archivers, so they should be renamed with the archiver
        !          1426:                extension.
        !          1427:        */
        !          1428:        get_header_info_from_file( outfile, header, 8 );
        !          1429: 
        !          1430:        newname = NULL;
        !          1431:        if (header[0] == CTB_CERT_PUBKEY) {
        !          1432:                /* Special case--may be public key, worth renaming */
        !          1433:                fprintf(pgpout, LANG("\nPlaintext file '%s' looks like it contains a public key."),
        !          1434:                        plainfile );
        !          1435:                newname = maybe_force_extension( plainfile, PGP_EXTENSION );
        !          1436:        }       /* Possible public key output file */
        !          1437: 
        !          1438:        else if ((i = compressSignature( header )) >= 0) {
        !          1439:                /*      Special case--may be an archived/compressed file, worth renaming        */
        !          1440:                fprintf(pgpout, LANG("\nPlaintext file '%s' looks like a %s file."),
        !          1441:                        plainfile, compressName[i] );
        !          1442:                newname = maybe_force_extension( plainfile, compressExt[i] );
        !          1443:        } else if (is_ctb(header[0]) &&
        !          1444:                   (  is_ctb_type (header[0], CTB_PKE_TYPE)
        !          1445:                   || is_ctb_type (header[0], CTB_SKE_TYPE)
        !          1446:                   || is_ctb_type (header[0], CTB_CKE_TYPE)))
        !          1447:        {
        !          1448:                /* Special case--may be another ciphertext file, worth renaming */
        !          1449:                fprintf(pgpout, LANG("\n\007Output file '%s' may contain more ciphertext or signature."),
        !          1450:                        plainfile );
        !          1451:                newname = maybe_force_extension( plainfile, PGP_EXTENSION );
        !          1452:        }       /* Possible ciphertext output file */
        !          1453: 
        !          1454:        if (savetemp(outfile, (newname ? newname : plainfile)) == NULL) {
        !          1455:                errorLvl = UNKNOWN_FILE_ERROR;
        !          1456:                return -1;
        !          1457:        }
        !          1458: 
        !          1459:        fprintf (pgpout, "\n");
        !          1460:        return 0;
        !          1461: } /* do_decrypt */
        !          1462: 
        !          1463: 
        !          1464: static int do_keyopt(char keychar)
        !          1465: {
        !          1466:        char keyfile[MAX_PATH];
        !          1467:        char ringfile[MAX_PATH];
        !          1468:        char *workfile;
        !          1469:        int status;
        !          1470: 
        !          1471:        if ((filter_mode || batchmode)
        !          1472:                && (keychar == 'g' || keychar == 'e' || keychar == 'd'
        !          1473:                        || (keychar == 'r' && sign_flag)))
        !          1474:        {
        !          1475:                errorLvl = NO_BATCH;
        !          1476:                arg_error();     /* interactive process, no go in batch mode */
        !          1477:        }
        !          1478: 
        !          1479:        /*
        !          1480:         * If we're not doing anything that uses stdout, produce output there,
        !          1481:         * in case user wants to redirect it.
        !          1482:         */
        !          1483:        if (!filter_mode)
        !          1484:                pgpout = stdout;
        !          1485: 
        !          1486:        switch (keychar) {
        !          1487: 
        !          1488:        /*-------------------------------------------------------*/
        !          1489:        case 'g':
        !          1490:        {       /*      Key generation
        !          1491:                        Arguments: bitcount, bitcount
        !          1492:                */
        !          1493:                char    keybits[6], ebits[6];
        !          1494: 
        !          1495:        /* 
        !          1496:         * Why all this code?
        !          1497:         *
        !          1498:         * Some dimwits have been distributing versions of PGP (especially on
        !          1499:         * MS-DOS) without the manuals.  This frustrates users (who call
        !          1500:         * Philip Zimmermann at all hours of the day and night), and in
        !          1501:         * addition to depriving them of instructions on how to operate the
        !          1502:         * program, also deprives them of IMPORTANT legal notices.  This is
        !          1503:         * a Bad Thing, so we've gone to the trouble of being fascist and
        !          1504:         * *forcing* the manuals to be there.
        !          1505:         *
        !          1506:         * The +nomanual flag (documented only in the manual) lets you
        !          1507:         * overrride this if desired.
        !          1508:         */
        !          1509: 
        !          1510:                if (!nomanual && manuals_missing()) {
        !          1511:                        char const * const *dir;
        !          1512: 
        !          1513:                        fputs(LANG("\a\nError: PGP User's Guide not found.\n\
        !          1514: PGP looked for it in the following directories:\n"), pgpout);
        !          1515:                        for (dir = manual_dirs; *dir; dir++)
        !          1516:                                fprintf(pgpout, "\t\"%s\"\n", *dir);
        !          1517:                        fputs(LANG("and the doc subdirectory of each of the above.  Please put a copy of\n\
        !          1518: both volumes of the User's Guide in one of these directories.\n\
        !          1519: \n\
        !          1520: Under NO CIRCUMSTANCES should PGP ever be distributed without the PGP\n\
        !          1521: User's Guide, which is included in the standard distribution package.\n\
        !          1522: If you got a copy of PGP without the manual, please inform whomever you\n\
        !          1523: got it from that this is an incomplete package that should not be\n\
        !          1524: distributed further.\n\
        !          1525: \n\
        !          1526: PGP will not generate a key without finding the User's Guide.\n\
        !          1527: \n"), pgpout);
        !          1528:                        return KEYGEN_ERROR;
        !          1529:                }
        !          1530: 
        !          1531:                if (myArgc > 2)
        !          1532:                        strncpy( keybits, myArgv[2], sizeof(keybits)-1 );
        !          1533:                else
        !          1534:                        keybits[0] = '\0';
        !          1535: 
        !          1536:                if (myArgc > 3)
        !          1537:                        strncpy( ebits, myArgv[3], sizeof(ebits)-1 );
        !          1538:                else
        !          1539:                        ebits[0] = '\0';
        !          1540: 
        !          1541:                /* dokeygen writes the keys out to the key rings... */
        !          1542:                status = dokeygen(keybits, ebits);
        !          1543: 
        !          1544:                if (status < 0) {
        !          1545:                        fprintf(pgpout, LANG("\007Keygen error. ") );
        !          1546:                        errorLvl = KEYGEN_ERROR;
        !          1547:                }
        !          1548:                return status;
        !          1549:        }       /* Key generation */
        !          1550: 
        !          1551:        /*-------------------------------------------------------*/
        !          1552:        case 'c':
        !          1553:        {       /*      Key checking
        !          1554:                        Arguments: userid, ringfile
        !          1555:                */
        !          1556: 
        !          1557:                if (myArgc < 3) {       /* Default to all user ID's */
        !          1558:                        mcguffin[0] = '\0';
        !          1559:                } else {
        !          1560:                        strcpy ( mcguffin, myArgv[2] );
        !          1561:                        if (strcmp( mcguffin, "*" ) == 0)
        !          1562:                                mcguffin[0] = '\0';
        !          1563:                }
        !          1564:                CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          1565: 
        !          1566:                if (myArgc < 4) /* default key ring filename */
        !          1567:                        strcpy(ringfile, globalPubringName);
        !          1568:                else
        !          1569:                        strncpy( ringfile, myArgv[3], sizeof(ringfile)-1 );
        !          1570: 
        !          1571:                if ((myArgc < 4 && myArgc > 2)  /* Allow just key file as arg */
        !          1572:                   && has_extension( myArgv[2], PGP_EXTENSION ) )
        !          1573:                {
        !          1574:                        strcpy( ringfile, myArgv[2] );
        !          1575:                        mcguffin[0] = '\0';
        !          1576:                }
        !          1577: 
        !          1578:                status = dokeycheck( mcguffin, ringfile, CHECK_ALL );
        !          1579: 
        !          1580:                if (status < 0) {
        !          1581:                        fprintf(pgpout, LANG("\007Keyring check error.\n") );
        !          1582:                        errorLvl = KEYRING_CHECK_ERROR;
        !          1583:                }
        !          1584:                if (status >= 0 && mcguffin[0] != '\0')
        !          1585:                        return status;  /* just checking a single user, dont do maintenance */
        !          1586: 
        !          1587:                if ((status = maint_check(ringfile, 0)) < 0 && status != -7) {
        !          1588:                        fprintf(pgpout, LANG("\007Maintenance pass error. ") );
        !          1589:                        errorLvl = KEYRING_CHECK_ERROR;
        !          1590:                }
        !          1591: 
        !          1592:                return status == -7 ? 0 : status;
        !          1593:        }       /* Key check */
        !          1594: 
        !          1595:        /*-------------------------------------------------------*/
        !          1596:        case 'm':
        !          1597:        {       /*      Maintenance pass
        !          1598:                        Arguments: ringfile
        !          1599:                */
        !          1600: 
        !          1601:                if (myArgc < 3) /* default key ring filename */
        !          1602:                        strcpy(ringfile, globalPubringName);
        !          1603:                else
        !          1604:                        strcpy( ringfile, myArgv[2] );
        !          1605: 
        !          1606: #ifdef MSDOS
        !          1607:                strlwr( ringfile );
        !          1608: #endif
        !          1609:                if (! file_exists( ringfile ))
        !          1610:                        default_extension( ringfile, PGP_EXTENSION );
        !          1611: 
        !          1612:                if ((status = maint_check(ringfile,
        !          1613:                        MAINT_VERBOSE|(c_flag ? MAINT_CHECK : 0))) < 0)
        !          1614:                {
        !          1615:                        if (status == -7)
        !          1616:                                fprintf(pgpout, LANG("File '%s' is not a public keyring\n"), ringfile);
        !          1617:                        fprintf(pgpout, LANG("\007Maintenance pass error. ") );
        !          1618:                        errorLvl = KEYRING_CHECK_ERROR;
        !          1619:                }
        !          1620:                return status;
        !          1621:        }       /* Maintenance pass */
        !          1622: 
        !          1623:        /*-------------------------------------------------------*/
        !          1624:        case 's':
        !          1625:        {       /*      Key signing
        !          1626:                        Arguments: her_id, keyfile
        !          1627:                */
        !          1628: 
        !          1629:                if (myArgc >= 4)
        !          1630:                        strncpy( keyfile, myArgv[3], sizeof(keyfile)-1 );
        !          1631:                else
        !          1632:                        strcpy(keyfile, globalPubringName);
        !          1633: 
        !          1634:                if (myArgc >= 3) {
        !          1635:                        strcpy( mcguffin, myArgv[2] );  /* Userid to sign */
        !          1636:                } else {
        !          1637:                        fprintf(pgpout, LANG("\nA user ID is required to select the public key you want to sign. "));
        !          1638:                        if (batchmode)  /* not interactive, userid must be on command line */
        !          1639:                                return -1;
        !          1640:                        fprintf(pgpout, LANG("\nEnter the public key's user ID: "));
        !          1641:                        getstring( mcguffin, 255, TRUE );       /* echo keyboard */
        !          1642:                }
        !          1643:                CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          1644: 
        !          1645:                if (my_name[0] == '\0') {
        !          1646:                        fprintf(pgpout, LANG("\nA secret key is required to make a signature. "));
        !          1647:                        fprintf(pgpout, LANG("\nYou specified no user ID to select your secret key,\n\
        !          1648: so the default user ID and key will be the most recently\n\
        !          1649: added key on your secret keyring.\n"));
        !          1650:                }
        !          1651: 
        !          1652:                status = signkey ( mcguffin, my_name, keyfile );
        !          1653: 
        !          1654:                if (status >= 0) {
        !          1655:                        status = maint_update(keyfile, 0);
        !          1656:                        if (status == -7) {     /* ringfile is a keyfile or secret keyring */
        !          1657:                                fprintf(pgpout, "Warning: '%s' is not a public keyring\n", keyfile);
        !          1658:                                return 0;
        !          1659:                        }
        !          1660:                        if (status < 0)
        !          1661:                                fprintf(pgpout, LANG("\007Maintenance pass error. ") );
        !          1662:                }
        !          1663: 
        !          1664:                if (status < 0) {
        !          1665:                        fprintf(pgpout, LANG("\007Key signature error. ") );
        !          1666:                        errorLvl = KEY_SIGNATURE_ERROR;
        !          1667:                }
        !          1668:                return status;
        !          1669:        }       /* Key signing */
        !          1670: 
        !          1671: 
        !          1672:        /*-------------------------------------------------------*/
        !          1673:        case 'd':
        !          1674:        {       /*      disable/revoke key
        !          1675:                        Arguments: userid, keyfile
        !          1676:                */
        !          1677: 
        !          1678:                if (myArgc >= 4)
        !          1679:                        strncpy( keyfile, myArgv[3], sizeof(keyfile)-1 );
        !          1680:                else
        !          1681:                        strcpy(keyfile, globalPubringName);
        !          1682: 
        !          1683:                if (myArgc >= 3) {
        !          1684:                        strcpy( mcguffin, myArgv[2] );  /* Userid to sign */
        !          1685:                } else {
        !          1686:                        fprintf(pgpout, LANG("\nA user ID is required to select the key you want to revoke or disable. "));
        !          1687:                        fprintf(pgpout, LANG("\nEnter user ID: "));
        !          1688:                        getstring( mcguffin, 255, TRUE );       /* echo keyboard */
        !          1689:                }
        !          1690:                CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          1691: 
        !          1692:                status = disable_key ( mcguffin, keyfile );
        !          1693: 
        !          1694:                if (status >= 0) {
        !          1695:                        status = maint_update(keyfile, 0);
        !          1696:                        if (status == -7) {     /* ringfile is a keyfile or secret keyring */
        !          1697:                                fprintf(pgpout, "Warning: '%s' is not a public keyring\n", keyfile);
        !          1698:                                return 0;
        !          1699:                        }
        !          1700:                        if (status < 0)
        !          1701:                                fprintf(pgpout, LANG("\007Maintenance pass error. ") );
        !          1702:                }
        !          1703: 
        !          1704:                if (status < 0)
        !          1705:                        errorLvl = KEY_SIGNATURE_ERROR;
        !          1706:                return status;
        !          1707:        }       /* Key compromise */
        !          1708: 
        !          1709:        /*-------------------------------------------------------*/
        !          1710:        case 'e':
        !          1711:        {       /*      Key editing
        !          1712:                        Arguments: userid, ringfile
        !          1713:                */
        !          1714: 
        !          1715:                if (myArgc >= 4)
        !          1716:                        strncpy( ringfile, myArgv[3], sizeof(ringfile)-1 );
        !          1717:                else    /* default key ring filename */
        !          1718:                        strcpy(ringfile, globalPubringName);
        !          1719: 
        !          1720:                if (myArgc >= 3) {
        !          1721:                        strcpy( mcguffin, myArgv[2] );  /* Userid to edit */
        !          1722:                } else {
        !          1723:                        fprintf(pgpout, LANG("\nA user ID is required to select the key you want to edit. "));
        !          1724:                        fprintf(pgpout, LANG("\nEnter the key's user ID: "));
        !          1725:                        getstring( mcguffin, 255, TRUE );       /* echo keyboard */
        !          1726:                }
        !          1727:                CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          1728: 
        !          1729:                status = dokeyedit( mcguffin, ringfile );
        !          1730: 
        !          1731:                if (status >= 0) {
        !          1732:                        status = maint_update(ringfile, 0);
        !          1733:                        if (status == -7)
        !          1734:                                status = 0;     /* ignore "not a public keyring" error */
        !          1735:                        if (status < 0)
        !          1736:                                fprintf(pgpout, LANG("\007Maintenance pass error. ") );
        !          1737:                }
        !          1738: 
        !          1739:                if (status < 0) {
        !          1740:                        fprintf(pgpout, LANG("\007Keyring edit error. ") );
        !          1741:                        errorLvl = KEYRING_EDIT_ERROR;
        !          1742:                }
        !          1743:                return status;
        !          1744:        }       /* Key edit */
        !          1745: 
        !          1746:        /*-------------------------------------------------------*/
        !          1747:        case 'a':
        !          1748:        {       /*      Add key to key ring
        !          1749:                        Arguments: keyfile, ringfile
        !          1750:                */
        !          1751: 
        !          1752:                if (myArgc < 3 && !filter_mode)
        !          1753:                        arg_error();
        !          1754: 
        !          1755:                if (!filter_mode) {     /* Get the keyfile from args */
        !          1756:                        strncpy( keyfile, myArgv[2], sizeof(keyfile)-1 );
        !          1757:                        
        !          1758: #ifdef MSDOS
        !          1759:                        strlwr( keyfile  );
        !          1760: #endif
        !          1761:                        if (! file_exists( keyfile ))
        !          1762:                                default_extension( keyfile, PGP_EXTENSION );
        !          1763: 
        !          1764:                        if (! file_exists( keyfile )) {
        !          1765:                                fprintf(pgpout, LANG("\n\007Key file '%s' does not exist.\n"), keyfile );
        !          1766:                                errorLvl = NONEXIST_KEY_ERROR;
        !          1767:                                return -1;
        !          1768:                        }
        !          1769: 
        !          1770:                        workfile = keyfile;
        !          1771: 
        !          1772:                } else {
        !          1773:                        workfile = tempfile(TMP_WIPE|TMP_TMPDIR);
        !          1774:                        readPhantomInput(workfile);
        !          1775:                }
        !          1776: 
        !          1777:                if (myArgc < (filter_mode ? 3 : 4)) { /* default key ring filename */
        !          1778:                        byte ctb;
        !          1779:                        get_header_info_from_file(workfile, &ctb, 1);
        !          1780:                        if (ctb == CTB_CERT_SECKEY)
        !          1781:                                strcpy(ringfile, globalSecringName);
        !          1782:                        else
        !          1783:                                strcpy(ringfile, globalPubringName);
        !          1784:                } else {
        !          1785:                        strncpy( ringfile, myArgv[(filter_mode ? 2 : 3)], sizeof(ringfile)-1 );
        !          1786:                        default_extension( ringfile, PGP_EXTENSION );
        !          1787:                }
        !          1788: #ifdef MSDOS
        !          1789:                strlwr( ringfile );
        !          1790: #endif
        !          1791: 
        !          1792:                status = addto_keyring( workfile, ringfile);
        !          1793: 
        !          1794:                if (filter_mode)
        !          1795:                        rmtemp(workfile);
        !          1796: 
        !          1797:                if (status < 0) {
        !          1798:                        fprintf(pgpout, LANG("\007Keyring add error. ") );
        !          1799:                        errorLvl = KEYRING_ADD_ERROR;
        !          1800:                }
        !          1801:                return status;
        !          1802:        }       /* Add key to key ring */
        !          1803: 
        !          1804:        /*-------------------------------------------------------*/
        !          1805:        case 'x':
        !          1806:        {       /*      Extract key from key ring
        !          1807:                        Arguments: mcguffin, keyfile, ringfile
        !          1808:                */
        !          1809: 
        !          1810:                if (myArgc >= (filter_mode ? 4 : 5))    /* default key ring filename */
        !          1811:                        strncpy( ringfile, myArgv[(filter_mode ? 3 : 4)], sizeof(ringfile)-1 );
        !          1812:                else
        !          1813:                        strcpy(ringfile, globalPubringName);
        !          1814: 
        !          1815:                if (myArgc >= (filter_mode ? 2 : 3)) {
        !          1816:                        if (myArgv[2])
        !          1817:                                /* Userid to extract */
        !          1818:                                strcpy( mcguffin, myArgv[2] );  
        !          1819:                        else
        !          1820:                                strcpy( mcguffin, "" );
        !          1821:                } else {
        !          1822:                        fprintf(pgpout, LANG("\nA user ID is required to select the key you want to extract. "));
        !          1823:                        if (batchmode)  /* not interactive, userid must be on command line */
        !          1824:                                return -1;
        !          1825:                        fprintf(pgpout, LANG("\nEnter the key's user ID: "));
        !          1826:                        getstring( mcguffin, 255, TRUE );       /* echo keyboard */
        !          1827:                }
        !          1828:                CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          1829: 
        !          1830:                if (!filter_mode) {
        !          1831:                        if (myArgc >= 4)
        !          1832:                                strncpy(keyfile, myArgv[3], sizeof(keyfile)-1);
        !          1833:                        else
        !          1834:                                keyfile[0] = '\0';
        !          1835: 
        !          1836:                        workfile = keyfile;
        !          1837:                } else {
        !          1838:                        workfile = tempfile(TMP_WIPE|TMP_TMPDIR);
        !          1839:                }
        !          1840: 
        !          1841: #ifdef MSDOS
        !          1842:                strlwr( workfile );
        !          1843:                strlwr( ringfile );
        !          1844: #endif
        !          1845: 
        !          1846:                default_extension( ringfile, PGP_EXTENSION );
        !          1847: 
        !          1848:                status = extract_from_keyring( mcguffin, workfile,
        !          1849:                                ringfile, (filter_mode ? FALSE :
        !          1850:                                           emit_radix_64) );
        !          1851: 
        !          1852:                if (status < 0) {
        !          1853:                        fprintf(pgpout, LANG("\007Keyring extract error. ") );
        !          1854:                        errorLvl = KEYRING_EXTRACT_ERROR;
        !          1855:                        if (filter_mode)
        !          1856:                                rmtemp(workfile);
        !          1857:                        return status;
        !          1858:                }
        !          1859: 
        !          1860: 
        !          1861:                if (filter_mode && !status) {
        !          1862:                        if (emit_radix_64) {
        !          1863:                                /* NULL for outputfile means write to stdout */
        !          1864:                                if (armor_file(workfile, NULL, NULL, NULL) != 0)
        !          1865:                                {
        !          1866:                                        errorLvl = UNKNOWN_FILE_ERROR;
        !          1867:                                        return -1;
        !          1868:                                }
        !          1869:                        } else {
        !          1870:                                if (writePhantomOutput(workfile) < 0) {
        !          1871:                                        errorLvl = UNKNOWN_FILE_ERROR;
        !          1872:                                        return -1;
        !          1873:                                }
        !          1874:                        }
        !          1875:                        rmtemp(workfile);
        !          1876:                }
        !          1877: 
        !          1878:                return 0;
        !          1879:        }       /* Extract key from key ring */
        !          1880: 
        !          1881:        /*-------------------------------------------------------*/
        !          1882:        case 'r':
        !          1883:        {       /*      Remove keys or selected key signatures from userid keys
        !          1884:                        Arguments: userid, ringfile
        !          1885:                */
        !          1886: 
        !          1887:                if (myArgc >= 4)
        !          1888:                        strcpy( ringfile, myArgv[3] );
        !          1889:                else    /* default key ring filename */
        !          1890:                        strcpy(ringfile, globalPubringName);
        !          1891: 
        !          1892:                if (myArgc >= 3) {
        !          1893:                        strcpy( mcguffin, myArgv[2] );  /* Userid to work on */
        !          1894:                } else {
        !          1895:                        if (sign_flag) {
        !          1896:                                fprintf(pgpout, LANG("\nA user ID is required to select the public key you want to\n\
        !          1897: remove certifying signatures from. "));
        !          1898:                        } else {
        !          1899:                                fprintf(pgpout, LANG("\nA user ID is required to select the key you want to remove. "));
        !          1900:                        }
        !          1901:                        if (batchmode)  /* not interactive, userid must be on command line */
        !          1902:                                return -1;
        !          1903:                        fprintf(pgpout, LANG("\nEnter the key's user ID: "));
        !          1904:                        getstring( mcguffin, 255, TRUE );       /* echo keyboard */
        !          1905:                }
        !          1906:                CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          1907: 
        !          1908: #ifdef MSDOS
        !          1909:                strlwr( ringfile );
        !          1910: #endif
        !          1911:                if (! file_exists( ringfile ))
        !          1912:                        default_extension( ringfile, PGP_EXTENSION );
        !          1913: 
        !          1914:                if (sign_flag) {                /* Remove signatures */
        !          1915:                        if (remove_sigs( mcguffin, ringfile ) < 0) {
        !          1916:                                fprintf(pgpout, LANG("\007Key signature remove error. ") );
        !          1917:                                errorLvl = KEYSIG_REMOVE_ERROR;
        !          1918:                                return -1;
        !          1919:                        }
        !          1920:                } else {                /* Remove keyring */
        !          1921:                        if (remove_from_keyring( NULL, mcguffin, ringfile, (boolean) (myArgc < 4) ) < 0)
        !          1922:                        {
        !          1923:                                fprintf(pgpout, LANG("\007Keyring remove error. ") );
        !          1924:                                errorLvl = KEYRING_REMOVE_ERROR;
        !          1925:                                return -1;
        !          1926:                        }
        !          1927:                }
        !          1928:                return 0;
        !          1929:        }       /* remove key signatures from userid */
        !          1930: 
        !          1931:        /*-------------------------------------------------------*/
        !          1932:        case 'v':
        !          1933:        case 'V':               /* -kvv */
        !          1934:        {       /*      View or remove key ring entries, with userid match
        !          1935:                        Arguments: userid, ringfile
        !          1936:                */
        !          1937: 
        !          1938:                if (myArgc < 4) /* default key ring filename */
        !          1939:                        strcpy(ringfile, globalPubringName);
        !          1940:                else
        !          1941:                        strcpy( ringfile, myArgv[3] );
        !          1942: 
        !          1943:                if (myArgc > 2) {
        !          1944:                        strcpy( mcguffin, myArgv[2] );
        !          1945:                        if (strcmp( mcguffin, "*" ) == 0)
        !          1946:                                mcguffin[0] = '\0';
        !          1947:                } else {
        !          1948:                        *mcguffin = '\0';
        !          1949:                }
        !          1950: 
        !          1951:                if ((myArgc == 3) && has_extension( myArgv[2], PGP_EXTENSION ))
        !          1952:                {
        !          1953:                        strcpy( ringfile, myArgv[2] );
        !          1954:                        mcguffin[0] = '\0';
        !          1955:                }
        !          1956:                CONVERT_TO_CANONICAL_CHARSET(mcguffin);
        !          1957: 
        !          1958: #ifdef MSDOS
        !          1959:                strlwr( ringfile );
        !          1960: #endif
        !          1961:                if (! file_exists( ringfile ))
        !          1962:                        default_extension( ringfile, PGP_EXTENSION );
        !          1963: 
        !          1964:                /* If a second 'v' (keychar = V), show signatures too */
        !          1965:                status = view_keyring(mcguffin, ringfile, (boolean) (keychar == 'V'), c_flag);
        !          1966:                if (status < 0) {
        !          1967:                        fprintf(pgpout, LANG("\007Keyring view error. ") );
        !          1968:                        errorLvl = KEYRING_VIEW_ERROR;
        !          1969:                }
        !          1970:                return status;
        !          1971:        }       /* view key ring entries, with userid match */
        !          1972: 
        !          1973:        default:
        !          1974:                arg_error();
        !          1975:        }
        !          1976:        return 0;
        !          1977: } /* do_keyopt */
        !          1978: 
        !          1979: 
        !          1980: 
        !          1981: void user_error() /* comes here if user made a boo-boo. */
        !          1982: {
        !          1983:        fprintf(pgpout,LANG("\nFor a usage summary, type:  pgp -h\n"));
        !          1984:        fprintf(pgpout,LANG("For more detailed help, consult the PGP User's Guide.\n"));
        !          1985:        exitPGP(errorLvl ? errorLvl : 127);             /* error exit */
        !          1986: }
        !          1987: 
        !          1988: #if defined(DEBUG) && defined(linux)
        !          1989: #include <malloc.h>
        !          1990: #endif
        !          1991: /*
        !          1992:  * exitPGP: wipes and removes temporary files, also tries to wipe
        !          1993:  * the stack.
        !          1994:  */
        !          1995: void exitPGP(int returnval)
        !          1996: {
        !          1997:        char buf[STACK_WIPE];
        !          1998:        struct hashedpw *hpw;
        !          1999: 
        !          2000:        if (verbose)
        !          2001:                fprintf(pgpout, "exitPGP: exitcode = %d\n", returnval);
        !          2002:        for (hpw = passwds; hpw; hpw = hpw->next)
        !          2003:                memset(hpw->hash, 0, sizeof(hpw->hash));
        !          2004:        for (hpw = keypasswds; hpw; hpw = hpw->next)
        !          2005:                memset(hpw->hash, 0, sizeof(hpw->hash));
        !          2006:        cleanup_tmpf();
        !          2007: #if defined(DEBUG) && defined(linux)
        !          2008:        if (verbose) {
        !          2009:                struct mstats mstat;
        !          2010:                mstat = mstats();
        !          2011:                printf("%d chunks used (%d bytes)  %d bytes total\n",
        !          2012:                        mstat.chunks_used, mstat.bytes_used, mstat.bytes_total);
        !          2013:        }
        !          2014: #endif
        !          2015:        memset(buf, 0, sizeof(buf));    /* wipe stack */
        !          2016: #ifdef VMS
        !          2017: /*
        !          2018:  * Fake VMS style error returns with severity in bottom 3 bits
        !          2019:  */
        !          2020:        if (returnval)
        !          2021:            returnval = (returnval << 3) | 0x10000002;
        !          2022:        else
        !          2023:            returnval = 0x10000001;
        !          2024: #endif /* VMS */
        !          2025:        exit(returnval);
        !          2026: }
        !          2027: 
        !          2028: 
        !          2029: static void arg_error()
        !          2030: {
        !          2031:        signon_msg();
        !          2032:        fprintf(pgpout,LANG("\nInvalid arguments.\n"));
        !          2033:        errorLvl = BAD_ARG_ERROR;
        !          2034:        user_error();
        !          2035: }
        !          2036: 
        !          2037: /*
        !          2038:  * Check for language specific help files in PGPPATH, then the system
        !          2039:  * directory.  If that fails, check for the default pgp.hlp, again
        !          2040:  * firat a private copy, then the system-wide one.
        !          2041:  *
        !          2042:  * System-wide copies currently only exist on Unix.
        !          2043:  */
        !          2044: static void
        !          2045: build_helpfile(char *helpfile, char const *extra)
        !          2046: {
        !          2047:        if (strcmp(language, "en")) {
        !          2048:                buildfilename(helpfile, language);
        !          2049:                strcat(helpfile, extra);
        !          2050:                force_extension(helpfile, HLP_EXTENSION);
        !          2051:                if (file_exists(helpfile))
        !          2052:                        return;
        !          2053: #ifdef PGP_SYSTEM_DIR
        !          2054:                strcpy(helpfile, PGP_SYSTEM_DIR);
        !          2055:                strcat(helpfile, language);
        !          2056:                strcat(helpfile, extra);
        !          2057:                force_extension(helpfile, HLP_EXTENSION);
        !          2058:                if (file_exists(helpfile))
        !          2059:                        return;
        !          2060: #endif
        !          2061:        }
        !          2062:        buildfilename(helpfile, "pgp");
        !          2063:        strcat(helpfile, extra);
        !          2064:        force_extension(helpfile, HLP_EXTENSION);
        !          2065: #ifdef PGP_SYSTEM_DIR
        !          2066:        if (file_exists(helpfile))
        !          2067:                return;
        !          2068:        strcpy(helpfile, PGP_SYSTEM_DIR);
        !          2069:        strcat(helpfile, "pgp");
        !          2070:        strcat(helpfile, extra);
        !          2071:        force_extension(helpfile, HLP_EXTENSION);
        !          2072: #endif
        !          2073: }
        !          2074: 
        !          2075: static void usage()
        !          2076: {
        !          2077:        char helpfile[MAX_PATH];
        !          2078:        char *tmphelp = helpfile;
        !          2079:        extern unsigned char *ext_c_ptr;
        !          2080: 
        !          2081:        signon_msg();
        !          2082:        build_helpfile(helpfile, "");
        !          2083:   
        !          2084:        if (ext_c_ptr) {
        !          2085:                /* conversion to external format necessary */
        !          2086:                tmphelp = tempfile(TMP_TMPDIR);
        !          2087:                CONVERSION = EXT_CONV;
        !          2088:                if (copyfiles_by_name(helpfile, tmphelp) < 0) {
        !          2089:                        rmtemp(tmphelp);
        !          2090:                        tmphelp = helpfile;
        !          2091:                }
        !          2092:                CONVERSION = NO_CONV;
        !          2093:        }
        !          2094: 
        !          2095:          /* built-in help if pgp.hlp is not available */
        !          2096:        if (more_file(tmphelp) < 0)
        !          2097:                fprintf(pgpout,LANG("\nUsage summary:\
        !          2098: \nTo encrypt a plaintext file with recipent's public key, type:\
        !          2099: \n   pgp -e textfile her_userid [other userids] (produces textfile.pgp)\
        !          2100: \nTo sign a plaintext file with your secret key:\
        !          2101: \n   pgp -s textfile [-u your_userid]           (produces textfile.pgp)\
        !          2102: \nTo sign a plaintext file with your secret key, and then encrypt it\
        !          2103: \n   with recipent's public key, producing a .pgp file:\
        !          2104: \n   pgp -es textfile her_userid [other userids] [-u your_userid]\
        !          2105: \nTo encrypt with conventional encryption only:\
        !          2106: \n   pgp -c textfile\
        !          2107: \nTo decrypt or check a signature for a ciphertext (.pgp) file:\
        !          2108: \n   pgp ciphertextfile [plaintextfile]\
        !          2109: \nTo produce output in ASCII for email, add the -a option to other options.\
        !          2110: \nTo generate your own unique public/secret key pair:  pgp -kg\
        !          2111: \nFor help on other key management functions, type:   pgp -k\n"));
        !          2112:        if (ext_c_ptr)
        !          2113:                rmtemp(tmphelp);
        !          2114:        exit(BAD_ARG_ERROR);            /* error exit */
        !          2115: }
        !          2116: 
        !          2117: 
        !          2118: static void key_usage()
        !          2119: {
        !          2120:        char helpfile[MAX_PATH];
        !          2121:        char *tmphelp = helpfile;
        !          2122:        extern unsigned char *ext_c_ptr;
        !          2123: 
        !          2124:        signon_msg();
        !          2125:        build_helpfile(helpfile, "key");
        !          2126:   
        !          2127:        if (ext_c_ptr) {
        !          2128:                /* conversion to external format necessary */
        !          2129:                tmphelp = tempfile(TMP_TMPDIR);
        !          2130:                CONVERSION = EXT_CONV;
        !          2131:                if (copyfiles_by_name(helpfile, tmphelp) < 0) {
        !          2132:                        rmtemp(tmphelp);
        !          2133:                        tmphelp = helpfile;
        !          2134:                }
        !          2135:                CONVERSION = NO_CONV;
        !          2136:        }
        !          2137: 
        !          2138:          /* built-in help if pgp.hlp is not available */
        !          2139:        if (more_file(tmphelp) < 0)
        !          2140:                /* only use built-in help if there is no helpfile */
        !          2141:                fprintf(pgpout,LANG("\nKey management functions:\
        !          2142: \nTo generate your own unique public/secret key pair:\
        !          2143: \n   pgp -kg\
        !          2144: \nTo add a key file's contents to your public or secret key ring:\
        !          2145: \n   pgp -ka keyfile [keyring]\
        !          2146: \nTo remove a key or a user ID from your public or secret key ring:\
        !          2147: \n   pgp -kr userid [keyring]\
        !          2148: \nTo edit your user ID or pass phrase:\
        !          2149: \n   pgp -ke your_userid [keyring]\
        !          2150: \nTo extract (copy) a key from your public or secret key ring:\
        !          2151: \n   pgp -kx userid keyfile [keyring]\
        !          2152: \nTo view the contents of your public key ring:\
        !          2153: \n   pgp -kv[v] [userid] [keyring]\
        !          2154: \nTo check signatures on your public key ring:\
        !          2155: \n   pgp -kc [userid] [keyring]\
        !          2156: \nTo sign someone else's public key on your public key ring:\
        !          2157: \n   pgp -ks her_userid [-u your_userid] [keyring]\
        !          2158: \nTo remove selected signatures from a userid on a keyring:\
        !          2159: \n   pgp -krs userid [keyring]\
        !          2160: \n"));
        !          2161:        
        !          2162:        exit(BAD_ARG_ERROR);            /* error exit */
        !          2163: }

unix.superglobalmegacorp.com

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