Re: [gtk-vnc-devel] PATCH: Portability to compile under MinGW for Windows



On Wed, Sep 10, 2008 at 03:14:59PM -0500, Anthony Liguori wrote:
> Daniel P. Berrange wrote:
> >This patch addresses the (surprisingly few) portability problems which
> >prevent compilation of gtk-vnc with MinGW. We had already addressed
> >the major problem with the  pthreads based coroutine in the past, and
> >this ties up loose ends. The two issues addressed are a drop in impl
> >of getaddrinfo from GNULIB, and errno / WSAGetLastError() changes.
> >  
> 
> I'm surprised this worked this easily but then I thought that perhaps 
> you've only tested with GNUtls?
> 
> My understanding was that Windows sockets were not file descriptors and 
> that read/write cannot be used with them.  Neither can select.  It's 
> been a long time since I've done windows socket programming though so I 
> may be mistaken.

Attached is an updated version of the patch. All same stuff as before,
but it also now checks the extra errno's that winsock requires, uses
send/recv instead of read/write, and fixes a pthread coroutine  bug.

With this I have successfully run gvncviewer demo program under WINE
and connected to  a Vino server.

Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
diff -r f1d5c8fae2e9 .hgignore
--- a/.hgignore	Fri Sep 05 13:32:03 2008 +0100
+++ b/.hgignore	Wed Oct 08 14:15:50 2008 -0400
@@ -24,7 +24,7 @@
 ^build
 ^examples/\.deps/
 ^examples/\.libs/
-^examples/gvncviewer$
+^examples/gvncviewer(\.exe)?$
 ^missing$
 ^INSTALL$
 ^depcomp$
@@ -36,9 +36,9 @@
 ^plugin/gtk-vnc-plugin.la$
 ^plugin/gtk_vnc_plugin_la-.*
 ^plugin/gtk-vnc-plugin.so
