card: Allow card selection with LIST.
authorWerner Koch <wk@gnupg.org>
Wed, 3 Apr 2019 08:27:08 +0000 (10:27 +0200)
committerWerner Koch <wk@gnupg.org>
Wed, 3 Apr 2019 08:27:08 +0000 (10:27 +0200)
* tools/card-call-scd.c (start_agent): Request serialno only whean
started.
(scd_serialno): Allow NULL for r_serialno.
* tools/gpg-card.c (cmd_factoryreset): Use changed scd_serialno.
(cmd_list): New.
(dispatch_command): Use cmd_list for cmdLIST.
(interactive_loop): Ditto.

Signed-off-by: Werner Koch <wk@gnupg.org>
tools/card-call-scd.c
tools/gpg-card.c

index 0a01bf5..c2580bf 100644 (file)
@@ -310,11 +310,13 @@ static gpg_error_t
 start_agent (unsigned int flags)
 {
   gpg_error_t err;
+  int started = 0;
 
   if (agent_ctx)
     err = 0;
   else
     {
+      started = 1;
       err = start_new_gpg_agent (&agent_ctx,
                                  GPG_ERR_SOURCE_DEFAULT,
                                  opt.agent_program,
@@ -347,7 +349,7 @@ start_agent (unsigned int flags)
         }
     }
 
-  if (!err && !(flags & START_AGENT_NO_STARTUP_CMDS))
+  if (started && !err && !(flags & START_AGENT_NO_STARTUP_CMDS))
     {
       /* Request the serial number of the card for an early test.  */
       struct card_info_s info;
@@ -990,7 +992,7 @@ learn_status_cb (void *opaque, const char *line)
 
 
 /* Call the scdaemon to learn about a smartcard.  This fills INFO
- * wioth data from the card. */
+ * with data from the card. */
 gpg_error_t
 scd_learn (card_info_t info)
 {
@@ -1268,7 +1270,7 @@ scd_genkey (const char *keyref, int force, const char *algo, u32 *createtime)
 \f
 /* Return the serial number of the card or an appropriate error.  The
  * serial number is returned as a hexstring.  If DEMAND is not NULL
- * the reader with the a card of the serilanumber DEMAND is
+ * the reader with the a card of the serial number DEMAND is
  * requested.  */
 gpg_error_t
 scd_serialno (char **r_serialno, const char *demand)
@@ -1295,7 +1297,10 @@ scd_serialno (char **r_serialno, const char *demand)
       return err;
     }
 
-  *r_serialno = serialno;
+  if (r_serialno)
+    *r_serialno = serialno;
+  else
+    xfree (serialno);
   return 0;
 }
 
index d98a545..ddc4d12 100644 (file)
@@ -1000,6 +1000,81 @@ list_card (card_info_t info)
 
 
 \f
+/* The LIST command.  This also updates INFO. */
+static gpg_error_t
+cmd_list (card_info_t info, char *argstr)
+{
+  gpg_error_t err;
+  int opt_cards;
+  strlist_t cards = NULL;
+  strlist_t sl;
+  estream_t fp = opt.interactive? NULL : es_stdout;
+  int cardno, count;
+
+
+  if (!info)
+    return print_help
+      ("LIST [--cards] [N]\n\n"
+       "Show the content of the current card or with N given the N-th card.\n"
+       "Option --cards lists available cards.",
+       0);
+
+  opt_cards = has_leading_option (argstr, "--cards");
+  argstr = skip_options (argstr);
+
+
+  if (digitp (argstr))
+    {
+      cardno = atoi (argstr);
+      while (digitp (argstr))
+        argstr++;
+      while (spacep (argstr))
+        argstr++;
+    }
+  else
+    cardno = -1;
+
+
+  if (opt_cards)
+    {
+      err = scd_cardlist (&cards);
+      if (err)
+        goto leave;
+      for (count = 0, sl = cards; sl; sl = sl->next, count++)
+        tty_fprintf (fp, "%d %s\n", count, sl->d);
+    }
+  else
+    {
+      if (cardno != -1)
+        {
+          err = scd_cardlist (&cards);
+          if (err)
+            goto leave;
+          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;
+            }
+          err = scd_serialno (NULL, sl->d);
+          if (err)
+            goto leave;
+        }
+
+      err = scd_learn (info);
+      if (!err)
+        list_card (info);
+    }
+
+ leave:
+  free_strlist (cards);
+  return err;
+}
+
+
+\f
 /* The VERIFY command.  */
 static gpg_error_t
 cmd_verify (card_info_t info, char *argstr)
@@ -2478,9 +2553,8 @@ cmd_factoryreset (card_info_t info)
   if (err)
     goto leave;
 
-  /* Then, connect the card again (answer used as a dummy).  */
-  xfree (answer); answer = NULL;
-  err = scd_serialno (&answer, NULL);
+  /* Then, connect the card again.  */
+  err = scd_serialno (NULL, NULL);
 
  leave:
   if (err && any_apdu && !is_yubikey)
@@ -3158,20 +3232,6 @@ dispatch_command (card_info_t info, const char *orig_command)
         }
       break;
 
-    case cmdLIST:
-      if (!info)
-        print_help ("LIST\n\n"
-                    "Show content of the card.", 0);
-      else
-        {
-          err = scd_learn (info);
-          if (err)
-            log_error ("Error reading card: %s\n", gpg_strerror (err));
-          else
-            list_card (info);
-        }
-      break;
-
     case cmdRESET:
       if (!info)
         print_help ("RESET\n\n"
@@ -3183,6 +3243,7 @@ dispatch_command (card_info_t info, const char *orig_command)
         }
       break;
 
+    case cmdLIST:         err = cmd_list (info, argstr); break;
     case cmdVERIFY:       err = cmd_verify (info, argstr); break;
     case cmdAUTH:         err = cmd_authenticate (info, argstr); break;
     case cmdNAME:         err = cmd_name (info, argstr); break;
@@ -3268,14 +3329,11 @@ interactive_loop (void)
         }
       else if (redisplay)
         {
-          err = scd_learn (info);
+          err = cmd_list (info, "");
           if (err)
-            {
-              log_error ("Error reading card: %s\n", gpg_strerror (err));
-            }
+            log_error ("Error reading card: %s\n", gpg_strerror (err));
           else
             {
-              list_card (info);
               tty_printf("\n");
               redisplay = 0;
             }
@@ -3388,17 +3446,6 @@ interactive_loop (void)
             }
           break;
 
-        case cmdLIST:
-          if (!info)
-            print_help ("LIST\n\n"
-                        "Show content of the card.", 0);
-          else
-            {
-              /* Actual work is done by the redisplay code block.  */
-              redisplay = 1;
-            }
-          break;
-
         case cmdRESET:
           if (!info)
             print_help ("RESET\n\n"
@@ -3410,6 +3457,7 @@ interactive_loop (void)
             }
           break;
 
+        case cmdLIST:      err = cmd_list (info, argstr); break;
         case cmdVERIFY:
           err = cmd_verify (info, argstr);
           if (!err)