Fully fix build on Cygwin.
authorMichael Poole <mdpoole@troilus.org>
Wed, 30 Apr 2008 02:13:08 +0000 (22:13 -0400)
committerMichael Poole <mdpoole@troilus.org>
Wed, 30 Apr 2008 02:13:08 +0000 (22:13 -0400)
src/common.h (localtime_r): Do not declare in this file.
src/compat.h (localtime_r): Fix conditional definition of localtime_r().
  (EAI_*): Define getaddrinfo()/getnameinfo() error codes if needed.
src/compat.c (getaddrinfo): Return errors by macro.
  (getnameinfo): Implement a simple version of this function.

src/common.h
src/compat.c
src/compat.h

index f8e4de5884d0e100cfd54009f320a61a537ebfdd..37f8f4be340f65ff7f956f20e1a63f65629e9489 100644 (file)
 #include "compat.h"
 #include "proto.h"
 
-#if !defined(HAVE_LOCALTIME_R) && !defined(__CYGWIN__)
-extern struct tm *localtime_r(const time_t *clock, struct tm *res);
-#elif defined(__CYGWIN__)
-# define localtime_r(clock, res) memcpy(res, localtime(clock), sizeof(struct tm));
-#endif
-
 #ifndef true
 #define true 1
 #endif
index 65ffada5f963e1a2fd99feb4f530cdee838090fe..91105371dc16e9ca81bac416eabf6ee0e9722a22 100644 (file)
@@ -363,7 +363,7 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
     struct sockaddr_in sin;
 
     if (hints && hints->ai_family != AF_INET)
-        return 1;
+        return EAI_FAMILY;
     memset(&sin, 0, sizeof(sin));
     sin.sin_family = AF_INET;
 
@@ -371,17 +371,17 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
         if (hints && hints->ai_flags & AI_NUMERICHOST) {
 #if HAVE_INET_ATON
             if (!inet_aton(node, &sin.sin_addr))
-                return 2;
+                return EAI_NONAME;
 #else
             sin.sin_addr.s_addr = inet_addr(node);
             if (sin.sin_addr.s_addr == INADDR_NONE)
-                return 2;
+                return EAI_NONAME;
 #endif
         } else {
             struct hostent *he;
             he = gethostbyname(node);
             if (!he)
-                return 3;
+                return EAI_NONAME;
             memcpy(&sin.sin_addr, he->h_addr, he->h_length);
         }
     } else if (hints && hints->ai_flags & AI_PASSIVE) {
@@ -393,7 +393,7 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi
     if (!service)
         sin.sin_port = ntohs(0);
     else if (!(sin.sin_port = ntohs(atoi(service))))
-        return 4;
+        return EAI_NONAME;
 
     *res = calloc(1, sizeof(**res) + sizeof(sin));
     (*res)->ai_family = sin.sin_family;
@@ -467,6 +467,56 @@ int getnameinfo(const struct sockaddr *sa, socklen_t salen,
                 char *host, size_t hostlen,
                 char *serv, size_t servlen, int flags)
 {
-    /* TODO: implement fallback getnameinfo() */
+    if (sa->sa_family == AF_INET) {
+       const struct sockaddr_in *sin;
+       int tmp;
+
+       /* This comparison is a bit screwy looking, but socklen_t is
+        * signed on some platforms and unsigned on others, so gcc
+        * will complain if we use "salen < 0".
+        */
+       if (salen < 1 || (size_t)salen < sizeof(*sin))
+           return EAI_FAMILY;
+       sin = (const struct sockaddr_in *)sa;
+       tmp = snprintf(serv, servlen, "%d", ntohs(sin->sin_port));
+       if (tmp < 1 || (size_t)tmp >= servlen)
+           return EAI_OVERFLOW;
+       if (0 == (flags & NI_NUMERICHOST)) {
+           struct hostent *he;
+
+           /* Try to get host entry by address.
+            * The first argument should be void *, but Cygwin is
+            * apparently wandering around the pre-C89 era.
+            */
+           he = gethostbyaddr((const char*)&sin->sin_addr, sa->sa_family, SOCK_STREAM);
+           if (he != NULL) {
+               if (servlen <= strlen(he->h_name))
+                   return EAI_OVERFLOW;
+               safestrncpy(serv, he->h_name, servlen);
+               return 0;
+           }
+
+           /* If we couldn't, why did we fail, and what should we do? */
+           switch (h_errno) {
+           case NO_RECOVERY:
+               return EAI_FAIL;
+           case TRY_AGAIN:
+               return EAI_AGAIN;
+           default:
+               /* Fall through and out to inet_ntop() path. */
+               break;
+           }
+       }
+
+       /* Try to get numeric representation of address. */
+       if (inet_ntop(sa->sa_family, &sin->sin_addr, host, hostlen) != NULL)
+           return 0;
+       else if (errno == ENOSPC)
+           return EAI_OVERFLOW;
+       else
+           return EAI_FAIL;
+    }
+    else
+       return EAI_FAMILY;
 }
 #endif
index 66a1fd88fe4532d7563e3dad9390fe1661478098..bf4cb2e298df68aa1892f692beec3739f1058692 100644 (file)
@@ -97,7 +97,7 @@ struct timezone;
 extern int gettimeofday(struct timeval * tv, struct timezone * tz);
 #endif
 
-#ifndef HAVE_GETLOCALTIME_R
+#ifndef HAVE_LOCALTIME_R
 extern struct tm *localtime_r(const time_t *timep, struct tm *result);
 #endif
 
@@ -147,9 +147,20 @@ void freeaddrinfo(struct addrinfo *res);
 const char *gai_strerror(int errcode);
 #endif
 
+#ifndef EAI_FAMILY
+# define EAI_FAMILY -1
+# define EAI_NONAME -2
+# define EAI_OVERFLOW -3
+# define EAI_FAIL -4
+# define EAI_AGAIN -5
+#endif
+
 #ifndef HAVE_GETNAMEINFO
+
 #define NI_NUMERICHOST 1
+
 int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
+
 #endif
 
 #ifndef EINPROGRESS