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 "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, 0},
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:fTdhvaeCHt: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 'e':
358  DebugLogSetLevel(PCSC_LOG_ERROR);
359  break;
360 
361  case 'C':
362  DebugLogSetLevel(PCSC_LOG_CRITICAL);
363  break;
364 
365  case 'h':
366  print_usage (argv[0]);
367  return EXIT_SUCCESS;
368 
369  case 'v':
370  print_version ();
371  return EXIT_SUCCESS;
372 
373  case 'a':
374  DebugLogSetCategory(DEBUG_CATEGORY_APDU);
375  break;
376 
377  case 'H':
378  /* debug to stdout instead of default syslog */
379  DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
380  HotPlug = TRUE;
381  break;
382 
383  case 't':
384  customMaxThreadCounter = optarg ? atoi(optarg) : 0;
385  Log2(PCSC_LOG_INFO, "setting customMaxThreadCounter to: %d",
386  customMaxThreadCounter);
387  break;
388 
389  case 'r':
390  customMaxReaderHandles = optarg ? atoi(optarg) : 0;
391  Log2(PCSC_LOG_INFO, "setting customMaxReaderHandles to: %d",
392  customMaxReaderHandles);
393  break;
394 
395  case 's':
396  customMaxThreadCardHandles = optarg ? atoi(optarg) : 0;
397  Log2(PCSC_LOG_INFO, "setting customMaxThreadCardHandles to: %d",
398  customMaxThreadCardHandles);
399  break;
400 
401  case 'x':
402  AutoExit = TRUE;
403  Log2(PCSC_LOG_INFO, "Auto exit after %d seconds of inactivity",
404  TIME_BEFORE_SUICIDE);
405  break;
406 
407  case 'S':
408  Add_Serial_In_Name = FALSE;
409  break;
410 
411  case 'I':
412  Add_Interface_In_Name = FALSE;
413  break;
414 
415  default:
416  print_usage (argv[0]);
417  return EXIT_FAILURE;
418  }
419 
420  }
421 
422  if (argv[optind])
423  {
424  printf("Unknown option: %s\n", argv[optind]);
425  print_usage(argv[0]);
426  return EXIT_FAILURE;
427  }
428 
429  /*
430  * Check if systemd passed us any file descriptors
431  */
432  rv = sd_listen_fds(0);
433  if (rv > 1)
434  {
435  Log1(PCSC_LOG_CRITICAL, "Too many file descriptors received");
436  return EXIT_FAILURE;
437  }
438  else
439  {
440  if (rv == 1)
441  {
442  SocketActivated = TRUE;
443  Log1(PCSC_LOG_INFO, "Started by systemd");
444  }
445  else
446  SocketActivated = FALSE;
447  }
448 
449  /*
450  * test the presence of /var/run/pcscd/pcscd.comm
451  */
452 
453  rv = stat(PCSCLITE_CSOCK_NAME, &fStatBuf);
454 
455  /* if the file exist and pcscd was _not_ started by systemd */
456  if (rv == 0 && !SocketActivated)
457  {
458  pid_t pid;
459 
460  /* read the pid file to get the old pid and test if the old pcscd is
461  * still running
462  */
463  pid = GetDaemonPid();
464 
465  if (pid != -1)
466  {
467  if (HotPlug)
468  return SendHotplugSignal();
469 
470  rv = kill(pid, 0);
471  if (0 == rv)
472  {
473  Log1(PCSC_LOG_CRITICAL,
474  "file " PCSCLITE_CSOCK_NAME " already exists.");
475  Log2(PCSC_LOG_CRITICAL,
476  "Another pcscd (pid: %ld) seems to be running.", (long)pid);
477  return EXIT_FAILURE;
478  }
479  else
480  if (ESRCH == errno)
481  {
482  /* the old pcscd is dead. make some cleanup */
483  clean_temp_files();
484  }
485  else
486  {
487  /* permission denied or other error */
488  Log2(PCSC_LOG_CRITICAL, "kill failed: %s", strerror(errno));
489  return EXIT_FAILURE;
490  }
491  }
492  else
493  {
494  if (HotPlug)
495  {
496  Log1(PCSC_LOG_CRITICAL, "file " PCSCLITE_RUN_PID " do not exist");
497  Log1(PCSC_LOG_CRITICAL, "Hotplug failed");
498  return EXIT_FAILURE;
499  }
500  }
501  }
502  else
503  if (HotPlug)
504  {
505  Log1(PCSC_LOG_CRITICAL, "Hotplug failed: pcscd is not running");
506  return EXIT_FAILURE;
507  }
508 
509  /* like in daemon(3): changes the current working directory to the
510  * root ("/") */
511  r = chdir("/");
512  if (r < 0)
513  {
514  Log2(PCSC_LOG_CRITICAL, "chdir() failed: %s", strerror(errno));
515  return EXIT_FAILURE;
516  }
517 
518  /*
519  * If this is set to one the user has asked it not to fork
520  */
521  if (!setToForeground)
522  {
523  int pid;
524  int fd;
525 
526  if (pipe(pipefd) == -1)
527  {
528  Log2(PCSC_LOG_CRITICAL, "pipe() failed: %s", strerror(errno));
529  return EXIT_FAILURE;
530  }
531 
532  pid = fork();
533  if (-1 == pid)
534  {
535  Log2(PCSC_LOG_CRITICAL, "fork() failed: %s", strerror(errno));
536  return EXIT_FAILURE;
537  }
538 
539  /* like in daemon(3): redirect standard input, standard output
540  * and standard error to /dev/null */
541  fd = open("/dev/null", O_RDWR);
542  if (fd != -1)
543  {
544  dup2(fd, STDIN_FILENO);
545  dup2(fd, STDOUT_FILENO);
546  dup2(fd, STDERR_FILENO);
547 
548  /* do not close stdin, stdout or stderr */
549  if (fd > 2)
550  close(fd);
551  }
552 
553  if (pid)
554  /* in the father */
555  {
556  char buf;
557  int ret;
558 
559  /* close write side */
560  close(pipefd[1]);
561 
562  /* wait for the son to write the return code */
563  ret = read(pipefd[0], &buf, 1);
564  if (ret <= 0)
565  return 2;
566 
567  close(pipefd[0]);
568 
569  /* exit code */
570  return buf;
571  }
572  else
573  /* in the son */
574  {
575  /* close read side */
576  close(pipefd[0]);
577  }
578  }
579 
580  /*
581  * cleanly remove /var/run/pcscd/files when exiting
582  * signal_trap() does just set a global variable used by the main loop
583  */
584  (void)signal(SIGQUIT, signal_trap);
585  (void)signal(SIGTERM, signal_trap); /* default kill signal & init round 1 */
586  (void)signal(SIGINT, signal_trap); /* sent by Ctrl-C */
587 
588  /* exits on SIGALARM to allow pcscd to suicide if not used */
589  (void)signal(SIGALRM, signal_trap);
590 
591  if (pipe(signal_handler_fd) == -1)
592  {
593  Log2(PCSC_LOG_CRITICAL, "pipe() failed: %s", strerror(errno));
594  return EXIT_FAILURE;
595  }
596 
597  pthread_t signal_handler_thread;
598  rv = pthread_create(&signal_handler_thread, NULL, signal_thread, NULL);
599  if (rv)
600  {
601  Log2(PCSC_LOG_CRITICAL, "pthread_create failed: %s", strerror(rv));
602  return EXIT_FAILURE;
603  }
604 
605  /*
606  * If PCSCLITE_IPC_DIR does not exist then create it
607  */
608  {
609  int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;
610 
611  rv = mkdir(PCSCLITE_IPC_DIR, mode);
612  if ((rv != 0) && (errno != EEXIST))
613  {
614  Log2(PCSC_LOG_CRITICAL,
615  "cannot create " PCSCLITE_IPC_DIR ": %s", strerror(errno));
616  return EXIT_FAILURE;
617  }
618 
619  /* set mode so that the directory is world readable and
620  * executable even is umask is restrictive
621  * The directory containes files used by libpcsclite */
622  (void)chmod(PCSCLITE_IPC_DIR, mode);
623  }
624 
625  /*
626  * Allocate memory for reader structures
627  */
628  rv = RFAllocateReaderSpace(customMaxReaderHandles);
629  if (SCARD_S_SUCCESS != rv)
630  at_exit();
631 
632 #ifdef USE_SERIAL
633  /*
634  * Grab the information from the reader.conf
635  */
636  if (newReaderConfig)
637  {
638  rv = RFStartSerialReaders(newReaderConfig);
639  if (rv != 0)
640  {
641  Log3(PCSC_LOG_CRITICAL, "invalid file %s: %s", newReaderConfig,
642  strerror(errno));
643  at_exit();
644  }
645  }
646  else
647  {
648  rv = RFStartSerialReaders(PCSCLITE_CONFIG_DIR);
649  if (rv == -1)
650  at_exit();
651  }
652 #endif
653 
654  Log1(PCSC_LOG_INFO, "pcsc-lite " VERSION " daemon ready.");
655 
656  /*
657  * Record our pid to make it easier
658  * to kill the correct pcscd
659  *
660  * Do not fork after this point or the stored pid will be wrong
661  */
662  {
663  int f;
664  int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
665 
666  f = open(PCSCLITE_RUN_PID, O_RDWR | O_CREAT, mode);
667  if (f != -1)
668  {
669  char pid[PID_ASCII_SIZE];
670  ssize_t rr;
671 
672  (void)snprintf(pid, sizeof(pid), "%u\n", (unsigned) getpid());
673  rr = write(f, pid, strlen(pid) + 1);
674  if (rr < 0)
675  {
676  Log2(PCSC_LOG_CRITICAL,
677  "writing " PCSCLITE_RUN_PID " failed: %s",
678  strerror(errno));
679  }
680  (void)close(f);
681 
682  /* set mode so that the file is world readable even is umask is
683  * restrictive
684  * The file is used by libpcsclite */
685  (void)chmod(PCSCLITE_RUN_PID, mode);
686  }
687  else
688  Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_RUN_PID ": %s",
689  strerror(errno));
690  }
691 
692  /*
693  * post initialistion
694  */
695  Init = FALSE;
696 
697  /*
698  * Hotplug rescan
699  */
700  (void)signal(SIGUSR1, signal_trap);
701 
702  /*
703  * Initialize the comm structure
704  */
705  if (SocketActivated)
706  rv = ListenExistingSocket(SD_LISTEN_FDS_START + 0);
707  else
708  rv = InitializeSocket();
709 
710  if (rv)
711  {
712  Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
713  at_exit();
714  }
715 
716  /*
717  * Initialize the contexts structure
718  */
719  rv = ContextsInitialize(customMaxThreadCounter, customMaxThreadCardHandles);
720 
721  if (rv == -1)
722  {
723  Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
724  at_exit();
725  }
726 
727  (void)signal(SIGPIPE, SIG_IGN);
728  (void)signal(SIGHUP, SIG_IGN); /* needed for Solaris. The signal is sent
729  * when the shell is existed */
730 
731 #if !defined(PCSCLITE_STATIC_DRIVER) && defined(USE_USB)
732  /*
733  * Set up the search for USB/PCMCIA devices
734  */
735  rv = HPSearchHotPluggables();
736 #ifndef USE_SERIAL
737  if (rv)
738  at_exit();
739 #endif
740 
741  rv = HPRegisterForHotplugEvents();
742  if (rv)
743  {
744  Log1(PCSC_LOG_ERROR, "HPRegisterForHotplugEvents failed");
745  at_exit();
746  }
747 
748  RFWaitForReaderInit();
749 #endif
750 
751  /* initialisation succeeded */
752  if (pipefd[1] >= 0)
753  {
754  char buf = 0;
755  ssize_t rr;
756 
757  /* write a 0 (success) to father process */
758  rr = write(pipefd[1], &buf, 1);
759  if (rr < 0)
760  {
761  Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
762  }
763  close(pipefd[1]);
764  pipefd[1] = -1;
765  }
766 
768 
769  Log1(PCSC_LOG_ERROR, "SVCServiceRunLoop returned");
770  return EXIT_FAILURE;
771 }
772 
773 static void at_exit(void)
774 {
775  Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR);
776 
777  clean_temp_files();
778 
779  if (pipefd[1] >= 0)
780  {
781  char buf;
782  ssize_t r;
783 
784  /* write the error code to father process */
785  buf = ExitValue;
786  r = write(pipefd[1], &buf, 1);
787  if (r < 0)
788  {
789  Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
790  }
791  close(pipefd[1]);
792  }
793 
794  exit(ExitValue);
795 }
796 
797 static void clean_temp_files(void)
798 {
799  int rv;
800 
801  if (!SocketActivated)
802  {
803  rv = remove(PCSCLITE_CSOCK_NAME);
804  if (rv != 0)
805  Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s",
806  strerror(errno));
807  }
808 
809  rv = remove(PCSCLITE_RUN_PID);
810  if (rv != 0)
811  Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_RUN_PID ": %s",
812  strerror(errno));
813 }
814 
815 static void signal_trap(int sig)
816 {
817  int r;
818 
819  r = write(signal_handler_fd[1], &sig, sizeof sig);
820  if (r < 0)
821  Log2(PCSC_LOG_ERROR, "write failed: %s", strerror(errno));
822 }
823 
824 static void print_version(void)
825 {
826  printf("%s version %s.\n", PACKAGE, VERSION);
827  printf("Copyright (C) 1999-2002 by David Corcoran <corcoran@musclecard.com>.\n");
828  printf("Copyright (C) 2001-2015 by Ludovic Rousseau <ludovic.rousseau@free.fr>.\n");
829  printf("Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.\n");
830  printf("Report bugs to <pcsclite-muscle@lists.alioth.debian.org>.\n");
831 
832  printf ("Enabled features:%s\n", PCSCLITE_FEATURES);
833 }
834 
835 static void print_usage(char const * const progname)
836 {
837  printf("Usage: %s options\n", progname);
838  printf("Options:\n");
839 #ifdef HAVE_GETOPT_LONG
840  printf(" -a, --apdu log APDU commands and results\n");
841  printf(" -c, --config path to reader.conf\n");
842  printf(" -f, --foreground run in foreground (no daemon),\n");
843  printf(" send logs to stdout instead of syslog\n");
844  printf(" -T, --color force use of colored logs\n");
845  printf(" -h, --help display usage information\n");
846  printf(" -H, --hotplug ask the daemon to rescan the available readers\n");
847  printf(" -v, --version display the program version number\n");
848  printf(" -d, --debug display lower level debug messages\n");
849  printf(" --info display info level debug messages\n");
850  printf(" -e --error display error level debug messages (default level)\n");
851  printf(" -C --critical display critical only level debug messages\n");
852  printf(" --force-reader-polling ignore the IFD_GENERATE_HOTPLUG reader capability\n");
853  printf(" -t, --max-thread maximum number of threads (default %d)\n", PCSC_MAX_CONTEXT_THREADS);
854  printf(" -s, --max-card-handle-per-thread maximum number of card handle per thread (default: %d)\n", PCSC_MAX_CONTEXT_CARD_HANDLES);
855  printf(" -r, --max-card-handle-per-reader maximum number of card handle per reader (default: %d)\n", PCSC_MAX_READER_HANDLES);
856  printf(" -x, --auto-exit pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
857  printf(" -S, --reader-name-no-serial do not include the USB serial number in the name\n");
858  printf(" -I, --reader-name-no-interface do not include the USB interface name in the name\n");
859 #else
860  printf(" -a log APDU commands and results\n");
861  printf(" -c path to reader.conf\n");
862  printf(" -f run in foreground (no daemon), send logs to stdout instead of syslog\n");
863  printf(" -T force use of colored logs\n");
864  printf(" -d display debug messages.\n");
865  printf(" -e display error messages (default level).\n");
866  printf(" -C display critical messages.\n");
867  printf(" -h display usage information\n");
868  printf(" -H ask the daemon to rescan the available readers\n");
869  printf(" -v display the program version number\n");
870  printf(" -t maximum number of threads\n");
871  printf(" -s maximum number of card handle per thread\n");
872  printf(" -r maximum number of card handle per reader\n");
873  printf(" -x pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
874 #endif
875 }
876 
#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.