Port Windows code to NPTH.
[gnupg.git] / scd / command.c
index 2ade38a..4c3646c 100644 (file)
@@ -26,8 +26,8 @@
 #include <ctype.h>
 #include <unistd.h>
 #include <signal.h>
-#ifdef USE_GNU_PTH
-# include <pth.h>
+#ifdef USE_NPTH
+# include <npth.h>
 #endif
 
 #include "scdaemon.h"
 #include <ksba.h>
 #include "app-common.h"
 #include "apdu.h" /* Required for apdu_*_reader (). */
+#include "atr.h"
 #include "exechelp.h"
 #ifdef HAVE_LIBUSB
 #include "ccid-driver.h"
 #endif
 
+
 /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
 #define MAXLEN_PIN 100
 
@@ -154,7 +156,7 @@ static struct server_local_s *locked_session;
 
 /* While doing a reset we need to make sure that the ticker does not
    call scd_update_reader_status_file while we are using it. */
-static pth_mutex_t status_file_update_lock;
+static npth_mutex_t status_file_update_lock;
 
 \f
 /*-- Local prototypes --*/
@@ -171,15 +173,30 @@ void
 initialize_module_command (void)
 {
   static int initialized;
+  int err;
 
   if (!initialized)
     {
-      if (pth_mutex_init (&status_file_update_lock))
+      err = npth_mutex_init (&status_file_update_lock, NULL);
+      if (!err)
         initialized = 1;
     }
 }
 
 
+/* Helper to return the slot number for a given virtual reader index
+   VRDR.  In case on an error -1 is returned.  */
+static int
+vreader_slot (int vrdr)
+{
+  if (vrdr == -1 || !(vrdr >= 0 && vrdr < DIM(vreader_table)))
+    return -1;
+  if (!vreader_table [vrdr].valid)
+    return -1;
+  return vreader_table[vrdr].slot;
+}
+
+
 /* Update the CARD_REMOVED element of all sessions using the virtual
    reader given by VRDR to VALUE.  */
 static void
@@ -187,6 +204,9 @@ update_card_removed (int vrdr, int value)
 {
   struct server_local_s *sl;
 
+  if (vrdr == -1)
+    return;
+
   for (sl=session_list; sl; sl = sl->next_session)
     if (sl->ctrl_backlink
         && sl->ctrl_backlink->server_local->vreader_idx == vrdr)
@@ -195,20 +215,7 @@ update_card_removed (int vrdr, int value)
       }
   /* Let the card application layer know about the removal.  */
   if (value)
-    application_notify_card_reset (vrdr);
-}
-
-
-/* Helper to return the slot number for a given virtual reader index
-   VRDR.  In case on an error -1 is returned.  */
-static int
-vreader_slot (int vrdr)
-{
-  if (vrdr == -1 || !(vrdr >= 0 && vrdr < DIM(vreader_table)))
-    return -1;
-  if (!vreader_table [vrdr].valid)
-    return -1;
-  return vreader_table[vrdr].slot;
+    application_notify_card_reset (vreader_slot (vrdr));
 }
 
 
@@ -298,6 +305,8 @@ static void
 do_reset (ctrl_t ctrl, int send_reset)
 {
   int vrdr = ctrl->server_local->vreader_idx;
+  int slot;
+  int err;
 
   if (!(vrdr == -1 || (vrdr >= 0 && vrdr < DIM(vreader_table))))
     BUG ();
@@ -324,13 +333,22 @@ do_reset (ctrl_t ctrl, int send_reset)
 
   /* If we want a real reset for the card, send the reset APDU and
      tell the application layer about it.  */
-  if (vrdr != -1 && send_reset && !IS_LOCKED (ctrl) )
+  slot = vreader_slot (vrdr);
+  if (slot != -1 && send_reset && !IS_LOCKED (ctrl) )
     {
-      if (apdu_reset (vreader_table[vrdr].slot))
+      application_notify_card_reset (slot);
+      switch (apdu_reset (slot))
         {
-          vreader_table[vrdr].valid = 0;
+        case 0:
+          break;
+        case SW_HOST_NO_CARD:
+        case SW_HOST_CARD_INACTIVE:
+          break;
+        default:
+         apdu_close_reader (slot);
+          vreader_table[vrdr].slot = slot = -1;
+          break;
         }
-      application_notify_card_reset (vrdr);
     }
 
   /* If we hold a lock, unlock now. */
@@ -345,7 +363,8 @@ do_reset (ctrl_t ctrl, int send_reset)
      try to update the file.  Calling update_reader_status_file is
      required to get hold of the new status of the card in the vreader
      table.  */
-  if (!pth_mutex_acquire (&status_file_update_lock, 0, NULL))
+  err = npth_mutex_lock (&status_file_update_lock);
+  if (err)
     {
       log_error ("failed to acquire status_file_update lock\n");
       ctrl->server_local->vreader_idx = -1;
@@ -353,8 +372,10 @@ do_reset (ctrl_t ctrl, int send_reset)
     }
   update_reader_status_file (0);  /* Update slot status table.  */
   update_card_removed (vrdr, 0);  /* Clear card_removed flag.  */
-  if (!pth_mutex_release (&status_file_update_lock))
-    log_error ("failed to release status_file_update lock\n");
+  err = npth_mutex_unlock (&status_file_update_lock);
+  if (err)
+    log_error ("failed to release status_file_update lock: %s\n",
+              strerror (err));
 
   /* Do this last, so that the update_card_removed above does its job.  */
   ctrl->server_local->vreader_idx = -1;
@@ -1582,18 +1603,18 @@ cmd_lock (assuan_context_t ctx, char *line)
   else
     locked_session = ctrl->server_local;
 
-#ifdef USE_GNU_PTH
+#ifdef USE_NPTH
   if (rc && has_option (line, "--wait"))
     {
       rc = 0;
-      pth_sleep (1); /* Better implement an event mechanism. However,
-                        for card operations this should be
-                        sufficient. */
+      npth_sleep (1); /* Better implement an event mechanism. However,
+                        for card operations this should be
+                        sufficient. */
       /* FIXME: Need to check that the connection is still alive.
          This can be done by issuing status messages. */
       goto retry;
     }
-#endif /*USE_GNU_PTH*/
+#endif /*USE_NPTH*/
 
   if (rc)
     log_error ("cmd_lock failed: %s\n", gpg_strerror (rc));
@@ -1696,11 +1717,7 @@ cmd_getinfo (assuan_context_t ctx, char *line)
            BUG ();
 
          vr = &vreader_table[vrdr];
-
-         if (!vr->valid)
-           BUG ();
-
-         if (vr->any && (vr->status & 1))
+         if (vr->valid && vr->any && (vr->status & 1))
            flag = 'u';
        }
       rc = assuan_send_data (ctx, &flag, 1);
