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 +}