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