+/* Bionic has res_init() but it's not in any header */
+#ifdef __BIONIC__
+int res_init (void);
+#endif
+
+static void
+g_resolver_maybe_reload (GResolver *resolver)
+{
+#ifdef G_OS_UNIX
+ struct stat st;
+
+ if (stat (_PATH_RESCONF, &st) == 0)
+ {
+ if (st.st_mtime != resolver->priv->resolv_conf_timestamp)
+ {
+ resolver->priv->resolv_conf_timestamp = st.st_mtime;
+#ifdef HAVE_RES_INIT
+ res_init ();
+#endif
+ g_signal_emit (resolver, signals[RELOAD], 0);
+ }
+ }
+#endif
+}
+
+/* filter out duplicates, cf. https://bugzilla.gnome.org/show_bug.cgi?id=631379 */
+static void
+remove_duplicates (GList *addrs)
+{
+ GList *l;
+ GList *ll;
+ GList *lll;
+
+ /* TODO: if this is too slow (it's O(n^2) but n is typically really
+ * small), we can do something more clever but note that we must not
+ * change the order of elements...
+ */
+ for (l = addrs; l != NULL; l = l->next)
+ {
+ GInetAddress *address = G_INET_ADDRESS (l->data);
+ for (ll = l->next; ll != NULL; ll = lll)
+ {
+ GInetAddress *other_address = G_INET_ADDRESS (ll->data);
+ lll = ll->next;
+ if (g_inet_address_equal (address, other_address))
+ {
+ g_object_unref (other_address);
+ /* we never return the first element */
+ g_warn_if_fail (g_list_delete_link (addrs, ll) == addrs);
+ }
+ }
+ }
+}
+
+/* Note that this does not follow the "FALSE means @error is set"
+ * convention. The return value tells the caller whether it should
+ * return @addrs and @error to the caller right away, or if it should
+ * continue and trying to resolve the name as a hostname.
+ */
+static gboolean
+handle_ip_address (const char *hostname,
+ GList **addrs,
+ GError **error)
+{
+ GInetAddress *addr;
+#ifndef G_OS_WIN32
+ struct in_addr ip4addr;
+#endif
+
+ addr = g_inet_address_new_from_string (hostname);
+ if (addr)
+ {
+ *addrs = g_list_append (NULL, addr);
+ return TRUE;
+ }
+
+ *addrs = NULL;
+
+ /* Reject non-standard IPv4 numbers-and-dots addresses.
+ * g_inet_address_new_from_string() will have accepted any "real" IP
+ * address, so if inet_aton() succeeds, then it's an address we want
+ * to reject. This check is not necessary for Windows, as getaddrinfo()
+ * already rejects such IPv4 addresses on Windows.
+ */
+#ifndef G_OS_WIN32
+ if (inet_aton (hostname, &ip4addr))
+ {
+ g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
+ _("Error resolving '%s': %s"),
+ hostname, gai_strerror (EAI_NONAME));
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}