diff options
author | Matthias Andree <matthias.andree@gmx.de> | 2005-08-28 14:59:23 +0000 |
---|---|---|
committer | Matthias Andree <matthias.andree@gmx.de> | 2005-08-28 14:59:23 +0000 |
commit | e073fea25d254e62b2d3cf607bdbbb5104ca9778 (patch) | |
tree | e8a9c40b8dfe427315ddc945f74e1a3fed8217e2 | |
parent | 2927f46cfd4abd60a77862fa0746aca40c3d1235 (diff) | |
download | fetchmail-e073fea25d254e62b2d3cf607bdbbb5104ca9778.tar.gz fetchmail-e073fea25d254e62b2d3cf607bdbbb5104ca9778.tar.bz2 fetchmail-e073fea25d254e62b2d3cf607bdbbb5104ca9778.zip |
Add gethostby* from libesmtp
svn path=/trunk/; revision=4278
-rw-r--r-- | libesmtp/getaddrinfo.c | 43 | ||||
-rw-r--r-- | libesmtp/getaddrinfo.h | 5 | ||||
-rw-r--r-- | libesmtp/gethostbyname.c | 228 | ||||
-rw-r--r-- | libesmtp/gethostbyname.h | 103 |
4 files changed, 361 insertions, 18 deletions
diff --git a/libesmtp/getaddrinfo.c b/libesmtp/getaddrinfo.c index 575b51d2..5eaa0a68 100644 --- a/libesmtp/getaddrinfo.c +++ b/libesmtp/getaddrinfo.c @@ -27,6 +27,8 @@ #include <config.h> #endif +#ifndef HAVE_GETADDRINFO + /* Need to turn off Posix features in glibc to build this */ #undef _POSIX_C_SOURCE #undef _XOPEN_SOURCE @@ -89,26 +91,29 @@ getaddrinfo (const char *nodename, const char *servname, hints = &hint; } - /* servname must not be NULL in this implementation */ - if (servname == NULL) + if (servname == NULL && nodename == NULL) return EAI_NONAME; - /* check for tcp or udp sockets only */ - if (hints->ai_socktype == SOCK_STREAM) - socktype = "tcp"; - else if (hints->ai_socktype == SOCK_DGRAM) - socktype = "udp"; - else - return EAI_SERVICE; - result.ai_socktype = hints->ai_socktype; - - /* Note: maintain port in host byte order to make debugging easier */ - if (isdigit (*servname)) - port = strtol (servname, NULL, 10); - else if ((servent = getservbyname (servname, socktype)) != NULL) - port = ntohs (servent->s_port); - else - return EAI_NONAME; + if (servname == NULL) + port = 0; + else { + /* check for tcp or udp sockets only */ + if (hints->ai_socktype == SOCK_STREAM) + socktype = "tcp"; + else if (hints->ai_socktype == SOCK_DGRAM) + socktype = "udp"; + else + return EAI_SERVICE; + result.ai_socktype = hints->ai_socktype; + + /* Note: maintain port in host byte order to make debugging easier */ + if (isdigit (*servname)) + port = strtol (servname, NULL, 10); + else if ((servent = getservbyname (servname, socktype)) != NULL) + port = ntohs (servent->s_port); + else + return EAI_NONAME; + } /* if nodename == NULL refer to the local host for a client or any for a server */ @@ -305,6 +310,7 @@ gai_strerror (int ecode) "servname not supported for ai_socktype", /* EAI_SERVICE */ "ai_socktype not supported", /* EAI_SOCKTYPE */ "system error returned in errno", /* EAI_SYSTEM */ + "argument buffer overflow", /* EAI_OVERFLOW */ }; if (ecode < 0 || ecode > (int) (sizeof eai_descr/ sizeof eai_descr[0])) @@ -312,3 +318,4 @@ gai_strerror (int ecode) return eai_descr[ecode]; } +#endif diff --git a/libesmtp/getaddrinfo.h b/libesmtp/getaddrinfo.h index c474d3bc..1d7bf3cc 100644 --- a/libesmtp/getaddrinfo.h +++ b/libesmtp/getaddrinfo.h @@ -24,6 +24,9 @@ /* Structure and prototypes aken from RFC 2553 */ +#include <config.h> +#ifndef HAVE_GETADDRINFO + struct addrinfo { int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ @@ -53,6 +56,7 @@ struct addrinfo #define EAI_SERVICE 9 /* servname not supported for ai_socktype */ #define EAI_SOCKTYPE 10 /* ai_socktype not supported */ #define EAI_SYSTEM 11 /* system error returned in errno */ +#define EAI_OVERFLOW 12 /* argument buffer too small */ /* RFC 2553 / Posix resolver */ int getaddrinfo (const char *nodename, const char *servname, @@ -65,3 +69,4 @@ void freeaddrinfo (struct addrinfo *ai); const char *gai_strerror (int code); #endif +#endif diff --git a/libesmtp/gethostbyname.c b/libesmtp/gethostbyname.c new file mode 100644 index 00000000..d151606d --- /dev/null +++ b/libesmtp/gethostbyname.c @@ -0,0 +1,228 @@ +/* + * This file is a ghastly hack because nobody can agree on + * gethostbyname_r()'s prototype. + * + * Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#define _SVID_SOURCE 1 /* Need this to get gethostbyname_r() */ + +#include <assert.h> + +#include <stdlib.h> +#include <string.h> +#include <netdb.h> +#include <errno.h> + +#include "gethostbyname.h" + +#if HAVE_GETIPNODEBYNAME + +void +free_ghbnctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + if (ctx->hostent != NULL) + freehostent (ctx->hostent); +} + +struct hostent * +gethostbyname_ctx (const char *host, struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + memset (ctx, 0, sizeof (struct ghbnctx)); + ctx->hostent = getipnodebyname (host, AF_UNSPEC, AI_ADDRCONFIG, &ctx->h_err); + return ctx->hostent; +} + +int +h_error_ctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + return ctx->h_err; +} + +#elif HAVE_GETHOSTBYNAME_R == 6 + +void +free_ghbnctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + if (ctx->hostbuf != NULL) + free (ctx->hostbuf); +} + +struct hostent * +gethostbyname_ctx (const char *host, struct ghbnctx *ctx) +{ + struct hostent *hp; + char *tmp; + int err; + + assert (ctx != NULL); + + memset (ctx, 0, sizeof (struct ghbnctx)); + ctx->hostbuf_len = 2048; + if ((ctx->hostbuf = malloc (ctx->hostbuf_len)) == NULL) + { + errno = ENOMEM; + return NULL; + } + while ((err = gethostbyname_r (host, + &ctx->hostent, ctx->hostbuf, ctx->hostbuf_len, + &hp, &ctx->h_err)) == ERANGE) + { + ctx->hostbuf_len += 1024; + if ((tmp = realloc (ctx->hostbuf, ctx->hostbuf_len)) == NULL) + { + errno = ENOMEM; + return NULL; + } + ctx->hostbuf = tmp; + } + if (err != 0) + { + errno = err; + return NULL; + } + return hp; +} + +int +h_error_ctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + return ctx->h_err; +} + +#elif HAVE_GETHOSTBYNAME_R == 5 + +void +free_ghbnctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + if (ctx->hostbuf != NULL) + free (ctx->hostbuf); +} + +struct hostent * +gethostbyname_ctx (const char *host, struct ghbnctx *ctx) +{ + struct hostent *hp; + char *tmp; + + assert (ctx != NULL); + + memset (ctx, 0, sizeof (struct ghbnctx)); + ctx->hostbuf_len = 2048; + if ((ctx->hostbuf = malloc (ctx->hostbuf_len)) == NULL) + { + errno = ENOMEM; + return NULL; + } + while ((hp = gethostbyname_r (host, &ctx->hostent, + ctx->hostbuf, ctx->hostbuf_len, + &ctx->h_err)) == NULL && errno == ERANGE) + { + ctx->hostbuf_len += 1024; + if ((tmp = realloc (ctx->hostbuf, ctx->hostbuf_len)) == NULL) + { + errno = ENOMEM; + return NULL; + } + ctx->hostbuf = tmp; + } + return hp; +} + +int +h_error_ctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + return ctx->h_err; +} + +#elif HAVE_GETHOSTBYNAME_R == 3 + +void +free_ghbnctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + /* FIXME: does this need to do anything? */ +} + +struct hostent * +gethostbyname_ctx (const char *host, struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + if (!gethostbyname_r (host, &ctx->hostent, &ctx->hostent_data)) + { + ctx->h_err = h_errno; /* FIXME: is this correct? */ + return NULL; + } + return &ctx->hostent; +} + +int +h_error_ctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + return ctx->h_err; +} + +#else + +void +free_ghbnctx (struct ghbnctx *ctx __attribute__ ((unused))) +{ + assert (ctx != NULL); +} + +struct hostent * +gethostbyname_ctx (const char *host, struct ghbnctx *ctx) +{ + struct hostent *hp; + + hp = gethostbyname (host); + if (hp == NULL) + ctx->h_err = h_errno; + return hp; +} + +int +h_error_ctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + return ctx->h_err; +} + +#endif diff --git a/libesmtp/gethostbyname.h b/libesmtp/gethostbyname.h new file mode 100644 index 00000000..2b963997 --- /dev/null +++ b/libesmtp/gethostbyname.h @@ -0,0 +1,103 @@ +/* + * This file is a ghastly hack because nobody can agree on + * gethostbyname_r()'s prototype. + * + * Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/************************************************************************* + Usage: + + #include <errno.h> + #include "gethostbyname.h" + + f () + { + struct ghbnctx ctx; + + errno = 0; + hp = gethostbyname_ctx (host, &ctx); + if (hp == NULL) + { + if (errno != 0) + handle_value_of_errno (errno); + else + handle_value_of_h_errno (h_error_ctx (&ctx)); + } + else + { + ... + } + free_ghbnctx (&ctx); + } + *************************************************************************/ + +#ifndef _gethostbyname_h +#define _gethostbyname_h + +#if HAVE_GETIPNODEBYNAME + +struct ghbnctx + { + int h_err; + struct hostent *hostent; + }; + +#elif HAVE_GETHOSTBYNAME_R == 6 + +struct ghbnctx + { + int h_err; + struct hostent hostent; + char *hostbuf; + size_t hostbuf_len; + }; + +#elif HAVE_GETHOSTBYNAME_R == 5 + +struct ghbnctx + { + int h_err; + struct hostent hostent; + char *hostbuf; + int hostbuf_len; + }; + +#elif HAVE_GETHOSTBYNAME_R == 3 + +struct ghbnctx + { + int h_err; + struct hostent_data hostent_data; + struct hostent hostent; + }; + +#else + +struct ghbnctx + { + int h_err; + }; + +#endif + +struct hostent *gethostbyname_ctx (const char *host, struct ghbnctx *ctx); +int h_error_ctx (struct ghbnctx *ctx); +void free_ghbnctx (struct ghbnctx *ctx); + +#endif + |