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