Mark component descriptions for translation.
[gnupg.git] / g13 / runner.c
index 27d0370..7e9c262 100644 (file)
 #include "keyblob.h"
 #include "runner.h"
 #include "../common/exechelp.h"
-
+#include "mountinfo.h"
 
 /* The runner object.  */
 struct runner_s
 {
-  char *name;   /* The name of this runner.  */
+  char *name;              /* The name of this runner.  */
+  unsigned int identifier; /* The runner identifier.  */
 
   int spawned;  /* True if runner_spawn has been called.  */
   pth_t threadid; /* The TID of the runner thread.  */
@@ -47,12 +48,12 @@ struct runner_s
 
 
   /* We use a reference counter to know when it is safe to remove the
-     object.  Lackiong an explicit ref fucntion this counter will take
+     object.  Lacking an explicit ref function this counter will take
      only these two values:
 
      1 = Thread not running or only the thread is still running.
      2 = Thread is running and someone is holding a reference.  */
-  int refcount; 
+  int refcount;
 
   pid_t pid;  /* PID of the backend's process (the engine).  */
   int in_fd;  /* File descriptors to read from the engine.  */
@@ -81,7 +82,7 @@ writen (int fd, const void *buf, size_t nbytes)
 {
   size_t nleft = nbytes;
   int nwritten;
-  
+
   while (nleft > 0)
     {
       nwritten = pth_write (fd, buf, nleft);
@@ -95,7 +96,7 @@ writen (int fd, const void *buf, size_t nbytes)
       nleft -= nwritten;
       buf = (const char*)buf + nwritten;
     }
-    
+
   return 0;
 }
 
@@ -131,18 +132,25 @@ runner_get_threads (void)
 void
 runner_release (runner_t runner)
 {
+  gpg_error_t err;
+
   if (!runner)
     return;
 
   if (!--runner->refcount)
     return;
 
+  err = mountinfo_del_mount (NULL, NULL, runner->identifier);
+  if (err)
+    log_error ("failed to remove mount with rid %u from mtab: %s\n",
+               runner->identifier, gpg_strerror (err));
+
   es_fclose (runner->status_fp);
   if (runner->in_fd != -1)
     close (runner->in_fd);
   if (runner->out_fd != -1)
     close (runner->out_fd);
-  
+
   /* Fixme: close the process. */
 
   /* Tell the engine to release its data.  */
@@ -157,7 +165,8 @@ runner_release (runner_t runner)
           arbitrary NAME of the runner object.  However it does not
           matter because that information is only used for
           diagnostics.)  */
-      gnupg_wait_process (runner->name, runner->pid, NULL);
+      gnupg_wait_process (runner->name, runner->pid, 1, NULL);
+      gnupg_release_process (runner->pid);
     }
 
   xfree (runner->name);
@@ -168,17 +177,35 @@ runner_release (runner_t runner)
 /* Create a new runner context.  On success a new runner object is
    stored at R_RUNNER.  On failure NULL is stored at this address and
    an error code returned.  */
