X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fcompat.c;h=08d7d39e3c2c91a66d2fb892acf6e9bcc4a9653b;hb=80d9ed728be4b02ac483f3339cbb184f6602d15b;hp=cc3132481cf376a3cdb1d2681039e0c93b70079c;hpb=6f22223d9d80a148babc60a6483dd50c74cce723;p=srvx.git diff --git a/src/compat.c b/src/compat.c index cc31324..08d7d39 100644 --- a/src/compat.c +++ b/src/compat.c @@ -16,7 +16,7 @@ #endif #if !defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) -extern int gettimeofday(struct timeval * tv, struct timezone * tz) +int gettimeofday(struct timeval * tv, struct timezone * tz) { if (!tv) { @@ -35,8 +35,8 @@ extern int gettimeofday(struct timeval * tv, struct timezone * tz) } #endif -#ifndef HAVE_GETLOCALTIME_R -extern struct tm *localtime_r(const time_t *timep, struct tm *result) +#if !defined(HAVE_LOCALTIME_R) && defined(HAVE_LOCALTIME) +struct tm *localtime_r(const time_t *timep, struct tm *result) { memcpy(result, localtime(timep), sizeof(*result)); return result; @@ -44,7 +44,7 @@ extern struct tm *localtime_r(const time_t *timep, struct tm *result) #endif #ifndef HAVE_MEMCPY -extern void * memcpy(void * dest, void const * src, unsigned long n) +void * memcpy(void * dest, void const * src, unsigned long n) { /* very slow, your fault for not having memcpy()*/ unsigned char * td=dest; @@ -62,7 +62,7 @@ extern void * memcpy(void * dest, void const * src, unsigned long n) #ifndef HAVE_MEMSET /* very slow, deal with it */ -extern void * memset(void * dest, int c, unsigned long n) +void * memset(void * dest, int c, unsigned long n) { unsigned char * temp=dest; unsigned long i; @@ -77,7 +77,7 @@ extern void * memset(void * dest, int c, unsigned long n) #endif #ifndef HAVE_STRDUP -extern char * strdup(char const * str) +char * strdup(char const * str) { char * out; @@ -91,265 +91,265 @@ extern char * strdup(char const * str) #endif #ifndef HAVE_STRERROR -extern char const * strerror(int errornum) +char const * strerror(int errornum) { if (errornum==0) - return "No error"; + return "No error"; #ifdef EPERM if (errornum==EPERM) - return "Operation not permitted"; + return "Operation not permitted"; #endif #ifdef ENOENT if (errornum==ENOENT) - return "No such file or directory"; + return "No such file or directory"; #endif #ifdef ESRCH if (errornum==ESRCH) - return "No such process"; + return "No such process"; #endif #ifdef EINTR if (errornum==EINTR) - return "Interrupted system call"; + return "Interrupted system call"; #endif #ifdef EIO if (errornum==EIO) - return "I/O error"; + return "I/O error"; #endif #ifdef ENXIO if (errornum==EIO) - return "No such device or address"; + return "No such device or address"; #endif #ifdef EBADF if (errornum==EBADF) - return "Bad file number"; + return "Bad file number"; #endif #ifdef EAGAIN if (errornum==EAGAIN) - return "Try again"; + return "Try again"; #endif #ifdef ENOMEM if (errornum==ENOMEM) - return "Out of memory"; + return "Out of memory"; #endif #ifdef EACCES if (errornum==EACCES) - return "Permission denied"; + return "Permission denied"; #endif #ifdef EFAULT if (errornum==EFAULT) - return "Bad address"; + return "Bad address"; #endif #ifdef EBUSY if (errornum==EBUSY) - return "Device or resource busy"; + return "Device or resource busy"; #endif #ifdef EEXIST if (errornum==EEXIST) - return "File exists"; + return "File exists"; #endif #ifdef EXDEV if (errornum==EXDEV) - return "Cross-device link"; + return "Cross-device link"; #endif #ifdef EDEADLK if (errornum==EXDEV) - return "Resource deadlock would occur"; + return "Resource deadlock would occur"; #endif #ifdef EDEADLOCK if (errornum==EDEADLOCK) - return "Resource deadlock would occur"; + return "Resource deadlock would occur"; #endif #ifdef ENODEV if (errornum==ENODEV) - return "No such device"; + return "No such device"; #endif #ifdef ENOTDIR if (errornum==ENOTDIR) - return "Not a directory"; + return "Not a directory"; #endif #ifdef EISDIR if (errornum==EISDIR) - return "Is a directory"; + return "Is a directory"; #endif #ifdef EINVAL if (errornum==EINVAL) - return "Invalid argument"; + return "Invalid argument"; #endif #ifdef ENFILE if (errornum==ENFILE) - return "Too many open files in system"; + return "Too many open files in system"; #endif #ifdef EMFILE if (errornum==EMFILE) - return "Too many open files"; + return "Too many open files"; #endif #ifdef ENOTTY if (errornum==ENOTTY) - return "Not a typewriter"; + return "Not a typewriter"; #endif #ifdef ETXTBSY if (errornum==ETXTBSY) - return "Text file busy"; + return "Text file busy"; #endif #ifdef EFBIG if (errornum==EFBIG) - return "File too large"; + return "File too large"; #endif #ifdef ENOSPC if (errornum==ENOSPC) - return "No space left on device"; + return "No space left on device"; #endif #ifdef ESPIPE if (errornum==ESPIPE) - return "Illegal seek"; + return "Illegal seek"; #endif #ifdef EROFS if (errornum==EROFS) - return "Read-only file system"; + return "Read-only file system"; #endif #ifdef EMLINK if (errornum==EMLINK) - return "Too many links"; + return "Too many links"; #endif #ifdef EPIPE if (errornum==EPIPE) - return "Broken pipe"; + return "Broken pipe"; #endif #ifdef EDOM if (errornum==EDOM) - return "Math argument out of domain of func"; + return "Math argument out of domain of func"; #endif #ifdef ERANGE if (errornum==ERANGE) - return "Math result not representable"; + return "Math result not representable"; #endif #ifdef ENAMETOOLONG if (errornum==ENAMETOOLONG) - return "File name too long"; + return "File name too long"; #endif #ifdef ENOLCK if (errornum==ENOLCK) - return "No record locks avaliable"; + return "No record locks avaliable"; #endif #ifdef ENOSYS if (errornum==ENOSYS) - return "Function not implemented"; + return "Function not implemented"; #endif #ifdef ENOTEMPTY if (errornum==ENOTEMPTY) - return "Directory not empty"; + return "Directory not empty"; #endif #ifdef ELOOP if (errornum==ELOOP) - return "Too many symbolic links encountered"; + return "Too many symbolic links encountered"; #endif #ifdef EHOSTDOWN if (errornum==EHOSTDOWN) - return "Host is down"; + return "Host is down"; #endif #ifdef EHOSTUNREACH if (errornum==EHOSTUNREACH) - return "No route to host"; + return "No route to host"; #endif #ifdef EALREADY if (errornum==EALREADY) - return "Operation already in progress"; + return "Operation already in progress"; #endif #ifdef EINPROGRESS if (errornum==EINPROGRESS) - return "Operation now in progress"; + return "Operation now in progress"; #endif #ifdef ESTALE if (errornum==ESTALE) - return "Stale NFS filehandle"; + return "Stale NFS filehandle"; #endif #ifdef EDQUOT if (errornum==EDQUOT) - return "Quota exceeded"; + return "Quota exceeded"; #endif #ifdef EWOULDBLOCK if (errornum==EWOULDBLOCK) - return "Operation would block"; + return "Operation would block"; #endif #ifdef ECOMM if (errornum==ECOMM) - return "Communication error on send"; + return "Communication error on send"; #endif #ifdef EPROTO if (errornum==EPROTO) - return "Protocol error"; + return "Protocol error"; #endif #ifdef EPROTONOSUPPORT if (errornum==EPROTONOSUPPORT) - return "Protocol not supported"; + return "Protocol not supported"; #endif #ifdef ESOCKTNOSUPPORT if (errornum==ESOCKTNOSUPPORT) - return "Socket type not supported"; + return "Socket type not supported"; #endif #ifdef ESOCKTNOSUPPORT if (errornum==EOPNOTSUPP) - return "Operation not supported"; + return "Operation not supported"; #endif #ifdef EPFNOSUPPORT if (errornum==EPFNOSUPPORT) - return "Protocol family not supported"; + return "Protocol family not supported"; #endif #ifdef EAFNOSUPPORT if (errornum==EAFNOSUPPORT) - return "Address family not supported by protocol family"; + return "Address family not supported by protocol family"; #endif #ifdef EADDRINUSE if (errornum==EADDRINUSE) - return "Address already in use"; + return "Address already in use"; #endif #ifdef EADDRNOTAVAIL if (errornum==EADDRNOTAVAIL) - return "Cannot assign requested address"; + return "Cannot assign requested address"; #endif #ifdef ENETDOWN if (errornum==ENETDOWN) - return "Network is down"; + return "Network is down"; #endif #ifdef ENETUNREACH if (errornum==ENETUNREACH) - return "Network is unreachable"; + return "Network is unreachable"; #endif #ifdef ENETRESET if (errornum==ENETRESET) - return "Network dropped connection on reset"; + return "Network dropped connection on reset"; #endif #ifdef ECONNABORTED if (errornum==ECONNABORTED) - return "Software caused connection abort"; + return "Software caused connection abort"; #endif #ifdef ECONNRESET if (errornum==ECONNRESET) - return " Connection reset by peer"; + return " Connection reset by peer"; #endif #ifdef ENOBUFS if (errornum==ENOBUFS) - return "No buffer space available"; + return "No buffer space available"; #endif #ifdef EISCONN if (errornum==EISCONN) - return "Socket is already connected"; + return "Socket is already connected"; #endif #ifdef ENOTCONN if (errornum==ENOTCONN) - return "Socket is not connected"; + return "Socket is not connected"; #endif #ifdef ESHUTDOWN if (errornum==ESHUTDOWN) - return " Cannot send after socket shutdown"; + return " Cannot send after socket shutdown"; #endif #ifdef ETIMEDOUT if (errornum==ETIMEDOUT) - return "Connection timed out"; + return "Connection timed out"; #endif #ifdef ECONNREFUSED if (errornum==ECONNREFUSED) - return "Connection refused"; + return "Connection refused"; #endif return "Unknown error"; } @@ -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; @@ -407,8 +407,6 @@ int getaddrinfo(const char *node, const char *service, const struct addrinfo *hi return 0; } -/* TODO: implement fallback getnameinfo() */ - void freeaddrinfo(struct addrinfo *res) { struct addrinfo *next; @@ -417,7 +415,6 @@ void freeaddrinfo(struct addrinfo *res) free(res); } } - #endif #ifndef HAVE_GAI_STRERROR @@ -464,3 +461,62 @@ const char *gai_strerror(int errcode) return "Unknown GAI_* error"; } #endif + +#ifndef HAVE_GETNAMEINFO +int getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, int flags) +{ + 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