From: Mehdi ABAAKOUK Date: Fri, 24 Feb 2017 14:43:36 +0000 (+0100) Subject: Use getaddrinfo_a if possible (#420) X-Git-Tag: neomutt-20170225~7 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f05e079cc9d948cc9b67bedf529509013b7d67b5;p=neomutt Use getaddrinfo_a if possible (#420) 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 --- diff --git a/configure.ac b/configure.ac index 31e7be8ee..211f913d1 100644 --- a/configure.ac +++ b/configure.ac @@ -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.]) diff --git a/getdomain.c b/getdomain.c index f7bace7d5..97fd9f429 100644 --- a/getdomain.c +++ b/getdomain.c @@ -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; }