]> Pileus Git - ~andy/fetchmail/commitdiff
Add gethostby* from libesmtp
authorMatthias Andree <matthias.andree@gmx.de>
Sun, 28 Aug 2005 14:59:23 +0000 (14:59 -0000)
committerMatthias Andree <matthias.andree@gmx.de>
Sun, 28 Aug 2005 14:59:23 +0000 (14:59 -0000)
svn path=/trunk/; revision=4278

libesmtp/getaddrinfo.c
libesmtp/getaddrinfo.h
libesmtp/gethostbyname.c [new file with mode: 0644]
libesmtp/gethostbyname.h [new file with mode: 0644]

index 575b51d2019508a6fa42e1671a67861d1a1eab47..5eaa0a68309974acf4c59d604ff934851f1641e4 100644 (file)
@@ -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
index c474d3bc19589845a21b459673919330a37c9f52..1d7bf3cc6f55e45ba968402b0efe9c2bcd84c886 100644 (file)
@@ -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 (file)
index 0000000..d151606
--- /dev/null
@@ -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 (file)
index 0000000..2b96399
--- /dev/null
@@ -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
+