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