Merge commit 'origin/master'
[bpt/guile.git] / libguile / net_db.c
index 5395991..4307091 100644 (file)
@@ -1,19 +1,20 @@
 /* "net_db.c" network database support
- * Copyright (C) 1995,1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
+ * Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2006, 2009 Free Software Foundation, Inc.
  * 
  * 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.
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 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
+ * 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  */
 
 
@@ -25,7 +26,7 @@
  */
 \f
 
-#if HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
 #  include <config.h>
 #endif
 
@@ -35,6 +36,7 @@
 #include "libguile/feature.h"
 #include "libguile/strings.h"
 #include "libguile/vectors.h"
+#include "libguile/dynwind.h"
 
 #include "libguile/validate.h"
 #include "libguile/net_db.h"
 extern int h_errno;
 #endif
 
+#if defined HAVE_HSTRERROR && !HAVE_DECL_HSTRERROR     \
+  && !defined __MINGW32__ && !defined __CYGWIN__
+/* Some OSes, such as Tru64 5.1b, lack a declaration for hstrerror(3).  */
+extern const char *hstrerror (int);
+#endif
+
 \f
 
 SCM_SYMBOL (scm_host_not_found_key, "host-not-found");
@@ -139,6 +147,7 @@ SCM_DEFINE (scm_gethost, "gethost", 0, 1, 0,
   struct in_addr inad;
   char **argv;
   int i = 0;
+
   if (SCM_UNBNDP (host))
     {
 #ifdef HAVE_GETHOSTENT
@@ -157,25 +166,28 @@ SCM_DEFINE (scm_gethost, "gethost", 0, 1, 0,
          return SCM_BOOL_F;
        }
     }
-  else if (SCM_STRINGP (host))
+  else if (scm_is_string (host))
     {
-      entry = gethostbyname (SCM_STRING_CHARS (host));
+      char *str = scm_to_locale_string (host);
+      entry = gethostbyname (str);
+      free (str);
     }
   else
     {
-      inad.s_addr = htonl (SCM_NUM2ULONG (1, host));
+      inad.s_addr = htonl (scm_to_ulong (host));
       entry = gethostbyaddr ((char *) &inad, sizeof (inad), AF_INET);
     }
+
   if (!entry)
     scm_resolv_error (FUNC_NAME, host);
   
-  SCM_VECTOR_SET(result, 0, scm_mem2string (entry->h_name, strlen (entry->h_name)));
-  SCM_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->h_aliases));
-  SCM_VECTOR_SET(result, 2, scm_from_int (entry->h_addrtype));
-  SCM_VECTOR_SET(result, 3, scm_from_int (entry->h_length));
+  SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->h_name));
+  SCM_SIMPLE_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->h_aliases));
+  SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_int (entry->h_addrtype));
+  SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_int (entry->h_length));
   if (sizeof (struct in_addr) != entry->h_length)
     {
-      SCM_VECTOR_SET(result, 4, SCM_BOOL_F);
+      SCM_SIMPLE_VECTOR_SET(result, 4, SCM_BOOL_F);
       return result;
     }
   for (argv = entry->h_addr_list; argv[i]; i++);
@@ -184,7 +196,7 @@ SCM_DEFINE (scm_gethost, "gethost", 0, 1, 0,
       inad = *(struct in_addr *) argv[i];
       lst = scm_cons (scm_from_ulong (ntohl (inad.s_addr)), lst);
     }
-  SCM_VECTOR_SET(result, 4, lst);
+  SCM_SIMPLE_VECTOR_SET(result, 4, lst);
   return result;
 }
 #undef FUNC_NAME
@@ -211,8 +223,9 @@ SCM_DEFINE (scm_getnet, "getnet", 0, 1, 0,
            "given.")
 #define FUNC_NAME s_scm_getnet
 {
-  SCM   result = scm_c_make_vector (4, SCM_UNSPECIFIED);
+  SCM result = scm_c_make_vector (4, SCM_UNSPECIFIED);
   struct netent *entry;
+  int eno;
 
   if (SCM_UNBNDP (net))
     {
@@ -225,22 +238,27 @@ SCM_DEFINE (scm_getnet, "getnet", 0, 1, 0,
          return SCM_BOOL_F;
        }
     }
-  else if (SCM_STRINGP (net))
+  else if (scm_is_string (net))
     {
-      entry = getnetbyname (SCM_STRING_CHARS (net));
+      char *str = scm_to_locale_string (net);
+      entry = getnetbyname (str);
+      eno = errno;
+      free (str);
     }
   else
     {
-      unsigned long netnum;
-      netnum = SCM_NUM2ULONG (1, net);
+      unsigned long netnum = scm_to_ulong (net);
       entry = getnetbyaddr (netnum, AF_INET);
+      eno = errno;
     }
+
   if (!entry)
-    SCM_SYSERROR_MSG ("no such network ~A", scm_list_1 (net), errno);
-  SCM_VECTOR_SET(result, 0, scm_mem2string (entry->n_name, strlen (entry->n_name)));
-  SCM_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->n_aliases));
-  SCM_VECTOR_SET(result, 2, scm_from_int (entry->n_addrtype));
-  SCM_VECTOR_SET(result, 3, scm_from_ulong (entry->n_net));
+    SCM_SYSERROR_MSG ("no such network ~A", scm_list_1 (net), eno);
+
+  SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->n_name));
+  SCM_SIMPLE_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->n_aliases));
+  SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_int (entry->n_addrtype));
+  SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_ulong (entry->n_net));
   return result;
 }
 #undef FUNC_NAME