-
-syntax: glob
-examples/*.o
-src/*.defs
-src/*.orig
-*.spec
+.gnulib
+examples/.*\.o
+src/.*\.defs
+src/.*\.orig
+.*\.spec
+.*\.tar\.gz$
diff -r f1d5c8fae2e9 Makefile.am
--- a/Makefile.am	Fri Sep 05 13:32:03 2008 +0100
+++ b/Makefile.am	Wed Oct 08 14:15:50 2008 -0400
@@ -1,5 +1,9 @@
 
-SUBDIRS = src examples plugin
+SUBDIRS = gnulib/lib src examples plugin gnulib/tests
+
+ACLOCAL_AMFLAGS = -I gnulib/m4
+
+
 
 pkgconfig_DATA = @PACKAGE -1 0 pc
 pkgconfigdir = $(libdir)/pkgconfig
diff -r f1d5c8fae2e9 autogen.sh
--- a/autogen.sh	Fri Sep 05 13:32:03 2008 +0100
+++ b/autogen.sh	Wed Oct 08 14:15:50 2008 -0400
@@ -45,7 +45,7 @@
 fi
 
 libtoolize --copy --force
-aclocal
+aclocal -I gnulib/m4
 autoheader
 automake --add-missing --copy
 autoconf
diff -r f1d5c8fae2e9 bootstrap
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bootstrap	Wed Oct 08 14:15:50 2008 -0400
@@ -0,0 +1,84 @@
+#!/bin/sh
+# Run this after autogen.sh, to pull in all of the gnulib-related bits.
+# It's important to run *after* autogen.sh, since it updates some of
+# the same files autogen.sh does, yet those from gnulib are newer,
+# and match the tests.  So if a gnulib bug has been fixed since the
+# snapshot taken for whatever gettext release you're using, yet you
+# run "make check" against the wrong version, the corresponding unit
+# test in gl-tests/ may well fail.
+
+usage() {
+  echo >&2 "\
+Usage: $0 [OPTION]...
+Bootstrap this package from the checked-out sources.
+
+Options:
+ --gnulib-srcdir=DIRNAME  Specify the local directory where gnulib
+                          sources reside.  Use this if you already
+                          have gnulib sources on your machine, and
+                          do not want to waste your bandwidth downloading
+                          them again.
+
+If the file bootstrap.conf exists in the current working directory, its
+contents are read as shell variables to configure the bootstrap.
+
+Running without arguments will suffice in most cases.
+"
+}
+
+for option
+do
+  case $option in
+  --help)
+    usage
+    exit;;
+  --gnulib-srcdir=*)
+    GNULIB_SRCDIR=`expr "$option" : '--gnulib-srcdir=\(.*\)'`;;
+  *)
+    echo >&2 "$0: $option: unknown option"
+    exit 1;;
+  esac
+done
+
+cleanup_gnulib() {
+  st=$?
+  rm -fr .gnulib
+  exit $st
+}
+
+case ${GNULIB_SRCDIR--} in
+-)
+  if [ ! -d .gnulib ]; then
+    echo "$0: getting gnulib files..."
+
+    trap cleanup_gnulib 1 2 13 15
+
+    git clone --depth 1 git://git.sv.gnu.org/gnulib .gnulib ||
+      cleanup_gnulib
+
+    trap - 1 2 13 15
+  fi
+  GNULIB_SRCDIR=.gnulib
+esac
+
+gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
+<$gnulib_tool || exit
+
+modules='
+getaddrinfo
+vc-list-files
+'
+
+# Tell gnulib to:
+#   require LGPLv2+
+#   put *.m4 files in new gnulib/m4/ dir
+#   put *.[ch] files in new gnulib/lib/ dir.
+
+$gnulib_tool			\
+  --lgpl=2			\
+  --with-tests			\
+  --m4-base=gnulib/m4		\
+  --source-base=gnulib/lib	\
+  --tests-base=gnulib/tests	\
+  --import $modules
+
diff -r f1d5c8fae2e9 configure.ac
--- a/configure.ac	Fri Sep 05 13:32:03 2008 +0100
+++ b/configure.ac	Wed Oct 08 14:15:50 2008 -0400
@@ -23,14 +23,28 @@
 
 AC_CONFIG_HEADERS([config.h:config.hin])
 
-
 AC_CANONICAL_TARGET
 
 AM_INIT_AUTOMAKE(gtk-vnc, 0.3.7)
 
+
+dnl gl_INIT uses m4_foreach_w, yet that is not defined in autoconf-2.59.
+dnl In order to accommodate developers with such old tools, here's a
+dnl replacement definition.
+m4_ifndef([m4_foreach_w],
+  [m4_define([m4_foreach_w],
+    [m4_foreach([$1], m4_split(m4_normalize([$2]), [ ]), [$3])])])
+
+gl_EARLY
+gl_INIT
+
 AC_PROG_CC_STDC
 AM_PROG_CC_C_O
+AC_LIBTOOL_WIN32_DLL
+
 AC_PROG_LIBTOOL
+
+AC_CHECK_HEADERS([pwd.h winsock2.h])
 
 AC_ARG_WITH(python,
 [  --with-python           build python bindings],
@@ -234,6 +248,8 @@
 
 AC_CONFIG_FILES(
   Makefile
+  gnulib/lib/Makefile
+  gnulib/tests/Makefile
   src/Makefile
   examples/Makefile
   plugin/Makefile
diff -r f1d5c8fae2e9 src/Makefile.am
--- a/src/Makefile.am	Fri Sep 05 13:32:03 2008 +0100
+++ b/src/Makefile.am	Wed Oct 08 14:15:50 2008 -0400
@@ -4,13 +4,15 @@
 lib_LTLIBRARIES = libgtk-vnc-1.0.la
 
 libgtk_vnc_1_0_la_LIBADD = @GTK_LIBS@ @GTKGLEXT_LIBS@ @GNUTLS_LIBS@ \
-			   @GTHREAD_LIBS@
+			   @GTHREAD_LIBS@ \
+                           ../gnulib/lib/libgnu.la
 libgtk_vnc_1_0_la_CFLAGS = @GTK_CFLAGS@ @GTKGLEXT_CFLAGS@ @GNUTLS_CFLAGS@ \
 			   @GTHREAD_CFLAGS@ @WARNING_CFLAGS@ \
 			   -DSYSCONFDIR=\""$(sysconfdir)"\" \
-                           -DG_LOG_DOMAIN=\"gtk-vnc\"
+                           -DG_LOG_DOMAIN=\"gtk-vnc\" \
+                           -I$(top_srcdir)gnulib/lib -I../gnulib/lib
 libgtk_vnc_1_0_la_LDFLAGS = -Wl, @LD_VERSION_SCRIPT_SUPPORT@ \
-                            -version-info 0:1:0
+                            -version-info 0:1:0 -no-undefined
 
 gtk_vnc_includedir = $(includedir)/gtk-vnc-1.0/
 gtk_vnc_include_HEADERS = vncdisplay.h
@@ -22,7 +24,7 @@
 	vncdisplay.h vncdisplay.c \
         vncmarshal.h vncmarshal.c \
 	x_keymap.h x_keymap.c vnc_keycodes.h \
-	utils.h
+	utils.h socketcompat.h
 
 if WITH_UCONTEXT
 libgtk_vnc_1_0_la_SOURCES += continuation.h continuation.c coroutine_ucontext.c
diff -r f1d5c8fae2e9 src/continuation.c
--- a/src/continuation.c	Fri Sep 05 13:32:03 2008 +0100
+++ b/src/continuation.c	Wed Oct 08 14:15:50 2008 -0400
@@ -7,6 +7,8 @@
  *
  *  GTK VNC Widget
  */
