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