gpgconf: Fix for --homedir.
[gnupg.git] / scd / command.c
index 72ff132..9d978ab 100644 (file)
@@ -129,10 +129,6 @@ struct server_local_s
      continue operation. */
   int card_removed;
 
-  /* Flag indicating that the application context needs to be released
-     at the next opportunity.  */
-  int app_ctx_marked_for_release;
-
   /* A disconnect command has been sent.  */
   int disconnect_allowed;
 
@@ -209,14 +205,31 @@ update_card_removed (int vrdr, int value)
     return;
 
   for (sl=session_list; sl; sl = sl->next_session)
-    if (sl->ctrl_backlink
-        && sl->ctrl_backlink->server_local->vreader_idx == vrdr)
-      {
-        sl->card_removed = value;
-      }
+    {
+      ctrl_t ctrl = sl->ctrl_backlink;
+
+      if (ctrl && ctrl->server_local->vreader_idx == vrdr)
+        {
+          sl->card_removed = value;
+          if (value)
+            {
+              struct app_ctx_s *app = ctrl->app_ctx;
+              ctrl->app_ctx = NULL;
+              release_application (app);
+            }
+        }
+    }
+
   /* Let the card application layer know about the removal.  */
   if (value)
-    application_notify_card_reset (vreader_slot (vrdr));
+    {
+      int slot = vreader_slot (vrdr);
+
+      log_debug ("Removal of a card: %d\n", vrdr);
+      apdu_close_reader (slot);
+      application_notify_card_reset (slot);
+      vreader_table[vrdr].slot = -1;
+    }
 }
 
 
@@ -261,27 +274,36 @@ do_reset (ctrl_t ctrl, int send_reset)
   int vrdr = ctrl->server_local->vreader_idx;
   int slot;
   int err;
+  struct app_ctx_s *app = ctrl->app_ctx;
 
   if (!(vrdr == -1 || (vrdr >= 0 && vrdr < DIM(vreader_table))))
     BUG ();
 
-  /* If there is an active application, release it.  Tell all other
-     sessions using the same application to release the
-     application.  */
-  if (ctrl->app_ctx)
+  /* If there is an active application, release it. */
+  if (app)
     {
-      release_application (ctrl->app_ctx);
       ctrl->app_ctx = NULL;
-      if (send_reset)
+      release_application (app);
+    }
+
+  /* Release the same application which is used by other sessions.  */
+  if (send_reset)
+    {
+      struct server_local_s *sl;
+
+      for (sl=session_list; sl; sl = sl->next_session)
         {
-          struct server_local_s *sl;
+          ctrl_t c = sl->ctrl_backlink;
 
-          for (sl=session_list; sl; sl = sl->next_session)
-            if (sl->ctrl_backlink
-                && sl->ctrl_backlink->server_local->vreader_idx == vrdr)
-              {
-                sl->app_ctx_marked_for_release = 1;
-              }
+          if (c && c != ctrl && c->server_local->vreader_idx == vrdr)
+            {
+              struct app_ctx_s *app0 = c->app_ctx;
+              if (app0)
+                {
+                  c->app_ctx = NULL;
+                  release_application (app0);
+                }
+            }
         }
     }
 
@@ -299,8 +321,8 @@ do_reset (ctrl_t ctrl, int send_reset)
         case SW_HOST_CARD_INACTIVE:
           break;
         default:
-         apdu_close_reader (slot);
-          vreader_table[vrdr].slot = slot = -1;
+          apdu_close_reader (slot);
+          vreader_table[vrdr].slot = -1;
           break;
         }
     }
@@ -426,16 +448,6 @@ open_card (ctrl_t ctrl, const char *apptype)
   if ( IS_LOCKED (ctrl) )
     return gpg_error (GPG_ERR_LOCKED);
 
-  /* If the application has been marked for release do it now.  We
-     can't do it immediately in do_reset because the application may
-     still be in use.  */
-  if (ctrl->server_local->app_ctx_marked_for_release)
-    {
-      ctrl->server_local->app_ctx_marked_for_release = 0;
-      release_application (ctrl->app_ctx);
-      ctrl->app_ctx = NULL;
-    }
-
   /* If we are already initialized for one specific application we
      need to check that the client didn't requested a specific
      application different from the one in use before we continue. */
@@ -490,7 +502,7 @@ static const char hlp_serialno[] =
   "error is returned if the application is not supported or available.\n"
   "The default is to auto-select the application using a hardwired\n"
   "preference system.  Note, that a future extension to this function\n"
-  "may allow to specify a list and order of applications to try.\n"
+  "may enable specifying a list and order of applications to try.\n"
   "\n"
   "This function is special in that it can be used to reset the card.\n"
   "Most other functions will return an error when a card change has\n"
@@ -1742,13 +1754,14 @@ static gpg_error_t
 cmd_restart (assuan_context_t ctx, char *line)
 {
   ctrl_t ctrl = assuan_get_pointer (ctx);
+  struct app_ctx_s *app = ctrl->app_ctx;
 
   (void)line;
 
-  if (ctrl->app_ctx)
+  if (app)
     {
-      release_application (ctrl->app_ctx);
       ctrl->app_ctx = NULL;
+      release_application (app);
     }
   if (locked_session && ctrl->server_local == locked_session)
     {
@@ -2029,14 +2042,10 @@ scd_command_handler (ctrl_t ctrl, int fd)
   session_list = ctrl->server_local;
   ctrl->server_local->ctrl_backlink = ctrl;
   ctrl->server_local->assuan_ctx = ctx;
-  ctrl->server_local->vreader_idx = -1;
 
   /* We open the reader right at startup so that the ticker is able to
      update the status file. */
-  if (ctrl->server_local->vreader_idx == -1)
-    {
-      ctrl->server_local->vreader_idx = get_current_reader ();
-    }
+  ctrl->server_local->vreader_idx = get_current_reader ();
 
   /* Command processing loop. */
   for (;;)
@@ -2254,9 +2263,7 @@ 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;
+          apdu_close_reader (vr->slot);
           status = 0;
           changed = vr->changed;
         }
@@ -2281,7 +2288,7 @@ update_reader_status_file (int set_card_removed_flag)
             depends on how client sessions will associate the reader
             status with their session.  */
           snprintf (templ, sizeof templ, "reader_%d.status", vr->slot);
-          fname = make_filename (opt.homedir, templ, NULL );
+          fname = make_filename (gnupg_homedir (), templ, NULL );
           fp = fopen (fname, "w");
           if (fp)
             {
@@ -2300,7 +2307,7 @@ update_reader_status_file (int set_card_removed_flag)
             char *homestr, *envstr;
             gpg_error_t err;
 
-            homestr = make_filename (opt.homedir, NULL);
+            homestr = make_filename (gnupg_homedir (), NULL);
             if (gpgrt_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
               log_error ("out of core while building environment\n");
             else
@@ -2323,7 +2330,7 @@ update_reader_status_file (int set_card_removed_flag)
                            (status & 2)? "PRESENT": "NOCARD");
                 args[8] = NULL;
 
-                fname = make_filename (opt.homedir, "scd-event", NULL);
+                fname = make_filename (gnupg_homedir (), "scd-event", NULL);
                 err = gnupg_spawn_process_detached (fname, args, envs);
                 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
                   log_error ("failed to run event handler '%s': %s\n",