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