diff options
Diffstat (limited to 'common/sysutils.c')
-rw-r--r-- | common/sysutils.c | 182 |
1 files changed, 175 insertions, 7 deletions
diff --git a/common/sysutils.c b/common/sysutils.c index 90627b7c8..6c7d616b9 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -559,17 +559,15 @@ translate_sys2libc_fd (gnupg_fd_t fd, int for_write) } /* This is the same as translate_sys2libc_fd but takes an integer - which is assumed to be such an system handle. On WindowsCE the - passed FD is a rendezvous ID and the function finishes the pipe - creation. */ + which is assumed to be such an system handle. */ int translate_sys2libc_fd_int (int fd, int for_write) { #ifdef HAVE_W32_SYSTEM if (fd <= 2) - return fd; /* Do not do this for error, stdin, stdout, stderr. */ + return fd; /* Do not do this for stdin, stdout, and stderr. */ - return translate_sys2libc_fd ((void*)fd, for_write); + return translate_sys2libc_fd ((void*)(intptr_t)fd, for_write); #else (void)for_write; return fd; @@ -577,6 +575,70 @@ translate_sys2libc_fd_int (int fd, int for_write) } +/* + * Parse the string representation of a file reference (file handle on + * Windows or file descriptor on POSIX) in FDSTR. The string + * representation may be either of folllowing: + + * (1) 0, 1, or 2 which means stdin, stdout, and stderr, respectively. + * (2) Integer representation (by %d of printf). + * (3) Hex representation which starts as "0x". + * + * Then, fill R_SYSHD, according to the value of a file reference. + * + */ +gpg_error_t +gnupg_parse_fdstr (const char *fdstr, es_syshd_t *r_syshd) +{ + int fd = -1; +#ifdef HAVE_W32_SYSTEM + gnupg_fd_t hd; + char *endptr; + int base; + + if (!strcmp (fdstr, "0")) + fd = 0; + else if (!strcmp (fdstr, "1")) + fd = 1; + else if (!strcmp (fdstr, "2")) + fd = 2; + + if (fd >= 0) + { + r_syshd->type = ES_SYSHD_FD; + r_syshd->u.fd = fd; + return 0; + } + + if (!strncmp (fdstr, "0x", 2)) + { + base = 16; + fdstr += 2; + } + else + base = 10; + + gpg_err_set_errno (0); +#ifdef _WIN64 + hd = (gnupg_fd_t)strtoll (fdstr, &endptr, base); +#else + hd = (gnupg_fd_t)strtol (fdstr, &endptr, base); +#endif + if (errno != 0 || endptr == fdstr || *endptr != '\0') + return gpg_error (GPG_ERR_INV_ARG); + + r_syshd->type = ES_SYSHD_HANDLE; + r_syshd->u.handle = hd; + return 0; +#else + fd = atoi (fdstr); + r_syshd->type = ES_SYSHD_FD; + r_syshd->u.fd = fd; + return 0; +#endif +} + + /* Check whether FNAME has the form "-&nnnn", where N is a non-zero * number. Returns this number or -1 if it is not the case. If the * caller wants to use the file descriptor for writing FOR_WRITE shall @@ -594,13 +656,74 @@ check_special_filename (const char *fname, int for_write, int notranslate) for (i=0; digitp (fname+i); i++ ) ; if (!fname[i]) - return notranslate? atoi (fname) - /**/ : translate_sys2libc_fd_int (atoi (fname), for_write); + { + if (notranslate) + return atoi (fname); + else + { + es_syshd_t syshd; + + if (gnupg_parse_fdstr (fname, &syshd)) + return -1; + +#ifdef HAVE_W32_SYSTEM + if (syshd.type == ES_SYSHD_FD) + return syshd.u.fd; + else + return translate_sys2libc_fd ((gnupg_fd_t)syshd.u.handle, for_write); +#else + (void)for_write; + return syshd.u.fd; +#endif + } + } } return -1; } +/* Check whether FNAME has the form "-&nnnn", where N is a number + * representing a file. Returns GNUPG_INVALID_FD if it is not the + * case. Returns a file descriptor on POSIX, a system handle on + * Windows. */ +gnupg_fd_t +gnupg_check_special_filename (const char *fname) +{ + if (allow_special_filenames + && fname && *fname == '-' && fname[1] == '&') + { + int i; + + fname += 2; + for (i=0; digitp (fname+i); i++ ) + ; + if (!fname[i]) + { + es_syshd_t syshd; + + if (gnupg_parse_fdstr (fname, &syshd)) + return GNUPG_INVALID_FD; + +#ifdef HAVE_W32_SYSTEM + if (syshd.type == ES_SYSHD_FD) + { + if (syshd.u.fd == 0) + return GetStdHandle (STD_INPUT_HANDLE); + else if (syshd.u.fd == 1) + return GetStdHandle (STD_OUTPUT_HANDLE); + else if (syshd.u.fd == 2) + return GetStdHandle (STD_ERROR_HANDLE); + } + else + return syshd.u.handle; +#else + return syshd.u.fd; +#endif + } + } + return GNUPG_INVALID_FD; +} + /* Replacement for tmpfile(). This is required because the tmpfile function of Windows' runtime library is broken, insecure, ignores TMPDIR and so on. In addition we create a file with an inheritable @@ -1158,6 +1281,19 @@ gnupg_setenv (const char *name, const char *value, int overwrite) return setenv (name, value, overwrite); #else /*!HAVE_SETENV*/ if (! getenv (name) || overwrite) +#if defined(HAVE_W32_SYSTEM) && defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) + { + int e = _putenv_s (name, value); + + if (e) + { + gpg_err_set_errno (e); + return -1; + } + else + return 0; + } +#else { char *buf; @@ -1175,6 +1311,7 @@ gnupg_setenv (const char *name, const char *value, int overwrite) # endif return putenv (buf); } +#endif /*!HAVE_W32_SYSTEM*/ return 0; #endif /*!HAVE_SETENV*/ } @@ -1199,6 +1336,18 @@ gnupg_unsetenv (const char *name) #ifdef HAVE_UNSETENV return unsetenv (name); +#elif defined(HAVE_W32_SYSTEM) && defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) + { + int e = _putenv_s (name, ""); + + if (e) + { + gpg_err_set_errno (e); + return -1; + } + else + return 0; + } #else /*!HAVE_UNSETENV*/ { char *buf; @@ -1829,3 +1978,22 @@ gnupg_fd_valid (int fd) close (d); return 1; } + + +/* Open a stream from FD (a file descriptor on POSIX, a system + handle on Windows), non-closed. */ +estream_t +open_stream_nc (gnupg_fd_t fd, const char *mode) +{ + es_syshd_t syshd; + +#ifdef HAVE_W32_SYSTEM + syshd.type = ES_SYSHD_HANDLE; + syshd.u.handle = fd; +#else + syshd.type = ES_SYSHD_FD; + syshd.u.fd = fd; +#endif + + return es_sysopen_nc (&syshd, mode); +} |