1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
3 /* GIO - GLib Input, Output and Streaming Library
5 * Copyright (C) 2008 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307, USA.
35 static GResolver *resolver;
36 static GCancellable *cancellable;
37 static GMainLoop *loop;
38 static int nlookups = 0;
43 fprintf (stderr, "Usage: resolver [-t] [-s] [hostname | IP | service/protocol/domain ] ...\n");
44 fprintf (stderr, " Use -t to enable threading.\n");
45 fprintf (stderr, " Use -s to do synchronous lookups.\n");
46 fprintf (stderr, " Both together will result in simultaneous lookups in multiple threads\n");
50 G_LOCK_DEFINE_STATIC (response);
58 /* In the sync case we need to make sure we don't call
59 * g_main_loop_quit before the loop is actually running...
61 g_idle_add ((GSourceFunc)g_main_loop_quit, loop);
66 print_resolved_name (const char *phys,
71 printf ("Address: %s\n", phys);
74 printf ("Error: %s\n", error->message);
79 printf ("Name: %s\n", name);
89 print_resolved_addresses (const char *name,
97 printf ("Name: %s\n", name);
100 printf ("Error: %s\n", error->message);
101 g_error_free (error);
105 for (a = addresses; a; a = a->next)
107 phys = g_inet_address_to_string (a->data);
108 printf ("Address: %s\n", phys);
110 g_object_unref (a->data);
112 g_list_free (addresses);
121 print_resolved_service (const char *service,
128 printf ("Service: %s\n", service);
131 printf ("Error: %s\n", error->message);
132 g_error_free (error);
136 for (t = targets; t; t = t->next)
138 printf ("%s:%u (pri %u, weight %u)\n",
139 g_srv_target_get_hostname (t->data),
140 g_srv_target_get_port (t->data),
141 g_srv_target_get_priority (t->data),
142 g_srv_target_get_weight (t->data));
143 g_srv_target_free (t->data);
145 g_list_free (targets);
154 lookup_one_sync (const char *arg)
156 GError *error = NULL;
158 if (strchr (arg, '/'))
161 /* service/protocol/domain */
162 char **parts = g_strsplit (arg, "/", 3);
164 if (!parts || !parts[2])
167 targets = g_resolver_lookup_service (resolver,
168 parts[0], parts[1], parts[2],
169 cancellable, &error);
170 print_resolved_service (arg, targets, error);
172 else if (g_hostname_is_ip_address (arg))
174 GInetAddress *addr = g_inet_address_new_from_string (arg);
177 name = g_resolver_lookup_by_address (resolver, addr, cancellable, &error);
178 print_resolved_name (arg, name, error);
179 g_object_unref (addr);
185 addresses = g_resolver_lookup_by_name (resolver, arg, cancellable, &error);
186 print_resolved_addresses (arg, addresses, error);
191 lookup_thread (gpointer arg)
193 lookup_one_sync (arg);
198 start_threaded_lookups (char **argv, int argc)
202 for (i = 0; i < argc; i++)
203 g_thread_create (lookup_thread, argv[i], FALSE, NULL);
207 start_sync_lookups (char **argv, int argc)
211 for (i = 0; i < argc; i++)
212 lookup_one_sync (argv[i]);
216 lookup_by_addr_callback (GObject *source, GAsyncResult *result,
219 const char *phys = user_data;
220 GError *error = NULL;
223 name = g_resolver_lookup_by_address_finish (resolver, result, &error);
224 print_resolved_name (phys, name, error);
228 lookup_by_name_callback (GObject *source, GAsyncResult *result,
231 const char *name = user_data;
232 GError *error = NULL;
235 addresses = g_resolver_lookup_by_name_finish (resolver, result, &error);
236 print_resolved_addresses (name, addresses, error);
240 lookup_service_callback (GObject *source, GAsyncResult *result,
243 const char *service = user_data;
244 GError *error = NULL;
247 targets = g_resolver_lookup_service_finish (resolver, result, &error);
248 print_resolved_service (service, targets, error);
252 start_async_lookups (char **argv, int argc)
256 for (i = 0; i < argc; i++)
258 if (strchr (argv[i], '/'))
260 /* service/protocol/domain */
261 char **parts = g_strsplit (argv[i], "/", 3);
263 if (!parts || !parts[2])
266 g_resolver_lookup_service_async (resolver,
267 parts[0], parts[1], parts[2],
269 lookup_service_callback, argv[i]);
271 else if (g_hostname_is_ip_address (argv[i]))
273 GInetAddress *addr = g_inet_address_new_from_string (argv[i]);
275 g_resolver_lookup_by_address_async (resolver, addr, cancellable,
276 lookup_by_addr_callback, argv[i]);
277 g_object_unref (addr);
281 g_resolver_lookup_by_name_async (resolver, argv[i], cancellable,
282 lookup_by_name_callback,
289 static int cancel_fds[2];
292 interrupted (int sig)
294 signal (SIGINT, SIG_DFL);
295 write (cancel_fds[1], "x", 1);
299 async_cancel (GIOChannel *source, GIOCondition cond, gpointer cancellable)
301 g_cancellable_cancel (cancellable);
307 main (int argc, char **argv)
309 gboolean threaded = FALSE, synchronous = FALSE;
315 /* We can't use GOptionContext because we use the arguments to
316 * decide whether or not to call g_thread_init().
318 while (argc >= 2 && argv[1][0] == '-')
320 if (!strcmp (argv[1], "-t"))
322 g_thread_init (NULL);
325 else if (!strcmp (argv[1], "-s"))
338 resolver = g_resolver_get_default ();
340 cancellable = g_cancellable_new ();
343 /* Set up cancellation; we want to cancel if the user ^C's the
344 * program, but we can't cancel directly from an interrupt.
346 signal (SIGINT, interrupted);
348 if (pipe (cancel_fds) == -1)
353 chan = g_io_channel_unix_new (cancel_fds[0]);
354 watch = g_io_add_watch (chan, G_IO_IN, async_cancel, cancellable);
355 g_io_channel_unref (chan);
359 loop = g_main_loop_new (NULL, TRUE);
361 if (threaded && synchronous)
362 start_threaded_lookups (argv + 1, argc - 1);
363 else if (synchronous)
364 start_sync_lookups (argv + 1, argc - 1);
366 start_async_lookups (argv + 1, argc - 1);
369 g_main_loop_unref (loop);
372 g_source_remove (watch);
374 g_object_unref (cancellable);