45 #include <sys/types.h> 61 #include "sd-daemon.h" 67 #include "configfile.h" 78 static char Init = TRUE;
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;
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);
117 (void)HPStopHotPluggables();
123 EHDeinitializeEventStructures();
124 ContextsDeinitialize();
132 Log2(PCSC_LOG_DEBUG,
"A new context thread creation is requested: %d", dwClientID);
136 Log1(PCSC_LOG_ERROR,
"Problem during the context thread creation");
148 Log1(PCSC_LOG_ERROR,
"Error in ProcessEventsServer");
162 Log2(PCSC_LOG_ERROR,
"ProcessEventsServer unknown retval: %d",
185 r = read(signal_handler_fd[0], &sig,
sizeof sig);
188 Log2(PCSC_LOG_ERROR,
"read failed: %s", strerror(errno));
192 Log2(PCSC_LOG_INFO,
"Received signal: %d", sig);
199 HPReCheckSerialReaders();
203 (void)signal(SIGUSR1, signal_trap);
212 Log1(PCSC_LOG_INFO,
"Direct suicide");
219 ExitValue = EXIT_SUCCESS;
223 if (AraKiri == FALSE)
225 Log1(PCSC_LOG_INFO,
"Preparing for suicide");
233 Log1(PCSC_LOG_INFO,
"Suicide during init");
240 static int lives = 2;
246 Log1(PCSC_LOG_INFO,
"Forced suicide");
256 int main(
int argc,
char **argv)
259 char setToForeground;
261 char *newReaderConfig;
262 struct stat fStatBuf;
263 int customMaxThreadCounter = 0;
264 int customMaxReaderHandles = 0;
265 int customMaxThreadCardHandles = 0;
267 int limited_rights = FALSE;
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'},
293 #define OPT_STRING "c:fTdhvaeCHt:r:s:xSI" 295 newReaderConfig = NULL;
296 setToForeground = FALSE;
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);
316 DebugLogSetLogType(DEBUGLOG_SYSLOG_DEBUG);
319 limited_rights = (getgid() != getegid()) && (getuid() != 0);
324 #ifdef HAVE_GETOPT_LONG 325 while ((opt = getopt_long (argc, argv, OPT_STRING, long_options, &option_index)) != -1) {
327 while ((opt = getopt (argc, argv, OPT_STRING)) != -1) {
330 #ifdef HAVE_GETOPT_LONG 332 if (strcmp(long_options[option_index].name,
333 "force-reader-polling") == 0)
334 HPForceReaderPolling = optarg ? abs(atoi(optarg)) : 1;
340 Log1(PCSC_LOG_CRITICAL,
"Can't use a user specified config file");
343 Log2(PCSC_LOG_INFO,
"using new config file: %s", optarg);
344 newReaderConfig = optarg;
348 setToForeground = TRUE;
350 DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
352 "pcscd set to foreground with debug send to stdout");
356 DebugLogSetLogType(DEBUGLOG_STDOUT_COLOR_DEBUG);
357 Log1(PCSC_LOG_INFO,
"Force colored logs");
361 DebugLogSetLevel(PCSC_LOG_DEBUG);
365 DebugLogSetLevel(PCSC_LOG_ERROR);
369 DebugLogSetLevel(PCSC_LOG_CRITICAL);
373 print_usage (argv[0]);
383 Log1(PCSC_LOG_CRITICAL,
"Can't log APDU (restricted)");
386 (void)DebugLogSetCategory(DEBUG_CATEGORY_APDU);
391 DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
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);
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);
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);
421 Log2(PCSC_LOG_INFO,
"Auto exit after %d seconds of inactivity",
422 TIME_BEFORE_SUICIDE);
426 Add_Serial_In_Name = FALSE;
430 Add_Interface_In_Name = FALSE;
434 print_usage (argv[0]);
442 printf(
"Unknown option: %s\n", argv[optind]);
443 print_usage(argv[0]);
450 rv = sd_listen_fds(0);
453 Log1(PCSC_LOG_CRITICAL,
"Too many file descriptors received");
460 SocketActivated = TRUE;
461 Log1(PCSC_LOG_INFO,
"Started by systemd");
464 SocketActivated = FALSE;
471 rv = stat(PCSCLITE_CSOCK_NAME, &fStatBuf);
474 if (rv == 0 && !SocketActivated)
481 pid = GetDaemonPid();
486 return SendHotplugSignal();
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);
506 Log2(PCSC_LOG_CRITICAL,
"kill failed: %s", strerror(errno));
514 Log1(PCSC_LOG_CRITICAL,
"file " PCSCLITE_RUN_PID
" do not exist");
515 Log1(PCSC_LOG_CRITICAL,
"Hotplug failed");
523 Log1(PCSC_LOG_CRITICAL,
"Hotplug failed: pcscd is not running");
532 Log2(PCSC_LOG_CRITICAL,
"chdir() failed: %s", strerror(errno));
539 if (!setToForeground)
544 if (pipe(pipefd) == -1)
546 Log2(PCSC_LOG_CRITICAL,
"pipe() failed: %s", strerror(errno));
553 Log2(PCSC_LOG_CRITICAL,
"fork() failed: %s", strerror(errno));
559 fd = open(
"/dev/null", O_RDWR);
562 dup2(fd, STDIN_FILENO);
563 dup2(fd, STDOUT_FILENO);
564 dup2(fd, STDERR_FILENO);
581 ret = read(pipefd[0], &buf, 1);
602 (void)signal(SIGQUIT, signal_trap);
603 (void)signal(SIGTERM, signal_trap);
604 (void)signal(SIGINT, signal_trap);
607 (void)signal(SIGALRM, signal_trap);
609 if (pipe(signal_handler_fd) == -1)
611 Log2(PCSC_LOG_CRITICAL,
"pipe() failed: %s", strerror(errno));
615 pthread_t signal_handler_thread;
616 rv = pthread_create(&signal_handler_thread, NULL,
signal_thread, NULL);
619 Log2(PCSC_LOG_CRITICAL,
"pthread_create failed: %s", strerror(rv));
627 int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;
629 rv = mkdir(PCSCLITE_IPC_DIR, mode);
630 if ((rv != 0) && (errno != EEXIST))
632 Log2(PCSC_LOG_CRITICAL,
633 "cannot create " PCSCLITE_IPC_DIR
": %s", strerror(errno));
640 (void)chmod(PCSCLITE_IPC_DIR, mode);
646 rv = RFAllocateReaderSpace(customMaxReaderHandles);
656 rv = RFStartSerialReaders(newReaderConfig);
659 Log3(PCSC_LOG_CRITICAL,
"invalid file %s: %s", newReaderConfig,
666 rv = RFStartSerialReaders(PCSCLITE_CONFIG_DIR);
672 Log1(PCSC_LOG_INFO,
"pcsc-lite " VERSION
" daemon ready.");
682 int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
684 f = open(PCSCLITE_RUN_PID, O_RDWR | O_CREAT, mode);
687 char pid[PID_ASCII_SIZE];
690 (void)snprintf(pid,
sizeof(pid),
"%u\n", (unsigned) getpid());
691 rr = write(f, pid, strlen(pid) + 1);
694 Log2(PCSC_LOG_CRITICAL,
695 "writing " PCSCLITE_RUN_PID
" failed: %s",
703 (void)chmod(PCSCLITE_RUN_PID, mode);
706 Log2(PCSC_LOG_CRITICAL,
"cannot create " PCSCLITE_RUN_PID
": %s",
718 (void)signal(SIGUSR1, signal_trap);
730 Log1(PCSC_LOG_CRITICAL,
"Error initializing pcscd.");
737 rv = ContextsInitialize(customMaxThreadCounter, customMaxThreadCardHandles);
741 Log1(PCSC_LOG_CRITICAL,
"Error initializing pcscd.");
745 (void)signal(SIGPIPE, SIG_IGN);
746 (void)signal(SIGHUP, SIG_IGN);
749 #if !defined(PCSCLITE_STATIC_DRIVER) && defined(USE_USB) 753 rv = HPSearchHotPluggables();
759 rv = HPRegisterForHotplugEvents();
762 Log1(PCSC_LOG_ERROR,
"HPRegisterForHotplugEvents failed");
766 RFWaitForReaderInit();
781 rr = write(pipefd[1], &buf, 1);
784 Log2(PCSC_LOG_ERROR,
"write() failed: %s", strerror(errno));
792 Log1(PCSC_LOG_ERROR,
"SVCServiceRunLoop returned");
796 static void at_exit(
void)
798 Log1(PCSC_LOG_INFO,
"cleaning " PCSCLITE_IPC_DIR);
809 r = write(pipefd[1], &buf, 1);
812 Log2(PCSC_LOG_ERROR,
"write() failed: %s", strerror(errno));
820 static void clean_temp_files(
void)
824 if (!SocketActivated)
826 rv =
remove(PCSCLITE_CSOCK_NAME);
828 Log2(PCSC_LOG_ERROR,
"Cannot remove " PCSCLITE_CSOCK_NAME
": %s",
832 rv =
remove(PCSCLITE_RUN_PID);
834 Log2(PCSC_LOG_ERROR,
"Cannot remove " PCSCLITE_RUN_PID
": %s",
838 static void signal_trap(
int sig)
842 r = write(signal_handler_fd[1], &sig,
sizeof sig);
844 Log2(PCSC_LOG_ERROR,
"write failed: %s", strerror(errno));
847 static void print_version (
void)
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");
855 printf (
"Enabled features:%s\n", PCSCLITE_FEATURES);
858 static void print_usage (
char const *
const progname)
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");
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);
#define SCARD_S_SUCCESS
No error was encountered.
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.
This handles power management routines.
This handles abstract system level calls.
char AutoExit
Represents an Application Context on the Server side.
int SYS_Sleep(int)
Makes the current process sleep for some seconds.
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.
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.
This keeps a list of defines for pcsc-lite.
static void * signal_thread(void *arg)
thread dedicated to handle signals
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.