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