From 059b57677c14ac832249193042f0cf61e9c15ff2 Mon Sep 17 00:00:00 2001
From: Yang Tse <yangsita@gmail.com>
Date: Fri, 16 Feb 2007 15:04:44 +0000
Subject: [PATCH] use macros ERRNO, SET_ERRNO(), SOCKERRNO and SET_SOCKERRNO()
 for errno handling

---
 ares/adig.c          |  2 +-
 ares/ares_init.c     | 21 +++++++++++++--------
 ares/ares_process.c  | 20 +++++++-------------
 ares/inet_net_pton.c | 24 +++++++++++++++++-------
 ares/inet_ntop.c     | 11 ++++++++---
 ares/windows_port.c  |  2 +-
 6 files changed, 47 insertions(+), 33 deletions(-)

diff --git a/ares/adig.c b/ares/adig.c
index 6a23c51381..32e07217d5 100644
--- a/ares/adig.c
+++ b/ares/adig.c
@@ -289,7 +289,7 @@ int main(int argc, char **argv)
         break;
       tvp = ares_timeout(channel, NULL, &tv);
       count = select(nfds, &read_fds, &write_fds, NULL, tvp);
-      if (count < 0 && errno != EINVAL)
+      if (count < 0 && SOCKERRNO != EINVAL)
         {
           perror("select");
           return 1;
diff --git a/ares/ares_init.c b/ares/ares_init.c
index b0fa50f2b2..5268745d0b 100644
--- a/ares/ares_init.c
+++ b/ares/ares_init.c
@@ -610,6 +610,7 @@ DhcpNameServer
     char *p;
     FILE *fp;
     int linesize;
+    int error;
 
     fp = fopen(PATH_RESOLV_CONF, "r");
     if (fp) {
@@ -635,13 +636,14 @@ DhcpNameServer
       fclose(fp);
     }
     else {
-      switch(errno) {
+      error = ERRNO;
+      switch(error) {
       case ENOENT:
         status = ARES_EOF;
         break;
       default:
         DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
-                       errno, strerror(errno)));
+                       error, strerror(error)));
         DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF));
         status = ARES_EFILE;
       }
@@ -659,13 +661,14 @@ DhcpNameServer
         fclose(fp);
       }
       else {
-        switch(errno) {
+        error = ERRNO;
+        switch(error) {
         case ENOENT:
           status = ARES_EOF;
           break;
         default:
           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
-                         errno, strerror(errno)));
+                         error, strerror(error)));
           DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/nsswitch.conf"));
           status = ARES_EFILE;
         }
@@ -684,13 +687,14 @@ DhcpNameServer
         fclose(fp);
       }
       else {
-        switch(errno) {
+        error = ERRNO;
+        switch(error) {
         case ENOENT:
           status = ARES_EOF;
           break;
         default:
           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
-                         errno, strerror(errno)));
+                         error, strerror(error)));
           DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/host.conf"));
           status = ARES_EFILE;
         }
@@ -709,13 +713,14 @@ DhcpNameServer
         fclose(fp);
       }
       else {
-        switch(errno) {
+        error = ERRNO;
+        switch(error) {
         case ENOENT:
           status = ARES_EOF;
           break;
         default:
           DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n",
-                         errno, strerror(errno)));
+                         error, strerror(error)));
           DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf"));
           status = ARES_EFILE;
         }
diff --git a/ares/ares_process.c b/ares/ares_process.c
index f6669ca989..480948ebef 100644
--- a/ares/ares_process.c
+++ b/ares/ares_process.c
@@ -59,12 +59,6 @@
 #define TRUE 1
 #endif
 
-#ifdef USE_WINSOCK
-#define GET_ERRNO()  WSAGetLastError()
-#else
-#define GET_ERRNO()  errno
-#endif
-
 static int try_again(int errnum);
 static void write_tcp_data(ares_channel channel, fd_set *write_fds,
                            time_t now);
@@ -97,7 +91,7 @@ void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
   process_timeouts(channel, now);
 }
 
-/* Return 1 if the specified errno describes a readiness error, or 0
+/* Return 1 if the specified error number describes a readiness error, or 0
  * otherwise. This is mostly for HP-UX, which could return EAGAIN or
  * EWOULDBLOCK. See this man page
  *
@@ -164,7 +158,7 @@ static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
           free(vec);
           if (wcount < 0)
             {
-              if (!try_again(GET_ERRNO()))
+              if (!try_again(SOCKERRNO))
                   handle_error(channel, i, now);
               continue;
             }
@@ -200,7 +194,7 @@ static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
           scount = swrite(server->tcp_socket, sendreq->data, sendreq->len);
           if (scount < 0)
             {
-              if (!try_again(GET_ERRNO()))
+              if (!try_again(SOCKERRNO))
                   handle_error(channel, i, now);
               continue;
             }
@@ -253,7 +247,7 @@ static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now)
                         2 - server->tcp_lenbuf_pos);
           if (count <= 0)
             {
-              if (!(count == -1 && try_again(GET_ERRNO())))
+              if (!(count == -1 && try_again(SOCKERRNO)))
                   handle_error(channel, i, now);
               continue;
             }
@@ -280,7 +274,7 @@ static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now)
                         server->tcp_length - server->tcp_buffer_pos);
           if (count <= 0)
             {
-              if (!(count == -1 && try_again(GET_ERRNO())))
+              if (!(count == -1 && try_again(SOCKERRNO)))
                   handle_error(channel, i, now);
               continue;
             }
@@ -322,7 +316,7 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds,
         continue;
 
       count = sread(server->udp_socket, buf, sizeof(buf));
-      if (count == -1 && try_again(GET_ERRNO()))
+      if (count == -1 && try_again(SOCKERRNO))
         continue;
       else if (count <= 0)
         handle_error(channel, i, now);
@@ -615,7 +609,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server)
   sockin.sin_addr = server->addr;
   sockin.sin_port = (unsigned short)(channel->tcp_port & 0xffff);
   if (connect(s, (struct sockaddr *) &sockin, sizeof(sockin)) == -1) {
-    int err = GET_ERRNO();
+    int err = SOCKERRNO;
 
     if (err != EINPROGRESS && err != EWOULDBLOCK) {
       closesocket(s);
diff --git a/ares/inet_net_pton.c b/ares/inet_net_pton.c
index 49bac69a68..af941bf6ba 100644
--- a/ares/inet_net_pton.c
+++ b/ares/inet_net_pton.c
@@ -66,6 +66,11 @@
  * note:
  *      network byte order assumed.  this means 192.5.5.240/28 has
  *      0b11110000 in its fourth octet.
+ * note:
+ *      On Windows we store the error in the thread errno, not
+ *      in the winsock error code. This is to avoid loosing the
+ *      actual last winsock error. So use macro ERRNO to fetch the
+ *      errno this funtion sets when returning (-1), not SOCKERRNO.
  * author:
  *      Paul Vixie (ISC), June 1996
  */
