1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

This commit was manufactured by cvs2svn to create branch

'GNUPG-1-9-BRANCH'.
This commit is contained in:
Repo Admin 2002-10-19 07:55:27 +00:00
parent 8d76177f10
commit 82a17c9fb3
563 changed files with 0 additions and 267875 deletions

View file

@ -1,102 +0,0 @@
2002-09-25 David Shaw <dshaw@jabberwocky.com>
* Makefile.am: Link bftest with EGDLIBS (i.e. NETLIBS) as EGD uses
sockets.
2002-05-07 Stefan Bellon <sbellon@sbellon.de>
* gpgsplit.c (create_filename): Use EXTSEP_S instead of ".".
2002-04-23 David Shaw <dshaw@jabberwocky.com>
* Makefile.am: Do not list libraries in -lxxx format in a
dependency line.
2002-01-02 Stefan Bellon <sbellon@sbellon.de>
* gpgsplit.c [__riscos__]: Added RISC OS specific file name
code.
* gpgsplit.c (write_part): Introduced two explicit casts.
2001-12-21 David Shaw <dshaw@jabberwocky.com>
* gpgsplit.c (pkttype_to_string): PKT_PHOTO_ID -> PKT_ATTRIBUTE
2001-10-23 Werner Koch <wk@gnupg.org>
* Makefile.am (gpgsplit_LDADD): Add ZLIBS.
2001-09-18 Werner Koch <wk@gnupg.org>
* gpgsplit.c: New option --uncompress.
(write_part): Handle old style uncompressing.
2001-06-20 Werner Koch <wk@gnupg.org>
* gpgsplit.c: New.
* Makefile.am (bin_PROGRAMS): Install gpgsplit.
2001-03-27 Werner Koch <wk@gnupg.org>
* mail-signed-keys: Add option --dry-run.
2001-03-21 Werner Koch <wk@gnupg.org>
* shmtest.c: Add sys/types.h
Fri Sep 15 18:40:36 CEST 2000 Werner Koch <wk@openit.de>
* ring-a-party: An array start at offset 1 no 0. Many thanks to Mike
for finding this bug.
Thu Sep 14 14:20:38 CEST 2000 Werner Koch <wk@openit.de>
* ring-a-party: Flush the last key.
Wed Jul 5 13:28:45 CEST 2000 Werner Koch <wk@>
* mail-signed-keys: New.
Tue May 23 09:19:00 CEST 2000 Werner Koch <wk@openit.de>
* ring-a-party: New.
Thu Jul 8 16:21:27 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* lspgpot: New
Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* Makefile.am: Support for libtool.
Tue Jun 8 13:36:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* mpicalc.c (main): hex digits may now be lowercase
(do_mulm): new.
Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* mpicalc.c (main): Moved initialization out of definition.
Mon May 18 15:39:22 1998 Werner Koch (wk@isil.d.shuttle.de)
* mk-tdata.c: New.
Tue Apr 7 19:50:41 1998 Werner Koch (wk@isil.d.shuttle.de)
* bftest.c: Now supports all availabe ciphers.
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

View file

@ -1,45 +0,0 @@
# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
#
# This file is part of GnuPG.
#
# GnuPG is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# GnuPG is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
## Process this file with automake to produce Makefile.in
EXTRA_DIST = lspgpot ring-a-party mail-signed-keys
INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl
needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a
bin_PROGRAMS = gpgsplit
noinst_PROGRAMS = mpicalc bftest clean-sat mk-tdata shmtest
mpicalc_SOURCES = mpicalc.c
bftest_SOURCES = bftest.c
clean_sat_SOURCES = clean-sat.c
mk_tdata_SOURCES = mk-tdata.c
shmtest_SOURCES = shmtest.c
gpgsplit_SOURCES = gpgsplit.c
mpicalc_LDADD = $(needed_libs) @INTLLIBS@
bftest_LDADD = $(needed_libs) @EGDLIBS@ @INTLLIBS@
shmtest_LDADD = $(needed_libs) @INTLLIBS@
gpgsplit_LDADD = @ZLIBS@ $(needed_libs) @INTLLIBS@
mpicalc bftest shmtest gpgsplit: $(needed_libs)

View file

@ -1,112 +0,0 @@
/* bftest.c - Blowfish test program
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_DOSISH_SYSTEM
#include <io.h>
#include <fcntl.h>
#endif
#include "util.h"
#include "cipher.h"
#include "i18n.h"
static void
my_usage(void)
{
fprintf(stderr, "usage: bftest [-e][-d] algo key\n");
exit(1);
}
const char *
strusage( int level )
{
return default_strusage(level);
}
static void
i18n_init(void)
{
#ifdef ENABLE_NLS
#ifdef HAVE_LC_MESSAGES
setlocale( LC_MESSAGES, "" );
#else
setlocale( LC_ALL, "" );
#endif
bindtextdomain( PACKAGE, G10_LOCALEDIR );
textdomain( PACKAGE );
#endif
}
int
main(int argc, char **argv)
{
int encode=0;
CIPHER_HANDLE hd;
char buf[4096];
int n, size=4096;
int algo;
#ifdef HAVE_DOSISH_SYSTEM
setmode( fileno(stdin), O_BINARY );
setmode( fileno(stdout), O_BINARY );
#endif
i18n_init();
if( argc > 1 && !strcmp(argv[1], "-e") ) {
encode++;
argc--; argv++;
}
else if( argc > 1 && !strcmp(argv[1], "-E") ) {
encode++;
argc--; argv++;
size = 10;
}
else if( argc > 1 && !strcmp(argv[1], "-d") ) {
argc--; argv++;
}
else if( argc > 1 && !strcmp(argv[1], "-D") ) {
argc--; argv++;
size = 10;
}
if( argc != 3 )
my_usage();
argc--; argv++;
algo = string_to_cipher_algo( *argv );
argc--; argv++;
hd = cipher_open( algo, CIPHER_MODE_CFB, 0 );
cipher_setkey( hd, *argv, strlen(*argv) );
cipher_setiv( hd, NULL, 0 );
while( (n = fread( buf, 1, size, stdin )) > 0 ) {
if( encode )
cipher_encrypt( hd, buf, buf, n );
else
cipher_decrypt( hd, buf, buf, n );
if( fwrite( buf, 1, n, stdout) != n )
log_fatal("write error\n");
}
cipher_close(hd);
return 0;
}

View file

@ -1,34 +0,0 @@
/* clean-sat.c
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is free software; as a special exception the author gives
* unlimited permission to copy and/or distribute it, with or without
* modifications, as long as this notice is preserved.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stdio.h>
int
main(int argc, char **argv)
{
int c;
if( argc > 1 ) {
fprintf(stderr, "no arguments, please\n");
return 1;
}
while( (c=getchar()) == '\n' )
;
while( c != EOF ) {
putchar(c);
c = getchar();
}
return 0;
}

View file

@ -1,53 +0,0 @@
/* crlf.c
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is free software; as a special exception the author gives
* unlimited permission to copy and/or distribute it, with or without
* modifications, as long as this notice is preserved.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <stdio.h>
int
main(int argc, char **argv)
{
int c, lc;
int off=0;
if( argc > 1 ) {
fprintf(stderr, "no arguments, please\n");
return 1;
}
lc = -1;
while( (c=getchar()) != EOF ) {
#if 0
if( c == '\r' && lc == ' ' )
fprintf(stderr,"SP,CR at %d\n", off );
if( c == '\n' && lc == ' ' )
fprintf(stderr,"SP,LF at %d\n", off );
#endif
if( c == '\n' && lc == '\r' )
putchar(c);
else if( c == '\n' ) {
putchar('\r');
putchar(c);
}
else if( c != '\n' && lc == '\r' ) {
putchar('\n');
putchar(c);
}
else
putchar(c);
lc = c;
off++;
}
return 0;
}

View file

@ -1,553 +0,0 @@
/* gpgsplit.c - An OpenPGP packet splitting tool
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/*
* TODO: Add an option to uncompress packets. This should come quite handy.
*/
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <assert.h>
#ifdef HAVE_DOSISH_SYSTEM
#include <fcntl.h> /* for setmode() */
#endif
#include <zlib.h>
#ifdef __riscos__
#include <unixlib/local.h>
#endif /* __riscos__ */
#define INCLUDED_BY_MAIN_MODULE 1
#include "../g10/packet.h"
#include "util.h"
static int opt_verbose;
static const char *opt_prefix = "";
static int opt_uncompress;
static void g10_exit( int rc );
static void split_packets (const char *fname);
enum cmd_and_opt_values { aNull = 0,
oVerbose = 'v',
oPrefix = 'p',
oUncompress = 500,
aTest };
static ARGPARSE_OPTS opts[] = {
{ 301, NULL, 0, "@Options:\n " },
{ oVerbose, "verbose", 0, "verbose" },
{ oPrefix, "prefix", 2, "|STRING|Prepend filenames with STRING" },
{ oUncompress, "uncompress", 0, "uncompress a packet"},
{0} };
const char *
strusage( int level )
{
const char *p;
switch( level ) {
case 11: p = "gpgsplit (GnuPG)";
break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p =
"Please report bugs to <bug-gnupg@gnu.org>.\n";
break;
case 1:
case 40: p =
"Usage: gpgsplit [options] [files] (-h for help)";
break;
case 41: p =
"Syntax: gpgsplit [options] [files]\n"
"Split an OpenPGP message into packets\n";
break;
default: p = default_strusage(level);
}
return p;
}
int
main( int argc, char **argv )
{
ARGPARSE_ARGS pargs;
#ifdef __riscos__
/* set global RISC OS specific properties */
__riscosify_control = __RISCOSIFY_NO_PROCESS;
#endif /* __riscos__ */
#ifdef HAVE_DOSISH_SYSTEM
setmode( fileno(stdin), O_BINARY );
setmode( fileno(stdout), O_BINARY );
#endif
log_set_name("gpgsplit");
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */
while( optfile_parse( NULL, NULL, NULL, &pargs, opts) ) {
switch( pargs.r_opt ) {
case oVerbose: opt_verbose = 1; break;
case oPrefix: opt_prefix = pargs.r.ret_str; break;
case oUncompress: opt_uncompress = 1; break;
default : pargs.err = 2; break;
}
}
if( log_get_errorcount(0) )
g10_exit(2);
if (!argc)
split_packets (NULL);
else {
for ( ;argc; argc--, argv++)
split_packets (*argv);
}
g10_exit (0);
return 0;
}
static void
g10_exit( int rc )
{
rc = rc? rc : log_get_errorcount(0)? 2 : 0;
exit(rc );
}
static const char *
pkttype_to_string (int pkttype)
{
const char *s;
switch (pkttype) {
case PKT_PUBKEY_ENC : s = "pk_enc"; break;
case PKT_SIGNATURE : s = "sig"; break;
case PKT_SYMKEY_ENC : s = "sym_enc"; break;
case PKT_ONEPASS_SIG : s = "onepass_sig"; break;
case PKT_SECRET_KEY : s = "secret_key"; break;
case PKT_PUBLIC_KEY : s = "public_key"; break;
case PKT_SECRET_SUBKEY : s = "secret_subkey"; break;
case PKT_COMPRESSED :
s = opt_uncompress? "uncompressed":"compressed";
break;
case PKT_ENCRYPTED : s = "encrypted"; break;
case PKT_MARKER : s = "marker"; break;
case PKT_PLAINTEXT : s = "plaintext"; break;
case PKT_RING_TRUST : s = "ring_trust"; break;
case PKT_USER_ID : s = "user_id"; break;
case PKT_PUBLIC_SUBKEY : s = "public_subkey"; break;
case PKT_OLD_COMMENT : s = "old_comment"; break;
case PKT_ATTRIBUTE : s = "attribute"; break;
case PKT_ENCRYPTED_MDC : s = "encrypted_mdc"; break;
case PKT_MDC : s = "mdc"; break;
case PKT_COMMENT : s = "comment"; break;
case PKT_GPG_CONTROL : s = "gpg_control"; break;
default: s = "unknown"; break;
}
return s;
}
/*
* Create a new filename and a return a pointer to a statically
* allocated buffer
*/
static char *
create_filename (int pkttype)
{
static unsigned int partno = 0;
static char *name;
if (!name)
name = m_alloc (strlen (opt_prefix) + 100 );
assert (pkttype < 1000 && pkttype >= 0 );
partno++;
sprintf (name, "%s%06u-%03d" EXTSEP_S "%.40s",
opt_prefix, partno, pkttype, pkttype_to_string (pkttype));
return name;
}
static int
read_u16 (FILE *fp, size_t *rn)
{
int c;
if ( (c = getc (fp)) == EOF )
return -1;
*rn = c << 8;
if ( (c = getc (fp)) == EOF )
return -1;
*rn |= c;
return 0;
}
static int
read_u32 (FILE *fp, unsigned long *rn)
{
size_t tmp;
if (read_u16 (fp, &tmp))
return -1;
*rn = tmp << 16;
if (read_u16 (fp, &tmp))
return -1;
*rn |= tmp;
return 0;
}
/* hdr must pint to a buffer large enough to hold all header bytes */
static int
write_part ( const char *fname, FILE *fpin, unsigned long pktlen,
int pkttype, int partial, unsigned char *hdr, size_t hdrlen)
{
FILE *fpout;
int c, first;
unsigned char *p;
const char *outname = create_filename (pkttype);
/* fixme: should we check that this file does not yet exist? */
if (opt_verbose)
log_info ("writing `%s'\n", outname);
fpout = fopen (outname, "wb");
if (!fpout) {
log_error ("error creating `%s': %s\n", outname, strerror(errno));
/* stop right now, otherwise we would mess up the sequence of
* the part numbers */
g10_exit (1);
}
if (!opt_uncompress) {
for (p=hdr; hdrlen; p++, hdrlen--) {
if ( putc (*p, fpout) == EOF )
goto write_error;
}
}
first = 1;
while (partial) {
size_t partlen;
if (partial == 1) { /* openpgp */
if( first ) {
c = pktlen;
assert( c >= 224 && c < 255 );
first = 0;
}
else if( (c = getc (fpin)) == EOF ) {
goto read_error;
}
else
hdr[hdrlen++] = c;
if( c < 192 ) {
pktlen = c;
partial = 0; /* (last segment may follow) */
}
else if( c < 224 ) {
pktlen = (c - 192) * 256;
if( (c = getc (fpin)) == EOF )
goto read_error;
hdr[hdrlen++] = c;
pktlen += c + 192;
partial = 0;
}
else if( c == 255 ) {
if (read_u32 (fpin, &pktlen))
goto read_error;
hdr[hdrlen++] = pktlen >> 24;
hdr[hdrlen++] = pktlen >> 16;
hdr[hdrlen++] = pktlen >> 8;
hdr[hdrlen++] = pktlen;
partial = 0;
}
else { /* next partial body length */
for (p=hdr; hdrlen; p++, hdrlen--) {
if ( putc (*p, fpout) == EOF )
goto write_error;
}
partlen = 1 << (c & 0x1f);
for (; partlen; partlen--) {
if ((c = getc (fpin)) == EOF)
goto read_error;
if ( putc (c, fpout) == EOF )
goto write_error;
}
}
}
else if (partial == 2) { /* old gnupg */
assert (!pktlen);
if ( read_u16 (fpin, &partlen) )
goto read_error;
hdr[hdrlen++] = partlen >> 8;
hdr[hdrlen++] = partlen;
for (p=hdr; hdrlen; p++, hdrlen--) {
if ( putc (*p, fpout) == EOF )
goto write_error;
}
if (!partlen)
partial = 0; /* end of packet */
for (; partlen; partlen--) {
c = getc (fpin);
if (c == EOF)
goto read_error;
if ( putc (c, fpout) == EOF )
goto write_error;
}
}
else { /* compressed: read to end */
pktlen = 0;
partial = 0;
hdrlen = 0;
if (opt_uncompress) {
z_stream zs;
byte *inbuf, *outbuf;
unsigned int inbufsize, outbufsize;
int algo, zinit_done, zrc, nread, count;
size_t n;
if ((c = getc (fpin)) == EOF)
goto read_error;
algo = c;
memset (&zs, 0, sizeof zs);
inbufsize = 2048;
inbuf = m_alloc (inbufsize);
outbufsize = 8192;
outbuf = m_alloc (outbufsize);
zs.avail_in = 0;
zinit_done = 0;
do {
if (zs.avail_in < inbufsize) {
n = zs.avail_in;
if (!n)
zs.next_in = (Bytef *) inbuf;
count = inbufsize - n;
for (nread=0;
nread < count && (c=getc (fpin)) != EOF;
nread++) {
inbuf[n+nread] = c;
}
n += nread;
if (nread < count && algo == 1) {
inbuf[n] = 0xFF; /* chew dummy byte */
n++;
}
zs.avail_in = n;
}
zs.next_out = (Bytef *) outbuf;
zs.avail_out = outbufsize;
if (!zinit_done) {
zrc = algo == 1? inflateInit2 ( &zs, -13)
: inflateInit ( &zs );
if (zrc != Z_OK) {
log_fatal ("zlib problem: %s\n", zs.msg? zs.msg :
zrc == Z_MEM_ERROR ? "out of core" :
zrc == Z_VERSION_ERROR ?
"invalid lib version" :
"unknown error" );
}
zinit_done = 1;
}
else {
#ifdef Z_SYNC_FLUSH
zrc = inflate (&zs, Z_SYNC_FLUSH);
#else
zrc = inflate (&zs, Z_PARTIAL_FLUSH);
#endif
if (zrc == Z_STREAM_END)
; /* eof */
else if (zrc != Z_OK && zrc != Z_BUF_ERROR) {
if (zs.msg)
log_fatal ("zlib inflate problem: %s\n", zs.msg );
else
log_fatal ("zlib inflate problem: rc=%d\n", zrc );
}
for (n=0; n < outbufsize - zs.avail_out; n++) {
if (putc (outbuf[n], fpout) == EOF )
goto write_error;
}
}
} while (zrc != Z_STREAM_END && zrc != Z_BUF_ERROR);
inflateEnd (&zs);
}
else {
while ( (c=getc (fpin)) != EOF ) {
if ( putc (c, fpout) == EOF )
goto write_error;
}
}
if (!feof (fpin))
goto read_error;
}
}
for (p=hdr; hdrlen; p++, hdrlen--) {
if ( putc (*p, fpout) == EOF )
goto write_error;
}
/* standard packet or last segment of partial length encoded packet */
for (; pktlen; pktlen--) {
c = getc (fpin);
if (c == EOF)
goto read_error;
if ( putc (c, fpout) == EOF )
goto write_error;
}
if ( fclose (fpout) )
log_error ("error closing `%s': %s\n", outname, strerror (errno));
return 0;
write_error:
log_error ("error writing `%s': %s\n", outname, strerror (errno));
fclose (fpout);
return 2;
read_error: {
int save = errno;
fclose (fpout);
errno = save;
}
return -1;
}
static int
do_split (const char *fname, FILE *fp)
{
int c, ctb, pkttype;
unsigned long pktlen = 0;
int partial = 0;
unsigned char header[20];
int header_idx = 0;
ctb = getc (fp);
if (ctb == EOF)
return 3; /* ready */
header[header_idx++] = ctb;
if( !(ctb & 0x80) ) {
log_error("invalid CTB %02x\n", ctb );
return 1;
}
if ( (ctb & 0x40) ) { /* new CTB */
pkttype = (ctb & 0x3f);
if( (c = getc (fp)) == EOF )
return -1;
header[header_idx++] = c;
if( c < 192 )
pktlen = c;
else if( c < 224 ) {
pktlen = (c - 192) * 256;
if( (c = getc (fp)) == EOF )
return -1;
header[header_idx++] = c;
pktlen += c + 192;
}
else if( c == 255 ) {
if (read_u32 (fp, &pktlen))
return -1;
header[header_idx++] = pktlen >> 24;
header[header_idx++] = pktlen >> 16;
header[header_idx++] = pktlen >> 8;
header[header_idx++] = pktlen;
}
else { /* partial body length */
pktlen = c;
partial = 1;
}
}
else {
int lenbytes;
pkttype = (ctb>>2)&0xf;
lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
if( !lenbytes ) {
pktlen = 0; /* don't know the value */
if( pkttype == PKT_COMPRESSED )
partial = 3;
else
partial = 2; /* the old GnuPG partial length encoding */
}
else {
for( ; lenbytes; lenbytes-- ) {
pktlen <<= 8;
if( (c = getc (fp)) == EOF )
return -1;
header[header_idx++] = c;
pktlen |= c;
}
}
}
return write_part (fname, fp, pktlen, pkttype, partial,
header, header_idx);
}
static void
split_packets (const char *fname)
{
FILE *fp;
int rc;
if (!fname || !strcmp (fname, "-")) {
fp = stdin;
fname = "-";
}
else if ( !(fp = fopen (fname,"rb")) ) {
log_error ("can't open `%s': %s\n", fname, strerror (errno));
return;
}
while ( !(rc = do_split (fname, fp)) )
;
if ( rc > 0 )
; /* error already handled */
else if ( ferror (fp) )
log_error ("error reading `%s': %s\n", fname, strerror (errno));
else
log_error ("premature EOF while reading `%s'\n", fname );
if ( fp != stdin )
fclose (fp);
}

View file

@ -1,23 +0,0 @@
#!/bin/sh
# lspgpot - script to extract the ownertrust values
# from PGP keyrings and list them in GnuPG ownertrust format.
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
../g10/gpg --dry-run --with-fingerprint --with-colons $* | awk '
BEGIN { FS=":"
printf "# Ownertrust listing generated by lspgpot\n"
printf "# This can be imported using the command:\n"
printf "# ggp --import-ownertrust\n\n" }
$1 == "fpr" { fpr = $10 }
$1 == "rtv" && $2 == 1 && $3 == 2 { printf "%s:3:\n", fpr; next }
$1 == "rtv" && $2 == 1 && $3 == 5 { printf "%s:4:\n", fpr; next }
$1 == "rtv" && $2 == 1 && $3 == 6 { printf "%s:5:\n", fpr; next }
'

View file

@ -1,114 +0,0 @@
#!/bin/sh
# Copyright (C) 2000, 2001 Free Software Foundation, Inc.
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# FIXME: Add --dry-run, use only valid email addreses, extract only given keys
dryrun=0
if [ "$1" = "--dry-run" ]; then
dryrun=1
shift
fi
if [ -z "$1" -o -z "$2" -o -z "$3" ]; then
echo "usage: mail-signed-keys keyring signedby signame" >&2
exit 1
fi
signame="$3"
if [ ! -f $1 ]; then
echo "mail-signed-keys: '$1': no such file" >&2
exit 1
fi
[ -f '.#tdb.tmp' ] && rm '.#tdb.tmp'
ro="--homedir . --no-options --trustdb-name=./.#tdb.tmp --dry-run --lock-never --no-default-keyring --keyring $1"
signedby=`gpg $ro --list-keys --with-colons $2 \
2>/dev/null | awk -F: '$1=="pub" {print $5; exit 0}'`
if [ -z "$signedby" ]; then
echo "mail-signed-keys: '$2': no such signator" >&2
exit 1
fi
if [ "$dryrun" = "0" ]; then
echo "About to send the the keys signed by $signedby" >&2
echo -n "to their owners. Do you really want to do this? (y/N)" >&2
read
[ "$REPLY" != "y" -a "$REPLY" != "Y" ] && exit 0
fi
gpg $ro --check-sigs --with-colons 2>/dev/null \
| awk -F: -v signedby="$signedby" -v gpgopt="$ro" \
-v dryrun="$dryrun" -v signame="$signame" '
BEGIN { sendmail="/usr/lib/sendmail -oi -t " }
$1 == "pub" { nextkid=$5; nextuid=$10
if( uidcount > 0 ) { myflush() }
kid=nextkid; uid=nextuid; next
}
$1 == "uid" { uid=$10 ; next }
$1 == "sig" && $2 == "!" && $5 == signedby { uids[uidcount++] = uid; next }
END { if( uidcount > 0 ) { myflush() } }
function myflush()
{
if ( kid == signedby ) { uidcount=0; return }
print "sending key " substr(kid,9) " to" | "cat >&2"
for(i=0; i < 1; i++ ) {
print " " uids[i] | "cat >&2"
if( dryrun == 0 ) {
if( i == 0 ) {
printf "To: %s", uids[i] | sendmail
}
else {
printf ",\n %s", uids[i] | sendmail
}
}
}
if(dryrun == 0) {
printf "\n" | sendmail
print "Subject: I signed your key " substr(kid,9) | sendmail
print "" | sendmail
print "Hi," | sendmail
print "" | sendmail
print "Here you get back the signed key." | sendmail
print "Please send it yourself to a keyserver." | sendmail
print "" | sendmail
print "Peace," | sendmail
print " " signame | sendmail
print "" | sendmail
cmd = "gpg " gpgopt " --export -a " kid " 2>/dev/null"
while( (cmd | getline) > 0 ) {
print | sendmail
}
print "" | sendmail
close(cmd)
close( sendmail )
}
uidcount=0
}
'

