aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/gpg-card.c131
1 files changed, 92 insertions, 39 deletions
diff --git a/tools/gpg-card.c b/tools/gpg-card.c
index 626579882..84bbd7ec1 100644
--- a/tools/gpg-card.c
+++ b/tools/gpg-card.c
@@ -1011,53 +1011,92 @@ list_card (card_info_t info, int no_key_lookup)
+/* Helper for cmd_list. */
+static void
+print_card_list (estream_t fp, card_info_t info, strlist_t cards,
+ int only_current)
+{
+ int count;
+ strlist_t sl;
+ size_t snlen;
+ int star;
+ const char *s;
+
+ for (count = 0, sl = cards; sl; sl = sl->next, count++)
+ {
+ if (info && info->serialno)
+ {
+ s = strchr (sl->d, ' ');
+ if (s)
+ snlen = s - sl->d;
+ else
+ snlen = strlen (sl->d);
+ star = (strlen (info->serialno) == snlen
+ && !memcmp (info->serialno, sl->d, snlen));
+ }
+ else
+ star = 0;
+ if (!only_current || star)
+ tty_fprintf (fp, "%d%c %s\n", count, star? '*':' ', sl->d);
+ }
+}
+
+
/* The LIST command. This also updates INFO if needed. */
static gpg_error_t
cmd_list (card_info_t info, char *argstr)
{
gpg_error_t err;
- int opt_cards, opt_apps, opt_no_key_lookup;
+ int opt_cards, opt_apps, opt_info, opt_no_key_lookup;
strlist_t cards = NULL;
strlist_t sl;
estream_t fp = opt.interactive? NULL : es_stdout;
- int cardno = -1;
+ const char *cardsn = NULL;
char *appstr = NULL;
int count;
int need_learn = 0;
- int star;
- size_t snlen;
- const char *s;
if (!info)
return print_help
- ("LIST [--cards] [--apps] [--no-key-lookup] [N] [APP]\n\n"
+ ("LIST [--cards] [--apps] [--info] [--no-key-lookup] [N] [APP]\n\n"
"Show the content of the current card.\n"
- "With N given select and list the n-th card;\n"
+ "With N given select and list the N-th card;\n"
"with APP also given select that application.\n"
"To select an APP on the current card use '-' for N.\n"
- " --cards lists available cards\n"
- " --apps lists additional card applications\n"
+ "The S/N of the card may be used instead of N.\n"
+ " --cards lists available cards\n"
+ " --apps lists additional card applications\n"
+ " --info selects a card and prints its s/n\n"
" --no-key-lookup does not list matching OpenPGP or X.509 keys\n"
, 0);
opt_cards = has_leading_option (argstr, "--cards");
opt_apps = has_leading_option (argstr, "--apps");
+ opt_info = has_leading_option (argstr, "--info");
opt_no_key_lookup = has_leading_option (argstr, "--no-key-lookup");
argstr = skip_options (argstr);
if (opt.no_key_lookup)
opt_no_key_lookup = 1;
- if (digitp (argstr) || (*argstr == '-' && spacep (argstr+1)))
+ if (hexdigitp (argstr) || (*argstr == '-' && spacep (argstr+1)))
{
if (*argstr == '-' && (argstr[1] || spacep (argstr+1)))
argstr++; /* Keep current card. */
else
{
- cardno = atoi (argstr);
- while (digitp (argstr))
+ cardsn = argstr;
+ while (hexdigitp (argstr))
argstr++;
+ if (*argstr && !spacep (argstr))
+ {
+ err = gpg_error (GPG_ERR_INV_ARG);
+ goto leave;
+ }
+ if (*argstr)
+ *argstr++ = 0;
}
+
while (spacep (argstr))
argstr++;
if (*argstr)
@@ -1082,7 +1121,6 @@ cmd_list (card_info_t info, char *argstr)
goto leave;
}
-
if (!info->serialno)
{
/* This is probably the first call. We need to send a SERIALNO
@@ -1093,7 +1131,6 @@ cmd_list (card_info_t info, char *argstr)
need_learn = 1;
}
-
if (opt_cards || opt_apps)
{
/* Note that with option --apps CARDS is here the list of all
@@ -1105,42 +1142,53 @@ cmd_list (card_info_t info, char *argstr)
err = scd_cardlist (&cards);
if (err)
goto leave;
- for (count = 0, sl = cards; sl; sl = sl->next, count++)
- {
- if (info && info->serialno)
- {
- s = strchr (sl->d, ' ');
- if (s)
- snlen = s - sl->d;
- else
- snlen = strlen (sl->d);
- star = (strlen (info->serialno) == snlen
- && !memcmp (info->serialno, sl->d, snlen));
- }
- else
- star = 0;
- tty_fprintf (fp, "%d%c %s\n", count, star? '*':' ', sl->d);
- }
+ print_card_list (fp, info, cards, 0);
}
else
{
- if (cardno != -1)
+ if (cardsn)
{
- /* Switch to the requested card. */
+ int i, cardno;
+
err = scd_cardlist (&cards);
if (err)
goto leave;
- for (count = 0, sl = cards; sl; sl = sl->next, count++)
- if (count == cardno)
- break;
- if (!sl)
+
+ /* Switch to the requested card. */
+ for (i=0; digitp (cardsn+i); i++)
+ ;
+ if (i && i < 4 && !cardsn[i])
+ { /* Looks like an index into the card list. */
+ cardno = atoi (cardsn);
+ for (count = 0, sl = cards; sl; sl = sl->next, count++)
+ if (count == cardno)
+ break;
+ if (!sl)
+ {
+ err = gpg_error (GPG_ERR_INV_INDEX);
+ goto leave;
+ }
+ }
+ else /* S/N of card specified. */
{
- err = gpg_error (GPG_ERR_INV_INDEX);
- goto leave;
+ for (sl = cards; sl; sl = sl->next)
+ if (!ascii_strcasecmp (sl->d, cardsn))
+ break;
+ if (!sl)
+ {
+ err = gpg_error (GPG_ERR_INV_INDEX);
+ goto leave;
+ }
}
err = scd_switchcard (sl->d);
need_learn = 1;
}
+ else /* --info with not args - show app list. */
+ {
+ err = scd_applist (&cards, 1);
+ if (err)
+ goto leave;
+ }
if (appstr && *appstr)
{
@@ -1155,7 +1203,12 @@ cmd_list (card_info_t info, char *argstr)
err = scd_learn (info);
else
err = 0;
- if (!err)
+
+ if (err)
+ ;
+ else if (opt_info)
+ print_card_list (fp, info, cards, 1);
+ else
list_card (info, opt_no_key_lookup);
}