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