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