+
+#include <config.h>
 
 #include "continuation.h"
 
diff -r f1d5c8fae2e9 src/coroutine_gthread.c
--- a/src/coroutine_gthread.c	Fri Sep 05 13:32:03 2008 +0100
+++ b/src/coroutine_gthread.c	Wed Oct 08 14:15:50 2008 -0400
@@ -8,6 +8,8 @@
  *  GTK VNC Widget
  */
 
+#include <config.h>
+
 #include "coroutine.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -17,13 +19,24 @@
 static struct coroutine *current;
 static struct coroutine leader;
 
+#if 0
+#define CO_DEBUG(OP) fprintf(stderr, "%s %p %s %d\n", OP, g_thread_self(), __FUNCTION__, __LINE__)
+#else
+#define CO_DEBUG(OP)
+#endif
+
 static void coroutine_system_init(void)
 {
-	if (!g_thread_supported())
+	if (!g_thread_supported()) {
+	        CO_DEBUG("INIT");
 		g_thread_init(NULL);
+	}
+
 
 	run_cond = g_cond_new();
 	run_lock = g_mutex_new();
+	CO_DEBUG("LOCK");
+	g_mutex_lock(run_lock);
 
 	/* The thread that creates the first coroutine is the system coroutine
 	 * so let's fill out a structure for it */
@@ -42,17 +55,22 @@
 static gpointer coroutine_thread(gpointer opaque)
 {
 	struct coroutine *co = opaque;
+	CO_DEBUG("LOCK");
+	g_mutex_lock(run_lock);
+	while (!co->runnable) {
+		CO_DEBUG("WAIT");
+		g_cond_wait(run_cond, run_lock);
+	}
 
-	g_mutex_lock(run_lock);
-	while (!co->runnable)
-		g_cond_wait(run_cond, run_lock);
-
+	CO_DEBUG("RUNNABLE");
 	current = co;
 	co->data = co->entry(co->data);
 	co->exited = 1;
 
 	co->caller->runnable = TRUE;
+	CO_DEBUG("BROADCAST");
 	g_cond_broadcast(run_cond);
+	CO_DEBUG("UNLOCK");
 	g_mutex_unlock(run_lock);
 
 	return NULL;
@@ -62,7 +80,8 @@
 {
 	if (run_cond == NULL)
 		coroutine_system_init();
-	
+
+	CO_DEBUG("NEW");
 	co->thread = g_thread_create_full(coroutine_thread, co, co->stack_size,
 					  FALSE, TRUE,
 					  G_THREAD_PRIORITY_NORMAL,
@@ -88,15 +107,19 @@
 	to->runnable = TRUE;
 	to->data = arg;
 	to->caller = from;
+	CO_DEBUG("BROADCAST");
 	g_cond_broadcast(run_cond);
+	CO_DEBUG("UNLOCK");
 	g_mutex_unlock(run_lock);
-
+	CO_DEBUG("LOCK");
 	g_mutex_lock(run_lock);
-	while (!from->runnable)
+	while (!from->runnable) {
+	        CO_DEBUG("WAIT");
 		g_cond_wait(run_cond, run_lock);
-
+	}
 	current = from;
 
+	CO_DEBUG("SWAPPED");
 	return from->data;
 }
 
@@ -111,6 +134,7 @@
 		fprintf(stderr, "Co-routine is re-entering itself\n");
 		abort();
 	}
+	CO_DEBUG("SWAP");
 	return coroutine_swap(coroutine_self(), to, arg);
 }
 
@@ -121,6 +145,8 @@
 		fprintf(stderr, "Co-routine is yielding to no one\n");
 		abort();
 	}
+
+	CO_DEBUG("SWAP");
 	coroutine_self()->caller = NULL;
 	return coroutine_swap(coroutine_self(), to, arg);
 }
diff -r f1d5c8fae2e9 src/coroutine_ucontext.c
--- a/src/coroutine_ucontext.c	Fri Sep 05 13:32:03 2008 +0100
+++ b/src/coroutine_ucontext.c	Wed Oct 08 14:15:50 2008 -0400
@@ -7,6 +7,8 @@
  *
  *  GTK VNC Widget
  */
+
+#include <config.h>
 
 #include <sys/types.h>
 #include <sys/mman.h>
diff -r f1d5c8fae2e9 src/gvnc.c
--- a/src/gvnc.c	Fri Sep 05 13:32:03 2008 +0100
+++ b/src/gvnc.c	Wed Oct 08 14:15:50 2008 -0400
@@ -8,13 +8,10 @@
  *  GTK VNC Widget
  */
 
+#include <config.h>
+
 #include "gvnc.h"
 
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <netdb.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -40,6 +37,15 @@
 #include <gdk/gdkkeysyms.h>
 
 #include "vnc_keycodes.h"
+#include "socketcompat.h"
+#include "getaddrinfo.h"
+
+/* AI_ADDRCONFIG is missing on some systems and gnulib won't provide it
+   even if its emulated getaddrinfo() for us . */
+#ifndef AI_ADDRCONFIG
+# define AI_ADDRCONFIG 0
+#endif
+
 
 struct wait_queue
 {
@@ -185,7 +191,6 @@
 
 	g_io_add_watch(channel, cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL, g_io_wait_helper, coroutine_self());
 	ret = coroutine_yield(NULL);
-
 	return *ret;
 }
 
@@ -321,10 +326,8 @@
 
 			/* inflate as much as possible */
 			err = inflate(gvnc->strm, Z_SYNC_FLUSH);
-			if (err != Z_OK) {
-				errno = EIO;
-				return -1;
-			}
+			if (err != Z_OK)
+				return -EIO;
 
 			gvnc->uncompressed_length = (uint8_t *)gvnc->strm->next_out - gvnc->uncompressed_buffer;
 			gvnc->compressed_length -= (uint8_t *)gvnc->strm->next_in - gvnc->compressed_buffer;
@@ -344,7 +347,7 @@
 	size_t offset = 0;
 
 	if (gvnc->has_error) return -EINVAL;
