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