00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00021 #include "config.h"
00022 #include <time.h>
00023 #include <syslog.h>
00024 #include <signal.h>
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027 #include <fcntl.h>
00028 #include <errno.h>
00029 #include <stdio.h>
00030 #include <unistd.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #ifdef HAVE_GETOPT_H
00034 #include <getopt.h>
00035 #endif
00036
00037 #include "misc.h"
00038 #include "pcsclite.h"
00039 #include "pcscd.h"
00040 #include "debuglog.h"
00041 #include "winscard_msg.h"
00042 #include "winscard_svc.h"
00043 #include "sys_generic.h"
00044 #include "thread_generic.h"
00045 #include "hotplug.h"
00046 #include "readerfactory.h"
00047 #include "configfile.h"
00048 #include "powermgt_generic.h"
00049 #include "utils.h"
00050
00051 #ifndef TRUE
00052 #define TRUE 1
00053 #define FALSE 0
00054 #endif
00055
00056 char AraKiri = FALSE;
00057 static char Init = TRUE;
00058 static int ExitValue = EXIT_SUCCESS;
00059 int HPForceReaderPolling = 0;
00060
00061
00062
00063
00064 void SVCServiceRunLoop(void);
00065 void SVCClientCleanup(psharedSegmentMsg);
00066 void at_exit(void);
00067 void clean_temp_files(void);
00068 void signal_reload(int sig);
00069 void signal_trap(int);
00070 void print_version (void);
00071 void print_usage (char const * const);
00072
00073 PCSCLITE_MUTEX usbNotifierMutex;
00074
00078 void SVCClientCleanup(psharedSegmentMsg msgStruct)
00079 {
00080
00081
00082
00083 }
00084
00093 void SVCServiceRunLoop(void)
00094 {
00095 int rsp;
00096 LONG rv;
00097 uint32_t dwClientID;
00098
00099 rsp = 0;
00100 rv = 0;
00101
00102
00103
00104
00105 rsp = SHMInitializeCommonSegment();
00106
00107 if (rsp == -1)
00108 {
00109 Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
00110 exit(-1);
00111 }
00112
00113
00114
00115
00116 rv = ContextsInitialize();
00117
00118 if (rv == -1)
00119 {
00120 Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
00121 exit(-1);
00122 }
00123
00124
00125
00126
00127
00128 signal(SIGALRM, SIG_IGN);
00129 signal(SIGPIPE, SIG_IGN);
00130 signal(SIGHUP, SIG_IGN);
00131
00132
00133
00134
00135
00136 rsp = SYS_MutexInit(&usbNotifierMutex);
00137
00138
00139
00140
00141 HPSearchHotPluggables();
00142 HPRegisterForHotplugEvents();
00143
00144
00145
00146
00147 PMRegisterForPowerEvents();
00148
00149 while (TRUE)
00150 {
00151 switch (rsp = SHMProcessEventsServer(&dwClientID, 0))
00152 {
00153
00154 case 0:
00155 Log2(PCSC_LOG_DEBUG, "A new context thread creation is requested: %d", dwClientID);
00156 rv = CreateContextThread(&dwClientID);
00157
00158 if (rv != SCARD_S_SUCCESS)
00159 Log1(PCSC_LOG_ERROR, "Problem during the context thread creation");
00160 break;
00161
00162 case 2:
00163
00164
00165
00166
00167
00168 break;
00169
00170 case -1:
00171 Log1(PCSC_LOG_ERROR, "Error in SHMProcessEventsServer");
00172 break;
00173
00174 case -2:
00175
00176
00177
00178 break;
00179
00180 default:
00181 Log2(PCSC_LOG_ERROR, "SHMProcessEventsServer unknown retval: %d",
00182 rsp);
00183 break;
00184 }
00185
00186 if (AraKiri)
00187 {
00188
00189 HPStopHotPluggables();
00190 SYS_Sleep(1);
00191
00192
00193 RFCleanupReaders(1);
00194 }
00195 }
00196 }
00197
00198 int main(int argc, char **argv)
00199 {
00200 int rv;
00201 char setToForeground;
00202 char HotPlug;
00203 char *newReaderConfig;
00204 struct stat fStatBuf;
00205 int opt;
00206 #ifdef HAVE_GETOPT_LONG
00207 int option_index = 0;
00208 static struct option long_options[] = {
00209 {"config", 1, NULL, 'c'},
00210 {"foreground", 0, NULL, 'f'},
00211 {"help", 0, NULL, 'h'},
00212 {"version", 0, NULL, 'v'},
00213 {"apdu", 0, NULL, 'a'},
00214 {"debug", 0, NULL, 'd'},
00215 {"info", 0, NULL, 0},
00216 {"error", 0, NULL, 'e'},
00217 {"critical", 0, NULL, 'C'},
00218 {"hotplug", 0, NULL, 'H'},
00219 {"force-reader-polling", optional_argument, NULL, 0},
00220 {NULL, 0, NULL, 0}
00221 };
00222 #endif
00223 #define OPT_STRING "c:fdhvaeCH"
00224
00225 rv = 0;
00226 newReaderConfig = NULL;
00227 setToForeground = FALSE;
00228 HotPlug = FALSE;
00229
00230
00231
00232
00233 if (strcmp(PCSCLITE_VERSION_NUMBER, VERSION) != 0)
00234 {
00235 printf("BUILD ERROR: The release version number PCSCLITE_VERSION_NUMBER\n");
00236 printf(" in pcsclite.h (%s) does not match the release version number\n",
00237 PCSCLITE_VERSION_NUMBER);
00238 printf(" generated in config.h (%s) (see configure.in).\n", VERSION);
00239
00240 return EXIT_FAILURE;
00241 }
00242
00243
00244
00245
00246
00247 DebugLogSetLogType(DEBUGLOG_SYSLOG_DEBUG);
00248
00249
00250
00251
00252 #ifdef HAVE_GETOPT_LONG
00253 while ((opt = getopt_long (argc, argv, OPT_STRING, long_options, &option_index)) != -1) {
00254 #else
00255 while ((opt = getopt (argc, argv, OPT_STRING)) != -1) {
00256 #endif
00257 switch (opt) {
00258 #ifdef HAVE_GETOPT_LONG
00259 case 0:
00260 if (strcmp(long_options[option_index].name,
00261 "force-reader-polling") == 0)
00262 HPForceReaderPolling = optarg ? abs(atoi(optarg)) : 1;
00263 break;
00264 #endif
00265 case 'c':
00266 Log2(PCSC_LOG_INFO, "using new config file: %s", optarg);
00267 newReaderConfig = optarg;
00268 break;
00269
00270 case 'f':
00271 setToForeground = TRUE;
00272
00273 DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG);
00274 Log1(PCSC_LOG_INFO,
00275 "pcscd set to foreground with debug send to stderr");
00276 break;
00277
00278 case 'd':
00279 DebugLogSetLevel(PCSC_LOG_DEBUG);
00280 break;
00281
00282 case 'e':
00283 DebugLogSetLevel(PCSC_LOG_ERROR);
00284 break;
00285
00286 case 'C':
00287 DebugLogSetLevel(PCSC_LOG_CRITICAL);
00288 break;
00289
00290 case 'h':
00291 print_usage (argv[0]);
00292 return EXIT_SUCCESS;
00293
00294 case 'v':
00295 print_version ();
00296 return EXIT_SUCCESS;
00297
00298 case 'a':
00299 DebugLogSetCategory(DEBUG_CATEGORY_APDU);
00300 break;
00301
00302 case 'H':
00303
00304 DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG);
00305 HotPlug = TRUE;
00306 break;
00307
00308 default:
00309 print_usage (argv[0]);
00310 return EXIT_FAILURE;
00311 }
00312
00313 }
00314
00315 if (argv[optind])
00316 {
00317 printf("Unknown option: %s\n\n", argv[optind]);
00318 print_usage(argv[0]);
00319 return EXIT_SUCCESS;
00320 }
00321
00322
00323
00324
00325
00326 rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &fStatBuf);
00327
00328 if (rv == 0)
00329 {
00330 pid_t pid;
00331
00332
00333
00334
00335 pid = GetDaemonPid();
00336
00337 if (pid != -1)
00338 {
00339 if (HotPlug)
00340 return SendHotplugSignal();
00341
00342 if (kill(pid, 0) == 0)
00343 {
00344 Log1(PCSC_LOG_CRITICAL,
00345 "file " PCSCLITE_PUBSHM_FILE " already exists.");
00346 Log2(PCSC_LOG_CRITICAL,
00347 "Another pcscd (pid: %d) seems to be running.", pid);
00348 return EXIT_FAILURE;
00349 }
00350 else
00351
00352 clean_temp_files();
00353 }
00354 else
00355 {
00356 if (HotPlug)
00357 {
00358 Log1(PCSC_LOG_CRITICAL, "file " PCSCLITE_RUN_PID " do not exist");
00359 Log1(PCSC_LOG_CRITICAL, "Hotplug failed");
00360 return EXIT_FAILURE;
00361 }
00362
00363 Log1(PCSC_LOG_CRITICAL,
00364 "file " PCSCLITE_PUBSHM_FILE " already exists.");
00365 Log1(PCSC_LOG_CRITICAL,
00366 "Maybe another pcscd is running?");
00367 Log1(PCSC_LOG_CRITICAL,
00368 "I can't read process pid from " PCSCLITE_RUN_PID);
00369 Log1(PCSC_LOG_CRITICAL,
00370 "Remove " PCSCLITE_PUBSHM_FILE " and " PCSCLITE_CSOCK_NAME);
00371 Log1(PCSC_LOG_CRITICAL,
00372 "if pcscd is not running to clear this message.");
00373 return EXIT_FAILURE;
00374 }
00375 }
00376 else
00377 if (HotPlug)
00378 {
00379 Log1(PCSC_LOG_CRITICAL, "Hotplug failed: pcscd is not running");
00380 return EXIT_FAILURE;
00381 }
00382
00383
00384
00385
00386 if (!setToForeground)
00387 {
00388 if (SYS_Daemon(0, 0))
00389 Log2(PCSC_LOG_CRITICAL, "SYS_Daemon() failed: %s",
00390 strerror(errno));
00391 }
00392
00393
00394
00395
00396 signal(SIGQUIT, signal_trap);
00397 signal(SIGTERM, signal_trap);
00398 signal(SIGINT, signal_trap);
00399 signal(SIGHUP, signal_trap);
00400
00401
00402
00403
00404 rv = SYS_Stat(PCSCLITE_IPC_DIR, &fStatBuf);
00405 if (rv < 0)
00406 {
00407 rv = SYS_Mkdir(PCSCLITE_IPC_DIR,
00408 S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU);
00409 if (rv != 0)
00410 {
00411 Log2(PCSC_LOG_CRITICAL,
00412 "cannot create " PCSCLITE_IPC_DIR ": %s", strerror(errno));
00413 return EXIT_FAILURE;
00414 }
00415 }
00416
00417
00418
00419
00420
00421 {
00422 int f;
00423
00424 if ((f = SYS_OpenFile(PCSCLITE_RUN_PID, O_RDWR | O_CREAT, 00644)) != -1)
00425 {
00426 char pid[PID_ASCII_SIZE];
00427
00428 snprintf(pid, sizeof(pid), "%u\n", (unsigned) getpid());
00429 SYS_WriteFile(f, pid, strlen(pid));
00430 SYS_CloseFile(f);
00431
00432
00433
00434 SYS_Chmod(PCSCLITE_RUN_PID, 0644);
00435 }
00436 else
00437 Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_RUN_PID ": %s",
00438 strerror(errno));
00439 }
00440
00441
00442 if (atexit(at_exit))
00443 Log2(PCSC_LOG_CRITICAL, "atexit() failed: %s", strerror(errno));
00444
00445
00446
00447
00448 RFAllocateReaderSpace();
00449
00450
00451
00452
00453 if (newReaderConfig)
00454 {
00455 rv = RFStartSerialReaders(newReaderConfig);
00456 if (rv != 0)
00457 {
00458 Log3(PCSC_LOG_CRITICAL, "invalid file %s: %s", newReaderConfig,
00459 strerror(errno));
00460 ExitValue = EXIT_FAILURE;
00461 at_exit();
00462 }
00463 }
00464 else
00465 {
00466 rv = RFStartSerialReaders(PCSCLITE_READER_CONFIG);
00467
00468 #if 0
00469 if (rv == 1)
00470 {
00471 Log1(PCSC_LOG_INFO,
00472 "warning: no " PCSCLITE_READER_CONFIG " found");
00473
00474
00475
00476 }
00477 else
00478 #endif
00479 if (rv == -1)
00480 {
00481 ExitValue = EXIT_FAILURE;
00482 at_exit();
00483 }
00484 }
00485
00486
00487
00488
00489 g_rgSCardT0Pci.dwProtocol = SCARD_PROTOCOL_T0;
00490 g_rgSCardT1Pci.dwProtocol = SCARD_PROTOCOL_T1;
00491 g_rgSCardRawPci.dwProtocol = SCARD_PROTOCOL_RAW;
00492
00493 Log1(PCSC_LOG_INFO, "pcsc-lite " VERSION " daemon ready.");
00494
00495
00496
00497
00498 Init = FALSE;
00499
00500
00501
00502
00503 signal(SIGQUIT, signal_trap);
00504 signal(SIGTERM, signal_trap);
00505 signal(SIGINT, signal_trap);
00506 signal(SIGHUP, signal_trap);
00507
00508 signal(SIGUSR1, signal_reload);
00509
00510 SVCServiceRunLoop();
00511
00512 Log1(PCSC_LOG_ERROR, "SVCServiceRunLoop returned");
00513 return EXIT_FAILURE;
00514 }
00515
00516 void at_exit(void)
00517 {
00518 Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR);
00519
00520 clean_temp_files();
00521
00522 SYS_Exit(ExitValue);
00523 }
00524
00525 void clean_temp_files(void)
00526 {
00527 int rv;
00528
00529 rv = SYS_Unlink(PCSCLITE_PUBSHM_FILE);
00530 if (rv != 0)
00531 Log2(PCSC_LOG_ERROR, "Cannot unlink " PCSCLITE_PUBSHM_FILE ": %s",
00532 strerror(errno));
00533
00534 rv = SYS_Unlink(PCSCLITE_CSOCK_NAME);
00535 if (rv != 0)
00536 Log2(PCSC_LOG_ERROR, "Cannot unlink " PCSCLITE_CSOCK_NAME ": %s",
00537 strerror(errno));
00538
00539 rv = SYS_Unlink(PCSCLITE_RUN_PID);
00540 if (rv != 0)
00541 Log2(PCSC_LOG_ERROR, "Cannot unlink " PCSCLITE_RUN_PID ": %s",
00542 strerror(errno));
00543 }
00544
00545 void signal_reload(int sig)
00546 {
00547 if (AraKiri)
00548 return;
00549
00550 HPReCheckSerialReaders();
00551 }
00552
00553 void signal_trap(int sig)
00554 {
00555
00556 if (AraKiri == FALSE)
00557 {
00558 Log1(PCSC_LOG_INFO, "Preparing for suicide");
00559 AraKiri = TRUE;
00560
00561
00562
00563
00564 if (Init)
00565 {
00566 Log1(PCSC_LOG_INFO, "Suicide during init");
00567 at_exit();
00568 }
00569 }
00570 }
00571
00572 void print_version (void)
00573 {
00574 printf("%s version %s.\n", PACKAGE, VERSION);
00575 printf("Copyright (C) 1999-2002 by David Corcoran <corcoran@linuxnet.com>.\n");
00576 printf("Copyright (C) 2001-2007 by Ludovic Rousseau <ludovic.rousseau@free.fr>.\n");
00577 printf("Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.\n");
00578 printf("Report bugs to <sclinux@linuxnet.com>.\n");
00579 }
00580
00581 void print_usage (char const * const progname)
00582 {
00583 printf("Usage: %s options\n", progname);
00584 printf("Options:\n");
00585 #ifdef HAVE_GETOPT_LONG
00586 printf(" -a, --apdu log APDU commands and results\n");
00587 printf(" -c, --config path to reader.conf\n");
00588 printf(" -f, --foreground run in foreground (no daemon),\n");
00589 printf(" send logs to stderr instead of syslog\n");
00590 printf(" -h, --help display usage information\n");
00591 printf(" -H, --hotplug ask the daemon to rescan the available readers\n");
00592 printf(" -v, --version display the program version number\n");
00593 printf(" -d, --debug display lower level debug messages\n");
00594 printf(" --info display info level debug messages (default level)\n");
00595 printf(" -e --error display error level debug messages\n");
00596 printf(" -C --critical display critical only level debug messages\n");
00597 printf(" --force-reader-polling ignore the IFD_GENERATE_HOTPLUG reader capability\n");
00598 #else
00599 printf(" -a log APDU commands and results\n");
00600 printf(" -c path to reader.conf\n");
00601 printf(" -f run in foreground (no daemon), send logs to stderr instead of syslog\n");
00602 printf(" -d display debug messages. Output may be:\n");
00603 printf(" -h display usage information\n");
00604 printf(" -H ask the daemon to rescan the available readers\n");
00605 printf(" -v display the program version number\n");
00606 #endif
00607 }
00608