Line data Source code
1 : /* scdaemon.c - The GnuPG Smartcard Daemon
2 : * Copyright (C) 2001-2002, 2004-2005, 2007-2009 Free Software Foundation, Inc.
3 : * Copyright (C) 2001-2002, 2004-2005, 2007-2014 Werner Koch
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * GnuPG is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * GnuPG is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 :
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include <stddef.h>
26 : #include <stdarg.h>
27 : #include <string.h>
28 : #include <errno.h>
29 : #include <assert.h>
30 : #include <time.h>
31 : #include <fcntl.h>
32 : #ifndef HAVE_W32_SYSTEM
33 : #include <sys/socket.h>
34 : #include <sys/un.h>
35 : #endif /*HAVE_W32_SYSTEM*/
36 : #include <unistd.h>
37 : #include <signal.h>
38 : #include <npth.h>
39 :
40 : #define GNUPG_COMMON_NEED_AFLOCAL
41 : #include "scdaemon.h"
42 : #include <ksba.h>
43 : #include <gcrypt.h>
44 :
45 : #include <assuan.h> /* malloc hooks */
46 :
47 : #include "i18n.h"
48 : #include "sysutils.h"
49 : #include "app-common.h"
50 : #include "iso7816.h"
51 : #include "apdu.h"
52 : #include "ccid-driver.h"
53 : #include "gc-opt-flags.h"
54 : #include "asshelp.h"
55 : #include "../common/init.h"
56 :
57 : #ifndef ENAMETOOLONG
58 : # define ENAMETOOLONG EINVAL
59 : #endif
60 :
61 : enum cmd_and_opt_values
62 : { aNull = 0,
63 : oCsh = 'c',
64 : oQuiet = 'q',
65 : oSh = 's',
66 : oVerbose = 'v',
67 :
68 : oNoVerbose = 500,
69 : aGPGConfList,
70 : aGPGConfTest,
71 : oOptions,
72 : oDebug,
73 : oDebugAll,
74 : oDebugLevel,
75 : oDebugWait,
76 : oDebugAllowCoreDump,
77 : oDebugCCIDDriver,
78 : oDebugLogTid,
79 : oDebugAssuanLogCats,
80 : oNoGreeting,
81 : oNoOptions,
82 : oHomedir,
83 : oNoDetach,
84 : oNoGrab,
85 : oLogFile,
86 : oServer,
87 : oMultiServer,
88 : oDaemon,
89 : oBatch,
90 : oReaderPort,
91 : oCardTimeout,
92 : octapiDriver,
93 : opcscDriver,
94 : oDisableCCID,
95 : oDisableOpenSC,
96 : oDisablePinpad,
97 : oAllowAdmin,
98 : oDenyAdmin,
99 : oDisableApplication,
100 : oEnablePinpadVarlen,
101 : oDebugDisableTicker
102 : };
103 :
104 :
105 :
106 : static ARGPARSE_OPTS opts[] = {
107 : ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
108 : ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
109 :
110 : ARGPARSE_group (301, N_("@Options:\n ")),
111 :
112 : ARGPARSE_s_n (oServer,"server", N_("run in server mode (foreground)")),
113 : ARGPARSE_s_n (oMultiServer, "multi-server",
114 : N_("run in multi server mode (foreground)")),
115 : ARGPARSE_s_n (oDaemon, "daemon", N_("run in daemon mode (background)")),
116 : ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
117 : ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")),
118 : ARGPARSE_s_n (oSh, "sh", N_("sh-style command output")),
119 : ARGPARSE_s_n (oCsh, "csh", N_("csh-style command output")),
120 : ARGPARSE_s_s (oOptions, "options", N_("|FILE|read options from FILE")),
121 : ARGPARSE_s_s (oDebug, "debug", "@"),
122 : ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
123 : ARGPARSE_s_s (oDebugLevel, "debug-level" ,
124 : N_("|LEVEL|set the debugging level to LEVEL")),
125 : ARGPARSE_s_i (oDebugWait, "debug-wait", "@"),
126 : ARGPARSE_s_n (oDebugAllowCoreDump, "debug-allow-core-dump", "@"),
127 : ARGPARSE_s_n (oDebugCCIDDriver, "debug-ccid-driver", "@"),
128 : ARGPARSE_s_n (oDebugDisableTicker, "debug-disable-ticker", "@"),
129 : ARGPARSE_s_n (oDebugLogTid, "debug-log-tid", "@"),
130 : ARGPARSE_p_u (oDebugAssuanLogCats, "debug-assuan-log-cats", "@"),
131 : ARGPARSE_s_n (oNoDetach, "no-detach", N_("do not detach from the console")),
132 : ARGPARSE_s_s (oLogFile, "log-file", N_("|FILE|write a log to FILE")),
133 : ARGPARSE_s_s (oReaderPort, "reader-port",
134 : N_("|N|connect to reader at port N")),
135 : ARGPARSE_s_s (octapiDriver, "ctapi-driver",
136 : N_("|NAME|use NAME as ct-API driver")),
137 : ARGPARSE_s_s (opcscDriver, "pcsc-driver",
138 : N_("|NAME|use NAME as PC/SC driver")),
139 : ARGPARSE_s_n (oDisableCCID, "disable-ccid",
140 : #ifdef HAVE_LIBUSB
141 : N_("do not use the internal CCID driver")
142 : #else
143 : "@"
144 : #endif
145 : /* end --disable-ccid */),
146 : ARGPARSE_s_u (oCardTimeout, "card-timeout",
147 : N_("|N|disconnect the card after N seconds of inactivity")),
148 :
149 : ARGPARSE_s_n (oDisablePinpad, "disable-pinpad",
150 : N_("do not use a reader's pinpad")),
151 : ARGPARSE_ignore (300, "disable-keypad"),
152 :
153 : ARGPARSE_s_n (oAllowAdmin, "allow-admin", "@"),
154 : ARGPARSE_s_n (oDenyAdmin, "deny-admin",
155 : N_("deny the use of admin card commands")),
156 : ARGPARSE_s_s (oDisableApplication, "disable-application", "@"),
157 : ARGPARSE_s_n (oEnablePinpadVarlen, "enable-pinpad-varlen",
158 : N_("use variable length input for pinpad")),
159 : ARGPARSE_s_s (oHomedir, "homedir", "@"),
160 :
161 : ARGPARSE_end ()
162 : };
163 :
164 :
165 : /* The list of supported debug flags. */
166 : static struct debug_flags_s debug_flags [] =
167 : {
168 : { DBG_COMMAND_VALUE, "command" },
169 : { DBG_MPI_VALUE , "mpi" },
170 : { DBG_CRYPTO_VALUE , "crypto" },
171 : { DBG_MEMORY_VALUE , "memory" },
172 : { DBG_CACHE_VALUE , "cache" },
173 : { DBG_MEMSTAT_VALUE, "memstat" },
174 : { DBG_HASHING_VALUE, "hashing" },
175 : { DBG_IPC_VALUE , "ipc" },
176 : { DBG_CARD_IO_VALUE, "cardio" },
177 : { DBG_READER_VALUE , "reader" },
178 : { 0, NULL }
179 : };
180 :
181 :
182 : /* The card driver we use by default for PC/SC. */
183 : #if defined(HAVE_W32_SYSTEM) || defined(__CYGWIN__)
184 : #define DEFAULT_PCSC_DRIVER "winscard.dll"
185 : #elif defined(__APPLE__)
186 : #define DEFAULT_PCSC_DRIVER "/System/Library/Frameworks/PCSC.framework/PCSC"
187 : #elif defined(__GLIBC__)
188 : #define DEFAULT_PCSC_DRIVER "libpcsclite.so.1"
189 : #else
190 : #define DEFAULT_PCSC_DRIVER "libpcsclite.so"
191 : #endif
192 :
193 : /* The timer tick used for housekeeping stuff. We poll every 500ms to
194 : let the user immediately know a status change.
195 :
196 : This is not too good for power saving but given that there is no
197 : easy way to block on card status changes it is the best we can do.
198 : For PC/SC we could in theory use an extra thread to wait for status
199 : changes but that requires a native thread because there is no way
200 : to make the underlying PC/SC card change function block using a Npth
201 : mechanism. Given that a native thread could only be used under W32
202 : we don't do that at all. */
203 : #define TIMERTICK_INTERVAL_SEC (0)
204 : #define TIMERTICK_INTERVAL_USEC (500000)
205 :
206 : /* Flag to indicate that a shutdown was requested. */
207 : static int shutdown_pending;
208 :
209 : /* It is possible that we are currently running under setuid permissions */
210 : static int maybe_setuid = 1;
211 :
212 : /* Flag telling whether we are running as a pipe server. */
213 : static int pipe_server;
214 :
215 : /* Name of the communication socket */
216 : static char *socket_name;
217 : /* Name of the redirected socket or NULL. */
218 : static char *redir_socket_name;
219 :
220 : /* We need to keep track of the server's nonces (these are dummies for
221 : POSIX systems). */
222 : static assuan_sock_nonce_t socket_nonce;
223 :
224 : /* Debug flag to disable the ticker. The ticker is in fact not
225 : disabled but it won't perform any ticker specific actions. */
226 : static int ticker_disabled;
227 :
228 :
229 :
230 : static char *create_socket_name (char *standard_name);
231 : static gnupg_fd_t create_server_socket (const char *name,
232 : char **r_redir_name,
233 : assuan_sock_nonce_t *nonce);
234 :
235 : static void *start_connection_thread (void *arg);
236 : static void handle_connections (int listen_fd);
237 :
238 : /* Pth wrapper function definitions. */
239 0 : ASSUAN_SYSTEM_NPTH_IMPL;
240 :
241 : static int active_connections;
242 :
243 :
244 : static char *
245 0 : make_libversion (const char *libname, const char *(*getfnc)(const char*))
246 : {
247 : const char *s;
248 : char *result;
249 :
250 0 : if (maybe_setuid)
251 : {
252 0 : gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* Drop setuid. */
253 0 : maybe_setuid = 0;
254 : }
255 0 : s = getfnc (NULL);
256 0 : result = xmalloc (strlen (libname) + 1 + strlen (s) + 1);
257 0 : strcpy (stpcpy (stpcpy (result, libname), " "), s);
258 0 : return result;
259 : }
260 :
261 :
262 : static const char *
263 0 : my_strusage (int level)
264 : {
265 : static char *ver_gcry, *ver_ksba;
266 : const char *p;
267 :
268 0 : switch (level)
269 : {
270 0 : case 11: p = "@SCDAEMON@ (@GNUPG@)";
271 0 : break;
272 0 : case 13: p = VERSION; break;
273 0 : case 17: p = PRINTABLE_OS_NAME; break;
274 0 : case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
275 :
276 : case 20:
277 0 : if (!ver_gcry)
278 0 : ver_gcry = make_libversion ("libgcrypt", gcry_check_version);
279 0 : p = ver_gcry;
280 0 : break;
281 : case 21:
282 0 : if (!ver_ksba)
283 0 : ver_ksba = make_libversion ("libksba", ksba_check_version);
284 0 : p = ver_ksba;
285 0 : break;
286 : case 1:
287 0 : case 40: p = _("Usage: @SCDAEMON@ [options] (-h for help)");
288 0 : break;
289 0 : case 41: p = _("Syntax: scdaemon [options] [command [args]]\n"
290 : "Smartcard daemon for @GNUPG@\n");
291 0 : break;
292 :
293 0 : default: p = NULL;
294 : }
295 0 : return p;
296 : }
297 :
298 :
299 : static int
300 0 : tid_log_callback (unsigned long *rvalue)
301 : {
302 0 : int len = sizeof (*rvalue);
303 : npth_t thread;
304 :
305 0 : thread = npth_self ();
306 0 : if (sizeof (thread) < len)
307 0 : len = sizeof (thread);
308 0 : memcpy (rvalue, &thread, len);
309 :
310 0 : return 2; /* Use use hex representation. */
311 : }
312 :
313 :
314 : /* Setup the debugging. With a LEVEL of NULL only the active debug
315 : flags are propagated to the subsystems. With LEVEL set, a specific
316 : set of debug flags is set; thus overriding all flags already
317 : set. */
318 : static void
319 0 : set_debug (const char *level)
320 : {
321 0 : int numok = (level && digitp (level));
322 0 : int numlvl = numok? atoi (level) : 0;
323 :
324 0 : if (!level)
325 : ;
326 0 : else if (!strcmp (level, "none") || (numok && numlvl < 1))
327 0 : opt.debug = 0;
328 0 : else if (!strcmp (level, "basic") || (numok && numlvl <= 2))
329 0 : opt.debug = DBG_IPC_VALUE;
330 0 : else if (!strcmp (level, "advanced") || (numok && numlvl <= 5))
331 0 : opt.debug = DBG_IPC_VALUE|DBG_COMMAND_VALUE;
332 0 : else if (!strcmp (level, "expert") || (numok && numlvl <= 8))
333 0 : opt.debug = (DBG_IPC_VALUE|DBG_COMMAND_VALUE
334 : |DBG_CACHE_VALUE|DBG_CARD_IO_VALUE);
335 0 : else if (!strcmp (level, "guru") || numok)
336 : {
337 0 : opt.debug = ~0;
338 : /* Unless the "guru" string has been used we don't want to allow
339 : hashing debugging. The rationale is that people tend to
340 : select the highest debug value and would then clutter their
341 : disk with debug files which may reveal confidential data. */
342 0 : if (numok)
343 0 : opt.debug &= ~(DBG_HASHING_VALUE);
344 : }
345 : else
346 : {
347 0 : log_error (_("invalid debug-level '%s' given\n"), level);
348 0 : scd_exit(2);
349 : }
350 :
351 :
352 0 : if (opt.debug && !opt.verbose)
353 0 : opt.verbose = 1;
354 0 : if (opt.debug && opt.quiet)
355 0 : opt.quiet = 0;
356 :
357 0 : if (opt.debug & DBG_MPI_VALUE)
358 0 : gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2);
359 0 : if (opt.debug & DBG_CRYPTO_VALUE )
360 0 : gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
361 0 : gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
362 :
363 0 : if (opt.debug)
364 0 : parse_debug_flag (NULL, &opt.debug, debug_flags);
365 0 : }
366 :
367 :
368 :
369 : static void
370 0 : cleanup (void)
371 : {
372 0 : if (socket_name && *socket_name)
373 : {
374 : char *name;
375 :
376 0 : name = redir_socket_name? redir_socket_name : socket_name;
377 :
378 0 : gnupg_remove (name);
379 0 : *socket_name = 0;
380 : }
381 0 : }
382 :
383 :
384 :
385 : int
386 0 : main (int argc, char **argv )
387 : {
388 : ARGPARSE_ARGS pargs;
389 : int orig_argc;
390 : char **orig_argv;
391 0 : FILE *configfp = NULL;
392 0 : char *configname = NULL;
393 : const char *shell;
394 : unsigned int configlineno;
395 0 : int parse_debug = 0;
396 0 : const char *debug_level = NULL;
397 0 : int default_config =1;
398 0 : int greeting = 0;
399 0 : int nogreeting = 0;
400 0 : int multi_server = 0;
401 0 : int is_daemon = 0;
402 0 : int nodetach = 0;
403 0 : int csh_style = 0;
404 0 : char *logfile = NULL;
405 0 : int debug_wait = 0;
406 0 : int gpgconf_list = 0;
407 0 : const char *config_filename = NULL;
408 0 : int allow_coredump = 0;
409 : struct assuan_malloc_hooks malloc_hooks;
410 : int res;
411 : npth_t pipecon_handler;
412 :
413 0 : early_system_init ();
414 0 : set_strusage (my_strusage);
415 0 : gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
416 : /* Please note that we may running SUID(ROOT), so be very CAREFUL
417 : when adding any stuff between here and the call to INIT_SECMEM()
418 : somewhere after the option parsing */
419 0 : log_set_prefix ("scdaemon", GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_PID);
420 :
421 : /* Make sure that our subsystems are ready. */
422 0 : i18n_init ();
423 0 : init_common_subsystems (&argc, &argv);
424 :
425 0 : npth_init ();
426 :
427 0 : ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
428 :
429 0 : malloc_hooks.malloc = gcry_malloc;
430 0 : malloc_hooks.realloc = gcry_realloc;
431 0 : malloc_hooks.free = gcry_free;
432 0 : assuan_set_malloc_hooks (&malloc_hooks);
433 0 : assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
434 0 : assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);
435 0 : assuan_sock_init ();
436 0 : setup_libassuan_logging (&opt.debug, NULL);
437 :
438 0 : setup_libgcrypt_logging ();
439 0 : gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
440 :
441 0 : disable_core_dumps ();
442 :
443 : /* Set default options. */
444 0 : opt.allow_admin = 1;
445 0 : opt.pcsc_driver = DEFAULT_PCSC_DRIVER;
446 :
447 0 : shell = getenv ("SHELL");
448 0 : if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
449 0 : csh_style = 1;
450 :
451 : /* Check whether we have a config file on the commandline */
452 0 : orig_argc = argc;
453 0 : orig_argv = argv;
454 0 : pargs.argc = &argc;
455 0 : pargs.argv = &argv;
456 0 : pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */
457 0 : while (arg_parse( &pargs, opts))
458 : {
459 0 : if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
460 0 : parse_debug++;
461 0 : else if (pargs.r_opt == oOptions)
462 : { /* yes there is one, so we do not try the default one, but
463 : read the option file when it is encountered at the
464 : commandline */
465 0 : default_config = 0;
466 : }
467 0 : else if (pargs.r_opt == oNoOptions)
468 0 : default_config = 0; /* --no-options */
469 0 : else if (pargs.r_opt == oHomedir)
470 0 : gnupg_set_homedir (pargs.r.ret_str);
471 : }
472 :
473 : /* initialize the secure memory. */
474 0 : gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
475 0 : maybe_setuid = 0;
476 :
477 : /*
478 : Now we are working under our real uid
479 : */
480 :
481 :
482 0 : if (default_config)
483 0 : configname = make_filename (gnupg_homedir (), SCDAEMON_NAME EXTSEP_S "conf",
484 : NULL );
485 :
486 :
487 0 : argc = orig_argc;
488 0 : argv = orig_argv;
489 0 : pargs.argc = &argc;
490 0 : pargs.argv = &argv;
491 0 : pargs.flags= 1; /* do not remove the args */
492 : next_pass:
493 0 : if (configname)
494 : {
495 0 : configlineno = 0;
496 0 : configfp = fopen (configname, "r");
497 0 : if (!configfp)
498 : {
499 0 : if (default_config)
500 : {
501 0 : if( parse_debug )
502 0 : log_info (_("Note: no default option file '%s'\n"),
503 : configname );
504 : }
505 : else
506 : {
507 0 : log_error (_("option file '%s': %s\n"),
508 0 : configname, strerror(errno) );
509 0 : exit(2);
510 : }
511 0 : xfree (configname);
512 0 : configname = NULL;
513 : }
514 0 : if (parse_debug && configname )
515 0 : log_info (_("reading options from '%s'\n"), configname );
516 0 : default_config = 0;
517 : }
518 :
519 0 : while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) )
520 : {
521 0 : switch (pargs.r_opt)
522 : {
523 0 : case aGPGConfList: gpgconf_list = 1; break;
524 0 : case aGPGConfTest: gpgconf_list = 2; break;
525 0 : case oQuiet: opt.quiet = 1; break;
526 0 : case oVerbose: opt.verbose++; break;
527 0 : case oBatch: opt.batch=1; break;
528 :
529 : case oDebug:
530 0 : if (parse_debug_flag (pargs.r.ret_str, &opt.debug, debug_flags))
531 : {
532 0 : pargs.r_opt = ARGPARSE_INVALID_ARG;
533 0 : pargs.err = ARGPARSE_PRINT_ERROR;
534 : }
535 0 : break;
536 0 : case oDebugAll: opt.debug = ~0; break;
537 0 : case oDebugLevel: debug_level = pargs.r.ret_str; break;
538 0 : case oDebugWait: debug_wait = pargs.r.ret_int; break;
539 : case oDebugAllowCoreDump:
540 0 : enable_core_dumps ();
541 0 : allow_coredump = 1;
542 0 : break;
543 : case oDebugCCIDDriver:
544 : #ifdef HAVE_LIBUSB
545 0 : ccid_set_debug_level (ccid_set_debug_level (-1)+1);
546 : #endif /*HAVE_LIBUSB*/
547 0 : break;
548 0 : case oDebugDisableTicker: ticker_disabled = 1; break;
549 : case oDebugLogTid:
550 0 : log_set_pid_suffix_cb (tid_log_callback);
551 0 : break;
552 : case oDebugAssuanLogCats:
553 0 : set_libassuan_log_cats (pargs.r.ret_ulong);
554 0 : break;
555 :
556 : case oOptions:
557 : /* config files may not be nested (silently ignore them) */
558 0 : if (!configfp)
559 : {
560 0 : xfree(configname);
561 0 : configname = xstrdup(pargs.r.ret_str);
562 0 : goto next_pass;
563 : }
564 0 : break;
565 0 : case oNoGreeting: nogreeting = 1; break;
566 0 : case oNoVerbose: opt.verbose = 0; break;
567 0 : case oNoOptions: break; /* no-options */
568 0 : case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
569 0 : case oNoDetach: nodetach = 1; break;
570 0 : case oLogFile: logfile = pargs.r.ret_str; break;
571 0 : case oCsh: csh_style = 1; break;
572 0 : case oSh: csh_style = 0; break;
573 0 : case oServer: pipe_server = 1; break;
574 0 : case oMultiServer: pipe_server = 1; multi_server = 1; break;
575 0 : case oDaemon: is_daemon = 1; break;
576 :
577 0 : case oReaderPort: opt.reader_port = pargs.r.ret_str; break;
578 0 : case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break;
579 0 : case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break;
580 0 : case oDisableCCID: opt.disable_ccid = 1; break;
581 0 : case oDisableOpenSC: break;
582 :
583 0 : case oDisablePinpad: opt.disable_pinpad = 1; break;
584 :
585 : case oAllowAdmin: /* Dummy because allow is now the default. */
586 0 : break;
587 0 : case oDenyAdmin: opt.allow_admin = 0; break;
588 :
589 0 : case oCardTimeout: opt.card_timeout = pargs.r.ret_ulong; break;
590 :
591 : case oDisableApplication:
592 0 : add_to_strlist (&opt.disabled_applications, pargs.r.ret_str);
593 0 : break;
594 :
595 0 : case oEnablePinpadVarlen: opt.enable_pinpad_varlen = 1; break;
596 :
597 : default:
598 0 : pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
599 0 : break;
600 : }
601 : }
602 0 : if (configfp)
603 : {
604 0 : fclose( configfp );
605 0 : configfp = NULL;
606 : /* Keep a copy of the config name for use by --gpgconf-list. */
607 0 : config_filename = configname;
608 0 : configname = NULL;
609 0 : goto next_pass;
610 : }
611 0 : xfree (configname);
612 0 : configname = NULL;
613 0 : if (log_get_errorcount(0))
614 0 : exit(2);
615 0 : if (nogreeting )
616 0 : greeting = 0;
617 :
618 0 : if (greeting)
619 : {
620 0 : es_fprintf (es_stderr, "%s %s; %s\n",
621 : strusage(11), strusage(13), strusage(14) );
622 0 : es_fprintf (es_stderr, "%s\n", strusage(15) );
623 : }
624 : #ifdef IS_DEVELOPMENT_VERSION
625 : log_info ("NOTE: this is a development version!\n");
626 : #endif
627 :
628 : /* Print a warning if an argument looks like an option. */
629 0 : if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
630 : {
631 : int i;
632 :
633 0 : for (i=0; i < argc; i++)
634 0 : if (argv[i][0] == '-' && argv[i][1] == '-')
635 0 : log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
636 : }
637 :
638 0 : if (atexit (cleanup))
639 : {
640 0 : log_error ("atexit failed\n");
641 0 : cleanup ();
642 0 : exit (1);
643 : }
644 :
645 0 : set_debug (debug_level);
646 :
647 0 : initialize_module_command ();
648 :
649 0 : if (gpgconf_list == 2)
650 0 : scd_exit (0);
651 0 : if (gpgconf_list)
652 : {
653 : /* List options and default values in the GPG Conf format. */
654 0 : char *filename = NULL;
655 : char *filename_esc;
656 :
657 0 : if (config_filename)
658 0 : filename = xstrdup (config_filename);
659 : else
660 0 : filename = make_filename (gnupg_homedir (),
661 : SCDAEMON_NAME EXTSEP_S "conf", NULL);
662 0 : filename_esc = percent_escape (filename, NULL);
663 :
664 0 : es_printf ("%s-%s.conf:%lu:\"%s\n",
665 : GPGCONF_NAME, SCDAEMON_NAME,
666 : GC_OPT_FLAG_DEFAULT, filename_esc);
667 0 : xfree (filename_esc);
668 0 : xfree (filename);
669 :
670 0 : es_printf ("verbose:%lu:\n"
671 : "quiet:%lu:\n"
672 : "debug-level:%lu:\"none:\n"
673 : "log-file:%lu:\n",
674 : GC_OPT_FLAG_NONE,
675 : GC_OPT_FLAG_NONE,
676 : GC_OPT_FLAG_DEFAULT,
677 : GC_OPT_FLAG_NONE );
678 :
679 0 : es_printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE );
680 0 : es_printf ("ctapi-driver:%lu:\n", GC_OPT_FLAG_NONE );
681 0 : es_printf ("pcsc-driver:%lu:\"%s:\n",
682 : GC_OPT_FLAG_DEFAULT, DEFAULT_PCSC_DRIVER );
683 : #ifdef HAVE_LIBUSB
684 0 : es_printf ("disable-ccid:%lu:\n", GC_OPT_FLAG_NONE );
685 : #endif
686 0 : es_printf ("deny-admin:%lu:\n", GC_OPT_FLAG_NONE );
687 0 : es_printf ("disable-pinpad:%lu:\n", GC_OPT_FLAG_NONE );
688 0 : es_printf ("card-timeout:%lu:%d:\n", GC_OPT_FLAG_DEFAULT, 0);
689 0 : es_printf ("enable-pinpad-varlen:%lu:\n", GC_OPT_FLAG_NONE );
690 :
691 0 : scd_exit (0);
692 : }
693 :
694 : /* Now start with logging to a file if this is desired. */
695 0 : if (logfile)
696 : {
697 0 : log_set_file (logfile);
698 0 : log_set_prefix (NULL, GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_TIME | GPGRT_LOG_WITH_PID);
699 : }
700 :
701 0 : if (debug_wait && pipe_server)
702 : {
703 0 : log_debug ("waiting for debugger - my pid is %u .....\n",
704 0 : (unsigned int)getpid());
705 0 : gnupg_sleep (debug_wait);
706 0 : log_debug ("... okay\n");
707 : }
708 :
709 0 : if (pipe_server)
710 : {
711 : /* This is the simple pipe based server */
712 : ctrl_t ctrl;
713 : npth_attr_t tattr;
714 0 : int fd = -1;
715 :
716 : #ifndef HAVE_W32_SYSTEM
717 : {
718 : struct sigaction sa;
719 :
720 0 : sa.sa_handler = SIG_IGN;
721 0 : sigemptyset (&sa.sa_mask);
722 0 : sa.sa_flags = 0;
723 0 : sigaction (SIGPIPE, &sa, NULL);
724 : }
725 : #endif
726 :
727 : /* If --debug-allow-core-dump has been given we also need to
728 : switch the working directory to a place where we can actually
729 : write. */
730 0 : if (allow_coredump)
731 : {
732 0 : if (chdir("/tmp"))
733 0 : log_debug ("chdir to '/tmp' failed: %s\n", strerror (errno));
734 : else
735 0 : log_debug ("changed working directory to '/tmp'\n");
736 : }
737 :
738 : /* In multi server mode we need to listen on an additional
739 : socket. Create that socket now before starting the handler
740 : for the pipe connection. This allows that handler to send
741 : back the name of that socket. */
742 0 : if (multi_server)
743 : {
744 0 : socket_name = create_socket_name (SCDAEMON_SOCK_NAME);
745 0 : fd = FD2INT(create_server_socket (socket_name,
746 : &redir_socket_name, &socket_nonce));
747 : }
748 :
749 0 : res = npth_attr_init (&tattr);
750 0 : if (res)
751 : {
752 0 : log_error ("error allocating thread attributes: %s\n",
753 : strerror (res));
754 0 : scd_exit (2);
755 : }
756 0 : npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
757 :
758 0 : ctrl = xtrycalloc (1, sizeof *ctrl);
759 0 : if ( !ctrl )
760 : {
761 0 : log_error ("error allocating connection control data: %s\n",
762 0 : strerror (errno) );
763 0 : scd_exit (2);
764 : }
765 0 : ctrl->thread_startup.fd = GNUPG_INVALID_FD;
766 0 : res = npth_create (&pipecon_handler, &tattr, start_connection_thread, ctrl);
767 0 : if (res)
768 : {
769 0 : log_error ("error spawning pipe connection handler: %s\n",
770 : strerror (res) );
771 0 : xfree (ctrl);
772 0 : scd_exit (2);
773 : }
774 0 : npth_setname_np (pipecon_handler, "pipe-connection");
775 0 : npth_attr_destroy (&tattr);
776 :
777 : /* We run handle_connection to wait for the shutdown signal and
778 : to run the ticker stuff. */
779 0 : handle_connections (fd);
780 0 : if (fd != -1)
781 0 : close (fd);
782 : }
783 0 : else if (!is_daemon)
784 : {
785 0 : log_info (_("please use the option '--daemon'"
786 : " to run the program in the background\n"));
787 : }
788 : else
789 : { /* Regular server mode */
790 : int fd;
791 : #ifndef HAVE_W32_SYSTEM
792 : pid_t pid;
793 : int i;
794 : #endif
795 :
796 : /* Create the socket. */
797 0 : socket_name = create_socket_name (SCDAEMON_SOCK_NAME);
798 0 : fd = FD2INT (create_server_socket (socket_name,
799 : &redir_socket_name, &socket_nonce));
800 :
801 :
802 0 : fflush (NULL);
803 : #ifdef HAVE_W32_SYSTEM
804 : (void)csh_style;
805 : (void)nodetach;
806 : #else
807 0 : pid = fork ();
808 0 : if (pid == (pid_t)-1)
809 : {
810 0 : log_fatal ("fork failed: %s\n", strerror (errno) );
811 : exit (1);
812 : }
813 0 : else if (pid)
814 : { /* we are the parent */
815 : char *infostr;
816 :
817 0 : close (fd);
818 :
819 : /* create the info string: <name>:<pid>:<protocol_version> */
820 0 : if (gpgrt_asprintf (&infostr, "SCDAEMON_INFO=%s:%lu:1",
821 : socket_name, (ulong) pid) < 0)
822 : {
823 0 : log_error ("out of core\n");
824 0 : kill (pid, SIGTERM);
825 0 : exit (1);
826 : }
827 0 : *socket_name = 0; /* don't let cleanup() remove the socket -
828 : the child should do this from now on */
829 0 : if (argc)
830 : { /* run the program given on the commandline */
831 0 : if (putenv (infostr))
832 : {
833 0 : log_error ("failed to set environment: %s\n",
834 0 : strerror (errno) );
835 0 : kill (pid, SIGTERM );
836 0 : exit (1);
837 : }
838 0 : execvp (argv[0], argv);
839 0 : log_error ("failed to run the command: %s\n", strerror (errno));
840 0 : kill (pid, SIGTERM);
841 0 : exit (1);
842 : }
843 : else
844 : {
845 : /* Print the environment string, so that the caller can use
846 : shell's eval to set it */
847 0 : if (csh_style)
848 : {
849 0 : *strchr (infostr, '=') = ' ';
850 0 : es_printf ( "setenv %s;\n", infostr);
851 : }
852 : else
853 : {
854 0 : es_printf ( "%s; export SCDAEMON_INFO;\n", infostr);
855 : }
856 0 : xfree (infostr);
857 0 : exit (0);
858 : }
859 : /* NOTREACHED */
860 : } /* end parent */
861 :
862 : /* This is the child. */
863 :
864 : /* Detach from tty and put process into a new session. */
865 0 : if (!nodetach )
866 : {
867 : /* Close stdin, stdout and stderr unless it is the log stream. */
868 0 : for (i=0; i <= 2; i++)
869 : {
870 0 : if ( log_test_fd (i) && i != fd)
871 0 : close (i);
872 : }
873 0 : if (setsid() == -1)
874 : {
875 0 : log_error ("setsid() failed: %s\n", strerror(errno) );
876 0 : cleanup ();
877 0 : exit (1);
878 : }
879 : }
880 :
881 : {
882 : struct sigaction sa;
883 :
884 0 : sa.sa_handler = SIG_IGN;
885 0 : sigemptyset (&sa.sa_mask);
886 0 : sa.sa_flags = 0;
887 0 : sigaction (SIGPIPE, &sa, NULL);
888 : }
889 :
890 0 : if (chdir("/"))
891 : {
892 0 : log_error ("chdir to / failed: %s\n", strerror (errno));
893 0 : exit (1);
894 : }
895 :
896 : #endif /*!HAVE_W32_SYSTEM*/
897 :
898 0 : handle_connections (fd);
899 :
900 0 : close (fd);
901 : }
902 :
903 0 : return 0;
904 : }
905 :
906 : void
907 0 : scd_exit (int rc)
908 : {
909 0 : apdu_prepare_exit ();
910 : #if 0
911 : #warning no update_random_seed_file
912 : update_random_seed_file();
913 : #endif
914 : #if 0
915 : /* at this time a bit annoying */
916 : if (opt.debug & DBG_MEMSTAT_VALUE)
917 : {
918 : gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
919 : gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
920 : }
921 : if (opt.debug)
922 : gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
923 : #endif
924 0 : gcry_control (GCRYCTL_TERM_SECMEM );
925 0 : rc = rc? rc : log_get_errorcount(0)? 2 : 0;
926 0 : exit (rc);
927 : }
928 :
929 :
930 : static void
931 0 : scd_init_default_ctrl (ctrl_t ctrl)
932 : {
933 : (void)ctrl;
934 0 : }
935 :
936 : static void
937 0 : scd_deinit_default_ctrl (ctrl_t ctrl)
938 : {
939 0 : if (!ctrl)
940 0 : return;
941 0 : xfree (ctrl->in_data.value);
942 0 : ctrl->in_data.value = NULL;
943 0 : ctrl->in_data.valuelen = 0;
944 : }
945 :
946 :
947 : /* Return the name of the socket to be used to connect to this
948 : process. If no socket is available, return NULL. */
949 : const char *
950 0 : scd_get_socket_name ()
951 : {
952 0 : if (socket_name && *socket_name)
953 0 : return socket_name;
954 0 : return NULL;
955 : }
956 :
957 :
958 : #ifndef HAVE_W32_SYSTEM
959 : static void
960 0 : handle_signal (int signo)
961 : {
962 0 : switch (signo)
963 : {
964 : case SIGHUP:
965 0 : log_info ("SIGHUP received - "
966 : "re-reading configuration and resetting cards\n");
967 : /* reread_configuration (); */
968 0 : break;
969 :
970 : case SIGUSR1:
971 0 : log_info ("SIGUSR1 received - printing internal information:\n");
972 : /* Fixme: We need to see how to integrate pth dumping into our
973 : logging system. */
974 : /* pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ()); */
975 0 : app_dump_state ();
976 0 : break;
977 :
978 : case SIGUSR2:
979 0 : log_info ("SIGUSR2 received - no action defined\n");
980 0 : break;
981 :
982 : case SIGTERM:
983 0 : if (!shutdown_pending)
984 0 : log_info ("SIGTERM received - shutting down ...\n");
985 : else
986 0 : log_info ("SIGTERM received - still %i running threads\n",
987 : active_connections);
988 0 : shutdown_pending++;
989 0 : if (shutdown_pending > 2)
990 : {
991 0 : log_info ("shutdown forced\n");
992 0 : log_info ("%s %s stopped\n", strusage(11), strusage(13) );
993 0 : cleanup ();
994 0 : scd_exit (0);
995 : }
996 0 : break;
997 :
998 : case SIGINT:
999 0 : log_info ("SIGINT received - immediate shutdown\n");
1000 0 : log_info( "%s %s stopped\n", strusage(11), strusage(13));
1001 0 : cleanup ();
1002 0 : scd_exit (0);
1003 0 : break;
1004 :
1005 : default:
1006 0 : log_info ("signal %d received - no action defined\n", signo);
1007 : }
1008 0 : }
1009 : #endif /*!HAVE_W32_SYSTEM*/
1010 :
1011 :
1012 : static void
1013 0 : handle_tick (void)
1014 : {
1015 0 : if (!ticker_disabled)
1016 0 : scd_update_reader_status_file ();
1017 0 : }
1018 :
1019 :
1020 : /* Create a name for the socket. We check for valid characters as
1021 : well as against a maximum allowed length for a unix domain socket
1022 : is done. The function terminates the process in case of an error.
1023 : Retunrs: Pointer to an allcoated string with the absolute name of
1024 : the socket used. */
1025 : static char *
1026 0 : create_socket_name (char *standard_name)
1027 : {
1028 : char *name;
1029 :
1030 0 : name = make_filename (gnupg_socketdir (), standard_name, NULL);
1031 0 : if (strchr (name, PATHSEP_C))
1032 : {
1033 0 : log_error (("'%s' are not allowed in the socket name\n"), PATHSEP_S);
1034 0 : scd_exit (2);
1035 : }
1036 0 : return name;
1037 : }
1038 :
1039 :
1040 :
1041 : /* Create a Unix domain socket with NAME. Returns the file descriptor
1042 : or terminates the process in case of an error. If the socket has
1043 : been redirected the name of the real socket is stored as a malloced
1044 : string at R_REDIR_NAME. */
1045 : static gnupg_fd_t
1046 0 : create_server_socket (const char *name, char **r_redir_name,
1047 : assuan_sock_nonce_t *nonce)
1048 : {
1049 : struct sockaddr *addr;
1050 : struct sockaddr_un *unaddr;
1051 : socklen_t len;
1052 : gnupg_fd_t fd;
1053 : int rc;
1054 :
1055 0 : xfree (*r_redir_name);
1056 0 : *r_redir_name = NULL;
1057 :
1058 0 : fd = assuan_sock_new (AF_UNIX, SOCK_STREAM, 0);
1059 0 : if (fd == GNUPG_INVALID_FD)
1060 : {
1061 0 : log_error (_("can't create socket: %s\n"), strerror (errno));
1062 0 : scd_exit (2);
1063 : }
1064 :
1065 0 : unaddr = xmalloc (sizeof (*unaddr));
1066 0 : addr = (struct sockaddr*)unaddr;
1067 :
1068 : {
1069 : int redirected;
1070 :
1071 0 : if (assuan_sock_set_sockaddr_un (name, addr, &redirected))
1072 : {
1073 0 : if (errno == ENAMETOOLONG)
1074 0 : log_error (_("socket name '%s' is too long\n"), name);
1075 : else
1076 0 : log_error ("error preparing socket '%s': %s\n",
1077 : name, gpg_strerror (gpg_error_from_syserror ()));
1078 0 : scd_exit (2);
1079 : }
1080 0 : if (redirected)
1081 : {
1082 0 : *r_redir_name = xstrdup (unaddr->sun_path);
1083 0 : if (opt.verbose)
1084 0 : log_info ("redirecting socket '%s' to '%s'\n", name, *r_redir_name);
1085 : }
1086 : }
1087 :
1088 0 : len = SUN_LEN (unaddr);
1089 :
1090 0 : rc = assuan_sock_bind (fd, addr, len);
1091 0 : if (rc == -1 && errno == EADDRINUSE)
1092 : {
1093 0 : gnupg_remove (unaddr->sun_path);
1094 0 : rc = assuan_sock_bind (fd, addr, len);
1095 : }
1096 0 : if (rc != -1
1097 0 : && (rc=assuan_sock_get_nonce (addr, len, nonce)))
1098 0 : log_error (_("error getting nonce for the socket\n"));
1099 0 : if (rc == -1)
1100 : {
1101 0 : log_error (_("error binding socket to '%s': %s\n"),
1102 0 : unaddr->sun_path,
1103 : gpg_strerror (gpg_error_from_syserror ()));
1104 0 : assuan_sock_close (fd);
1105 0 : scd_exit (2);
1106 : }
1107 :
1108 0 : if (gnupg_chmod (unaddr->sun_path, "-rwx"))
1109 0 : log_error (_("can't set permissions of '%s': %s\n"),
1110 0 : unaddr->sun_path, strerror (errno));
1111 :
1112 0 : if (listen (FD2INT(fd), 5 ) == -1)
1113 : {
1114 0 : log_error (_("listen() failed: %s\n"),
1115 : gpg_strerror (gpg_error_from_syserror ()));
1116 0 : assuan_sock_close (fd);
1117 0 : scd_exit (2);
1118 : }
1119 :
1120 0 : if (opt.verbose)
1121 0 : log_info (_("listening on socket '%s'\n"), unaddr->sun_path);
1122 :
1123 0 : return fd;
1124 : }
1125 :
1126 :
1127 :
1128 : /* This is the standard connection thread's main function. */
1129 : static void *
1130 0 : start_connection_thread (void *arg)
1131 : {
1132 0 : ctrl_t ctrl = arg;
1133 :
1134 0 : if (ctrl->thread_startup.fd != GNUPG_INVALID_FD
1135 0 : && assuan_sock_check_nonce (ctrl->thread_startup.fd, &socket_nonce))
1136 : {
1137 0 : log_info (_("error reading nonce on fd %d: %s\n"),
1138 0 : FD2INT(ctrl->thread_startup.fd), strerror (errno));
1139 0 : assuan_sock_close (ctrl->thread_startup.fd);
1140 0 : xfree (ctrl);
1141 0 : return NULL;
1142 : }
1143 :
1144 0 : scd_init_default_ctrl (ctrl);
1145 0 : if (opt.verbose)
1146 0 : log_info (_("handler for fd %d started\n"),
1147 : FD2INT(ctrl->thread_startup.fd));
1148 :
1149 : /* If this is a pipe server, we request a shutdown if the command
1150 : handler asked for it. With the next ticker event and given that
1151 : no other connections are running the shutdown will then
1152 : happen. */
1153 0 : if (scd_command_handler (ctrl, FD2INT(ctrl->thread_startup.fd))
1154 0 : && pipe_server)
1155 0 : shutdown_pending = 1;
1156 :
1157 0 : if (opt.verbose)
1158 0 : log_info (_("handler for fd %d terminated\n"),
1159 : FD2INT (ctrl->thread_startup.fd));
1160 :
1161 0 : scd_deinit_default_ctrl (ctrl);
1162 0 : xfree (ctrl);
1163 0 : return NULL;
1164 : }
1165 :
1166 :
1167 : /* Connection handler loop. Wait for connection requests and spawn a
1168 : thread after accepting a connection. LISTEN_FD is allowed to be -1
1169 : in which case this code will only do regular timeouts and handle
1170 : signals. */
1171 : static void
1172 0 : handle_connections (int listen_fd)
1173 : {
1174 : npth_attr_t tattr;
1175 : struct sockaddr_un paddr;
1176 : socklen_t plen;
1177 : fd_set fdset, read_fdset;
1178 : int ret;
1179 : int fd;
1180 : int nfd;
1181 : struct timespec abstime;
1182 : struct timespec curtime;
1183 : struct timespec timeout;
1184 : int saved_errno;
1185 : #ifndef HAVE_W32_SYSTEM
1186 : int signo;
1187 : #endif
1188 :
1189 0 : ret = npth_attr_init(&tattr);
1190 : /* FIXME: Check error. */
1191 0 : npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
1192 :
1193 : #ifndef HAVE_W32_SYSTEM
1194 0 : npth_sigev_init ();
1195 0 : npth_sigev_add (SIGHUP);
1196 0 : npth_sigev_add (SIGUSR1);
1197 0 : npth_sigev_add (SIGUSR2);
1198 0 : npth_sigev_add (SIGINT);
1199 0 : npth_sigev_add (SIGTERM);
1200 0 : npth_sigev_fini ();
1201 : #endif
1202 :
1203 0 : FD_ZERO (&fdset);
1204 0 : nfd = 0;
1205 0 : if (listen_fd != -1)
1206 : {
1207 0 : FD_SET (listen_fd, &fdset);
1208 0 : nfd = listen_fd;
1209 : }
1210 :
1211 0 : npth_clock_gettime (&curtime);
1212 0 : timeout.tv_sec = TIMERTICK_INTERVAL_SEC;
1213 0 : timeout.tv_nsec = TIMERTICK_INTERVAL_USEC * 1000;
1214 0 : npth_timeradd (&curtime, &timeout, &abstime);
1215 : /* We only require abstime here. The others will be reused. */
1216 :
1217 : for (;;)
1218 : {
1219 0 : if (shutdown_pending)
1220 : {
1221 0 : if (active_connections == 0)
1222 0 : break; /* ready */
1223 :
1224 : /* Do not accept anymore connections but wait for existing
1225 : connections to terminate. We do this by clearing out all
1226 : file descriptors to wait for, so that the select will be
1227 : used to just wait on a signal or timeout event. */
1228 0 : FD_ZERO (&fdset);
1229 0 : listen_fd = -1;
1230 : }
1231 :
1232 0 : npth_clock_gettime (&curtime);
1233 0 : if (!(npth_timercmp (&curtime, &abstime, <)))
1234 : {
1235 : /* Timeout. */
1236 0 : handle_tick ();
1237 0 : timeout.tv_sec = TIMERTICK_INTERVAL_SEC;
1238 0 : timeout.tv_nsec = TIMERTICK_INTERVAL_USEC * 1000;
1239 0 : npth_timeradd (&curtime, &timeout, &abstime);
1240 : }
1241 0 : npth_timersub (&abstime, &curtime, &timeout);
1242 :
1243 : /* POSIX says that fd_set should be implemented as a structure,
1244 : thus a simple assignment is fine to copy the entire set. */
1245 0 : read_fdset = fdset;
1246 :
1247 : #ifndef HAVE_W32_SYSTEM
1248 0 : ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, &timeout, npth_sigev_sigmask());
1249 0 : saved_errno = errno;
1250 :
1251 0 : while (npth_sigev_get_pending(&signo))
1252 0 : handle_signal (signo);
1253 : #else
1254 : ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout, NULL, NULL);
1255 : saved_errno = errno;
1256 : #endif
1257 :
1258 0 : if (ret == -1 && saved_errno != EINTR)
1259 : {
1260 0 : log_error (_("npth_pselect failed: %s - waiting 1s\n"),
1261 : strerror (saved_errno));
1262 0 : npth_sleep (1);
1263 0 : continue;
1264 : }
1265 :
1266 0 : if (ret <= 0)
1267 : /* Timeout. Will be handled when calculating the next timeout. */
1268 0 : continue;
1269 :
1270 0 : if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset))
1271 : {
1272 : ctrl_t ctrl;
1273 :
1274 0 : plen = sizeof paddr;
1275 0 : fd = npth_accept (listen_fd, (struct sockaddr *)&paddr, &plen);
1276 0 : if (fd == -1)
1277 : {
1278 0 : log_error ("accept failed: %s\n", strerror (errno));
1279 : }
1280 0 : else if ( !(ctrl = xtrycalloc (1, sizeof *ctrl)) )
1281 : {
1282 0 : log_error ("error allocating connection control data: %s\n",
1283 0 : strerror (errno) );
1284 0 : close (fd);
1285 : }
1286 : else
1287 : {
1288 : char threadname[50];
1289 : npth_t thread;
1290 :
1291 0 : snprintf (threadname, sizeof threadname-1, "conn fd=%d", fd);
1292 0 : threadname[sizeof threadname -1] = 0;
1293 0 : ctrl->thread_startup.fd = INT2FD (fd);
1294 0 : ret = npth_create (&thread, &tattr, start_connection_thread, ctrl);
1295 0 : if (ret)
1296 : {
1297 0 : log_error ("error spawning connection handler: %s\n",
1298 : strerror (ret));
1299 0 : xfree (ctrl);
1300 0 : close (fd);
1301 : }
1302 : else
1303 0 : npth_setname_np (thread, threadname);
1304 : }
1305 0 : fd = -1;
1306 : }
1307 0 : }
1308 :
1309 0 : cleanup ();
1310 0 : log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
1311 0 : npth_attr_destroy (&tattr);
1312 0 : }
|