opensc-notify: handle reader insertion/removal events

- If readers are attatched, the new reader is probed for a card to check
if a notification needs to be sent
- removal of readers are not notified to the user, we assume that PC/SC
sends the correct card removal event
- The list of readers to be monitored is adjusted once a reader (dis)appears
- On macOS, without PnP notification, we always check for new/removed
readers with SCardListReaders
- fixes interrupt handling in opensc-notify on Unix

fixes https://github.com/OpenSC/OpenSC/issues/1874
This commit is contained in:
Frank Morgner 2020-01-13 17:25:38 +01:00
parent 7893d2860c
commit 2c26b7392d
6 changed files with 248 additions and 130 deletions

View File

@ -45,8 +45,8 @@ const char *sc_strerror(int error)
"Message too long (keypad)",
"Timeout while waiting for event from card reader",
"Unresponsive card (correctly inserted?)",
"Reader detached (hotplug device?)",
"Reader reattached (hotplug device?)",
"Reader detached",
"Reader reattached",
"Reader in use by another application"
};
const int rdr_base = -SC_ERROR_READER;

View File

@ -100,6 +100,7 @@ typedef unsigned __int8 uint8_t;
#define SCARD_E_NOT_TRANSACTED 0x80100016 /**< An attempt was made to end a non-existent transaction. */
#define SCARD_E_READER_UNAVAILABLE 0x80100017 /**< The specified reader is not currently available for use. */
#define SCARD_E_NO_SERVICE 0x8010001D /**< The Smart card resource manager is not running. */
#define SCARD_E_SERVICE_STOPPED 0x8010001E /**< The smart card resource manager has shut down. */
#define SCARD_E_NO_READERS_AVAILABLE 0x8010002E /**< Cannot find a smart card reader. */
#define SCARD_W_UNRESPONSIVE_CARD 0x80100066 /**< The smart card is not responding to a reset. */
#define SCARD_W_UNPOWERED_CARD 0x80100067 /**< Power has been removed from the smart card, so that further communication is not possible. */

View File

