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