-gpg_error_t 
+gpg_error_t
 runner_new (runner_t *r_runner, const char *name)
 {
-  runner_t runner;
+  static unsigned int namecounter; /* Global name counter.  */
+  char *namebuffer;
+  runner_t runner, r;
 
   *r_runner = NULL;
 
   runner = xtrycalloc (1, sizeof *runner);
   if (!runner)
     return gpg_error_from_syserror ();
-  runner->name = xtrystrdup (name? name: "[unknown]");
+
+  /* Bump up the namecounter.  In case we ever had an overflow we
+     check that this number is currently not in use.  The algorithm is
+     a bit lame but should be sufficient because such an wrap is not
+     very likely: Assuming that we do a mount 10 times a second, then
+     we would overwrap on a 32 bit system after 13 years.  */
+  do
+    {
+      namecounter++;
+      for (r = running_threads; r; r = r->next_running)
+        if (r->identifier == namecounter)
+          break;
+    }
+  while (r);
+
+  runner->identifier = namecounter;
+  runner->name = namebuffer = xtryasprintf ("%s-%d", name, namecounter);
   if (!runner->name)
     {
       xfree (runner);
@@ -188,14 +215,38 @@ runner_new (runner_t *r_runner, const char *name)
   runner->pid = (pid_t)(-1);
   runner->in_fd = -1;
   runner->out_fd = -1;
-  
 
   *r_runner = runner;
   return 0;
 }
 
 
-/* A runner usually maintaines two file descriptors to control the
+/* Return the identifier of RUNNER.  */
+unsigned int
+runner_get_rid (runner_t runner)
+{
+  return runner->identifier;
+}
+
+
+/* Find a runner by its rid.  Returns the runner object.  The caller
+   must release the runner object.  */
+runner_t
+runner_find_by_rid (unsigned int rid)
+{
+  runner_t r;
+
+  for (r = running_threads; r; r = r->next_running)
+    if (r->identifier == rid)
+      {
+        r->refcount++;
+        return r;
+      }
+  return NULL;
+}
+
+
+/* A runner usually maintains two file descriptors to control the
    backend engine.  This function is used to set these file
    descriptors.  The function takes ownership of these file
    descriptors.  IN_FD will be used to read from engine and OUT_FD to
@@ -231,8 +282,8 @@ runner_set_pid (runner_t runner, pid_t pid)
    and its private HANDLER_DATA with RUNNER.  */
 void
 runner_set_handler (runner_t runner,
-                    engine_handler_fnc_t handler, 
-                    engine_handler_cleanup_fnc_t handler_cleanup, 
+                    engine_handler_fnc_t handler,
+                    engine_handler_cleanup_fnc_t handler_cleanup,
                     void *handler_data)
 {
   if (check_already_spawned (runner, "runner_set_handler"))
@@ -274,14 +325,14 @@ runner_thread (void *arg)
             {
               buffer[pos - (c == '\n')] = 0;
               if (opt.verbose)
-                log_info ("%s%s: %s\n", 
+                log_info ("%s%s: %s\n",
                           runner->name, cont_line? "(cont)":"", buffer);
               /* We handle only complete lines and ignore any stuff we
                  possibly had to truncate.  That is - at least for the
                  encfs engine - not an issue because our changes to
                  the tool make sure that only relatively short prompt
                  lines are of interest.  */
-              if (!cont_line && runner->handler) 
+              if (!cont_line && runner->handler)
                 err = runner->handler (runner->handler_data,
                                        runner, buffer);
               pos = 0;
@@ -298,7 +349,7 @@ runner_thread (void *arg)
           if (opt.verbose)
             log_info ("%s%s: %s\n",
                       runner->name, cont_line? "(cont)":"", buffer);
-          if (!cont_line && !err && runner->handler) 
+          if (!cont_line && !err && runner->handler)
             err = runner->handler (runner->handler_data,
                                           runner, buffer);
         }
@@ -320,7 +371,8 @@ runner_thread (void *arg)
       int exitcode;
 
       log_debug ("runner thread waiting ...\n");
-      err = gnupg_wait_process (runner->name, runner->pid, &exitcode);
+      err = gnupg_wait_process (runner->name, runner->pid, 1, &exitcode);
+      gnupg_release_process (runner->pid);
       runner->pid = (pid_t)(-1);
       if (err)
         log_error ("running `%s' failed (exitcode=%d): %s\n",
@@ -332,7 +384,7 @@ runner_thread (void *arg)
   log_debug ("runner thread releasing runner ...\n");
   {
     runner_t r, rprev;
-    
+
     for (r = running_threads, rprev = NULL; r; rprev = r, r = r->next_running)
       if (r == runner)
         {
@@ -346,7 +398,7 @@ runner_thread (void *arg)
   }
   runner_release (runner);
   log_debug ("runner thread runner released\n");
-  
+
   return NULL;
 }
 
@@ -358,7 +410,7 @@ runner_spawn (runner_t runner)
   gpg_error_t err;
   pth_attr_t tattr;
   pth_t tid;
-  
+
   if (check_already_spawned (runner, "runner_spawn"))
     return gpg_error (GPG_ERR_BUG);
 
@@ -369,7 +421,7 @@ runner_spawn (runner_t runner)
   if (runner->in_fd != -1)
     {
       estream_t fp;
-      
+
       fp = es_fdopen (runner->in_fd, "r");
       if (!fp)
         {
@@ -382,10 +434,10 @@ runner_spawn (runner_t runner)
     }
 
   tattr = pth_attr_new ();
-  pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
-  pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
+  pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
+  pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 128*1024);
   pth_attr_set (tattr, PTH_ATTR_NAME, runner->name);
-  
+
   tid = pth_spawn (tattr, runner_thread, runner);
   if (!tid)
     {
@@ -431,7 +483,7 @@ runner_cancel_all (void)
 {
   runner_t r;
 
-  do 
+  do
     {
       for (r = running_threads; r; r = r->next_running)
         if (r->spawned && !r->canceled)
@@ -447,7 +499,7 @@ runner_cancel_all (void)
 /* Send a line of data down to the engine.  This line may not contain
    a binary Nul or a LF character.  This function is used by the
    engine's handler.  */
-gpg_error_t 
+gpg_error_t
 runner_send_line (runner_t runner, const void *data, size_t datalen)
 {
   gpg_error_t err = 0;
@@ -481,6 +533,6 @@ runner_send_line (runner_t runner, const void *data, size_t datalen)
   if (!err)
     if (writen (runner->out_fd, "\n", 1))
       err = gpg_error_from_syserror ();
-  
+
   return err;
 }