-	
+
 	while (offset < len) {
 		size_t tmp;
 
@@ -352,10 +355,10 @@
 		 * so we must by-pass it */
 		if (gvnc_use_compression(gvnc)) {
 			int ret = gvnc_zread(gvnc, data + offset, len);
-			if (ret == -1) {
+			if (ret < 0) {
 				GVNC_DEBUG("Closing the connection: gvnc_read() - gvnc_zread() failed\n");
 				gvnc->has_error = TRUE;
-				return -errno;
+				return ret;
 			}
 			offset += ret;
 			continue;
@@ -366,17 +369,19 @@
 				ret = gnutls_read(gvnc->tls_session, gvnc->read_buffer, 4096);
 				if (ret < 0) {
 					if (ret == GNUTLS_E_AGAIN)
-						errno = EAGAIN;
+						ret = -EAGAIN;
 					else
-						errno = EIO;
-					ret = -1;
+						ret = -EIO;
 				}
-			} else
-				ret = read(fd, gvnc->read_buffer, 4096);
+			} else {
+				ret = recv(fd, gvnc->read_buffer, 4096, 0);
+				if (ret < 0)
+					ret = socket_errno() * -1;
+			}
 
-			if (ret == -1) {
-				switch (errno) {
-				case EAGAIN:
+			if (ret < 0) {
+				switch (ret * -1) {
+				case EWOULDBLOCK:
 					if (gvnc->wait_interruptable) {
 						if (!g_io_wait_interruptable(&gvnc->wait,
 									     gvnc->channel, G_IO_IN))
@@ -386,9 +391,9 @@
 				case EINTR:
 					continue;
 				default:
-					GVNC_DEBUG("Closing the connection: gvnc_read() - ret=-1\n");
+					GVNC_DEBUG("Closing the connection: gvnc_read() - ret=%d\n", ret);
 					gvnc->has_error = TRUE;
-					return -errno;
+					return ret;
 				}
 			}
 			if (ret == 0) {
@@ -425,23 +430,25 @@
 					   gvnc->write_offset-offset);
 			if (ret < 0) {
 				if (ret == GNUTLS_E_AGAIN)
-					errno = EAGAIN;
+					ret = -EAGAIN;
 				else
-					errno = EIO;
-				ret = -1;
+					ret = -EIO;
 			}
-		} else
-			ret = write(fd,
-				    gvnc->write_buffer+offset,
-				    gvnc->write_offset-offset);
-		if (ret == -1) {
-			switch (errno) {
-			case EAGAIN:
+		} else {
+			ret = send(fd,
+				   gvnc->write_buffer+offset,
+				   gvnc->write_offset-offset, 0);
+			if (ret < 0)
+				ret = socket_errno() * -1;
+		}
+		if (ret < 0) {
+			switch (ret * -1) {
+			case EWOULDBLOCK:
 				g_io_wait(gvnc->channel, G_IO_OUT);
 			case EINTR:
 				continue;
 			default:
-				GVNC_DEBUG("Closing the connection: gvnc_flush\n");
+				GVNC_DEBUG("Closing the connection: gvnc_flush %d\n", ret);
 				gvnc->has_error = TRUE;
 				return;
 			}
@@ -488,7 +495,7 @@
  retry:
 	ret = write(fd, data, len);
 	if (ret < 0) {
-		if (errno == EINTR)
+		if (socket_errno() == EINTR)
 			goto retry;
 		return -1;
 	}
@@ -506,7 +513,7 @@
  retry:
 	ret = read(fd, data, len);
 	if (ret < 0) {
-		if (errno == EINTR)
+		if (socket_errno() == EINTR)
 			goto retry;
 		return -1;
 	}
@@ -2802,12 +2809,12 @@
 	if (gvnc_has_error(gvnc))
 		return FALSE;
 
-	if (!gvnc->fmt.true_color_flag && gvnc->ops.get_preferred_pixel_format)
+	if (!gvnc->fmt.true_color_flag && gvnc->ops.get_preferred_pixel_format) {
 		if (gvnc->ops.get_preferred_pixel_format(gvnc->ops_data, &gvnc->fmt))
 			gvnc_set_pixel_format(gvnc, &gvnc->fmt);
 		else
 			goto fail;
-
+	}
 	memset(&gvnc->strm, 0, sizeof(gvnc->strm));
 	/* FIXME what level? */
 	for (i = 0; i < 5; i++)
@@ -2822,15 +2829,16 @@
 	return !gvnc_has_error(gvnc);
 }
 
-gboolean gvnc_open_fd(struct gvnc *gvnc, int fd)
+static gboolean gvnc_set_nonblock(int fd)
 {
-	int flags;
-	if (gvnc_is_open(gvnc)) {
-		GVNC_DEBUG ("Error: already connected?\n");
+#ifdef __MINGW32__
+	unsigned long flags = 1;
+	if (ioctlsocket(fd, FIONBIO, &flags) < 0) {
+		GVNC_DEBUG ("Failed to set nonblocking flag\n");
 		return FALSE;
 	}
-
-	GVNC_DEBUG("Connecting to FD %d\n", fd);
+#else
+	int flags;
 	if ((flags = fcntl(fd, F_GETFL)) < 0) {
 		GVNC_DEBUG ("Failed to fcntl()\n");
 		return FALSE;
@@ -2840,6 +2848,21 @@
 		GVNC_DEBUG ("Failed to fcntl()\n");
 		return FALSE;
 	}
+#endif
+	return TRUE;
+}
+
+gboolean gvnc_open_fd(struct gvnc *gvnc, int fd)
+{
+	if (gvnc_is_open(gvnc)) {
+		GVNC_DEBUG ("Error: already connected?\n");
+		return FALSE;
+	}
+
+	GVNC_DEBUG("Connecting to FD %d\n", fd);
+
+	if (!gvnc_set_nonblock(fd))
+		return FALSE;
 
 	if (!(gvnc->channel = g_io_channel_unix_new(fd))) {
 		GVNC_DEBUG ("Failed to g_io_channel_unix_new()\n");
@@ -2873,7 +2896,7 @@
 
         runp = ai;
         while (runp != NULL) {
-                int flags, fd;
+                int fd;
                 GIOChannel *chan;
 
 		if ((fd = socket(runp->ai_family, runp->ai_socktype,
@@ -2883,17 +2906,8 @@
 		}
 
                 GVNC_DEBUG("Trying socket %d\n", fd);
-                if ((flags = fcntl(fd, F_GETFL)) < 0) {
-                        close(fd);
-                        GVNC_DEBUG ("Failed to fcntl()\n");
-                        break;
-                }
-                flags |= O_NONBLOCK;
-                if (fcntl(fd, F_SETFL, flags) < 0) {
-                        close(fd);
-                        GVNC_DEBUG ("Failed to fcntl()\n");
-                        break;
-                }
+		if (!gvnc_set_nonblock(fd))
+			break;
 
                 if (!(chan = g_io_channel_unix_new(fd))) {
                         close(fd);
@@ -2904,21 +2918,22 @@
         reconnect:
                 /* FIXME: Better handle EINPROGRESS/EISCONN return values,
                    as explained in connect(2) man page */
-                if ( (connect(fd, runp->ai_addr, runp->ai_addrlen) == 0) || errno == EISCONN) {
+                if ((connect(fd, runp->ai_addr, runp->ai_addrlen) == 0) ||
+		    socket_errno() == EISCONN) {
                         gvnc->channel = chan;
                         gvnc->fd = fd;
                         freeaddrinfo(ai);
                         return !gvnc_has_error(gvnc);
                 }
-
-                if (errno == EINPROGRESS) {
+                if (socket_errno() == EINPROGRESS ||
+                    socket_errno() == EWOULDBLOCK) {
                         g_io_wait(chan, G_IO_OUT|G_IO_ERR|G_IO_HUP);
                         goto reconnect;
-                } else if (errno != ECONNREFUSED &&
-                           errno != EHOSTUNREACH) {
+                } else if (socket_errno() != ECONNREFUSED &&
+                           socket_errno() != EHOSTUNREACH) {
                         g_io_channel_unref(chan);
                         close(fd);
-                        GVNC_DEBUG ("Failed with errno = %d\n", errno);
+                        GVNC_DEBUG ("Failed with errno = %d\n", socket_errno());
                         break;
                 }
                 close(fd);
diff -r f1d5c8fae2e9 src/socketcompat.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/socketcompat.h	Wed Oct 08 14:15:50 2008 -0400
@@ -0,0 +1,64 @@
+/*
+ * socketcompat.h: Socket compatibility for Windows, making it slightly
+ * less painful to use.
+ *
+ * Use this header under the following circumstances:
+ * (a) Instead of including any of: <net/if.h>, <netinet/in.h>,
+ *     <sys/socket.h>, <netdb.h>, <netinet/tcp.h>, AND
+ * (b) The file will be part of what is built on Windows (basically
+ *     just remote client stuff).
+ *
+ * You need to use socket_errno() instead of errno to get socket
+ * errors.
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Richard W.M. Jones <rjones redhat com>
+ */
+
+#ifndef __SOCKETCOMPAT_H__
+#define __SOCKETCOMPAT_H__
+
+#include <config.h>
+
+#include <errno.h>
+
+#ifndef HAVE_WINSOCK2_H		/* Unix & Cygwin. */
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+static inline int
+socket_errno (void)
+{
+  return errno;
+}
+
+#else                           /* MinGW & Win32 */
+
+#include <winsock2.h>
+
+/* Socket functions in Windows don't set errno.  Instead of using errno
+ * to test for socket errors, call this function to get the errno.
+ */
+static inline int
+socket_errno (void)
+{
+  return WSAGetLastError ();
+}
+
+/* Compatibility. */
+#define EWOULDBLOCK             WSAEWOULDBLOCK
+#define ECONNREFUSED            WSAECONNREFUSED
+#define EINPROGRESS             WSAEINPROGRESS
+#define EHOSTUNREACH            WSAEHOSTUNREACH
+#define EISCONN                 WSAEISCONN
+
+#endif /* HAVE_WINSOCK2_H */
+
+#endif /* __WINSOCKWRAPPER_H__ */
diff -r f1d5c8fae2e9 src/vncdisplay.c
--- a/src/vncdisplay.c	Fri Sep 05 13:32:03 2008 +0100
+++ b/src/vncdisplay.c	Wed Oct 08 14:15:50 2008 -0400
@@ -7,6 +7,8 @@
  *
  *  GTK VNC Widget
  */
+
+#include <config.h>
 
 #include "vncdisplay.h"
 #include "coroutine.h"
@@ -24,7 +26,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#ifdef HAVE_PWD_H
 #include <pwd.h>
+#endif
 
 #if WITH_GTKGLEXT
 #include <gtk/gtkgl.h>
@@ -2192,33 +2196,44 @@
 
 static int vnc_display_set_x509_credential(VncDisplay *obj, const char *name)
 {
-	char sysdir[PATH_MAX], userdir[PATH_MAX];
+	char file[PATH_MAX];
+	char sysdir[PATH_MAX];
+#ifndef __MINGW32__
+	char userdir[PATH_MAX];
 	struct passwd *pw;
-	char file[PATH_MAX];
 	char *dirs[] = { sysdir, userdir };
+#else
+	char *dirs[] = { sysdir };
+#endif
 
 	strncpy(sysdir, SYSCONFDIR "/pki", PATH_MAX-1);
 	sysdir[PATH_MAX-1] = '\0';
 
+#ifndef __MINGW32__
 	if (!(pw = getpwuid(getuid())))
 		return TRUE;
 
 	snprintf(userdir, PATH_MAX-1, "%s/.pki", pw->pw_dir);
 	userdir[PATH_MAX-1] = '\0';
+#endif
 
-	if (vnc_display_best_path(file, PATH_MAX, "CA", "cacert.pem", dirs, 2) < 0)
+	if (vnc_display_best_path(file, PATH_MAX, "CA", "cacert.pem",
+				  dirs, sizeof(dirs)/sizeof(dirs[0])) < 0)
 		return TRUE;
 	gvnc_set_credential_x509_cacert(obj->priv->gvnc, file);
 
 	/* Don't mind failures of CRL */
-	if (vnc_display_best_path(file, PATH_MAX, "CA", "cacrl.pem", dirs, 2) == 0)
+	if (vnc_display_best_path(file, PATH_MAX, "CA", "cacrl.pem",
+				  dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
 		gvnc_set_credential_x509_cacert(obj->priv->gvnc, file);
 
 	/* Set client key & cert if we have them. Server will reject auth
 	 * if it decides it requires them*/
-	if (vnc_display_best_path(file, PATH_MAX, name, "private/clientkey.pem", dirs, 2) == 0)
+	if (vnc_display_best_path(file, PATH_MAX, name, "private/clientkey.pem",
+				  dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
 		gvnc_set_credential_x509_key(obj->priv->gvnc, file);
-	if (vnc_display_best_path(file, PATH_MAX, name, "clientcert.pem", dirs, 2) == 0)
+	if (vnc_display_best_path(file, PATH_MAX, name, "clientcert.pem",
+				  dirs, sizeof(dirs)/sizeof(dirs[0])) == 0)
 		gvnc_set_credential_x509_cert(obj->priv->gvnc, file);
 
 	return FALSE;
diff -r f1d5c8fae2e9 vc-list-files
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vc-list-files	Wed Oct 08 14:15:50 2008 -0400
@@ -0,0 +1,107 @@
+#!/bin/sh
+# List version-controlled file names.
+
+# Print a version string.
+scriptversion=2008-07-11.19
+
+# Copyright (C) 2006-2008 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+# List the specified version-controlled files.
+# With no argument, list them all.  With a single DIRECTORY argument,
+# list the version-controlled files in that directory.
+
+# If there's an argument, it must be a single, "."-relative directory name.
+# cvsu is part of the cvsutils package: http://www.red-bean.com/cvsutils/
+
+postprocess=
+case $1 in
+  --help) cat <<EOF
+Usage: $0 [-C SRCDIR] [DIR]
+
+Output a list of version-controlled files in DIR (default .), relative to
+SRCDIR (default .).  SRCDIR must be the top directory of a checkout.
+
+Options:
+  --help     print this help, then exit
+  --version  print version number, then exit
+  -C SRCDIR  change directory to SRCDIR before generating list
+
+Report bugs and patches to <bug-gnulib gnu org>.
+EOF
+    exit ;;
+
+  --version)
+    year=`echo "$scriptversion" | sed 's/[^0-9].*//'`
+    cat <<EOF
+vc-list-files $scriptversion
+Copyright (C) $year Free Software Foundation, Inc,
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+EOF
+    exit ;;
+
+  -C)
+    test "$2" = . || postprocess="| sed 's|^|$2/|'"
+    cd "$2" || exit 1
+    shift; shift ;;
+esac
+
+dir=
+case $# in
+  0) ;;
+  1) dir=$1 ;;
+  *) echo "$0: too many arguments" 1>&2
+     echo "Usage: $0 [-C srcdir] [DIR]" 1>&2; exit 1;;
+esac
+
+test "x$dir" = x && dir=.
+
+if test -d .git; then
+  eval exec git ls-files '"$dir"' $postprocess
+elif test -d .hg; then
+  eval exec hg locate '"$dir/*"' $postprocess
+elif test -d .bzr; then
+  test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
+  eval exec bzr ls --versioned '"$dir"' $postprocess
+elif test -d CVS; then
+  test "$postprocess" = '' && postprocess="| sed 's|^\./||'"
+  if test -x build-aux/cvsu; then
+    eval build-aux/cvsu --find --types=AFGM '"$dir"' $postprocess
+  elif (cvsu --help) >/dev/null 2>&1; then
+    eval cvsu --find --types=AFGM '"$dir"' $postprocess
+  else
+    eval awk -F/ \''{			\
+	if (!$1 && $3 !~ /^-/) {	\
+	  f=FILENAME;			\
+	  if (f ~ /CVS\/Entries$/)	\
+	    f = substr(f, 0, length(f)-11); \
+	  print f $2;			\
+	}}'\''				\
+      `find "$dir" -name Entries -print` /dev/null' $postprocess
+  fi
+else
+  echo "$0: Failed to determine type of version control used in `pwd`" 1>&2
+  exit 1
+fi
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]