pcsc-lite  1.8.16
pcscdaemon.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
3  *
4  * Copyright (C) 1999-2002
5  * David Corcoran <corcoran@musclecard.com>
6  * Copyright (C) 2002-2011
7  * Ludovic Rousseau <ludovic.rousseau@free.fr>
8  *
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 
13 1. Redistributions of source code must retain the above copyright
14  notice, this list of conditions and the following disclaimer.
15 2. Redistributions in binary form must reproduce the above copyright
16  notice, this list of conditions and the following disclaimer in the
17  documentation and/or other materials provided with the distribution.
18 3. The name of the author may not be used to endorse or promote products
19  derived from this software without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
42 #include "config.h"
43 #include <time.h>
44 #include <signal.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include <errno.h>
49 #include <stdio.h>
50 #include <unistd.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #ifdef HAVE_GETOPT_H
54 #include <getopt.h>
55 #endif
56 
57 #include "misc.h"
58 #include "pcsclite.h"
59 #include "pcscd.h"
60 #include "debuglog.h"
61 #include "sd-daemon.h"
62 #include "winscard_msg.h"
63 #include "winscard_svc.h"
64 #include "sys_generic.h"
65 #include "hotplug.h"
66 #include "readerfactory.h"
67 #include "configfile.h"
68 #include "powermgt_generic.h"
69 #include "utils.h"
70 #include "eventhandler.h"
71 
72 #ifndef TRUE
73 #define TRUE 1
74 #define FALSE 0
75 #endif
76 
77 char AraKiri = FALSE;
78 static char Init = TRUE;
79 char AutoExit = FALSE;
80 char SocketActivated = FALSE;
81 static int ExitValue = EXIT_FAILURE;
82 int HPForceReaderPolling = 0;
83 static int pipefd[] = {-1, -1};
84 char Add_Serial_In_Name = TRUE;
85 char Add_Interface_In_Name = TRUE;
86 
87 /*
88  * Some internal functions
89  */
90 static void at_exit(void);
91 static void clean_temp_files(void);
92 static void signal_reload(int sig);
93 static void signal_trap(int);
94 static void print_version (void);
95 static void print_usage (char const * const);
96 
105 static void SVCServiceRunLoop(void)
106 {
107  int rsp;
108  LONG rv;
109  uint32_t dwClientID; /* Connection ID used to reference the Client */
110 
111  while (TRUE)
112  {
113  if (AraKiri)
114  {
115  /* stop the hotpug thread and waits its exit */
116 #ifdef USE_USB
117  (void)HPStopHotPluggables();
118 #endif
119  (void)SYS_Sleep(1);
120 
121  /* now stop all the drivers */
122  RFCleanupReaders();
123  EHDeinitializeEventStructures();
124  ContextsDeinitialize();
125  at_exit();
126  }
127 
128  switch (rsp = ProcessEventsServer(&dwClientID))
129  {
130 
131  case 0:
132  Log2(PCSC_LOG_DEBUG, "A new context thread creation is requested: %d", dwClientID);
133  rv = CreateContextThread(&dwClientID);
134 
135  if (rv != SCARD_S_SUCCESS)
136  Log1(PCSC_LOG_ERROR, "Problem during the context thread creation");
137  break;
138 
139  case 2:
140  /*
141  * timeout in ProcessEventsServer(): do nothing
142  * this is used to catch the Ctrl-C signal at some time when
143  * nothing else happens
144  */
145  break;
146 
147  case -1:
148  Log1(PCSC_LOG_ERROR, "Error in ProcessEventsServer");
149  break;
150 
151  case -2:
152  /* Nothing to do in case of a syscall interrupted
153  * It happens when SIGUSR1 (reload) or SIGINT (Ctrl-C) is received
154  * We just try again */
155  break;
156 
157  default:
158  Log2(PCSC_LOG_ERROR, "ProcessEventsServer unknown retval: %d",
159  rsp);
160  break;
161  }
162  }
163 }
164 
165 int main(int argc, char **argv)
166 {
167  int rv;
168  char setToForeground;
169  char HotPlug;
170  char *newReaderConfig;
171  struct stat fStatBuf;
172  int customMaxThreadCounter = 0;
173  int customMaxReaderHandles = 0;
174  int customMaxThreadCardHandles = 0;
175  int opt;
176  int limited_rights = FALSE;
177  int r;
178 #ifdef HAVE_GETOPT_LONG
179  int option_index = 0;
180  static struct option long_options[] = {
181  {"config", 1, NULL, 'c'},
182  {"foreground", 0, NULL, 'f'},
183  {"color", 0, NULL, 'T'},
184  {"help", 0, NULL, 'h'},
185  {"version", 0, NULL, 'v'},
186  {"apdu", 0, NULL, 'a'},
187  {"debug", 0, NULL, 'd'},
188  {"info", 0, NULL, 0},
189  {"error", 0, NULL, 'e'},
190  {"critical", 0, NULL, 'C'},
191  {"hotplug", 0, NULL, 'H'},
192  {"force-reader-polling", optional_argument, NULL, 0},
193  {"max-thread", 1, NULL, 't'},
194  {"max-card-handle-per-thread", 1, NULL, 's'},
195  {"max-card-handle-per-reader", 1, NULL, 'r'},
196  {"auto-exit", 0, NULL, 'x'},
197  {"reader-name-no-serial", 0, NULL, 'S'},
198  {"reader-name-no-interface", 0, NULL, 'I'},
199  {NULL, 0, NULL, 0}
200  };
201 #endif
202 #define OPT_STRING "c:fTdhvaeCHt:r:s:xSI"
203 
204  newReaderConfig = NULL;
205  setToForeground = FALSE;
206  HotPlug = FALSE;
207 
208  /*
209  * test the version
210  */
211  if (strcmp(PCSCLITE_VERSION_NUMBER, VERSION) != 0)
212  {
213  printf("BUILD ERROR: The release version number PCSCLITE_VERSION_NUMBER\n");
214  printf(" in pcsclite.h (%s) does not match the release version number\n",
216  printf(" generated in config.h (%s) (see configure.in).\n", VERSION);
217 
218  return EXIT_FAILURE;
219  }
220 
221  /*
222  * By default we create a daemon (not connected to any output)
223  * so log to syslog to have error messages.
224  */
225  DebugLogSetLogType(DEBUGLOG_SYSLOG_DEBUG);
226 
227  /* if the process is setuid or setgid it may have some restrictions */
228  limited_rights = (getgid() != getegid()) && (getuid() != 0);
229 
230  /*
231  * Handle any command line arguments
232  */
233 #ifdef HAVE_GETOPT_LONG
234  while ((opt = getopt_long (argc, argv, OPT_STRING, long_options, &option_index)) != -1) {
235 #else
236  while ((opt = getopt (argc, argv, OPT_STRING)) != -1) {
237 #endif
238  switch (opt) {
239 #ifdef HAVE_GETOPT_LONG
240  case 0:
241  if (strcmp(long_options[option_index].name,
242  "force-reader-polling") == 0)
243  HPForceReaderPolling = optarg ? abs(atoi(optarg)) : 1;
244  break;
245 #endif
246  case 'c':
247  if (limited_rights)
248  {
249  Log1(PCSC_LOG_CRITICAL, "Can't use a user specified config file");
250  return EXIT_FAILURE;
251  }
252  Log2(PCSC_LOG_INFO, "using new config file: %s", optarg);
253  newReaderConfig = optarg;
254  break;
255 
256  case 'f':
257  setToForeground = TRUE;
258  /* debug to stdout instead of default syslog */
259  DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
260  Log1(PCSC_LOG_INFO,
261  "pcscd set to foreground with debug send to stdout");
262  break;
263 
264  case 'T':
265  DebugLogSetLogType(DEBUGLOG_STDOUT_COLOR_DEBUG);
266  Log1(PCSC_LOG_INFO, "Force colored logs");
267  break;
268 
269  case 'd':
270  DebugLogSetLevel(PCSC_LOG_DEBUG);
271  break;
272 
273  case 'e':
274  DebugLogSetLevel(PCSC_LOG_ERROR);
275  break;
276 
277  case 'C':
278  DebugLogSetLevel(PCSC_LOG_CRITICAL);
279  break;
280 
281  case 'h':
282  print_usage (argv[0]);
283  return EXIT_SUCCESS;
284 
285  case 'v':
286  print_version ();
287  return EXIT_SUCCESS;
288 
289  case 'a':
290  if (limited_rights)
291  {
292  Log1(PCSC_LOG_CRITICAL, "Can't log APDU (restricted)");
293  return EXIT_FAILURE;
294  }
295  (void)DebugLogSetCategory(DEBUG_CATEGORY_APDU);
296  break;
297 
298  case 'H':
299  /* debug to stdout instead of default syslog */
300  DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
301  HotPlug = TRUE;
302  break;
303 
304  case 't':
305  customMaxThreadCounter = optarg ? atoi(optarg) : 0;
306  if (limited_rights && (customMaxThreadCounter < PCSC_MAX_CONTEXT_THREADS))
307  customMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS;
308  Log2(PCSC_LOG_INFO, "setting customMaxThreadCounter to: %d",
309  customMaxThreadCounter);
310  break;
311 
312  case 'r':
313  customMaxReaderHandles = optarg ? atoi(optarg) : 0;
314  if (limited_rights && (customMaxReaderHandles < PCSC_MAX_READER_HANDLES))
315  customMaxReaderHandles = PCSC_MAX_READER_HANDLES;
316  Log2(PCSC_LOG_INFO, "setting customMaxReaderHandles to: %d",
317  customMaxReaderHandles);
318  break;
319 
320  case 's':
321  customMaxThreadCardHandles = optarg ? atoi(optarg) : 0;
322  if (limited_rights && (customMaxThreadCardHandles < PCSC_MAX_CONTEXT_CARD_HANDLES))
323  customMaxThreadCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES;
324  Log2(PCSC_LOG_INFO, "setting customMaxThreadCardHandles to: %d",
325  customMaxThreadCardHandles);
326  break;
327 
328  case 'x':
329  AutoExit = TRUE;
330  Log2(PCSC_LOG_INFO, "Auto exit after %d seconds of inactivity",
331  TIME_BEFORE_SUICIDE);
332  break;
333 
334  case 'S':
335  Add_Serial_In_Name = FALSE;
336  break;
337 
338  case 'I':
339  Add_Interface_In_Name = FALSE;
340  break;
341 
342  default:
343  print_usage (argv[0]);
344  return EXIT_FAILURE;
345  }
346 
347  }
348 
349  if (argv[optind])
350  {
351  printf("Unknown option: %s\n", argv[optind]);
352  print_usage(argv[0]);
353  return EXIT_FAILURE;
354  }
355 
356  /*
357  * Check if systemd passed us any file descriptors
358  */
359  rv = sd_listen_fds(0);
360  if (rv > 1)
361  {
362  Log1(PCSC_LOG_CRITICAL, "Too many file descriptors received");
363  return EXIT_FAILURE;
364  }
365  else
366  {
367  if (rv == 1)
368  {
369  SocketActivated = TRUE;
370  Log1(PCSC_LOG_INFO, "Started by systemd");
371  }
372  else
373  SocketActivated = FALSE;
374  }
375 
376  /*
377  * test the presence of /var/run/pcscd/pcscd.comm
378  */
379 
380  rv = stat(PCSCLITE_CSOCK_NAME, &fStatBuf);
381 
382  /* if the file exist and pcscd was _not_ started by systemd */
383  if (rv == 0 && !SocketActivated)
384  {
385  pid_t pid;
386 
387  /* read the pid file to get the old pid and test if the old pcscd is
388  * still running
389  */
390  pid = GetDaemonPid();
391 
392  if (pid != -1)
393  {
394  if (HotPlug)
395  return SendHotplugSignal();
396 
397  rv = kill(pid, 0);
398  if (0 == rv)
399  {
400  Log1(PCSC_LOG_CRITICAL,
401  "file " PCSCLITE_CSOCK_NAME " already exists.");
402  Log2(PCSC_LOG_CRITICAL,
403  "Another pcscd (pid: %d) seems to be running.", pid);
404  return EXIT_FAILURE;
405  }
406  else
407  if (ESRCH == errno)
408  {
409  /* the old pcscd is dead. make some cleanup */
410  clean_temp_files();
411  }
412  else
413  {
414  /* permission denied or other error */
415  Log2(PCSC_LOG_CRITICAL, "kill failed: %s", strerror(errno));
416  return EXIT_FAILURE;
417  }
418  }
419  else
420  {
421  if (HotPlug)
422  {
423  Log1(PCSC_LOG_CRITICAL, "file " PCSCLITE_RUN_PID " do not exist");
424  Log1(PCSC_LOG_CRITICAL, "Hotplug failed");
425  return EXIT_FAILURE;
426  }
427  }
428  }
429  else
430  if (HotPlug)
431  {
432  Log1(PCSC_LOG_CRITICAL, "Hotplug failed: pcscd is not running");
433  return EXIT_FAILURE;
434  }
435 
436  /* like in daemon(3): changes the current working directory to the
437  * root ("/") */
438  r = chdir("/");
439  if (r < 0)
440  {
441  Log2(PCSC_LOG_CRITICAL, "chdir() failed: %s", strerror(errno));
442  return EXIT_FAILURE;
443  }
444 
445  /*
446  * If this is set to one the user has asked it not to fork
447  */
448  if (!setToForeground)
449  {
450  int pid;
451  int fd;
452 
453  if (pipe(pipefd) == -1)
454  {
455  Log2(PCSC_LOG_CRITICAL, "pipe() failed: %s", strerror(errno));
456  return EXIT_FAILURE;
457  }
458 
459  pid = fork();
460  if (-1 == pid)
461  {
462  Log2(PCSC_LOG_CRITICAL, "fork() failed: %s", strerror(errno));
463  return EXIT_FAILURE;
464  }
465 
466  /* like in daemon(3): redirect standard input, standard output
467  * and standard error to /dev/null */
468  fd = open("/dev/null", O_RDWR);
469  if (fd != -1)
470  {
471  dup2(fd, STDIN_FILENO);
472  dup2(fd, STDOUT_FILENO);
473  dup2(fd, STDERR_FILENO);
474 
475  /* do not close stdin, stdout or stderr */
476  if (fd > 2)
477  close(fd);
478  }
479 
480  if (pid)
481  /* in the father */
482  {
483  char buf;
484  int ret;
485 
486  /* close write side */
487  close(pipefd[1]);
488 
489  /* wait for the son to write the return code */
490  ret = read(pipefd[0], &buf, 1);
491  if (ret <= 0)
492  return 2;
493 
494  close(pipefd[0]);
495 
496  /* exit code */
497  return buf;
498  }
499  else
500  /* in the son */
501  {
502  /* close read side */
503  close(pipefd[0]);
504  }
505  }
506 
507  /*
508  * cleanly remove /var/run/pcscd/files when exiting
509  * signal_trap() does just set a global variable used by the main loop
510  */
511  (void)signal(SIGQUIT, signal_trap);
512  (void)signal(SIGTERM, signal_trap); /* default kill signal & init round 1 */
513  (void)signal(SIGINT, signal_trap); /* sent by Ctrl-C */
514 
515  /* exits on SIGALARM to allow pcscd to suicide if not used */
516  (void)signal(SIGALRM, signal_trap);
517 
518  /*
519  * If PCSCLITE_IPC_DIR does not exist then create it
520  */
521  {
522  int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;
523 
524  rv = mkdir(PCSCLITE_IPC_DIR, mode);
525  if ((rv != 0) && (errno != EEXIST))
526  {
527  Log2(PCSC_LOG_CRITICAL,
528  "cannot create " PCSCLITE_IPC_DIR ": %s", strerror(errno));
529  return EXIT_FAILURE;
530  }
531 
532  /* set mode so that the directory is world readable and
533  * executable even is umask is restrictive
534  * The directory containes files used by libpcsclite */
535  (void)chmod(PCSCLITE_IPC_DIR, mode);
536  }
537 
538  /*
539  * Allocate memory for reader structures
540  */
541  rv = RFAllocateReaderSpace(customMaxReaderHandles);
542  if (SCARD_S_SUCCESS != rv)
543  at_exit();
544 
545 #ifdef USE_SERIAL
546  /*
547  * Grab the information from the reader.conf
548  */
549  if (newReaderConfig)
550  {
551  rv = RFStartSerialReaders(newReaderConfig);
552  if (rv != 0)
553  {
554  Log3(PCSC_LOG_CRITICAL, "invalid file %s: %s", newReaderConfig,
555  strerror(errno));
556  at_exit();
557  }
558  }
559  else
560  {
561  rv = RFStartSerialReaders(PCSCLITE_CONFIG_DIR);
562  if (rv == -1)
563  at_exit();
564  }
565 #endif
566 
567  Log1(PCSC_LOG_INFO, "pcsc-lite " VERSION " daemon ready.");
568 
569  /*
570  * Record our pid to make it easier
571  * to kill the correct pcscd
572  *
573  * Do not fork after this point or the stored pid will be wrong
574  */
575  {
576  int f;
577  int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
578 
579  f = open(PCSCLITE_RUN_PID, O_RDWR | O_CREAT, mode);
580  if (f != -1)
581  {
582  char pid[PID_ASCII_SIZE];
583  ssize_t rr;
584 
585  (void)snprintf(pid, sizeof(pid), "%u\n", (unsigned) getpid());
586  rr = write(f, pid, strlen(pid) + 1);
587  if (rr < 0)
588  {
589  Log2(PCSC_LOG_CRITICAL,
590  "writing " PCSCLITE_RUN_PID " failed: %s",
591  strerror(errno));
592  }
593  (void)close(f);
594 
595  /* set mode so that the file is world readable even is umask is
596  * restrictive
597  * The file is used by libpcsclite */
598  (void)chmod(PCSCLITE_RUN_PID, mode);
599  }
600  else
601  Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_RUN_PID ": %s",
602  strerror(errno));
603  }
604 
605  /*
606  * post initialistion
607  */
608  Init = FALSE;
609 
610  /*
611  * Hotplug rescan
612  */
613  (void)signal(SIGUSR1, signal_reload);
614 
615  /*
616  * Initialize the comm structure
617  */
618  if (SocketActivated)
619  rv = ListenExistingSocket(SD_LISTEN_FDS_START + 0);
620  else
621  rv = InitializeSocket();
622 
623  if (rv)
624  {
625  Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
626  at_exit();
627  }
628 
629  /*
630  * Initialize the contexts structure
631  */
632  rv = ContextsInitialize(customMaxThreadCounter, customMaxThreadCardHandles);
633 
634  if (rv == -1)
635  {
636  Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
637  at_exit();
638  }
639 
640  (void)signal(SIGPIPE, SIG_IGN);
641  (void)signal(SIGHUP, SIG_IGN); /* needed for Solaris. The signal is sent
642  * when the shell is existed */
643 
644 #if !defined(PCSCLITE_STATIC_DRIVER) && defined(USE_USB)
645  /*
646  * Set up the search for USB/PCMCIA devices
647  */
648  rv = HPSearchHotPluggables();
649 #ifndef USE_SERIAL
650  if (rv)
651  at_exit();
652 #endif
653 
654  rv = HPRegisterForHotplugEvents();
655  if (rv)
656  {
657  Log1(PCSC_LOG_ERROR, "HPRegisterForHotplugEvents failed");
658  at_exit();
659  }
660 
661  RFWaitForReaderInit();
662 #endif
663 
664  /*
665  * Set up the power management callback routine
666  */
667  (void)PMRegisterForPowerEvents();
668 
669  /* initialisation succeeded */
670  if (pipefd[1] >= 0)
671  {
672  char buf = 0;
673  ssize_t rr;
674 
675  /* write a 0 (success) to father process */
676  rr = write(pipefd[1], &buf, 1);
677  if (rr < 0)
678  {
679  Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
680  }
681  close(pipefd[1]);
682  pipefd[1] = -1;
683  }
684 
686 
687  Log1(PCSC_LOG_ERROR, "SVCServiceRunLoop returned");
688  return EXIT_FAILURE;
689 }
690 
691 static void at_exit(void)
692 {
693  Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR);
694 
695  clean_temp_files();
696 
697  if (pipefd[1] >= 0)
698  {
699  char buf;
700  ssize_t r;
701 
702  /* write the error code to father process */
703  buf = ExitValue;
704  r = write(pipefd[1], &buf, 1);
705  if (r < 0)
706  {
707  Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
708  }
709  close(pipefd[1]);
710  }
711 
712  exit(ExitValue);
713 }
714 
715 static void clean_temp_files(void)
716 {
717  int rv;
718 
719  if (!SocketActivated)
720  {
721  rv = remove(PCSCLITE_CSOCK_NAME);
722  if (rv != 0)
723  Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s",
724  strerror(errno));
725  }
726 
727  rv = remove(PCSCLITE_RUN_PID);
728  if (rv != 0)
729  Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_RUN_PID ": %s",
730  strerror(errno));
731 }
732 
733 static void signal_reload(/*@unused@*/ int sig)
734 {
735  (void)signal(SIGUSR1, signal_reload);
736 
737  (void)sig;
738 
739  if (AraKiri)
740  return;
741 
742 #ifdef USE_USB
743  HPReCheckSerialReaders();
744 #endif
745 } /* signal_reload */
746 
747 static void signal_trap(int sig)
748 {
749  Log2(PCSC_LOG_INFO, "Received signal: %d", sig);
750 
751  /* do not wait if asked to terminate
752  * avoids waiting after the reader(s) in shutdown for example */
753  if (SIGTERM == sig)
754  {
755  Log1(PCSC_LOG_INFO, "Direct suicide");
756  at_exit();
757  }
758 
759  if (SIGALRM == sig)
760  {
761  /* normal exit without error */
762  ExitValue = EXIT_SUCCESS;
763  }
764 
765  /* the signal handler is called several times for the same Ctrl-C */
766  if (AraKiri == FALSE)
767  {
768  Log1(PCSC_LOG_INFO, "Preparing for suicide");
769  AraKiri = TRUE;
770 
771  /* if still in the init/loading phase the AraKiri will not be
772  * seen by the main event loop
773  */
774  if (Init)
775  {
776  Log1(PCSC_LOG_INFO, "Suicide during init");
777  at_exit();
778  }
779  }
780  else
781  {
782  /* if pcscd do not want to die */
783  static int lives = 2;
784 
785  lives--;
786  /* no live left. Something is blocking the normal death. */
787  if (0 == lives)
788  {
789  Log1(PCSC_LOG_INFO, "Forced suicide");
790  at_exit();
791  }
792  }
793 }
794 
795 static void print_version (void)
796 {
797  printf("%s version %s.\n", PACKAGE, VERSION);
798  printf("Copyright (C) 1999-2002 by David Corcoran <corcoran@musclecard.com>.\n");
799  printf("Copyright (C) 2001-2015 by Ludovic Rousseau <ludovic.rousseau@free.fr>.\n");
800  printf("Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.\n");
801  printf("Report bugs to <pcsclite-muscle@lists.alioth.debian.org>.\n");
802 
803  printf ("Enabled features:%s\n", PCSCLITE_FEATURES);
804 }
805 
806 static void print_usage (char const * const progname)
807 {
808  printf("Usage: %s options\n", progname);
809  printf("Options:\n");
810 #ifdef HAVE_GETOPT_LONG
811  printf(" -a, --apdu log APDU commands and results\n");
812  printf(" -c, --config path to reader.conf\n");
813  printf(" -f, --foreground run in foreground (no daemon),\n");
814  printf(" send logs to stdout instead of syslog\n");
815  printf(" -T, --color force use of colored logs\n");
816  printf(" -h, --help display usage information\n");
817  printf(" -H, --hotplug ask the daemon to rescan the available readers\n");
818  printf(" -v, --version display the program version number\n");
819  printf(" -d, --debug display lower level debug messages\n");
820  printf(" --info display info level debug messages\n");
821  printf(" -e --error display error level debug messages (default level)\n");
822  printf(" -C --critical display critical only level debug messages\n");
823  printf(" --force-reader-polling ignore the IFD_GENERATE_HOTPLUG reader capability\n");
824  printf(" -t, --max-thread maximum number of threads (default %d)\n", PCSC_MAX_CONTEXT_THREADS);
825  printf(" -s, --max-card-handle-per-thread maximum number of card handle per thread (default: %d)\n", PCSC_MAX_CONTEXT_CARD_HANDLES);
826  printf(" -r, --max-card-handle-per-reader maximum number of card handle per reader (default: %d)\n", PCSC_MAX_READER_HANDLES);
827  printf(" -x, --auto-exit pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
828  printf(" -S, --reader-name-no-serial do not include the USB serial number in the name\n");
829  printf(" -I, --reader-name-no-interface do not include the USB interface name in the name\n");
830 #else
831  printf(" -a log APDU commands and results\n");
832  printf(" -c path to reader.conf\n");
833  printf(" -f run in foreground (no daemon), send logs to stdout instead of syslog\n");
834  printf(" -T force use of colored logs\n");
835  printf(" -d display debug messages.\n");
836  printf(" -e display error messages (default level).\n");
837  printf(" -C display critical messages.\n");
838  printf(" -h display usage information\n");
839  printf(" -H ask the daemon to rescan the available readers\n");
840  printf(" -v display the program version number\n");
841  printf(" -t maximum number of threads\n");
842  printf(" -s maximum number of card handle per thread\n");
843  printf(" -r maximum number of card handle per reader\n");
844  printf(" -x pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
845 #endif
846 }
847 
#define SCARD_S_SUCCESS
No error was encountered.
Definition: pcsclite.h:107
INTERNAL int32_t ListenExistingSocket(int fd)
Acquires a socket passed in from systemd.
LONG CreateContextThread(uint32_t *pdwClientID)
Creates threads to handle messages received from Clients.
Definition: winscard_svc.c:168
This handles power management routines.
This handles abstract system level calls.
char AutoExit
Represents an Application Context on the Server side.
Definition: pcscdaemon.c:79
int SYS_Sleep(int)
Makes the current process sleep for some seconds.
Definition: sys_unix.c:65
This demarshalls functions over the message queue and keeps track of clients and their handles...
This defines some structures and #defines to be used over the transport layer.
INTERNAL int32_t InitializeSocket(void)
Prepares the communication channel used by the server to talk to the clients.
ULONG PMRegisterForPowerEvents(void)
Registers for Power Management callbacks.
This handles card insertion/removal events, updates ATR, protocol, and status information.
static void SVCServiceRunLoop(void)
The Server's Message Queue Listener function.
Definition: pcscdaemon.c:105
This keeps a list of defines for pcsc-lite.
This keeps a list of defines for pcsc-lite.
INTERNAL int32_t ProcessEventsServer(uint32_t *pdwClientID)
Looks for messages sent by clients.
This keeps track of a list of currently available reader structures.
This provides a search API for hot pluggble devices.
#define PCSCLITE_VERSION_NUMBER
Current version.
Definition: pcsclite.h:282
This handles debugging.