diff --git a/common/ChangeLog b/common/ChangeLog index 5bb986f30..dde8987d1 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,15 @@ +2008-06-18 Marcus Brinkmann + + * sysutils.h (translate_table_init, translate_table_lookup): New + prototypes. + * sysutils.c: Include . + (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 * homedir.c (w32_commondir): New. diff --git a/common/iobuf.c b/common/iobuf.c index ae35d301e..3cac9e072 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -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; } diff --git a/common/sysutils.c b/common/sysutils.c index 5e550b43a..3b6d82c0a 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -50,6 +50,7 @@ # include #endif #include +#include #include "util.h" #include "i18n.h" @@ -278,6 +279,116 @@ gnupg_sleep (unsigned int seconds) } + +/* 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; +} + + /* 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 } diff --git a/common/sysutils.h b/common/sysutils.h index de1e3bb1e..9e0a323dd 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -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);