@ -213,10 +213,10 @@ extern "C" {
/* Event masks for sc_wait_for_event() */
#define SC_EVENT_CARD_INSERTED 0x0001
#define SC_EVENT_CARD_REMOVED 0x0002
#define SC_EVENT_CARD_EVENTS SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED
#define SC_EVENT_CARD_EVENTS (SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED)
#define SC_EVENT_READER_ATTACHED 0x0004
#define SC_EVENT_READER_DETACHED 0x0008
#define SC_EVENT_READER_EVENTS SC_EVENT_READER_ATTACHED|SC_EVENT_READER_DETACHED
#define SC_EVENT_READER_EVENTS (SC_EVENT_READER_ATTACHED|SC_EVENT_READER_DETACHED)
#define MAX_FILE_SIZE 65535
@ -1024,18 +1024,25 @@ int sc_disconnect_card(struct sc_card *card);
int sc_detect_card_presence(sc_reader_t *reader);
/**
* Waits for an event on readers. Note: only the event is detected,
* there is no update of any card or other info.
* NOTE: Only PC/SC backend implements this.
* @param ctx pointer to a Context structure
* @param event_mask The types of events to wait for; this should
* be ORed from one of the following
* SC_EVENT_CARD_REMOVED
* SC_EVENT_CARD_INSERTED
* SC_EVENT_READER_ATTACHED
* @param event_reader (OUT) the reader on which the event was detected, or NULL if new reader
* Waits for an event on readers.
*
* In case of a reader event (attached/detached), the list of reader is
* adjusted accordingly. This means that a subsequent call to
* `sc_ctx_detect_readers()` is not needed.
*
* @note Only PC/SC backend implements this. An infinite timeout on macOS does
* not detect reader events (use a limited timeout instead if needed).
*
* @param ctx (IN) pointer to a Context structure
* @param event_mask (IN) The types of events to wait for; this should
* be ORed from one of the following:
* - SC_EVENT_CARD_REMOVED
* - SC_EVENT_CARD_INSERTED
* - SC_EVENT_READER_ATTACHED
* - SC_EVENT_READER_DETACHED
* @param event_reader (OUT) the reader on which the event was detected
* @param event (OUT) the events that occurred. This is also ORed
* from the SC_EVENT_CARD_* constants listed above.
* from the constants listed above.
* @param timeout Amount of millisecs to wait; -1 means forever
* @retval < 0 if an error occurred
* @retval = 0 if a an event happened

View File

@ -127,6 +127,9 @@ struct pcsc_global_private_data {
SCardTransmit_t SCardTransmit;
SCardListReaders_t SCardListReaders;
SCardGetAttrib_t SCardGetAttrib;
sc_reader_t *attached_reader;
sc_reader_t *removed_reader;
};
struct pcsc_private_data {
@ -185,6 +188,7 @@ static int pcsc_to_opensc_error(LONG rv)
return SC_ERROR_READER_DETACHED;
case SCARD_E_NO_SERVICE:
case SCARD_E_SERVICE_STOPPED:
/* If the service is (auto)started, there could be readers later */
return SC_ERROR_NO_READERS_FOUND;
case SCARD_E_NO_SMARTCARD:
@ -358,7 +362,7 @@ static int refresh_attributes(sc_reader_t *reader)
if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE)
return SC_ERROR_NOT_ALLOWED;
if (priv->reader_state.szReader == NULL) {
if (priv->reader_state.szReader == NULL || reader->ctx->flags & SC_READER_REMOVED) {
priv->reader_state.szReader = reader->name;
priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
priv->reader_state.dwEventState = SCARD_STATE_UNAWARE;
@ -382,12 +386,11 @@ static int refresh_attributes(sc_reader_t *reader)
}
/* the system could not detect the reader. It means, the prevoiusly attached reader is disconnected. */
if (
if (rv == (LONG)SCARD_E_UNKNOWN_READER
#ifdef SCARD_E_NO_READERS_AVAILABLE
(rv == (LONG)SCARD_E_NO_READERS_AVAILABLE) ||
|| rv == (LONG)SCARD_E_NO_READERS_AVAILABLE
#endif
(rv == (LONG)SCARD_E_UNKNOWN_READER) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) {
|| rv == (LONG)SCARD_E_SERVICE_STOPPED) {
if (old_flags & SC_READER_CARD_PRESENT) {
reader->flags |= SC_READER_CARD_CHANGED;
}
@ -1143,7 +1146,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
return;
rv = gpriv->SCardControl(card_handle, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, feature_buf, sizeof(feature_buf), &feature_len);
if (rv != (LONG)SCARD_S_SUCCESS) {
if (rv != SCARD_S_SUCCESS) {
PCSC_TRACE(reader, "SCardControl failed", rv);
return;
}
@ -1382,6 +1385,8 @@ static int pcsc_detect_readers(sc_context_t *ctx)
}
sc_log(ctx, "Probing PC/SC readers");
gpriv->attached_reader = NULL;
gpriv->removed_reader = NULL;
do {
if (gpriv->pcsc_ctx == (SCARDCONTEXT)-1) {
@ -1399,12 +1404,11 @@ static int pcsc_detect_readers(sc_context_t *ctx)
* All readers have disappeared, so mark them as
* such so we don't keep polling them over and over.
*/
if (
if (rv == (LONG)SCARD_E_NO_SERVICE
#ifdef SCARD_E_NO_READERS_AVAILABLE
(rv == (LONG)SCARD_E_NO_READERS_AVAILABLE) ||
|| rv == (LONG)SCARD_E_NO_READERS_AVAILABLE
#endif
(rv == (LONG)SCARD_E_NO_SERVICE) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) {
|| rv == (LONG)SCARD_E_SERVICE_STOPPED) {
for (i = 0; i < sc_ctx_get_reader_count(ctx); i++) {
sc_reader_t *reader = sc_ctx_get_reader(ctx, i);
@ -1414,6 +1418,7 @@ static int pcsc_detect_readers(sc_context_t *ctx)
}
reader->flags |= SC_READER_REMOVED;
gpriv->removed_reader = reader;
}
}
@ -1473,6 +1478,7 @@ static int pcsc_detect_readers(sc_context_t *ctx)
if (!strcmp(reader->name, reader_name)) {
if (reader->flags & SC_READER_REMOVED) {
reader->flags &= ~SC_READER_REMOVED;
gpriv->attached_reader = reader;
refresh_attributes(reader);
}
break;
@ -1487,8 +1493,11 @@ static int pcsc_detect_readers(sc_context_t *ctx)
(reader_buf + reader_buf_size) - next_reader_name);
reader_buf_size -= (next_reader_name - reader_name);
} else {
/* existing reader not found */
reader->flags |= SC_READER_REMOVED;
if (!(reader->flags & SC_READER_REMOVED)) {
/* existing reader not found */
reader->flags |= SC_READER_REMOVED;
gpriv->removed_reader = reader;
}
}
}
@ -1503,6 +1512,7 @@ static int pcsc_detect_readers(sc_context_t *ctx)
_sc_delete_reader(ctx, reader);
continue;
}
gpriv->attached_reader = reader;
/* check for pinpad support early, to allow opensc-tool -l display accurate information */
priv = reader->drv_data;
@ -1555,7 +1565,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
SCARD_READERSTATE *rgReaderStates;
size_t i;
unsigned int num_watch, count;
int r = SC_ERROR_INTERNAL;
int r = SC_ERROR_INTERNAL, detect_readers = 0, detected_hotplug = 0;
DWORD dwtimeout;
LOG_FUNC_CALLED(ctx);
@ -1579,8 +1589,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
sc_reader_t *reader = sc_ctx_get_reader(ctx, i);
if (reader->flags & SC_READER_REMOVED)
continue;
struct pcsc_private_data *priv = reader->drv_data;
rgReaderStates[num_watch].szReader = reader->name;
rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE;
if (priv->reader_state.szReader == NULL) {
rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE;
} else {
rgReaderStates[num_watch].dwCurrentState = priv->reader_state.dwEventState;
}
rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE;
num_watch++;
}
@ -1589,6 +1604,12 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
#ifdef __APPLE__
/* OS X 10.6.2 - 10.12.6 do not support PnP notification */
sc_log(ctx, "PnP notification not supported");
/* Always check on new readers as if a hotplug
* event was detected. This overwrites a
* SC_ERROR_EVENT_TIMEOUT if a new reader is
* detected with SC_SUCCESS. */
detect_readers = 1;
detected_hotplug = 1;
#else
rgReaderStates[num_watch].szReader = "\\\\?PnP?\\Notification";
rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE;
@ -1622,9 +1643,11 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
goto out;
}
*event_reader = NULL;
*event = 0;
if (num_watch == 0) {
sc_log(ctx, "No readers available to be watched");
*event_reader = NULL;
r = SC_ERROR_NO_READERS_FOUND;
goto out;
}
@ -1646,7 +1669,6 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
/* Scan the current state of all readers to see if they
* match any of the events we're polling for */
*event = 0;
for (i = 0, rsp = rgReaderStates; i < num_watch; i++, rsp++) {
DWORD state, prev_state;
sc_log(ctx, "'%s' before=0x%08X now=0x%08X",
@ -1657,51 +1679,72 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
state = rsp->dwEventState;
rsp->dwCurrentState = rsp->dwEventState;
if (state & SCARD_STATE_CHANGED) {
/* check for hotplug events */
if (!strcmp(rgReaderStates[i].szReader, "\\\\?PnP?\\Notification")) {
if (!strcmp(rsp->szReader, "\\\\?PnP?\\Notification")) {
sc_log(ctx, "detected hotplug event");
*event |= SC_EVENT_READER_ATTACHED;
*event_reader = NULL;
}
/* Windows sends hotplug event on both, attaching and
* detaching a reader. pcscd only sends it in case of
* attaching a reader. We'll detect later in which case we
* are. */
detect_readers = 1;
detected_hotplug = 1;
if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) {
sc_log(ctx, "card inserted event");
*event |= SC_EVENT_CARD_INSERTED;
}
/* Windows wants us to manually reset the changed state */
rsp->dwEventState &= ~SCARD_STATE_CHANGED;
if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) {
sc_log(ctx, "card removed event");
*event |= SC_EVENT_CARD_REMOVED;
}
/* By default, ignore a hotplug event as if a timout
* occurred, since it may be an unrequested removal or
* false alarm. Just continue to loop and check at the end
* of this function whether we need to return the attached
* reader or not. */
r = SC_ERROR_EVENT_TIMEOUT;
} else {
sc_reader_t *reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader);
if (reader) {
/* copy the state so we know what to watch out for */
struct pcsc_private_data *priv = reader->drv_data;
priv->reader_state.dwEventState = state;
priv->reader_state.dwCurrentState = prev_state;
}
if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) {
sc_log(ctx, "reader detached event");
*event |= SC_EVENT_READER_DETACHED;
}
if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) {
sc_log(ctx, "card inserted event");
*event |= SC_EVENT_CARD_INSERTED;
}
if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) {
sc_log(ctx, "reader re-attached event");
*event |= SC_EVENT_READER_ATTACHED;
}
if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) {
sc_log(ctx, "card removed event");
*event |= SC_EVENT_CARD_REMOVED;
}
if (*event & event_mask) {
sc_log(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader);
*event_reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader);
r = SC_SUCCESS;
goto out;
}
if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) {
sc_log(ctx, "reader detached event");
*event |= SC_EVENT_READER_DETACHED;
detect_readers = 1;
}
if ((state & SCARD_STATE_IGNORE) && !(prev_state & SCARD_STATE_IGNORE)) {
sc_log(ctx, "reader detached event");
*event |= SC_EVENT_READER_DETACHED;
detect_readers = 1;
}
if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) {
sc_log(ctx, "reader re-attached event");
*event |= SC_EVENT_READER_ATTACHED;
detect_readers = 1;
}
if (*event & event_mask) {
sc_log(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader);
*event_reader = reader;
r = SC_SUCCESS;
goto out;
} else {
*event = 0;
}
}
}
/* No match - copy the state so pcscd knows
* what to watch out for */
/* rsp->dwCurrentState = rsp->dwEventState; */
}
if (timeout == 0) {
r = SC_ERROR_EVENT_TIMEOUT;
goto out;
}
/* Set the timeout if caller wants to time out */
@ -1713,13 +1756,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, dwtimeout, rgReaderStates, num_watch);
if (rv == (LONG) SCARD_E_CANCELLED) {
if (rv == (LONG)SCARD_E_CANCELLED) {
/* C_Finalize was called, events don't matter */
r = SC_ERROR_EVENT_TIMEOUT;
goto out;
}
if (rv == (LONG) SCARD_E_TIMEOUT) {
if (rv == (LONG)SCARD_E_TIMEOUT) {
r = SC_ERROR_EVENT_TIMEOUT;
goto out;
}
@ -1731,12 +1774,54 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
}
}
out:
if (!reader_states) {
free(rgReaderStates);
/* in case of an error re-detect all readers */
if (r < 0 && r != SC_ERROR_EVENT_TIMEOUT)
detect_readers = 1;
if (detect_readers) {
pcsc_detect_readers(ctx);
}
else if (*reader_states == NULL) {
sc_log(ctx, "return allocated 'reader states'");
*reader_states = rgReaderStates;
if (detected_hotplug) {
if (gpriv->attached_reader) {
if (event_reader && event && !*event) {
/* no other event has been detected, yet */
*event_reader = gpriv->attached_reader;
*event = SC_EVENT_READER_ATTACHED;
r = SC_SUCCESS;
}
gpriv->attached_reader = NULL;
} else if (gpriv->removed_reader) {
/* Normally, we only check the hotplug event for attached readers.
* However, Windows also notifies on removal. Check, if the latter
* was requested by the caller. */
if (event_mask & SC_EVENT_READER_DETACHED
&& event_reader && event && !*event) {
/* no other event has been detected, yet */
*event_reader = gpriv->removed_reader;
*event = SC_EVENT_READER_DETACHED;
r = SC_SUCCESS;
}
gpriv->removed_reader = NULL;
} else {
/* false alarm, there was no reader attached or removed,
* avoid re-initialize the reader states by resetting detect_readers */
detect_readers = 0;
}
}
if (detect_readers) {
free(rgReaderStates);
if (reader_states && *reader_states)
*reader_states = NULL;
} else {
if (!reader_states) {
free(rgReaderStates);
}
else if (*reader_states == NULL) {
sc_log(ctx, "return allocated reader states");
*reader_states = rgReaderStates;
}
}
LOG_FUNC_RETURN(ctx, r);
@ -2449,6 +2534,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c
}
sc_log(ctx, "Probing PC/SC reader");
gpriv->attached_reader = NULL;
gpriv->pcsc_ctx = *(SCARDCONTEXT *)pcsc_context_handle;
card_handle = *(SCARDHANDLE *)pcsc_card_handle;
@ -2467,6 +2553,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c
} else {
_sc_delete_reader(ctx, reader);
}
gpriv->attached_reader = reader;
}
out:

