From 5db5c2db61e7b6493c3a92742bf5ee1e49e3e511 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Tue, 21 Aug 2001 20:39:54 +0000 Subject: [PATCH] > Ok, where's a "system dependent hack" :) > It seems that win9x doesn't have the "netmsg.dll" so it defaults to "normal" > FormatMessage. > I wonder if one could load wsock32.dll or winsock.dll on those systems > instead of netmsg.dll. > > Mikhail, could you please test this code on your nt4 system? > Could someone else test this code on a win98/95 system? > > It works on win2k over here. It works on win2k here too but not on win98/95 or winNT. Anyway, attached is the patch which uses Magnus's my_sock_strerror function (renamed to winsock_strerror). The only difference is that I put the code to load and unload netmsg.dll in the libpqdll.c (is this OK Magnus?). Mikhail Terekhov --- src/interfaces/libpq/fe-connect.c | 30 +++++++-------- src/interfaces/libpq/fe-exec.c | 13 +++---- src/interfaces/libpq/fe-lobj.c | 8 +--- src/interfaces/libpq/fe-misc.c | 62 +++++++++++++++++++++---------- src/interfaces/libpq/libpq-fe.h | 13 ++++++- src/interfaces/libpq/libpqdll.c | 6 +++ src/interfaces/libpq/win32.h | 18 ++++----- 7 files changed, 90 insertions(+), 60 deletions(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 26fd7e0784..9301d1b1cf 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.175 2001/08/17 15:11:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.176 2001/08/21 20:39:52 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -703,7 +703,7 @@ connectMakeNonblocking(PGconn *conn) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not set socket to non-blocking mode: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); return 0; } @@ -727,7 +727,7 @@ connectNoDelay(PGconn *conn) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not set socket to TCP no delay mode: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); return 0; } @@ -750,7 +750,7 @@ connectFailureMessage(PGconn *conn, int errorno) "\tIs the server running locally and accepting\n" "\tconnections on Unix domain socket \"%s\"?\n" ), - strerror(errorno), + SOCK_STRERROR(errorno), conn->raddr.un.sun_path); else printfPQExpBuffer(&conn->errorMessage, @@ -759,7 +759,7 @@ connectFailureMessage(PGconn *conn, int errorno) "\tIs the server running on host %s and accepting\n" "\tTCP/IP connections on port %s?\n" ), - strerror(errorno), + SOCK_STRERROR(errorno), conn->pghost ? conn->pghost : (conn->pghostaddr @@ -882,7 +882,7 @@ connectDBStart(PGconn *conn) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not create socket: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); goto connect_errReturn; } @@ -914,7 +914,7 @@ connectDBStart(PGconn *conn) */ if (connect(conn->sock, &conn->raddr.sa, conn->raddr_len) < 0) { - if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == 0) + if (SOCK_ERRNO == EINPROGRESS || SOCK_ERRNO == EWOULDBLOCK || SOCK_ERRNO == 0) { /* * This is fine - we're in non-blocking mode, and the @@ -925,7 +925,7 @@ connectDBStart(PGconn *conn) else { /* Something's gone wrong */ - connectFailureMessage(conn, errno); + connectFailureMessage(conn, SOCK_ERRNO); goto connect_errReturn; } } @@ -945,7 +945,7 @@ connectDBStart(PGconn *conn) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not send SSL negotiation packet: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); goto connect_errReturn; } /* Now receive the postmasters response */ @@ -953,7 +953,7 @@ connectDBStart(PGconn *conn) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not receive server response to SSL negotiation packet: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); goto connect_errReturn; } if (SSLok == 'S') @@ -1203,7 +1203,7 @@ keep_going: /* We will come back to here until there { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not get socket error status: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); goto error_return; } else if (optval != 0) @@ -1223,7 +1223,7 @@ keep_going: /* We will come back to here until there { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not get client address from socket: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); goto error_return; } @@ -1262,7 +1262,7 @@ keep_going: /* We will come back to here until there { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not send startup packet: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); goto error_return; } @@ -2097,7 +2097,7 @@ PQresetPoll(PGconn *conn) int PQrequestCancel(PGconn *conn) { - int save_errno = errno; + int save_errno = SOCK_ERRNO; int tmpsock = -1; struct { @@ -2169,7 +2169,7 @@ PQrequestCancel(PGconn *conn) return TRUE; cancel_errReturn: - strcat(conn->errorMessage.data, strerror(errno)); + strcat(conn->errorMessage.data, SOCK_STRERROR(SOCK_ERRNO)); strcat(conn->errorMessage.data, "\n"); conn->errorMessage.len = strlen(conn->errorMessage.data); if (tmpsock >= 0) diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 8fd0a5c8b6..d02b74490e 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.107 2001/08/17 15:11:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.108 2001/08/21 20:39:53 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2038,10 +2038,6 @@ PQoidStatus(const PGresult *res) return buf; } -#ifdef WIN32 /* need to get at normal errno here */ -#undef errno -#endif - /* PQoidValue - a perhaps preferable form of the above which just returns @@ -2056,7 +2052,11 @@ PQoidValue(const PGresult *res) if (!res || !res->cmdStatus || strncmp(res->cmdStatus, "INSERT ", 7) != 0) return InvalidOid; +#ifdef WIN32 + SetLastError(0); +#else errno = 0; +#endif result = strtoul(res->cmdStatus + 7, &endptr, 10); if (!endptr || (*endptr != ' ' && *endptr != '\0') || errno == ERANGE) @@ -2065,9 +2065,6 @@ PQoidValue(const PGresult *res) return (Oid) result; } -#ifdef WIN32 /* back to socket errno */ -#define errno WSAGetLastError() -#endif /* PQcmdTuples - diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c index 3ec1b4f2cf..873095ce99 100644 --- a/src/interfaces/libpq/fe-lobj.c +++ b/src/interfaces/libpq/fe-lobj.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.37 2001/08/17 15:11:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.38 2001/08/21 20:39:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -30,12 +30,6 @@ #include "libpq/libpq-fs.h" /* must come after sys/stat.h */ - -#ifdef WIN32 /* need to use normal errno in this file */ -#undef errno -#endif - - #define LO_BUFSIZE 8192 static int lo_initialize(PGconn *conn); diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 4fb2157836..81af3be753 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -25,7 +25,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.53 2001/08/17 15:11:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.54 2001/08/21 20:39:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -347,13 +347,13 @@ retry: if (select(conn->sock + 1, &input_mask, (fd_set *) NULL, (fd_set *) NULL, &timeout) < 0) { - if (errno == EINTR) + if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry; printfPQExpBuffer(&conn->errorMessage, libpq_gettext("select() failed: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); return -1; } @@ -381,13 +381,13 @@ retry: if (select(conn->sock + 1, (fd_set *) NULL, &input_mask, (fd_set *) NULL, &timeout) < 0) { - if (errno == EINTR) + if (SOCK_ERRNO == EINTR) /* Interrupted system call - we'll just try again */ goto retry; printfPQExpBuffer(&conn->errorMessage, libpq_gettext("select() failed: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); return -1; } return FD_ISSET(conn->sock, &input_mask) ? 1 : 0; @@ -467,25 +467,25 @@ tryAgain: conn->inBufSize - conn->inEnd, 0); if (nread < 0) { - if (errno == EINTR) + if (SOCK_ERRNO == EINTR) goto tryAgain; /* Some systems return EAGAIN/EWOULDBLOCK for no data */ #ifdef EAGAIN - if (errno == EAGAIN) + if (SOCK_ERRNO == EAGAIN) return someread; #endif #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) - if (errno == EWOULDBLOCK) + if (SOCK_ERRNO == EWOULDBLOCK) return someread; #endif /* We might get ECONNRESET here if using TCP and backend died */ #ifdef ECONNRESET - if (errno == ECONNRESET) + if (SOCK_ERRNO == ECONNRESET) goto definitelyFailed; #endif printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not receive data from server: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); return -1; } if (nread > 0) @@ -553,25 +553,25 @@ tryAgain2: conn->inBufSize - conn->inEnd, 0); if (nread < 0) { - if (errno == EINTR) + if (SOCK_ERRNO == EINTR) goto tryAgain2; /* Some systems return EAGAIN/EWOULDBLOCK for no data */ #ifdef EAGAIN - if (errno == EAGAIN) + if (SOCK_ERRNO == EAGAIN) return 0; #endif #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) - if (errno == EWOULDBLOCK) + if (SOCK_ERRNO == EWOULDBLOCK) return 0; #endif /* We might get ECONNRESET here if using TCP and backend died */ #ifdef ECONNRESET - if (errno == ECONNRESET) + if (SOCK_ERRNO == ECONNRESET) goto definitelyFailed; #endif printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not receive data from server: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); return -1; } if (nread > 0) @@ -653,7 +653,7 @@ pqFlush(PGconn *conn) * EPIPE or ECONNRESET, assume we've lost the backend * connection permanently. */ - switch (errno) + switch (SOCK_ERRNO) { #ifdef EAGAIN case EAGAIN: @@ -689,7 +689,7 @@ pqFlush(PGconn *conn) default: printfPQExpBuffer(&conn->errorMessage, libpq_gettext("could not send data to server: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); /* We don't assume it's a fatal error... */ return EOF; } @@ -772,11 +772,11 @@ retry: if (select(conn->sock + 1, &input_mask, &output_mask, &except_mask, (struct timeval *) NULL) < 0) { - if (errno == EINTR) + if (SOCK_ERRNO == EINTR) goto retry; printfPQExpBuffer(&conn->errorMessage, libpq_gettext("select() failed: %s\n"), - strerror(errno)); + SOCK_STRERROR(SOCK_ERRNO)); return EOF; } } @@ -851,3 +851,27 @@ libpq_gettext(const char *msgid) return dgettext("libpq", msgid); } #endif /* ENABLE_NLS */ + +#ifdef WIN32 +/* + * strerror replacement for windows: + */ +const char* +winsock_strerror(DWORD eno) +{ + if (!FormatMessage( + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM | /* always consider system table */ + ((netmsgModule != NULL) ? FORMAT_MESSAGE_FROM_HMODULE : 0), + netmsgModule, /* module to get message from (NULL == system) */ + eno, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + winsock_strerror_buf,sizeof(winsock_strerror_buf)-1, + NULL + )){ + sprintf(winsock_strerror_buf,"Unknown socket error(%u)",eno); + } + winsock_strerror_buf[sizeof(winsock_strerror_buf)-1]='\0'; + return winsock_strerror_buf; +} +#endif diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h index 95279a133a..79166533e9 100644 --- a/src/interfaces/libpq/libpq-fe.h +++ b/src/interfaces/libpq/libpq-fe.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: libpq-fe.h,v 1.71 2001/03/22 04:01:27 momjian Exp $ + * $Id: libpq-fe.h,v 1.72 2001/08/21 20:39:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -21,10 +21,21 @@ extern "C" #endif #include + +#ifdef WIN32 + #define SOCK_ERRNO (WSAGetLastError ()) + #define SOCK_STRERROR winsock_strerror +#else + #define SOCK_ERRNO errno + #define SOCK_STRERROR strerror +#endif + + /* postgres_ext.h defines the backend's externally visible types, * such as Oid. */ #include "postgres_ext.h" + #ifdef USE_SSL #include #endif diff --git a/src/interfaces/libpq/libpqdll.c b/src/interfaces/libpq/libpqdll.c index f0241acf78..1e7d647937 100644 --- a/src/interfaces/libpq/libpqdll.c +++ b/src/interfaces/libpq/libpqdll.c @@ -1,6 +1,7 @@ #define WIN32_LEAN_AND_MEAN #include #include +#include "win32.h" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, @@ -20,8 +21,13 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, */ return FALSE; } + if (netmsgModule == NULL){ + netmsgModule=LoadLibraryEx("netmsg.dll",NULL,LOAD_LIBRARY_AS_DATAFILE); + } break; case DLL_PROCESS_DETACH: + if (netmsgModule != NULL) + FreeLibrary(netmsgModule); WSACleanup(); break; } diff --git a/src/interfaces/libpq/win32.h b/src/interfaces/libpq/win32.h index 38099b079e..2ba2d842a6 100644 --- a/src/interfaces/libpq/win32.h +++ b/src/interfaces/libpq/win32.h @@ -23,19 +23,17 @@ */ #define crypt(a,b) (a) -/* - * Most of libpq uses "errno" to access error conditions from socket calls, - * so on Windows we want to redirect those usages to WSAGetLastError(). - * Rather than #ifdef'ing every single place that has "errno", hack it up - * with a macro instead. But there are a few places that do need to touch - * the regular errno variable. For them, we #undef and then redefine errno. - */ - -#define errno WSAGetLastError() - #undef EAGAIN /* doesn't apply on sockets */ #undef EINTR #define EINTR WSAEINTR #define EWOULDBLOCK WSAEWOULDBLOCK #define ECONNRESET WSAECONNRESET #define EINPROGRESS WSAEINPROGRESS + +/* + * Windows network messaging stuff: + */ +static HINSTANCE netmsgModule = NULL; + +static char winsock_strerror_buf[512]; +const char* winsock_strerror(DWORD eno);