From eaeb9cdc97f84be6ac910c555686742b7942cc53 Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Tue, 29 Apr 2008 22:13:08 -0400 Subject: [PATCH] Fully fix build on Cygwin. 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 | 6 ----- src/compat.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++----- src/compat.h | 13 ++++++++++- 3 files changed, 68 insertions(+), 13 deletions(-) diff --git a/src/common.h b/src/common.h index f8e4de5..37f8f4b 100644 --- a/src/common.h +++ b/src/common.h @@ -24,12 +24,6 @@ #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 diff --git a/src/compat.c b/src/compat.c index 65ffada..9110537 100644 --- a/src/compat.c +++ b/src/compat.c @@ -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 diff --git a/src/compat.h b/src/compat.h index 66a1fd8..bf4cb2e 100644 --- a/src/compat.h +++ b/src/compat.h @@ -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 -- 2.20.1