+2009-06-12 Werner Koch <wk@g10code.com>
+
+ * gpgme-w32spawn.c (translate_get_from_file): Parse optional spawn
+ flags. Add new arg R_FLAGS. Fix segv on file w/o LF.
+ (translate_handles): Add new arg R_FLAGS. Avoid possible segv.
+ (main): Pass flags for my_spawn.
+ (my_spawn): Add arg FLAGS and implement AllowSetForegroundWindow.
+
+ * priv-io.h (IOSPAWN_FLAG_ALLOW_SET_FG): New.
+ * w32-io.c (_gpgme_io_spawn): Add arg FLAGS and implement it.
+ * w32-glib-io.c (_gpgme_io_spawn): Ditto.
+ * w32-qt-io.cpp (_gpgme_io_spawn): Ditto.
+ * posix-io.c (_gpgme_io_spawn): Add dummy arg FLAGS.
+ * engine-gpg.c (start): Call spawn with new flag.
+
+ * w32-util.c (_gpgme_allow_set_foregound_window): Rename to
+ _gpgme_allow_set_foreground_window. Change all callers.
+ * posix-util.c (_gpgme_allow_set_foreground_window): Ditto.
+
+2009-06-10 Werner Koch <wk@g10code.com>
+
+ * w32-util.c (_gpgme_allow_set_foregound_window): Add trace support.
+
2009-06-09 Werner Koch <wk@g10code.com>
* engine-gpg.c (gpg_io_event): Test for cmd.fd.
cfd[0].fd = rp[1];
- status = _gpgme_io_spawn (pgmname, argv, cfd, NULL);
+ status = _gpgme_io_spawn (pgmname, argv, 0, cfd, NULL);
if (status < 0)
{
_gpgme_io_close (rp[0]);
if (llass->opt.gpg_agent && !strcmp (keyword, "PINENTRY_LAUNCHED"))
{
- _gpgme_allow_set_foregound_window ((pid_t)strtoul (args, NULL, 10));
+ _gpgme_allow_set_foreground_window ((pid_t)strtoul (args, NULL, 10));
}
if (llass->user.inq_cb)
fd_list[n].dup_to = -1;
status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name :
- _gpgme_get_gpg_path (), gpg->argv, fd_list, &pid);
+ _gpgme_get_gpg_path (), gpg->argv,
+ IOSPAWN_FLAG_ALLOW_SET_FG,
+ fd_list, &pid);
saved_errno = errno;
free (fd_list);
}
}
- _gpgme_allow_set_foregound_window (pid);
-
gpg_io_event (gpg, GPGME_EVENT_START, NULL);
/* fixme: check what data we can release here */
cfd[0].fd = rp[1];
- status = _gpgme_io_spawn (gpgconf->file_name, argv, cfd, NULL);
+ status = _gpgme_io_spawn (gpgconf->file_name, argv, 0, cfd, NULL);
if (status < 0)
{
_gpgme_io_close (rp[0]);
cfd[0].fd = rp[0];
- status = _gpgme_io_spawn (gpgconf->file_name, argv, cfd, NULL);
+ status = _gpgme_io_spawn (gpgconf->file_name, argv, 0, cfd, NULL);
if (status < 0)
{
_gpgme_io_close (rp[0]);
{
if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
{
- _gpgme_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
+ _gpgme_allow_set_foreground_window ((pid_t)strtoul (line+17, NULL, 10));
}
return 0;
#include <process.h>
#include <windows.h>
+/* Flag values as used by gpgme. */
+#define IOSPAWN_FLAG_ALLOW_SET_FG 1
+
+
+/* Name of this program. */
+#define PGM "gpgme-w32spawn"
+
\f
struct spawn_fd_item_s
int
-my_spawn (char **argv, struct spawn_fd_item_s *fd_list)
+my_spawn (char **argv, struct spawn_fd_item_s *fd_list, unsigned int flags)
{
SECURITY_ATTRIBUTES sec_attr;
PROCESS_INFORMATION pi =
i = 0;
while (argv[i])
{
- fprintf (stderr, "argv[%2i] = %s\n", i, argv[i]);
+ fprintf (stderr, PGM": argv[%2i] = %s\n", i, argv[i]);
i++;
}
si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
- fprintf (stderr, "spawning: %s\n", arg_string);
+ fprintf (stderr, PGM": spawning: %s\n", arg_string);
for (i = 0; fd_list[i].handle != -1; i++)
{
{
si.hStdInput = (HANDLE) fd_list[i].peer_name;
duped_stdin = 1;
- fprintf (stderr, "dup 0x%x to stdin\n", fd_list[i].peer_name);
+ fprintf (stderr, PGM": dup 0x%x to stdin\n", fd_list[i].peer_name);
}
else if (fd_list[i].dup_to == 1)
{
si.hStdOutput = (HANDLE) fd_list[i].peer_name;
duped_stdout = 1;
- fprintf (stderr, "dup 0x%x to stdout\n", fd_list[i].peer_name);
+ fprintf (stderr, PGM": dup 0x%x to stdout\n", fd_list[i].peer_name);
}
else if (fd_list[i].dup_to == 2)
{
si.hStdError = (HANDLE) fd_list[i].peer_name;
duped_stderr = 1;
- fprintf (stderr, "dup 0x%x to stderr\n", fd_list[i].peer_name);
+ fprintf (stderr, PGM":dup 0x%x to stderr\n", fd_list[i].peer_name);
}
}
for (i = 0; fd_list[i].handle != -1; i++)
CloseHandle ((HANDLE) fd_list[i].handle);
+
+ if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
+ {
+ static int initialized;
+ static BOOL (WINAPI * func)(DWORD);
+ void *handle;
+
+ if (!initialized)
+ {
+ /* Available since W2000; thus we dynload it. */
+ initialized = 1;
+ handle = LoadLibrary ("user32.dll");
+ if (handle)
+ {
+ func = GetProcAddress (handle, "AllowSetForegroundWindow");
+ if (!func)
+ FreeLibrary (handle);
+ }
+ }
+
+ if (func)
+ {
+ int rc = func (pi.dwProcessId);
+ fprintf (stderr, PGM": AllowSetForegroundWindow(%d): rc=%d\n",
+ (int)pi.dwProcessId, rc);
+ }
+ }
ResumeThread (pi.hThread);
CloseHandle (pi.hThread);
int
translate_get_from_file (const char *trans_file,
- struct spawn_fd_item_s *fd_list)
+ struct spawn_fd_item_s *fd_list,
+ unsigned int *r_flags)
{
/* Hold roughly MAX_TRANS triplets of 64 bit numbers in hex
notation: "0xFEDCBA9876543210". 10*19*4 - 1 = 759. This plans
ahead for a time when a HANDLE is 64 bit. */
-#define BUFFER_MAX 800
+#define BUFFER_MAX 810
char line[BUFFER_MAX + 1];
char *linep;
int res;
int fd;
+ *r_flags = 0;
+
fd = open (trans_file, O_RDONLY);
if (fd < 0)
return -1;
line[BUFFER_MAX] = '\0';
linep = strchr (line, '\n');
- if (linep > line && linep[-1] == '\r')
- linep--;
- *linep = '\0';
-
+ if (linep)
+ {
+ if (linep > line && linep[-1] == '\r')
+ linep--;
+ *linep = '\0';
+ }
linep = line;
/* Now start to read mapping pairs. */
linep++;
if (*linep == '\0')
break;
+ if (!idx && *linep == '~')
+ {
+ /* Spawn flags have been passed. */
+ linep++;
+ *r_flags = strtoul (linep, &tail, 0);
+ if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
+ break;
+ linep = tail;
+
+ while (isspace (*((unsigned char *)linep)))
+ linep++;
+ if (*linep == '\0')
+ break;
+ }
+
from = strtoul (linep, &tail, 0);
if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
break;
FD_LIST (which must be MAX_TRANS+1 large). */
char **
translate_handles (const char *trans_file, const char * const *argv,
- struct spawn_fd_item_s *fd_list)
+ struct spawn_fd_item_s *fd_list, unsigned int *r_flags)
{
int res;
int idx;
+ int n_args;
char **args;
- res = translate_get_from_file (trans_file, fd_list);
+ res = translate_get_from_file (trans_file, fd_list, r_flags);
if (res < 0)
return NULL;
return NULL;
}
args[idx] = NULL;
+ n_args = idx;
for (idx = 0; fd_list[idx].handle != -1; idx++)
{
if (aidx == 0)
continue;
+ if (aidx >= n_args)
+ {
+ fprintf (stderr, PGM": translation file does not match args\n");
+ return NULL;
+ }
+
args[aidx] = malloc (sizeof (buf));
/* We currently disable translation for stdin/stdout/stderr. We
assume that the spawned program handles 0/1/2 specially
int rc = 0;
char **argv_spawn;
struct spawn_fd_item_s fd_list[MAX_TRANS + 1];
+ unsigned int flags;
if (argc < 3)
{
goto leave;
}
- argv_spawn = translate_handles (argv[1], &argv[2], fd_list);
+ argv_spawn = translate_handles (argv[1], &argv[2], fd_list, &flags);
if (!argv_spawn)
{
rc = 2;
/* Using execv does not replace the existing program image, but
spawns a new one and daemonizes it, confusing the command line
interpreter. So we have to use spawnv. */
- rc = my_spawn (argv_spawn, fd_list);
+ rc = my_spawn (argv_spawn, fd_list, flags);
if (rc < 0)
{
- fprintf (stderr, "gpgwrap: executing `%s' failed: %s\n",
+ fprintf (stderr, PGM": executing `%s' failed: %s\n",
argv[0], strerror (errno));
rc = 2;
goto leave;
leave:
if (rc)
- fprintf (stderr, "gpg-w32spawn: internal error\n");
+ fprintf (stderr, PGM": internal error\n");
/* Always try to delete the temporary file. */
if (argc >= 2)
{
if (DeleteFile (argv[1]) == 0)
- fprintf (stderr, "Failed to delete %s: ec=%ld\n",
+ fprintf (stderr, PGM": failed to delete %s: ec=%ld\n",
argv[1], GetLastError ());
}
return rc;
/* Returns 0 on success, -1 on error. */
int
-_gpgme_io_spawn (const char *path, char *const argv[],
+_gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
struct spawn_fd_item_s *fd_list, pid_t *r_pid)
{
pid_t pid;
int i;
int status;
int signo;
+
+ (void)flags;
+
TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path,
"path=%s", path);
i = 0;
}
void
-_gpgme_allow_set_foregound_window (pid_t pid)
+_gpgme_allow_set_foreground_window (pid_t pid)
{
(void)pid;
/* Not needed. */
void *value);
int _gpgme_io_set_nonblocking (int fd);
+/* A flag to tell the spawn function to allow the child process to set
+ the foreground window. */
+#define IOSPAWN_FLAG_ALLOW_SET_FG 1
+
/* Spawn the executable PATH with ARGV as arguments. After forking
close all fds except for those in FD_LIST in the child, then
optionally dup() the child fds. Finally, all fds in the list are
closed in the parent. */
-int _gpgme_io_spawn (const char *path, char *const argv[],
+int _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
struct spawn_fd_item_s *fd_list, pid_t *r_pid);
int _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock);
const char *_gpgme_get_gpgsm_path (void);
const char *_gpgme_get_gpgconf_path (void);
int _gpgme_get_conf_int (const char *key, int *value);
-void _gpgme_allow_set_foregound_window (pid_t pid);
+void _gpgme_allow_set_foreground_window (pid_t pid);
/*-- dirinfo.c --*/
const char *_gpgme_get_default_homedir (void);
cfd[0].fd = rp[1];
- status = _gpgme_io_spawn (file_name, argv, cfd, NULL);
+ status = _gpgme_io_spawn (file_name, argv, 0, cfd, NULL);
if (status < 0)
{
_gpgme_io_close (rp[0]);
int
-_gpgme_io_spawn (const char *path, char * const argv[],
+_gpgme_io_spawn (const char *path, char * const argv[], unsigned int flags,
struct spawn_fd_item_s *fd_list, pid_t *r_pid)
{
SECURITY_ATTRIBUTES sec_attr;
0 /* returns tid */
};
STARTUPINFO si;
- int cr_flags = CREATE_DEFAULT_ERROR_MODE
- | GetPriorityClass (GetCurrentProcess ());
+ int cr_flags = (CREATE_DEFAULT_ERROR_MODE
+ | GetPriorityClass (GetCurrentProcess ()));
int i;
char **args;
char *arg_string;
free (arg_string);
+ if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
+ _gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);
+
/* Insert the inherited handles. */
for (i = 0; fd_list[i].fd != -1; i++)
{
int written;
size_t len;
- line[0] = '\n';
- line[1] = '\0';
+ if ((flags & IOSPAWN_FLAG_ALLOW_SET_FG))
+ strcpy (line, "~1 \n");
+ else
+ strcpy (line, "\n");
for (i = 0; fd_list[i].fd != -1; i++)
{
/* Strip the newline. */
int
-_gpgme_io_spawn (const char *path, char *const argv[],
+_gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
struct spawn_fd_item_s *fd_list, pid_t *r_pid)
{
SECURITY_ATTRIBUTES sec_attr;
0 /* returns tid */
};
STARTUPINFO si;
- int cr_flags = CREATE_DEFAULT_ERROR_MODE
- | GetPriorityClass (GetCurrentProcess ());
+ int cr_flags = (CREATE_DEFAULT_ERROR_MODE
+ | GetPriorityClass (GetCurrentProcess ()));
int i;
char **args;
char *arg_string;
free (arg_string);
+ if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
+ _gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);
+
/* Insert the inherited handles. */
for (i = 0; fd_list[i].fd != -1; i++)
{
notation: "0xFEDCBA9876543210" with an extra white space after
every quadruplet. 10*(19*4 + 1) - 1 = 769. This plans ahead
for a time when a HANDLE is 64 bit. */
-#define BUFFER_MAX 800
+#define BUFFER_MAX 810
char line[BUFFER_MAX + 1];
int res;
int written;
size_t len;
- line[0] = '\n';
- line[1] = '\0';
+ if ((flags & IOSPAWN_FLAG_ALLOW_SET_FG))
+ strcpy (line, "~1 \n");
+ else
+ strcpy (line, "\n");
for (i = 0; fd_list[i].fd != -1; i++)
{
/* Strip the newline. */
if (r_pid)
*r_pid = (pid_t)pi.dwProcessId;
+
if (ResumeThread (pi.hThread) < 0)
TRACE_LOG1 ("ResumeThread failed: ec=%d", (int) GetLastError ());
int
-_gpgme_io_spawn (const char *path, char * const argv[],
+_gpgme_io_spawn (const char *path, char * const argv[], unsigned int flags,
struct spawn_fd_item_s *fd_list, pid_t *r_pid)
{
SECURITY_ATTRIBUTES sec_attr;
free (arg_string);
+ if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
+ _gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);
+
/* Insert the inherited handles. */
for (i = 0; fd_list[i].fd != -1; i++)
{
int written;
size_t len;
- line[0] = '\n';
- line[1] = '\0';
+ if ((flags & IOSPAWN_FLAG_ALLOW_SET_FG))
+ strcpy (line, "~1 \n");
+ else
+ strcpy (line, "\n");
for (i = 0; fd_list[i].fd != -1; i++)
{
/* Strip the newline. */
void
-_gpgme_allow_set_foregound_window (pid_t pid)
+_gpgme_allow_set_foreground_window (pid_t pid)
{
static int initialized;
static BOOL (WINAPI * func)(DWORD);
}
if (!pid || pid == (pid_t)(-1))
- ;
+ {
+ TRACE1 (DEBUG_ENGINE, "gpgme:AllowSetForegroundWindow", 0,
+ "no action for pid %d", (int)pid);
+ }
else if (func)
- func (pid);
+ {
+ int rc = func (pid);
+ TRACE2 (DEBUG_ENGINE, "gpgme:AllowSetForegroundWindow", 0,
+ "called for pid %d; result=%d", (int)pid, rc);
+
+ }
+ else
+ {
+ TRACE0 (DEBUG_ENGINE, "gpgme:AllowSetForegroundWindow", 0,
+ "function not available");
+ }
}