📄 pgpexit.c
字号:
/*
* pgpExit.c -- This code is for a runtime app. It is *NOT* threaded,
* in any sense of the word. It stores state in static variables
* and wipes system stack and heap when exiting from the application.
*
* Copyright (C) 1996,1997 Pretty Good Privacy, Inc. All rights reserved.
*
* Written by: Colin Plumb and Derek Atkins <warlord@MIT.EDU>
*
* $Id: pgpExit.c,v 1.4.2.4.2.7 1997/07/15 21:26:17 quark Exp $
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <signal.h>
#include <string.h> /* For memset() */
#include <stdio.h>
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* for getenv() */
#endif
#ifdef UNIX
#include <sys/types.h> /* For sbrk() */
#elif defined(MSDOS)
#include <malloc.h> /* For stackavail(), alloca() */
#if MSC_VER >= 800
/*
* See flame elsewhere about Microsoft's stupid ideas about the name spaces
* that are reserved by ANSI C if you do something undefined by ANSI like
* include an undefined header (like <malloc.h>).
*/
#define alloca _alloca
#define stackavail _stackavail
#endif /* MSC_VER >= 800 */
#endif /* MSDOS */
#include "pgpExit.h"
#include "pgpKeyRings.h"
#include "pgpEnv.h"
#include "pgpRndPool.h"
#include "pgpRndSeed.h"
#include "pgpTimeDate.h"
#include "pgpVersion.h"
#include "pgpOutput.h"
static void *stack0 = NULL, *heap0 = NULL;
static struct PgpEnv *env0 = NULL;
static int program_name = 0;
static int newversion = 0; /* whether keyrings should be rewritten as
latest version (1) or original version (0) */
/* Expiry date in days - defined for beta versions */
#define EXPIRY_DATE pgpDateFromYMD(1997, 12, 31)
/*
* This usually returns, but will exit if this is an old beta version that
* shouldn't be in use any more.
*/
void
exitExpiryCheck (struct PgpEnv *env)
{
#ifdef EXPIRY_DATE
int tzFix = pgpenvGetInt (env, PGPENV_TZFIX, NULL, NULL);
unsigned today = (unsigned)(pgpTimeStamp (tzFix)/86400);
unsigned expires = EXPIRY_DATE;
if (expires >= today) {
expires -= today;
if (expires < 30)
fprintf (stderr,
"This beta version of PGP will expire in %u days\n", expires);
return;
}
fputs ("\aThis beta evaluation version of PGP has expired.\n", stderr);
#if 0
if (!getenv ("OVERRIDE_PGP_TIMEBOMB"))
exitCleanup(PGPEXIT_VERSION);
#endif
#endif
}
void
exitUsage (int code)
{
switch (program_name) {
case EXIT_PROG_PGPE:
fputs ("\n\
pgpe [[-r <recip1> -r <recip2>] [-s [-u <myid>]] | [-c]] [-afqtvz]\n\
<file1> [-o outfile1] <file2> [-o <outfile2>]\n\
\n\
PGP Encrypt file(s)\n\
\n\
-a ASCII armoring\n\
-c Conventional Encryption (IDEA only; is mutually exclusive\n\
with -s, -u and -r)\n\
-f Filter Mode; Read from stdin to stdout\n\
-o <output file> Output file for most recent input file\n\
-q Quiet mode\n\
-r <userid> UserID to encrypt to. May be specified multiple times.\n\
-s Sign, as well as encrypt (use pgps to just sign). If no\n\
userid is specified with -u, the default userid is used.\n\
-t Text mode\n\
-u <userid> UserID of the key you wish to sign with. May only be\n\
specified once.\n\
-v Verbose\n\
-z Batch mode (assumes no user interaction; not yet\n\
implemented.\n\n\
--license Display usage license\n\
Other programs in this suite include pgps to sign, pgpv to decrypt/verify,\n\
and pgpk for key management.\n", stdout);
break;
case EXIT_PROG_PGPS:
fputs ("\n\
pgps [-u userid] [-bafqtvz] <file1> [-o <outfile> file2 [-o <outfile2>]]\n\
\n\
PGP Sign file(s)\n\
\n\
-a ASCII armoring\n\
-b Detached signature\n\
-f Filter Mode; Read from stdin to stdout\n\
-o <output file> Output file for most recent input file\n\
-q Quiet mode\n\
-t Text mode\n\
-u <userid> UserID of the key you wish to sign with. May only be\n\
specified once. If not specified, your default signing\n\
key will be used.\n\
-v Verbose\n\
-z Batch mode (assumes no user interaction; not yet\n\
implemented.)\n\n\
--license Display usage license\n\
Other programs in this suite include pgpe to encrypt, pgpv to\n\
decrypt/verify, and pgpk for key management.\n", stdout);
break;
case EXIT_PROG_PGPV:
fputs ("\n\
pgpv [-dfKmqvz] <file1> [-o <outfile> file2 -o <outfile2>]\n\
\n\
Decrypt/Verify PGP encrypted and/or signed file(s)\n\
\n\
-f Filter Mode; Read from stdin to stdout\n\
-K Do not process any keys that are present (normally pgpv\n\
will add keys to your keyring if found in an input file)\n\
-m More Mode; display using pager rather than saving\n\
-o <output file> Output file for most recent input file\n\
-q Quiet mode\n\
-v Verbose\n\
-z Batch mode (assumes no user interaction; not yet\n\
implemented).\n\n\
--license Display usage license\n\
Other programs in this suite include pgpe to encrypt, pgps to sign,\n\
and pgpk for key management.\n", stdout);
break;
case EXIT_PROG_PGPO:
fputs ("\n\
pgp_old [-dfKmqvz] <file1> [-o <outfile> file2 -o <outfile2>]\n\
\n\
Old-style PGP 2.6.2 emulation command-line\n\
\n\
--license Display usage license\n\
Sadly, this isn't implemented yet.\n", stdout);
break;
/*XXX Rewrite this to be more Unix-like*/
case EXIT_PROG_PGPK:
fputs ("\n"\
"Usage summary: (for full details, see the User's guide)\n"\
"\n"\
"To generate your own unique public/private key pair:\n"\
" pgpk -g [<userid> DSS|RSA <keysize> <userid> <validity> <passphrase>]\n"\
"To add a key file's contents to your public or private key ring:\n"\
" pgpk -a keyfile [keyfile ...]\n"\
"To remove a key from your public and private key ring:\n"\
" pgpk -r userid (or pgpk -rk userid)\n"\
"To remove a user ID from your public and private key ring:\n"\
" pgpk -ru userid\n"\
"To remove a signature from your public key ring:\n"\
" pgpk -rs userid\n"\
"To edit your user ID or pass phrase:\n"\
" pgpk -e your_userid\n"\
"To edit the confidence you have in a person as an introducer:\n"\
" pgpk -e her_userid\n"\
"To extract (copy) a key from your public key ring:\n"\
" pgpk -x userid -o keyfile\n"\
"To extract (copy) a key from your public key ring in ascii form:\n"\
" pgpk -xa userid -o keyfile\n"\
"To list the contents of your key rings:\n"\
" pgpk -l[l] [userid]\n"\
"To check signatures on your public key ring:\n"\
" pgpk -c [userid]\n"\
"To sign someone else's public key on your public key ring:\n"\
" pgpk -s her_userid [-u your_userid]\n"\
"To disable or re-enable some else's public key on your public key ring:\n"\
" pgpk -d her_userid\n"\
"To permanently revoke your own key on your public and private key rings:\n"\
" pgpk --revoke your_userid\n"\
"To revoke a signature you made on someone else's key on your pub key ring:\n"\
" pgpk --revokes your_userid\n"\
"To view the license granted you:\n"\
" pgpk --license\n"\
"", stdout);
break;
default:
fputs ("\n\
Usage summary unavailable for this program.\n\
\n", stdout);
break;
}
exitCleanup(code);
}
/* attribute(x) expands to nothing unless __GNUC__ is defined. */
static void exitWipe(int code) attribute((noreturn));
static void exitWipe1(int code, void *base) attribute((noreturn));
#ifdef MSDOS
#include <dos.h> /* FOR MK_FP, FP_SEG and FP_OFF */
#include <malloc.h> /* for alloca(), stackavail(), _heapwalk() */
/*
* Now, Microsoft has recently developed a habit of prepending an underscore
* to the beginning of everything. They wave their arms and mutter about ANSI.
* If they have a really broken linker then I can see how they might not be
* able to deal with user code declaring functions that are also supplied in
* the library, so they need to put the functions in a name space that user
* code can't declare in, BUT THIS SURE DOESN'T APPLY TO MACROS. For any
* header *not* defined by ANSI (such as, say, <dos.h>, <conio.h>, <io.h>,
* <unistd.h>, <sys/types.h>, etc.), any structures, unions, macros, enums,
* and so on - anything not visible to the linker - can be defined any
* way you like.
*
* So I don't understand Microsoft. Defining prefix-prepended aliases
* for library-internal calls is fine (so my extern variable "write"
* won't get called when I call printf()), but to get rid of more convenient
* names if I *do* include the relevant file? Wierd.
*/
#ifndef MK_FP
#ifdef _MK_FP
#define MK_FP _MK_FP
#else
#define MK_FP(seg,off) ((void __far *)((seg)<<16 | (off)))
#endif
#endif /* !MK_FP */
#ifndef FP_SEG
#ifdef _FP_SEG
#define FP_SEG _FP_SEG
#else
#define FP_SEG(ptr) ((unsigned)((unsigned long)(ptr) >> 16))
#endif
#endif /* !FP_SEG */
#ifndef FP_OFF
#ifdef _FP_OFF
#define FP_OFF _FP_OFF
#else
#define FP_OFF(ptr) ((unsigned)(ptr))
#endif
#endif /* !FP_OFF */
#if MSC_VER >= 800
#define alloca _alloca
#define stackavail _stackavail
#endif
static void
exitWipe1(int code, void *base)
{
int status;
/* Wipe the stack */
if (stack0)
memset(base, 0, (char *)(stack0)-(char *)base);
#ifdef UNIX
/* ACHTUNG! This code might be dangerous */
{
struct _heapinfo info;
/* Wipe the heap */
/* First pass - initial wipe with 0xff */
_heapset(0xff);
info._pentry = 0;
while (_heapwalk(&info) == _HEAPOK) {
if (info._useflag == _USEDENTRY) {
memset(info._pentry, 0xff, info._size);
free(info._pentry);
/* free() mucks up _heapwalk, so restart */
info._pentry = 0;
}
}
/* Second pass - wipe all free areas */
_heapset(0);
}
#endif /* UNIX */
exit(code);
}
#if __BORLANDC__
#if __BORLANDC <= 0x0400
unsigned _stklen = 16384;
#else
unsigned const _stklen = 16384;
#endif
#endif
static void
exitWipe(int code)
{
exitWipe1(code, alloca(stackavail()-500));
}
#else /* !MSDOS */
static void
exitWipe1(int code, void *base)
{
/* Wipe the stack */
if (stack0)
memset(base, 0, ((char *)(stack0)-(char *)base));
#if 0 /* Disabled until stdio problems can be resolved */
/* Wipe the heap */
if (heap0) {
base = sbrk(0);
memset(heap0, 0, (char *)base-(char *)heap0);
}
#endif
#ifdef VMS /* On VMS, the bottom 3 bits are a severity */
code = (1<<28) | (code << 3) | (1 + (code != 0));
#endif
exit(code);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -