aboutsummaryrefslogtreecommitdiffstats
path: root/gpgme/w32-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'gpgme/w32-io.c')
-rw-r--r--gpgme/w32-io.c143
1 files changed, 130 insertions, 13 deletions
diff --git a/gpgme/w32-io.c b/gpgme/w32-io.c
index 36bbe2a6..39e50826 100644
--- a/gpgme/w32-io.c
+++ b/gpgme/w32-io.c
@@ -33,8 +33,19 @@
#include <fcntl.h>
#include <windows.h>
+#include "util.h"
#include "io.h"
+#define DEBUG_SELECT_ENABLED 1
+
+#if DEBUG_SELECT_ENABLED
+# define DEBUG_SELECT(a) fprintf a
+#else
+# define DEBUG_SELECT(a) do { } while(0)
+#endif
+
+
+
/*
* We assume that a HANDLE can be represented by an int which should be true
* for all i386 systems (HANDLE is defined as void *) and these are the only
@@ -45,7 +56,7 @@
#define fd_to_handle(a) ((HANDLE)(a))
#define handle_to_fd(a) ((int)(a))
#define pid_to_handle(a) ((HANDLE)(a))
-#define handle_to_pid(a) ((pid_t)(a))
+#define handle_to_pid(a) ((int)(a))
int
@@ -86,9 +97,18 @@ _gpgme_io_pipe ( int filedes[2] )
return -1;
filedes[0] = handle_to_fd (r);
filedes[1] = handle_to_fd (w);
- return 0
+ return 0;
+}
+
+int
+_gpgme_io_close ( int fd )
+{
+ if ( fd == -1 )
+ return -1;
+ return CloseHandle (fd_to_handle(fd)) ? 0 : -1;
}
+
int
_gpgme_io_set_nonblocking ( int fd )
{
@@ -97,7 +117,7 @@ _gpgme_io_set_nonblocking ( int fd )
static char *
-build_commandline ( char **argv );
+build_commandline ( char **argv )
{
int i, n = 0;
char *buf, *p;
@@ -118,7 +138,7 @@ build_commandline ( char **argv );
}
-pid_t
+int
_gpgme_io_spawn ( const char *path, char **argv,
struct spawn_fd_item_s *fd_child_list,
struct spawn_fd_item_s *fd_parent_list )
@@ -138,7 +158,8 @@ _gpgme_io_spawn ( const char *path, char **argv,
char *envblock = NULL;
int cr_flags = CREATE_DEFAULT_ERROR_MODE
| GetPriorityClass (GetCurrentProcess ());
- int rc;
+ int i, rc;
+ char *arg_string;
HANDLE save_stdout;
HANDLE outputfd[2], statusfd[2], inputfd[2];
@@ -204,9 +225,43 @@ _gpgme_io_spawn ( const char *path, char **argv,
int
-_gpgme_io_waitpid ( pid_t pid, int hang, int *r_status, int *r_signal )
+_gpgme_io_waitpid ( int pid, int hang, int *r_status, int *r_signal )
{
- return 0;
+ HANDLE proc = fd_to_handle (pid);
+ int code, exc, ret = 0;
+
+ *r_status = 0;
+ *r_signal = 0;
+ code = WaitForSingleObject ( proc, hang? INFINITE : NULL );
+ switch (code) {
+ case WAIT_FAILED:
+ fprintf (stderr, "** WFSO pid=%d failed: %d\n",
+ (int)pid, (int)GetLastError () );
+ break;
+
+ case WAIT_OBJECT_0:
+ if (!GetExitCodeProcess (proc, &exc)) {
+ fprintf (stderr, "** GECP pid=%d failed: ec=%d\n",
+ (int)pid, (int)GetLastError () );
+ *r_status = 4;
+ }
+ else {
+ fprintf (stderr, "** GECP pid=%d exit code=%d\n",
+ (int)pid, exc);
+ *r_status = exc;
+ }
+ ret = 1;
+ break;
+
+ case WAIT_TIMEOUT:
+ fprintf (stderr, "** WFSO pid=%d timed out\n", (int)pid);
+ break;
+
+ default:
+ fprintf (stderr, "** WFSO pid=%d returned %d\n", (int)pid, code );
+ break;
+ }
+ return ret;
}
@@ -219,13 +274,75 @@ _gpgme_io_waitpid ( pid_t pid, int hang, int *r_status, int *r_signal )
int
_gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
{
- return -1;
-}
-
-
-
-
+ HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS];
+ int code, nwait;
+ int i, any, ret;
+
+ DEBUG_SELECT ((stderr, "gpgme:select on [ "));
+ any = 0;
+ nwait = 0;
+ for ( i=0; i < nfds; i++ ) {
+ if ( fds[i].fd == -1 )
+ continue;
+ if ( fds[i].for_read || fds[i].for_write ) {
+ if ( nwait >= DIM (waitbuf) ) {
+ DEBUG_SELECT ((stderr, "oops ]\n" ));
+ fprintf (stderr, "** Too many objects for WFMO!\n" );
+ return -1;
+ }
+ else {
+ waitbuf[nwait++] = fd_to_handle (fds[i].fd);
+ DEBUG_SELECT ((stderr, "%c%d ",
+ fds[i].for_read? 'r':'w',fds[i].fd ));
+ any = 1;
+ }
+ }
+ fds[i].signaled = 0;
+ }
+ DEBUG_SELECT ((stderr, "]\n" ));
+ if (!any)
+ return 0;
+
+ ret = 0;
+ code = WaitForMultipleObjects ( nwait, waitbuf, 0, 1000 );
+ if (code == WAIT_FAILED ) {
+ fprintf (stderr, "** WFMO failed: %d\n", (int)GetLastError () );
+ ret = -1;
+ }
+ else if ( code == WAIT_TIMEOUT ) {
+ fprintf (stderr, "** WFMO timed out\n" );
+ }
+ else if ( code >= WAIT_OBJECT_0 && code < WAIT_OBJECT_0 + nwait ) {
+ /* This WFMO is a really silly function: It does return either
+ * the index of the signaled object or if 2 objects have been
+ * signalled at the same time, the index of the object with the
+ * lowest object is returned - so and how do we find out
+ * how many objects have been signaled???.
+ * The only solution I can imagine is to test each object starting
+ * with the returned index individually - how dull.
+ */
+ any = 0;
+ for (i=code - WAIT_OBJECT_0; i < nwait; i++ ) {
+ if (WaitForSingleObject ( waitbuf[i], NULL ) == WAIT_OBJECT_0) {
+ fds[i].signaled = 1;
+ any = 1;
+ }
+ }
+ if (any)
+ ret = 1;
+ else {
+ fprintf (stderr,
+ "** Oops: No signaled objects found after WFMO\n");
+ ret = -1;
+ }
+ }
+ else {
+ fprintf (stderr, "** WFMO returned %d\n", code );
+ ret = -1;
+ }
+ return ret;
+}
#endif /*HAVE_DOSISH_SYSTEM*/