View file

@ -1,43 +0,0 @@
/* mk-tdata.c - Create some simple random testdata
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is free software; as a special exception the author gives
* unlimited permission to copy and/or distribute it, with or without
* modifications, as long as this notice is preserved.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef RAND_MAX /* for SunOS */
#define RAND_MAX 32767
#endif
int
main(int argc, char **argv)
{
int i, c;
int limit =0;
limit = argc > 1 ? atoi(argv[1]) : 0;
srand(getpid());
for(i=0; !limit || i < limit; i++ ) {
#ifdef HAVE_RAND
c = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
#else
c = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
#endif
putchar(c);
}
return 0;
}

View file

@ -1,390 +0,0 @@
/* mpitest.c - test the mpi functions
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This is an RPN calculator; values must be given in hex.
* Operation is like dc(1) except that the input/output radix is
* always 16 and you can use a '-' to prefix a negative number.
* Addition operators: ++ and --. All operators must be delimited by a blank
*
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "util.h"
#include "mpi.h"
#include "i18n.h"
#define STACKSIZE 100
static MPI stack[STACKSIZE];
static int stackidx;
const char *
strusage( int level )
{
const char *p;
switch( level ) {
case 10:
case 0: p = "mpicalc - v" VERSION "; "
"Copyright 1997 Werner Koch (dd9jn)" ; break;
case 13: p = "mpicalc"; break;
case 14: p = VERSION; break;
case 1:
case 11: p = "Usage: mpicalc (-h for help)";
break;
case 2:
case 12: p =
"\nSyntax: mpicalc [options] [files]\n"
"MPI RPN calculator\n";
break;
default: p = default_strusage(level);
}
return p;
}
static void
i18n_init(void)
{
#ifdef ENABLE_NLS
#ifdef HAVE_LC_MESSAGES
setlocale( LC_MESSAGES, "" );
#else
setlocale( LC_ALL, "" );
#endif
bindtextdomain( PACKAGE, G10_LOCALEDIR );
textdomain( PACKAGE );
#endif
}
static void
do_add(void)
{
if( stackidx < 2 ) {
fputs("stack underflow\n",stderr);
return;
}
mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
stackidx--;
}
static void
do_sub(void)
{
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
stackidx--;
}
static void
do_inc(void)
{
if( stackidx < 1 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_add_ui( stack[stackidx-1], stack[stackidx-1], 1 );
}
static void
do_dec(void)
{
if( stackidx < 1 ) {
fputs("stack underflow\n", stderr);
return;
}
/* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */
}
static void
do_mul(void)
{
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_mul( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
stackidx--;
}
static void
do_mulm(void)
{
if( stackidx < 3 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_mulm( stack[stackidx-3], stack[stackidx-3],
stack[stackidx-2], stack[stackidx-1] );
stackidx -= 2;
}
static void
do_div(void)
{
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_fdiv_q( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
stackidx--;
}
static void
do_rem(void)
{
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_fdiv_r( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
stackidx--;
}
static void
do_powm(void)
{
MPI a;
if( stackidx < 3 ) {
fputs("stack underflow\n", stderr);
return;
}
a= mpi_alloc(10);
mpi_powm( a, stack[stackidx-3], stack[stackidx-2], stack[stackidx-1] );
mpi_free(stack[stackidx-3]);
stack[stackidx-3] = a;
stackidx -= 2;
}
static void
do_inv(void)
{
MPI a = mpi_alloc(40);
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_invm( a, stack[stackidx-2], stack[stackidx-1] );
mpi_set(stack[stackidx-2],a);
mpi_free(a);
stackidx--;
}
static void
do_gcd(void)
{
MPI a = mpi_alloc(40);
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_gcd( a, stack[stackidx-2], stack[stackidx-1] );
mpi_set(stack[stackidx-2],a);
mpi_free(a);
stackidx--;
}
static void
do_rshift(void)
{
if( stackidx < 1 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 );
}
int
main(int argc, char **argv)
{
static ARGPARSE_OPTS opts[] = {
{0} };
ARGPARSE_ARGS pargs;
int i, c;
int state = 0;
char strbuf[1000];
int stridx=0;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags = 0;
i18n_init();
while( arg_parse( &pargs, opts) ) {
switch( pargs.r_opt ) {
default : pargs.err = 2; break;
}
}
if( argc )
usage(1);
for(i=0; i < STACKSIZE; i++ )
stack[i] = NULL;
stackidx =0;
while( (c=getc(stdin)) != EOF ) {
if( !state ) { /* waiting */
if( isdigit(c) ) {
state = 1;
ungetc(c, stdin);
strbuf[0] = '0';
strbuf[1] = 'x';
stridx=2;
}
else if( isspace(c) )
;
else {
switch(c) {
case '+':
if( (c=getc(stdin)) == '+' )
do_inc();
else {
ungetc(c, stdin);
do_add();
}
break;
case '-':
if( (c=getc(stdin)) == '-' )
do_dec();
else if( isdigit(c) || (c >='A' && c <= 'F') ) {
state = 1;
ungetc(c, stdin);
strbuf[0] = '-';
strbuf[1] = '0';
strbuf[2] = 'x';
stridx=3;
}
else {
ungetc(c, stdin);
do_sub();
}
break;
case '*':
do_mul();
break;
case 'm':
do_mulm();
break;
case '/':
do_div();
break;
case '%':
do_rem();
break;
case '^':
do_powm();
break;
case 'I':
do_inv();
break;
case 'G':
do_gcd();
break;
case '>':
do_rshift();
break;
case 'i': /* dummy */
if( !stackidx )
fputs("stack underflow\n", stderr);
else {
mpi_free(stack[stackidx-1]);
stackidx--;
}
break;
case 'd': /* duplicate the tos */
if( !stackidx )
fputs("stack underflow\n", stderr);
else if( stackidx < STACKSIZE ) {
mpi_free(stack[stackidx]);
stack[stackidx] = mpi_copy( stack[stackidx-1] );
stackidx++;
}
else
fputs("stack overflow\n", stderr);
break;
case 'c':
for(i=0; i < stackidx; i++ )
mpi_free(stack[i]), stack[i] = NULL;
stackidx = 0;
break;
case 'p': /* print the tos */
if( !stackidx )
puts("stack is empty");
else {
mpi_print(stdout, stack[stackidx-1], 1 );
putchar('\n');
}
break;
case 'f': /* print the stack */
for( i = stackidx-1 ; i >= 0; i-- ) {
printf("[%2d]: ", i );
mpi_print(stdout, stack[i], 1 );
putchar('\n');
}
break;
default:
fputs("invalid operator\n", stderr);
}
}
}
else if( state == 1 ) { /* in a number */
if( !isxdigit(c) ) { /* store the number */
state = 0;
ungetc(c, stdin);
if( stridx < 1000 )
strbuf[stridx] = 0;
if( stackidx < STACKSIZE ) {
if( !stack[stackidx] )
stack[stackidx] = mpi_alloc(10);
if( mpi_fromstr(stack[stackidx], strbuf) )
fputs("invalid number\n", stderr);
else
stackidx++;
}
else
fputs("stack overflow\n", stderr);
}
else { /* store digit */
if( stridx < 999 )
strbuf[stridx++] = c;
else if( stridx == 999 ) {
strbuf[stridx] = 0;
fputs("string too large - truncated\n", stderr);
stridx++;
}
}
}
}
for(i=0; i < stackidx; i++ )
mpi_free(stack[i]);
return 0;
}

View file

@ -1,118 +0,0 @@
#!/bin/sh
# ring-a-party - print a keyring suitable for a key signing party
# Copyright (C) 2000, 2001 Free Software Foundation, Inc.
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
if [ $# -lt 1 ]; then
echo "usage: ring-a-party keyring [headerline]" >&2
exit 1
fi
keyring="$1"
hdrline="$1"
if [ $# -gt 1 ]; then
hdrline="$2"
fi
if [ ! -f $keyring ]; then
echo "ring-a-party: '$keyring': no such file" >&2
exit 1
fi
echo "ring-a-party: output will be written to 'a.pub'" >&2
gpg --dry-run --with-fingerprint --with-colons $keyring \
| gawk -v "KEYRING=$hdrline" '
BEGIN { FS=":"
algos[1] = "RSA";
algos[16] = "ElGamal";
algos[17] = "DSA";
any = 0;
lines = -1;
page = 0;
now = strftime("%b %d %H:%M %Y");
}
END {
if (any) myflush();
}
$1 == "pub" {
if( any ) myflush();
uidcount = 0;
signencrypt = 0;
uids[uidcount++] = $10;
nbits = $3;
keyid = substr($5,9);
created = $6;
expires = $7;
algostr = mapalgo($4);
if( $4 == 20 || $4 == 1 ) signencrypt = 1;
any = 1;
}
$1 == "fpr" { fpr = $10 }
$1 == "uid" { uids[uidcount++] = $10 }
$1 == "sub" { if( $4 != 17 && $4 != 3 ) signencrypt=1 }
function myflush()
{
# fixme: take lines to print here into account
if( lines > 45 || lines == -1 ) {
if( lines != -1 ) printf "\f";
page++;
printf "%s %-50.50s Page %d\n\n", now, KEYRING, page ;
printf " Type Bits KeyID Created Expires Algorithm Use\n\n";
lines = 1;
}
printf "[ ] pub %04d 0x%s %10s %10s %-10s %15s\n",
nbits, keyid, created, expires == ""? "----------":expires, algostr,
signencrypt == 1? "Sign & Encrypt":"Sign only";
length(fpr) == 40 ? printfpr20( fpr ) : printfpr16( fpr );
lnes += 2;
for( i=0; i < uidcount; i++ ) {
printf "( ) uid %s\n", uids[i];
lines++;
}
printf "\n\n";
lines += 2;
}
function mapalgo( no )
{
if( no in algos )
return algos[no];
return sprintf( "algoID=%ds", no );
}
function printfpr16( s )
{
printf " f16 Fingerprint16 =";
for(i=0; i < 16; i++ ) {
if( i == 8 ) printf " ";
printf " %s", substr( s, i*2+1, 2 );
}
printf "\n"
}
function printfpr20( s )
{
printf " f20 Fingerprint20 =";
for(i=0; i < 10; i++ ) {
if( i == 5 ) printf " ";
printf " %s", substr( s, i*4+1, 4 );
}
printf "\n"
}
' | tee a.pub | gpg --print-mds

View file

@ -1,206 +0,0 @@
/* shmtest.c
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
* This file is free software; as a special exception the author gives
* unlimited permission to copy and/or distribute it, with or without
* modifications, as long as this notice is preserved.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#ifdef HAVE_SYS_IPC_H
#include <sys/types.h>
#include <sys/ipc.h>
#endif
#ifdef HAVE_SYS_SHM_H
#include <sys/shm.h>
#endif
#include "util.h"
#include "ttyio.h"
#include "i18n.h"
#ifdef HAVE_DOSISH_SYSTEM
int main( int argc, char **argv )
{
fprintf(stderr, "Sorry, not yet available for DOSish systems\n");
exit(1);
}
#else
static int serverpid = -1;
static void
my_usage(void)
{
fprintf(stderr, "usage: shmtest gpg-command-line\n");
exit(1);
}
const char *
strusage( int level )
{
return default_strusage(level);
}
static void
i18n_init(void)
{
#ifdef ENABLE_NLS
#ifdef HAVE_LC_MESSAGES
setlocale( LC_MESSAGES, "" );
#else
setlocale( LC_ALL, "" );
#endif
bindtextdomain( PACKAGE, G10_LOCALEDIR );
textdomain( PACKAGE );
#endif
}
static void
do_get_string( int mode, const char *keyword, byte *area, size_t areasize )
{
size_t n, len;
char *p=NULL;
int yes=0;
n = area[0] << 8 | area[1];
/* fixme: do some sanity checks here */
if( mode == 1 )
p = tty_get( keyword );
else if( mode == 3 )
p = tty_get_hidden( keyword );
else
yes = tty_get_answer_is_yes( keyword );
if( p ) {
len = strlen(p);
memcpy( area+n+2, p, len );
area[n] = len >> 8;
area[n+1] = len;
m_free(p);
}
else { /* bool */
area[n] = 0;
area[n+1] = 1;
area[n+2] = yes;
}
area[3] = 1; /* we should better use a semaphore */
kill( serverpid, SIGUSR1 );
}
int
main(int argc, char **argv)
{
void *area = NULL;
size_t areasize = 4096;
int shm_id = -1;
FILE *fp;
char buf[200];
char *p, *p2;
size_t n;
int i;
log_set_name("shmtest");
i18n_init();
#ifndef USE_SHM_COPROCESSING
log_info("SHM_COPRPOCESSING is not available\n");
#else
if( argc < 1 )
my_usage();
for(n=0,i=1; i < argc; i++ )
n += strlen(argv[i]) + 1;
p = m_alloc( 100 + n );
strcpy( p, "../g10/gpg --status-fd 1 --run-as-shm-coprocess 0");
for(i=1; i < argc; i++ ) {
strcat(p, " " );
strcat(p, argv[i] );
}
fp = popen( p, "r" );
m_free( p );
if( !fp )
log_error("popen failed: %s\n", strerror(errno));
while ( fgets (buf, sizeof (buf) - 1, fp ) != NULL ) {
size_t len = strlen(buf);
if( len >= 9 && !memcmp( buf, "[GNUPG:] ", 9 ) ) {
int word=0;
int is_info = 0, is_get = 0;
for( p = strtok(buf+9, " \n"); p ; p = strtok(NULL, " \n")) {
word++;
if( word==1 && !strcmp(p,"SHM_INFO") ) {
if( !area )
is_info=1;
else
log_error("duplicate SHM_INFO ignored\n" );
}
else if( is_info && (p2 = strchr(p, '=' )) ) {
int val;
*p2++ = 0;
val = atoi(p2); /* should be atou() for some values */
if( !strcmp(p, "pv" ) ) {
if( atoi(p2) != 1 )
log_fatal("invalid protocol version %d\n", val );
is_info = 2;
}
else if( !strcmp(p, "pid" ) )
serverpid = val;
else if( !strcmp(p, "shmid" ) )
shm_id = val;
}
else if( word == 1 && !strcmp(p,"SHM_GET") )
is_get = 1;
else if( word == 1 && !strcmp(p,"SHM_GET_BOOL") )
is_get = 2;
else if( word == 1 && !strcmp(p,"SHM_GET_HIDDEN") )
is_get = 3;
else if( word == 2 && is_get ) {
do_get_string( is_get, p, area, areasize );
break;
}
else if( word == 1 )
log_info("Status: %s\n", p);
}
if( is_info ) {
if( is_info < 2 )
log_fatal("SHM info without protocol version\n");
if( serverpid == -1 )
log_fatal("SHM info without server's pid\n");
if( shm_id == -1 )
log_fatal("SHM info without id\n");
log_info("Shared memory info: server=%d shm_id=%d\n",
serverpid, shm_id);
area = shmat( shm_id, 0, 0 );
if( area == (void*)-1 )
log_fatal("attach to shared memory failed: %s\n",
strerror(errno));
}
}
else
fputs (buf, stdout);
}
if( pclose(fp) )
log_error("pclose failed\n");
return 0;
#endif
}
#endif

View file

@ -1,33 +0,0 @@
#!/bin/sh
if [ ! -f ./$1 ]; then
echo "usage: signmany keyring" >&2
exit 1
fi
ro="--trustdb-name=./tdb.tmp --no-default-keyring --secret-keyring /floppy/secring.gpg --keyring ./$1"
kis=`gpg $ro --fast-list-mode --list-keys --with-colons \
| awk -F: '$1=="pub" { print $5 }'`
for k in $kis; do
echo "Keyid: $k"
answer=A
while [ "$answer" = "A" ]; do
gpg $ro --lock-never --sign-key $k
answer=""
while [ "$answer" = "" ]; do
read -p 'Okay, Again or Quit? (O/A/Q) '
case "$REPLY" in
o|O) answer=O ;;
a|A) answer=A ;;
q|Q) answer=Q ;;
*) ;;
esac
done
done
[ "$answer" = "Q" ] && break
done