g13: New command --find-device.
[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 <npth.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 "asshelp.h"
39 #include "../common/init.h"
40 #include "keyblob.h"
41 #include "server.h"
42 #include "runner.h"
43 #include "create.h"
44 #include "mount.h"
45 #include "suspend.h"
46 #include "mountinfo.h"
47 #include "backend.h"
48 #include "call-syshelp.h"
49
50
51 enum cmd_and_opt_values {
52   aNull = 0,
53   oQuiet        = 'q',
54   oVerbose      = 'v',
55   oRecipient    = 'r',
56
57   aGPGConfList  = 500,
58   aGPGConfTest,
59   aCreate,
60   aMount,
61   aUmount,
62   aSuspend,
63   aResume,
64   aServer,
65   aFindDevice,
66
67   oOptions,
68   oDebug,
69   oDebugLevel,
70   oDebugAll,
71   oDebugNone,
72   oDebugWait,
73   oDebugAllowCoreDump,
74   oLogFile,
75   oNoLogFile,
76   oAuditLog,
77
78   oOutput,
79
80   oAgentProgram,
81   oGpgProgram,
82   oType,
83
84   oDisplay,
85   oTTYname,
86   oTTYtype,
87   oLCctype,
88   oLCmessages,
89   oXauthority,
90
91   oStatusFD,
92   oLoggerFD,
93
94   oNoVerbose,
95   oNoSecmemWarn,
96   oNoGreeting,
97   oNoTTY,
98   oNoOptions,
99   oHomedir,
100   oWithColons,
101   oDryRun,
102   oNoDetach,
103
104   oNoRandomSeedFile,
105   oFakedSystemTime
106  };
107
108
109 static ARGPARSE_OPTS opts[] = {
110
111   ARGPARSE_group (300, N_("@Commands:\n ")),
112
113   ARGPARSE_c (aCreate, "create", N_("Create a new file system container")),
114   ARGPARSE_c (aMount,  "mount",  N_("Mount a file system container") ),
115   ARGPARSE_c (aUmount, "umount", N_("Unmount a file system container") ),
116   ARGPARSE_c (aSuspend, "suspend", N_("Suspend a file system container") ),
117   ARGPARSE_c (aResume,  "resume",  N_("Resume a file system container") ),
118   ARGPARSE_c (aServer, "server", N_("Run in server mode")),
119   ARGPARSE_c (aFindDevice, "find-device", "@"),
120
121   ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
122   ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
123
124   ARGPARSE_group (301, N_("@\nOptions:\n ")),
125
126   ARGPARSE_s_s (oRecipient, "recipient", N_("|USER-ID|encrypt for USER-ID")),
127   ARGPARSE_s_s (oType, "type", N_("|NAME|use container format NAME")),
128
129   ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")),
130   ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
131   ARGPARSE_s_n (oQuiet, "quiet",  N_("be somewhat more quiet")),
132   ARGPARSE_s_n (oNoTTY, "no-tty", N_("don't use the terminal at all")),
133   ARGPARSE_s_n (oNoDetach, "no-detach", N_("do not detach from the console")),
134   ARGPARSE_s_s (oLogFile, "log-file",  N_("|FILE|write log output to FILE")),
135   ARGPARSE_s_n (oNoLogFile, "no-log-file", "@"),
136   ARGPARSE_s_i (oLoggerFD, "logger-fd", "@"),
137
138   ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
139
140   ARGPARSE_s_s (oOptions, "options", N_("|FILE|read options from FILE")),
141
142   ARGPARSE_s_s (oDebug, "debug", "@"),
143   ARGPARSE_s_s (oDebugLevel, "debug-level",
144                 N_("|LEVEL|set the debugging level to LEVEL")),
145   ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
146   ARGPARSE_s_n (oDebugNone, "debug-none", "@"),
147   ARGPARSE_s_i (oDebugWait, "debug-wait", "@"),
148   ARGPARSE_s_n (oDebugAllowCoreDump, "debug-allow-core-dump", "@"),
149
150   ARGPARSE_s_i (oStatusFD, "status-fd",
151                 N_("|FD|write status info to this FD")),
152
153   ARGPARSE_group (302, N_(
154   "@\n(See the man page for a complete listing of all commands and options)\n"
155   )),
156
157   ARGPARSE_group (303, N_("@\nExamples:\n\n"
158     " blurb\n"
159                           " blurb\n")),
160
161   /* Hidden options. */
162   ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
163   ARGPARSE_s_n (oNoSecmemWarn, "no-secmem-warning", "@"),
164   ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"),
165   ARGPARSE_s_n (oNoOptions, "no-options", "@"),
166   ARGPARSE_s_s (oHomedir, "homedir", "@"),
167   ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
168   ARGPARSE_s_s (oGpgProgram, "gpg-program", "@"),
169   ARGPARSE_s_s (oDisplay,    "display", "@"),
170   ARGPARSE_s_s (oTTYname,    "ttyname", "@"),
171   ARGPARSE_s_s (oTTYtype,    "ttytype", "@"),
172   ARGPARSE_s_s (oLCctype,    "lc-ctype", "@"),
173   ARGPARSE_s_s (oLCmessages, "lc-messages", "@"),
174   ARGPARSE_s_s (oXauthority, "xauthority", "@"),
175   ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"),
176   ARGPARSE_s_n (oWithColons, "with-colons", "@"),
177   ARGPARSE_s_n (oNoRandomSeedFile,  "no-random-seed-file", "@"),
178
179   /* Command aliases.  */
180
181   ARGPARSE_end ()
182 };
183
184
185 /* The list of supported debug flags.  */
186 static struct debug_flags_s debug_flags [] =
187   {
188     { DBG_MOUNT_VALUE  , "mount"  },
189     { DBG_CRYPTO_VALUE , "crypto"  },
190     { DBG_MEMORY_VALUE , "memory"  },
191     { DBG_MEMSTAT_VALUE, "memstat" },
192     { DBG_IPC_VALUE    , "ipc"     },
193     { 0, NULL }
194   };
195
196
197 /* The timer tick interval used by the idle task.  */
198 #define TIMERTICK_INTERVAL_SEC     (1)
199
200 /* It is possible that we are currently running under setuid permissions.  */
201 static int maybe_setuid = 1;
202
203 /* Helper to implement --debug-level and --debug.  */
204 static const char *debug_level;
205 static unsigned int debug_value;
206
207 /* Flag to indicate that a shutdown was requested.  */
208 static int shutdown_pending;
209
210 /* The thread id of the idle task.  */
211 static npth_t idle_task_thread;
212
213
214 /* The container type as specified on the command line.  */
215 static int cmdline_conttype;
216
217
218 \f
219 static void set_cmd (enum cmd_and_opt_values *ret_cmd,
220                      enum cmd_and_opt_values new_cmd );
221
222 static void start_idle_task (void);
223 static void join_idle_task (void);
224
225 \f
226 /* Begin NPth wrapper functions. */
227 ASSUAN_SYSTEM_NPTH_IMPL;
228
229 \f
230 static const char *
231 my_strusage( int level )
232 {
233   const char *p;
234
235   switch (level)
236     {
237     case 11: p = "@G13@ (@GNUPG@)";
238       break;
239     case 13: p = VERSION; break;
240     case 17: p = PRINTABLE_OS_NAME; break;
241     case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
242       break;
243     case 1:
244     case 40: p = _("Usage: @G13@ [options] [files] (-h for help)");
245       break;
246     case 41:
247       p = _("Syntax: @G13@ [options] [files]\n"
248             "Create, mount or unmount an encrypted file system container\n");
249       break;
250
251     case 31: p = "\nHome: "; break;
252     case 32: p = gnupg_homedir (); break;
253
254     default: p = NULL; break;
255     }
256   return p;
257 }
258
259
260 static void
261 wrong_args (const char *text)
262 {
263   fprintf (stderr, _("usage: %s [options] "), G13_NAME);
264   fputs (text, stderr);
265   putc ('\n', stderr);
266   g13_exit (2);
267 }
268
269
270 /* Setup the debugging.  With a DEBUG_LEVEL of NULL only the active
271    debug flags are propagated to the subsystems.  With DEBUG_LEVEL
272    set, a specific set of debug flags is set; and individual debugging
273    flags will be added on top.  */
274 static void
275 set_debug (void)
276 {
277   int numok = (debug_level && digitp (debug_level));
278   int numlvl = numok? atoi (debug_level) : 0;
279
280   if (!debug_level)
281     ;
282   else if (!strcmp (debug_level, "none") || (numok && numlvl < 1))
283     opt.debug = 0;
284   else if (!strcmp (debug_level, "basic") || (numok && numlvl <= 2))
285     opt.debug = DBG_IPC_VALUE|DBG_MOUNT_VALUE;
286   else if (!strcmp (debug_level, "advanced") || (numok && numlvl <= 5))
287     opt.debug = DBG_IPC_VALUE|DBG_MOUNT_VALUE;
288   else if (!strcmp (debug_level, "expert") || (numok && numlvl <= 8))
289     opt.debug = (DBG_IPC_VALUE|DBG_MOUNT_VALUE|DBG_CRYPTO_VALUE);
290   else if (!strcmp (debug_level, "guru") || numok)
291     {
292       opt.debug = ~0;
293       /* if (numok) */
294       /*   opt.debug &= ~(DBG_HASHING_VALUE); */
295     }
296   else
297     {
298       log_error (_("invalid debug-level '%s' given\n"), debug_level);
299       g13_exit(2);
300     }
301
302   opt.debug |= debug_value;
303
304   if (opt.debug && !opt.verbose)
305     opt.verbose = 1;
306   if (opt.debug)
307     opt.quiet = 0;
308
309   if (opt.debug & DBG_CRYPTO_VALUE )
310     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
311   gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
312
313   if (opt.debug)
314     parse_debug_flag (NULL, &opt.debug, debug_flags);
315 }
316
317
318
319 static void
320 set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
321 {
322   enum cmd_and_opt_values cmd = *ret_cmd;
323
324   if (!cmd || cmd == new_cmd)
325     cmd = new_cmd;
326   else
327     {
328       log_error (_("conflicting commands\n"));
329       g13_exit (2);
330     }
331
332   *ret_cmd = cmd;
333 }
334
335
336 int
337 main ( int argc, char **argv)
338 {
339   ARGPARSE_ARGS pargs;
340   int orig_argc;
341   char **orig_argv;
342   gpg_error_t err = 0;
343   /* const char *fname; */
344   int may_coredump;
345   FILE *configfp = NULL;
346   char *configname = NULL;
347   unsigned configlineno;
348   int parse_debug = 0;
349   int no_more_options = 0;
350   int default_config =1;
351   char *logfile = NULL;
352   int greeting = 0;
353   int nogreeting = 0;
354   /* int debug_wait = 0; */
355   int use_random_seed = 1;
356   /* int nodetach = 0; */
357   /* int nokeysetup = 0; */
358   enum cmd_and_opt_values cmd = 0;
359   struct server_control_s ctrl;
360   strlist_t recipients = NULL;
361
362   /*mtrace();*/
363
364   early_system_init ();
365   gnupg_reopen_std (G13_NAME);
366   set_strusage (my_strusage);
367   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
368
369   log_set_prefix (G13_NAME, GPGRT_LOG_WITH_PREFIX);
370
371   /* Make sure that our subsystems are ready.  */
372   i18n_init ();
373   init_common_subsystems (&argc, &argv);
374
375   npth_init ();
376
377   /* Take extra care of the random pool.  */
378   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
379
380   may_coredump = disable_core_dumps ();
381
382   g13_init_signals ();
383
384   dotlock_create (NULL, 0); /* Register locking cleanup.  */
385
386   opt.session_env = session_env_new ();
387   if (!opt.session_env)
388     log_fatal ("error allocating session environment block: %s\n",
389                strerror (errno));
390
391   /* First check whether we have a config file on the commandline.  */
392   orig_argc = argc;
393   orig_argv = argv;
394   pargs.argc = &argc;
395   pargs.argv = &argv;
396   pargs.flags= 1|(1<<6);  /* Do not remove the args, ignore version.  */
397   while (arg_parse( &pargs, opts))
398     {
399       if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
400         parse_debug++;
401       else if (pargs.r_opt == oOptions)
402         { /* Yes, there is one, so we do not try the default one but
403              read the config file when it is encountered at the
404              commandline.  */
405           default_config = 0;
406         }
407       else if (pargs.r_opt == oNoOptions)
408         default_config = 0; /* --no-options */
409       else if (pargs.r_opt == oHomedir)
410         gnupg_set_homedir (pargs.r.ret_str);
411     }
412
413   /* Initialize the secure memory. */
414   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
415   maybe_setuid = 0;
416
417   /*
418      Now we are now working under our real uid
419   */
420
421   /* Setup malloc hooks. */
422   {
423     struct assuan_malloc_hooks malloc_hooks;
424
425     malloc_hooks.malloc = gcry_malloc;
426     malloc_hooks.realloc = gcry_realloc;
427     malloc_hooks.free = gcry_free;
428     assuan_set_malloc_hooks (&malloc_hooks);
429   }
430
431   /* Prepare libassuan.  */
432   assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
433   assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);
434   setup_libassuan_logging (&opt.debug);
435
436   /* Setup a default control structure for command line mode.  */
437   memset (&ctrl, 0, sizeof ctrl);
438   g13_init_default_ctrl (&ctrl);
439   ctrl.no_server = 1;
440   ctrl.status_fd = -1; /* No status output. */
441
442   /* Set the default option file */
443   if (default_config )
444     configname = make_filename (gnupg_homedir (), G13_NAME".conf", NULL);
445
446   argc        = orig_argc;
447   argv        = orig_argv;
448   pargs.argc  = &argc;
449   pargs.argv  = &argv;
450   pargs.flags =  1;  /* Do not remove the args.  */
451
452  next_pass:
453   if (configname)
454     {
455       configlineno = 0;
456       configfp = fopen (configname, "r");
457       if (!configfp)
458         {
459           if (default_config)
460             {
461               if (parse_debug)
462                 log_info (_("Note: no default option file '%s'\n"), configname);
463             }
464           else
465             {
466               log_error (_("option file '%s': %s\n"),
467                          configname, strerror(errno));
468               g13_exit(2);
469             }
470           xfree (configname);
471           configname = NULL;
472         }
473       if (parse_debug && configname)
474         log_info (_("reading options from '%s'\n"), configname);
475       default_config = 0;
476     }
477
478   while (!no_more_options
479          && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
480     {
481       switch (pargs.r_opt)
482         {
483         case aGPGConfList:
484         case aGPGConfTest:
485           set_cmd (&cmd, pargs.r_opt);
486           nogreeting = 1;
487           /* nokeysetup = 1; */
488           break;
489
490         case aServer:
491         case aMount:
492         case aUmount:
493         case aSuspend:
494         case aResume:
495         case aCreate:
496         case aFindDevice:
497           set_cmd (&cmd, pargs.r_opt);
498           break;
499
500         case oOutput: opt.outfile = pargs.r.ret_str; break;
501
502         case oQuiet: opt.quiet = 1; break;
503         case oNoGreeting: nogreeting = 1; break;
504         case oNoTTY:  break;
505
506         case oDryRun: opt.dry_run = 1; break;
507
508         case oVerbose:
509           opt.verbose++;
510           gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
511           break;
512         case oNoVerbose:
513           opt.verbose = 0;
514           gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
515           break;
516
517         case oLogFile: logfile = pargs.r.ret_str; break;
518         case oNoLogFile: logfile = NULL; break;
519
520         case oNoDetach: /*nodetach = 1; */break;
521
522         case oDebug:
523           if (parse_debug_flag (pargs.r.ret_str, &opt.debug, debug_flags))
524             {
525               pargs.r_opt = ARGPARSE_INVALID_ARG;
526               pargs.err = ARGPARSE_PRINT_ERROR;
527             }
528             break;
529         case oDebugAll: debug_value = ~0; break;
530         case oDebugNone: debug_value = 0; break;
531         case oDebugLevel: debug_level = pargs.r.ret_str; break;
532         case oDebugWait: /*debug_wait = pargs.r.ret_int; */break;
533         case oDebugAllowCoreDump:
534           may_coredump = enable_core_dumps ();
535           break;
536
537         case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
538         case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
539
540         case oNoOptions: break; /* no-options */
541         case oOptions:
542           /* Config files may not be nested (silently ignore them).  */
543           if (!configfp)
544             {
545               xfree(configname);
546               configname = xstrdup (pargs.r.ret_str);
547               goto next_pass;
548             }
549           break;
550
551         case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
552
553         case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
554         case oGpgProgram: opt.gpg_program = pargs.r.ret_str;  break;
555         case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
556         case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
557         case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
558         case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
559         case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
560         case oXauthority: opt.xauthority = xstrdup (pargs.r.ret_str); break;
561
562         case oFakedSystemTime:
563           {
564             time_t faked_time = isotime2epoch (pargs.r.ret_str);
565             if (faked_time == (time_t)(-1))
566               faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
567             gnupg_set_time (faked_time, 0);
568           }
569           break;
570
571         case oNoSecmemWarn: gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); break;
572
573         case oNoRandomSeedFile: use_random_seed = 0; break;
574
575         case oRecipient: /* Store the encryption key.  */
576           add_to_strlist (&recipients, pargs.r.ret_str);
577           break;
578
579         case oType:
580           if (!strcmp (pargs.r.ret_str, "help"))
581             {
582               be_parse_conttype_name (NULL);
583               g13_exit (0);
584             }
585           cmdline_conttype = be_parse_conttype_name (pargs.r.ret_str);
586           if (!cmdline_conttype)
587             {
588               pargs.r_opt = ARGPARSE_INVALID_ARG;
589               pargs.err = ARGPARSE_PRINT_ERROR;
590             }
591           break;
592
593         default:
594           pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
595           break;
596         }
597     }
598
599   /* XXX Construct GPG arguments.  */
600   {
601     strlist_t last;
602     last = append_to_strlist (&opt.gpg_arguments, "-z");
603     last = append_to_strlist (&last, "0");
604     last = append_to_strlist (&last, "--trust-model");
605     last = append_to_strlist (&last, "always");
606     (void) last;
607   }
608
609   if (configfp)
610     {
611       fclose (configfp);
612       configfp = NULL;
613       /* Keep a copy of the config filename. */
614       opt.config_filename = configname;
615       configname = NULL;
616       goto next_pass;
617     }
618   xfree (configname);
619   configname = NULL;
620
621   if (!opt.config_filename)
622     opt.config_filename = make_filename (gnupg_homedir (),
623                                          G13_NAME".conf", NULL);
624
625   if (log_get_errorcount(0))
626     g13_exit(2);
627
628   /* Now that we have the options parsed we need to update the default
629      control structure.  */
630   g13_init_default_ctrl (&ctrl);
631   ctrl.recipients = recipients;
632   recipients = NULL;
633
634   if (nogreeting)
635     greeting = 0;
636
637   if (greeting)
638     {
639       fprintf (stderr, "%s %s; %s\n",
640                strusage(11), strusage(13), strusage(14) );
641       fprintf (stderr, "%s\n", strusage(15) );
642     }
643
644   if (may_coredump && !opt.quiet)
645     log_info (_("WARNING: program may create a core file!\n"));
646
647   /* Print a warning if an argument looks like an option.  */
648   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
649     {
650       int i;
651
652       for (i=0; i < argc; i++)
653         if (argv[i][0] == '-' && argv[i][1] == '-')
654           log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
655     }
656
657
658   if (logfile)
659     {
660       log_set_file (logfile);
661       log_set_prefix (NULL, GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_TIME | GPGRT_LOG_WITH_PID);
662     }
663
664   if (gnupg_faked_time_p ())
665     {
666       gnupg_isotime_t tbuf;
667
668       log_info (_("WARNING: running with faked system time: "));
669       gnupg_get_isotime (tbuf);
670       dump_isotime (tbuf);
671       log_printf ("\n");
672     }
673
674   /* Print any pending secure memory warnings.  */
675   gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
676
677   /* Setup the debug flags for all subsystems.  */
678   set_debug ();
679
680   /* Install emergency cleanup handler.  */
681   g13_install_emergency_cleanup ();
682
683   /* Terminate if we found any error until now.  */
684   if (log_get_errorcount(0))
685     g13_exit (2);
686
687   /* Set the standard GnuPG random seed file.  */
688   if (use_random_seed)
689     {
690       char *p = make_filename (gnupg_homedir (), "random_seed", NULL);
691       gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
692       xfree(p);
693     }
694
695   /* Store given filename into FNAME. */
696   /* fname = argc? *argv : NULL; */
697
698   /* Parse all given encryption keys.  This does a lookup of the keys
699      and stops if any of the given keys was not found. */
700 #if 0 /* Currently not implemented.  */
701   if (!nokeysetup)
702     {
703       strlist_t sl;
704       int failed = 0;
705
706       for (sl = ctrl->recipients; sl; sl = sl->next)
707         if (check_encryption_key ())
708           failed = 1;
709       if (failed)
710         g13_exit (1);
711     }
712 #endif /*0*/
713
714   /* Dispatch command.  */
715   err = 0;
716   switch (cmd)
717     {
718     case aGPGConfList:
719       { /* List options and default values in the GPG Conf format.  */
720         char *config_filename_esc = percent_escape (opt.config_filename, NULL);
721
722         printf ("gpgconf-g13.conf:%lu:\"%s\n",
723                 GC_OPT_FLAG_DEFAULT, config_filename_esc);
724         xfree (config_filename_esc);
725
726         printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE);
727         printf ("quiet:%lu:\n", GC_OPT_FLAG_NONE);
728         printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
729         printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
730       }
731       break;
732     case aGPGConfTest:
733       /* This is merely a dummy command to test whether the
734          configuration file is valid.  */
735       break;
736
737     case aServer:
738       {
739         start_idle_task ();
740         ctrl.no_server = 0;
741         err = g13_server (&ctrl);
742         if (err)
743           log_error ("server exited with error: %s <%s>\n",
744                      gpg_strerror (err), gpg_strsource (err));
745         else
746           g13_request_shutdown ();
747       }
748       break;
749
750     case aFindDevice:
751       {
752         char *blockdev;
753
754         if (argc != 1)
755           wrong_args ("--find-device name");
756
757         err = call_syshelp_find_device (&ctrl, argv[0], &blockdev);
758         if (err)
759           log_error ("error finding device '%s': %s <%s>\n",
760                      argv[0], gpg_strerror (err), gpg_strsource (err));
761         else
762           puts (blockdev);
763       }
764       break;
765
766     case aCreate: /* Create a new container. */
767       {
768         if (argc != 1)
769           wrong_args ("--create filename");
770         start_idle_task ();
771         err = g13_create_container (&ctrl, argv[0]);
772         if (err)
773           log_error ("error creating a new container: %s <%s>\n",
774                      gpg_strerror (err), gpg_strsource (err));
775         else
776           g13_request_shutdown ();
777       }
778       break;
779
780     case aMount: /* Mount a container. */
781       {
782         if (argc != 1 && argc != 2 )
783           wrong_args ("--mount filename [mountpoint]");
784         start_idle_task ();
785         err = g13_mount_container (&ctrl, argv[0], argc == 2?argv[1]:NULL);
786         if (err)
787           log_error ("error mounting container '%s': %s <%s>\n",
788                      *argv, gpg_strerror (err), gpg_strsource (err));
789       }
790       break;
791
792     case aUmount: /* Unmount a mounted container.  */
793       {
794         if (argc != 1)
795           wrong_args ("--umount filename");
796         err = GPG_ERR_NOT_IMPLEMENTED;
797         log_error ("error unmounting container '%s': %s <%s>\n",
798                    *argv, gpg_strerror (err), gpg_strsource (err));
799       }
800       break;
801
802     case aSuspend: /* Suspend a container. */
803       {
804         /* Fixme: Should we add a suspend all container option?  */
805         if (argc != 1)
806           wrong_args ("--suspend filename");
807         err = g13_suspend_container (&ctrl, argv[0]);
808         if (err)
809           log_error ("error suspending container '%s': %s <%s>\n",
810                      *argv, gpg_strerror (err), gpg_strsource (err));
811       }
812       break;
813
814     case aResume: /* Resume a suspended container. */
815       {
816         /* Fixme: Should we add a resume all container option?  */
817         if (argc != 1)
818           wrong_args ("--resume filename");
819         err = g13_resume_container (&ctrl, argv[0]);
820         if (err)
821           log_error ("error resuming container '%s': %s <%s>\n",
822                      *argv, gpg_strerror (err), gpg_strsource (err));
823       }
824       break;
825
826     default:
827       log_error (_("invalid command (there is no implicit command)\n"));
828       break;
829     }
830
831   g13_deinit_default_ctrl (&ctrl);
832
833   if (!err)
834     join_idle_task ();
835
836   /* Cleanup.  */
837   g13_exit (0);
838   return 8; /*NOTREACHED*/
839 }
840
841
842 /* Store defaults into the per-connection CTRL object.  */
843 void
844 g13_init_default_ctrl (ctrl_t ctrl)
845 {
846   ctrl->conttype = cmdline_conttype? cmdline_conttype : CONTTYPE_ENCFS;
847 }
848
849
850 /* Release remaining resources allocated in the CTRL object.  */
851 void
852 g13_deinit_default_ctrl (ctrl_t ctrl)
853 {
854   call_syshelp_release (ctrl);
855   FREE_STRLIST (ctrl->recipients);
856 }
857
858
859 /* Request a shutdown.  This can be used when the process should
860  * finish instead of running the idle task.  */
861 void
862 g13_request_shutdown (void)
863 {
864   shutdown_pending++;
865 }
866
867
868 /* This function is called for each signal we catch.  It is run in the
869    main context or the one of a NPth thread and thus it is not
870    restricted in what it may do.  */
871 static void
872 handle_signal (int signo)
873 {
874   switch (signo)
875     {
876 #ifndef HAVE_W32_SYSTEM
877     case SIGHUP:
878       log_info ("SIGHUP received - re-reading configuration\n");
879       /* Fixme:  Not yet implemented.  */
880       break;
881
882     case SIGUSR1:
883       log_info ("SIGUSR1 received - printing internal information:\n");
884       /* Fixme: We need to see how to integrate pth dumping into our
885          logging system.  */
886       /* pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ()); */
887       mountinfo_dump_all ();
888       break;
889
890     case SIGUSR2:
891       log_info ("SIGUSR2 received - no action defined\n");
892       break;
893
894     case SIGTERM:
895       if (!shutdown_pending)
896         log_info ("SIGTERM received - shutting down ...\n");
897       else
898         log_info ("SIGTERM received - still %u runners active\n",
899                   runner_get_threads ());
900       shutdown_pending++;
901       if (shutdown_pending > 2)
902         {
903           log_info ("shutdown forced\n");
904           log_info ("%s %s stopped\n", strusage(11), strusage(13) );
905           g13_exit (0);
906         }
907       break;
908
909     case SIGINT:
910       log_info ("SIGINT received - immediate shutdown\n");
911       log_info( "%s %s stopped\n", strusage(11), strusage(13));
912       g13_exit (0);
913       break;
914 #endif /*!HAVE_W32_SYSTEM*/
915
916     default:
917       log_info ("signal %d received - no action defined\n", signo);
918     }
919 }
920
921
922 /* This ticker function is called about every TIMERTICK_INTERVAL_SEC
923    seconds. */
924 static void
925 handle_tick (void)
926 {
927   /* log_debug ("TICK\n"); */
928 }
929
930
931 /* The idle task.  We use a separate thread to do idle stuff and to
932    catch signals.  */
933 static void *
934 idle_task (void *dummy_arg)
935 {
936   int signo;           /* The number of a raised signal is stored here.  */
937   int saved_errno;
938   struct timespec abstime;
939   struct timespec curtime;
940   struct timespec timeout;
941   int ret;
942
943   (void)dummy_arg;
944
945   /* Create the event to catch the signals. */
946 #ifndef HAVE_W32_SYSTEM
947   npth_sigev_init ();
948   npth_sigev_add (SIGHUP);
949   npth_sigev_add (SIGUSR1);
950   npth_sigev_add (SIGUSR2);
951   npth_sigev_add (SIGINT);
952   npth_sigev_add (SIGTERM);
953   npth_sigev_fini ();
954 #endif
955
956   npth_clock_gettime (&abstime);
957   abstime.tv_sec += TIMERTICK_INTERVAL_SEC;
958
959   for (;;)
960     {
961       /* The shutdown flag allows us to terminate the idle task.  */
962       if (shutdown_pending)
963         {
964           runner_cancel_all ();
965
966           if (!runner_get_threads ())
967             break; /* ready */
968         }
969
970       npth_clock_gettime (&curtime);
971       if (!(npth_timercmp (&curtime, &abstime, <)))
972         {
973           /* Timeout.  */
974           handle_tick ();
975           npth_clock_gettime (&abstime);
976           abstime.tv_sec += TIMERTICK_INTERVAL_SEC;
977         }
978       npth_timersub (&abstime, &curtime, &timeout);
979
980 #ifndef HAVE_W32_SYSTEM
981       ret = npth_pselect (0, NULL, NULL, NULL, &timeout, npth_sigev_sigmask());
982       saved_errno = errno;
983
984       while (npth_sigev_get_pending(&signo))
985         handle_signal (signo);
986 #else
987       ret = npth_eselect (0, NULL, NULL, NULL, &timeout, NULL, NULL);
988       saved_errno = errno;
989 #endif
990
991       if (ret == -1 && saved_errno != EINTR)
992         {
993           log_error (_("npth_pselect failed: %s - waiting 1s\n"),
994                      strerror (saved_errno));
995           npth_sleep (1);
996           continue;
997         }
998
999       if (ret <= 0)
1000         {
1001           /* Interrupt or timeout.  Will be handled when calculating the
1002              next timeout.  */
1003           continue;
1004         }
1005
1006       /* Here one would add processing of file descriptors.  */
1007     }
1008
1009   log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
1010   return NULL;
1011 }
1012
1013
1014 /* Start the idle task.   */
1015 static void
1016 start_idle_task (void)
1017 {
1018   npth_attr_t tattr;
1019   npth_t thread;
1020   sigset_t sigs;       /* The set of signals we want to catch.  */
1021   int err;
1022
1023 #ifndef HAVE_W32_SYSTEM
1024   /* These signals should always go to the idle task, so they need to
1025      be blocked everywhere else.  We assume start_idle_task is called
1026      from the main thread before any other threads are created.  */
1027   sigemptyset (&sigs);
1028   sigaddset (&sigs, SIGHUP);
1029   sigaddset (&sigs, SIGUSR1);
1030   sigaddset (&sigs, SIGUSR2);
1031   sigaddset (&sigs, SIGINT);
1032   sigaddset (&sigs, SIGTERM);
1033   npth_sigmask (SIG_BLOCK, &sigs, NULL);
1034 #endif
1035
1036   npth_attr_init (&tattr);
1037   npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
1038
1039   err = npth_create (&thread, &tattr, idle_task, NULL);
1040   if (err)
1041     {
1042       log_fatal ("error starting idle task: %s\n", strerror (err));
1043       return; /*NOTREACHED*/
1044     }
1045   npth_setname_np (thread, "idle-task");
1046   idle_task_thread = thread;
1047   npth_attr_destroy (&tattr);
1048 }
1049
1050
1051 /* Wait for the idle task to finish.  */
1052 static void
1053 join_idle_task (void)
1054 {
1055   int err;
1056
1057   /* FIXME: This assumes that a valid pthread_t is non-null.  That is
1058      not guaranteed.  */
1059   if (idle_task_thread)
1060     {
1061       err = npth_join (idle_task_thread, NULL);
1062       if (err)
1063         log_error ("waiting for idle task thread failed: %s\n",
1064                    strerror (err));
1065     }
1066 }