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