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