pcsc-lite  1.8.17
pcscdaemon.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
3  *
4  * Copyright (C) 1999-2002
5  * David Corcoran <corcoran@musclecard.com>
6  * Copyright (C) 2002-2011
7  * Ludovic Rousseau <ludovic.rousseau@free.fr>
8  *
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 
13 1. Redistributions of source code must retain the above copyright
14  notice, this list of conditions and the following disclaimer.
15 2. Redistributions in binary form must reproduce the above copyright
16  notice, this list of conditions and the following disclaimer in the
17  documentation and/or other materials provided with the distribution.
18 3. The name of the author may not be used to endorse or promote products
19  derived from this software without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
42 #include "config.h"
43 #include <time.h>
44 #include <signal.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include <errno.h>
49 #include <stdio.h>
50 #include <unistd.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #ifdef HAVE_GETOPT_H
54 #include <getopt.h>
55 #endif
56 
57 #include "misc.h"
58 #include "pcsclite.h"
59 #include "pcscd.h"
60 #include "debuglog.h"
61 #include "sd-daemon.h"
62 #include "winscard_msg.h"
63 #include "winscard_svc.h"
64 #include "sys_generic.h"
65 #include "hotplug.h"
66 #include "readerfactory.h"
67 #include "configfile.h"
68 #include "powermgt_generic.h"
69 #include "utils.h"
70 #include "eventhandler.h"
71 
72 #ifndef TRUE
73 #define TRUE 1
74 #define FALSE 0
75 #endif
76 
77 char AraKiri = FALSE;
78 static char Init = TRUE;
79 char AutoExit = FALSE;
80 char SocketActivated = FALSE;
81 static int ExitValue = EXIT_FAILURE;
82 int HPForceReaderPolling = 0;
83 static int pipefd[] = {-1, -1};
84 static int signal_handler_fd[] = {-1, -1};
85 char Add_Serial_In_Name = TRUE;
86 char Add_Interface_In_Name = TRUE;
87 
88 /*
89  * Some internal functions
90  */
91 static void at_exit(void);
92 static void clean_temp_files(void);
93 static void signal_trap(int);
94 static void print_version (void);
95 static void print_usage (char const * const);
96 
105 static void SVCServiceRunLoop(void)
106 {
107  int rsp;
108  LONG rv;
109  uint32_t dwClientID; /* Connection ID used to reference the Client */
110 
111  while (TRUE)
112  {
113  if (AraKiri)
114  {
115  /* stop the hotpug thread and waits its exit */
116 #ifdef USE_USB
117  (void)HPStopHotPluggables();
118 #endif
119  (void)SYS_Sleep(1);
120 
121  /* now stop all the drivers */
122  RFCleanupReaders();
123  EHDeinitializeEventStructures();
124  ContextsDeinitialize();
125  at_exit();
126  }
127 
128  switch (rsp = ProcessEventsServer(&dwClientID))
129  {
130 
131  case 0:
132  Log2(PCSC_LOG_DEBUG, "A new context thread creation is requested: %d", dwClientID);
133  rv = CreateContextThread(&dwClientID);
134 
135  if (rv != SCARD_S_SUCCESS)
136  Log1(PCSC_LOG_ERROR, "Problem during the context thread creation");
137  break;
138 
139  case 2:
140  /*
141  * timeout in ProcessEventsServer(): do nothing
142  * this is used to catch the Ctrl-C signal at some time when
143  * nothing else happens
144  */
145  break;
146 
147  case -1:
148  Log1(PCSC_LOG_ERROR, "Error in ProcessEventsServer");
149  break;
150 
151  case -2:
152  /* Nothing to do in case of a syscall interrupted
153  * It happens when SIGUSR1 (reload) or SIGINT (Ctrl-C) is received
154  * We just try again */
155 
156  /* we wait a bit so that the signal handler thread can do
157  * its job and set AraKiri if needed */
158  SYS_USleep(1000);
159  break;
160 
161  default:
162  Log2(PCSC_LOG_ERROR, "ProcessEventsServer unknown retval: %d",
163  rsp);
164  break;
165  }
166  }
167 }
168 
176 static void *signal_thread(void *arg)
177 {
178  (void)arg;
179 
180  while (TRUE)
181  {
182  int r;
183  int sig;
184 
185  r = read(signal_handler_fd[0], &sig, sizeof sig);
186  if (r < 0)
187  {
188  Log2(PCSC_LOG_ERROR, "read failed: %s", strerror(errno));
189  return NULL;
190  }
191 
192  Log2(PCSC_LOG_INFO, "Received signal: %d", sig);
193 
194  /* signal for hotplug */
195  if (SIGUSR1 == sig)
196  {
197 #ifdef USE_USB
198  if (! AraKiri)
199  HPReCheckSerialReaders();
200 #endif
201  /* Reenable the signal handler.
202  * This is needed on Solaris and HPUX. */
203  (void)signal(SIGUSR1, signal_trap);
204 
205  continue;
206  }
207 
208  /* do not wait if asked to terminate
209  * avoids waiting after the reader(s) in shutdown for example */
210  if (SIGTERM == sig)
211  {
212  Log1(PCSC_LOG_INFO, "Direct suicide");
213  at_exit();
214  }
215 
216  if (SIGALRM == sig)
217  {
218  /* normal exit without error */
219  ExitValue = EXIT_SUCCESS;
220  }
221 
222  /* the signal handler is called several times for the same Ctrl-C */
223  if (AraKiri == FALSE)
224  {
225  Log1(PCSC_LOG_INFO, "Preparing for suicide");
226  AraKiri = TRUE;
227 
228  /* if still in the init/loading phase the AraKiri will not be
229  * seen by the main event loop
230  */
231  if (Init)
232  {
233  Log1(PCSC_LOG_INFO, "Suicide during init");
234  at_exit();
235  }
236  }
237  else
238  {
239  /* if pcscd do not want to die */
240  static int lives = 2;
241 
242  lives--;
243  /* no live left. Something is blocking the normal death. */
244  if (0 == lives)
245  {
246  Log1(PCSC_LOG_INFO, "Forced suicide");
247  at_exit();
248  }
249  }
250  }
251 
252  return NULL;
253 }
254 
255 
256 int main(int argc, char **argv)
257 {
258  int rv;
259  char setToForeground;
260  char HotPlug;
261  char *newReaderConfig;
262  struct stat fStatBuf;
263  int customMaxThreadCounter = 0;
264  int customMaxReaderHandles = 0;
265  int customMaxThreadCardHandles = 0;
266  int opt;
267  int limited_rights = FALSE;
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, 0},
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:fTdhvaeCHt: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  /*
313  * By default we create a daemon (not connected to any output)
314  * so log to syslog to have error messages.
315  */
316  DebugLogSetLogType(DEBUGLOG_SYSLOG_DEBUG);
317 
318  /* if the process is setuid or setgid it may have some restrictions */
319  limited_rights = (getgid() != getegid()) && (getuid() != 0);
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  if (limited_rights)
339  {
340  Log1(PCSC_LOG_CRITICAL, "Can't use a user specified config file");
341  return EXIT_FAILURE;
342  }
343  Log2(PCSC_LOG_INFO, "using new config file: %s", optarg);
344  newReaderConfig = optarg;
345  break;
346 
347  case 'f':
348  setToForeground = TRUE;
349  /* debug to stdout instead of default syslog */
350  DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
351  Log1(PCSC_LOG_INFO,
352  "pcscd set to foreground with debug send to stdout");
353  break;
354 
355  case 'T':
356  DebugLogSetLogType(DEBUGLOG_STDOUT_COLOR_DEBUG);
357  Log1(PCSC_LOG_INFO, "Force colored logs");
358  break;
359 
360  case 'd':
361  DebugLogSetLevel(PCSC_LOG_DEBUG);
362  break;
363 
364  case 'e':
365  DebugLogSetLevel(PCSC_LOG_ERROR);
366  break;
367 
368  case 'C':
369  DebugLogSetLevel(PCSC_LOG_CRITICAL);
370  break;
371 
372  case 'h':
373  print_usage (argv[0]);
374  return EXIT_SUCCESS;
375 
376  case 'v':
377  print_version ();
378  return EXIT_SUCCESS;
379 
380  case 'a':
381  if (limited_rights)
382  {
383  Log1(PCSC_LOG_CRITICAL, "Can't log APDU (restricted)");
384  return EXIT_FAILURE;
385  }
386  (void)DebugLogSetCategory(DEBUG_CATEGORY_APDU);
387  break;
388 
389  case 'H':
390  /* debug to stdout instead of default syslog */
391  DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
392  HotPlug = TRUE;
393  break;
394 
395  case 't':
396  customMaxThreadCounter = optarg ? atoi(optarg) : 0;
397  if (limited_rights && (customMaxThreadCounter < PCSC_MAX_CONTEXT_THREADS))
398  customMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS;
399  Log2(PCSC_LOG_INFO, "setting customMaxThreadCounter to: %d",
400  customMaxThreadCounter);
401  break;
402 
403  case 'r':
404  customMaxReaderHandles = optarg ? atoi(optarg) : 0;
405  if (limited_rights && (customMaxReaderHandles < PCSC_MAX_READER_HANDLES))
406  customMaxReaderHandles = PCSC_MAX_READER_HANDLES;
407  Log2(PCSC_LOG_INFO, "setting customMaxReaderHandles to: %d",
408  customMaxReaderHandles);
409  break;
410 
411  case 's':
412  customMaxThreadCardHandles = optarg ? atoi(optarg) : 0;
413  if (limited_rights && (customMaxThreadCardHandles < PCSC_MAX_CONTEXT_CARD_HANDLES))
414  customMaxThreadCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES;
415  Log2(PCSC_LOG_INFO, "setting customMaxThreadCardHandles to: %d",
416  customMaxThreadCardHandles);
417  break;
418 
419  case 'x':
420  AutoExit = TRUE;
421  Log2(PCSC_LOG_INFO, "Auto exit after %d seconds of inactivity",
422  TIME_BEFORE_SUICIDE);
423  break;
424 
425  case 'S':
426  Add_Serial_In_Name = FALSE;
427  break;
428 
429  case 'I':
430  Add_Interface_In_Name = FALSE;
431  break;
432 
433  default:
434  print_usage (argv[0]);
435  return EXIT_FAILURE;
436  }
437 
438  }
439 
440  if (argv[optind])
441  {
442  printf("Unknown option: %s\n", argv[optind]);
443  print_usage(argv[0]);
444  return EXIT_FAILURE;
445  }
446 
447  /*
448  * Check if systemd passed us any file descriptors
449  */
450  rv = sd_listen_fds(0);
451  if (rv > 1)
452  {
453  Log1(PCSC_LOG_CRITICAL, "Too many file descriptors received");
454  return EXIT_FAILURE;
455  }
456  else
457  {
458  if (rv == 1)
459  {
460  SocketActivated = TRUE;
461  Log1(PCSC_LOG_INFO, "Started by systemd");
462  }
463  else
464  SocketActivated = FALSE;
465  }
466 
467  /*
468  * test the presence of /var/run/pcscd/pcscd.comm
469  */
470 
471  rv = stat(PCSCLITE_CSOCK_NAME, &fStatBuf);
472 
473  /* if the file exist and pcscd was _not_ started by systemd */
474  if (rv == 0 && !SocketActivated)
475  {
476  pid_t pid;
477 
478  /* read the pid file to get the old pid and test if the old pcscd is
479  * still running
480  */
481  pid = GetDaemonPid();
482 
483  if (pid != -1)
484  {
485  if (HotPlug)
486  return SendHotplugSignal();
487 
488  rv = kill(pid, 0);
489  if (0 == rv)
490  {
491  Log1(PCSC_LOG_CRITICAL,
492  "file " PCSCLITE_CSOCK_NAME " already exists.");
493  Log2(PCSC_LOG_CRITICAL,
494  "Another pcscd (pid: %ld) seems to be running.", (long)pid);
495  return EXIT_FAILURE;
496  }
497  else
498  if (ESRCH == errno)
499  {
500  /* the old pcscd is dead. make some cleanup */
501  clean_temp_files();
502  }
503  else
504  {
505  /* permission denied or other error */
506  Log2(PCSC_LOG_CRITICAL, "kill failed: %s", strerror(errno));
507  return EXIT_FAILURE;
508  }
509  }
510  else
511  {
512  if (HotPlug)
513  {
514  Log1(PCSC_LOG_CRITICAL, "file " PCSCLITE_RUN_PID " do not exist");
515  Log1(PCSC_LOG_CRITICAL, "Hotplug failed");
516  return EXIT_FAILURE;
517  }
518  }
519  }
520  else
521  if (HotPlug)
522  {
523  Log1(PCSC_LOG_CRITICAL, "Hotplug failed: pcscd is not running");
524  return EXIT_FAILURE;
525  }
526 
527  /* like in daemon(3): changes the current working directory to the
528  * root ("/") */
529  r = chdir("/");
530  if (r < 0)
531  {
532  Log2(PCSC_LOG_CRITICAL, "chdir() failed: %s", strerror(errno));
533  return EXIT_FAILURE;
534  }
535 
536  /*
537  * If this is set to one the user has asked it not to fork
538  */
539  if (!setToForeground)
540  {
541  int pid;
542  int fd;
543 
544  if (pipe(pipefd) == -1)
545  {
546  Log2(PCSC_LOG_CRITICAL, "pipe() failed: %s", strerror(errno));
547  return EXIT_FAILURE;
548  }
549 
550  pid = fork();
551  if (-1 == pid)
552  {
553  Log2(PCSC_LOG_CRITICAL, "fork() failed: %s", strerror(errno));
554  return EXIT_FAILURE;
555  }
556 
557  /* like in daemon(3): redirect standard input, standard output
558  * and standard error to /dev/null */
559  fd = open("/dev/null", O_RDWR);
560  if (fd != -1)
561  {
562  dup2(fd, STDIN_FILENO);
563  dup2(fd, STDOUT_FILENO);
564  dup2(fd, STDERR_FILENO);
565 
566  /* do not close stdin, stdout or stderr */
567  if (fd > 2)
568  close(fd);
569  }
570 
571  if (pid)
572  /* in the father */
573  {
574  char buf;
575  int ret;
576 
577  /* close write side */
578  close(pipefd[1]);
579 
580  /* wait for the son to write the return code */
581  ret = read(pipefd[0], &buf, 1);
582  if (ret <= 0)
583  return 2;
584 
585  close(pipefd[0]);
586 
587  /* exit code */
588  return buf;
589  }
590  else
591  /* in the son */
592  {
593  /* close read side */
594  close(pipefd[0]);
595  }
596  }
597 
598  /*
599  * cleanly remove /var/run/pcscd/files when exiting
600  * signal_trap() does just set a global variable used by the main loop
601  */
602  (void)signal(SIGQUIT, signal_trap);
603  (void)signal(SIGTERM, signal_trap); /* default kill signal & init round 1 */
604  (void)signal(SIGINT, signal_trap); /* sent by Ctrl-C */
605 
606  /* exits on SIGALARM to allow pcscd to suicide if not used */
607  (void)signal(SIGALRM, signal_trap);
608 
609  if (pipe(signal_handler_fd) == -1)
610  {
611  Log2(PCSC_LOG_CRITICAL, "pipe() failed: %s", strerror(errno));
612  return EXIT_FAILURE;
613  }
614 
615  pthread_t signal_handler_thread;
616  rv = pthread_create(&signal_handler_thread, NULL, signal_thread, NULL);
617  if (rv)
618  {
619  Log2(PCSC_LOG_CRITICAL, "pthread_create failed: %s", strerror(rv));
620  return EXIT_FAILURE;
621  }
622 
623  /*
624  * If PCSCLITE_IPC_DIR does not exist then create it
625  */
626  {
627  int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;
628 
629  rv = mkdir(PCSCLITE_IPC_DIR, mode);
630  if ((rv != 0) && (errno != EEXIST))
631  {
632  Log2(PCSC_LOG_CRITICAL,
633  "cannot create " PCSCLITE_IPC_DIR ": %s", strerror(errno));
634  return EXIT_FAILURE;
635  }
636 
637  /* set mode so that the directory is world readable and
638  * executable even is umask is restrictive
639  * The directory containes files used by libpcsclite */
640  (void)chmod(PCSCLITE_IPC_DIR, mode);
641  }
642 
643  /*
644  * Allocate memory for reader structures
645  */
646  rv = RFAllocateReaderSpace(customMaxReaderHandles);
647  if (SCARD_S_SUCCESS != rv)
648  at_exit();
649 
650 #ifdef USE_SERIAL
651  /*
652  * Grab the information from the reader.conf
653  */
654  if (newReaderConfig)
655  {
656  rv = RFStartSerialReaders(newReaderConfig);
657  if (rv != 0)
658  {
659  Log3(PCSC_LOG_CRITICAL, "invalid file %s: %s", newReaderConfig,
660  strerror(errno));
661  at_exit();
662  }
663  }
664  else
665  {
666  rv = RFStartSerialReaders(PCSCLITE_CONFIG_DIR);
667  if (rv == -1)
668  at_exit();
669  }
670 #endif
671 
672  Log1(PCSC_LOG_INFO, "pcsc-lite " VERSION " daemon ready.");
673 
674  /*
675  * Record our pid to make it easier
676  * to kill the correct pcscd
677  *
678  * Do not fork after this point or the stored pid will be wrong
679  */
680  {
681  int f;
682  int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
683 
684  f = open(PCSCLITE_RUN_PID, O_RDWR | O_CREAT, mode);
685  if (f != -1)
686  {
687  char pid[PID_ASCII_SIZE];
688  ssize_t rr;
689 
690  (void)snprintf(pid, sizeof(pid), "%u\n", (unsigned) getpid());
691  rr = write(f, pid, strlen(pid) + 1);
692  if (rr < 0)
693  {
694  Log2(PCSC_LOG_CRITICAL,
695  "writing " PCSCLITE_RUN_PID " failed: %s",
696  strerror(errno));
697  }
698  (void)close(f);
699 
700  /* set mode so that the file is world readable even is umask is
701  * restrictive
702  * The file is used by libpcsclite */
703  (void)chmod(PCSCLITE_RUN_PID, mode);
704  }
705  else
706  Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_RUN_PID ": %s",
707  strerror(errno));
708  }
709 
710  /*
711  * post initialistion
712  */
713  Init = FALSE;
714 
715  /*
716  * Hotplug rescan
717  */
718  (void)signal(SIGUSR1, signal_trap);
719 
720  /*
721  * Initialize the comm structure
722  */
723  if (SocketActivated)
724  rv = ListenExistingSocket(SD_LISTEN_FDS_START + 0);
725  else
726  rv = InitializeSocket();
727 
728  if (rv)
729  {
730  Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
731  at_exit();
732  }
733 
734  /*
735  * Initialize the contexts structure
736  */
737  rv = ContextsInitialize(customMaxThreadCounter, customMaxThreadCardHandles);
738 
739  if (rv == -1)
740  {
741  Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
742  at_exit();
743  }
744 
745  (void)signal(SIGPIPE, SIG_IGN);
746  (void)signal(SIGHUP, SIG_IGN); /* needed for Solaris. The signal is sent
747  * when the shell is existed */
748 
749 #if !defined(PCSCLITE_STATIC_DRIVER) && defined(USE_USB)
750  /*
751  * Set up the search for USB/PCMCIA devices
752  */
753  rv = HPSearchHotPluggables();
754 #ifndef USE_SERIAL
755  if (rv)
756  at_exit();
757 #endif
758 
759  rv = HPRegisterForHotplugEvents();
760  if (rv)
761  {
762  Log1(PCSC_LOG_ERROR, "HPRegisterForHotplugEvents failed");
763  at_exit();
764  }
765 
766  RFWaitForReaderInit();
767 #endif
768 
769  /*
770  * Set up the power management callback routine
771  */
772  (void)PMRegisterForPowerEvents();
773 
774  /* initialisation succeeded */
775  if (pipefd[1] >= 0)
776  {
777  char buf = 0;
778  ssize_t rr;
779 
780  /* write a 0 (success) to father process */
781  rr = write(pipefd[1], &buf, 1);
782  if (rr < 0)
783  {
784  Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
785  }
786  close(pipefd[1]);
787  pipefd[1] = -1;
788  }
789 
791 
792  Log1(PCSC_LOG_ERROR, "SVCServiceRunLoop returned");
793  return EXIT_FAILURE;
794 }
795 
796 static void at_exit(void)
797 {
798  Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR);
799 
800  clean_temp_files();
801 
802  if (pipefd[1] >= 0)
803  {
804  char buf;
805  ssize_t r;
806 
807  /* write the error code to father process */
808  buf = ExitValue;
809  r = write(pipefd[1], &buf, 1);
810  if (r < 0)
811  {
812  Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
813  }
814  close(pipefd[1]);
815  }
816 
817  exit(ExitValue);
818 }
819 
820 static void clean_temp_files(void)
821 {
822  int rv;
823 
824  if (!SocketActivated)
825  {
826  rv = remove(PCSCLITE_CSOCK_NAME);
827  if (rv != 0)
828  Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s",
829  strerror(errno));
830  }
831 
832  rv = remove(PCSCLITE_RUN_PID);
833  if (rv != 0)
834  Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_RUN_PID ": %s",
835  strerror(errno));
836 }
837 
838 static void signal_trap(int sig)
839 {
840  int r;
841 
842  r = write(signal_handler_fd[1], &sig, sizeof sig);
843  if (r < 0)
844  Log2(PCSC_LOG_ERROR, "write failed: %s", strerror(errno));
845 }
846 
847 static void print_version (void)
848 {
849  printf("%s version %s.\n", PACKAGE, VERSION);
850  printf("Copyright (C) 1999-2002 by David Corcoran <corcoran@musclecard.com>.\n");
851  printf("Copyright (C) 2001-2015 by Ludovic Rousseau <ludovic.rousseau@free.fr>.\n");
852  printf("Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.\n");
853  printf("Report bugs to <pcsclite-muscle@lists.alioth.debian.org>.\n");
854 
855  printf ("Enabled features:%s\n", PCSCLITE_FEATURES);
856 }
857 
858 static void print_usage (char const * const progname)
859 {
860  printf("Usage: %s options\n", progname);
861  printf("Options:\n");
862 #ifdef HAVE_GETOPT_LONG
863  printf(" -a, --apdu log APDU commands and results\n");
864  printf(" -c, --config path to reader.conf\n");
865  printf(" -f, --foreground run in foreground (no daemon),\n");
866  printf(" send logs to stdout instead of syslog\n");
867  printf(" -T, --color force use of colored logs\n");
868  printf(" -h, --help display usage information\n");
869  printf(" -H, --hotplug ask the daemon to rescan the available readers\n");
870  printf(" -v, --version display the program version number\n");
871  printf(" -d, --debug display lower level debug messages\n");
872  printf(" --info display info level debug messages\n");
873  printf(" -e --error display error level debug messages (default level)\n");
874  printf(" -C --critical display critical only level debug messages\n");
875  printf(" --force-reader-polling ignore the IFD_GENERATE_HOTPLUG reader capability\n");
876  printf(" -t, --max-thread maximum number of threads (default %d)\n", PCSC_MAX_CONTEXT_THREADS);
877  printf(" -s, --max-card-handle-per-thread maximum number of card handle per thread (default: %d)\n", PCSC_MAX_CONTEXT_CARD_HANDLES);
878  printf(" -r, --max-card-handle-per-reader maximum number of card handle per reader (default: %d)\n", PCSC_MAX_READER_HANDLES);
879  printf(" -x, --auto-exit pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
880  printf(" -S, --reader-name-no-serial do not include the USB serial number in the name\n");
881  printf(" -I, --reader-name-no-interface do not include the USB interface name in the name\n");
882 #else
883  printf(" -a log APDU commands and results\n");
884  printf(" -c path to reader.conf\n");
885  printf(" -f run in foreground (no daemon), send logs to stdout instead of syslog\n");
886  printf(" -T force use of colored logs\n");
887  printf(" -d display debug messages.\n");
888  printf(" -e display error messages (default level).\n");
889  printf(" -C display critical messages.\n");
890  printf(" -h display usage information\n");
891  printf(" -H ask the daemon to rescan the available readers\n");
892  printf(" -v display the program version number\n");
893  printf(" -t maximum number of threads\n");
894  printf(" -s maximum number of card handle per thread\n");
895  printf(" -r maximum number of card handle per reader\n");
896  printf(" -x pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
897 #endif
898 }
899 
#define SCARD_S_SUCCESS
No error was encountered.
Definition: pcsclite.h:107
INTERNAL int32_t ListenExistingSocket(int fd)
Acquires a socket passed in from systemd.
LONG CreateContextThread(uint32_t *pdwClientID)
Creates threads to handle messages received from Clients.
Definition: winscard_svc.c:168
This handles power management routines.
This handles abstract system level calls.
char AutoExit
Represents an Application Context on the Server side.
Definition: pcscdaemon.c:79
int SYS_Sleep(int)
Makes the current process sleep for some seconds.
Definition: sys_unix.c:65
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:83
This defines some structures and #defines to be used over the transport layer.
INTERNAL int32_t InitializeSocket(void)
Prepares the communication channel used by the server to talk to the clients.
ULONG PMRegisterForPowerEvents(void)
Registers for Power Management callbacks.
This handles card insertion/removal events, updates ATR, protocol, and status information.
static void SVCServiceRunLoop(void)
The Server&#39;s Message Queue Listener function.
Definition: pcscdaemon.c:105
This keeps a list of defines for pcsc-lite.
static void * signal_thread(void *arg)
thread dedicated to handle signals
Definition: pcscdaemon.c:176
This keeps a list of defines for pcsc-lite.
INTERNAL int32_t ProcessEventsServer(uint32_t *pdwClientID)
Looks for messages sent by clients.
This keeps track of a list of currently available reader structures.
This provides a search API for hot pluggble devices.
#define PCSCLITE_VERSION_NUMBER
Current version.
Definition: pcsclite.h:282
This handles debugging.