diff -u3 -H -B -w CVS-latest/lib/connect.c lib/connect.c --- CVS-latest/lib/connect.c Tue Mar 23 16:48:27 2004 +++ lib/connect.c Tue Mar 23 17:15:20 2004 @@ -86,6 +86,7 @@ #include "urldata.h" #include "sendf.h" #include "if2ip.h" +#include "curl_strerror.h" #include "connect.h" /* The last #include file should be: */ @@ -295,7 +296,7 @@ if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, data->set.device, strlen(data->set.device)+1) != 0) { /* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n", - sockfd, data->set.device, strerror(Curl_ourerrno())); */ + sockfd, data->set.device, Curl_strerror(Curl_ourerrno())); */ infof(data, "SO_BINDTODEVICE %s failed\n", data->set.device); /* This is typically "errno 1, error: Operation not permitted" if @@ -353,36 +354,7 @@ } #endif if(!bindworked) { - int err = Curl_ourerrno(); - switch(err) { - case EBADF: - failf(data, "Invalid descriptor: %d", err); - break; - case EINVAL: - failf(data, "Invalid request: %d", err); - break; - case EACCES: - failf(data, "Address is protected, user not superuser: %d", err); - break; - case ENOTSOCK: - failf(data, - "Argument is a descriptor for a file, not a socket: %d", - err); - break; - case EFAULT: - failf(data, "Inaccessable memory error: %d", err); - break; - case ENAMETOOLONG: - failf(data, "Address too long: %d", err); - break; - case ENOMEM: - failf(data, "Insufficient kernel memory was available: %d", err); - break; - default: - failf(data, "errno %d", err); - break; - } /* end of switch(err) */ - + failf(data, Curl_strerror(conn,Curl_ourerrno())); return CURLE_HTTP_PORT_FAILED; } /* end of else */ @@ -489,8 +461,8 @@ } else if(1 != rc) { int error = Curl_ourerrno(); - failf(data, "Failed connect to %s:%d, errno: %d", - conn->hostname, conn->port, error); + failf(data, "Failed connect to %s:%d; %s", + conn->hostname, conn->port, Curl_strerror(conn,error)); return CURLE_COULDNT_CONNECT; } /* @@ -652,8 +624,8 @@ break; default: /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect to %s IP number %d: %d", - hostname, aliasindex+1, error); + failf(data, "Failed to connect to %s IP number %d: %s", + hostname, aliasindex+1, Curl_strerror(conn,error)); break; } } diff -u3 -H -B -w CVS-latest/lib/curl_strerror.c lib/curl_strerror.c --- CVS-latest/lib/curl_strerror.c Mon Mar 15 12:51:32 2004 +++ lib/curl_strerror.c Wed Mar 24 13:31:01 2004 @@ -21,6 +21,12 @@ ***************************************************************************/ #include +#include "setup.h" +#include +#include +#include + +#include "curl_strerror.h" const char * curl_easy_strerror(CURLcode error) @@ -293,4 +299,226 @@ } return "CURLSH unknown"; +} + +#if defined(WIN32) && !defined(__CYGWIN__) + +/* This function handles most / all (?) Winsock errors cURL is able to produce. + */ +static const char * +get_winsock_error (int err, char *buf, size_t len) +{ + char *p; + + switch (err) + { + case WSAEINTR: + p = "Call interrupted."; + break; + case WSAEBADF: + p = "Bad file"; + break; + case WSAEACCES: + p = "Bad access"; + break; + case WSAEFAULT: + p = "Bad argument"; + break; + case WSAEINVAL: + p = "Invalid arguments"; + break; + case WSAEMFILE: + p = "Out of file descriptors"; + break; + case WSAEWOULDBLOCK: + p = "Call would block"; + break; + case WSAEINPROGRESS: + case WSAEALREADY: + p = "Blocking call in progress"; + break; + case WSAENOTSOCK: + p = "Descriptor is not a socket."; + break; + case WSAEDESTADDRREQ: + p = "Need destination address"; + break; + case WSAEMSGSIZE: + p = "Bad message size"; + break; + case WSAEPROTOTYPE: + p = "Bad protocol"; + break; + case WSAENOPROTOOPT: + p = "Protocol option is unsupported"; + break; + case WSAEPROTONOSUPPORT: + p = "Protocol is unsupported"; + break; + case WSAESOCKTNOSUPPORT: + p = "Socket is unsupported"; + break; + case WSAEOPNOTSUPP: + p = "Operation not supported"; + break; + case WSAEAFNOSUPPORT: + p = "Address family not supported"; + break; + case WSAEPFNOSUPPORT: + p = "Protocol family not supported"; + break; + case WSAEADDRINUSE: + p = "Address already in use"; + break; + case WSAEADDRNOTAVAIL: + p = "Address not available"; + break; + case WSAENETDOWN: + p = "Network down"; + break; + case WSAENETUNREACH: + p = "Network unreachable"; + break; + case WSAENETRESET: + p = "Network has been reset"; + break; + case WSAECONNABORTED: + p = "Connection was aborted"; + break; + case WSAECONNRESET: + p = "Connection was reset"; + break; + case WSAENOBUFS: + p = "No buffer space"; + break; + case WSAEISCONN: + p = "Socket is already connected"; + break; + case WSAENOTCONN: + p = "Socket is not connected"; + break; + case WSAESHUTDOWN: + p = "Socket has been shut down"; + break; + case WSAETOOMANYREFS: + p = "Too many references"; + break; + case WSAETIMEDOUT: + p = "Timed out"; + break; + case WSAECONNREFUSED: + p = "Connection refused"; + break; + case WSAELOOP: + p = "Loop??"; + break; + case WSAENAMETOOLONG: + p = "Name too long"; + break; + case WSAEHOSTDOWN: + p = "Host down"; + break; + case WSAEHOSTUNREACH: + p = "Host unreachable"; + break; + case WSAENOTEMPTY: + p = "Not empty"; + break; + case WSAEPROCLIM: + p = "Process limit reached"; + break; + case WSAEUSERS: + p = "Too many users"; + break; + case WSAEDQUOT: + p = "Bad quota"; + break; + case WSAESTALE: + p = "Something is stale"; + break; + case WSAEREMOTE: + p = "Remote error"; + break; + case WSAEDISCON: + p = "Disconnected"; + break; + + /* Extended Winsock errors */ + case WSASYSNOTREADY: + p = "Winsock library is not ready"; + break; + case WSANOTINITIALISED: + p = "Winsock library not initalised"; + break; + case WSAVERNOTSUPPORTED: + p = "Winsock version not supported."; + break; + + /* getXbyY() errors (already handled in herrmsg): + * Authoritative Answer: Host not found */ + case WSAHOST_NOT_FOUND: + p = "Host not found"; + break; + + /* Non-Authoritative: Host not found, or SERVERFAIL */ + case WSATRY_AGAIN: + p = "Host not found, try again"; + break; + + /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ + case WSANO_RECOVERY: + p = "Unrecoverable error in call to nameserver"; + break; + + /* Valid name, no data record of requested type */ + case WSANO_DATA: + p = "No data record of requested type"; + break; + + default: + return NULL; + } + strncpy (buf, p, len); + buf [len-1] = '\0'; + return buf; +} +#endif /* WIN32 && !__CYGWIN__ */ + +/* + * Our thread-safe and smart strerror() replacement. + */ +const char *Curl_strerror (struct connectdata *conn, int err) +{ + char *buf, *p; + size_t max; + + if (!conn) + return ("No 'conn' data"); + + buf = conn->syserr_buf; + max = sizeof(conn->syserr_buf)-1; + *buf = '\0'; + if (err >= 0 && err < sys_nerr) { + /* These should be atomic and hopefully thread-safe */ +#ifdef HAVE_STRERROR_R + strerror_r (err, buf, max); /* this may set ERANGE! */ +#else + strncpy (buf, strerror(err), max); +#endif + *(buf+max) = '\0'; + } + else +#if defined(WIN32) && !defined(__CYGWIN__) + if (!get_winsock_error (err, buf, max) && + !FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, buf, max, NULL)) +#endif + snprintf (buf, max, "Unknown error %d (%#x)", err, err); + + /* strip trailing '\r\n' or '\n'. */ + if ((p = strrchr(buf,'\n')) != NULL && (p - buf) >= 2) + *p = '\0'; + if ((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1) + *p = '\0'; + return buf; } diff -u3 -H -B -w CVS-latest/lib/ftp.c lib/ftp.c --- CVS-latest/lib/ftp.c Wed Mar 17 13:46:45 2004 +++ lib/ftp.c Tue Mar 23 17:02:47 2004 @@ -91,6 +91,7 @@ #include "strequal.h" #include "ssluse.h" #include "connect.h" +#include "curl_strerror.h" #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) #include "inet_ntoa_r.h" @@ -1138,6 +1139,7 @@ const char *mode[] = { "EPRT", "LPRT", "PORT", NULL }; char **modep; int rc; + int error; /* * we should use Curl_if2ip? given pickiness of recent ftpd, @@ -1172,6 +1174,7 @@ } portsock = CURL_SOCKET_BAD; + error = 0; for (ai = res; ai; ai = ai->ai_next) { /* * Workaround for AIX5 getaddrinfo() problem (it doesn't set ai_socktype): @@ -1180,16 +1183,20 @@ ai->ai_socktype = hints.ai_socktype; portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (portsock == CURL_SOCKET_BAD) + if (portsock == CURL_SOCKET_BAD) { + error = Curl_ourerrno(); continue; + } if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) { + error = Curl_ourerrno(); sclose(portsock); portsock = CURL_SOCKET_BAD; continue; } if (listen(portsock, 1) < 0) { + error = Curl_ourerrno(); sclose(portsock); portsock = CURL_SOCKET_BAD; continue; @@ -1199,13 +1206,13 @@ } freeaddrinfo(res); if (portsock == CURL_SOCKET_BAD) { - failf(data, "%s", strerror(errno)); + failf(data, "%s", Curl_strerror(conn,error)); return CURLE_FTP_PORT_FAILED; } sslen = sizeof(ss); if (getsockname(portsock, sa, &sslen) < 0) { - failf(data, "%s", strerror(errno)); + failf(data, "%s", Curl_strerror(conn,Curl_ourerrno())); return CURLE_FTP_PORT_FAILED; } diff -u3 -H -B -w CVS-latest/lib/urldata.h lib/urldata.h --- CVS-latest/lib/urldata.h Tue Mar 23 17:01:31 2004 +++ lib/urldata.h Tue Mar 23 17:13:05 2004 @@ -572,6 +572,8 @@ int sockerror; /* errno stored by Curl_read() if the underlying layer returns error */ + char syserr_buf [256]; /* buffer for Curl_strerror() */ + #if defined(USE_ARES) || defined(USE_THREADING_GETHOSTBYNAME) /* data used for the asynch name resolve callback */ struct Curl_async async;