(Does not compile yet)
[gnupg.git] / g10 / g10.c
1 /* g10.c - The GnuPG utility (main for gpg)
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GNUPG.
5  *
6  * GNUPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GNUPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 /* #define MAINTAINER_OPTIONS */
29
30 #include "packet.h"
31 #include "iobuf.h"
32 #include "memory.h"
33 #include "util.h"
34 #include "main.h"
35 #include "options.h"
36 #include "keydb.h"
37 #include "mpi.h"
38 #include "cipher.h"
39 #include "filter.h"
40 #include "trustdb.h"
41 #include "ttyio.h"
42 #include "i18n.h"
43 #include "status.h"
44 #include "g10defs.h"
45
46 #ifndef IS_G10MAINT
47   #define IS_G10 1
48 #endif
49
50
51 enum cmd_and_opt_values { aNull = 0,
52     oArmor        = 'a',
53     aDetachedSign = 'b',
54     aSym          = 'c',
55     aDecrypt      = 'd',
56     aEncr         = 'e',
57     oKOption      = 'k',
58     oDryRun       = 'n',
59     oOutput       = 'o',
60     oQuiet        = 'q',
61     oRemote       = 'r',
62     aSign         = 's',
63     oTextmodeShort= 't',
64     oUser         = 'u',
65     oVerbose      = 'v',
66     oCompress     = 'z',
67     oBatch        = 500,
68     aClearsign,
69     aStore,
70     aKeygen,
71     aSignEncr,
72     aSignKey,
73     aListPackets,
74     aEditKey,
75     aDeleteKey,
76     aDeleteSecretKey,
77     aKMode,
78     aKModeC,
79     aImport,
80     aFastImport,
81     aVerify,
82     aListKeys,
83     aListSigs,
84     aListSecretKeys,
85     aExport,
86     aExportSecret,
87     aCheckKeys,
88     aGenRevoke,
89     aPrimegen,
90     aPrintMD,
91     aPrintMDs,
92     aCheckTrustDB,
93     aUpdateTrustDB,
94     aFixTrustDB,
95     aListTrustDB,
96     aListTrustPath,
97     aExportOwnerTrust,
98     aImportOwnerTrust,
99     aDeArmor,
100     aEnArmor,
101     aGenRandom,
102
103     oTextmode,
104     oFingerprint,
105     oAnswerYes,
106     oAnswerNo,
107     oKeyring,
108     oSecretKeyring,
109     oDefaultKey,
110     oOptions,
111     oDebug,
112     oDebugAll,
113     oStatusFD,
114     oNoComment,
115     oCompletesNeeded,
116     oMarginalsNeeded,
117     oLoadExtension,
118     oRFC1991,
119     oCipherAlgo,
120     oDigestAlgo,
121     oCompressAlgo,
122     oPasswdFD,
123     oQuickRandom,
124     oNoVerbose,
125     oTrustDBName,
126     oNoSecmemWarn,
127     oNoArmor,
128     oNoDefKeyring,
129     oNoGreeting,
130     oNoOptions,
131     oNoBatch,
132     oHomedir,
133     oWithColons,
134     oSkipVerify,
135     oCompressKeys,
136     oCompressSigs,
137     oAlwaysTrust,
138     oEmuChecksumBug,
139     oRunAsShmCP,
140     oSetFilename,
141     oComment,
142     oThrowKeyid,
143     oForceV3Sigs,
144     oS2KMode,
145     oS2KDigest,
146     oS2KCipher,
147 aTest };
148
149
150 static ARGPARSE_OPTS opts[] = {
151
152     { 300, NULL, 0, N_("@Commands:\n ") },
153
154   #ifdef IS_G10
155     { aSign, "sign",      256, N_("|[file]|make a signature")},
156     { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") },
157     { aDetachedSign, "detach-sign", 256, N_("make a detached signature")},
158     { aEncr, "encrypt",   256, N_("encrypt data")},
159     { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")},
160     { aStore, "store",     256, N_("store only")},
161     { aDecrypt, "decrypt",   256, N_("decrypt data (default)")},
162     { aVerify, "verify"   , 256, N_("verify a signature")},
163   #endif
164     { aListKeys, "list-keys", 256, N_("list keys")},
165     { aListSigs, "list-sigs", 256, N_("list keys and signatures")},
166     { aCheckKeys, "check-sigs",256, N_("check key signatures")},
167     { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
168     { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
169   #ifdef IS_G10
170     { aKeygen, "gen-key",   256, N_("generate a new key pair")},
171   #endif
172     { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
173   #ifdef IS_G10
174     { aEditKey, "edit-key"  ,256, N_("sign or edit a key")},
175     { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")},
176   #endif
177     { aExport, "export"          , 256, N_("export keys") },
178     { aExportSecret, "export-secret-keys" , 256, "@" },
179     { aImport, "import",      256     , N_("import/merge keys")},
180     { aFastImport, "fast-import",  256 , "@"},
181     { aListPackets, "list-packets",256,N_("list only the sequence of packets")},
182   #ifdef IS_G10MAINT
183     { aExportOwnerTrust,
184               "export-ownertrust", 256, N_("export the ownertrust values")},
185     { aImportOwnerTrust,
186               "import-ownertrust", 256 , N_("import ownertrust values")},
187     { aUpdateTrustDB,
188               "update-trustdb",0 , N_("|[NAMES]|update the trust database")},
189     { aCheckTrustDB,
190               "check-trustdb",0 , N_("|[NAMES]|check the trust database")},
191     { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")},
192     { aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") },
193     { aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") },
194     { aPrintMD,  "print-md" , 256, N_("|algo [files]|print message digests")},
195     { aPrintMDs, "print-mds" , 256, N_("print all message digests")},
196     #ifdef MAINTAINER_OPTIONS
197     { aPrimegen, "gen-prime" , 256, "@" },
198     { aGenRandom, "gen-random" , 256, "@" },
199     #endif
200   #endif
201
202     { 301, NULL, 0, N_("@\nOptions:\n ") },
203
204     { oArmor, "armor",     0, N_("create ascii armored output")},
205   #ifdef IS_G10
206     { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
207     { oRemote, "remote-user", 2, N_("use this user-id for encryption")},
208     { oCompress, NULL,        1, N_("|N|set compress level N (0 disables)") },
209     { oTextmodeShort, NULL,   0, "@"},
210     { oTextmode, "textmode",  0, N_("use canonical text mode")},
211   #endif
212     { oOutput, "output",    2, N_("use as output file")},
213     { oVerbose, "verbose",   0, N_("verbose") },
214     { oQuiet,   "quiet",   0, N_("be somewhat more quiet") },
215     { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") },
216  /* { oDryRun, "dry-run",   0, N_("do not make any changes") }, */
217     { oBatch, "batch",     0, N_("batch mode: never ask")},
218     { oAnswerYes, "yes",       0, N_("assume yes on most questions")},
219     { oAnswerNo,  "no",        0, N_("assume no on most questions")},
220     { oKeyring, "keyring"   ,2, N_("add this keyring to the list of keyrings")},
221     { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
222     { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
223     { oOptions, "options"   , 2, N_("read options from file")},
224
225     { oDebug, "debug"     ,4|16, N_("set debugging flags")},
226     { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
227     { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
228     { oNoComment, "no-comment", 0,   N_("do not write comment packets")},
229     { oCompletesNeeded, "completes-needed", 1, N_("(default is 1)")},
230     { oMarginalsNeeded, "marginals-needed", 1, N_("(default is 3)")},
231     { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
232     { oRFC1991, "rfc1991",   0, N_("emulate the mode described in RFC1991")},
233     { oS2KMode, "s2k-mode",  1, N_("|N|use passphrase mode N")},
234     { oS2KDigest, "s2k-digest-algo",2,
235                 N_("|NAME|use message digest algorithm NAME for passphrases")},
236     { oS2KCipher, "s2k-cipher-algo",2,
237                 N_("|NAME|use cipher algorithm NAME for passphrases")},
238   #ifdef IS_G10
239     { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
240     { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
241     { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
242     { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
243   #else /* some dummies */
244     { oCipherAlgo, "cipher-algo", 2 , "@"},
245     { oDigestAlgo, "digest-algo", 2 , "@"},
246     { oCompressAlgo, "compress-algo", 1 , "@"},
247   #endif
248
249   #ifdef IS_G10
250     { 302, NULL, 0, N_("@\nExamples:\n\n"
251     " -se -r Bob [file]          sign and encrypt for user Bob\n"
252     " --clearsign [file]         make a clear text signature\n"
253     " --detach-sign [file]       make a detached signature\n"
254     " --list-keys [names]        show keys\n"
255     " --fingerprint [names]      show fingerprints\n"  ) },
256   #endif
257
258   /* hidden options */
259   #ifdef IS_G10MAINT
260     { aTest, "test"      , 0, "@" },
261     { aExportOwnerTrust, "list-ownertrust",0 , "@"},  /* alias */
262     { aListTrustDB, "list-trustdb",0 , "@"},
263     { aListTrustPath, "list-trust-path",0, "@"},
264   #endif
265   #ifdef IS_G10
266     { oKOption, NULL,    0, "@"},
267     { aEditKey, "edit-sig"  ,0, "@"}, /* alias for edit-key */
268     { oPasswdFD, "passphrase-fd",1, "@" },
269     { aSignKey, "sign-key"  ,256, "@" }, /* alias for edit-key */
270   #endif
271     { aDeleteSecretKey, "delete-secret-key",0, "@" },
272     { oQuickRandom, "quick-random", 0, "@"},
273     { oNoVerbose, "no-verbose", 0, "@"},
274     { oTrustDBName, "trustdb-name", 2, "@" },
275     { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */
276     { oNoArmor, "no-armor",   0, "@"},
277     { oNoDefKeyring, "no-default-keyring", 0, "@" },
278     { oNoGreeting, "no-greeting", 0, "@" },
279     { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */
280     { oHomedir, "homedir", 2, "@" },   /* defaults to "~/.gnupg" */
281     { oNoBatch, "no-batch", 0, "@" },
282     { oWithColons, "with-colons", 0, "@"},
283     { aListKeys, "list-key", 0, "@" }, /* alias */
284     { aListSigs, "list-sig", 0, "@" }, /* alias */
285     { aCheckKeys, "check-sig",0, "@" }, /* alias */
286     { oSkipVerify, "skip-verify",0, "@" },
287     { oCompressKeys, "compress-keys",0, "@"},
288     { oCompressSigs, "compress-sigs",0, "@"},
289     { oAlwaysTrust, "always-trust", 0, "@"},
290     { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"},
291     { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
292     { oSetFilename, "set-filename", 2, "@" },
293     { oComment, "comment", 2, "@" },
294 {0} };
295
296
297
298 static int maybe_setuid = 1;
299
300 static char *build_list( const char *text,
301                          const char *(*mapf)(int), int (*chkf)(int) );
302 static void set_cmd( enum cmd_and_opt_values *ret_cmd,
303                         enum cmd_and_opt_values new_cmd );
304 #ifdef IS_G10MAINT
305 static void print_hex( byte *p, size_t n );
306 static void print_mds( const char *fname, int algo );
307 #endif
308
309 const char *
310 strusage( int level )
311 {
312   static char *digests, *pubkeys, *ciphers;
313     const char *p;
314     switch( level ) {
315       case 11: p =
316           #ifdef IS_G10MAINT
317             "gpgm (GnuPG)";
318           #else
319             "gpg (GnuPG)";
320           #endif
321         break;
322       case 13: p = VERSION; break;
323       case 17: p = PRINTABLE_OS_NAME; break;
324       case 19: p =
325             _("Please report bugs to <gnupg-bugs@gnu.org>.\n");
326         break;
327       case 1:
328       case 40:  p =
329           #ifdef IS_G10MAINT
330             _("Usage: gpgm [options] [files] (-h for help)");
331           #else
332             _("Usage: gpg [options] [files] (-h for help)");
333           #endif
334         break;
335       case 41:  p =
336           #ifdef IS_G10MAINT
337             _("Syntax: gpgm [options] [files]\n"
338               "GnuPG maintenance utility\n");
339           #else
340             _("Syntax: gpg [options] [files]\n"
341               "sign, check, encrypt or decrypt\n"
342               "default operation depends on the input data\n");
343           #endif
344         break;
345
346       case 31: p = _("\nSupported algorithms:\n"); break;
347       case 32:
348         if( !ciphers )
349             ciphers = build_list("Cipher: ", cipher_algo_to_string,
350                                                         check_cipher_algo );
351         p = ciphers;
352         break;
353       case 33:
354         if( !pubkeys )
355             pubkeys = build_list("Pubkey: ", pubkey_algo_to_string,
356                                                         check_pubkey_algo );
357         p = pubkeys;
358         break;
359       case 34:
360         if( !digests )
361             digests = build_list("Hash: ", digest_algo_to_string,
362                                                         check_digest_algo );
363         p = digests;
364         break;
365
366       default:  p = default_strusage(level);
367     }
368     return p;
369 }
370
371
372 static char *
373 build_list( const char *text, const char * (*mapf)(int), int (*chkf)(int) )
374 {
375     int i;
376     const char *s;
377     size_t n=strlen(text)+2;
378     char *list, *p;
379
380     if( maybe_setuid )
381         secmem_init( 0 );    /* drop setuid */
382
383     for(i=1; i < 110; i++ )
384         if( !chkf(i) && (s=mapf(i)) )
385             n += strlen(s) + 2;
386     list = m_alloc( 21 + n ); *list = 0;
387     for(p=NULL, i=1; i < 110; i++ ) {
388         if( !chkf(i) && (s=mapf(i)) ) {
389             if( !p )
390                 p = stpcpy( list, text );
391             else
392                 p = stpcpy( p, ", ");
393             p = stpcpy(p, s );
394         }
395     }
396     if( p )
397         p = stpcpy(p, "\n" );
398     return list;
399 }
400
401
402 static void
403 i18n_init(void)
404 {
405   #ifdef ENABLE_NLS
406     #ifdef HAVE_LC_MESSAGES
407        setlocale( LC_TIME, "" );
408        setlocale( LC_MESSAGES, "" );
409     #else
410        setlocale( LC_ALL, "" );
411     #endif
412     bindtextdomain( PACKAGE, G10_LOCALEDIR );
413     textdomain( PACKAGE );
414   #endif
415 }
416
417 static void
418 wrong_args( const char *text)
419 {
420   #ifdef IS_G10MAINT
421     fputs(_("usage: gpgm [options] "),stderr);
422   #else
423     fputs(_("usage: gpg [options] "),stderr);
424   #endif
425     fputs(text,stderr);
426     putc('\n',stderr);
427     g10_exit(2);
428 }
429
430 static void
431 set_debug(void)
432 {
433     if( opt.debug & DBG_MEMORY_VALUE )
434         memory_debug_mode = 1;
435     if( opt.debug & DBG_MEMSTAT_VALUE )
436         memory_stat_debug_mode = 1;
437     if( opt.debug & DBG_MPI_VALUE )
438         mpi_debug_mode = 1;
439     if( opt.debug & DBG_CIPHER_VALUE )
440         g10c_debug_mode = 1;
441     if( opt.debug & DBG_IOBUF_VALUE )
442         iobuf_debug_mode = 1;
443
444 }
445
446
447 static void
448 set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd )
449 {
450     enum cmd_and_opt_values cmd = *ret_cmd;
451
452     if( !cmd || cmd == new_cmd )
453         cmd = new_cmd;
454     else if( cmd == aSign && new_cmd == aEncr )
455         cmd = aSignEncr;
456     else if( cmd == aEncr && new_cmd == aSign )
457         cmd = aSignEncr;
458     else if( cmd == aKMode && new_cmd == aSym )
459         cmd = aKModeC;
460     else if(    ( cmd == aSign     && new_cmd == aClearsign )
461              || ( cmd == aClearsign && new_cmd == aSign )  )
462         cmd = aClearsign;
463     else {
464         log_error(_("conflicting commands\n"));
465         g10_exit(2);
466     }
467
468     *ret_cmd = cmd;
469 }
470
471
472
473 int
474 main( int argc, char **argv )
475 {
476     ARGPARSE_ARGS pargs;
477     IOBUF a;
478     int rc=0;
479     int orig_argc;
480     char **orig_argv;
481     const char *fname;
482     STRLIST sl, remusr= NULL, locusr=NULL;
483     STRLIST nrings=NULL, sec_nrings=NULL;
484     armor_filter_context_t afx;
485     int detached_sig = 0;
486     FILE *configfp = NULL;
487     char *configname = NULL;
488     unsigned configlineno;
489     int parse_debug = 0;
490     int default_config =1;
491     int errors=0;
492     int default_keyring = 1;
493     int greeting = 1;
494     enum cmd_and_opt_values cmd = 0;
495     const char *trustdb_name = NULL;
496     char *def_cipher_string = NULL;
497     char *def_digest_string = NULL;
498     char *s2k_cipher_string = NULL;
499     char *s2k_digest_string = NULL;
500     int pwfd = -1;
501   #ifdef USE_SHM_COPROCESSING
502     ulong requested_shm_size=0;
503   #endif
504
505     trap_unaligned();
506     secmem_set_flags( secmem_get_flags() | 2 ); /* suspend warnings */
507   #ifdef IS_G10MAINT
508     secmem_init( 0 );      /* disable use of secmem */
509     maybe_setuid = 0;
510     log_set_name("gpgm");
511   #else
512     /* Please note that we may running SUID(ROOT), so be very CAREFUL
513      * when adding any stuff between here and the call to
514      * secmem_init()  somewhere after the option parsing
515      */
516     log_set_name("gpg");
517     secure_random_alloc(); /* put random number into secure memory */
518     disable_core_dumps();
519   #endif
520     init_signals();
521     i18n_init();
522     opt.compress = -1; /* defaults to standard compress level */
523     /* fixme: set the next two to zero and decide where used */
524     opt.def_cipher_algo = 0;
525     opt.def_digest_algo = 0;
526     opt.def_compress_algo = 2;
527     opt.s2k_mode = 1; /* salted */
528     opt.s2k_digest_algo = DIGEST_ALGO_RMD160;
529     opt.s2k_cipher_algo = CIPHER_ALGO_BLOWFISH;
530     opt.completes_needed = 1;
531     opt.marginals_needed = 3;
532     opt.homedir = getenv("GNUPGHOME");
533     if( !opt.homedir || !*opt.homedir ) {
534       #ifdef __MINGW32__
535         opt.homedir = "c:/gnupg";
536       #else
537         opt.homedir = "~/.gnupg";
538       #endif
539     }
540
541     /* check whether we have a config file on the commandline */
542     orig_argc = argc;
543     orig_argv = argv;
544     pargs.argc = &argc;
545     pargs.argv = &argv;
546     pargs.flags= 1|(1<<6);  /* do not remove the args, ignore version */
547     while( arg_parse( &pargs, opts) ) {
548         if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll )
549             parse_debug++;
550         else if( pargs.r_opt == oOptions ) {
551             /* yes there is one, so we do not try the default one, but
552              * read the option file when it is encountered at the commandline
553              */
554             default_config = 0;
555         }
556         else if( pargs.r_opt == oNoOptions )
557             default_config = 0; /* --no-options */
558         else if( pargs.r_opt == oHomedir )
559             opt.homedir = pargs.r.ret_str;
560       #ifdef USE_SHM_COPROCESSING
561         else if( pargs.r_opt == oRunAsShmCP ) {
562             /* does not make sense in a options file, we do it here,
563              * so that we are the able to drop setuid as soon as possible */
564             opt.shm_coprocess = 1;
565             requested_shm_size = pargs.r.ret_ulong;
566         }
567       #endif
568     }
569
570
571   #ifdef USE_SHM_COPROCESSING
572     if( opt.shm_coprocess ) {
573       #ifdef IS_G10
574         init_shm_coprocessing(requested_shm_size, 1 );
575       #else
576         init_shm_coprocessing(requested_shm_size, 0 );
577       #endif
578     }
579   #endif
580   #ifdef IS_G10
581     /* initialize the secure memory. */
582     secmem_init( 16384 );
583     maybe_setuid = 0;
584     /* Okay, we are now working under our real uid */
585   #endif
586
587     if( default_config )
588         configname = make_filename(opt.homedir, "options", NULL );
589
590     argc = orig_argc;
591     argv = orig_argv;
592     pargs.argc = &argc;
593     pargs.argv = &argv;
594     pargs.flags=  1;  /* do not remove the args */
595   next_pass:
596     if( configname ) {
597         configlineno = 0;
598         configfp = fopen( configname, "r" );
599         if( !configfp ) {
600             if( default_config ) {
601                 if( parse_debug )
602                     log_info(_("note: no default option file '%s'\n"),
603                                                             configname );
604             }
605             else {
606                 log_error(_("option file '%s': %s\n"),
607                                     configname, strerror(errno) );
608                 g10_exit(2);
609             }
610             m_free(configname); configname = NULL;
611         }
612         if( parse_debug && configname )
613             log_info(_("reading options from '%s'\n"), configname );
614         default_config = 0;
615     }
616
617     while( optfile_parse( configfp, configname, &configlineno,
618                                                 &pargs, opts) ) {
619         switch( pargs.r_opt ) {
620           case aCheckKeys: set_cmd( &cmd, aCheckKeys); break;
621           case aListPackets: set_cmd( &cmd, aListPackets); break;
622           case aImport: set_cmd( &cmd, aImport); break;
623           case aFastImport: set_cmd( &cmd, aFastImport); break;
624           case aExport: set_cmd( &cmd, aExport); break;
625           case aListKeys: set_cmd( &cmd, aListKeys); break;
626           case aListSigs: set_cmd( &cmd, aListSigs); break;
627           case aExportSecret: set_cmd( &cmd, aExportSecret); break;
628           case aDeleteSecretKey: set_cmd( &cmd, aDeleteSecretKey); break;
629           case aDeleteKey: set_cmd( &cmd, aDeleteKey); break;
630
631         #ifdef IS_G10
632           case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break;
633           case aSym: set_cmd( &cmd, aSym); break;
634           case aDecrypt: set_cmd( &cmd, aDecrypt); break;
635           case aEncr: set_cmd( &cmd, aEncr); break;
636           case aSign: set_cmd( &cmd, aSign );  break;
637           case aKeygen: set_cmd( &cmd, aKeygen); break;
638           case aSignKey: set_cmd( &cmd, aSignKey); break;
639           case aStore: set_cmd( &cmd, aStore); break;
640           case aEditKey: set_cmd( &cmd, aEditKey); break;
641           case aClearsign: set_cmd( &cmd, aClearsign); break;
642           case aGenRevoke: set_cmd( &cmd, aGenRevoke); break;
643           case aVerify: set_cmd( &cmd, aVerify); break;
644         #else
645           #ifdef MAINTAINER_OPTIONS
646             case aPrimegen: set_cmd( &cmd, aPrimegen); break;
647             case aTest: set_cmd( &cmd, aTest); break;
648             case aGenRandom: set_cmd( &cmd, aGenRandom); break;
649           #endif
650           case aPrintMD: set_cmd( &cmd, aPrintMD); break;
651           case aPrintMDs: set_cmd( &cmd, aPrintMDs); break;
652           case aListTrustDB: set_cmd( &cmd, aListTrustDB); break;
653           case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break;
654           case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break;
655           case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break;
656           case aListTrustPath: set_cmd( &cmd, aListTrustPath); break;
657           case aDeArmor: set_cmd( &cmd, aDeArmor); break;
658           case aEnArmor: set_cmd( &cmd, aEnArmor); break;
659           case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break;
660           case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break;
661         #endif /* IS_G10MAINT */
662
663
664
665           case oArmor: opt.armor = 1; opt.no_armor=0; break;
666           case oOutput: opt.outfile = pargs.r.ret_str; break;
667           case oQuiet: opt.quiet = 1; break;
668           case oVerbose: g10_opt_verbose++;
669                     opt.verbose++; opt.list_sigs=1; break;
670           case oKOption: set_cmd( &cmd, aKMode ); break;
671
672           case oBatch: opt.batch = 1; greeting = 0; break;
673           case oAnswerYes: opt.answer_yes = 1; break;
674           case oAnswerNo: opt.answer_no = 1; break;
675           case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
676           case oDebug: opt.debug |= pargs.r.ret_ulong; break;
677           case oDebugAll: opt.debug = ~0; break;
678           case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
679           case oFingerprint: opt.fingerprint++; break;
680           case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break;
681           case oOptions:
682             /* config files may not be nested (silently ignore them) */
683             if( !configfp ) {
684                 m_free(configname);
685                 configname = m_strdup(pargs.r.ret_str);
686                 goto next_pass;
687             }
688             break;
689           case oNoArmor: opt.no_armor=1; opt.armor=0; break;
690           case oNoDefKeyring: default_keyring = 0; break;
691           case oNoGreeting: greeting = 0; break;
692           case oNoVerbose: g10_opt_verbose = 0;
693                            opt.verbose = 0; opt.list_sigs=0; break;
694           case oQuickRandom: quick_random_gen(1); break;
695           case oNoComment: opt.no_comment=1; break;
696           case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break;
697           case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break;
698           case oTrustDBName: trustdb_name = pargs.r.ret_str; break;
699           case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break;
700           case oNoOptions: break; /* no-options */
701           case oHomedir: opt.homedir = pargs.r.ret_str; break;
702           case oNoBatch: opt.batch = 0; break;
703           case oWithColons: opt.with_colons=':'; break;
704
705           case oSkipVerify: opt.skip_verify=1; break;
706           case oCompressAlgo: opt.def_compress_algo = pargs.r.ret_int; break;
707           case oCompressKeys: opt.compress_keys = 1; break;
708           case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break;
709           case oAlwaysTrust: opt.always_trust = 1; break;
710           case oLoadExtension:
711             register_cipher_extension(orig_argc? *orig_argv:NULL,
712                                       pargs.r.ret_str);
713             break;
714           case oRFC1991: opt.rfc1991 = 1; opt.no_comment = 1; break;
715           case oEmuChecksumBug: opt.emulate_bugs |= EMUBUG_GPGCHKSUM; break;
716           case oCompressSigs: opt.compress_sigs = 1; break;
717           case oRunAsShmCP:
718           #ifndef USE_SHM_COPROCESSING
719             /* not possible in the option file,
720              * but we print the warning here anyway */
721             log_error("shared memory coprocessing is not available\n");
722           #endif
723             break;
724           case oSetFilename: opt.set_filename = pargs.r.ret_str; break;
725           case oComment: opt.comment_string = pargs.r.ret_str; break;
726           case oThrowKeyid: opt.throw_keyid = 1; break;
727           case oForceV3Sigs: opt.force_v3_sigs = 1; break;
728           case oS2KMode:   opt.s2k_mode = pargs.r.ret_int; break;
729           case oS2KDigest: s2k_digest_string = m_strdup(pargs.r.ret_str); break;
730           case oS2KCipher: s2k_cipher_string = m_strdup(pargs.r.ret_str); break;
731
732         #ifdef IS_G10
733           case oRemote: /* store the remote users */
734             sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
735             strcpy(sl->d, pargs.r.ret_str);
736             sl->next = remusr;
737             remusr = sl;
738             break;
739           case oTextmodeShort: opt.textmode = 2; break;
740           case oTextmode: opt.textmode=1;  break;
741           case oUser: /* store the local users */
742             sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
743             strcpy(sl->d, pargs.r.ret_str);
744             sl->next = locusr;
745             locusr = sl;
746             break;
747           case oCompress: opt.compress = pargs.r.ret_int; break;
748           case oPasswdFD: pwfd = pargs.r.ret_int; break;
749           case oCipherAlgo: def_cipher_string = m_strdup(pargs.r.ret_str); break;
750           case oDigestAlgo: def_digest_string = m_strdup(pargs.r.ret_str); break;
751           case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break;
752         #else
753           case oCipherAlgo:
754           case oDigestAlgo:
755           case oNoSecmemWarn:
756             break;  /* dummies */
757         #endif
758
759           default : errors++; pargs.err = configfp? 1:2; break;
760         }
761     }
762     if( configfp ) {
763         fclose( configfp );
764         configfp = NULL;
765         m_free(configname); configname = NULL;
766         goto next_pass;
767     }
768     m_free( configname ); configname = NULL;
769     if( log_get_errorcount(0) )
770         g10_exit(2);
771
772     if( greeting ) {
773         tty_printf("%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
774         tty_printf("%s\n", strusage(15) );
775     }
776
777     secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
778
779     set_debug();
780
781     /* must do this after dropping setuid, because string_to...
782      * may try to load an module */
783     if( def_cipher_string ) {
784         opt.def_cipher_algo = string_to_cipher_algo(def_cipher_string);
785         m_free(def_cipher_string); def_cipher_string = NULL;
786         if( check_cipher_algo(opt.def_cipher_algo) )
787             log_error(_("selected cipher algorithm is invalid\n"));
788     }
789     if( def_digest_string ) {
790         opt.def_digest_algo = string_to_digest_algo(def_digest_string);
791         m_free(def_digest_string); def_digest_string = NULL;
792         if( check_digest_algo(opt.def_digest_algo) )
793             log_error(_("selected digest algorithm is invalid\n"));
794     }
795     if( s2k_cipher_string ) {
796         opt.s2k_cipher_algo = string_to_cipher_algo(s2k_cipher_string);
797         m_free(s2k_cipher_string); s2k_cipher_string = NULL;
798         if( check_cipher_algo(opt.s2k_cipher_algo) )
799             log_error(_("selected cipher algorithm is invalid\n"));
800     }
801     if( s2k_digest_string ) {
802         opt.s2k_digest_algo = string_to_digest_algo(s2k_digest_string);
803         m_free(s2k_digest_string); s2k_digest_string = NULL;
804         if( check_digest_algo(opt.s2k_digest_algo) )
805             log_error(_("selected digest algorithm is invalid\n"));
806     }
807     if( opt.def_compress_algo < 1 || opt.def_compress_algo > 2 )
808         log_error(_("compress algorithm must be in range %d..%d\n"), 1, 2);
809     if( opt.completes_needed < 1 )
810         log_error(_("completes-needed must be greater than 0\n"));
811     if( opt.marginals_needed < 2 )
812         log_error(_("marginals-needed must be greater than 1\n"));
813     switch( opt.s2k_mode ) {
814       case 0:
815         log_info(_("note: simple S2K mode (0) is strongly discouraged\n"));
816         break;
817       case 1: case 3: break;
818       default:
819         log_error(_("invalid S2K mode; must be 0, 1 or 3\n"));
820     }
821
822     if( log_get_errorcount(0) )
823         g10_exit(2);
824
825     if( !cmd && opt.fingerprint )
826         set_cmd( &cmd, aListKeys);
827
828     if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */
829         if( cmd == aKModeC ) {
830             opt.fingerprint = 1;
831             cmd = aKMode;
832         }
833         opt.list_sigs = 0;
834         if( opt.verbose > 2 )
835             opt.check_sigs++;
836         if( opt.verbose > 1 )
837             opt.list_sigs++;
838
839         opt.verbose = opt.verbose > 1;
840         g10_opt_verbose = opt.verbose;
841     }
842
843
844     /* kludge to let -sat generate a clear text signature */
845     if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign )
846         cmd = aClearsign;
847
848     if( opt.verbose > 1 )
849         set_packet_list_mode(1);
850
851     /* add the keyrings, but not for some special commands and
852      * not in case of "-kvv userid keyring" */
853     if( cmd != aDeArmor && cmd != aEnArmor
854         && !(cmd == aKMode && argc == 2 ) ) {
855
856         if( !sec_nrings || default_keyring )  /* add default secret rings */
857             add_keyblock_resource("secring.gpg", 0, 1);
858         for(sl = sec_nrings; sl; sl = sl->next )
859             add_keyblock_resource( sl->d, 0, 1 );
860         if( !nrings || default_keyring )  /* add default ring */
861             add_keyblock_resource("pubring.gpg", 0, 0);
862         for(sl = nrings; sl; sl = sl->next )
863             add_keyblock_resource( sl->d, 0, 0 );
864     }
865     FREE_STRLIST(nrings);
866     FREE_STRLIST(sec_nrings);
867
868
869     if( pwfd != -1 )  /* read the passphrase now. */
870         read_passphrase_from_fd( pwfd );
871
872     fname = argc? *argv : NULL;
873
874     switch( cmd ) {
875       case aPrimegen:
876       case aPrintMD:
877       case aPrintMDs:
878       case aGenRandom:
879       case aDeArmor:
880       case aEnArmor:
881       case aFixTrustDB:
882         break;
883       case aKMode:
884       case aListKeys:
885       case aListSecretKeys:
886       case aCheckKeys:
887         if( opt.with_colons ) /* need this to list the trust */
888             rc = init_trustdb(1, trustdb_name );
889         break;
890       case aExportOwnerTrust: rc = init_trustdb( 0, trustdb_name ); break;
891       case aListTrustDB: rc = init_trustdb( argc? 1:0, trustdb_name ); break;
892       default: rc = init_trustdb(1, trustdb_name ); break;
893     }
894     if( rc )
895         log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc));
896
897
898     switch( cmd ) {
899       case aStore: /* only store the file */
900         if( argc > 1 )
901             wrong_args(_("--store [filename]"));
902         if( (rc = encode_store(fname)) )
903             log_error_f( print_fname_stdin(fname),
904                         "store failed: %s\n", g10_errstr(rc) );
905         break;
906     #ifdef IS_G10
907       case aSym: /* encrypt the given file only with the symmetric cipher */
908         if( argc > 1 )
909             wrong_args(_("--symmetric [filename]"));
910         if( (rc = encode_symmetric(fname)) )
911             log_error_f(print_fname_stdin(fname),
912                         "symmetric encryption failed: %s\n",g10_errstr(rc) );
913         break;
914
915       case aEncr: /* encrypt the given file */
916         if( argc > 1 )
917             wrong_args(_("--encrypt [filename]"));
918         if( (rc = encode_crypt(fname,remusr)) )
919             log_error("%s: encryption failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
920         break;
921
922       case aSign: /* sign the given file */
923         sl = NULL;
924         if( detached_sig ) { /* sign all files */
925             for( ; argc; argc--, argv++ )
926                 add_to_strlist( &sl, *argv );
927         }
928         else {
929             if( argc > 1 )
930                 wrong_args(_("--sign [filename]"));
931             if( argc ) {
932                 sl = m_alloc_clear( sizeof *sl + strlen(fname));
933                 strcpy(sl->d, fname);
934             }
935         }
936         if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) )
937             log_error("signing failed: %s\n", g10_errstr(rc) );
938         free_strlist(sl);
939         break;
940
941       case aSignEncr: /* sign and encrypt the given file */
942         if( argc > 1 )
943             wrong_args(_("--sign --encrypt [filename]"));
944         if( argc ) {
945             sl = m_alloc_clear( sizeof *sl + strlen(fname));
946             strcpy(sl->d, fname);
947         }
948         else
949             sl = NULL;
950         if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
951             log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
952         free_strlist(sl);
953         break;
954
955       case aClearsign: /* make a clearsig */
956         if( argc > 1 )
957             wrong_args(_("--clearsign [filename]"));
958         if( (rc = clearsign_file(fname, locusr, NULL)) )
959             log_error("%s: clearsign failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
960         break;
961
962       case aVerify:
963         if( (rc = verify_signatures( argc, argv ) ))
964             log_error("verify signatures failed: %s\n", g10_errstr(rc) );
965         break;
966
967       case aDecrypt:
968         if( argc > 1 )
969             wrong_args(_("--decrypt [filename]"));
970         if( (rc = decrypt_message( fname ) ))
971             log_error("decrypt_message failed: %s\n", g10_errstr(rc) );
972         break;
973
974
975       case aSignKey: /* sign the key given as argument */
976       case aEditKey: /* Edit a key signature */
977         if( argc != 1 )
978             wrong_args(_("--edit-key username"));
979         keyedit_menu(fname, locusr );
980         break;
981
982       #endif /* IS_G10 */
983
984       case aDeleteSecretKey:
985         if( argc != 1 )
986             wrong_args(_("--delete-secret-key username"));
987       case aDeleteKey:
988         if( argc != 1 )
989             wrong_args(_("--delete-key username"));
990         /* note: fname is the user id! */
991         if( (rc = delete_key(fname, cmd==aDeleteSecretKey)) )
992             log_error("%s: delete key failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
993         break;
994
995
996       case aCheckKeys:
997         opt.check_sigs = 1;
998       case aListSigs:
999         opt.list_sigs = 1;
1000       case aListKeys:
1001         public_key_list( argc, argv );
1002         break;
1003       case aListSecretKeys:
1004         secret_key_list( argc, argv );
1005         break;
1006
1007       case aKMode: /* list keyring */
1008         if( argc < 2 )  /* -kv [userid] */
1009             public_key_list( (argc && **argv)? 1:0, argv );
1010         else if( argc == 2 ) { /* -kv userid keyring */
1011             if( access( argv[1], R_OK ) ) {
1012                 log_error(_("can't open %s: %s\n"),
1013                                print_fname_stdin(argv[1]), strerror(errno));
1014             }
1015             else {
1016                 /* add keyring (default keyrings are not registered in this
1017                  * special case */
1018                 add_keyblock_resource( argv[1], 0, 0 );
1019                 public_key_list( **argv?1:0, argv );
1020             }
1021         }
1022         else
1023             wrong_args(_("-k[v][v][v][c] [userid] [keyring]") );
1024         break;
1025
1026     #ifdef IS_G10
1027       case aKeygen: /* generate a key (interactive) */
1028         if( argc )
1029             wrong_args("--gen-key");
1030         generate_keypair();
1031         break;
1032     #endif
1033
1034       case aFastImport:
1035       case aImport:
1036         if( !argc  ) {
1037             rc = import_keys( NULL, (cmd == aFastImport) );
1038             if( rc )
1039                 log_error("import failed: %s\n", g10_errstr(rc) );
1040         }
1041         for( ; argc; argc--, argv++ ) {
1042             rc = import_keys( *argv, (cmd == aFastImport) );
1043             if( rc )
1044                 log_error("import from '%s' failed: %s\n",
1045                                                 *argv, g10_errstr(rc) );
1046         }
1047         break;
1048
1049       case aExport:
1050         sl = NULL;
1051         for( ; argc; argc--, argv++ )
1052             add_to_strlist( &sl, *argv );
1053         export_pubkeys( sl );
1054         free_strlist(sl);
1055         break;
1056
1057       case aExportSecret:
1058         sl = NULL;
1059         for( ; argc; argc--, argv++ )
1060             add_to_strlist( &sl, *argv );
1061         export_seckeys( sl );
1062         free_strlist(sl);
1063         break;
1064
1065     #ifdef IS_G10
1066       case aGenRevoke:
1067         if( argc != 1 )
1068             wrong_args("--gen-revoke user-id");
1069         gen_revoke( *argv );
1070         break;
1071     #endif
1072
1073     #ifdef IS_G10MAINT
1074       case aDeArmor:
1075         if( argc > 1 )
1076             wrong_args("--dearmor [file]");
1077         rc = dearmor_file( argc? *argv: NULL );
1078         if( rc )
1079             log_error(_("dearmoring failed: %s\n"), g10_errstr(rc));
1080         break;
1081
1082       case aEnArmor:
1083         if( argc > 1 )
1084             wrong_args("--enarmor [file]");
1085         rc = enarmor_file( argc? *argv: NULL );
1086         if( rc )
1087             log_error(_("enarmoring failed: %s\n"), g10_errstr(rc));
1088         break;
1089
1090
1091      #ifdef MAINTAINER_OPTIONS
1092       case aPrimegen:
1093         if( argc == 1 ) {
1094             mpi_print( stdout, generate_public_prime( atoi(argv[0]) ), 1);
1095             putchar('\n');
1096         }
1097         else if( argc == 2 ) {
1098             mpi_print( stdout, generate_elg_prime( 0, atoi(argv[0]),
1099                                                    atoi(argv[1]), NULL,NULL ), 1);
1100             putchar('\n');
1101         }
1102         else if( argc == 3 ) {
1103             MPI g = mpi_alloc(1);
1104             mpi_print( stdout, generate_elg_prime( 0, atoi(argv[0]),
1105                                                    atoi(argv[1]), g, NULL ), 1);
1106             printf("\nGenerator: ");
1107             mpi_print( stdout, g, 1 );
1108             putchar('\n');
1109             mpi_free(g);
1110         }
1111         else if( argc == 4 ) {
1112             mpi_print( stdout, generate_elg_prime( 1, atoi(argv[0]),
1113                                                    atoi(argv[1]), NULL,NULL ), 1);
1114             putchar('\n');
1115         }
1116         else
1117             usage(1);
1118         break;
1119       #endif /* MAINTAINER OPTIONS */
1120
1121       #ifdef MAINTAINER_OPTIONS
1122       case aGenRandom:
1123         if( argc < 1 || argc > 2 )
1124             wrong_args("--gen-random level [hex]");
1125         {
1126             int level = atoi(*argv);
1127             for(;;) {
1128                 byte *p = get_random_bits( 8, level, 0);
1129                 if( argc == 1 ) {
1130                     printf("%02x", *p );
1131                     fflush(stdout);
1132                 }
1133                 else
1134                     putchar(c&0xff);
1135                 m_free(p);
1136             }
1137         }
1138         break;
1139       #endif /* MAINTAINER OPTIONS */
1140
1141       case aPrintMD:
1142         if( argc < 1)
1143             wrong_args("--print-md algo [file]");
1144         else {
1145             int algo = string_to_digest_algo(*argv);
1146
1147             if( !algo )
1148                 log_error(_("invalid hash algorithm '%s'\n"), *argv );
1149             else {
1150                 argc--; argv++;
1151                 if( !argc )
1152                     print_mds(NULL, algo);
1153                 else {
1154                     for(; argc; argc--, argv++ )
1155                         print_mds(*argv, algo);
1156                 }
1157             }
1158         }
1159         break;
1160
1161       case aPrintMDs:
1162         if( !argc )
1163             print_mds(NULL,0);
1164         else {
1165             for(; argc; argc--, argv++ )
1166                 print_mds(*argv,0);
1167         }
1168         break;
1169
1170      #ifdef MAINTAINER_OPTIONS
1171       case aTest: do_test( argc? atoi(*argv): 1 ); break;
1172       #endif /* MAINTAINER OPTIONS */
1173
1174       case aListTrustDB:
1175         if( !argc )
1176             list_trustdb(NULL);
1177         else {
1178             for( ; argc; argc--, argv++ )
1179                 list_trustdb( *argv );
1180         }
1181         break;
1182
1183       case aUpdateTrustDB:
1184         if( argc )
1185             wrong_args("--update-trustdb");
1186         update_trustdb();
1187         break;
1188
1189       case aCheckTrustDB:
1190         if( !argc )
1191             check_trustdb(NULL);
1192         else {
1193             for( ; argc; argc--, argv++ )
1194                 check_trustdb( *argv );
1195         }
1196         break;
1197
1198       case aFixTrustDB:
1199         log_error("this command ist not yet implemented.\"\n");
1200         log_error("A workaround is to use \"--export-ownertrust\", remove\n");
1201         log_error("the trustdb file and do an \"--import-ownertrust\".\n" );
1202         break;
1203
1204       case aListTrustPath:
1205         if( argc != 2 )
1206             wrong_args("--list-trust-path [-- -]<maxdepth> <username>");
1207         list_trust_path( atoi(*argv), argv[1] );
1208         break;
1209
1210       case aExportOwnerTrust:
1211         if( argc )
1212             wrong_args("--export-ownertrust");
1213         export_ownertrust();
1214         break;
1215
1216       case aImportOwnerTrust:
1217         if( argc > 1 )
1218             wrong_args("--import-ownertrust [file]");
1219         import_ownertrust( argc? *argv:NULL );
1220         break;
1221
1222      #endif /* IS_G10MAINT */
1223
1224
1225       case aListPackets:
1226         opt.list_packets=1;
1227       default:
1228         /* fixme: g10maint should do regular maintenace tasks here */
1229         if( argc > 1 )
1230             wrong_args(_("[filename]"));
1231         if( !(a = iobuf_open(fname)) )
1232             log_error(_("can't open '%s'\n"), print_fname_stdin(fname));
1233         else {
1234             if( !opt.no_armor ) {
1235                 if( use_armor_filter( a ) ) {
1236                     memset( &afx, 0, sizeof afx);
1237                     iobuf_push_filter( a, armor_filter, &afx );
1238                 }
1239             }
1240             if( cmd == aListPackets ) {
1241                 set_packet_list_mode(1);
1242                 opt.list_packets=1;
1243             }
1244             proc_packets( a );
1245             iobuf_close(a);
1246         }
1247         break;
1248     }
1249
1250     /* cleanup */
1251     FREE_STRLIST(remusr);
1252     FREE_STRLIST(locusr);
1253     g10_exit(0);
1254     return 8; /*NEVER REACHED*/
1255 }
1256
1257
1258 void
1259 g10_exit( int rc )
1260 {
1261     if( opt.debug & DBG_MEMSTAT_VALUE )
1262         m_print_stats("on exit");
1263     if( opt.debug )
1264         secmem_dump_stats();
1265     secmem_term();
1266     rc = rc? rc : log_get_errorcount(0)? 2:0;
1267     /*write_status( STATUS_LEAVE );*/
1268     exit(rc );
1269 }
1270
1271
1272 void
1273 do_not_use_RSA()
1274 {
1275     static int did_rsa_note = 0;
1276
1277     if( !did_rsa_note ) {
1278         did_rsa_note = 1;
1279         log_info(_("RSA keys are deprecated; please consider "
1280                    "creating a new key and use this key in the future\n"));
1281     }
1282 }
1283
1284
1285 #ifdef IS_G10MAINT
1286 static void
1287 print_hex( byte *p, size_t n )
1288 {
1289     int i;
1290
1291     if( n == 20 ) {
1292         for(i=0; i < n ; i++, i++, p += 2 ) {
1293             if( i )
1294                 putchar(' ');
1295             if( i == 10 )
1296                 putchar(' ');
1297             printf("%02X%02X", *p, p[1] );
1298         }
1299     }
1300     else if( n == 24 ) {
1301         for(i=0; i < n ; i += 4, p += 4 ) {
1302             if( i )
1303                 putchar(' ');
1304             if( i == 12 )
1305                 putchar(' ');
1306             printf("%02X%02X%02X%02X", *p, p[1], p[2], p[3] );
1307         }
1308     }
1309     else {
1310         for(i=0; i < n ; i++, p++ ) {
1311             if( i )
1312                 putchar(' ');
1313             if( i && !(i%8) )
1314                 putchar(' ');
1315             printf("%02X", *p );
1316         }
1317     }
1318 }
1319
1320 static void
1321 print_mds( const char *fname, int algo )
1322 {
1323     FILE *fp;
1324     char buf[1024];
1325     size_t n;
1326     MD_HANDLE md;
1327     char *pname;
1328
1329     if( !fname ) {
1330         fp = stdin;
1331         pname = m_strdup("[stdin]: ");
1332     }
1333     else {
1334         pname = m_alloc(strlen(fname)+3);
1335         strcpy(stpcpy(pname,fname),": ");
1336         fp = fopen( fname, "rb" );
1337     }
1338     if( !fp ) {
1339         log_error("%s%s\n", pname, strerror(errno) );
1340         m_free(pname);
1341         return;
1342     }
1343
1344     md = md_open( 0, 0 );
1345     if( algo )
1346         md_enable( md, algo );
1347     else {
1348         md_enable( md, DIGEST_ALGO_MD5 );
1349         md_enable( md, DIGEST_ALGO_SHA1 );
1350         md_enable( md, DIGEST_ALGO_RMD160 );
1351         if( !check_digest_algo(DIGEST_ALGO_TIGER) )
1352             md_enable( md, DIGEST_ALGO_TIGER );
1353     }
1354
1355     while( (n=fread( buf, 1, DIM(buf), fp )) )
1356         md_write( md, buf, n );
1357     if( ferror(fp) )
1358         log_error("%s%s\n", pname, strerror(errno) );
1359     else {
1360         md_final(md);
1361         if( algo ) {
1362             if( fname )
1363                 fputs( pname, stdout );
1364             print_hex(md_read(md, algo), md_digest_length(algo) );
1365         }
1366         else {
1367             printf(  "%s   MD5 = ", fname?pname:"" );
1368                             print_hex(md_read(md, DIGEST_ALGO_MD5), 16 );
1369             printf("\n%s  SHA1 = ", fname?pname:""  );
1370                             print_hex(md_read(md, DIGEST_ALGO_SHA1), 20 );
1371             printf("\n%sRMD160 = ", fname?pname:""  );
1372                             print_hex(md_read(md, DIGEST_ALGO_RMD160), 20 );
1373             if( !check_digest_algo(DIGEST_ALGO_TIGER) ) {
1374                 printf("\n%s TIGER = ", fname?pname:""  );
1375                             print_hex(md_read(md, DIGEST_ALGO_TIGER), 24 );
1376             }
1377         }
1378         putchar('\n');
1379     }
1380     md_close(md);
1381
1382     if( fp != stdin )
1383         fclose(fp);
1384 }
1385
1386
1387
1388 #ifdef MAINTAINER_OPTIONS
1389 static void
1390 do_test(int times)
1391 {
1392     m_check(NULL);
1393 }
1394 #endif /* MAINTAINER OPTIONS */
1395 #endif /* IS_G10MAINT */
1396