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