* gpgsm.c (main): New option --log-file.
[gnupg.git] / sm / gpgsm.c
1 /* gpgsm.c - GnuPG for S/MIME 
2  *      Copyright (C) 2001, 2002 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 <ctype.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include <gcrypt.h>
31 #include "gpgsm.h"
32 #include "../assuan/assuan.h" /* malloc hooks */
33 #include "../kbx/keybox.h" /* malloc hooks */
34 #include "i18n.h"
35 #include "keydb.h"
36 #include "sysutils.h"
37
38 enum cmd_and_opt_values {
39   aNull = 0,
40   oArmor        = 'a',
41   aDetachedSign = 'b',
42   aSym          = 'c',
43   aDecrypt      = 'd',
44   aEncr         = 'e',
45   oInteractive  = 'i',
46   oKOption      = 'k',
47   oDryRun       = 'n',
48   oOutput       = 'o',
49   oQuiet        = 'q',
50   oRecipient    = 'r',
51   aSign         = 's',
52   oTextmodeShort= 't',
53   oUser         = 'u',
54   oVerbose      = 'v',
55   oCompress     = 'z',
56   oNotation     = 'N',
57   oBatch        = 500,
58   aClearsign,
59   aStore,
60   aKeygen,
61   aSignEncr,
62   aSignKey,
63   aLSignKey,
64   aListPackets,
65   aEditKey,
66   aDeleteKey,
67   aImport,
68   aVerify,
69   aVerifyFiles,
70   aListKeys,
71   aListSigs,
72   aListSecretKeys,
73   aSendKeys,
74   aRecvKeys,
75   aExport,
76   aCheckKeys,
77   aServer,                        
78   aLearnCard,
79
80   oOptions,
81   oDebug,
82   oDebugAll,
83   oDebugWait,
84   oLogFile,
85
86   oEnableSpecialFilenames,
87
88   oAgentProgram,
89   oDisplay,
90   oTTYname,
91   oTTYtype,
92   oLCctype,
93   oLCmessages,
94
95   oDirmngrProgram,
96   oFakedSystemTime,
97
98
99   oAssumeArmor,
100   oAssumeBase64,
101   oAssumeBinary,
102
103   oBase64,
104   oNoArmor,
105
106   oDisableCRLChecks,
107   oEnableCRLChecks,
108
109   oIncludeCerts,
110   oPolicyFile,
111   oDisablePolicyChecks,
112   oEnablePolicyChecks,
113
114   
115
116   oTextmode,
117   oFingerprint,
118   oWithFingerprint,
119   oAnswerYes,
120   oAnswerNo,
121   oKeyring,
122   oSecretKeyring,
123   oDefaultKey,
124   oDefRecipient,
125   oDefRecipientSelf,
126   oNoDefRecipient,
127   oStatusFD,
128   oNoComment,
129   oNoVersion,
130   oEmitVersion,
131   oCompletesNeeded,
132   oMarginalsNeeded,
133   oMaxCertDepth,
134   oLoadExtension,
135   oRFC1991,
136   oOpenPGP,
137   oCipherAlgo,
138   oDigestAlgo,
139   oCompressAlgo,
140   oPasswdFD,
141   oCommandFD,
142   oNoVerbose,
143   oTrustDBName,
144   oNoSecmemWarn,
145   oNoDefKeyring,
146   oNoGreeting,
147   oNoTTY,
148   oNoOptions,
149   oNoBatch,
150   oHomedir,
151   oWithColons,
152   oWithKeyData,
153   oSkipVerify,
154   oCompressKeys,
155   oCompressSigs,
156   oAlwaysTrust,
157   oRunAsShmCP,
158   oSetFilename,
159   oSetPolicyURL,
160   oUseEmbeddedFilename,
161   oComment,
162   oDefaultComment,
163   oThrowKeyid,
164   oForceV3Sigs,
165   oForceMDC,
166   oS2KMode,
167   oS2KDigest,
168   oS2KCipher,
169   oCharset,
170   oNotDashEscaped,
171   oEscapeFrom,
172   oLockOnce,
173   oLockMultiple,
174   oLockNever,
175   oKeyServer,
176   oEncryptTo,
177   oNoEncryptTo,
178   oLoggerFD,
179   oUtf8Strings,
180   oNoUtf8Strings,
181   oDisableCipherAlgo,
182   oDisablePubkeyAlgo,
183   oAllowNonSelfsignedUID,
184   oAllowFreeformUID,
185   oNoLiteral,
186   oSetFilesize,
187   oHonorHttpProxy,
188   oFastListMode,
189   oListOnly,
190   oIgnoreTimeConflict,
191   oNoRandomSeedFile,
192   oNoAutoKeyRetrieve,
193   oUseAgent,
194   oMergeOnly,
195   oTryAllSecrets,
196   oTrustedKey,
197   oEmuMDEncodeBug,
198   aDummy
199  };
200
201
202 static ARGPARSE_OPTS opts[] = {
203
204     { 300, NULL, 0, N_("@Commands:\n ") },
205
206     { aSign, "sign",      256, N_("|[file]|make a signature")},
207     { aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") },
208     { aDetachedSign, "detach-sign", 256, N_("make a detached signature")},
209     { aEncr, "encrypt",   256, N_("encrypt data")},
210     { aSym, "symmetric", 256, N_("encryption only with symmetric cipher")},
211     { aDecrypt, "decrypt",   256, N_("decrypt data (default)")},
212     { aVerify, "verify"   , 256, N_("verify a signature")},
213     { aVerifyFiles, "verify-files" , 256, "@" },
214     { aListKeys, "list-keys", 256, N_("list keys")},
215     { aListKeys, "list-public-keys", 256, "@" },
216     { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
217     { aListSigs,   "list-sigs", 256, N_("list certificate chain")}, 
218     { aListSigs,   "check-sigs",256, "@"},
219     { oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
220     { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
221     { aKeygen,     "gen-key",  256, N_("generate a new key pair")},
222     { aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
223     { aSendKeys, "send-keys"     , 256, N_("export keys to a key server") },
224     { aRecvKeys, "recv-keys"     , 256, N_("import keys from a key server") },
225     { aImport, "import",      256     , N_("import certificates")},
226     { aExport, "export",      256     , N_("export certificates")},
227     { aLearnCard, "learn-card", 256 ,N_("register a smartcard")},
228     { aServer, "server",      256, N_("run in server mode")},
229     { oLogFile, "log-file"   ,2, N_("use a log file for the server")},
230     
231
232     { 301, NULL, 0, N_("@\nOptions:\n ") },
233
234     { oArmor, "armor",     0, N_("create ascii armored output")},
235     { oArmor, "armour",    0, "@" },
236     { oBase64, "base64",    0, N_("create base-64 encoded output")},
237     
238     { oAssumeArmor,  "assume-armor", 0, N_("assume input is in PEM format")},
239     { oAssumeBase64, "assume-base64", 0,
240                                       N_("assume input is in base-64 format")},
241     { oAssumeBinary, "assume-binary", 0,
242                                       N_("assume input is in binary format")},
243
244     { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")},
245
246
247     { oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")},
248     { oEnableCRLChecks, "enable-crl-checks", 0, "@"},
249
250     { oIncludeCerts, "include-certs", 1,
251                                  N_("|N|number of certificates to include") },
252
253     { oPolicyFile, "policy-file", 2,
254                     N_("|FILE|take policy information from FILE") },
255
256     { oDisablePolicyChecks, "disable-policy-checks", 0,
257                            N_("do not check certificate policies")},
258     { oEnablePolicyChecks, "enable-policy-checks", 0, "@"},
259
260 #if 0
261     { oDefRecipient, "default-recipient" ,2,
262                                   N_("|NAME|use NAME as default recipient")},
263     { oDefRecipientSelf, "default-recipient-self" ,0,
264                                 N_("use the default key as default recipient")},
265     { oNoDefRecipient, "no-default-recipient", 0, "@" },
266     { oEncryptTo, "encrypt-to", 2, "@" },
267     { oNoEncryptTo, "no-encrypt-to", 0, "@" },
268
269 #endif
270     { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
271
272 #if 0
273     { oCompress, NULL,        1, N_("|N|set compress level N (0 disables)") },
274     { oTextmodeShort, NULL,   0, "@"},
275     { oTextmode, "textmode",  0, N_("use canonical text mode")},
276 #endif
277
278     { oOutput, "output",    2, N_("use as output file")},
279     { oVerbose, "verbose",   0, N_("verbose") },
280     { oQuiet,   "quiet",   0, N_("be somewhat more quiet") },
281     { oNoTTY, "no-tty", 0, N_("don't use the terminal at all") },
282 #if 0
283     { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") },
284     { oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") },
285 #endif
286     { oDryRun, "dry-run",   0, N_("do not make any changes") },
287   /*{ oInteractive, "interactive", 0, N_("prompt before overwriting") }, */
288     /*{ oUseAgent, "use-agent",0, N_("use the gpg-agent")},*/
289     { oBatch, "batch",     0, N_("batch mode: never ask")},
290     { oAnswerYes, "yes",       0, N_("assume yes on most questions")},
291     { oAnswerNo,  "no",        0, N_("assume no on most questions")},
292
293     { oKeyring, "keyring"   ,2, N_("add this keyring to the list of keyrings")},
294     { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
295     { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
296     { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")},
297     { oCharset, "charset"   , 2, N_("|NAME|set terminal charset to NAME") },
298     { oOptions, "options"   , 2, N_("read options from file")},
299
300     { oDebug, "debug"     ,4|16, "@"},
301     { oDebugAll, "debug-all" ,0, "@"},
302     { oDebugWait, "debug-wait" ,1, "@"},
303     { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
304     { aDummy, "no-comment", 0,   "@"},
305     { aDummy, "completes-needed", 1, "@"},
306     { aDummy, "marginals-needed", 1, "@"},
307     { oMaxCertDepth,    "max-cert-depth", 1, "@" },
308     { aDummy, "trusted-key", 2, "@"},
309     { oLoadExtension, "load-extension" ,2,
310       N_("|FILE|load extension module FILE")},
311     { aDummy, "rfc1991",   0, "@"},
312     { aDummy, "openpgp",   0, "@"},
313     { aDummy, "s2k-mode",  1, "@"},
314     { aDummy, "s2k-digest-algo",2, "@"},
315     { aDummy, "s2k-cipher-algo",2, "@"},
316     { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
317     { oDigestAlgo, "digest-algo", 2 ,
318       N_("|NAME|use message digest algorithm NAME")},
319 #if 0
320     { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
321 #endif
322     { aDummy, "throw-keyid", 0, "@"},
323     { aDummy, "notation-data", 2, "@"},
324
325     { 302, NULL, 0, N_(
326   "@\n(See the man page for a complete listing of all commands and options)\n"
327                       )},
328
329     { 303, NULL, 0, N_("@\nExamples:\n\n"
330     " -se -r Bob [file]          sign and encrypt for user Bob\n"
331     " --clearsign [file]         make a clear text signature\n"
332     " --detach-sign [file]       make a detached signature\n"
333     " --list-keys [names]        show keys\n"
334     " --fingerprint [names]      show fingerprints\n"  ) },
335
336   /* hidden options */
337     { oNoVerbose, "no-verbose", 0, "@"},
338
339     { oEnableSpecialFilenames, "enable-special-filenames", 0, "@" },
340
341
342     { oTrustDBName, "trustdb-name", 2, "@" },
343     { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, 
344     { oNoArmor, "no-armor",   0, "@"},
345     { oNoArmor, "no-armour",   0, "@"},
346     { oNoDefKeyring, "no-default-keyring", 0, "@" },
347     { oNoGreeting, "no-greeting", 0, "@" },
348     { oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */
349     { oHomedir, "homedir", 2, "@" },   /* defaults to "~/.gnupg" */
350     { oAgentProgram, "agent-program", 2 , "@" },
351     { oDisplay,    "display",     2, "@" },
352     { oTTYname,    "ttyname",     2, "@" },
353     { oTTYtype,    "ttytype",     2, "@" },
354     { oLCctype,    "lc-ctype",    2, "@" },
355     { oLCmessages, "lc-messages", 2, "@" },
356     { oDirmngrProgram, "dirmngr-program", 2 , "@" },
357     { oFakedSystemTime, "faked-system-time", 4, "@" }, /* (epoch time) */
358
359
360     { oNoBatch, "no-batch", 0, "@" },
361     { oWithColons, "with-colons", 0, "@"},
362     { oWithKeyData,"with-key-data", 0, "@"},
363     { aListKeys, "list-key", 0, "@" }, /* alias */
364     { aListSigs, "list-sig", 0, "@" }, /* alias */
365     { aListSigs, "check-sig",0, "@" }, /* alias */
366     { oSkipVerify, "skip-verify",0, "@" },
367     { oCompressKeys, "compress-keys",0, "@"},
368     { oCompressSigs, "compress-sigs",0, "@"},
369     { oAlwaysTrust, "always-trust", 0, "@"},
370     { oNoVersion, "no-version", 0, "@"},
371     { oLockOnce, "lock-once", 0, "@" },
372     { oLockMultiple, "lock-multiple", 0, "@" },
373     { oLockNever, "lock-never", 0, "@" },
374     { oLoggerFD, "logger-fd",1, "@" },
375     { oWithFingerprint, "with-fingerprint", 0, "@" },
376     { oDisableCipherAlgo,  "disable-cipher-algo", 2, "@" },
377     { oDisablePubkeyAlgo,  "disable-pubkey-algo", 2, "@" },
378     { oHonorHttpProxy,"honor-http-proxy", 0, "@" },
379     { oListOnly, "list-only", 0, "@"},
380     { oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" },
381     { oNoRandomSeedFile,  "no-random-seed-file", 0, "@" },
382 {0} };
383
384
385
386 int gpgsm_errors_seen = 0;
387
388 /* It is possible that we are currentlu running under setuid permissions */
389 static int maybe_setuid = 1;
390
391 /* Option --enable-special-filenames */
392 static int allow_special_filenames;
393
394
395 static char *build_list (const char *text,
396                          const char *(*mapf)(int), int (*chkf)(int));
397 static void set_cmd (enum cmd_and_opt_values *ret_cmd,
398                      enum cmd_and_opt_values new_cmd );
399
400 static int check_special_filename (const char *fname);
401 static int open_read (const char *filename);
402 static FILE *open_fwrite (const char *filename);
403
404
405 static int
406 our_pk_test_algo (int algo)
407 {
408   return 1;
409 }
410
411 static int
412 our_cipher_test_algo (int algo)
413 {
414   return 1;
415 }
416
417 static int
418 our_md_test_algo (int algo)
419 {
420   return 1;
421 }
422
423 static const char *
424 my_strusage( int level )
425 {
426   static char *digests, *pubkeys, *ciphers;
427   const char *p;
428
429   switch (level)
430     {
431     case 11: p = "gpgsm (GnuPG)";
432       break;
433     case 13: p = VERSION; break;
434     case 17: p = PRINTABLE_OS_NAME; break;
435     case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
436       break;
437     case 1:
438     case 40: p = _("Usage: gpgsm [options] [files] (-h for help)");
439       break;
440     case 41:
441       p = _("Syntax: gpgsm [options] [files]\n"
442             "sign, check, encrypt or decrypt using the S/MIME protocol\n"
443             "default operation depends on the input data\n");
444       break;
445
446     case 31: p = "\nHome: "; break;
447     case 32: p = opt.homedir; break;
448     case 33: p = _("\nSupported algorithms:\n"); break;
449     case 34:
450       if (!ciphers)
451         ciphers = build_list ("Cipher: ", gcry_cipher_algo_name,
452                               our_cipher_test_algo );
453       p = ciphers;
454       break;
455     case 35:
456       if (!pubkeys)
457         pubkeys = build_list ("Pubkey: ", gcry_pk_algo_name,
458                               our_pk_test_algo );
459       p = pubkeys;
460       break;
461     case 36:
462       if (!digests)
463         digests = build_list("Hash: ", gcry_md_algo_name, our_md_test_algo );
464       p = digests;
465       break;
466       
467     default: p = NULL; break;
468     }
469   return p;
470 }
471
472
473 static char *
474 build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int))
475 {
476   int i;
477   size_t n=strlen(text)+2;
478   char *list, *p;
479   
480   if (maybe_setuid) {
481     gcry_control (GCRYCTL_DROP_PRIVS); /* drop setuid */
482   }
483
484   for (i=1; i < 110; i++ )
485     if (!chkf(i))
486       n += strlen(mapf(i)) + 2;
487   list = xmalloc (21 + n);
488   *list = 0;
489   for (p=NULL, i=1; i < 110; i++)
490     {
491       if (!chkf(i))
492         {
493           if( !p )
494             p = stpcpy (list, text );
495           else
496             p = stpcpy (p, ", ");
497           p = stpcpy (p, mapf(i) );
498         }
499     }
500   if (p)
501     p = stpcpy(p, "\n" );
502   return list;
503 }
504
505
506 static void
507 i18n_init(void)
508 {
509 #ifdef USE_SIMPLE_GETTEXT
510   set_gettext_file (PACKAGE);
511 #else
512 # ifdef ENABLE_NLS
513 #  ifdef HAVE_LC_MESSAGES
514   setlocale (LC_TIME, "");
515   setlocale (LC_MESSAGES, "");
516 #  else
517   setlocale (LC_ALL, "" );
518 #  endif
519   bindtextdomain (PACKAGE, GNUPG_LOCALEDIR);
520   textdomain (PACKAGE);
521 # endif
522 #endif
523 }
524
525
526 static void
527 wrong_args (const char *text)
528 {
529   fputs (_("usage: gpgsm [options] "), stderr);
530   fputs (text, stderr);
531   putc ('\n', stderr);
532   gpgsm_exit (2);
533 }
534
535
536 static void
537 set_debug(void)
538 {
539   if (opt.debug & DBG_MPI_VALUE)
540     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
541   if (opt.debug & DBG_CRYPTO_VALUE )
542     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
543 }
544
545
546 static void
547 set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
548 {
549   enum cmd_and_opt_values cmd = *ret_cmd;
550
551   if (!cmd || cmd == new_cmd)
552     cmd = new_cmd;
553   else if ( cmd == aSign && new_cmd == aEncr )
554     cmd = aSignEncr;
555   else if ( cmd == aEncr && new_cmd == aSign )
556     cmd = aSignEncr;
557   else if ( (cmd == aSign && new_cmd == aClearsign)
558             || (cmd == aClearsign && new_cmd == aSign) )
559     cmd = aClearsign;
560   else 
561     {
562       log_error(_("conflicting commands\n"));
563       gpgsm_exit(2);
564     }
565
566   *ret_cmd = cmd;
567 }
568
569
570 int
571 main ( int argc, char **argv)
572 {
573   ARGPARSE_ARGS pargs;
574   int orig_argc;
575   char **orig_argv;
576   const char *fname;
577   /*  char *username;*/
578   int may_coredump;
579   STRLIST sl, remusr= NULL, locusr=NULL;
580   STRLIST nrings=NULL;
581   int detached_sig = 0;
582   FILE *configfp = NULL;
583   char *configname = NULL;
584   unsigned configlineno;
585   int parse_debug = 0;
586   int default_config =1;
587   int default_keyring = 1;
588   char *logfile = NULL;
589   int greeting = 0;
590   int nogreeting = 0;
591   int debug_wait = 0;
592   int use_random_seed = 1;
593   int with_fpr = 0;
594   char *def_digest_string = NULL;
595   enum cmd_and_opt_values cmd = 0;
596   struct server_control_s ctrl;
597   CERTLIST recplist = NULL;
598
599   /* trap_unaligned ();*/
600   set_strusage (my_strusage);
601   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
602   /* Please note that we may running SUID(ROOT), so be very CAREFUL
603      when adding any stuff between here and the call to secmem_init()
604      somewhere after the option parsing */
605   log_set_prefix ("gpgsm", 1);
606   /* check that the libraries are suitable.  Do it here because the
607      option parse may need services of the library */
608   if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
609     {
610       log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
611                  NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
612     }
613   if (!ksba_check_version (NEED_LIBKSBA_VERSION) )
614     {
615       log_fatal( _("libksba is too old (need %s, have %s)\n"),
616                  NEED_LIBKSBA_VERSION, ksba_check_version (NULL) );
617     }
618
619   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
620
621   may_coredump = disable_core_dumps ();
622   
623   /* Fixme: init_signals();*/
624   
625   create_dotlock (NULL); /* register locking cleanup */
626   i18n_init();
627
628   opt.def_cipher_algoid = "1.2.840.113549.3.7";  /*des-EDE3-CBC*/
629 #ifdef __MINGW32__
630   opt.homedir = read_w32_registry_string ( NULL,
631                                            "Software\\GNU\\GnuPG", "HomeDir" );
632 #else
633   opt.homedir = getenv ("GNUPGHOME");
634 #endif
635   if (!opt.homedir || !*opt.homedir ) 
636     {
637       opt.homedir = "~/.gnupg-test" /*fixme: GNUPG_HOMEDIR*/;
638     }
639
640   /* first check whether we have a config file on the commandline */
641   orig_argc = argc;
642   orig_argv = argv;
643   pargs.argc = &argc;
644   pargs.argv = &argv;
645   pargs.flags= 1|(1<<6);  /* do not remove the args, ignore version */
646   while (arg_parse( &pargs, opts))
647     {
648       if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
649         parse_debug++;
650       else if (pargs.r_opt == oOptions)
651         { /* yes there is one, so we do not try the default one but
652              read the config file when it is encountered at the
653              commandline */
654           default_config = 0;
655         }
656       else if (pargs.r_opt == oNoOptions)
657         default_config = 0; /* --no-options */
658       else if (pargs.r_opt == oHomedir)
659         opt.homedir = pargs.r.ret_str;
660     }
661   
662   
663   /* initialize the secure memory. */
664   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
665   maybe_setuid = 0;
666
667   /* 
668      Now we are now working under our real uid 
669   */
670
671   ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
672   assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
673   keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
674
675   /* Setup a default control structure for command line mode */
676   memset (&ctrl, 0, sizeof ctrl);
677   gpgsm_init_default_ctrl (&ctrl);
678   ctrl.no_server = 1;
679   ctrl.status_fd = -1; /* not status output */
680   ctrl.autodetect_encoding = 1;
681
682   /* set the default option file */
683   if (default_config )
684     configname = make_filename (opt.homedir, "gpgsm.conf", NULL);
685   /* cet the default policy file */
686   opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL);
687   
688   argc        = orig_argc;
689   argv        = orig_argv;
690   pargs.argc  = &argc;
691   pargs.argv  = &argv;
692   pargs.flags =  1;  /* do not remove the args */
693
694  next_pass:
695   if (configname) {
696     configlineno = 0;
697     configfp = fopen (configname, "r");
698     if (!configfp)
699       {
700         if (default_config)
701           {
702             if (parse_debug)
703               log_info (_("NOTE: no default option file `%s'\n"), configname);
704           }
705         else 
706           {
707             log_error (_("option file `%s': %s\n"), configname, strerror(errno));
708             gpgsm_exit(2);
709           }
710         xfree(configname);
711         configname = NULL;
712       }
713     if (parse_debug && configname)
714       log_info (_("reading options from `%s'\n"), configname);
715     default_config = 0;
716   }
717
718   while (optfile_parse (configfp, configname, &configlineno, &pargs, opts))
719     {
720       switch (pargs.r_opt)
721         {
722         case aServer: 
723           opt.batch = 1;
724           set_cmd (&cmd, aServer);
725           break;
726
727         case aCheckKeys: set_cmd (&cmd, aCheckKeys); break;
728         case aImport: set_cmd (&cmd, aImport); break;
729         case aSendKeys: set_cmd (&cmd, aSendKeys); break;
730         case aRecvKeys: set_cmd (&cmd, aRecvKeys); break;
731         case aExport: set_cmd (&cmd, aExport); break;
732         case aListKeys: set_cmd (&cmd, aListKeys); break;
733         case aListSecretKeys: set_cmd (&cmd, aListSecretKeys); break;
734         case aListSigs: set_cmd (&cmd, aListSigs); break;
735
736         case aLearnCard: set_cmd (&cmd, aLearnCard); break;
737
738         case aDeleteKey:
739           set_cmd (&cmd, aDeleteKey);
740           greeting=1;
741           break;
742
743         case aDetachedSign:
744           detached_sig = 1;
745           set_cmd (&cmd, aSign ); 
746           break;
747           
748         case aSym: set_cmd (&cmd, aSym); break;
749         case aDecrypt: set_cmd (&cmd, aDecrypt); break;
750         case aEncr: set_cmd (&cmd, aEncr); break;
751         case aSign: set_cmd (&cmd, aSign );  break;
752         case aKeygen: set_cmd (&cmd, aKeygen); greeting=1; break;
753         case aClearsign: set_cmd (&cmd, aClearsign); break;
754         case aVerify: set_cmd (&cmd, aVerify); break;
755
756
757           /* output encoding selection */
758         case oArmor:
759           ctrl.create_pem = 1;
760           break;
761         case oBase64: 
762           ctrl.create_pem = 0;
763           ctrl.create_base64 = 1;
764           break;
765         case oNoArmor: 
766           ctrl.create_pem = 0;
767           ctrl.create_base64 = 0;
768           break;
769           
770           /* Input encoding selection */
771         case oAssumeArmor:
772           ctrl.autodetect_encoding = 0;
773           ctrl.is_pem = 1;
774           ctrl.is_base64 = 0;
775           break;
776         case oAssumeBase64:
777           ctrl.autodetect_encoding = 0;
778           ctrl.is_pem = 0;
779           ctrl.is_base64 = 1;
780           break;
781         case oAssumeBinary:
782           ctrl.autodetect_encoding = 0;
783           ctrl.is_pem = 0;
784           ctrl.is_base64 = 0;
785           break;
786
787         case oDisableCRLChecks:
788           opt.no_crl_check = 1;
789           break;
790         case oEnableCRLChecks:
791           opt.no_crl_check = 0;
792           break;
793
794         case oIncludeCerts: ctrl.include_certs = pargs.r.ret_int; break;
795
796         case oPolicyFile:
797           xfree (opt.policy_file);
798           if (*pargs.r.ret_str)
799             opt.policy_file = xstrdup (pargs.r.ret_str);
800           else
801             opt.policy_file = NULL;
802           break;
803
804         case oDisablePolicyChecks:
805           opt.no_policy_check = 1;
806           break;
807         case oEnablePolicyChecks:
808           opt.no_policy_check = 0;
809           break;
810
811
812         case oOutput: opt.outfile = pargs.r.ret_str; break;
813
814         
815         case oQuiet: opt.quiet = 1; break;
816         case oNoTTY: /* fixme:tty_no_terminal(1);*/ break;
817         case oDryRun: opt.dry_run = 1; break;
818
819         case oVerbose:
820           opt.verbose++;
821           gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
822           break;
823         case oNoVerbose:
824           opt.verbose = 0;
825           gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
826           break;
827
828         case oLogFile: logfile = pargs.r.ret_str; break;
829           
830         case oBatch: 
831           opt.batch = 1;
832           greeting = 0;
833           break;
834         case oNoBatch: opt.batch = 0; break;
835           
836         case oAnswerYes: opt.answer_yes = 1; break;
837         case oAnswerNo: opt.answer_no = 1; break;
838
839         case oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break;
840
841         case oDebug: opt.debug |= pargs.r.ret_ulong; break;
842         case oDebugAll: opt.debug = ~0; break;
843         case oDebugWait: debug_wait = pargs.r.ret_int; break;
844
845         case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
846         case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
847         case oWithFingerprint:
848           with_fpr=1; /*fall thru*/
849         case oFingerprint:
850           opt.fingerprint++;
851           break;
852
853         case oOptions:
854           /* config files may not be nested (silently ignore them) */
855           if (!configfp)
856             {
857               xfree(configname);
858               configname = xstrdup (pargs.r.ret_str);
859               goto next_pass;
860             }
861           break;
862         case oNoOptions: break; /* no-options */
863         case oHomedir: opt.homedir = pargs.r.ret_str; break;
864         case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
865         case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
866         case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
867         case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
868         case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
869         case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
870         case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str;  break;
871           
872         case oFakedSystemTime:
873           gnupg_set_time ( (time_t)pargs.r.ret_ulong, 0);
874           break;
875
876         case oNoDefKeyring: default_keyring = 0; break;
877         case oNoGreeting: nogreeting = 1; break;
878
879         case oDefaultKey:
880           /* fixme:opt.def_secret_key = pargs.r.ret_str;*/
881           break;
882         case oDefRecipient:
883           if (*pargs.r.ret_str)
884             opt.def_recipient = xstrdup (pargs.r.ret_str);
885           break;
886         case oDefRecipientSelf:
887           xfree (opt.def_recipient);
888           opt.def_recipient = NULL;
889           opt.def_recipient_self = 1;
890           break;
891         case oNoDefRecipient:
892           xfree (opt.def_recipient);
893           opt.def_recipient = NULL;
894           opt.def_recipient_self = 0;
895           break;
896
897         case oWithKeyData: opt.with_key_data=1; /* fall thru */
898         case oWithColons: ctrl.with_colons = 1; break;
899
900         case oSkipVerify: opt.skip_verify=1; break;
901
902         case oNoEncryptTo: /*fixme: opt.no_encrypt_to = 1;*/ break;
903         case oEncryptTo: /* store the recipient in the second list */
904           sl = add_to_strlist (&remusr, pargs.r.ret_str);
905           sl->flags = 1;
906           break;
907
908         case oRecipient: /* store the recipient */
909           add_to_strlist ( &remusr, pargs.r.ret_str);
910           break;
911
912         case oTextmodeShort: /*fixme:opt.textmode = 2;*/ break;
913         case oTextmode: /*fixme:opt.textmode=1;*/  break;
914
915         case oUser: /* store the local users */
916           opt.local_user = pargs.r.ret_str;
917           add_to_strlist ( &locusr, pargs.r.ret_str);
918           break;
919
920         case oNoSecmemWarn:
921           gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); 
922           break;
923
924         case oCipherAlgo:
925           opt.def_cipher_algoid = pargs.r.ret_str;
926           break;
927
928         case oDisableCipherAlgo: 
929           {
930             int algo = gcry_cipher_map_name (pargs.r.ret_str);
931             gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo);
932           }
933           break;
934         case oDisablePubkeyAlgo: 
935           {
936             int algo = gcry_pk_map_name (pargs.r.ret_str);
937             gcry_pk_ctl (GCRYCTL_DISABLE_ALGO,&algo, sizeof algo );
938           }
939           break;
940
941         case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
942         case oNoRandomSeedFile: use_random_seed = 0; break;
943
944         case oEnableSpecialFilenames: allow_special_filenames =1; break;
945           
946
947         case aDummy:
948           break;
949         default: 
950           pargs.err = configfp? 1:2; 
951           break;
952         }
953     }
954
955   if (configfp)
956     {
957       fclose (configfp);
958       configfp = NULL;
959       xfree (configname);
960       configname = NULL;
961       goto next_pass;
962     }
963   
964   xfree (configname);
965   configname = NULL;
966
967   if (log_get_errorcount(0))
968     gpgsm_exit(2);
969   
970   if (nogreeting)
971     greeting = 0;
972   
973   if (greeting)
974     {
975       fprintf(stderr, "%s %s; %s\n",
976               strusage(11), strusage(13), strusage(14) );
977       fprintf(stderr, "%s\n", strusage(15) );
978     }
979 #  ifdef IS_DEVELOPMENT_VERSION
980   if (!opt.batch)
981     {
982       log_info ("NOTE: THIS IS A DEVELOPMENT VERSION!\n");
983       log_info ("It is only intended for test purposes and should NOT be\n");
984       log_info ("used in a production environment or with production keys!\n");
985     }
986 #  endif
987
988   if (may_coredump && !opt.quiet)
989     log_info (_("WARNING: program may create a core file!\n"));
990
991   if (logfile)
992     {
993       log_set_file (logfile);
994       log_set_prefix (NULL, 1|2|4);
995     }
996
997   if (gnupg_faked_time_p ())
998     {
999       log_info (_("WARNING: running with faked system time: "));
1000       gpgsm_dump_time (gnupg_get_time ());
1001       log_printf ("\n");
1002     }
1003   
1004 /*FIXME    if (opt.batch) */
1005 /*      tty_batchmode (1); */
1006
1007   gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
1008
1009   set_debug ();
1010
1011   /* FIXME: should set filenames of libgcrypt explicitly
1012    * gpg_opt_homedir = opt.homedir; */
1013
1014   /* must do this after dropping setuid, because the mapping functions
1015      may try to load an module and we may have disabled an algorithm */
1016   if ( !gcry_cipher_map_name (opt.def_cipher_algoid)
1017        || !gcry_cipher_mode_from_oid (opt.def_cipher_algoid))
1018     log_error (_("selected cipher algorithm is invalid\n"));
1019
1020   if (def_digest_string)
1021     {
1022       opt.def_digest_algo = gcry_md_map_name (def_digest_string);
1023       xfree (def_digest_string);
1024       def_digest_string = NULL;
1025       if (our_md_test_algo(opt.def_digest_algo) )
1026         log_error (_("selected digest algorithm is invalid\n"));
1027     }
1028
1029   if (log_get_errorcount(0))
1030     gpgsm_exit(2);
1031   
1032   /* set the random seed file */
1033   if (use_random_seed) {
1034     char *p = make_filename (opt.homedir, "random_seed", NULL);
1035 #if 0
1036 #warning set_random_seed_file not yet available in Libgcrypt
1037     set_random_seed_file(p);
1038 #endif
1039     xfree(p);
1040   }
1041
1042
1043   if (!cmd && opt.fingerprint && !with_fpr)
1044     set_cmd (&cmd, aListKeys);
1045   
1046   if (!nrings && default_keyring)  /* add default keybox */
1047     keydb_add_resource ("pubring.kbx", 0, 0);
1048   for (sl = nrings; sl; sl = sl->next)
1049     keydb_add_resource (sl->d, 0, 0);
1050   FREE_STRLIST(nrings);
1051
1052   for (sl = remusr; sl; sl = sl->next)
1053     {
1054       int rc = gpgsm_add_to_certlist (sl->d, &recplist);
1055       if (rc)
1056         {
1057           log_error (_("can't encrypt to `%s': %s\n"),
1058                      sl->d, gnupg_strerror (rc));
1059           gpgsm_status2 (&ctrl, STATUS_INV_RECP,
1060                          rc == -1? "1":
1061                          rc == GNUPG_Ambiguous_Name? "2 ": "0 ",
1062                          sl->d, NULL);
1063         }
1064   }
1065   if (log_get_errorcount(0))
1066     gpgsm_exit(1); /* must stop for invalid recipients */
1067   
1068
1069   
1070   fname = argc? *argv : NULL;
1071   
1072   switch (cmd)
1073     {
1074     case aServer:
1075       if (debug_wait)
1076         {
1077           log_debug ("waiting for debugger - my pid is %u .....\n",
1078                      (unsigned int)getpid());
1079           sleep (debug_wait);
1080           log_debug ("... okay\n");
1081          }
1082       gpgsm_server ();
1083       break;
1084
1085     case aEncr: /* encrypt the given file */
1086       if (!argc)
1087         gpgsm_encrypt (&ctrl, recplist, 0, stdout); /* from stdin */
1088       else if (argc == 1)
1089         gpgsm_encrypt (&ctrl, recplist, open_read (*argv), stdout); /* from file */
1090       else
1091         wrong_args (_("--encrypt [datafile]"));
1092       break;
1093
1094     case aSign: /* sign the given file */
1095       /* FIXME: W we don't handle --output yet. We should also allow
1096          to concatenate multiple files for signing because that is
1097          what gpg does.*/
1098       if (!argc)
1099         gpgsm_sign (&ctrl, 0, detached_sig, stdout); /* create from stdin */
1100       else if (argc == 1)
1101         gpgsm_sign (&ctrl, open_read (*argv),
1102                     detached_sig, stdout); /* from file */
1103       else
1104         wrong_args (_("--sign [datafile]"));
1105       break;
1106 #if 0
1107       sl = NULL;
1108       if (detached_sig)
1109         { /* sign all files */
1110           for (; argc; argc--, argv++ )
1111             add_to_strlist ( &sl, *argv );
1112         }
1113       else
1114         {
1115           if (argc > 1 )
1116             wrong_args (_("--sign [filename]"));
1117           if (argc)
1118             {
1119               sl = xcalloc (1, sizeof *sl + strlen(fname));
1120               strcpy(sl->d, fname);
1121             }
1122         }
1123       if ( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) )
1124         log_error ("signing failed: %s\n", gpg_errstr(rc) );
1125       free_strlist(sl);
1126 #endif
1127       break;
1128         
1129     case aSignEncr: /* sign and encrypt the given file */
1130       log_error ("this command has not yet been implemented\n");
1131 #if 0
1132       if (argc > 1)
1133         wrong_args(_("--sign --encrypt [filename]"));
1134       if (argc)
1135         {
1136           sl = xcalloc( 1, sizeof *sl + strlen(fname));
1137           strcpy(sl->d, fname);
1138         }
1139       else
1140         sl = NULL;
1141
1142       if ( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
1143         log_error ("%s: sign+encrypt failed: %s\n",
1144                    print_fname_stdin(fname), gpg_errstr(rc) );
1145       free_strlist(sl);
1146 #endif
1147       break;
1148
1149     case aClearsign: /* make a clearsig */
1150       log_error ("this command has not yet been implemented\n");
1151 #if 0
1152       if (argc > 1)
1153         wrong_args (_("--clearsign [filename]"));
1154       if ( (rc = clearsign_file(fname, locusr, NULL)) )
1155         log_error ("%s: clearsign failed: %s\n",
1156                    print_fname_stdin(fname), gpg_errstr(rc) );
1157 #endif
1158       break;
1159
1160     case aVerify:
1161       {
1162         FILE *fp = NULL;
1163
1164         if (argc == 2 && *opt.outfile)
1165           log_info ("option --output ignored for a detached signature\n");
1166         else if (opt.outfile)
1167           fp = open_fwrite (opt.outfile);
1168
1169         if (!argc)
1170           gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */
1171         else if (argc == 1)
1172           gpgsm_verify (&ctrl, open_read (*argv), -1, fp); /* std signature */
1173         else if (argc == 2) /* detached signature (sig, detached) */
1174           gpgsm_verify (&ctrl, open_read (*argv), open_read (argv[1]), NULL); 
1175         else
1176           wrong_args (_("--verify [signature [detached_data]]"));
1177
1178         if (fp && fp != stdout)
1179           fclose (fp);
1180       }
1181       break;
1182
1183     case aVerifyFiles:
1184       log_error ("this command has not yet been implemented\n");
1185 /*        if ((rc = verify_files( argc, argv ))) */
1186 /*          log_error ("verify files failed: %s\n", gpg_errstr(rc) ); */
1187       break;
1188
1189     case aDecrypt:
1190       if (!argc)
1191         gpgsm_decrypt (&ctrl, 0, stdout); /* from stdin */
1192       else if (argc == 1)
1193         gpgsm_decrypt (&ctrl, open_read (*argv), stdout); /* from file */
1194       else
1195         wrong_args (_("--decrypt [filename]"));
1196       break;
1197
1198     case aDeleteKey:
1199       if (argc != 1)
1200         wrong_args(_("--delete-key user-id"));
1201       log_error ("this command has not yet been implemented\n");
1202 /*        username = make_username (fname); */
1203 /*        if( (rc = delete_key(username)) ) */
1204 /*          log_error ("%s: delete key failed: %s\n", username, gpg_errstr(rc) ); */
1205 /*        xfree(username); */
1206       break;
1207
1208     case aListSigs:
1209       ctrl.with_chain = 1;
1210     case aListKeys:
1211       for (sl=NULL; argc; argc--, argv++)
1212         add_to_strlist (&sl, *argv);
1213       gpgsm_list_keys (&ctrl, sl, stdout, (0 | (1<<6)));
1214       free_strlist(sl);
1215       break;
1216
1217     case aListSecretKeys:
1218       for (sl=NULL; argc; argc--, argv++)
1219         add_to_strlist (&sl, *argv);
1220       gpgsm_list_keys (&ctrl, sl, stdout, (2 | (1<<6)));
1221       free_strlist(sl);
1222       break;
1223
1224     case aKeygen: /* generate a key */
1225       log_error ("this function is not yet available from the commandline\n");
1226 /*        if (opt.batch) */
1227 /*          { */
1228 /*            if (argc > 1) */
1229 /*              wrong_args("--gen-key [parameterfile]"); */
1230 /*            generate_keypair (argc? *argv : NULL); */
1231 /*      } */
1232 /*        else */
1233 /*          { */
1234 /*            if (argc) */
1235 /*              wrong_args ("--gen-key"); */
1236 /*            generate_keypair(NULL); */
1237 /*      } */
1238       break;
1239
1240     case aImport:
1241       if (!argc)
1242         gpgsm_import (&ctrl, 0);
1243       else
1244         {
1245           for (; argc; argc--, argv++)
1246             gpgsm_import (&ctrl, open_read (*argv));
1247         }
1248       break;
1249
1250     case aExport:
1251       for (sl=NULL; argc; argc--, argv++)
1252         add_to_strlist (&sl, *argv);
1253       gpgsm_export (&ctrl, sl, stdout);
1254       free_strlist(sl);
1255       break;
1256
1257       
1258     case aSendKeys:
1259     case aRecvKeys:
1260       log_error ("this command has not yet been implemented\n");
1261 /*        sl = NULL; */
1262 /*        for ( ; argc; argc--, argv++ ) */
1263 /*          add_to_strlist (&sl, *argv); */
1264 /*        if ( cmd == aSendKeys ) */
1265 /*          ldap_export (sl); */
1266 /*        else if (cmd == aRecvKeys ) */
1267 /*          ldap_import (sl); */
1268 /*        else */
1269 /*          export_pubkeys (sl, (cmd == aExport)); */
1270 /*        free_strlist (sl); */
1271       break;
1272
1273
1274     case aLearnCard:
1275       if (argc)
1276         wrong_args ("--learn-card");
1277       else
1278         {
1279           int rc = gpgsm_agent_learn ();
1280           if (rc)
1281             log_error ("error learning card: %s\n", gnupg_strerror (rc));
1282         }
1283       break;
1284
1285
1286     default:
1287         log_error ("invalid command\n");
1288 #if 0
1289         if (argc > 1)
1290           wrong_args(_("[filename]"));
1291         /* Issue some output for the unix newbie */
1292         if ( !fname && !opt.outfile && isatty( fileno(stdin) )
1293             && isatty (fileno(stdout) ) && isatty (fileno(stderr) ) )
1294           log_info (_("Go ahead and type your message ...\n"));
1295         
1296         if ( !(a = iobuf_open(fname)) )
1297           log_error (_("can't open `%s'\n"), print_fname_stdin(fname));
1298         else
1299           {
1300             if (!opt.no_armor) 
1301               iobuf_close(a);
1302         }
1303 #endif
1304         break;
1305     }
1306   
1307   /* cleanup */
1308   gpgsm_release_certlist (recplist);
1309   FREE_STRLIST(remusr);
1310   FREE_STRLIST(locusr);
1311   gpgsm_exit(0);
1312   return 8; /*NEVER REACHED*/
1313 }
1314
1315
1316 void
1317 gpgsm_exit (int rc)
1318 {
1319   #if 0
1320 #warning no update_random_seed_file
1321   update_random_seed_file();
1322   #endif
1323 #if 0
1324   /* at this time a bit annoying */
1325   if (opt.debug & DBG_MEMSTAT_VALUE)
1326     {
1327       gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
1328       gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
1329     }
1330   if (opt.debug)
1331     gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
1332 #endif
1333   gcry_control (GCRYCTL_TERM_SECMEM );
1334   rc = rc? rc : log_get_errorcount(0)? 2 : gpgsm_errors_seen? 1 : 0;
1335   exit (rc);
1336 }
1337
1338
1339 void
1340 gpgsm_init_default_ctrl (struct server_control_s *ctrl)
1341 {
1342   ctrl->include_certs = 1;  /* only include the signer's cert */
1343 }
1344
1345
1346
1347 /* Check whether the filename has the form "-&nnnn", where n is a
1348    non-zero number.  Returns this number or -1 if it is not the case.  */
1349 static int
1350 check_special_filename (const char *fname)
1351 {
1352   if (allow_special_filenames
1353       && fname && *fname == '-' && fname[1] == '&' ) {
1354     int i;
1355     
1356     fname += 2;
1357     for (i=0; isdigit (fname[i]); i++ )
1358       ;
1359     if ( !fname[i] ) 
1360       return atoi (fname);
1361   }
1362   return -1;
1363 }
1364
1365
1366
1367 /* Open the FILENAME for read and return the filedescriptor.  Stop
1368    with an error message in case of problems.  "-" denotes stdin and
1369    if special filenames are allowed the given fd is opened instead. */
1370 static int 
1371 open_read (const char *filename)
1372 {
1373   int fd;
1374
1375   if (filename[0] == '-' && !filename[1])
1376     return 0; /* stdin */
1377   fd = check_special_filename (filename);
1378   if (fd != -1)
1379     return fd;
1380   fd = open (filename, O_RDONLY);
1381   if (fd == -1)
1382     {
1383       log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
1384       gpgsm_exit (2);
1385     }
1386   return fd;
1387 }
1388
1389 /* Open FILENAME for fwrite and return the stream.  Stop with an error
1390    message in case of problems.  "-" denotes stdout and if special
1391    filenames are allowed the given fd is opened instead. Caller must
1392    close the returned stream unless it is stdout. */
1393 static FILE *
1394 open_fwrite (const char *filename)
1395 {
1396   int fd;
1397   FILE *fp;
1398
1399   if (filename[0] == '-' && !filename[1])
1400     return stdout;
1401
1402   fd = check_special_filename (filename);
1403   if (fd != -1)
1404     {
1405       fp = fdopen (dup (fd), "wb");
1406       if (!fp)
1407         {
1408           log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
1409           gpgsm_exit (2);
1410         }
1411       return fp;
1412     }
1413   fp = fopen (filename, "wb");
1414   if (!fp)
1415     {
1416       log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
1417       gpgsm_exit (2);
1418     }
1419   return fp;
1420 }