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