]> granicus.if.org Git - neomutt/commitdiff
Use getaddrinfo_a if possible (#420)
authorMehdi ABAAKOUK <sileht@sileht.net>
Fri, 24 Feb 2017 14:43:36 +0000 (15:43 +0100)
committerRichard Russon <rich@flatcap.org>
Fri, 24 Feb 2017 14:43:36 +0000 (14:43 +0000)
When getaddrinfo_a is avialable we can use it to set a timeout for the
dns resolution. This avoid to have mutt that freeze on startup when the
network connection isn't working and the hosts/hostname misconfigured on
the system.

Closes #176
Closes #420

configure.ac
getdomain.c

index 31e7be8ee902a993dc7621f95f5fbe6b518d1f5d..211f913d14ce6134dedf7d781a109bb6c5f9e176 100644 (file)
@@ -658,11 +658,12 @@ need_socket="no"
 
 dnl -- socket dependencies --
 
-dnl getaddrinfo is used by getdomain.c, and requires libnsl and
-dnl libsocket on some platforms
+dnl getaddrinfo/getaddrinfo_a is used by getdomain.c, and requires libnsl and
+dnl libsocket on some platforms, and libanl
 AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent))
 AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt))
 AC_CHECK_FUNCS(getaddrinfo)
+AC_SEARCH_LIBS([getaddrinfo_a], [anl], [AC_DEFINE(HAVE_GETADDRINFO_A, 1, [Define to 1 if you have the `getaddrinfo_a' function.])])
 
 AS_IF([test x$use_pop = "xyes"], [
        AC_DEFINE(USE_POP, 1, [Define if you want support for the POP3 protocol.])
index f7bace7d5845c2dd9ef30f3c1cff33e3fbbf2682..97fd9f429179eb1a452d3f77071b9a70df4e9ea4 100644 (file)
@@ -33,41 +33,55 @@ int getdnsdomainname (char *d, size_t len)
 {
   int ret = -1;
 
-#ifdef HAVE_GETADDRINFO
-  char *node;
-  long node_len;
+#if defined HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A
+  char node[STRING];
+  if (gethostname(node, sizeof(node)))
+    return ret;
+
   struct addrinfo hints;
-  struct addrinfo *h;
-  char *p;
+  struct addrinfo *h = NULL;
 
   *d = '\0';
   memset(&hints, 0, sizeof (struct addrinfo));
   hints.ai_flags = AI_CANONNAME;
   hints.ai_family = AF_UNSPEC;
 
-  /* A DNS name can actually be only 253 octets, string is 256 */
-  if ((node_len = sysconf(_SC_HOST_NAME_MAX)) == -1)
-    node_len = STRING;
-  node = safe_malloc(node_len + 1);
-  if (gethostname(node, node_len))
-    ret = -1;
-  else if (getaddrinfo(node, NULL, &hints, &h))
-    ret = -1;
-  else
+#ifdef HAVE_GETADDRINFO_A
+
+  /* Allow 0.1 seconds to get the FQDN (fully-qualified domain name).
+   * If it takes longer, the system is mis-configured and the network is not
+   * working properly, so...
+   */
+  struct timespec timeout = {0, 100000000};
+  struct gaicb *reqs[1];
+  reqs[0] = safe_calloc(1, sizeof(*reqs[0]));
+  reqs[0]->ar_name = node;
+  reqs[0]->ar_request = &hints;
+  if ((getaddrinfo_a(GAI_NOWAIT, reqs, 1, NULL) == 0) &&
+      (gai_suspend((const struct gaicb * const *) reqs, 1, &timeout) == 0) &&
+      (gai_error(reqs[0]) == 0))
   {
-    if (!h->ai_canonname || !(p = strchr(h->ai_canonname, '.')))
-      ret = -1;
-    else
-    {
-      strfcpy(d, ++p, len);
-      ret = 0;
-      mutt_debug (1, "getdnsdomainname(): %s\n", d);
-    }
-    freeaddrinfo(h);
+    h = reqs[0]->ar_result;
   }
-  FREE (&node);
+  FREE(&reqs[0]);
+
+#else /* !HAVE_GETADDRINFO_A */
+
+  getaddrinfo(node, NULL, &hints, &h)
+
 #endif
 
+  char *p;
+  if (h != NULL && h->ai_canonname && (p = strchr(h->ai_canonname, '.')))
+  {
+    strfcpy(d, ++p, len);
+    ret = 0;
+    mutt_debug (1, "getdnsdomainname(): %s\n", d);
+    freeaddrinfo(h);
+  }
+
+#endif /* HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A */
+
   return ret;
 }