pcsc-lite  1.8.23
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-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 #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  (void)close(f);
689 
690  /* set mode so that the file is world readable even is umask is
691  * restrictive
692  * The file is used by libpcsclite */
693  (void)chmod(PCSCLITE_RUN_PID, mode);
694  }
695  else
696  Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_RUN_PID ": %s",
697  strerror(errno));
698  }
699 
700  /*
701  * post initialistion
702  */
703  Init = FALSE;
704 
705  /*
706  * Hotplug rescan
707  */
708  (void)signal(SIGUSR1, signal_trap);
709 
710  /*
711  * Initialize the comm structure
712  */
713 #ifdef USE_LIBSYSTEMD
714  if (SocketActivated)
715  rv = ListenExistingSocket(SD_LISTEN_FDS_START + 0);
716  else
717 #endif
718  rv = InitializeSocket();
719 
720  if (rv)
721  {
722  Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
723  at_exit();
724  }
725 
726  /*
727  * Initialize the contexts structure
728  */
729  rv = ContextsInitialize(customMaxThreadCounter, customMaxThreadCardHandles);
730 
731  if (rv == -1)
732  {
733  Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
734  at_exit();
735  }
736 
737  (void)signal(SIGPIPE, SIG_IGN);
738  (void)signal(SIGHUP, SIG_IGN); /* needed for Solaris. The signal is sent
739  * when the shell is existed */
740 
741 #if !defined(PCSCLITE_STATIC_DRIVER) && defined(USE_USB)
742  /*
743  * Set up the search for USB/PCMCIA devices
744  */
745  rv = HPSearchHotPluggables();
746 #ifndef USE_SERIAL
747  if (rv)
748  at_exit();
749 #endif
750 
751  rv = HPRegisterForHotplugEvents();
752  if (rv)
753  {
754  Log1(PCSC_LOG_ERROR, "HPRegisterForHotplugEvents failed");
755  at_exit();
756  }
757 
758  RFWaitForReaderInit();
759 #endif
760 
761  /* initialisation succeeded */
762  if (pipefd[1] >= 0)
763  {
764  char buf = 0;
765  ssize_t rr;
766 
767  /* write a 0 (success) to father process */
768  rr = write(pipefd[1], &buf, 1);
769  if (rr < 0)
770  {
771  Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
772  }
773  close(pipefd[1]);
774  pipefd[1] = -1;
775  }
776 
778 
779  Log1(PCSC_LOG_ERROR, "SVCServiceRunLoop returned");
780  return EXIT_FAILURE;
781 }
782 
783 static void at_exit(void)
784 {
785  Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR);
786 
787  clean_temp_files();
788 
789  if (pipefd[1] >= 0)
790  {
791  char buf;
792  ssize_t r;
793 
794  /* write the error code to father process */
795  buf = ExitValue;
796  r = write(pipefd[1], &buf, 1);
797  if (r < 0)
798  {
799  Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
800  }
801  close(pipefd[1]);
802  }
803 
804  exit(ExitValue);
805 }
806 
807 static void clean_temp_files(void)
808 {
809  int rv;
810 
811  if (!SocketActivated)
812  {
813  rv = remove(PCSCLITE_CSOCK_NAME);
814  if (rv != 0)
815  Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s",
816  strerror(errno));
817  }
818 
819  rv = remove(PCSCLITE_RUN_PID);
820  if (rv != 0)
821  Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_RUN_PID ": %s",
822  strerror(errno));
823 }
824 
825 static void signal_trap(int sig)
826 {
827  int r;
828 
829  r = write(signal_handler_fd[1], &sig, sizeof sig);
830  if (r < 0)
831  Log2(PCSC_LOG_ERROR, "write failed: %s", strerror(errno));
832 }
833 
834 static void print_version(void)
835 {
836  printf("%s version %s.\n", PACKAGE, VERSION);
837  printf("Copyright (C) 1999-2002 by David Corcoran <corcoran@musclecard.com>.\n");
838  printf("Copyright (C) 2001-2015 by Ludovic Rousseau <ludovic.rousseau@free.fr>.\n");
839  printf("Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.\n");
840  printf("Report bugs to <pcsclite-muscle@lists.alioth.debian.org>.\n");
841 
842  printf ("Enabled features:%s\n", PCSCLITE_FEATURES);
843 }
844 
845 static void print_usage(char const * const progname)
846 {
847  printf("Usage: %s options\n", progname);
848  printf("Options:\n");
849 #ifdef HAVE_GETOPT_LONG
850  printf(" -a, --apdu log APDU commands and results\n");
851  printf(" -c, --config path to reader.conf\n");
852  printf(" -f, --foreground run in foreground (no daemon),\n");
853  printf(" send logs to stdout instead of syslog\n");
854  printf(" -T, --color force use of colored logs\n");
855  printf(" -h, --help display usage information\n");
856  printf(" -H, --hotplug ask the daemon to rescan the available readers\n");
857  printf(" -v, --version display the program version number\n");
858  printf(" -d, --debug display lower level debug messages\n");
859  printf(" -i, --info display info level debug messages\n");
860  printf(" -e --error display error level debug messages (default level)\n");
861  printf(" -C --critical display critical only level debug messages\n");
862  printf(" --force-reader-polling ignore the IFD_GENERATE_HOTPLUG reader capability\n");
863  printf(" -t, --max-thread maximum number of threads (default %d)\n", PCSC_MAX_CONTEXT_THREADS);
864  printf(" -s, --max-card-handle-per-thread maximum number of card handle per thread (default: %d)\n", PCSC_MAX_CONTEXT_CARD_HANDLES);
865  printf(" -r, --max-card-handle-per-reader maximum number of card handle per reader (default: %d)\n", PCSC_MAX_READER_HANDLES);
866  printf(" -x, --auto-exit pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
867  printf(" -S, --reader-name-no-serial do not include the USB serial number in the name\n");
868  printf(" -I, --reader-name-no-interface do not include the USB interface name in the name\n");
869 #else
870  printf(" -a log APDU commands and results\n");
871  printf(" -c path to reader.conf\n");
872  printf(" -f run in foreground (no daemon), send logs to stdout instead of syslog\n");
873  printf(" -T force use of colored logs\n");
874  printf(" -d display debug messages.\n");
875  printf(" -i display info messages.\n");
876  printf(" -e display error messages (default level).\n");
877  printf(" -C display critical messages.\n");
878  printf(" -h display usage information\n");
879  printf(" -H ask the daemon to rescan the available readers\n");
880  printf(" -v display the program version number\n");
881  printf(" -t maximum number of threads\n");
882  printf(" -s maximum number of card handle per thread\n");
883  printf(" -r maximum number of card handle per reader\n");
884  printf(" -x pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
885 #endif
886 }
887 
#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&#39;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.