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 <https://www.gnu.org/licenses/>.
37 #include "gc-opt-flags.h"
39 #include "../common/init.h"
46 #include "mountinfo.h"
48 #include "call-syshelp.h"
51 enum cmd_and_opt_values {
109 static ARGPARSE_OPTS opts[] = {
111 ARGPARSE_group (300, N_("@Commands:\n ")),
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", "@"),
121 ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
122 ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
124 ARGPARSE_group (301, N_("@\nOptions:\n ")),
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")),
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", "@"),
138 ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
140 ARGPARSE_s_s (oOptions, "options", N_("|FILE|read options from FILE")),
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", "@"),
150 ARGPARSE_s_i (oStatusFD, "status-fd",
151 N_("|FD|write status info to this FD")),
153 ARGPARSE_group (302, N_(
154 "@\n(See the man page for a complete listing of all commands and options)\n"
157 ARGPARSE_group (303, N_("@\nExamples:\n\n"
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", "@"),
179 /* Command aliases. */
185 /* The list of supported debug flags. */
186 static struct debug_flags_s debug_flags [] =
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" },
197 /* The timer tick interval used by the idle task. */
198 #define TIMERTICK_INTERVAL_SEC (1)
200 /* It is possible that we are currently running under setuid permissions. */
201 static int maybe_setuid = 1;
203 /* Helper to implement --debug-level and --debug. */
204 static const char *debug_level;
205 static unsigned int debug_value;
207 /* Flag to indicate that a shutdown was requested. */
208 static int shutdown_pending;
210 /* The thread id of the idle task. */
211 static npth_t idle_task_thread;
214 /* The container type as specified on the command line. */
215 static int cmdline_conttype;
219 static void set_cmd (enum cmd_and_opt_values *ret_cmd,
220 enum cmd_and_opt_values new_cmd );
222 static void start_idle_task (void);
223 static void join_idle_task (void);
226 /* Begin NPth wrapper functions. */
227 ASSUAN_SYSTEM_NPTH_IMPL;
231 my_strusage( int level )
237 case 11: p = "@G13@ (@GNUPG@)";
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");
244 case 40: p = _("Usage: @G13@ [options] [files] (-h for help)");
247 p = _("Syntax: @G13@ [options] [files]\n"
248 "Create, mount or unmount an encrypted file system container\n");
251 case 31: p = "\nHome: "; break;
252 case 32: p = gnupg_homedir (); break;
254 default: p = NULL; break;
261 wrong_args (const char *text)
263 fprintf (stderr, _("usage: %s [options] "), G13_NAME);
264 fputs (text, stderr);
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. */
277 int numok = (debug_level && digitp (debug_level));
278 int numlvl = numok? atoi (debug_level) : 0;
282 else if (!strcmp (debug_level, "none") || (numok && numlvl < 1))
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)
294 /* opt.debug &= ~(DBG_HASHING_VALUE); */
298 log_error (_("invalid debug-level '%s' given\n"), debug_level);
302 opt.debug |= debug_value;
304 if (opt.debug && !opt.verbose)
309 if (opt.debug & DBG_CRYPTO_VALUE )
310 gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
311 gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
314 parse_debug_flag (NULL, &opt.debug, debug_flags);
320 set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
322 enum cmd_and_opt_values cmd = *ret_cmd;
324 if (!cmd || cmd == new_cmd)
328 log_error (_("conflicting commands\n"));
337 main ( int argc, char **argv)
343 /* const char *fname; */
345 FILE *configfp = NULL;
346 char *configname = NULL;
347 unsigned configlineno;
349 int no_more_options = 0;
350 int default_config =1;
351 char *logfile = NULL;
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;
364 early_system_init ();
365 gnupg_reopen_std (G13_NAME);
366 set_strusage (my_strusage);
367 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
369 log_set_prefix (G13_NAME, GPGRT_LOG_WITH_PREFIX);
371 /* Make sure that our subsystems are ready. */
373 init_common_subsystems (&argc, &argv);
377 /* Take extra care of the random pool. */
378 gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
380 may_coredump = disable_core_dumps ();
384 dotlock_create (NULL, 0); /* Register locking cleanup. */
386 opt.session_env = session_env_new ();
387 if (!opt.session_env)
388 log_fatal ("error allocating session environment block: %s\n",
391 /* First check whether we have a config file on the commandline. */
396 pargs.flags= 1|(1<<6); /* Do not remove the args, ignore version. */
397 while (arg_parse( &pargs, opts))
399 if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
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
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);
413 /* Initialize the secure memory. */
414 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
418 Now we are now working under our real uid
421 /* Setup malloc hooks. */
423 struct assuan_malloc_hooks malloc_hooks;
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);
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, NULL);
436 /* Setup a default control structure for command line mode. */
437 memset (&ctrl, 0, sizeof ctrl);
438 g13_init_default_ctrl (&ctrl);
440 ctrl.status_fd = -1; /* No status output. */
442 /* Set the default option file */
444 configname = make_filename (gnupg_homedir (), G13_NAME".conf", NULL);
450 pargs.flags = 1; /* Do not remove the args. */
456 configfp = fopen (configname, "r");
462 log_info (_("Note: no default option file '%s'\n"), configname);
466 log_error (_("option file '%s': %s\n"),
467 configname, strerror(errno));
473 if (parse_debug && configname)
474 log_info (_("reading options from '%s'\n"), configname);
478 while (!no_more_options
479 && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
485 set_cmd (&cmd, pargs.r_opt);
487 /* nokeysetup = 1; */
497 set_cmd (&cmd, pargs.r_opt);
500 case oOutput: opt.outfile = pargs.r.ret_str; break;
502 case oQuiet: opt.quiet = 1; break;
503 case oNoGreeting: nogreeting = 1; break;
506 case oDryRun: opt.dry_run = 1; break;
510 gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
514 gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
517 case oLogFile: logfile = pargs.r.ret_str; break;
518 case oNoLogFile: logfile = NULL; break;
520 case oNoDetach: /*nodetach = 1; */break;
523 if (parse_debug_flag (pargs.r.ret_str, &opt.debug, debug_flags))
525 pargs.r_opt = ARGPARSE_INVALID_ARG;
526 pargs.err = ARGPARSE_PRINT_ERROR;
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 ();
537 case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
538 case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
540 case oNoOptions: break; /* no-options */
542 /* Config files may not be nested (silently ignore them). */
546 configname = xstrdup (pargs.r.ret_str);
551 case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
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;
562 case oFakedSystemTime:
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);
571 case oNoSecmemWarn: gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); break;
573 case oNoRandomSeedFile: use_random_seed = 0; break;
575 case oRecipient: /* Store the encryption key. */
576 add_to_strlist (&recipients, pargs.r.ret_str);
580 if (!strcmp (pargs.r.ret_str, "help"))
582 be_parse_conttype_name (NULL);
585 cmdline_conttype = be_parse_conttype_name (pargs.r.ret_str);
586 if (!cmdline_conttype)
588 pargs.r_opt = ARGPARSE_INVALID_ARG;
589 pargs.err = ARGPARSE_PRINT_ERROR;
594 pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
599 /* XXX Construct GPG arguments. */
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");
613 /* Keep a copy of the config filename. */
614 opt.config_filename = configname;
621 if (!opt.config_filename)
622 opt.config_filename = make_filename (gnupg_homedir (),
623 G13_NAME".conf", NULL);
625 if (log_get_errorcount(0))
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;
639 fprintf (stderr, "%s %s; %s\n",
640 strusage(11), strusage(13), strusage(14) );
641 fprintf (stderr, "%s\n", strusage(15) );
644 if (may_coredump && !opt.quiet)
645 log_info (_("WARNING: program may create a core file!\n"));
647 /* Print a warning if an argument looks like an option. */
648 if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
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]);
660 log_set_file (logfile);
661 log_set_prefix (NULL, GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_TIME | GPGRT_LOG_WITH_PID);
664 if (gnupg_faked_time_p ())
666 gnupg_isotime_t tbuf;
668 log_info (_("WARNING: running with faked system time: "));
669 gnupg_get_isotime (tbuf);
674 /* Print any pending secure memory warnings. */
675 gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
677 /* Setup the debug flags for all subsystems. */
680 /* Install emergency cleanup handler. */
681 g13_install_emergency_cleanup ();
683 /* Terminate if we found any error until now. */
684 if (log_get_errorcount(0))
687 /* Set the standard GnuPG random seed file. */
690 char *p = make_filename (gnupg_homedir (), "random_seed", NULL);
691 gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
695 /* Store given filename into FNAME. */
696 /* fname = argc? *argv : NULL; */
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. */
706 for (sl = ctrl->recipients; sl; sl = sl->next)
707 if (check_encryption_key ())
714 /* Dispatch command. */
719 { /* List options and default values in the GPG Conf format. */
720 char *config_filename_esc = percent_escape (opt.config_filename, NULL);
722 printf ("gpgconf-g13.conf:%lu:\"%s\n",
723 GC_OPT_FLAG_DEFAULT, config_filename_esc);
724 xfree (config_filename_esc);
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);
733 /* This is merely a dummy command to test whether the
734 configuration file is valid. */
741 err = g13_server (&ctrl);
743 log_error ("server exited with error: %s <%s>\n",
744 gpg_strerror (err), gpg_strsource (err));
746 g13_request_shutdown ();
755 wrong_args ("--find-device name");
757 err = call_syshelp_find_device (&ctrl, argv[0], &blockdev);
759 log_error ("error finding device '%s': %s <%s>\n",
760 argv[0], gpg_strerror (err), gpg_strsource (err));
766 case aCreate: /* Create a new container. */
769 wrong_args ("--create filename");
771 err = g13_create_container (&ctrl, argv[0]);
773 log_error ("error creating a new container: %s <%s>\n",
774 gpg_strerror (err), gpg_strsource (err));
776 g13_request_shutdown ();
780 case aMount: /* Mount a container. */
782 if (argc != 1 && argc != 2 )
783 wrong_args ("--mount filename [mountpoint]");
785 err = g13_mount_container (&ctrl, argv[0], argc == 2?argv[1]:NULL);
787 log_error ("error mounting container '%s': %s <%s>\n",
788 *argv, gpg_strerror (err), gpg_strsource (err));
792 case aUmount: /* Unmount a mounted container. */
795 wrong_args ("--umount filename");
796 err = g13_umount_container (&ctrl, argv[0], NULL);
798 log_error ("error unmounting container '%s': %s <%s>\n",
799 *argv, gpg_strerror (err), gpg_strsource (err));
803 case aSuspend: /* Suspend a container. */
805 /* Fixme: Should we add a suspend all container option? */
807 wrong_args ("--suspend filename");
808 err = g13_suspend_container (&ctrl, argv[0]);
810 log_error ("error suspending container '%s': %s <%s>\n",
811 *argv, gpg_strerror (err), gpg_strsource (err));
815 case aResume: /* Resume a suspended container. */
817 /* Fixme: Should we add a resume all container option? */
819 wrong_args ("--resume filename");
820 err = g13_resume_container (&ctrl, argv[0]);
822 log_error ("error resuming container '%s': %s <%s>\n",
823 *argv, gpg_strerror (err), gpg_strsource (err));
828 log_error (_("invalid command (there is no implicit command)\n"));
832 g13_deinit_default_ctrl (&ctrl);
839 return 8; /*NOTREACHED*/
843 /* Store defaults into the per-connection CTRL object. */
845 g13_init_default_ctrl (ctrl_t ctrl)
847 ctrl->conttype = cmdline_conttype? cmdline_conttype : CONTTYPE_ENCFS;
851 /* Release remaining resources allocated in the CTRL object. */
853 g13_deinit_default_ctrl (ctrl_t ctrl)
855 call_syshelp_release (ctrl);
856 FREE_STRLIST (ctrl->recipients);
860 /* Request a shutdown. This can be used when the process should
861 * finish instead of running the idle task. */
863 g13_request_shutdown (void)
869 /* This function is called for each signal we catch. It is run in the
870 main context or the one of a NPth thread and thus it is not
871 restricted in what it may do. */
873 handle_signal (int signo)
877 #ifndef HAVE_W32_SYSTEM
879 log_info ("SIGHUP received - re-reading configuration\n");
880 /* Fixme: Not yet implemented. */
884 log_info ("SIGUSR1 received - printing internal information:\n");
885 /* Fixme: We need to see how to integrate pth dumping into our
887 /* pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ()); */
888 mountinfo_dump_all ();
892 log_info ("SIGUSR2 received - no action defined\n");
896 if (!shutdown_pending)
897 log_info ("SIGTERM received - shutting down ...\n");
899 log_info ("SIGTERM received - still %u runners active\n",
900 runner_get_threads ());
902 if (shutdown_pending > 2)
904 log_info ("shutdown forced\n");
905 log_info ("%s %s stopped\n", strusage(11), strusage(13) );
911 log_info ("SIGINT received - immediate shutdown\n");
912 log_info( "%s %s stopped\n", strusage(11), strusage(13));
915 #endif /*!HAVE_W32_SYSTEM*/
918 log_info ("signal %d received - no action defined\n", signo);
923 /* This ticker function is called about every TIMERTICK_INTERVAL_SEC
928 /* log_debug ("TICK\n"); */
932 /* The idle task. We use a separate thread to do idle stuff and to
935 idle_task (void *dummy_arg)
937 int signo; /* The number of a raised signal is stored here. */
939 struct timespec abstime;
940 struct timespec curtime;
941 struct timespec timeout;
946 /* Create the event to catch the signals. */
947 #ifndef HAVE_W32_SYSTEM
949 npth_sigev_add (SIGHUP);
950 npth_sigev_add (SIGUSR1);
951 npth_sigev_add (SIGUSR2);
952 npth_sigev_add (SIGINT);
953 npth_sigev_add (SIGTERM);
957 npth_clock_gettime (&abstime);
958 abstime.tv_sec += TIMERTICK_INTERVAL_SEC;
962 /* The shutdown flag allows us to terminate the idle task. */
963 if (shutdown_pending)
965 runner_cancel_all ();
967 if (!runner_get_threads ())
971 npth_clock_gettime (&curtime);
972 if (!(npth_timercmp (&curtime, &abstime, <)))
976 npth_clock_gettime (&abstime);
977 abstime.tv_sec += TIMERTICK_INTERVAL_SEC;
979 npth_timersub (&abstime, &curtime, &timeout);
981 #ifndef HAVE_W32_SYSTEM
982 ret = npth_pselect (0, NULL, NULL, NULL, &timeout, npth_sigev_sigmask());
985 while (npth_sigev_get_pending(&signo))
986 handle_signal (signo);
988 ret = npth_eselect (0, NULL, NULL, NULL, &timeout, NULL, NULL);
992 if (ret == -1 && saved_errno != EINTR)
994 log_error (_("npth_pselect failed: %s - waiting 1s\n"),
995 strerror (saved_errno));
1002 /* Interrupt or timeout. Will be handled when calculating the
1007 /* Here one would add processing of file descriptors. */
1010 log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
1015 /* Start the idle task. */
1017 start_idle_task (void)
1021 sigset_t sigs; /* The set of signals we want to catch. */
1024 #ifndef HAVE_W32_SYSTEM
1025 /* These signals should always go to the idle task, so they need to
1026 be blocked everywhere else. We assume start_idle_task is called
1027 from the main thread before any other threads are created. */
1028 sigemptyset (&sigs);
1029 sigaddset (&sigs, SIGHUP);
1030 sigaddset (&sigs, SIGUSR1);
1031 sigaddset (&sigs, SIGUSR2);
1032 sigaddset (&sigs, SIGINT);
1033 sigaddset (&sigs, SIGTERM);
1034 npth_sigmask (SIG_BLOCK, &sigs, NULL);
1037 npth_attr_init (&tattr);
1038 npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
1040 err = npth_create (&thread, &tattr, idle_task, NULL);
1043 log_fatal ("error starting idle task: %s\n", strerror (err));
1044 return; /*NOTREACHED*/
1046 npth_setname_np (thread, "idle-task");
1047 idle_task_thread = thread;
1048 npth_attr_destroy (&tattr);
1052 /* Wait for the idle task to finish. */
1054 join_idle_task (void)
1058 /* FIXME: This assumes that a valid pthread_t is non-null. That is
1060 if (idle_task_thread)
1062 err = npth_join (idle_task_thread, NULL);
1064 log_error ("waiting for idle task thread failed: %s\n",