24 #include <sys/types.h>
40 #include "sd-daemon.h"
46 #include "configfile.h"
56 static char Init = TRUE;
58 char SocketActivated = FALSE;
59 static int ExitValue = EXIT_FAILURE;
60 int HPForceReaderPolling = 0;
61 static int pipefd[] = {-1, -1};
66 static void at_exit(
void);
67 static void clean_temp_files(
void);
68 static void signal_reload(
int sig);
69 static void signal_trap(
int);
70 static void print_version (
void);
71 static void print_usage (
char const *
const);
93 Log2(PCSC_LOG_DEBUG,
"A new context thread creation is requested: %d", dwClientID);
97 Log1(PCSC_LOG_ERROR,
"Problem during the context thread creation");
109 Log1(PCSC_LOG_ERROR,
"Error in ProcessEventsServer");
119 Log2(PCSC_LOG_ERROR,
"ProcessEventsServer unknown retval: %d",
128 (void)HPStopHotPluggables();
134 ContextsDeinitialize();
140 int main(
int argc,
char **argv)
143 char setToForeground;
145 char *newReaderConfig;
146 struct stat fStatBuf;
147 int customMaxThreadCounter = 0;
148 int customMaxReaderHandles = 0;
149 int customMaxThreadCardHandles = 0;
151 int limited_rights = FALSE;
152 #ifdef HAVE_GETOPT_LONG
153 int option_index = 0;
154 static struct option long_options[] = {
155 {
"config", 1, NULL,
'c'},
156 {
"foreground", 0, NULL,
'f'},
157 {
"color", 0, NULL,
'T'},
158 {
"help", 0, NULL,
'h'},
159 {
"version", 0, NULL,
'v'},
160 {
"apdu", 0, NULL,
'a'},
161 {
"debug", 0, NULL,
'd'},
162 {
"info", 0, NULL, 0},
163 {
"error", 0, NULL,
'e'},
164 {
"critical", 0, NULL,
'C'},
165 {
"hotplug", 0, NULL,
'H'},
166 {
"force-reader-polling", optional_argument, NULL, 0},
167 {
"max-thread", 1, NULL,
't'},
168 {
"max-card-handle-per-thread", 1, NULL,
's'},
169 {
"max-card-handle-per-reader", 1, NULL,
'r'},
170 {
"auto-exit", 0, NULL,
'x'},
174 #define OPT_STRING "c:fTdhvaeCHt:r:s:x"
176 newReaderConfig = NULL;
177 setToForeground = FALSE;
185 printf(
"BUILD ERROR: The release version number PCSCLITE_VERSION_NUMBER\n");
186 printf(
" in pcsclite.h (%s) does not match the release version number\n",
188 printf(
" generated in config.h (%s) (see configure.in).\n", VERSION);
197 DebugLogSetLogType(DEBUGLOG_SYSLOG_DEBUG);
200 limited_rights = (getgid() != getegid()) && (getuid() != 0);
205 #ifdef HAVE_GETOPT_LONG
206 while ((opt = getopt_long (argc, argv, OPT_STRING, long_options, &option_index)) != -1) {
208 while ((opt = getopt (argc, argv, OPT_STRING)) != -1) {
211 #ifdef HAVE_GETOPT_LONG
213 if (strcmp(long_options[option_index].name,
214 "force-reader-polling") == 0)
215 HPForceReaderPolling = optarg ? abs(atoi(optarg)) : 1;
221 Log1(PCSC_LOG_CRITICAL,
"Can't use a user specified config file");
224 Log2(PCSC_LOG_INFO,
"using new config file: %s", optarg);
225 newReaderConfig = optarg;
229 setToForeground = TRUE;
231 DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
233 "pcscd set to foreground with debug send to stdout");
237 DebugLogSetLogType(DEBUGLOG_STDOUT_COLOR_DEBUG);
238 Log1(PCSC_LOG_INFO,
"Force colored logs");
242 DebugLogSetLevel(PCSC_LOG_DEBUG);
246 DebugLogSetLevel(PCSC_LOG_ERROR);
250 DebugLogSetLevel(PCSC_LOG_CRITICAL);
254 print_usage (argv[0]);
264 Log1(PCSC_LOG_CRITICAL,
"Can't log APDU (restricted)");
267 (void)DebugLogSetCategory(DEBUG_CATEGORY_APDU);
272 DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
277 customMaxThreadCounter = optarg ? atoi(optarg) : 0;
278 if (limited_rights && (customMaxThreadCounter < PCSC_MAX_CONTEXT_THREADS))
279 customMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS;
280 Log2(PCSC_LOG_INFO,
"setting customMaxThreadCounter to: %d",
281 customMaxThreadCounter);
285 customMaxReaderHandles = optarg ? atoi(optarg) : 0;
286 if (limited_rights && (customMaxReaderHandles < PCSC_MAX_READER_HANDLES))
287 customMaxReaderHandles = PCSC_MAX_READER_HANDLES;
288 Log2(PCSC_LOG_INFO,
"setting customMaxReaderHandles to: %d",
289 customMaxReaderHandles);
293 customMaxThreadCardHandles = optarg ? atoi(optarg) : 0;
294 if (limited_rights && (customMaxThreadCardHandles < PCSC_MAX_CONTEXT_CARD_HANDLES))
295 customMaxThreadCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES;
296 Log2(PCSC_LOG_INFO,
"setting customMaxThreadCardHandles to: %d",
297 customMaxThreadCardHandles);
302 Log2(PCSC_LOG_INFO,
"Auto exit after %d seconds of inactivity",
303 TIME_BEFORE_SUICIDE);
307 print_usage (argv[0]);
315 printf(
"Unknown option: %s\n", argv[optind]);
316 print_usage(argv[0]);
323 rv = sd_listen_fds(0);
326 Log1(PCSC_LOG_CRITICAL,
"Too many file descriptors received");
333 SocketActivated = TRUE;
334 Log1(PCSC_LOG_INFO,
"Started by systemd");
337 SocketActivated = FALSE;
344 rv = stat(PCSCLITE_CSOCK_NAME, &fStatBuf);
353 pid = GetDaemonPid();
358 return SendHotplugSignal();
363 Log1(PCSC_LOG_CRITICAL,
364 "file " PCSCLITE_CSOCK_NAME
" already exists.");
365 Log2(PCSC_LOG_CRITICAL,
366 "Another pcscd (pid: %d) seems to be running.", pid);
378 Log2(PCSC_LOG_CRITICAL,
"kill failed: %s", strerror(errno));
386 Log1(PCSC_LOG_CRITICAL,
"file " PCSCLITE_RUN_PID
" do not exist");
387 Log1(PCSC_LOG_CRITICAL,
"Hotplug failed");
395 Log1(PCSC_LOG_CRITICAL,
"Hotplug failed: pcscd is not running");
406 if (!setToForeground)
411 if (pipe(pipefd) == -1)
413 Log2(PCSC_LOG_CRITICAL,
"pipe() failed: %s", strerror(errno));
420 Log2(PCSC_LOG_CRITICAL,
"fork() failed: %s", strerror(errno));
426 fd = open(
"/dev/null", O_RDWR);
429 dup2(fd, STDIN_FILENO);
430 dup2(fd, STDOUT_FILENO);
431 dup2(fd, STDERR_FILENO);
448 ret = read(pipefd[0], &buf, 1);
469 (void)signal(SIGQUIT, signal_trap);
470 (void)signal(SIGTERM, signal_trap);
471 (void)signal(SIGINT, signal_trap);
474 (void)signal(SIGALRM, signal_trap);
480 int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;
482 rv = mkdir(PCSCLITE_IPC_DIR, mode);
483 if ((rv != 0) && (errno != EEXIST))
485 Log2(PCSC_LOG_CRITICAL,
486 "cannot create " PCSCLITE_IPC_DIR
": %s", strerror(errno));
493 (void)chmod(PCSCLITE_IPC_DIR, mode);
499 rv = RFAllocateReaderSpace(customMaxReaderHandles);
509 rv = RFStartSerialReaders(newReaderConfig);
512 Log3(PCSC_LOG_CRITICAL,
"invalid file %s: %s", newReaderConfig,
519 rv = RFStartSerialReaders(PCSCLITE_CONFIG_DIR);
525 Log1(PCSC_LOG_INFO,
"pcsc-lite " VERSION
" daemon ready.");
535 int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
537 f = open(PCSCLITE_RUN_PID, O_RDWR | O_CREAT, mode);
540 char pid[PID_ASCII_SIZE];
542 (void)snprintf(pid,
sizeof(pid),
"%u\n", (unsigned) getpid());
543 (void)write(f, pid, strlen(pid));
549 (void)chmod(PCSCLITE_RUN_PID, mode);
552 Log2(PCSC_LOG_CRITICAL,
"cannot create " PCSCLITE_RUN_PID
": %s",
564 (void)signal(SIGUSR1, signal_reload);
576 Log1(PCSC_LOG_CRITICAL,
"Error initializing pcscd.");
583 rv = ContextsInitialize(customMaxThreadCounter, customMaxThreadCardHandles);
587 Log1(PCSC_LOG_CRITICAL,
"Error initializing pcscd.");
591 (void)signal(SIGPIPE, SIG_IGN);
592 (void)signal(SIGHUP, SIG_IGN);
595 #if !defined(PCSCLITE_STATIC_DRIVER) && defined(USE_USB)
599 rv = HPSearchHotPluggables();
605 rv = HPRegisterForHotplugEvents();
608 Log1(PCSC_LOG_ERROR,
"HPRegisterForHotplugEvents failed");
612 RFWaitForReaderInit();
626 write(pipefd[1], &buf, 1);
632 Log1(PCSC_LOG_ERROR,
"SVCServiceRunLoop returned");
636 static void at_exit(
void)
638 Log1(PCSC_LOG_INFO,
"cleaning " PCSCLITE_IPC_DIR);
648 write(pipefd[1], &buf, 1);
655 static void clean_temp_files(
void)
659 if (!SocketActivated)
661 rv =
remove(PCSCLITE_CSOCK_NAME);
663 Log2(PCSC_LOG_ERROR,
"Cannot remove " PCSCLITE_CSOCK_NAME
": %s",
667 rv =
remove(PCSCLITE_RUN_PID);
669 Log2(PCSC_LOG_ERROR,
"Cannot remove " PCSCLITE_RUN_PID
": %s",
673 static void signal_reload(
int sig)
675 (void)signal(SIGUSR1, signal_reload);
683 HPReCheckSerialReaders();
687 static void signal_trap(
int sig)
689 Log2(PCSC_LOG_INFO,
"Received signal: %d", sig);
695 Log1(PCSC_LOG_INFO,
"Direct suicide");
702 ExitValue = EXIT_SUCCESS;
706 if (AraKiri == FALSE)
708 Log1(PCSC_LOG_INFO,
"Preparing for suicide");
716 Log1(PCSC_LOG_INFO,
"Suicide during init");
723 static int lives = 2;
729 Log1(PCSC_LOG_INFO,
"Forced suicide");
735 static void print_version (
void)
737 printf(
"%s version %s.\n", PACKAGE, VERSION);
738 printf(
"Copyright (C) 1999-2002 by David Corcoran <corcoran@linuxnet.com>.\n");
739 printf(
"Copyright (C) 2001-2011 by Ludovic Rousseau <ludovic.rousseau@free.fr>.\n");
740 printf(
"Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.\n");
741 printf(
"Report bugs to <muscle@lists.musclecard.com>.\n");
743 printf (
"Enabled features:%s\n", PCSCLITE_FEATURES);
746 static void print_usage (
char const *
const progname)
748 printf(
"Usage: %s options\n", progname);
749 printf(
"Options:\n");
750 #ifdef HAVE_GETOPT_LONG
751 printf(
" -a, --apdu log APDU commands and results\n");
752 printf(
" -c, --config path to reader.conf\n");
753 printf(
" -f, --foreground run in foreground (no daemon),\n");
754 printf(
" send logs to stdout instead of syslog\n");
755 printf(
" -T, --color force use of colored logs\n");
756 printf(
" -h, --help display usage information\n");
757 printf(
" -H, --hotplug ask the daemon to rescan the available readers\n");
758 printf(
" -v, --version display the program version number\n");
759 printf(
" -d, --debug display lower level debug messages\n");
760 printf(
" --info display info level debug messages\n");
761 printf(
" -e --error display error level debug messages (default level)\n");
762 printf(
" -C --critical display critical only level debug messages\n");
763 printf(
" --force-reader-polling ignore the IFD_GENERATE_HOTPLUG reader capability\n");
764 printf(
" -t, --max-thread maximum number of threads (default %d)\n", PCSC_MAX_CONTEXT_THREADS);
765 printf(
" -s, --max-card-handle-per-thread maximum number of card handle per thread (default: %d)\n", PCSC_MAX_CONTEXT_CARD_HANDLES);
766 printf(
" -r, --max-card-handle-per-reader maximum number of card handle per reader (default: %d)\n", PCSC_MAX_READER_HANDLES);
767 printf(
" -x, --auto-exit pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);
769 printf(
" -a log APDU commands and results\n");
770 printf(
" -c path to reader.conf\n");
771 printf(
" -f run in foreground (no daemon), send logs to stdout instead of syslog\n");
772 printf(
" -T force use of colored logs\n");
773 printf(
" -d display debug messages.\n");
774 printf(
" -e display error messages (default level).\n");
775 printf(
" -C display critical messages.\n");
776 printf(
" -h display usage information\n");
777 printf(
" -H ask the daemon to rescan the available readers\n");
778 printf(
" -v display the program version number\n");
779 printf(
" -t maximum number of threads\n");
780 printf(
" -s maximum number of card handle per thread\n");
781 printf(
" -r maximum number of card handle per reader\n");
782 printf(
" -x pcscd will quit after %d seconds of inactivity\n", TIME_BEFORE_SUICIDE);