@@ -257,9 +275,10 @@ SCM_DEFINE (scm_getproto, "getproto", 0, 1, 0,
            "@code{getprotoent} (see below) if no arguments are supplied.")
 #define FUNC_NAME s_scm_getproto
 {
-  SCM   result = scm_c_make_vector (3, SCM_UNSPECIFIED);
-
+  SCM result = scm_c_make_vector (3, SCM_UNSPECIFIED);
   struct protoent *entry;
+  int eno;
+
   if (SCM_UNBNDP (protocol))
     {
       entry = getprotoent ();
@@ -271,21 +290,26 @@ SCM_DEFINE (scm_getproto, "getproto", 0, 1, 0,
          return SCM_BOOL_F;
        }
     }
-  else if (SCM_STRINGP (protocol))
+  else if (scm_is_string (protocol))
     {
-      entry = getprotobyname (SCM_STRING_CHARS (protocol));
+      char *str = scm_to_locale_string (protocol);
+      entry = getprotobyname (str);
+      eno = errno;
+      free (str);
     }
   else
     {
-      unsigned long protonum;
-      protonum = SCM_NUM2ULONG (1, protocol);
+      unsigned long protonum = scm_to_ulong (protocol);
       entry = getprotobynumber (protonum);
+      eno = errno;
     }
+
   if (!entry)
-    SCM_SYSERROR_MSG ("no such protocol ~A", scm_list_1 (protocol), errno);
-  SCM_VECTOR_SET(result, 0, scm_mem2string (entry->p_name, strlen (entry->p_name)));
-  SCM_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->p_aliases));
-  SCM_VECTOR_SET(result, 2, scm_from_int (entry->p_proto));
+    SCM_SYSERROR_MSG ("no such protocol ~A", scm_list_1 (protocol), eno);
+
+  SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->p_name));
+  SCM_SIMPLE_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->p_aliases));
+  SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_int (entry->p_proto));
   return result;
 }
 #undef FUNC_NAME
@@ -297,10 +321,10 @@ scm_return_entry (struct servent *entry)
 {
   SCM result = scm_c_make_vector (4, SCM_UNSPECIFIED);
 
-  SCM_VECTOR_SET(result, 0, scm_mem2string (entry->s_name, strlen (entry->s_name)));
-  SCM_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->s_aliases));
-  SCM_VECTOR_SET(result, 2, scm_from_uint16 (ntohs (entry->s_port)));
-  SCM_VECTOR_SET(result, 3, scm_mem2string (entry->s_proto, strlen (entry->s_proto)));
+  SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->s_name));
+  SCM_SIMPLE_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->s_aliases));
+  SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_uint16 (ntohs (entry->s_port)));
+  SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_locale_string (entry->s_proto));
   return result;
 }
 
@@ -318,6 +342,9 @@ SCM_DEFINE (scm_getserv, "getserv", 0, 2, 0,
 #define FUNC_NAME s_scm_getserv
 {
   struct servent *entry;
+  char *protoname;
+  int eno;
+
   if (SCM_UNBNDP (name))
     {
       entry = getservent ();
@@ -330,19 +357,29 @@ SCM_DEFINE (scm_getserv, "getserv", 0, 2, 0,
        }
       return scm_return_entry (entry);
     }
-  SCM_VALIDATE_STRING (2, protocol);
-  if (SCM_STRINGP (name))
+
+  scm_dynwind_begin (0);
+
+  protoname = scm_to_locale_string (protocol);
+  scm_dynwind_free (protoname);
+
+  if (scm_is_string (name))
     {
-      entry = getservbyname (SCM_STRING_CHARS (name),
-                            SCM_STRING_CHARS (protocol));
+      char *str = scm_to_locale_string (name);
+      entry = getservbyname (str, protoname);
+      eno = errno;
+      free (str);
     }
   else
     {
-      entry = getservbyport (htons (scm_to_int (name)),
-                            SCM_STRING_CHARS (protocol));
+      entry = getservbyport (htons (scm_to_int (name)), protoname);
+      eno = errno;
     }
+
   if (!entry)
-    SCM_SYSERROR_MSG("no such service ~A", scm_list_1 (name), errno);
+    SCM_SYSERROR_MSG("no such service ~A", scm_list_1 (name), eno);
+
+  scm_dynwind_end ();
   return scm_return_entry (entry);
 }
 #undef FUNC_NAME