@@ -186,11 +191,11 @@ inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
   return (bits);
 
   enoent:
-  errno = ENOENT;
+  SET_ERRNO(ENOENT);
   return (-1);
 
   emsgsize:
-  errno = EMSGSIZE;
+  SET_ERRNO(EMSGSIZE);
   return (-1);
 }
 
@@ -381,11 +386,11 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
   return (bits);
 
   enoent:
-  errno = ENOENT;
+  SET_ERRNO(ENOENT);
   return (-1);
 
   emsgsize:
-  errno = EMSGSIZE;
+  SET_ERRNO(EMSGSIZE);
   return (-1);
 }
 
@@ -399,6 +404,11 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
  *      number of bits, either imputed classfully or specified with /CIDR,
  *      or -1 if some failure occurred (check errno).  ENOENT means it was
  *      not a valid network specification.
+ * note:
+ *      On Windows we store the error in the thread errno, not
+ *      in the winsock error code. This is to avoid loosing the
+ *      actual last winsock error. So use macro ERRNO to fetch the
+ *      errno this funtion sets when returning (-1), not SOCKERRNO.
  * author:
  *      Paul Vixie (ISC), June 1996
  */
@@ -411,7 +421,7 @@ ares_inet_net_pton(int af, const char *src, void *dst, size_t size)
   case AF_INET6:
     return (inet_net_pton_ipv6(src, dst, size));
   default:
-    errno = EAFNOSUPPORT;
+    SET_ERRNO(EAFNOSUPPORT);
     return (-1);
   }
 }
@@ -429,11 +439,11 @@ int ares_inet_pton(int af, const char *src, void *dst)
     size = sizeof(struct in6_addr);
   else
   {
-    errno = EAFNOSUPPORT;
+    SET_ERRNO(EAFNOSUPPORT);
     return -1;
   }
   result = ares_inet_net_pton(af, src, dst, size);
-  if (result == -1 && errno == ENOENT)
+  if (result == -1 && ERRNO == ENOENT)
     return 0;
   return (result > -1 ? 1 : -1);
 }
diff --git a/ares/inet_ntop.c b/ares/inet_ntop.c
index 097e7764e0..f076e06654 100644
--- a/ares/inet_ntop.c
+++ b/ares/inet_ntop.c
@@ -68,6 +68,11 @@ static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size);
  *     convert a network format address to presentation format.
  * return:
  *     pointer to presentation format address (`dst'), or NULL (see errno).
+ * note:
+ *      On Windows we store the error in the thread errno, not
+ *      in the winsock error code. This is to avoid loosing the
+ *      actual last winsock error. So use macro ERRNO to fetch the
+ *      errno this funtion sets when returning NULL, not SOCKERRNO.
  * author:
  *     Paul Vixie, 1996.
  */
@@ -81,7 +86,7 @@ ares_inet_ntop(int af, const void *src, char *dst, size_t size)
     case AF_INET6:
       return (inet_ntop6(src, dst, size));
     default:
-      errno = EAFNOSUPPORT;
+      SET_ERRNO(EAFNOSUPPORT);
       return (NULL);
     }
   /* NOTREACHED */
@@ -106,7 +111,7 @@ inet_ntop4(const unsigned char *src, char *dst, size_t size)
 
   if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size)
     {
-      errno = ENOSPC;
+      SET_ERRNO(ENOSPC);
       return (NULL);
     }
     strcpy(dst, tmp);
@@ -218,7 +223,7 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
    */
   if ((size_t)(tp - tmp) > size)
     {
-      errno = ENOSPC;
+      SET_ERRNO(ENOSPC);
       return (NULL);
     }
   strcpy(dst, tmp);
diff --git a/ares/windows_port.c b/ares/windows_port.c
index dabe0bcccd..d9c358e2f5 100644
--- a/ares/windows_port.c
+++ b/ares/windows_port.c
@@ -105,7 +105,7 @@ ares_writev (ares_socket_t s, const struct iovec *vector, size_t count)
   buffer = bp = (char*) alloca (bytes);
   if (!buffer)
   {
-    errno = ENOMEM;
+    SET_ERRNO(ENOMEM);
     return (-1);
   }