From 1f1aa573f9ac46a02cd54e5afe25ac7f62e32370 Mon Sep 17 00:00:00 2001 From: Tor Lillqvist Date: Fri, 13 May 2005 12:50:35 +0000 Subject: [PATCH] Don't bother looking for fd_set on Win32, we won't find it in sys/types.h 2005-05-13 Tor Lillqvist * configure.in: Don't bother looking for fd_set on Win32, we won't find it in sys/types.h or (the nonexistent) sys/select.h anyway. (It's in winsock2.h.) * plug-ins/common/xpm.c: Include gdkconfig.h for GDK_WINDOWING_WIN32. * plug-ins/script-fu/script-fu-server.c: Give it a chance to work on Win32 by covering for the differences between the WinSock and Unix socket APIs. Use recv() and send() instead of read() and write() on sockets. On Win32, use closesocket() for sockets instead of close(). Don't use perror() or look at errno after socket API errors on Win32. No EINTR failure mode with WinSock 2. (print_socket_api_error): New function. On Unix, just call perror(). On Win32, call WSAGetLastError() and produce an appropriate error message on stderr. * plug-ins/script-fu/Makefile.am (WINSOCK_LIBS): Link with the winsock2 library, as we compile with the winsock2 header. --- ChangeLog | 21 +++ configure.in | 31 ++-- plug-ins/common/xpm.c | 2 + plug-ins/script-fu/Makefile.am | 2 +- plug-ins/script-fu/script-fu-server.c | 235 +++++++++++++++++++++++--- 5 files changed, 249 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index bcafaa2da6..5afbe7fb38 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2005-05-13 Tor Lillqvist + + * configure.in: Don't bother looking for fd_set on Win32, we won't + find it in sys/types.h or (the nonexistent) sys/select.h + anyway. (It's in winsock2.h.) + + * plug-ins/common/xpm.c: Include gdkconfig.h for GDK_WINDOWING_WIN32. + + * plug-ins/script-fu/script-fu-server.c: Give it a chance to work + on Win32 by covering for the differences between the WinSock and + Unix socket APIs. Use recv() and send() instead of read() and + write() on sockets. On Win32, use closesocket() for sockets + instead of close(). Don't use perror() or look at errno after + socket API errors on Win32. No EINTR failure mode with WinSock 2. + (print_socket_api_error): New function. On Unix, just call + perror(). On Win32, call WSAGetLastError() and produce an + appropriate error message on stderr. + + * plug-ins/script-fu/Makefile.am (WINSOCK_LIBS): Link with the + winsock2 library, as we compile with the winsock2 header. + 2005-05-13 Michael Natterer * themes/Default/gtkrc diff --git a/configure.in b/configure.in index 67b9f3f00a..7bc66afc8e 100644 --- a/configure.in +++ b/configure.in @@ -832,22 +832,23 @@ AC_SUBST(HAVE_GLIBC_REGEX) # Check for select and fdset ############################ -AC_MSG_CHECKING([fd_set and sys/select]) -AC_TRY_COMPILE([#include ], - [fd_set readMask, writeMask;], gimp_ok=yes, gimp_ok=no) -if test $gimp_ok = no; then - AC_EGREP_HEADER(fd_mask, sys/select.h, gimp_ok=yes) - if test $gimp_ok = yes; then - AC_DEFINE(HAVE_SYS_SELECT_H, 1, - [Define to 1 if you have the header.]) - fi +if test x"$os_win32" != xyes; then + AC_MSG_CHECKING([fd_set and sys/select]) + AC_TRY_COMPILE([#include ], + [fd_set readMask, writeMask;], gimp_ok=yes, gimp_ok=no) + if test $gimp_ok = no; then + AC_EGREP_HEADER(fd_mask, sys/select.h, gimp_ok=yes) + if test $gimp_ok = yes; then + AC_DEFINE(HAVE_SYS_SELECT_H, 1, + [Define to 1 if you have the header.]) + fi + fi + AC_MSG_RESULT($gimp_ok) + if test $gimp_ok = no; then + AC_DEFINE(NO_FD_SET, 1, + [Define to 1 if you don't have the fd_set typedef.]) + fi fi -AC_MSG_RESULT($gimp_ok) -if test $gimp_ok = no; then - AC_DEFINE(NO_FD_SET, 1, - [Define to 1 if you don't have the fd_set function.]) -fi - ############################# # Threads and multi processor diff --git a/plug-ins/common/xpm.c b/plug-ins/common/xpm.c index e00e39ec51..c85efc7282 100644 --- a/plug-ins/common/xpm.c +++ b/plug-ins/common/xpm.c @@ -47,6 +47,8 @@ Previous...Inherited code from Ray Lehtiniemi, who inherited it from S & P. #include +#include /* For GDK_WINDOWING_WIN32 */ + #ifdef GDK_WINDOWING_WIN32 #ifndef XPM_NO_X #define XPM_NO_X diff --git a/plug-ins/script-fu/Makefile.am b/plug-ins/script-fu/Makefile.am index 504f68d154..b59549f785 100644 --- a/plug-ins/script-fu/Makefile.am +++ b/plug-ins/script-fu/Makefile.am @@ -11,7 +11,7 @@ libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la if OS_WIN32 mwindows = -mwindows -WINSOCK_LIBS = -lwsock32 +WINSOCK_LIBS = -lws2_32 endif AM_LDFLAGS = $(mwindows) diff --git a/plug-ins/script-fu/script-fu-server.c b/plug-ins/script-fu/script-fu-server.c index 9e9b5743a1..6da384496e 100644 --- a/plug-ins/script-fu/script-fu-server.c +++ b/plug-ins/script-fu/script-fu-server.c @@ -20,7 +20,6 @@ #include #include -#include #include #ifdef HAVE_UNISTD_H @@ -37,17 +36,16 @@ #ifdef G_OS_WIN32 #include -#include #else #include -#include -#include -#include -#endif - #ifdef HAVE_SYS_SELECT_H #include #endif /* HAVE_SYS_SELECT_H */ +#include +#include +#include +#include +#endif #include @@ -59,6 +57,11 @@ #include "siod-wrapper.h" #include "script-fu-server.h" +#ifdef G_OS_WIN32 +#define CLOSESOCKET(fd) closesocket(fd) +#else +#define CLOSESOCKET(fd) close(fd) +#endif #define COMMAND_HEADER 3 #define RESPONSE_HEADER 4 @@ -99,7 +102,7 @@ #define CMD_LEN_H_BYTE 1 #define CMD_LEN_L_BYTE 2 -#define ERROR 1 +#define ERROR_BYTE 1 #define RSP_LEN_H_BYTE 2 #define RSP_LEN_L_BYTE 3 @@ -142,7 +145,7 @@ static gboolean server_interface (void); static void response_callback (GtkWidget *widget, gint response_id, gpointer data); - +static void print_socket_api_error (const gchar *api_name); /* * Local variables @@ -254,7 +257,7 @@ script_fu_server_read_fd (gpointer key, server_log ("Server: disconnect from host %s.\n", (gchar *) value); - close (fd); + CLOSESOCKET (fd); /* Invalidate the file descriptor for pending commands from the disconnected client. */ @@ -297,7 +300,7 @@ script_fu_server_listen (gint timeout) if (select (FD_SETSIZE, &fds, NULL, NULL, tvp) < 0) { - perror ("select"); + print_socket_api_error ("select"); return; } @@ -313,7 +316,7 @@ script_fu_server_listen (gint timeout) if (new < 0) { - perror ("accept"); + print_socket_api_error ("accept"); return; } @@ -341,7 +344,7 @@ server_start (gint port, if (listen (server_sock, 5) < 0) { - perror ("listen"); + print_socket_api_error ("listen"); return; } @@ -421,24 +424,24 @@ execute_command (SFCommand *cmd) } buffer[MAGIC_BYTE] = MAGIC; - buffer[ERROR] = error ? TRUE : FALSE; + buffer[ERROR_BYTE] = error ? TRUE : FALSE; buffer[RSP_LEN_H_BYTE] = (guchar) (response_len >> 8); buffer[RSP_LEN_L_BYTE] = (guchar) (response_len & 0xFF); /* Write the response to the client */ for (i = 0; i < RESPONSE_HEADER; i++) - if (cmd->filedes > 0 && write (cmd->filedes, buffer + i, 1) < 0) + if (cmd->filedes > 0 && send (cmd->filedes, buffer + i, 1, 0) < 0) { /* Write error */ - perror ("write"); + print_socket_api_error ("send"); return FALSE; } for (i = 0; i < response_len; i++) - if (cmd->filedes > 0 && write (cmd->filedes, response + i, 1) < 0) + if (cmd->filedes > 0 && send (cmd->filedes, response + i, 1, 0) < 0) { /* Write error */ - perror ("write"); + print_socket_api_error ("send"); return FALSE; } @@ -459,13 +462,14 @@ read_from_client (gint filedes) for (i = 0; i < COMMAND_HEADER;) { - nbytes = read (filedes, buffer + i, COMMAND_HEADER - i); + nbytes = recv (filedes, buffer + i, COMMAND_HEADER - i, 0); if (nbytes < 0) { +#ifndef G_OS_WIN32 if (errno == EINTR) continue; - +#endif server_log ("Error reading command header.\n"); return -1; } @@ -487,13 +491,14 @@ read_from_client (gint filedes) for (i = 0; i < command_len;) { - nbytes = read (filedes, command + i, command_len - i); + nbytes = recv (filedes, command + i, command_len - i, 0); if (nbytes <= 0) { +#ifndef G_OS_WIN32 if (nbytes < 0 && errno == EINTR) continue; - +#endif server_log ("Error reading command. Read %d out of %d bytes.\n", i, command_len); g_free (command); @@ -548,7 +553,7 @@ make_socket (guint port) } else { - perror ("Can't initialize the Winsock DLL"); + print_socket_api_error ("WSAStartup"); gimp_quit (); } } @@ -558,7 +563,7 @@ make_socket (guint port) sock = socket (PF_INET, SOCK_STREAM, 0); if (sock < 0) { - perror ("socket"); + print_socket_api_error ("socket"); gimp_quit (); } @@ -571,7 +576,7 @@ make_socket (guint port) if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) { - perror ("bind"); + print_socket_api_error ("bind"); gimp_quit (); } @@ -607,7 +612,7 @@ script_fu_server_shutdown_fd (gpointer key, static void server_quit (void) { - close (server_sock); + CLOSESOCKET (server_sock); if (clients) { @@ -706,3 +711,181 @@ response_callback (GtkWidget *widget, gtk_widget_destroy (widget); } + +static void +print_socket_api_error (const gchar *api_name) +{ +#ifdef G_OS_WIN32 + /* Yes, this functionality really belongs to GLib. */ + const gchar *emsg; + gchar unk[100]; + int number = WSAGetLastError (); + + switch (number) + { + case WSAEINTR: + emsg = "Interrupted function call"; + break; + case WSAEACCES: + emsg = "Permission denied"; + break; + case WSAEFAULT: + emsg = "Bad address"; + break; + case WSAEINVAL: + emsg = "Invalid argument"; + break; + case WSAEMFILE: + emsg = "Too many open sockets"; + break; + case WSAEWOULDBLOCK: + emsg = "Resource temporarily unavailable"; + break; + case WSAEINPROGRESS: + emsg = "Operation now in progress"; + break; + case WSAEALREADY: + emsg = "Operation already in progress"; + break; + case WSAENOTSOCK: + emsg = "Socket operation on nonsocket"; + break; + case WSAEDESTADDRREQ: + emsg = "Destination address required"; + break; + case WSAEMSGSIZE: + emsg = "Message too long"; + break; + case WSAEPROTOTYPE: + emsg = "Protocol wrong type for socket"; + break; + case WSAENOPROTOOPT: + emsg = "Bad protocol option"; + break; + case WSAEPROTONOSUPPORT: + emsg = "Protocol not supported"; + break; + case WSAESOCKTNOSUPPORT: + emsg = "Socket type not supported"; + break; + case WSAEOPNOTSUPP: + emsg = "Operation not supported on transport endpoint"; + break; + case WSAEPFNOSUPPORT: + emsg = "Protocol family not supported"; + break; + case WSAEAFNOSUPPORT: + emsg = "Address family not supported by protocol family"; + break; + case WSAEADDRINUSE: + emsg = "Address already in use"; + break; + case WSAEADDRNOTAVAIL: + emsg = "Address not available"; + break; + case WSAENETDOWN: + emsg = "Network interface is not configured"; + break; + case WSAENETUNREACH: + emsg = "Network is unreachable"; + break; + case WSAENETRESET: + emsg = "Network dropped connection on reset"; + break; + case WSAECONNABORTED: + emsg = "Software caused connection abort"; + break; + case WSAECONNRESET: + emsg = "Connection reset by peer"; + break; + case WSAENOBUFS: + emsg = "No buffer space available"; + break; + case WSAEISCONN: + emsg = "Socket is already connected"; + break; + case WSAENOTCONN: + emsg = "Socket is not connected"; + break; + case WSAESHUTDOWN: + emsg = "Can't send after socket shutdown"; + break; + case WSAETIMEDOUT: + emsg = "Connection timed out"; + break; + case WSAECONNREFUSED: + emsg = "Connection refused"; + break; + case WSAEHOSTDOWN: + emsg = "Host is down"; + break; + case WSAEHOSTUNREACH: + emsg = "Host is unreachable"; + break; + case WSAEPROCLIM: + emsg = "Too many processes"; + break; + case WSASYSNOTREADY: + emsg = "Network subsystem is unavailable"; + break; + case WSAVERNOTSUPPORTED: + emsg = "Winsock.dll version out of range"; + break; + case WSANOTINITIALISED: + emsg = "Successful WSAStartup not yet performed"; + break; + case WSAEDISCON: + emsg = "Graceful shutdown in progress"; + break; + case WSATYPE_NOT_FOUND: + emsg = "Class type not found"; + break; + case WSAHOST_NOT_FOUND: + emsg = "Host not found"; + break; + case WSATRY_AGAIN: + emsg = "Nonauthoritative host not found"; + break; + case WSANO_RECOVERY: + emsg = "This is a nonrecoverable error"; + break; + case WSANO_DATA: + emsg = "Valid name, no data record of requested type"; + break; + case WSA_INVALID_HANDLE: + emsg = "Specified event object handle is invalid"; + break; + case WSA_INVALID_PARAMETER: + emsg = "One or more parameters are invalid"; + break; + case WSA_IO_INCOMPLETE: + emsg = "Overlapped I/O event object not in signaled state"; + break; + case WSA_NOT_ENOUGH_MEMORY: + emsg = "Insufficient memory available"; + break; + case WSA_OPERATION_ABORTED: + emsg = "Overlapped operation aborted"; + break; + case WSAEINVALIDPROCTABLE: + emsg = "Invalid procedure table from service provider"; + break; + case WSAEINVALIDPROVIDER: + emsg = "Invalid service provider version number"; + break; + case WSAEPROVIDERFAILEDINIT: + emsg = "Unable to initialize a service provider"; + break; + case WSASYSCALLFAILURE: + emsg = "System call failure"; + break; + default: + sprintf (unk, "Unknown WinSock error %d", number); + emsg = unk; + break; + } + fprintf (stderr, "%s failed: %s\n", api_name, emsg); +#else + perror (api_name); +#endif +}