a new release
[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
45 #ifndef IS_G10MAINT
46   #define IS_G10 1
47 #endif
48
49
50 enum cmd_and_opt_values { aNull = 0,
51     oArmor        = 'a',
52     aDetachedSign = 'b',
53     aSym          = 'c',
54     aDecrypt      = 'd',
55     aEncr         = 'e',
56     oKOption      = 'k',
57     oDryRun       = 'n',
58     oOutput       = 'o',
59     oRemote       = 'r',
60     aSign         = 's',
61     oTextmode     = 't',
62     oUser         = 'u',
63     oVerbose      = 'v',
64     oCompress     = 'z',
65     oBatch        = 500,
66     aClearsign,
67     aStore,
68     aKeygen,
69     aSignEncr,
70     aSignKey,
71     aListPackets,
72     aEditKey,
73     aDeleteKey,
74     aDeleteSecretKey,
75     aKMode,
76     aKModeC,
77     aImport,
78     aVerify,
79     aListKeys,
80     aListSigs,
81     aListSecretKeys,
82     aExport,
83     aExportSecret,
84     aCheckKeys,
85     aGenRevoke,
86     aPrimegen,
87     aPrintMD,
88     aPrintMDs,
89     aCheckTrustDB,
90     aFixTrustDB,
91     aListTrustDB,
92     aListTrustPath,
93     aExportOwnerTrust,
94     aImportOwnerTrust,
95     aDeArmor,
96     aEnArmor,
97     aGenRandom,
98
99     oFingerprint,
100     oDoNotExportRSA,
101     oAnswerYes,
102     oAnswerNo,
103     oKeyring,
104     oSecretKeyring,
105     oDefaultKey,
106     oOptions,
107     oDebug,
108     oDebugAll,
109     oStatusFD,
110     oNoComment,
111     oCompletesNeeded,
112     oMarginalsNeeded,
113     oLoadExtension,
114     oRFC1991,
115     oCipherAlgo,
116     oDigestAlgo,
117     oCompressAlgo,
118     oPasswdFD,
119     oQuickRandom,
120     oNoVerbose,
121     oTrustDBName,
122     oNoSecmemWarn,
123     oNoArmor,
124     oNoDefKeyring,
125     oNoGreeting,
126     oNoOptions,
127     oNoBatch,
128     oHomedir,
129     oWithColons,
130     oSkipVerify,
131     oCompressKeys,
132     oCompressSigs,
133     oAlwaysTrust,
134     oEmuChecksumBug,
135     oRunAsShmCP,
136     oSetFilename,
137     oComment,
138     oThrowKeyid,
139     oS2KMode,
140     oS2KDigest,
141     oS2KCipher,
142 aTest };
143
144
145 static ARGPARSE_OPTS opts[] = {
146
147     { 300, NULL, 0, N_("@Commands:\n ") },
148
149   #ifdef IS_G10
150     { aSign, "sign",      256, N_("|[file]|make a signature")},
151     { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") },
152     { aDetachedSign, "detach-sign", 256, N_("make a detached signature")},
153     { aEncr, "encrypt",   256, N_("encrypt data")},
154     { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")},
155     { aStore, "store",     256, N_("store only")},
156     { aDecrypt, "decrypt",   256, N_("decrypt data (default)")},
157     { aVerify, "verify"   , 256, N_("verify a signature")},
158   #endif
159     { aListKeys, "list-keys", 256, N_("list keys")},
160     { aListSigs, "list-sigs", 256, N_("list keys and signatures")},
161     { aCheckKeys, "check-sigs",256, N_("check key signatures")},
162     { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
163     { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
164   #ifdef IS_G10
165     { aKeygen, "gen-key",   256, N_("generate a new key pair")},
166   #endif
167     { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
168   #ifdef IS_G10
169     { aEditKey, "edit-key"  ,256, N_("sign or edit a key")},
170     { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")},
171   #endif
172     { aExport, "export"          , 256, N_("export keys") },
173     { aExportSecret, "export-secret-keys" , 256, "@" },
174     { oDoNotExportRSA, "do-not-export-rsa", 0, "@" },
175     { aImport, "import",      256     , N_("import/merge keys")},
176     { aListPackets, "list-packets",256,N_("list only the sequence of packets")},
177   #ifdef IS_G10MAINT
178     { aExportOwnerTrust, "export-ownertrust", 256, N_("export the ownertrust values")},
179     { aImportOwnerTrust, "import-ownertrust", 256 , N_("import ownertrust values")},
180     { aCheckTrustDB, "check-trustdb",0 , N_("|[NAMES]|check the trust database")},
181     { aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")},
182     { aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") },
183     { aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") },
184     { aPrintMD,  "print-md" , 256, N_("|algo [files]|print message digests")},
185     { aPrintMDs, "print-mds" , 256, N_("print all message digests")},
186     #ifdef MAINTAINER_OPTIONS
187     { aPrimegen, "gen-prime" , 256, "@" },
188     { aGenRandom, "gen-random" , 256, "@" },
189     #endif
190   #endif
191
192     { 301, NULL, 0, N_("@\nOptions:\n ") },
193
194     { oArmor, "armor",     0, N_("create ascii armored output")},
195   #ifdef IS_G10
196     { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
197     { oRemote, "remote-user", 2, N_("use this user-id for encryption")},
198     { oCompress, NULL,        1, N_("|N|set compress level N (0 disables)") },
199     { oTextmode, "textmode",  0, N_("use canonical text mode")},
200   #endif
201     { oOutput, "output",    2, N_("use as output file")},
202     { oVerbose, "verbose",   0, N_("verbose") },
203  /* { oDryRun, "dry-run",   0, N_("do not make any changes") }, */
204     { oBatch, "batch",     0, N_("batch mode: never ask")},
205     { oAnswerYes, "yes",       0, N_("assume yes on most questions")},
206     { oAnswerNo,  "no",        0, N_("assume no on most questions")},
207     { oKeyring, "keyring"   ,2, N_("add this keyring to the list of keyrings")},
208     { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
209     { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
210     { oOptions, "options"   , 2, N_("read options from file")},
211
212     { oDebug, "debug"     ,4|16, N_("set debugging flags")},
213     { oDebugAll, "debug-all" ,0, N_("enable full debugging")},
214     { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
215     { oNoComment, "no-comment", 0,   N_("do not write comment packets")},
216     { oCompletesNeeded, "completes-needed", 1, N_("(default is 1)")},
217     { oMarginalsNeeded, "marginals-needed", 1, N_("(default is 3)")},
218     { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
219     { oRFC1991, "rfc1991",   0, N_("emulate the mode described in RFC1991")},
220     { oS2KMode, "s2k-mode",  1, N_("|N|use passphrase mode N")},
221     { oS2KDigest, "s2k-digest-algo",2,
222                 N_("|NAME|use message digest algorithm NAME for passphrases")},
223     { oS2KCipher, "s2k-cipher-algo",2,
224                 N_("|NAME|use cipher algorithm NAME for passphrases")},
225   #ifdef IS_G10
226     { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
227     { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
228     { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
229     { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
230   #else /* some dummies */
231     { oCipherAlgo, "cipher-algo", 2 , "@"},
232     { oDigestAlgo, "digest-algo", 2 , "@"},
233     { oCompressAlgo, "compress-algo", 1 , "@"},
234   #endif
235
236   #ifdef IS_G10
237     { 302, NULL, 0, N_("@\nExamples:\n\n"
238     " -se -r Bob [file]          sign and encrypt for user Bob\n"
239     " --clearsign [file]         make a clear text signature\n"
240     " --detach-sign [file]       make a detached signature\n"
241     " --list-keys [names]        show keys\n"
242     " --fingerprint [names]      show fingerprints\n"  ) },
243   #endif
244
245   /* hidden options */
246   #ifdef IS_G10MAINT
247     { aTest, "test"      , 0, "@" },
248     { aExportOwnerTrust, "list-ownertrust",0 , "@"},  /* alias */
249     { aListTrustDB, "list-trustdb",0 , "@"},
250     { aListTrustPath, "list-trust-path",0, "@"},
251   #endif
252   #ifdef IS_G10
253     { oKOption, NULL,    0, "@"},
254     { aEditKey, "edit-sig"  ,0, "@"}, /* alias for edit-key */
255     { oPasswdFD, "passphrase-fd",1, "@" },
256     { aSignKey, "sign-key"  ,256, "@" }, /* alias for edit-key */
257   #endif
258     { aDeleteSecretKey, "delete-secret-key",0, "@" },
259     { oQuickRandom, "quick-random", 0, "@"},
260     { oNoVerbose, "no-verbose", 0, "@"},
261     { oTrustDBName, "trustdb-name", 2, "@" },
262     { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */
263     { oNoArmor, "no-armor",   0, "@"},
264     { oNoDefKeyring, "no-default-keyring", 0, "@" },
265     { oNoGreeting, "no-greeting", 0, "@" },
266     { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */
267     { oHomedir, "homedir", 2, "@" },   /* defaults to "~/.gnupg" */
268     { oNoBatch, "no-batch", 0, "@" },
269     { oWithColons, "with-colons", 0, "@"},
270     { aListKeys, "list-key", 0, "@" }, /* alias */
271     { aListSigs, "list-sig", 0, "@" }, /* alias */
272     { aCheckKeys, "check-sig",0, "@" }, /* alias */
273     { oSkipVerify, "skip-verify",0, "@" },
274     { oCompressKeys, "compress-keys",0, "@"},
275     { oCompressSigs, "compress-sigs",0, "@"},
276     { oAlwaysTrust, "always-trust", 0, "@"},
277     { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"},
278     { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
279     { oSetFilename, "set-filename", 2, "@" },
280     { oComment, "comment", 2, "@" },
281 {0} };
282
283
284
285 static int maybe_setuid = 1;
286
287 static char *build_list( const char *text,
288                          const char *(*mapf)(int), int (*chkf)(int) );
289 static void set_cmd( enum cmd_and_opt_values *ret_cmd,
290                         enum cmd_and_opt_values new_cmd );
291 #ifdef IS_G10MAINT
292 static void print_hex( byte *p, size_t n );
293 static void print_mds( const char *fname, int algo );
294 #endif
295
296 const char *
297 strusage( int level )
298 {
299   static char *digests, *pubkeys, *ciphers;
300     const char *p;
301     switch( level ) {
302       case 11: p =
303           #ifdef IS_G10MAINT
304             "gpgm (GNUPG)";
305           #else
306             "gpg (GNUPG)";
307           #endif
308         break;
309       case 13: p = VERSION; break;
310       case 17: p = PRINTABLE_OS_NAME; break;
311       case 19: p =
312             _("Please report bugs to <gnupg-bugs@gnu.org>.\n");
313         break;
314       case 1:
315       case 40:  p =
316           #ifdef IS_G10MAINT
317             _("Usage: gpgm [options] [files] (-h for help)");
318           #else
319             _("Usage: gpg [options] [files] (-h for help)");
320           #endif
321         break;
322       case 41:  p =
323           #ifdef IS_G10MAINT
324             _("Syntax: gpgm [options] [files]\n"
325               "GNUPG maintenance utility\n");
326           #else
327             _("Syntax: gpg [options] [files]\n"
328               "sign, check, encrypt or decrypt\n"
329               "default operation depends on the input data\n");
330           #endif
331         break;
332
333       case 31: p = _("\nSupported algorithms:\n"); break;
334       case 32:
335         if( !ciphers )
336             ciphers = build_list("Cipher: ", cipher_algo_to_string,
337                                                         check_cipher_algo );
338         p = ciphers;
339         break;
340       case 33:
341         if( !pubkeys )
342             pubkeys = build_list("Pubkey: ", pubkey_algo_to_string,
343                                                         check_pubkey_algo );
344         p = pubkeys;
345         break;
346       case 34:
347         if( !digests )
348             digests = build_list("Hash: ", digest_algo_to_string,
349                                                         check_digest_algo );
350         p = digests;
351         break;
352
353       default:  p = default_strusage(level);
354     }
355     return p;
356 }
357
358
359 static char *
360 build_list( const char *text, const char * (*mapf)(int), int (*chkf)(int) )
361 {
362     int i;
363     const char *s;
364     size_t n=strlen(text)+2;
365     char *list, *p;
366
367     if( maybe_setuid )
368         secmem_init( 0 );    /* drop setuid */
369
370     for(i=1; i < 110; i++ )
371         if( !chkf(i) && (s=mapf(i)) )
372             n += strlen(s) + 2;
373     list = m_alloc( 21 + n ); *list = 0;
374     for(p=NULL, i=1; i < 110; i++ ) {
375         if( !chkf(i) && (s=mapf(i)) ) {
376             if( !p )
377                 p = stpcpy( list, text );
378             else
379                 p = stpcpy( p, ", ");
380             p = stpcpy(p, s );
381         }
382     }
383     if( p )
384         p = stpcpy(p, "\n" );
385     return list;
386 }
387
388
389 static void
390 i18n_init(void)
391 {
392   #ifdef ENABLE_NLS
393     #ifdef HAVE_LC_MESSAGES
394        setlocale( LC_TIME, "" );
395        setlocale( LC_MESSAGES, "" );
396     #else
397        setlocale( LC_ALL, "" );
398     #endif
399     bindtextdomain( PACKAGE, G10_LOCALEDIR );
400     textdomain( PACKAGE );
401   #endif
402 }
403
404 static void
405 wrong_args( const char *text)
406 {
407   #ifdef IS_G10MAINT
408     fputs(_("usage: gpgm [options] "),stderr);
409   #else
410     fputs(_("usage: gpg [options] "),stderr);
411   #endif
412     fputs(text,stderr);
413     putc('\n',stderr);
414     g10_exit(2);
415 }
416
417 static void
418 set_debug(void)
419 {
420     if( opt.debug & DBG_MEMORY_VALUE )
421         memory_debug_mode = 1;
422     if( opt.debug & DBG_MEMSTAT_VALUE )
423         memory_stat_debug_mode = 1;
424     if( opt.debug & DBG_MPI_VALUE )
425         mpi_debug_mode = 1;
426     if( opt.debug & DBG_CIPHER_VALUE )
427         g10c_debug_mode = 1;
428     if( opt.debug & DBG_IOBUF_VALUE )
429         iobuf_debug_mode = 1;
430
431 }
432
433
434 static void
435 set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd )
436 {
437     enum cmd_and_opt_values cmd = *ret_cmd;
438
439     if( !cmd || cmd == new_cmd )
440         cmd = new_cmd;
441     else if( cmd == aSign && new_cmd == aEncr )
442         cmd = aSignEncr;
443     else if( cmd == aEncr && new_cmd == aSign )
444         cmd = aSignEncr;
445     else if( cmd == aKMode && new_cmd == aSym )
446         cmd = aKModeC;
447     else if(    ( cmd == aSign     && new_cmd == aClearsign )
448              || ( cmd == aClearsign && new_cmd == aSign )  )
449         cmd = aClearsign;
450     else {
451         log_error(_("conflicting commands\n"));
452         g10_exit(2);
453     }
454
455     *ret_cmd = cmd;
456 }
457
458
459
460 int
461 main( int argc, char **argv )
462 {
463     ARGPARSE_ARGS pargs;
464     IOBUF a;
465     int rc=0;
466     int orig_argc;
467     char **orig_argv;
468     const char *fname;
469     STRLIST sl, remusr= NULL, locusr=NULL;
470     STRLIST nrings=NULL, sec_nrings=NULL;
471     armor_filter_context_t afx;
472     int detached_sig = 0;
473     FILE *configfp = NULL;
474     char *configname = NULL;
475     unsigned configlineno;
476     int parse_debug = 0;
477     int default_config =1;
478     int errors=0;
479     int default_keyring = 1;
480     int greeting = 1;
481     enum cmd_and_opt_values cmd = 0;
482     const char *trustdb_name = NULL;
483     char *def_cipher_string = NULL;
484     char *def_digest_string = NULL;
485     char *s2k_cipher_string = NULL;
486     char *s2k_digest_string = NULL;
487     int pwfd = -1;
488   #ifdef USE_SHM_COPROCESSING
489     ulong requested_shm_size=0;
490   #endif
491
492     trap_unaligned();
493     secmem_set_flags( secmem_get_flags() | 2 ); /* suspend warnings */
494   #ifdef IS_G10MAINT
495     secmem_init( 0 );      /* disable use of secmem */
496     maybe_setuid = 0;
497     log_set_name("gpgm");
498   #else
499     /* Please note that we may running SUID(ROOT), so be very CAREFUL
500      * when adding any stuff between here and the call to
501      * secmem_init()  somewhere after the option parsing
502      */
503     log_set_name("gpg");
504     secure_random_alloc(); /* put random number into secure memory */
505     disable_core_dumps();
506     init_signals();
507   #endif
508     i18n_init();
509     opt.compress = -1; /* defaults to standard compress level */
510     /* fixme: set the next two to zero and decide where used */
511     opt.def_cipher_algo = 0;
512     opt.def_digest_algo = 0;
513     opt.def_compress_algo = 2;
514     opt.s2k_mode = 1; /* salted */
515     opt.s2k_digest_algo = DIGEST_ALGO_RMD160;
516     opt.s2k_cipher_algo = CIPHER_ALGO_BLOWFISH;
517     opt.completes_needed = 1;
518     opt.marginals_needed = 3;
519     opt.homedir = getenv("GNUPGHOME");
520     if( !opt.homedir || !*opt.homedir ) {
521       #ifdef __MINGW32__
522         opt.homedir = "c:/gnupg";
523       #else
524         opt.homedir = "~/.gnupg";
525       #endif
526     }
527
528     /* check whether we have a config file on the commandline */
529     orig_argc = argc;
530     orig_argv = argv;
531     pargs.argc = &argc;
532     pargs.argv = &argv;
533     pargs.flags= 1|(1<<6);  /* do not remove the args, ignore version */
534     while( arg_parse( &pargs, opts) ) {
535         if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll )
536             parse_debug++;
537         else if( pargs.r_opt == oOptions ) {
538             /* yes there is one, so we do not try the default one, but
539              * read the option file when it is encountered at the commandline
540              */
541             default_config = 0;
542         }
543         else if( pargs.r_opt == oNoOptions )
544             default_config = 0; /* --no-options */
545         else if( pargs.r_opt == oHomedir )
546             opt.homedir = pargs.r.ret_str;
547       #ifdef USE_SHM_COPROCESSING
548         else if( pargs.r_opt == oRunAsShmCP ) {
549             /* does not make sense in a options file, we do it here,
550              * so that we are the able to drop setuid as soon as possible */
551             opt.shm_coprocess = 1;
552             requested_shm_size = pargs.r.ret_ulong;
553         }
554       #endif
555     }
556
557
558   #ifdef USE_SHM_COPROCESSING
559     if( opt.shm_coprocess ) {
560       #ifdef IS_G10
561         init_shm_coprocessing(requested_shm_size, 1 );
562       #else
563         init_shm_coprocessing(requested_shm_size, 0 );
564       #endif
565     }
566   #endif
567   #ifdef IS_G10
568     /* initialize the secure memory. */
569     secmem_init( 16384 );
570     maybe_setuid = 0;
571     /* Okay, we are now working under our real uid */
572   #endif
573
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 )
1236         secmem_dump_stats();
1237     secmem_term();
1238     rc = rc? rc : log_get_errorcount(0)? 2:0;
1239     /*write_status( STATUS_LEAVE );*/
1240     exit(rc );
1241 }
1242
1243
1244 void
1245 do_not_use_RSA()
1246 {
1247     static int did_rsa_note = 0;
1248
1249     if( !did_rsa_note ) {
1250         did_rsa_note = 1;
1251         log_info(_("RSA keys are deprecated; please consider "
1252                    "creating a new key and use this key in the future\n"));
1253     }
1254 }
1255
1256
1257 #ifdef IS_G10MAINT
1258 static void
1259 print_hex( byte *p, size_t n )
1260 {
1261     int i;
1262
1263     if( n == 20 ) {
1264         for(i=0; i < n ; i++, i++, p += 2 ) {
1265             if( i )
1266                 putchar(' ');
1267             if( i == 10 )
1268                 putchar(' ');
1269             printf("%02X%02X", *p, p[1] );
1270         }
1271     }
1272     else if( n == 24 ) {
1273         for(i=0; i < n ; i += 4, p += 4 ) {
1274             if( i )
1275                 putchar(' ');
1276             if( i == 12 )
1277                 putchar(' ');
1278             printf("%02X%02X%02X%02X", *p, p[1], p[2], p[3] );
1279         }
1280     }
1281     else {
1282         for(i=0; i < n ; i++, p++ ) {
1283             if( i )
1284                 putchar(' ');
1285             if( i && !(i%8) )
1286                 putchar(' ');
1287             printf("%02X", *p );
1288         }
1289     }
1290 }
1291
1292 static void
1293 print_mds( const char *fname, int algo )
1294 {
1295     FILE *fp;
1296     char buf[1024];
1297     size_t n;
1298     MD_HANDLE md;
1299     char *pname;
1300
1301     if( !fname ) {
1302         fp = stdin;
1303         pname = m_strdup("[stdin]: ");
1304     }
1305     else {
1306         pname = m_alloc(strlen(fname)+3);
1307         strcpy(stpcpy(pname,fname),": ");
1308         fp = fopen( fname, "rb" );
1309     }
1310     if( !fp ) {
1311         log_error("%s%s\n", pname, strerror(errno) );
1312         m_free(pname);
1313         return;
1314     }
1315
1316     md = md_open( 0, 0 );
1317     if( algo )
1318         md_enable( md, algo );
1319     else {
1320         md_enable( md, DIGEST_ALGO_MD5 );
1321         md_enable( md, DIGEST_ALGO_SHA1 );
1322         md_enable( md, DIGEST_ALGO_RMD160 );
1323         if( !check_digest_algo(DIGEST_ALGO_TIGER) )
1324             md_enable( md, DIGEST_ALGO_TIGER );
1325     }
1326
1327     while( (n=fread( buf, 1, DIM(buf), fp )) )
1328         md_write( md, buf, n );
1329     if( ferror(fp) )
1330         log_error("%s%s\n", pname, strerror(errno) );
1331     else {
1332         md_final(md);
1333         if( algo ) {
1334             if( fname )
1335                 fputs( pname, stdout );
1336             print_hex(md_read(md, algo), md_digest_length(algo) );
1337         }
1338         else {
1339             printf(  "%s   MD5 = ", fname?pname:"" );
1340                             print_hex(md_read(md, DIGEST_ALGO_MD5), 16 );
1341             printf("\n%s  SHA1 = ", fname?pname:""  );
1342                             print_hex(md_read(md, DIGEST_ALGO_SHA1), 20 );
1343             printf("\n%sRMD160 = ", fname?pname:""  );
1344                             print_hex(md_read(md, DIGEST_ALGO_RMD160), 20 );
1345             if( !check_digest_algo(DIGEST_ALGO_TIGER) ) {
1346                 printf("\n%s TIGER = ", fname?pname:""  );
1347                             print_hex(md_read(md, DIGEST_ALGO_TIGER), 24 );
1348             }
1349         }
1350         putchar('\n');
1351     }
1352     md_close(md);
1353
1354     if( fp != stdin )
1355         fclose(fp);
1356 }
1357
1358
1359
1360 #ifdef MAINTAINER_OPTIONS
1361 static void
1362 do_test(int times)
1363 {
1364     m_check(NULL);
1365 }
1366 #endif /* MAINTAINER OPTIONS */
1367 #endif /* IS_G10MAINT */
1368