agent/
[gnupg.git] / g13 / g13.c
blob152058e28882d6c90fa4580f2fe19a53cf7b5a17
1 /* g13.c - Disk Key management with GnuPG
2 * Copyright (C) 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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/>.
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>
30 #include "g13.h"
32 #include <gcrypt.h>
33 #include <assuan.h>
35 #include "i18n.h"
36 #include "sysutils.h"
37 #include "gc-opt-flags.h"
38 #include "keyblob.h"
39 #include "server.h"
40 #include "runner.h"
41 #include "create.h"
42 #include "mount.h"
43 #include "mountinfo.h"
46 enum cmd_and_opt_values {
47 aNull = 0,
48 oQuiet = 'q',
49 oVerbose = 'v',
50 oRecipient = 'r',
52 aGPGConfList = 500,
53 aGPGConfTest,
54 aCreate,
55 aMount,
56 aUmount,
57 aServer,
59 oOptions,
60 oDebug,
61 oDebugLevel,
62 oDebugAll,
63 oDebugNone,
64 oDebugWait,
65 oDebugAllowCoreDump,
66 oLogFile,
67 oNoLogFile,
68 oAuditLog,
70 oOutput,
72 oAgentProgram,
73 oGpgProgram,
75 oDisplay,
76 oTTYname,
77 oTTYtype,
78 oLCctype,
79 oLCmessages,
80 oXauthority,
82 oStatusFD,
83 oLoggerFD,
85 oNoVerbose,
86 oNoSecmemWarn,
87 oNoGreeting,
88 oNoTTY,
89 oNoOptions,
90 oHomedir,
91 oWithColons,
92 oDryRun,
93 oNoDetach,
95 oNoRandomSeedFile,
96 oFakedSystemTime
100 static ARGPARSE_OPTS opts[] = {
102 ARGPARSE_group (300, N_("@Commands:\n ")),
104 ARGPARSE_c (aCreate, "create", N_("Create a new file system container")),
105 ARGPARSE_c (aMount, "mount", N_("Mount a file system container") ),
106 ARGPARSE_c (aUmount, "umount", N_("Unmount a file system container") ),
107 ARGPARSE_c (aServer, "server", N_("Run in server mode")),
109 ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
110 ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
112 ARGPARSE_group (301, N_("@\nOptions:\n ")),
114 ARGPARSE_s_s (oRecipient, "recipient", N_("|USER-ID|encrypt for USER-ID")),
116 ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")),
117 ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
118 ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")),
119 ARGPARSE_s_n (oNoTTY, "no-tty", N_("don't use the terminal at all")),
120 ARGPARSE_s_n (oNoDetach, "no-detach", N_("do not detach from the console")),
121 ARGPARSE_s_s (oLogFile, "log-file", N_("|FILE|write log output to FILE")),
122 ARGPARSE_s_n (oNoLogFile, "no-log-file", "@"),
123 ARGPARSE_s_i (oLoggerFD, "logger-fd", "@"),
125 ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
127 ARGPARSE_s_s (oOptions, "options", N_("|FILE|read options from FILE")),
129 ARGPARSE_p_u (oDebug, "debug", "@"),
130 ARGPARSE_s_s (oDebugLevel, "debug-level",
131 N_("|LEVEL|set the debugging level to LEVEL")),
132 ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
133 ARGPARSE_s_n (oDebugNone, "debug-none", "@"),
134 ARGPARSE_s_i (oDebugWait, "debug-wait", "@"),
135 ARGPARSE_s_n (oDebugAllowCoreDump, "debug-allow-core-dump", "@"),
137 ARGPARSE_s_i (oStatusFD, "status-fd",
138 N_("|FD|write status info to this FD")),
140 ARGPARSE_group (302, N_(
141 "@\n(See the man page for a complete listing of all commands and options)\n"
144 ARGPARSE_group (303, N_("@\nExamples:\n\n"
145 " blurb\n"
146 " blurb\n")),
148 /* Hidden options. */
149 ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
150 ARGPARSE_s_n (oNoSecmemWarn, "no-secmem-warning", "@"),
151 ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"),
152 ARGPARSE_s_n (oNoOptions, "no-options", "@"),
153 ARGPARSE_s_s (oHomedir, "homedir", "@"),
154 ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
155 ARGPARSE_s_s (oGpgProgram, "gpg-program", "@"),
156 ARGPARSE_s_s (oDisplay, "display", "@"),
157 ARGPARSE_s_s (oTTYname, "ttyname", "@"),
158 ARGPARSE_s_s (oTTYtype, "ttytype", "@"),
159 ARGPARSE_s_s (oLCctype, "lc-ctype", "@"),
160 ARGPARSE_s_s (oLCmessages, "lc-messages", "@"),
161 ARGPARSE_s_s (oXauthority, "xauthority", "@"),
162 ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"),
163 ARGPARSE_s_n (oWithColons, "with-colons", "@"),
164 ARGPARSE_s_n (oNoRandomSeedFile, "no-random-seed-file", "@"),
166 /* Command aliases. */
168 ARGPARSE_end ()
172 /* The timer tick interval used by the idle task. */
173 #define TIMERTICK_INTERVAL_SEC (1)
176 /* Global variable to keep an error count. */
177 int g13_errors_seen = 0;
179 /* It is possible that we are currently running under setuid permissions. */
180 static int maybe_setuid = 1;
182 /* Helper to implement --debug-level and --debug. */
183 static const char *debug_level;
184 static unsigned int debug_value;
186 /* Flag to indicate that a shutdown was requested. */
187 static int shutdown_pending;
189 /* The thread id of the idle task. */
190 static pth_t idle_task_tid;
194 static void set_cmd (enum cmd_and_opt_values *ret_cmd,
195 enum cmd_and_opt_values new_cmd );
197 static void emergency_cleanup (void);
198 static void start_idle_task (void);
199 static void join_idle_task (void);
203 /* Begin Pth wrapper functions. */
204 ASSUAN_SYSTEM_PTH_IMPL;
206 GCRY_THREAD_OPTION_PTH_IMPL;
207 static int fixed_gcry_pth_init (void)
209 return pth_self ()? 0 : (pth_init () == FALSE) ? errno : 0;
211 /* End Pth wrapper functions. */
214 static const char *
215 my_strusage( int level )
217 const char *p;
219 switch (level)
221 case 11: p = "g13 (GnuPG)";
222 break;
223 case 13: p = VERSION; break;
224 case 17: p = PRINTABLE_OS_NAME; break;
225 case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
226 break;
227 case 1:
228 case 40: p = _("Usage: g13 [options] [files] (-h for help)");
229 break;
230 case 41:
231 p = _("Syntax: g13 [options] [files]\n"
232 "Create, mount or unmount an encrypted file system container\n");
233 break;
235 case 31: p = "\nHome: "; break;
236 case 32: p = opt.homedir; break;
238 default: p = NULL; break;
240 return p;
244 static void
245 wrong_args (const char *text)
247 fputs (_("usage: g13 [options] "), stderr);
248 fputs (text, stderr);
249 putc ('\n', stderr);
250 g13_exit (2);
254 /* Setup the debugging. With a DEBUG_LEVEL of NULL only the active
255 debug flags are propagated to the subsystems. With DEBUG_LEVEL
256 set, a specific set of debug flags is set; and individual debugging
257 flags will be added on top. */
258 static void
259 set_debug (void)
261 if (!debug_level)
263 else if (!strcmp (debug_level, "none"))
264 opt.debug = 0;
265 else if (!strcmp (debug_level, "basic"))
266 opt.debug = DBG_ASSUAN_VALUE|DBG_MOUNT_VALUE;
267 else if (!strcmp (debug_level, "advanced"))
268 opt.debug = DBG_ASSUAN_VALUE|DBG_MOUNT_VALUE;
269 else if (!strcmp (debug_level, "expert"))
270 opt.debug = (DBG_ASSUAN_VALUE|DBG_MOUNT_VALUE|DBG_CRYPTO_VALUE);
271 else if (!strcmp (debug_level, "guru"))
272 opt.debug = ~0;
273 else
275 log_error (_("invalid debug-level `%s' given\n"), debug_level);
276 g13_exit(2);
279 opt.debug |= debug_value;
281 if (opt.debug && !opt.verbose)
282 opt.verbose = 1;
283 if (opt.debug)
284 opt.quiet = 0;
286 if (opt.debug & DBG_CRYPTO_VALUE )
287 gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
288 gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
293 static void
294 set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
296 enum cmd_and_opt_values cmd = *ret_cmd;
298 if (!cmd || cmd == new_cmd)
299 cmd = new_cmd;
300 else
302 log_error (_("conflicting commands\n"));
303 g13_exit (2);
306 *ret_cmd = cmd;
311 main ( int argc, char **argv)
313 ARGPARSE_ARGS pargs;
314 int orig_argc;
315 char **orig_argv;
316 gpg_error_t err;
317 const char *fname;
318 int may_coredump;
319 FILE *configfp = NULL;
320 char *configname = NULL;
321 unsigned configlineno;
322 int parse_debug = 0;
323 int no_more_options = 0;
324 int default_config =1;
325 char *logfile = NULL;
326 int greeting = 0;
327 int nogreeting = 0;
328 int debug_wait = 0;
329 int use_random_seed = 1;
330 int nodetach = 0;
331 int nokeysetup = 0;
332 enum cmd_and_opt_values cmd = 0;
333 struct server_control_s ctrl;
334 strlist_t recipients = NULL;
336 /*mtrace();*/
338 gnupg_reopen_std ("g13");
339 set_strusage (my_strusage);
340 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
342 log_set_prefix ("g13", 1);
344 /* Make sure that our subsystems are ready. */
345 i18n_init ();
346 init_common_subsystems ();
348 /* Libgcrypt requires us to register the threading model first.
349 Note that this will also do the pth_init. */
350 gcry_threads_pth.init = fixed_gcry_pth_init;
351 err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
352 if (err)
354 log_fatal ("can't register GNU Pth with Libgcrypt: %s\n",
355 gpg_strerror (err));
358 /* Check that the Libgcrypt is suitable. */
359 if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
360 log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
361 NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
363 /* Take extra care of the random pool. */
364 gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
366 may_coredump = disable_core_dumps ();
368 gnupg_init_signals (0, emergency_cleanup);
370 create_dotlock (NULL); /* Register locking cleanup. */
372 opt.homedir = default_homedir ();
374 /* First check whether we have a config file on the commandline. */
375 orig_argc = argc;
376 orig_argv = argv;
377 pargs.argc = &argc;
378 pargs.argv = &argv;
379 pargs.flags= 1|(1<<6); /* Do not remove the args, ignore version. */
380 while (arg_parse( &pargs, opts))
382 if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
383 parse_debug++;
384 else if (pargs.r_opt == oOptions)
385 { /* Yes, there is one, so we do not try the default one but
386 read the config file when it is encountered at the
387 commandline. */
388 default_config = 0;
390 else if (pargs.r_opt == oNoOptions)
391 default_config = 0; /* --no-options */
392 else if (pargs.r_opt == oHomedir)
393 opt.homedir = pargs.r.ret_str;
396 /* Initialize the secure memory. */
397 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
398 maybe_setuid = 0;
401 Now we are now working under our real uid
404 /* Setup malloc hooks. */
406 struct assuan_malloc_hooks malloc_hooks;
408 malloc_hooks.malloc = gcry_malloc;
409 malloc_hooks.realloc = gcry_realloc;
410 malloc_hooks.free = gcry_free;
411 assuan_set_malloc_hooks (&malloc_hooks);
414 /* Prepare libassuan. */
415 assuan_set_assuan_log_prefix (log_get_prefix (NULL));
416 assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
417 assuan_set_system_hooks (ASSUAN_SYSTEM_PTH);
420 /* Setup a default control structure for command line mode. */
421 memset (&ctrl, 0, sizeof ctrl);
422 g13_init_default_ctrl (&ctrl);
423 ctrl.no_server = 1;
424 ctrl.status_fd = -1; /* No status output. */
426 /* Set the default option file */
427 if (default_config )
428 configname = make_filename (opt.homedir, "g13.conf", NULL);
430 argc = orig_argc;
431 argv = orig_argv;
432 pargs.argc = &argc;
433 pargs.argv = &argv;
434 pargs.flags = 1; /* Do not remove the args. */
436 next_pass:
437 if (configname)
439 configlineno = 0;
440 configfp = fopen (configname, "r");
441 if (!configfp)
443 if (default_config)
445 if (parse_debug)
446 log_info (_("NOTE: no default option file `%s'\n"), configname);
448 else
450 log_error (_("option file `%s': %s\n"),
451 configname, strerror(errno));
452 g13_exit(2);
454 xfree (configname);
455 configname = NULL;
457 if (parse_debug && configname)
458 log_info (_("reading options from `%s'\n"), configname);
459 default_config = 0;
462 while (!no_more_options
463 && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
465 switch (pargs.r_opt)
467 case aGPGConfList:
468 case aGPGConfTest:
469 set_cmd (&cmd, pargs.r_opt);
470 nogreeting = 1;
471 nokeysetup = 1;
472 break;
474 case aServer:
475 case aMount:
476 case aUmount:
477 nokeysetup = 1;
478 case aCreate:
479 set_cmd (&cmd, pargs.r_opt);
480 break;
482 case oOutput: opt.outfile = pargs.r.ret_str; break;
484 case oQuiet: opt.quiet = 1; break;
485 case oNoGreeting: nogreeting = 1; break;
486 case oNoTTY: break;
488 case oDryRun: opt.dry_run = 1; break;
490 case oVerbose:
491 opt.verbose++;
492 gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
493 break;
494 case oNoVerbose:
495 opt.verbose = 0;
496 gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
497 break;
499 case oLogFile: logfile = pargs.r.ret_str; break;
500 case oNoLogFile: logfile = NULL; break;
502 case oNoDetach: nodetach = 1; break;
504 case oDebug: debug_value |= pargs.r.ret_ulong; break;
505 case oDebugAll: debug_value = ~0; break;
506 case oDebugNone: debug_value = 0; break;
507 case oDebugLevel: debug_level = pargs.r.ret_str; break;
508 case oDebugWait: debug_wait = pargs.r.ret_int; break;
509 case oDebugAllowCoreDump:
510 may_coredump = enable_core_dumps ();
511 break;
513 case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
514 case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
516 case oNoOptions: break; /* no-options */
517 case oOptions:
518 /* Config files may not be nested (silently ignore them). */
519 if (!configfp)
521 xfree(configname);
522 configname = xstrdup (pargs.r.ret_str);
523 goto next_pass;
525 break;
527 case oHomedir: opt.homedir = pargs.r.ret_str; break;
529 case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
530 case oGpgProgram: opt.gpg_program = pargs.r.ret_str; break;
531 case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
532 case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
533 case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
534 case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
535 case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
536 case oXauthority: opt.xauthority = xstrdup (pargs.r.ret_str); break;
538 case oFakedSystemTime:
540 time_t faked_time = isotime2epoch (pargs.r.ret_str);
541 if (faked_time == (time_t)(-1))
542 faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
543 gnupg_set_time (faked_time, 0);
545 break;
547 case oNoSecmemWarn: gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); break;
549 case oNoRandomSeedFile: use_random_seed = 0; break;
551 case oRecipient: /* Store the encryption key. */
552 add_to_strlist (&recipients, pargs.r.ret_str);
553 break;
556 default:
557 pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
558 break;
562 if (configfp)
564 fclose (configfp);
565 configfp = NULL;
566 /* Keep a copy of the config filename. */
567 opt.config_filename = configname;
568 configname = NULL;
569 goto next_pass;
571 xfree (configname);
572 configname = NULL;
574 if (!opt.config_filename)
575 opt.config_filename = make_filename (opt.homedir, "g13.conf", NULL);
577 if (log_get_errorcount(0))
578 g13_exit(2);
580 /* Now that we have the options parsed we need to update the default
581 control structure. */
582 g13_init_default_ctrl (&ctrl);
584 if (nogreeting)
585 greeting = 0;
587 if (greeting)
589 fprintf (stderr, "%s %s; %s\n",
590 strusage(11), strusage(13), strusage(14) );
591 fprintf (stderr, "%s\n", strusage(15) );
594 if (may_coredump && !opt.quiet)
595 log_info (_("WARNING: program may create a core file!\n"));
597 if (logfile)
599 log_set_file (logfile);
600 log_set_prefix (NULL, 1|2|4);
603 if (gnupg_faked_time_p ())
605 gnupg_isotime_t tbuf;
607 log_info (_("WARNING: running with faked system time: "));
608 gnupg_get_isotime (tbuf);
609 dump_isotime (tbuf);
610 log_printf ("\n");
613 /* Print any pending secure memory warnings. */
614 gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
616 /* Setup the debug flags for all subsystems. */
617 set_debug ();
619 /* Install a regular exit handler to make real sure that the secure
620 memory gets wiped out. */
621 if (atexit (emergency_cleanup))
623 log_error ("atexit failed\n");
624 g13_exit (2);
627 /* Terminate if we found any error until now. */
628 if (log_get_errorcount(0))
629 g13_exit (2);
631 /* Set the standard GnuPG random seed file. */
632 if (use_random_seed)
634 char *p = make_filename (opt.homedir, "random_seed", NULL);
635 gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
636 xfree(p);
639 /* Store given filename into FNAME. */
640 fname = argc? *argv : NULL;
642 /* Parse all given encryption keys. This does a lookup of the keys
643 and stops if any of the given keys was not found. */
644 #if 0 /* Currently not implemented. */
645 if (!nokeysetup)
647 strlist_t sl;
648 int failed = 0;
650 for (sl = recipients; sl; sl = sl->next)
651 if (check_encryption_key ())
652 failed = 1;
653 if (failed)
654 g13_exit (1);
656 #endif /*0*/
658 /* Dispatch command. */
659 switch (cmd)
661 case aGPGConfList:
662 { /* List options and default values in the GPG Conf format. */
663 char *config_filename_esc = percent_escape (opt.config_filename, NULL);
665 printf ("gpgconf-g13.conf:%lu:\"%s\n",
666 GC_OPT_FLAG_DEFAULT, config_filename_esc);
667 xfree (config_filename_esc);
669 printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE);
670 printf ("quiet:%lu:\n", GC_OPT_FLAG_NONE);
671 printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
672 printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
674 break;
675 case aGPGConfTest:
676 /* This is merely a dummy command to test whether the
677 configuration file is valid. */
678 break;
680 case aServer:
682 start_idle_task ();
683 ctrl.no_server = 0;
684 err = g13_server (&ctrl);
685 if (err)
686 log_error ("server exited with error: %s <%s>\n",
687 gpg_strerror (err), gpg_strsource (err));
688 else
689 shutdown_pending++;
691 break;
693 case aCreate: /* Create a new container. */
695 if (argc != 1)
696 wrong_args ("--create filename");
697 start_idle_task ();
698 err = g13_create_container (&ctrl, argv[0], recipients);
699 if (err)
700 log_error ("error creating a new container: %s <%s>\n",
701 gpg_strerror (err), gpg_strsource (err));
702 else
703 shutdown_pending++;
705 break;
707 case aMount: /* Mount a container. */
709 if (argc != 1 && argc != 2 )
710 wrong_args ("--mount filename [mountpoint]");
711 start_idle_task ();
712 err = g13_mount_container (&ctrl, argv[0], argc == 2?argv[1]:NULL);
713 if (err)
714 log_error ("error mounting container `%s': %s <%s>\n",
715 *argv, gpg_strerror (err), gpg_strsource (err));
717 break;
719 default:
720 log_error (_("invalid command (there is no implicit command)\n"));
721 break;
724 if (!err)
725 join_idle_task ();
727 /* Cleanup. */
728 g13_exit (0);
729 return 8; /*NOTREACHED*/
733 /* Note: This function is used by signal handlers!. */
734 static void
735 emergency_cleanup (void)
737 gcry_control (GCRYCTL_TERM_SECMEM );
741 void
742 g13_exit (int rc)
744 gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
745 if (opt.debug & DBG_MEMSTAT_VALUE)
747 gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
748 gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
750 if (opt.debug)
751 gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
752 emergency_cleanup ();
753 rc = rc? rc : log_get_errorcount(0)? 2 : g13_errors_seen? 1 : 0;
754 exit (rc);
758 /* Store defaults into the per-connection CTRL object. */
759 void
760 g13_init_default_ctrl (struct server_control_s *ctrl)
762 ctrl->conttype = CONTTYPE_ENCFS;
766 /* This function is called for each signal we catch. It is run in the
767 main context or the one of a Pth thread and thus it is not
768 restricted in what it may do. */
769 static void
770 handle_signal (int signo)
772 switch (signo)
774 #ifndef HAVE_W32_SYSTEM
775 case SIGHUP:
776 log_info ("SIGHUP received - re-reading configuration\n");
777 /* Fixme: Not yet implemented. */
778 break;
780 case SIGUSR1:
781 log_info ("SIGUSR1 received - printing internal information:\n");
782 pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ());
783 mountinfo_dump_all ();
784 break;
786 case SIGUSR2:
787 log_info ("SIGUSR2 received - no action defined\n");
788 break;
790 case SIGTERM:
791 if (!shutdown_pending)
792 log_info ("SIGTERM received - shutting down ...\n");
793 else
794 log_info ("SIGTERM received - still %u runners active\n",
795 runner_get_threads ());
796 shutdown_pending++;
797 if (shutdown_pending > 2)
799 log_info ("shutdown forced\n");
800 log_info ("%s %s stopped\n", strusage(11), strusage(13) );
801 g13_exit (0);
803 break;
805 case SIGINT:
806 log_info ("SIGINT received - immediate shutdown\n");
807 log_info( "%s %s stopped\n", strusage(11), strusage(13));
808 g13_exit (0);
809 break;
810 #endif /*!HAVE_W32_SYSTEM*/
812 default:
813 log_info ("signal %d received - no action defined\n", signo);
818 /* This ticker function is called about every TIMERTICK_INTERVAL_SEC
819 seconds. */
820 static void
821 handle_tick (void)
823 /* log_debug ("TICK\n"); */
827 /* The idle task. We use a separate thread to do idle stuff and to
828 catch signals. */
829 static void *
830 idle_task (void *dummy_arg)
832 sigset_t sigs; /* The set of signals we want to catch. */
833 pth_event_t ev; /* The main event to catch signals. */
834 pth_event_t time_ev; /* The time event. */
835 int signo; /* The number of a raised signal is stored here. */
837 (void)dummy_arg;
839 /* Create the event to catch the signals. */
840 #ifndef HAVE_W32_SYSTEM
841 sigemptyset (&sigs );
842 sigaddset (&sigs, SIGHUP);
843 sigaddset (&sigs, SIGUSR1);
844 sigaddset (&sigs, SIGUSR2);
845 sigaddset (&sigs, SIGINT);
846 sigaddset (&sigs, SIGTERM);
847 pth_sigmask (SIG_UNBLOCK, &sigs, NULL);
848 #else
849 sigs = 0;
850 #endif
851 ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
853 /* The time event neds to computed n tghe fly. */
854 time_ev = NULL;
856 for (;;)
858 /* The shutdown flag allows us to terminate the idle task. */
859 if (shutdown_pending)
861 runner_cancel_all ();
863 if (!runner_get_threads ())
864 break; /* ready */
867 /* Create a timeout event if needed. To help with power saving
868 we syncronize the ticks to the next full second. */
869 if (!time_ev)
871 pth_time_t nexttick;
873 nexttick = pth_timeout (TIMERTICK_INTERVAL_SEC, 0);
874 if (nexttick.tv_usec > 10) /* Use a 10 usec threshhold. */
876 nexttick.tv_sec++;
877 nexttick.tv_usec = 0;
879 time_ev = pth_event (PTH_EVENT_TIME, nexttick);
882 pth_event_concat (ev, time_ev, NULL);
883 pth_wait (ev);
884 pth_event_isolate (time_ev);
886 if (pth_event_occurred (ev))
888 handle_signal (signo);
891 if (time_ev && pth_event_occurred (time_ev))
893 pth_event_free (time_ev, PTH_FREE_ALL);
894 time_ev = NULL;
895 handle_tick ();
899 pth_event_free (ev, PTH_FREE_ALL);
900 if (time_ev)
901 pth_event_free (time_ev, PTH_FREE_ALL);
902 log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
903 return NULL;
907 /* Start the idle task. */
908 static void
909 start_idle_task (void)
911 pth_attr_t tattr;
912 pth_t tid;
914 tattr = pth_attr_new ();
915 pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
916 pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 64*1024);
917 pth_attr_set (tattr, PTH_ATTR_NAME, "idle-task");
919 tid = pth_spawn (tattr, idle_task, NULL);
920 if (!tid)
922 log_fatal ("error starting idle task: %s\n",
923 gpg_strerror (gpg_error_from_syserror ()));
924 return; /*NOTREACHED*/
926 idle_task_tid = tid;
927 pth_attr_destroy (tattr);
931 /* Wait for the idle task to finish. */
932 static void
933 join_idle_task (void)
935 if (idle_task_tid)
937 if (!pth_join (idle_task_tid, NULL))
938 log_error ("waiting for idle task thread failed: %s\n",
939 gpg_strerror (gpg_error_from_syserror ()));