@@ -1786,7 +1803,7 @@ cmd_disconnect (assuan_context_t ctx, char *line)
 
 
 static const char hlp_apdu[] =
-  "APDU [--atr] [--more] [--exlen[=N]] [hexstring]\n"
+  "APDU [--[dump-]atr] [--more] [--exlen[=N]] [hexstring]\n"
   "\n"
   "Send an APDU to the current reader.  This command bypasses the high\n"
   "level functions and sends the data directly to the card.  HEXSTRING\n"
@@ -1817,7 +1834,10 @@ cmd_apdu (assuan_context_t ctx, char *line)
   size_t exlen;
   int slot;
 
-  with_atr = has_option (line, "--atr");
+  if (has_option (line, "--dump-atr"))
+    with_atr = 2;
+  else
+    with_atr = has_option (line, "--atr");
   handle_more = has_option (line, "--more");
 
   if ((s=has_option_name (line, "--exlen")))
@@ -1852,9 +1872,32 @@ cmd_apdu (assuan_context_t ctx, char *line)
           rc = gpg_error (GPG_ERR_INV_CARD);
           goto leave;
         }
-      bin2hex (atr, atrlen, hexbuf);
+      if (with_atr == 2)
+        {
+          char *string, *p, *pend;
+
+          string = atr_dump (atr, atrlen);
+          if (string)
+            {
+              for (rc=0, p=string; !rc && (pend = strchr (p, '\n')); p = pend+1)
+                {
+                  rc = assuan_send_data (ctx, p, pend - p + 1);
+                  if (!rc)
+                    rc = assuan_send_data (ctx, NULL, 0);
+                }
+              if (!rc && *p)
+                rc = assuan_send_data (ctx, p, strlen (p));
+              es_free (string);
+              if (rc)
+                goto leave;
+            }
+        }
+      else
+        {
+          bin2hex (atr, atrlen, hexbuf);
+          send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
+        }
       xfree (atr);
-      send_status_info (ctrl, "CARD-ATR", hexbuf, strlen (hexbuf), NULL, 0);
     }
 
   apdu = hex_to_buffer (line, &apdulen);
@@ -1899,15 +1942,8 @@ cmd_killscd (assuan_context_t ctx, char *line)
   (void)line;
 
   ctrl->server_local->stopme = 1;
-#ifdef ASSUAN_FORCE_CLOSE
   assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
   return 0;
-#else
-  /* Actually returning an EOF does not anymore work with modern
-     Libassuan versions.  However we keep that non working code until
-     we make a Libassuan with the force close flag a requirement.  */
-  return gpg_error (GPG_ERR_EOF);
-#endif
 }
 
 
@@ -2248,9 +2284,9 @@ update_reader_status_file (int set_card_removed_flag)
       if (sw_apdu == SW_HOST_NO_READER)
         {
           /* Most likely the _reader_ has been unplugged.  */
+          application_notify_card_reset (vr->slot);
          apdu_close_reader (vr->slot);
           vr->slot = -1;
-         vr->valid = 0;
           status = 0;
           changed = vr->changed;
         }
@@ -2365,9 +2401,13 @@ update_reader_status_file (int set_card_removed_flag)
 void
 scd_update_reader_status_file (void)
 {
-  if (!pth_mutex_acquire (&status_file_update_lock, 1, NULL))
+  int err;
+  err = npth_mutex_lock (&status_file_update_lock);
+  if (err)
     return; /* locked - give up. */
   update_reader_status_file (1);
-  if (!pth_mutex_release (&status_file_update_lock))
-    log_error ("failed to release status_file_update lock\n");
+  err = npth_mutex_unlock (&status_file_update_lock);
+  if (err)
+    log_error ("failed to release status_file_update lock: %s\n",
+              strerror (err));
 }