2008-06-18 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Wed, 18 Jun 2008 14:46:05 +0000 (14:46 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Wed, 18 Jun 2008 14:46:05 +0000 (14:46 +0000)
* sysutils.h (translate_table_init, translate_table_lookup): New
prototypes.
* sysutils.c: Include <ctype.h>.
(FD_TRANSLATE_MAX): New macro.
(fd_translate, fd_translate_len): New static variables.
(translate_table_init, translate_table_lookup): New functions.
(translate_sys2libc_fd_int): Translate file descriptor.
* iobuf.c (check_special_filename): Translate handle values from
special filenames.

common/ChangeLog
common/iobuf.c
common/sysutils.c
common/sysutils.h

index 5bb986f..dde8987 100644 (file)
@@ -1,3 +1,15 @@
+2008-06-18  Marcus Brinkmann  <marcus@g10code.de>
+
+       * sysutils.h (translate_table_init, translate_table_lookup): New
+       prototypes.
+       * sysutils.c: Include <ctype.h>.
+       (FD_TRANSLATE_MAX): New macro.
+       (fd_translate, fd_translate_len): New static variables.
+       (translate_table_init, translate_table_lookup): New functions.
+       (translate_sys2libc_fd_int): Translate file descriptor.
+       * iobuf.c (check_special_filename): Translate handle values from
+       special filenames.
+
 2008-06-16  Werner Koch  <wk@g10code.com>
 
        * homedir.c (w32_commondir): New.
index ae35d30..3cac9e0 100644 (file)
@@ -1177,7 +1177,7 @@ check_special_filename (const char *fname)
       for (i = 0; digitp (fname+i); i++)
        ;
       if (!fname[i])
-       return atoi (fname);
+       return translate_table_lookup (atoi (fname));
     }
   return -1;
 }
index 5e550b4..3b6d82c 100644 (file)
@@ -50,6 +50,7 @@
 # include <pth.h>
 #endif
 #include <fcntl.h>
+#include <ctype.h>
 
 #include "util.h"
 #include "i18n.h"
@@ -278,6 +279,116 @@ gnupg_sleep (unsigned int seconds)
 }
 
 
+\f
+/* Handle translation.  On W32, we provide handle values on the
+   command line directly and using special file names such as
+   "-&HANDLE".  However, in GPGME we can not directly inherit the
+   handles as this may interfere with other components in a
+   multithreaded application.  Thus, we inject the handles after
+   creating the GPG process.  The problem is that the handle numbers
+   change at injection, but it is too late to change the command line.
+   Hence this hack, which allows us to translate the handle values
+   in the command line to their new values after injection.
+
+   Handles that must be translated are those occuring in special file
+   names (see iobuf.c::check_special_filename) as well as those given
+   directly to options (see translate_sys2libc_fd_int).  */
+
+/* For W32, we may have to translate handle values given on the
+   command line.  */
+#define FD_TRANSLATE_MAX 8
+static struct
+{
+  int from;
+  int to;
+} fd_translate[8];
+
+/* Number of entries used in fd_translate.  */
+static int fd_translate_len;
+
+
+/* Initialize the fd translation table.  This reads one line from
+   stdin which is expected to be in the format "FROM TO [...]" where
+   each "FROM TO" pair are two handle numbers.  Handle number FROM on
+   the command line is translated to handle number TO.  */
+void
+translate_table_init (void)
+{
+#define TRANS_MAX 100
+  char line[TRANS_MAX + 1];
+  char *linep;
+  int idx;
+  int res;
+  int newl = 0;
+
+  /* We always read one line from stdin.  */
+  for (idx = 0; idx < TRANS_MAX; idx++)
+    {
+      res = read (0, &line[idx], 1);
+      if (res != 1)
+       break;
+      if (line[idx] == '\n')
+       {
+         newl = 1;
+         break;
+       }
+    }
+  if (!newl)
+    {
+      char buf[1];
+      do
+       res = read (0, buf, 1);
+      while (res == 1 && *buf != '\n');
+    }
+
+  line[idx] = '\0';
+  linep = line;
+
+  /* Now start to read mapping pairs.  */
+  for (idx = 0; idx < FD_TRANSLATE_MAX; idx++)
+    {
+      unsigned long from;
+      unsigned long to;
+      char *tail;
+
+      while (isspace (*linep))
+       linep++;
+      if (*linep == '\0')
+       break;
+      from = strtoul (linep, &tail, 0);
+      if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
+       break;
+      linep = tail;
+
+      while (isspace (*linep))
+       linep++;
+      if (*linep == '\0')
+       break;
+      to = strtoul (linep, &tail, 0);
+      if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
+       break;
+      linep = tail;
+
+      fd_translate[idx].from = from;
+      fd_translate[idx].to = to;
+      fd_translate_len++;
+    }
+}
+
+
+/* Translate a handle number.  */
+int
+translate_table_lookup (int fd)
+{
+  int idx;
+
+  for (idx = 0; idx < fd_translate_len; idx++)
+    if (fd_translate[idx].from == fd)
+      return fd_translate[idx].to;
+  return fd;
+}
+
+\f
 /* This function is a NOP for POSIX systems but required under Windows
    as the file handles as returned by OS calls (like CreateFile) are
    different from the libc file descriptors (like open). This function
@@ -303,6 +414,7 @@ translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
 #endif
 }
 
+
 /* This is the same as translate_sys2libc_fd but takes an integer
    which is assumed to be such an system handle.  */
 int
@@ -312,8 +424,14 @@ translate_sys2libc_fd_int (int fd, int for_write)
   if (fd <= 2)
     return fd; /* Do not do this for error, stdin, stdout, stderr. */
 
+  /* Note: If this function is ever used in a different context than
+     option parsing in the main function, a variant that does not do
+     translation probable needs to be used.  */
+  fd = translate_table_lookup (fd);
+
   return translate_sys2libc_fd ((void*)fd, for_write);
 #else
+  fd = translate_table_lookup (fd);
   return fd;
 #endif
 }
index de1e3bb..9e0a323 100644 (file)
@@ -43,6 +43,16 @@ int  enable_core_dumps (void);
 const unsigned char *get_session_marker (size_t *rlen);
 /*int check_permissions (const char *path,int extension,int checkonly);*/
 void gnupg_sleep (unsigned int seconds);
+
+/* Initialize the fd translation table.  This reads one line from
+   stdin which is expected to be in the format "FROM TO [...]" where
+   each "FROM TO" pair are two handle numbers.  Handle number FROM on
+   the command line is translated to handle number TO.  */
+void translate_table_init (void);
+
+/* Translate a handle number.  */
+int translate_table_lookup (int fd);
+
 int translate_sys2libc_fd (gnupg_fd_t fd, int for_write);
 int translate_sys2libc_fd_int (int fd, int for_write);
 FILE *gnupg_tmpfile (void);