6b4d05a7fb90fbf1abe2aa2d3952421bd98c3521
[gnupg.git] / g13 / g13.c
1 /* g13.c - Disk Key management with GnuPG
2  * Copyright (C) 2009 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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <pth.h>
29
30 #include "g13.h"
31
32 #include <gcrypt.h>
33 #include <assuan.h>
34
35 #include "i18n.h"
36 #include "sysutils.h"
37 #include "gc-opt-flags.h"
38 #include "keyblob.h"
39 #include "./runner.h"
40 #include "./create.h"
41 #include "./mount.h"
42
43
44 enum cmd_and_opt_values {
45   aNull = 0,
46   oQuiet        = 'q',
47   oVerbose      = 'v',
48
49   aGPGConfList  = 500,
50   aGPGConfTest,
51   aCreate,
52   aMount,
53   aUmount,
54
55   oOptions,
56   oDebug,
57   oDebugLevel,
58   oDebugAll,
59   oDebugNone,
60   oDebugWait,
61   oDebugAllowCoreDump,
62   oLogFile,
63   oNoLogFile,
64   oAuditLog,
65
66   oOutput,
67
68   oAgentProgram,
69   oGpgProgram,
70
71   oDisplay,
72   oTTYname,
73   oTTYtype,
74   oLCctype,
75   oLCmessages,
76   oXauthority,
77
78   oStatusFD,
79   oLoggerFD,
80
81   oNoVerbose,
82   oNoSecmemWarn,
83   oNoGreeting,
84   oNoTTY,
85   oNoOptions,
86   oHomedir,
87   oWithColons,
88   oDryRun,
89   oNoDetach,
90
91   oRecipient,
92
93   oNoRandomSeedFile,
94   oFakedSystemTime
95  };
96
97
98 static ARGPARSE_OPTS opts[] = {
99
100   ARGPARSE_group (300, N_("@Commands:\n ")),
101
102   ARGPARSE_c (aCreate, "create", N_("Create a new file system container")),
103   ARGPARSE_c (aMount,  "mount",  N_("Mount a file system container") ),
104   ARGPARSE_c (aUmount, "umount", N_("Unmount a file system container") ),
105
106   ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
107   ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
108
109   ARGPARSE_group (301, N_("@\nOptions:\n ")),
110
111   ARGPARSE_s_s (oRecipient, "recipient", N_("|USER-ID|encrypt for USER-ID")),
112
113   ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")),
114   ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
115   ARGPARSE_s_n (oQuiet, "quiet",  N_("be somewhat more quiet")),
116   ARGPARSE_s_n (oNoTTY, "no-tty", N_("don't use the terminal at all")),
117   ARGPARSE_s_n (oNoDetach, "no-detach", N_("do not detach from the console")),
118   ARGPARSE_s_s (oLogFile, "log-file",  N_("|FILE|write log output to FILE")),
119   ARGPARSE_s_n (oNoLogFile, "no-log-file", "@"),
120   ARGPARSE_s_i (oLoggerFD, "logger-fd", "@"),
121
122   ARGPARSE_s_s (oAuditLog, "audit-log",
123                 N_("|FILE|write an audit log to FILE")),
124   ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
125
126   ARGPARSE_s_s (oOptions, "options", N_("|FILE|read options from FILE")),
127
128   ARGPARSE_p_u (oDebug, "debug", "@"),
129   ARGPARSE_s_s (oDebugLevel, "debug-level",
130                 N_("|LEVEL|set the debugging level to LEVEL")),
131   ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
132   ARGPARSE_s_n (oDebugNone, "debug-none", "@"),
133   ARGPARSE_s_i (oDebugWait, "debug-wait", "@"),
134   ARGPARSE_s_n (oDebugAllowCoreDump, "debug-allow-core-dump", "@"),
135
136   ARGPARSE_s_i (oStatusFD, "status-fd",
137                 N_("|FD|write status info to this FD")),
138
139   ARGPARSE_group (302, N_(
140   "@\n(See the man page for a complete listing of all commands and options)\n"
141   )),
142
143   ARGPARSE_group (303, N_("@\nExamples:\n\n"
144     " blurb\n"
145                           " blurb\n")),
146
147   /* Hidden options. */
148   ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
149   ARGPARSE_s_n (oNoSecmemWarn, "no-secmem-warning", "@"), 
150   ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"),
151   ARGPARSE_s_n (oNoOptions, "no-options", "@"),
152   ARGPARSE_s_s (oHomedir, "homedir", "@"),   
153   ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
154   ARGPARSE_s_s (oGpgProgram, "gpg-program", "@"),
155   ARGPARSE_s_s (oDisplay,    "display", "@"),
156   ARGPARSE_s_s (oTTYname,    "ttyname", "@"),
157   ARGPARSE_s_s (oTTYtype,    "ttytype", "@"),
158   ARGPARSE_s_s (oLCctype,    "lc-ctype", "@"),
159   ARGPARSE_s_s (oLCmessages, "lc-messages", "@"),
160   ARGPARSE_s_s (oXauthority, "xauthority", "@"),
161   ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"),
162   ARGPARSE_s_n (oWithColons, "with-colons", "@"),
163   ARGPARSE_s_n (oNoRandomSeedFile,  "no-random-seed-file", "@"),
164
165   /* Command aliases.  */
166
167   ARGPARSE_end ()
168 };
169
170
171 /* Global variable to keep an error count. */
172 int g13_errors_seen = 0;
173
174 /* It is possible that we are currently running under setuid permissions.  */
175 static int maybe_setuid = 1;
176
177 /* Helper to implement --debug-level and --debug.  */
178 static const char *debug_level;
179 static unsigned int debug_value;
180
181 static void set_cmd (enum cmd_and_opt_values *ret_cmd,
182                      enum cmd_and_opt_values new_cmd );
183
184 static void emergency_cleanup (void);
185
186 /* Begin Pth wrapper functions. */
187 GCRY_THREAD_OPTION_PTH_IMPL;
188 static int fixed_gcry_pth_init (void)
189 {
190   return pth_self ()? 0 : (pth_init () == FALSE) ? errno : 0;
191 }
192 /* End Pth wrapper functions. */
193
194
195 static const char *
196 my_strusage( int level )
197 {
198   const char *p;
199
200   switch (level)
201     {
202     case 11: p = "g13 (GnuPG)";
203       break;
204     case 13: p = VERSION; break;
205     case 17: p = PRINTABLE_OS_NAME; break;
206     case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
207       break;
208     case 1:
209     case 40: p = _("Usage: g13 [options] [files] (-h for help)");
210       break;
211     case 41:
212       p = _("Syntax: g13 [options] [files]\n"
213             "Create, mount or unmount an encrypted file system container\n");
214       break;
215
216     case 31: p = "\nHome: "; break;
217     case 32: p = opt.homedir; break;
218      
219     default: p = NULL; break;
220     }
221   return p;
222 }
223
224
225 static void
226 wrong_args (const char *text)
227 {
228   fputs (_("usage: g13 [options] "), stderr);
229   fputs (text, stderr);
230   putc ('\n', stderr);
231   g13_exit (2);
232 }
233
234
235 /* Setup the debugging.  With a DEBUG_LEVEL of NULL only the active
236    debug flags are propagated to the subsystems.  With DEBUG_LEVEL
237    set, a specific set of debug flags is set; and individual debugging
238    flags will be added on top.  */
239 static void
240 set_debug (void)
241 {
242   if (!debug_level)
243     ;
244   else if (!strcmp (debug_level, "none"))
245     opt.debug = 0;
246   else if (!strcmp (debug_level, "basic"))
247     opt.debug = DBG_ASSUAN_VALUE|DBG_MOUNT_VALUE;
248   else if (!strcmp (debug_level, "advanced"))
249     opt.debug = DBG_ASSUAN_VALUE|DBG_MOUNT_VALUE;
250   else if (!strcmp (debug_level, "expert"))
251     opt.debug = (DBG_ASSUAN_VALUE|DBG_MOUNT_VALUE|DBG_CRYPTO_VALUE);
252   else if (!strcmp (debug_level, "guru"))
253     opt.debug = ~0;
254   else
255     {
256       log_error (_("invalid debug-level `%s' given\n"), debug_level);
257       g13_exit(2);
258     }
259
260   opt.debug |= debug_value;
261
262   if (opt.debug && !opt.verbose)
263     opt.verbose = 1;
264   if (opt.debug)
265     opt.quiet = 0;
266
267   if (opt.debug & DBG_CRYPTO_VALUE )
268     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
269   gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
270 }
271  
272
273
274 static void
275 set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
276 {
277   enum cmd_and_opt_values cmd = *ret_cmd;
278
279   if (!cmd || cmd == new_cmd)
280     cmd = new_cmd;
281   else 
282     {
283       log_error (_("conflicting commands\n"));
284       g13_exit (2);
285     }
286
287   *ret_cmd = cmd;
288 }
289
290
291 /* Helper to add recipients to a list. */
292 static int
293 add_encryption_key (ctrl_t ctrl, const char *name,
294                     void /*FIXME*/ *keylist, int is_cms)
295 {
296   /* FIXME: Decide whether to add a CMS or OpenPGP key and then add
297      the key to a list.  */
298   /* int rc = foo_add_to_certlist (ctrl, name, 0, recplist, is_encrypt_to); */
299   /* if (rc) */
300   /*   { */
301   /*     if (recp_required) */
302   /*       { */
303   /*         log_error ("can't encrypt to `%s': %s\n", name, gpg_strerror (rc)); */
304   /*         gpgsm_status2 (ctrl, STATUS_INV_RECP, */
305   /*                        get_inv_recpsgnr_code (rc), name, NULL); */
306   /*       } */
307   /*     else */
308   /*       log_info (_("NOTE: won't be able to encrypt to `%s': %s\n"), */
309   /*                 name, gpg_strerror (rc)); */
310   /*   } */
311   return 0; /* Key is good.  */
312 }
313
314
315 int
316 main ( int argc, char **argv)
317 {
318   ARGPARSE_ARGS pargs;
319   int orig_argc;
320   char **orig_argv;
321   gpg_error_t err;
322   const char *fname;
323   int may_coredump;
324   FILE *configfp = NULL;
325   char *configname = NULL;
326   unsigned configlineno;
327   int parse_debug = 0;
328   int no_more_options = 0;
329   int default_config =1;
330   char *logfile = NULL;
331   char *auditlog = NULL;
332   int greeting = 0;
333   int nogreeting = 0;
334   int debug_wait = 0;
335   int use_random_seed = 1;
336   int nodetach = 0;
337   int nokeysetup = 0;
338   enum cmd_and_opt_values cmd = 0;
339   struct server_control_s ctrl;
340   estream_t auditfp = NULL;
341   strlist_t recipients = NULL;
342
343   /*mtrace();*/
344
345   gnupg_reopen_std ("g13");
346   set_strusage (my_strusage);
347   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
348
349   log_set_prefix ("g13", 1);
350
351   /* Make sure that our subsystems are ready.  */
352   i18n_init ();
353   init_common_subsystems ();
354
355   /* Libgcrypt requires us to register the threading model first.
356      Note that this will also do the pth_init. */
357   gcry_threads_pth.init = fixed_gcry_pth_init;
358   err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
359   if (err)
360     {
361       log_fatal ("can't register GNU Pth with Libgcrypt: %s\n",
362                  gpg_strerror (err));
363     }
364
365   /* Check that the Libgcrypt is suitable.  */
366   if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
367     log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt", 
368                NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
369
370   /* Take extra care of the random pool.  */
371   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
372
373   may_coredump = disable_core_dumps ();
374   
375   gnupg_init_signals (0, emergency_cleanup);
376   
377   create_dotlock (NULL); /* Register locking cleanup.  */
378
379   opt.homedir = default_homedir ();
380
381   /* First check whether we have a config file on the commandline.  */
382   orig_argc = argc;
383   orig_argv = argv;
384   pargs.argc = &argc;
385   pargs.argv = &argv;
386   pargs.flags= 1|(1<<6);  /* Do not remove the args, ignore version.  */
387   while (arg_parse( &pargs, opts))
388     {
389       if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
390         parse_debug++;
391       else if (pargs.r_opt == oOptions)
392         { /* Yes, there is one, so we do not try the default one but
393              read the config file when it is encountered at the
394              commandline.  */
395           default_config = 0;
396         }
397       else if (pargs.r_opt == oNoOptions)
398         default_config = 0; /* --no-options */
399       else if (pargs.r_opt == oHomedir)
400         opt.homedir = pargs.r.ret_str;
401     }
402
403   /* Initialize the secure memory. */
404   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
405   maybe_setuid = 0;
406
407   /* 
408      Now we are now working under our real uid 
409   */
410
411   /* Setup malloc hooks. */
412   {
413     struct assuan_malloc_hooks malloc_hooks;
414
415     malloc_hooks.malloc = gcry_malloc;
416     malloc_hooks.realloc = gcry_realloc;
417     malloc_hooks.free = gcry_free;
418     assuan_set_malloc_hooks (&malloc_hooks);
419   }
420   
421   /* Prepare libassuan.  */
422   assuan_set_assuan_log_prefix (log_get_prefix (NULL));
423   assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
424
425
426   /* Setup a default control structure for command line mode.  */
427   memset (&ctrl, 0, sizeof ctrl);
428   g13_init_default_ctrl (&ctrl);
429
430   /* Set the default option file */
431   if (default_config )
432     configname = make_filename (opt.homedir, "g13.conf", NULL);
433   
434   argc        = orig_argc;
435   argv        = orig_argv;
436   pargs.argc  = &argc;
437   pargs.argv  = &argv;
438   pargs.flags =  1;  /* Do not remove the args.  */
439
440  next_pass:
441   if (configname)
442     {
443       configlineno = 0;
444       configfp = fopen (configname, "r");
445       if (!configfp)
446         {
447           if (default_config)
448             {
449               if (parse_debug)
450                 log_info (_("NOTE: no default option file `%s'\n"), configname);
451             }
452           else 
453             {
454               log_error (_("option file `%s': %s\n"), 
455                          configname, strerror(errno));
456               g13_exit(2);
457             }
458           xfree (configname);
459           configname = NULL;
460         }
461       if (parse_debug && configname)
462         log_info (_("reading options from `%s'\n"), configname);
463       default_config = 0;
464     }
465   
466   while (!no_more_options 
467          && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
468     {
469       switch (pargs.r_opt)
470         {
471         case aGPGConfList: 
472         case aGPGConfTest: 
473           set_cmd (&cmd, pargs.r_opt);
474           nogreeting = 1;
475           nokeysetup = 1;
476           break;
477
478         case aMount:
479         case aUmount:
480           nokeysetup = 1;
481         case aCreate:
482           set_cmd (&cmd, pargs.r_opt);
483           break;
484
485         case oOutput: opt.outfile = pargs.r.ret_str; break;
486
487         case oQuiet: opt.quiet = 1; break;
488         case oNoGreeting: nogreeting = 1; break;
489         case oNoTTY:  break;
490
491         case oDryRun: opt.dry_run = 1; break;
492
493         case oVerbose:
494           opt.verbose++;
495           gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
496           break;
497         case oNoVerbose:
498           opt.verbose = 0;
499           gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
500           break;
501
502         case oLogFile: logfile = pargs.r.ret_str; break;
503         case oNoLogFile: logfile = NULL; break;          
504
505         case oAuditLog: auditlog = pargs.r.ret_str; break;
506
507         case oNoDetach: nodetach = 1; break;
508
509         case oDebug: debug_value |= pargs.r.ret_ulong; break;
510         case oDebugAll: debug_value = ~0; break;
511         case oDebugNone: debug_value = 0; break;
512         case oDebugLevel: debug_level = pargs.r.ret_str; break;
513         case oDebugWait: debug_wait = pargs.r.ret_int; break;
514         case oDebugAllowCoreDump:
515           may_coredump = enable_core_dumps ();
516           break;
517
518         case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
519         case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
520
521         case oNoOptions: break; /* no-options */
522         case oOptions:
523           /* Config files may not be nested (silently ignore them).  */
524           if (!configfp)
525             {
526               xfree(configname);
527               configname = xstrdup (pargs.r.ret_str);
528               goto next_pass;
529             }
530           break;
531
532         case oHomedir: opt.homedir = pargs.r.ret_str; break;
533
534         case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
535         case oGpgProgram: opt.gpg_program = pargs.r.ret_str;  break;
536         case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
537         case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
538         case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
539         case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
540         case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
541         case oXauthority: opt.xauthority = xstrdup (pargs.r.ret_str); break;
542           
543         case oFakedSystemTime:
544           {
545             time_t faked_time = isotime2epoch (pargs.r.ret_str); 
546             if (faked_time == (time_t)(-1))
547               faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
548             gnupg_set_time (faked_time, 0);
549           }
550           break;
551
552         case oNoSecmemWarn: gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); break;
553
554         case oNoRandomSeedFile: use_random_seed = 0; break;
555
556         case oRecipient: /* Store the encryption key.  */
557           add_to_strlist (&recipients, pargs.r.ret_str);
558           break;
559
560
561         default: 
562           pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR; 
563           break;
564         }
565     }
566
567   if (configfp)
568     {
569       fclose (configfp);
570       configfp = NULL;
571       /* Keep a copy of the config filename. */
572       opt.config_filename = configname;
573       configname = NULL;
574       goto next_pass;
575     }
576   xfree (configname);
577   configname = NULL;
578
579   if (!opt.config_filename)
580     opt.config_filename = make_filename (opt.homedir, "g13.conf", NULL);
581
582   if (log_get_errorcount(0))
583     g13_exit(2);
584
585   /* Now that we have the options parsed we need to update the default
586      control structure.  */
587   g13_init_default_ctrl (&ctrl);
588
589   if (nogreeting)
590     greeting = 0;
591   
592   if (greeting)
593     {
594       fprintf(stderr, "%s %s; %s\n",
595               strusage(11), strusage(13), strusage(14) );
596       fprintf(stderr, "%s\n", strusage(15) );
597     }
598
599   if (may_coredump && !opt.quiet)
600     log_info (_("WARNING: program may create a core file!\n"));
601
602   if (logfile)
603     {
604       log_set_file (logfile);
605       log_set_prefix (NULL, 1|2|4);
606     }
607
608   if (gnupg_faked_time_p ())
609     {
610       gnupg_isotime_t tbuf;
611
612       log_info (_("WARNING: running with faked system time: "));
613       gnupg_get_isotime (tbuf);
614       dump_isotime (tbuf);
615       log_printf ("\n");
616     }
617
618   /* Print any pending secure memory warnings.  */
619   gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
620
621   /* Setup the debug flags for all subsystems.  */
622   set_debug ();
623
624   /* Install a regular exit handler to make real sure that the secure
625      memory gets wiped out.  */
626   if (atexit (emergency_cleanup))
627     {
628       log_error ("atexit failed\n");
629       g13_exit (2);
630     }
631
632   /* Terminate if we found any error until now.  */
633   if (log_get_errorcount(0))
634     g13_exit (2);
635   
636   /* Set the standard GnuPG random seed file.  */
637   if (use_random_seed) 
638     {
639       char *p = make_filename (opt.homedir, "random_seed", NULL);
640       gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
641       xfree(p);
642     }
643   
644   /* Store given filename into FNAME. */
645   fname = argc? *argv : NULL;
646
647   /* Parse all given encryption keys.  This does a lookup of the keys
648      and stops if any of the given keys was not found. */
649   if (!nokeysetup)
650     {
651       strlist_t sl;
652       int failed = 0;
653       
654       for (sl = recipients; sl; sl = sl->next)
655         if (add_encryption_key (&ctrl, sl->d, NULL /* FIXME*/, 0))
656           failed = 1;
657       if (failed)
658         g13_exit (1);
659     }
660   
661   /* Dispatch command.  */
662   switch (cmd)
663     {
664     case aGPGConfList: 
665       { /* List options and default values in the GPG Conf format.  */
666         char *config_filename_esc = percent_escape (opt.config_filename, NULL);
667
668         printf ("gpgconf-g13.conf:%lu:\"%s\n",
669                 GC_OPT_FLAG_DEFAULT, config_filename_esc);
670         xfree (config_filename_esc);
671
672         printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE);
673         printf ("quiet:%lu:\n", GC_OPT_FLAG_NONE);
674         printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
675         printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
676       }
677       break;
678     case aGPGConfTest:
679       /* This is merely a dummy command to test whether the
680          configuration file is valid.  */
681       break;
682
683     case aCreate: /* Create a new container. */
684       {
685         if (argc != 1) 
686           wrong_args ("--create filename");
687         err = g13_create_container (&ctrl, argv[0]);
688         if (err)
689           log_error ("error creating a new container: %s <%s>\n",
690                      gpg_strerror (err), gpg_strsource (err));
691         else
692           {
693             unsigned int n;
694
695             while ((n = runner_get_threads ()))
696               {
697                 log_info ("number of running threads: %u\n", n);
698                 pth_sleep (5);
699               }
700           }
701       }
702       break;
703
704     case aMount: /* Mount a container. */
705       {
706         if (argc != 1 && argc != 2 ) 
707           wrong_args ("--mount filename [mountpoint]");
708         err = g13_mount_container (&ctrl, argv[0], argc == 2?argv[1]:NULL);
709         if (err)
710           log_error ("error mounting container `%s': %s <%s>\n",
711                      *argv, gpg_strerror (err), gpg_strsource (err));
712         else
713           {
714             unsigned int n;
715
716             while ((n = runner_get_threads ()))
717               {
718                 log_info ("number of running threads: %u\n", n);
719                 pth_sleep (5);
720               }
721           }
722       }
723       break;
724
725     default:
726       log_error (_("invalid command (there is no implicit command)\n"));
727       break;
728     }
729
730   /* Print the audit result if needed.  */
731   if (auditlog && auditfp)
732     {
733       /* audit_print_result (ctrl.audit, auditfp, 0); */
734       /* audit_release (ctrl.audit); */
735       ctrl.audit = NULL;
736       es_fclose (auditfp);
737     }
738   
739   /* Cleanup.  */
740   g13_exit (0);
741   return 8; /*NOTREACHED*/
742 }
743
744 /* Note: This function is used by signal handlers!. */
745 static void
746 emergency_cleanup (void)
747 {
748   gcry_control (GCRYCTL_TERM_SECMEM );
749 }
750
751
752 void
753 g13_exit (int rc)
754 {
755   gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
756   if (opt.debug & DBG_MEMSTAT_VALUE)
757     {
758       gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
759       gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
760     }
761   if (opt.debug)
762     gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
763   emergency_cleanup ();
764   rc = rc? rc : log_get_errorcount(0)? 2 : g13_errors_seen? 1 : 0;
765   exit (rc);
766 }
767
768
769 void
770 g13_init_default_ctrl (struct server_control_s *ctrl)
771 {
772   ctrl->conttype = CONTTYPE_ENCFS;
773 }
774
775
776 /* static void */
777 /* daemonize (int nodetach) */
778 /* { */
779 /*   gnupg_fd_t fd; */
780 /*   gnupg_fd_t fd_ssh; */
781 /*   pid_t pid; */
782
783 /*   fflush (NULL); */
784 /* #ifdef HAVE_W32_SYSTEM */
785 /*   pid = getpid (); */
786 /* #else /\*!HAVE_W32_SYSTEM*\/ */
787 /*   pid = fork (); */
788 /*   if (pid == (pid_t)-1)  */
789 /*     { */
790 /*       log_fatal ("fork failed: %s\n", strerror (errno) ); */
791 /*       g13_exit (1); */
792 /*     } */
793 /*   else if (pid) /\* We are the parent *\/ */
794 /*     {  */
795 /*       /\* We need to clwanup our resources.  An gcry_atfork might be */
796 /*          needed. *\/ */
797 /*       exit (0);  */
798 /*       /\*NOTREACHED*\/ */
799 /*     } /\* End parent *\/ */
800
801 /*   /\*  */
802 /*      This is the child */
803 /*   *\/ */
804
805 /*   /\* Detach from tty and put process into a new session *\/ */
806 /*   if (!nodetach ) */
807 /*     {  */
808 /*       int i; */
809 /*       unsigned int oldflags; */
810       
811 /*       /\* Close stdin, stdout and stderr unless it is the log stream *\/ */
812 /*       for (i=0; i <= 2; i++)  */
813 /*         { */
814 /*           if (!log_test_fd (i) && i != fd ) */
815 /*             { */
816 /*               if ( ! close (i) */
817 /*                    && open ("/dev/null", i? O_WRONLY : O_RDONLY) == -1) */
818 /*                 { */
819 /*                   log_error ("failed to open `%s': %s\n", */
820 /*                              "/dev/null", strerror (errno)); */
821 /*                   cleanup (); */
822 /*                   exit (1); */
823 /*                 } */
824 /*             } */
825 /*         } */
826 /*       if (setsid() == -1) */
827 /*         { */
828 /*           log_error ("setsid() failed: %s\n", strerror(errno) ); */
829 /*           cleanup (); */
830 /*           exit (1); */
831 /*         } */
832
833 /*       log_get_prefix (&oldflags); */
834 /*       log_set_prefix (NULL, oldflags | JNLIB_LOG_RUN_DETACHED); */
835 /*       opt.running_detached = 1; */
836 /*     } */
837   
838 /*   if (chdir("/")) */
839 /*     { */
840 /*       log_error ("chdir to / failed: %s\n", strerror (errno)); */
841 /*       exit (1); */
842 /*     } */
843
844 /*   { */
845 /*     struct sigaction sa; */
846     
847 /*     sa.sa_handler = SIG_IGN; */
848 /*     sigemptyset (&sa.sa_mask); */
849 /*     sa.sa_flags = 0; */
850 /*     sigaction (SIGPIPE, &sa, NULL); */
851 /*   } */
852 /* #endif /\*!HAVE_W32_SYSTEM*\/ */
853
854 /*   log_info ("%s %s started\n", strusage(11), strusage(13) ); */
855 /*   handle_something (fd, opt.ssh_support ? fd_ssh : GNUPG_INVALID_FD); */
856 /* } */