View File

@ -49,26 +49,21 @@ void Sleep(unsigned int Milliseconds)
}
#endif
void stop_daemon()
{
#ifdef PCSCLITE_GOOD
sc_cancel(ctx);
#endif
run_daemon = 0;
}
void notify_daemon()
{
int r;
const unsigned int event_mask = SC_EVENT_CARD_EVENTS;
const unsigned int event_mask = SC_EVENT_CARD_EVENTS|SC_EVENT_READER_EVENTS;
unsigned int event;
struct sc_reader *event_reader = NULL;
size_t error_count = 0;
void *reader_states = NULL;
#ifndef __APPLE__
/* timeout adjusted to the maximum response time for WM_CLOSE in case
* canceling doesn't work */
const int timeout = 20000;
struct sc_atr old_atr;
void *reader_states = NULL;
#else
/* lower timeout, because Apple doesn't support hotplug events */
const int timeout = 2000;
#endif
r = sc_establish_context(&ctx, "opensc-notify");
if (r < 0 || !ctx) {
@ -76,50 +71,51 @@ void notify_daemon()
return;
}
while (run_daemon && error_count < 1000) {
while (run_daemon) {
r = sc_wait_for_event(ctx, event_mask,
&event_reader, &event, timeout, &reader_states);
if (r < 0) {
if (r == SC_ERROR_NO_READERS_FOUND) {
/* No readers available, PnP notification not supported */
Sleep(200);
} else {
error_count++;
Sleep(timeout);
continue;
}
continue;
}
error_count = 0;
if (event & SC_EVENT_CARD_REMOVED) {
sc_notify_id(ctx, &old_atr, NULL, NOTIFY_CARD_REMOVED);
}
if (event & SC_EVENT_CARD_INSERTED) {
if (event_reader) {
/* FIXME `pcsc_wait_for_event` has all the information that's
* requested again with `pcsc_detect_card_presence`, but it
* doesn't use the ATR, for example, to refresh the reader's
* attributes. To get the ATR we need to call
* sc_detect_card_presence. Eventually this should be fixed. */
sc_detect_card_presence(event_reader);
memcpy(old_atr.value, event_reader->atr.value,
event_reader->atr.len);
old_atr.len = event_reader->atr.len;
} else {
old_atr.len = 0;
if (event_reader) {
if (event & SC_EVENT_CARD_REMOVED
|| (event & SC_EVENT_READER_DETACHED
&& event_reader->flags & SC_READER_CARD_PRESENT)) {
/* sc_notify_id uses only the reader's name for displaying on
* removal, so use a dummy card here to get that information
* into the notification */
struct sc_pkcs15_card p15card;
sc_card_t card;
memset(&card, 0, sizeof card);
card.reader = event_reader;
memset(&p15card, 0, sizeof p15card);
p15card.card = &card;
sc_notify_id(ctx, &event_reader->atr, &p15card, NOTIFY_CARD_REMOVED);
} else if (event & SC_EVENT_CARD_INSERTED
|| (event & SC_EVENT_READER_ATTACHED
&& event_reader->flags & SC_READER_CARD_PRESENT)) {
/* sc_notify_id prevers the reader's name for displaying on
* insertion, so use a dummy card here to get that information
* into the notification */
struct sc_pkcs15_card p15card;
sc_card_t card;
memset(&card, 0, sizeof card);
card.reader = event_reader;
memset(&p15card, 0, sizeof p15card);
p15card.card = &card;
sc_notify_id(ctx, &event_reader->atr, &p15card, NOTIFY_CARD_INSERTED);
}
sc_notify_id(ctx, old_atr.len ? &old_atr : NULL, NULL,
NOTIFY_CARD_INSERTED);
}
}
if (ctx) {
if (error_count >= 1000) {
sc_log(ctx, "Too many errors; aborting.");
}
/* free `reader_states` */
sc_wait_for_event(ctx, 0, NULL, NULL, 0, &reader_states);
reader_states = NULL;
sc_release_context(ctx);
ctx = NULL;
}
@ -132,7 +128,8 @@ void notify_daemon()
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_CLOSE || message == WM_QUIT) {
stop_daemon();
run_daemon = 0;
sc_cancel(ctx);
return TRUE;
}
@ -182,32 +179,54 @@ WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nShowC
#else
#ifdef HAVE_SIGACTION
#if defined(HAVE_SIGACTION) && defined(HAVE_PTHREAD)
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
static int cancellation_fd[] = {-1, -1};
void sig_handler(int sig) {
stop_daemon();
run_daemon = 0;
write(cancellation_fd[1], &sig, sizeof sig);
}
void set_sa_handler(void)
static void *cancellation_proc(void *arg)
{
struct sigaction new_sig, old_sig;
(void)arg;
while (run_daemon) {
int sig;
if (sizeof sig == read(cancellation_fd[0], &sig, sizeof sig)) {
break;
}
}
sc_cancel(ctx);
return NULL;
}
/* Register signal handlers */
void setup_cancellation(void)
{
pthread_t cancellation_thread;
struct sigaction new_sig, old_sig;
new_sig.sa_handler = sig_handler;
sigemptyset(&new_sig.sa_mask);
new_sig.sa_flags = SA_RESTART;
if ((sigaction(SIGINT, &new_sig, &old_sig) < 0)
|| (sigaction(SIGTERM, &new_sig, &old_sig) < 0)) {
fprintf(stderr, "Failed to create signal handler: %s", strerror(errno));
if (pipe(cancellation_fd) != 0
|| (errno = pthread_create(&cancellation_thread, NULL, cancellation_proc, NULL)) != 0
|| sigaction(SIGINT, &new_sig, &old_sig) != 0
|| sigaction(SIGTERM, &new_sig, &old_sig) != 0) {
fprintf(stderr, "Failed to setup cancellation: %s", strerror(errno));
}
}
#else
void set_sa_handler(void)
void setup_cancellation(void)
{
}
#endif
#include "opensc-notify-cmdline.h"
@ -244,8 +263,8 @@ main (int argc, char **argv)
if ((!cmdline.customized_mode_counter && !cmdline.standard_mode_counter)
|| cmdline.daemon_mode_counter) {
set_sa_handler();
run_daemon = 1;
setup_cancellation();
notify_daemon();
} else {
/* give the notification process some time to spawn */

View File

@ -34,8 +34,12 @@ static const char *get_inserted_text(struct sc_pkcs15_card *p15card, struct sc_a
static char text[3*SC_MAX_ATR_SIZE] = {0};
const char prefix[] = "ATR: ";
if (p15card && p15card->card && p15card->card->name) {
if (p15card && p15card->card
&& p15card->card->name) {
return p15card->card->name;
} else if (p15card && p15card->card
&& p15card->card->reader && p15card->card->reader->name) {
return p15card->card->reader->name;
}
if (!atr)
@ -192,7 +196,7 @@ const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr,
str = "Dieses Fenster wird automatisch geschlossen, wenn die PIN am PIN-Pad eingegeben wurde (Timeout typischerweise nach 30 Sekunden).";
break;
case NOTIFY_CARD_INSERTED:
if (p15card) {
if (p15card && p15card->card && p15card->card->name) {
str = "Smartcard kann jetzt verwendet werden";
} else {
str = "Smartcard erkannt";
@ -260,7 +264,7 @@ const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr,
str = "This window will be closed automatically after the PIN has been submitted on the PIN pad (timeout typically after 30 seconds).";
break;
case NOTIFY_CARD_INSERTED:
if (p15card) {
if (p15card && p15card->card && p15card->card->name) {
str = "Smart card is ready to use";
} else {
str = "Smart card detected";