aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scd/apdu.c45
-rw-r--r--scd/apdu.h1
-rw-r--r--scd/command.c54
3 files changed, 88 insertions, 12 deletions
diff --git a/scd/apdu.c b/scd/apdu.c
index f00b35915..709ce3086 100644
--- a/scd/apdu.c
+++ b/scd/apdu.c
@@ -60,6 +60,7 @@
#include "../common/exechelp.h"
#endif /* GNUPG_MAJOR_VERSION != 1 */
#include "../common/host2net.h"
+#include "../common/membuf.h"
#include "iso7816.h"
#include "apdu.h"
@@ -92,6 +93,7 @@ typedef unsigned long pcsc_dword_t;
static struct pcsc {
int count; /* Reference count - valid if .context != -1 */
long context;
+ char *reader_list; /* List of detected readers. */
} pcsc;
/* A structure to collect information pertaining to one reader
@@ -1204,6 +1206,10 @@ open_pcsc_reader (const char *portstr)
pcsc_dword_t nreader;
char *p;
size_t n;
+ membuf_t reader_mb;
+
+ xfree (pcsc.reader_list);
+ pcsc.reader_list = NULL;
if (pcsc.context == -1)
if (pcsc_init () < 0)
@@ -1212,6 +1218,7 @@ open_pcsc_reader (const char *portstr)
if (DBG_READER)
log_debug ("open_pcsc_reader(portstr=%s)\n", portstr);
+
slot = new_reader_slot ();
if (slot == -1)
return -1; /* No need to cleanup here. */
@@ -1243,6 +1250,8 @@ open_pcsc_reader (const char *portstr)
goto leave;
}
+ init_membuf (&reader_mb, 256);
+
p = list;
while (nreader > 0)
{
@@ -1260,11 +1269,17 @@ open_pcsc_reader (const char *portstr)
}
log_info ("detected reader '%s'\n", p);
+ put_membuf_str (&reader_mb, p);
+ put_membuf (&reader_mb, "\n", 1);
if (!rdrname && portstr && !strncmp (p, portstr, strlen (portstr)))
rdrname = p;
nreader -= n + 1;
p += n + 1;
}
+ put_membuf (&reader_mb, "", 1);
+ pcsc.reader_list = get_membuf (&reader_mb, NULL);
+ if (!pcsc.reader_list)
+ log_error ("error allocating memory for reader list\n");
if (!rdrname)
rdrname = list;
@@ -3353,6 +3368,35 @@ apdu_get_reader_name (int slot)
return reader_table[slot].rdrname;
}
+
+/* Return the list of currently known readers. Caller must free the
+ * returned value. Might return NULL. */
+char *
+apdu_get_reader_list (void)
+{
+ membuf_t mb;
+ char *ccidlist = NULL;
+
+ init_membuf (&mb, 256);
+#ifdef HAVE_LIBUSB
+ ccidlist = ccid_get_reader_list ();
+#endif
+
+ if (ccidlist && *ccidlist)
+ put_membuf_str (&mb, ccidlist);
+ if (pcsc.reader_list && *pcsc.reader_list)
+ {
+ if (ccidlist && *ccidlist)
+ put_membuf (&mb, "\n", 1);
+ put_membuf_str (&mb, pcsc.reader_list);
+ }
+ xfree (ccidlist);
+ put_membuf (&mb, "", 1);
+
+ return get_membuf (&mb, NULL);
+}
+
+
gpg_error_t
apdu_init (void)
{
@@ -3362,6 +3406,7 @@ apdu_init (void)
pcsc.count = 0;
pcsc.context = -1;
+ pcsc.reader_list = NULL;
if (npth_mutex_init (&reader_table_lock, NULL))
goto leave;
diff --git a/scd/apdu.h b/scd/apdu.h
index a7f2b145f..32b8e9eff 100644
--- a/scd/apdu.h
+++ b/scd/apdu.h
@@ -151,5 +151,6 @@ int apdu_send_direct (int slot, size_t extended_length,
int handle_more, unsigned int *r_sw,
unsigned char **retbuf, size_t *retbuflen);
const char *apdu_get_reader_name (int slot);
+char *apdu_get_reader_list (void);
#endif /*APDU_H*/
diff --git a/scd/command.c b/scd/command.c
index e2debf5b8..fab65860b 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -36,9 +36,6 @@
#include "iso7816.h"
#include "apdu.h" /* Required for apdu_*_reader (). */
#include "atr.h"
-#ifdef HAVE_LIBUSB
-#include "ccid-driver.h"
-#endif
#include "../common/asshelp.h"
#include "../common/server-help.h"
@@ -1401,6 +1398,45 @@ cmd_unlock (assuan_context_t ctx, char *line)
}
+/* Ease reading of Assuan data ;ines by sending a physical line after
+ * each LF. */
+static gpg_error_t
+pretty_assuan_send_data (assuan_context_t ctx,
+ const void *buffer_arg, size_t size)
+{
+ const char *buffer = buffer_arg;
+ const char *p;
+ size_t n, nbytes;
+ gpg_error_t err;
+
+ nbytes = size;
+ do
+ {
+ p = memchr (buffer, '\n', nbytes);
+ n = p ? (p - buffer) + 1 : nbytes;
+ err = assuan_send_data (ctx, buffer, n);
+ if (err)
+ {
+ /* We also set ERRNO in case this function is used by a
+ * custom estream I/O handler. */
+ gpg_err_set_errno (EIO);
+ goto leave;
+ }
+ buffer += n;
+ nbytes -= n;
+ if (nbytes && (err=assuan_send_data (ctx, NULL, 0))) /* Flush line. */
+ {
+ gpg_err_set_errno (EIO);
+ goto leave;
+ }
+ }
+ while (nbytes);
+
+ leave:
+ return err;
+}
+
+
static const char hlp_getinfo[] =
"GETINFO <what>\n"
"\n"
@@ -1418,8 +1454,7 @@ static const char hlp_getinfo[] =
" 'u' Usable card present.\n"
" 'r' Card removed. A reset is necessary.\n"
" These flags are exclusive.\n"
- " reader_list - Return a list of detected card readers. Does\n"
- " currently only work with the internal CCID driver.\n"
+ " reader_list - Return a list of detected card readers.\n"
" deny_admin - Returns OK if admin commands are not allowed or\n"
" GPG_ERR_GENERAL if admin commands are allowed.\n"
" app_list - Return a list of supported applications. One\n"
@@ -1474,14 +1509,9 @@ cmd_getinfo (assuan_context_t ctx, char *line)
}
else if (!strcmp (line, "reader_list"))
{
-#ifdef HAVE_LIBUSB
- char *s = ccid_get_reader_list ();
-#else
- char *s = NULL;
-#endif
-
+ char *s = apdu_get_reader_list ();
if (s)
- rc = assuan_send_data (ctx, s, strlen (s));
+ rc = pretty_assuan_send_data (ctx, s, strlen (s));
else
rc = gpg_error (GPG_ERR_NO_DATA);
xfree (s);