NeoMutt  2020-09-25
Teaching an old dog new tricks
DOXYGEN
getdomain.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <netdb.h>
31 #include <string.h>
32 #include <sys/socket.h>
33 #include <time.h>
34 #include <unistd.h>
35 #include "mutt/lib.h"
36 #include "conn/lib.h" // IWYU pragma: keep
37 
44 int getdnsdomainname(struct Buffer *domain)
45 {
46  int rc = -1;
47 
48 #if defined(HAVE_GETADDRINFO) || defined(HAVE_GETADDRINFO_A)
49  char node[256];
50  if (gethostname(node, sizeof(node)) != 0)
51  return rc;
52 
53  struct addrinfo hints;
54  struct addrinfo *h = NULL;
55 
56  mutt_buffer_reset(domain);
57  memset(&hints, 0, sizeof(struct addrinfo));
58  hints.ai_flags = AI_CANONNAME;
59  hints.ai_family = AF_UNSPEC;
60 
61 #ifdef HAVE_GETADDRINFO_A
62  /* Allow 0.1 seconds to get the FQDN (fully-qualified domain name).
63  * If it takes longer, the system is mis-configured and the network is not
64  * working properly, so... */
65  struct timespec timeout = { 0, 100000000 };
66  struct gaicb *reqs[1];
67  reqs[0] = mutt_mem_calloc(1, sizeof(*reqs[0]));
68  reqs[0]->ar_name = node;
69  reqs[0]->ar_request = &hints;
70  if (getaddrinfo_a(GAI_NOWAIT, reqs, 1, NULL) == 0)
71  {
72  gai_suspend((const struct gaicb *const *) reqs, 1, &timeout);
73  const int status = gai_error(reqs[0]);
74  if (status == 0)
75  h = reqs[0]->ar_result;
76  else if (status == EAI_INPROGRESS)
77  {
78  mutt_debug(LL_DEBUG1, "timeout\n");
79  /* request is not finish, cancel it to free it safely */
80  if (gai_cancel(reqs[0]) == EAI_NOTCANCELED)
81  {
82  while (gai_suspend((const struct gaicb *const *) reqs, 1, NULL) != 0)
83  continue;
84  }
85  }
86  else
87  mutt_debug(LL_DEBUG1, "fail: (%d) %s\n", status, gai_strerror(status));
88  }
89  FREE(&reqs[0]);
90 #else /* !HAVE_GETADDRINFO_A */
91  mutt_debug(LL_DEBUG3, "before getaddrinfo\n");
92  getaddrinfo(node, NULL, &hints, &h);
93  mutt_debug(LL_DEBUG3, "after getaddrinfo\n");
94 #endif
95 
96  char *p = NULL;
97  if (h && h->ai_canonname && (p = strchr(h->ai_canonname, '.')))
98  {
99  mutt_buffer_strcpy(domain, ++p);
100  rc = 0;
101  mutt_debug(LL_DEBUG1, "Hostname: %s\n", mutt_b2s(domain));
102  freeaddrinfo(h);
103  }
104 #endif /* HAVE_GETADDRINFO || defined HAVE_GETADDRINFO_A */
105 
106  return rc;
107 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:41
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
Log at debug level 1.
Definition: logging.h:40
Connection Library.
#define FREE(x)
Definition: memory.h:40
Time value with nanosecond precision.
Definition: file.h:46
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int getdnsdomainname(struct Buffer *domain)
Lookup the host&#39;s name using DNS.
Definition: getdomain.c:44
Convenience wrapper for the library headers.
Log at debug level 3.
Definition: logging.h:42