diff options
Diffstat (limited to 'gui/gdmchooser.c')
-rw-r--r-- | gui/gdmchooser.c | 2111 |
1 files changed, 0 insertions, 2111 deletions
diff --git a/gui/gdmchooser.c b/gui/gdmchooser.c deleted file mode 100644 index 68438de1..00000000 --- a/gui/gdmchooser.c +++ /dev/null @@ -1,2111 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K, Petersen <mkp@mkp.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* gdmchooser discovers hosts running XDMCP on the local network (s), - * presents a list of them and allows the user to choose one. The - * selected hostname will be printed on stdout. */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> -#include <string.h> -#include <unistd.h> -#include <ctype.h> -#include <fcntl.h> -#include <signal.h> -#include <netdb.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <net/if.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#ifdef HAVE_SYS_SOCKIO_H -#include <sys/sockio.h> -#endif - -#include <X11/Xmd.h> -#include <X11/Xdmcp.h> - -#include <gdk/gdkx.h> -#include <glib/gi18n.h> -#include <glade/glade.h> - -#include "gdm.h" -#include "misc.h" -#include "gdmwm.h" -#include "gdmcomm.h" -#include "gdmcommon.h" -#include "gdmconfig.h" - -#include "gdm-common.h" -#include "gdm-daemon-config-keys.h" - -static gboolean RUNNING_UNDER_GDM = FALSE; - -enum { - CHOOSER_LIST_ICON_COLUMN = 0, - CHOOSER_LIST_LABEL_COLUMN, - CHOOSER_LIST_HOST_COLUMN -}; - -typedef struct _GdmChooserHost GdmChooserHost; -struct _GdmChooserHost { - gchar *name; - gchar *desc; -#ifdef ENABLE_IPV6 - struct in6_addr ia6; -#endif - struct in_addr ia; - gint addrtype; /* Address stored is IPv4 or IPv6 */ - GdkPixbuf *picture; - gboolean willing; -}; - - -static const gchar *scanning_message = N_("Please wait: scanning local network..."); -static const gchar *empty_network = N_("No serving hosts were found."); -static const gchar *active_network = N_("Choose a ho_st to connect to:"); - -/* XDM chooser style stuff */ -static gchar *xdm_address = NULL; -static gchar *client_address = NULL; -static gint connection_type = 0; - -/* Exported for glade */ -void gdm_chooser_add_host (void); -void gdm_chooser_add_entry_changed (void); -void gdm_chooser_manage (GtkButton *button, gpointer data); -void gdm_chooser_browser_select (GtkWidget *widget, - gint selected, - GdkEvent *event); -void gdm_chooser_browser_unselect (GtkWidget *widget, - gint selected, - GdkEvent *event); -void gdm_chooser_xdmcp_discover (void); -void display_chooser_information (void); - -#define ADD_TIMEOUT 3000 -static guint add_check_handler = 0; - -/* if this is received, select that host automatically */ -#ifdef ENABLE_IPV6 -static struct in6_addr *added6_addr = NULL; -#endif -static struct in_addr *added_addr = NULL; -static char *added_host = NULL; - -static guint scan_time_handler = 0; - -#define PING_TIMEOUT 2000 -#define PING_TRIES 3 -static int ping_tries = PING_TRIES; -static guint ping_try_handler = 0; - -/* set in the main function */ -static char **stored_argv = NULL; -static int stored_argc = 0; - -/* Fixetyfix */ -int XdmcpReallocARRAY8 (ARRAY8Ptr array, int length); - - -typedef struct _XdmAuth { - ARRAY8 authentication; - ARRAY8 authorization; -} XdmAuthRec, *XdmAuthPtr; - -static XdmAuthRec authlist = { - { (CARD16) 0, (CARD8 *) 0 }, - { (CARD16) 0, (CARD8 *) 0 } -}; - - -static gint sockfd; -static XdmcpBuffer bcbuf; -static XdmcpBuffer querybuf; -static GSList *bcaddr; -static GSList *queryaddr; - -enum { - GDM_BACKGROUND_NONE = 0, - GDM_BACKGROUND_IMAGE = 1, - GDM_BACKGROUND_COLOR = 2 -}; - -static GladeXML *chooser_app; -static GtkWidget *chooser, *manage, *rescan, *cancel, *add_entry, *add_button; -static GtkWidget *status_label; - -static GIOChannel *channel; -static GList *chooser_hosts = NULL; -static GdkPixbuf *defhostimg; -static GtkWidget *browser; -static GtkTreeModel *browser_model; -static GdmChooserHost *curhost; - -static gboolean have_ipv6; /* Socket is IPv4 or IPv6 */ - -static gboolean -find_host_in_list (GdmChooserHost *host, GtkTreeIter *iter) -{ - if (gtk_tree_model_get_iter_first (browser_model, iter)) { - do { - GdmChooserHost *lhost; - gtk_tree_model_get (browser_model, iter, - CHOOSER_LIST_HOST_COLUMN, &lhost, - -1); - if (lhost == host) - return TRUE; - } while (gtk_tree_model_iter_next (browser_model, iter)); - } - return FALSE; -} - -static void -gdm_chooser_host_dispose (GdmChooserHost *host) -{ - if (!host) - return; - - if (host->picture != NULL) - g_object_unref (G_OBJECT (host->picture)); - host->picture = NULL; - - g_free (host->name); - host->name = NULL; - g_free (host->desc); - host->desc = NULL; - g_free (host); -} - -static GdmChooserHost * -gdm_chooser_host_alloc (const char *hostname, - const char *description, - char *ia, - int family, - gboolean willing) -{ - GdmChooserHost *host; - GdkPixbuf *img; - gchar *hostimg; - gchar *hostimgdir; - - host = g_new0 (GdmChooserHost, 1); - host->name = g_strdup (hostname); - host->desc = g_strdup (description); - host->willing = willing; - -#ifdef ENABLE_IPV6 - if (family == AF_INET6) - memcpy (&host->ia6, (struct in6_addr *)ia, sizeof (struct in6_addr)); - else -#endif - memcpy (&host->ia, (struct in_addr *)ia, sizeof (struct in_addr)); - - host->addrtype = family; - chooser_hosts = g_list_prepend (chooser_hosts, host); - - if ( ! willing) - return host; - - hostimgdir = gdm_config_get_string (GDM_KEY_HOST_IMAGE_DIR); - hostimg = g_strconcat (hostimgdir, "/", hostname, NULL); - if (g_access (hostimg, R_OK) != 0) { - g_free (hostimg); - hostimg = g_strconcat (hostimgdir, "/", hostname, ".png", NULL); - } - - if (g_access (hostimg, R_OK) == 0 && - (img = gdk_pixbuf_new_from_file (hostimg, NULL)) != NULL) { - gint w, h, maxw, maxh; - - w = gdk_pixbuf_get_width (img); - h = gdk_pixbuf_get_height (img); - - maxw = gdm_config_get_int (GDM_KEY_MAX_ICON_WIDTH); - maxh = gdm_config_get_int (GDM_KEY_MAX_ICON_HEIGHT); - - if (w > h && w > maxw) { - h = h * ((gfloat) maxw / w); - w = maxw; - } else if (h > maxh) { - w = w * ((gfloat) maxh / h); - h = maxh; - } - - - if (w != gdk_pixbuf_get_width (img) || - h != gdk_pixbuf_get_height (img)) - host->picture = gdk_pixbuf_scale_simple (img, w, h, - GDK_INTERP_BILINEAR); - else - host->picture = g_object_ref (G_OBJECT (img)); - - g_object_unref (G_OBJECT (img)); - } else if (defhostimg != NULL) { - host->picture = (GdkPixbuf *)g_object_ref (G_OBJECT (defhostimg)); - } - - g_free (hostimg); - - return host; -} - -static void -gdm_chooser_browser_add_host (GdmChooserHost *host) -{ - gboolean add_this_host = FALSE; - - if (host->willing) { - GtkTreeIter iter = {0}; - const char *addr; - char *label; - char *name, *desc; -#ifdef ENABLE_IPV6 - if (host->addrtype == AF_INET6) { /* IPv6 address */ - static char buffer6[INET6_ADDRSTRLEN]; - - addr = inet_ntop (AF_INET6, host->ia6.s6_addr, buffer6, INET6_ADDRSTRLEN); - } - else /* IPv4 address */ -#endif - { - addr = inet_ntoa (host->ia); - } - - name = g_markup_escape_text (host->name, -1); - desc = g_markup_escape_text (host->desc, -1); - - if (strcmp (addr, host->name) == 0) - label = g_strdup_printf ("<b>%s</b>\n%s", - name, - desc); - else - label = g_strdup_printf ("<b>%s</b> (%s)\n%s", - name, - addr, - desc); - - g_free (name); - g_free (desc); - - gtk_list_store_append (GTK_LIST_STORE (browser_model), &iter); - gtk_list_store_set (GTK_LIST_STORE (browser_model), &iter, - CHOOSER_LIST_ICON_COLUMN, host->picture, - CHOOSER_LIST_LABEL_COLUMN, label, - CHOOSER_LIST_HOST_COLUMN, host, - -1); - g_free (label); - -#ifdef ENABLE_IPV6 - if (added6_addr != NULL && memcmp (&host->ia6, added6_addr, - sizeof (struct in6_addr)) == 0) { - added6_addr = NULL; - add_this_host = TRUE; - } -#else - if (added_addr != NULL && - memcmp (&host->ia, added_addr, - sizeof (struct in_addr)) == 0) { - added_addr = NULL; - add_this_host = TRUE; - } -#endif - if (add_this_host) { - GtkTreeSelection *selection; - GtkTreePath *path = gtk_tree_model_get_path (browser_model, &iter); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (browser)); - gtk_tree_selection_select_iter (selection, &iter); - gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (browser), - path, NULL, - FALSE, 0.0, 0.0); - gtk_tree_path_free (path); - gtk_widget_grab_focus (manage); - } - g_free (added_host); - added_host = NULL; - if (add_check_handler > 0) - g_source_remove (add_check_handler); - add_check_handler = 0; - } - - gtk_widget_set_sensitive (GTK_WIDGET (browser), TRUE); -} - -static GdmChooserHost * -gdm_host_known (char *ia, gint family) -{ - GList *li; - - for (li = chooser_hosts; li != NULL; li = li->next) { - GdmChooserHost *host = li->data; -#ifdef ENABLE_IPV6 - if (family == AF_INET6) { - if (host->addrtype != AF_INET6) - continue; - if ( ! memcmp (&host->ia6, (struct in6_addr *)ia, sizeof (struct in6_addr))) - return host; - } - else -#endif - if (family == AF_INET) { - if (host->addrtype != AF_INET) - continue; - if ( ! memcmp (&host->ia, (struct in_addr *)ia, sizeof (struct in_addr))) - return host; - } - } - return NULL; -} - -static gboolean -is_loopback_addr (char *ia, gint family) -{ - const char lo[] = {127,0,0,1}; - -#ifdef ENABLE_IPV6 - if (family == AF_INET6 && IN6_IS_ADDR_LOOPBACK ((struct in6_addr *)ia)) { - return TRUE; - } else -#endif - if (((family == AF_INET) && (((struct in_addr *) ia)->s_addr == INADDR_LOOPBACK)) || memcmp (&((struct in_addr *)ia)->s_addr, lo, 4) == 0) { - return TRUE; - } - else { - return FALSE; - } -} - -static gboolean -gdm_addr_known (char *ia, gint family) -{ - GSList *li; - - for (li = queryaddr; li != NULL; li = li->next) { - struct sockaddr *sa = li->data; - -#ifdef ENABLE_IPV6 - if (sa->sa_family == AF_INET6) { - if (family != AF_INET6) - continue; - - if (!memcmp (&((struct sockaddr_in6 *)sa)->sin6_addr, (struct in6_addr *)ia , sizeof (struct in6_addr))) - return TRUE; - } - else if (sa->sa_family == AF_INET) { - if (family != AF_INET) - continue; - - if (!memcmp (&((struct sockaddr_in *)sa)->sin_addr, (struct in_addr *)ia, sizeof (struct in_addr))) - return TRUE; - - } -#else - if (memcmp (&((struct sockaddr_in *)sa)->sin_addr, (struct in_addr *)ia, sizeof (struct in_addr)) == 0) - return TRUE; -#endif - } - return FALSE; -} - -static GtkWidget * -hig_dialog_new (GtkWindow *parent, - GtkDialogFlags flags, - GtkMessageType type, - GtkButtonsType buttons, - const gchar *primary_message, - const gchar *secondary_message) -{ - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (GTK_WINDOW (parent), - GTK_DIALOG_DESTROY_WITH_PARENT, - type, - buttons, - "%s", primary_message); - - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), - "%s", secondary_message); - - gtk_window_set_title (GTK_WINDOW (dialog), ""); - gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); - gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14); - - return dialog; -} - -static gboolean -gdm_chooser_decode_packet (GIOChannel *source, - GIOCondition condition, - gpointer data) -{ -#ifdef ENABLE_IPV6 - char hbuf[NI_MAXHOST]; - struct sockaddr_in6 clnt6_sa; -#endif - struct sockaddr_in clnt_sa; - gint sa_len; - static XdmcpBuffer buf; - XdmcpHeader header; - struct hostent *he; - gchar *hostname = NULL; - gchar *status = NULL; - ARRAY8 auth = {0}, host = {0}, stat = {0}; - GdmChooserHost *gh; - int pipe_buf; - gboolean host_not_willing = FALSE; - -#ifdef PIPE_BUF - pipe_buf = PIPE_BUF; -#else - /* apparently Hurd doesn't have PIPE_BUF */ - pipe_buf = fpathconf (1 /*stdout*/, _PC_PIPE_BUF); - /* could return -1 if no limit */ -#endif - - if ( ! (condition & G_IO_IN)) - return TRUE; - -#ifdef ENABLE_IPV6 - if (have_ipv6) { - sa_len = sizeof (struct sockaddr_in6); - if (! XdmcpFill (sockfd, &buf, (XdmcpNetaddr) &clnt6_sa, &sa_len)) - return TRUE; - } else -#endif - { - sa_len = sizeof (struct sockaddr_in); - if (! XdmcpFill (sockfd, &buf, (XdmcpNetaddr) &clnt_sa, &sa_len)) - return TRUE; - } - - if (! XdmcpReadHeader (&buf, &header)) - return TRUE; - - if (header.version != XDM_PROTOCOL_VERSION) - return TRUE; - - if (header.opcode == WILLING) { - if (! XdmcpReadARRAY8 (&buf, &auth)) - goto done; - - if (! XdmcpReadARRAY8 (&buf, &host)) - goto done; - - if (! XdmcpReadARRAY8 (&buf, &stat)) - goto done; - - status = g_strndup ((char *) stat.data, MIN (stat.length, 256)); - } else if (header.opcode == UNWILLING) { - /* immaterial, will not be shown */ - status = NULL; - } else { - return TRUE; - } -#ifdef ENABLE_IPV6 - /*Since, IPv4 addresses will get extracted as V4 mapped IPv6 address*/ - - if (have_ipv6 && - IN6_IS_ADDR_V4MAPPED (&(clnt6_sa.sin6_addr))) { - memset (&clnt_sa, 0, sizeof (clnt_sa)); - memcpy (&(clnt_sa.sin_addr), &(clnt6_sa.sin6_addr.s6_addr[12]), 4); - clnt_sa.sin_family = AF_INET; - clnt_sa.sin_port = clnt6_sa.sin6_port; - clnt6_sa.sin6_family = AF_INET; - } - - if (have_ipv6 && - ((struct sockaddr *) &clnt6_sa)->sa_family == AF_INET6) { - if ( ! is_loopback_addr ((gchar *) &clnt6_sa.sin6_addr, AF_INET6)) { - clnt6_sa.sin6_scope_id = 0; - - getnameinfo ((struct sockaddr *)&clnt6_sa, sizeof (struct sockaddr_in6), hbuf, sizeof (hbuf), NULL, 0, 0); - - hostname = hbuf; - - if (strlen (hostname) + 1 > pipe_buf) - goto done; - hostname = g_strdup (hostname); - - } else { - hostname = g_new0 (char, 1024); - - if (gethostname (hostname, 1023) != 0) { - g_free (hostname); - goto done; - } - added6_addr = NULL; - gh = gdm_host_known ((char *)&clnt6_sa.sin6_addr, AF_INET6); - } - } else -#endif - { - if ( !is_loopback_addr ((char *)&clnt_sa.sin_addr, AF_INET)) { - he = gethostbyaddr ((gchar *) &clnt_sa.sin_addr, - sizeof (struct in_addr), - AF_INET); - - hostname = (he && he->h_name) ? he->h_name : inet_ntoa (clnt_sa.sin_addr); - if (strlen (hostname) + 1 > pipe_buf) - goto done; - - hostname = g_strdup (hostname); - } else { - hostname = g_new0 (char, 1024); - if (gethostname (hostname, 1023) != 0) { - g_free (hostname); - goto done; - } - } - } - - /* We can't pipe hostnames larger than this */ - if (pipe_buf > 0 && strlen (hostname)+1 > pipe_buf) { - g_free (hostname); - goto done; - } - -#ifdef ENABLE_IPV6 - if (have_ipv6 && ((struct sockaddr *) &clnt6_sa)->sa_family == AF_INET6) { - gh = gdm_host_known ((char *)&clnt6_sa.sin6_addr, AF_INET6); - if (gh == NULL) { - gh = gdm_chooser_host_alloc (hostname, status, (char *)&clnt6_sa.sin6_addr, AF_INET6, header.opcode == WILLING); - gdm_chooser_browser_add_host (gh); - } - } else -#endif - { - gh = gdm_host_known ((char *)&clnt_sa.sin_addr, AF_INET); - if (gh == NULL) { - gh = gdm_chooser_host_alloc (hostname, status, (char *)&clnt_sa.sin_addr, AF_INET, header.opcode == WILLING); - gdm_chooser_browser_add_host (gh); - } - } - if (gh != NULL) { - /* server changed it's mind */ - if (header.opcode == WILLING && - ! gh->willing) { - gh->willing = TRUE; - gdm_chooser_browser_add_host (gh); - } - /* hmmm what about the other change, just ignore - for now, it's kind of confusing to just remove - servers really */ - } -#ifdef ENABLE_IPV6 - if (have_ipv6 && - ((struct sockaddr *) &clnt6_sa)->sa_family == AF_INET6 && - ! gh->willing && - added6_addr != NULL && - memcmp (&gh->ia6, added6_addr, sizeof (struct in6_addr)) == 0) { - - added6_addr = NULL; - host_not_willing = TRUE; - } - else -#endif - if (clnt_sa.sin_family == AF_INET && - ! gh->willing && - added_addr != NULL && - memcmp (&gh->ia, added_addr, sizeof (struct in_addr)) == 0) { - - added_addr = NULL; - host_not_willing = TRUE; - } - - if (host_not_willing) { - GtkWidget *dialog; - gchar *msg; - - if (add_check_handler > 0) - g_source_remove (add_check_handler); - add_check_handler = 0; - - msg = g_strdup_printf (_("The host \"%s\" is not willing " - "to support a login session right now. " - "Please try again later."), - added_host); - - dialog = hig_dialog_new (GTK_WINDOW (chooser) /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Cannot connect to remote server"), - msg); - - g_free (msg); - - if (RUNNING_UNDER_GDM) - gdm_wm_center_window (GTK_WINDOW (dialog)); - - gdm_wm_no_login_focus_push (); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - gdm_wm_no_login_focus_pop (); - - g_free (added_host); - added_host = NULL; - } - - g_free (hostname); - - done: - if (header.opcode == WILLING) { - XdmcpDisposeARRAY8 (&auth); - XdmcpDisposeARRAY8 (&host); - XdmcpDisposeARRAY8 (&stat); - } - - g_free (status); - - return TRUE; -} - - -/* Find broadcast address for all active, non pointopoint interfaces */ -static void -gdm_chooser_find_bcaddr (void) -{ - int i = 0, num; - int sock; - struct ifconf ifc; - char *buf; - struct ifreq *ifr; - - sock = socket (AF_INET, SOCK_DGRAM, 0); -#ifdef SIOCGIFNUM - if (ioctl (sock, SIOCGIFNUM, &num) < 0) { - num = 64; - } -#else - num = 64; -#endif - - ifc.ifc_len = sizeof (struct ifreq) * num; - ifc.ifc_buf = buf = g_malloc0 (ifc.ifc_len); - if (ioctl (sock, SIOCGIFCONF, &ifc) < 0) { - g_free (buf); - gdm_common_error ("Could not get local addresses!"); - close (sock); - return; - } - - ifr = ifc.ifc_req; - num = ifc.ifc_len / sizeof (struct ifreq); - for (i = 0 ; i < num ; i++) { - if ( ! ve_string_empty (ifr[i].ifr_name)) { - struct ifreq ifreq; - struct sockaddr_in *ba = NULL; - struct sockaddr_in *sin = NULL; - - memset (&ifreq, 0, sizeof (ifreq)); - - strncpy (ifreq.ifr_name, ifr[i].ifr_name, - sizeof (ifreq.ifr_name)); - /* paranoia */ - ifreq.ifr_name[sizeof (ifreq.ifr_name) - 1] = '\0'; - - if (ioctl (sock, SIOCGIFFLAGS, &ifreq) < 0) - gdm_common_error ("Could not get SIOCGIFFLAGS for %s", ifr[i].ifr_name); - - if ((ifreq.ifr_flags & IFF_UP) == 0 || - (ifreq.ifr_flags & IFF_BROADCAST) == 0 || - ioctl (sock, SIOCGIFBRDADDR, &ifreq) < 0) - continue; - - ba = (struct sockaddr_in *) &ifreq.ifr_broadaddr; - - sin = g_new0 (struct sockaddr_in, 1); - - sin->sin_family = AF_INET; - memcpy (&sin->sin_addr, &ba->sin_addr, sizeof (ba->sin_addr)); - bcaddr = g_slist_append (bcaddr, sin); - } - } - - g_free (buf); -} - -/* Append multicast address into the list */ -#ifdef ENABLE_IPV6 -static void -gdm_chooser_find_mcaddr (void) -{ - struct sockaddr_in6 *sin6; - int sock; /* Temporary socket for getting information about available interfaces */ - u_char loop = 0; /* Disable multicast for loopback interface */ - int i, num; - char *buf; - /* For interfaces' list */ - struct ifconf ifc; - struct ifreq *ifr = NULL; - - sock = socket (AF_INET, SOCK_DGRAM, 0); -#ifdef SIOCGIFNUM - if (ioctl (sock, SIOCGIFNUM, &num) < 0) { - num = 64; - } -#else - num = 64; -#endif - ifc.ifc_len = sizeof (struct ifreq) * num; - ifc.ifc_buf = buf = malloc (ifc.ifc_len); - - if (setsockopt (sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof (loop)) < 0) - gdm_common_error ("setsockopt: Could not disable loopback interface for multicasting\n"); - - if (ioctl (sock, SIOCGIFCONF, &ifc) >= 0) - ifr = ifc.ifc_req; - num = ifc.ifc_len / sizeof (struct ifreq); /* No of interfaces */ - for (i = 0 ; i < num ; i++) { - struct ifreq ifreq; - int ifindex; - - memset (&ifreq, 0, sizeof (ifreq)); - strncpy (ifreq.ifr_name, ifr[i].ifr_name, sizeof (ifreq.ifr_name)); - ifreq.ifr_name[sizeof (ifreq.ifr_name) - 1] = '\0'; - - if (ioctl (sock, SIOCGIFFLAGS, &ifreq) < 0) - gdm_common_error ("Could not get interface flags for %s\n", ifr[i].ifr_name); - ifindex = if_nametoindex (ifr[i].ifr_name); - - if ((!(ifreq.ifr_flags & IFF_UP) || (!(ifreq.ifr_flags & IFF_MULTICAST))) || (ifindex == 0 )) { - /* Not a valid interface or Not up */ - continue; - } - - sin6 = g_new0 (struct sockaddr_in6, 1); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = htons (XDM_UDP_PORT); - sin6->sin6_scope_id = ifindex; - inet_pton (AF_INET6, gdm_config_get_string (GDM_KEY_MULTICAST_ADDR), - &sin6->sin6_addr); - - /* bcaddr is also serving for multicast address for IPv6 */ - bcaddr = g_slist_append (bcaddr, sin6); - } -} -#endif - -static gboolean -chooser_scan_time_update (gpointer data) -{ - GList *li; - scan_time_handler = 0; - for (li = chooser_hosts; li != NULL; li = li->next) { - GdmChooserHost *host = (GdmChooserHost *) li->data; - if (host->willing) - break; - } - if (li != NULL /* something was found */) { - gtk_label_set_label (GTK_LABEL (status_label), _(active_network)); - } else { - gtk_label_set_label (GTK_LABEL (status_label), _(empty_network)); - } - gtk_widget_set_sensitive (GTK_WIDGET (rescan), TRUE); - return FALSE; -} - -static void -do_ping (gboolean full) -{ - struct sockaddr_in sock; - GSList *bl = bcaddr; - GSList *ql = queryaddr; - struct sockaddr *ia; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 sock6; - - memset (&sock6, 0, sizeof (sock6)); - sock6.sin6_family = AF_INET6; - sock6.sin6_port = htons (XDM_UDP_PORT); -#endif - - sock.sin_family = AF_INET; - sock.sin_port = htons (XDM_UDP_PORT); - - while (bl) { - ia = (struct sockaddr *) bl->data; -#ifdef ENABLE_IPV6 - if (have_ipv6) { /* Convert the IPv4 broadcast address to v4 mapped v6 address.*/ - if (ia->sa_family == AF_INET) { - char tmpaddr[30]; - struct in6_addr in6; - - sprintf (tmpaddr, "::ffff:%s", inet_ntoa (((struct sockaddr_in *)(ia))->sin_addr)); - inet_pton (AF_INET6, tmpaddr, &in6); - memcpy (sock6.sin6_addr.s6_addr, in6.s6_addr, sizeof (struct in6_addr)); - XdmcpFlush (sockfd, &bcbuf, (XdmcpNetaddr) &sock6, (int) sizeof (struct sockaddr_in6)); - } - - else if (ia->sa_family == AF_INET6) { - memcpy (sock6.sin6_addr.s6_addr, ((struct sockaddr_in6 *)ia)->sin6_addr.s6_addr, sizeof (struct in6_addr)); - XdmcpFlush (sockfd, &bcbuf, (XdmcpNetaddr) &sock6, (int) sizeof (struct sockaddr_in6)); - } - } - else -#endif - { - if (ia->sa_family == AF_INET) { - sock.sin_addr.s_addr = ((struct sockaddr_in *)ia)->sin_addr.s_addr; - XdmcpFlush (sockfd, &bcbuf, (XdmcpNetaddr) &sock, (int)sizeof (struct sockaddr_in)); - } - } - bl = bl->next; - } - - while (ql != NULL) { - ia = (struct sockaddr *) ql->data; - -#ifdef ENABLE_IPV6 - if (have_ipv6) { - if (ia->sa_family == AF_INET) { - char tmpaddr[30]; - struct in6_addr in6; - - sprintf (tmpaddr, "::ffff:%s", inet_ntoa (((struct sockaddr_in *)(ia))->sin_addr)); - inet_pton (AF_INET6, tmpaddr, &in6); - - if (full || ! gdm_host_known ((char *)&((struct sockaddr_in6 *)ia)->sin6_addr, AF_INET6)) { - memcpy (sock6.sin6_addr.s6_addr, in6.s6_addr, sizeof (struct in6_addr)); - XdmcpFlush (sockfd, &bcbuf, (XdmcpNetaddr) &sock6, (int) sizeof (struct sockaddr_in6)); - } - } - - if (ia->sa_family == AF_INET6) { - if (full || ! gdm_host_known ((char *)&((struct sockaddr_in6 *)ia)->sin6_addr, AF_INET6)) { - memcpy (&sock6.sin6_addr, &((struct sockaddr_in6 *)ia)->sin6_addr, sizeof (struct in6_addr)); - XdmcpFlush (sockfd, &querybuf, (XdmcpNetaddr) &sock6, (int) sizeof (struct sockaddr_in6)); - } - } - } - else -#endif - { - if (full || ! gdm_host_known ((char *)&((struct sockaddr_in *)ia)->sin_addr, AF_INET)) { - sock.sin_addr.s_addr = ((struct sockaddr_in *)ia)->sin_addr.s_addr; - XdmcpFlush (sockfd, &querybuf, (XdmcpNetaddr) &sock, (int)sizeof (struct sockaddr_in)); - } - } - ql = ql->next; - } -} - -static gboolean -ping_try (gpointer data) -{ - do_ping (FALSE); - - ping_tries --; - if (ping_tries <= 0) - return FALSE; - else - return TRUE; -} - -void -gdm_chooser_xdmcp_discover (void) -{ - GList *hl = chooser_hosts; - - g_free (added_host); - added_host = NULL; -#ifdef ENABLE_IPV6 - added6_addr = NULL; -#endif - added_addr = NULL; - if (add_check_handler > 0) - g_source_remove (add_check_handler); - add_check_handler = 0; - - gtk_widget_set_sensitive (GTK_WIDGET (manage), FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (rescan), FALSE); - gtk_list_store_clear (GTK_LIST_STORE (browser_model)); - gtk_widget_set_sensitive (GTK_WIDGET (browser), FALSE); - gtk_label_set_label (GTK_LABEL (status_label), - _(scanning_message)); - - while (hl) { - gdm_chooser_host_dispose ((GdmChooserHost *) hl->data); - hl = hl->next; - } - - g_list_free (chooser_hosts); - chooser_hosts = NULL; - - do_ping (TRUE); - - if (scan_time_handler > 0) - g_source_remove (scan_time_handler); - scan_time_handler = g_timeout_add (gdm_config_get_int (GDM_KEY_SCAN_TIME) * 1000, - chooser_scan_time_update, NULL); - - /* Note we already used up one try */ - ping_tries = PING_TRIES - 1; - if (ping_try_handler > 0) - g_source_remove (ping_try_handler); - ping_try_handler = g_timeout_add (PING_TIMEOUT, ping_try, NULL); -} - -#ifndef ishexdigit -#define ishexdigit(c) (isdigit(c) || ('a' <= (c) && (c) <= 'f')) -#endif -#define HexChar(c) ('0' <= (c) && (c) <= '9' ? (c) - '0' : (c) - 'a' + 10) - -static int -from_hex (const char *s, char *d, int len) -{ - int t; - while (len >= 2) - { - if (!ishexdigit(*s)) - return 1; - t = HexChar(*s) << 4; - s++; - if (!ishexdigit(*s)) - return 1; - t += HexChar(*s); - s++; - *d++ = t; - len -= 2; - } - return len; -} - -static void -gdm_chooser_add_hosts (char **hosts) -{ - struct hostent *hostent; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 *qa6 = NULL; - struct addrinfo hints, *result, *res; -#endif - struct sockaddr_in* qa = NULL; - int used_addr = 0; - int i; - - for (i = 0; hosts != NULL && hosts[i] != NULL; i++) { - const char *name = hosts[i]; - - if (strcmp (name, "BROADCAST") == 0) { - gdm_chooser_find_bcaddr (); - continue; - } -#ifdef ENABLE_IPV6 - if (strcmp (name, "MULTICAST") == 0) { - gdm_chooser_find_mcaddr (); - continue; - } -#endif - if (used_addr == AF_INET || !qa) { - qa = g_new0 (struct sockaddr_in, 1); - memset (qa, 0, sizeof (*qa)); - qa->sin_family = AF_INET; - } -#ifdef ENABLE_IPV6 - if (used_addr == AF_INET6 || !qa6) { - qa6 = g_new0 (struct sockaddr_in6, 1); - memset (qa6, 0, sizeof (qa6)); - qa6->sin6_family = AF_INET6; - } - - result = NULL; - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; - - if ((strlen (name) == 32) && from_hex (name, (char *) &qa6->sin6_addr, strlen (name)) == 0) { - queryaddr = g_slist_append (queryaddr, qa6); - g_free (qa); - qa = NULL; - used_addr = AF_INET6; - } - else -#endif - if ((strlen (name) == 8) && (from_hex (name, (char *) &qa->sin_addr, strlen (name)) == 0)) { - queryaddr = g_slist_append (queryaddr, qa); -#ifdef ENABLE_IPV6 - g_free (qa6); - qa6 = NULL; -#endif - used_addr = AF_INET; - } - else -#ifdef ENABLE_IPV6 - if (inet_pton (AF_INET6, name, &qa6->sin6_addr) > 0) { - queryaddr = g_slist_append (queryaddr, qa6); - g_free (qa); - qa = NULL; - used_addr = AF_INET6; - } - else -#endif - if ((qa->sin_addr.s_addr = inet_addr (name)) != -1) { - queryaddr = g_slist_append (queryaddr, qa); -#ifdef ENABLE_IPV6 - g_free (qa6); - qa6 = NULL; -#endif - used_addr = AF_INET; - } - else -#ifdef ENABLE_IPV6 - if (getaddrinfo (name, NULL, &hints, &result) == 0) { - for (res = result; res; res = res->ai_next) { - if (res && res->ai_family == AF_INET6) { - memmove (qa6, res->ai_addr, res->ai_addrlen); - queryaddr = g_slist_append (queryaddr, qa6); - g_free (qa); - qa = NULL; - used_addr = AF_INET6; - } - if (res && res->ai_family == AF_INET) { - memmove (qa, res->ai_addr, res->ai_addrlen); - queryaddr = g_slist_append (queryaddr, qa); - g_free (qa6); - qa6 = NULL; - used_addr = AF_INET; - } - } - } else -#endif - if ((hostent = gethostbyname (name)) != NULL - && hostent->h_addrtype == AF_INET - && hostent->h_length == 4) { - qa->sin_family = AF_INET; - memmove (&qa->sin_addr, hostent->h_addr, 4); - queryaddr = g_slist_append (queryaddr, qa); -#ifdef ENABLE_IPV6 - g_free (qa6); - qa6 = NULL; -#endif - used_addr = AF_INET; - } else { - continue; /* not a valid address */ - } - } - - if (bcaddr == NULL && - queryaddr == NULL) - gdm_chooser_find_bcaddr (); -} - -static void -gdm_chooser_xdmcp_init (char **hosts) -{ - static XdmcpHeader header; - gint sockopts = 1; - - /* Open socket for communication */ -#ifdef ENABLE_IPV6 - if ((sockfd = socket (AF_INET6, SOCK_DGRAM, 0)) == -1) - have_ipv6 = FALSE; - else - have_ipv6 = TRUE; -#endif - if ( ! have_ipv6) { - if ((sockfd = socket (AF_INET, SOCK_DGRAM, 0)) == -1) { - gdm_common_fail_exit ("Could not create socket!"); - } - } - - if (setsockopt (sockfd, SOL_SOCKET, SO_BROADCAST, - (char *) &sockopts, sizeof (sockopts)) < 0) { - gdm_common_fail_exit ("Could not set socket options!"); - } - - /* Assemble XDMCP BROADCAST_QUERY packet in static buffer */ - header.opcode = (CARD16) BROADCAST_QUERY; - header.length = 1; - header.version = XDM_PROTOCOL_VERSION; - XdmcpWriteHeader (&bcbuf, &header); - XdmcpWriteARRAY8 (&bcbuf, &authlist.authentication); - - /* Assemble XDMCP QUERY packet in static buffer */ - header.opcode = (CARD16) QUERY; - header.length = 1; - header.version = XDM_PROTOCOL_VERSION; - XdmcpWriteHeader (&querybuf, &header); - XdmcpWriteARRAY8 (&querybuf, &authlist.authentication); - - gdm_chooser_add_hosts (hosts); - - channel = g_io_channel_unix_new (sockfd); - g_io_channel_set_encoding (channel, NULL, NULL); - g_io_channel_set_buffered (channel, FALSE); - g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, - G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL, - gdm_chooser_decode_packet, - GINT_TO_POINTER (sockfd), NULL); - g_io_channel_unref (channel); - - gdm_chooser_xdmcp_discover (); -} - -static void -gdm_chooser_choose_host (const char *hostname) -{ - ARRAY8 tmparr; -#ifndef ENABLE_IPV6 - struct hostent *hentry; -#endif - - printf ("\n%s\n", curhost->name); - fflush (stdout); - if (xdm_address != NULL) { -#ifdef ENABLE_IPV6 - int status; - struct sockaddr_in6 in6_addr; - struct addrinfo hints, *result; -#endif - struct sockaddr_in in_addr; - char xdm_addr[32]; - char client_addr[32]; - int fd; - char buf[1024]; - XdmcpBuffer buffer; - long family, port, addr; - - if (strlen (xdm_address) > 64 || - from_hex (xdm_address, xdm_addr, strlen (xdm_address)) != 0) { - gdm_common_fail_exit ("gdm_chooser_chooser_host: Invalid xdm address."); - } - - family = (xdm_addr[0] << 8) | xdm_addr[1]; - port = (xdm_addr[2] << 8) | xdm_addr[3]; - -#ifdef ENABLE_IPV6 - if (family == AF_INET6) { - memset (&in6_addr, 0, sizeof (in6_addr)); - - in6_addr.sin6_port = htons (port); - in6_addr.sin6_family = AF_INET6; - - memcpy (&in6_addr.sin6_addr, &xdm_address[4], 16); - - if ((fd = socket (PF_INET6, SOCK_STREAM, 0)) == -1) { - gdm_common_fail_exit ("gdm_chooser_choose_host: Could not create response socket."); - } - - if (connect (fd, (struct sockaddr *) &in6_addr, - sizeof (in6_addr)) == -1) { - - gdm_common_fail_exit ("gdm_chooser_chooser_host: Could not connect to xdm."); - } - } else -#endif - { - addr = (xdm_addr[4] << 24) | (xdm_addr[5] << 16) | - (xdm_addr[6] << 8) | xdm_addr[7]; - - in_addr.sin_family = AF_INET; - in_addr.sin_port = htons (port); - in_addr.sin_addr.s_addr = htonl (addr); - - if ((fd = socket (PF_INET, SOCK_STREAM, 0)) == -1) { - gdm_common_fail_exit ("gdm_chooser_chooser_host: Could not create response socket."); - } - - if (connect (fd, (struct sockaddr *) &in_addr, - sizeof (in_addr)) == -1) { - - gdm_common_fail_exit ("gdm_chooser_chooser_host: Could not connect to xdm."); - } - } - - buffer.data = (BYTE *) buf; - buffer.size = sizeof (buf); - buffer.pointer = 0; - buffer.count = 0; - - if (strlen (client_address) > 64 || from_hex (client_address, - client_addr, strlen (client_address)) != 0) { - - gdm_common_fail_exit ("gdm_chooser_chooser_host: Invalid client address."); - } - - tmparr.data = (BYTE *) client_addr; - tmparr.length = strlen (client_address) / 2; - - XdmcpWriteARRAY8 (&buffer, &tmparr); - XdmcpWriteCARD16 (&buffer, (CARD16) connection_type); - -#ifdef ENABLE_IPV6 - result = NULL; - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; - - status = getaddrinfo (hostname, NULL, &hints, &result); - - if (status != 0) { - gdm_common_fail_exit ("gdm_chooser_chooser_host: Could not get host entry for %s", - hostname); - } - - if (result->ai_family == AF_INET6) - tmparr.length = 16; - if (result->ai_family == AF_INET) - tmparr.length = 4; - tmparr.data = (BYTE *) result->ai_addr; -#else - hentry = gethostbyname (hostname); - - if (!hentry) { - gdm_common_fail_exit ("gdm_chooser_chooser_host: Could not get host entry for %s", - hostname); - } - - tmparr.data = (BYTE *) hentry->h_addr_list[0]; /* XXX */ - tmparr.length = 4; - -#endif - XdmcpWriteARRAY8 (&buffer, &tmparr); - write (fd, (char *) buffer.data, buffer.pointer); - close (fd); - } -} - -static gboolean -add_check (gpointer data) -{ - gboolean check = FALSE; - -#ifdef ENABLE_IPV6 - if (have_ipv6 && added6_addr != NULL) - check = TRUE; - else -#endif - if ((! have_ipv6) && added_addr != NULL) - check = TRUE; - - if (check) { - GtkWidget *dialog; - gchar *msg; - - msg = g_strdup_printf (_("Did not receive any response from host \"%s\" " - "in %d seconds. Perhaps the host is not " - "turned on, or is not willing to support a " - "login session right now. Please try again " - "later."), - added_host, - ADD_TIMEOUT / 1000); - - dialog = hig_dialog_new (GTK_WINDOW (chooser) /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Did not receive response from server"), - msg); - - g_free (msg); - - if (RUNNING_UNDER_GDM) - gdm_wm_center_window (GTK_WINDOW (dialog)); - - gdm_wm_no_login_focus_push (); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - gdm_wm_no_login_focus_pop (); - } - add_check_handler = 0; - return FALSE; -} - -void -gdm_chooser_add_host (void) -{ - struct hostent *hostent; - struct sockaddr_in *qa; - GdmChooserHost *host = NULL; - struct sockaddr_in sock; - gboolean status = FALSE; - const char *name; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 *qa6; - struct sockaddr_in6 sock6; - struct addrinfo hints, *result; - - result = NULL; - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_DGRAM; -#endif - - name = gtk_entry_get_text (GTK_ENTRY (add_entry)); - if (ve_string_empty (name)) - return; - - qa = g_new0 (struct sockaddr_in, 1); - qa->sin_family = AF_INET; -#ifdef ENABLE_IPV6 - qa6 = g_new0 (struct sockaddr_in6, 1); - qa6->sin6_family = AF_INET6; - - if (have_ipv6 && strlen (name) == 32 && - from_hex (name, (char *) &qa6->sin6_addr, strlen (name)) == 0) ; - - else -#endif - if (strlen (name) == 8 && - from_hex (name, (char *) &qa->sin_addr, strlen (name)) == 0) { -#ifdef ENABLE_IPV6 - if (have_ipv6) { - char tmpaddr[30]; - - sprintf (tmpaddr, "::ffff:%s", inet_ntoa (qa->sin_addr)); - inet_pton (AF_INET6, tmpaddr, &qa6->sin6_addr); - } -#endif - } - else -#ifdef ENABLE_IPV6 - if (have_ipv6 && inet_pton (AF_INET6, name, &qa6->sin6_addr) > 0) ; - else -#endif - if (inet_aton (name, &(qa->sin_addr))) { -#ifdef ENABLE_IPV6 - if (have_ipv6) { - char tmpaddr[30]; - - sprintf (tmpaddr, "::ffff:%s", inet_ntoa (qa->sin_addr)); - inet_pton (AF_INET6, tmpaddr, &qa6->sin6_addr); - } -#endif - } - else -#ifdef ENABLE_IPV6 - if (getaddrinfo (name, NULL, &hints, &result) == 0) { - if (result->ai_family == AF_INET6) { - memcpy (qa6, (struct sockaddr_in6 *)result->ai_addr, result->ai_addrlen); - } - else if (result->ai_family == AF_INET) { - if (have_ipv6) { - char tmpaddr [30]; - - sprintf (tmpaddr, "::ffff:%s", - inet_ntoa (((struct sockaddr_in *)result->ai_addr)->sin_addr)); - inet_pton (AF_INET6, tmpaddr, &qa6->sin6_addr); - } - } - } - else -#endif - if ((hostent = gethostbyname (name)) != NULL && - hostent->h_addrtype == AF_INET && hostent->h_length == 4) { - memmove (&qa->sin_addr, hostent->h_addr, 4); - } else { - GtkWidget *dialog; - gchar *msg; - - msg = g_strdup_printf (_("Cannot find the host \"%s\". " - "Perhaps you have mistyped it."), - name); - - dialog = hig_dialog_new (GTK_WINDOW (chooser) /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Cannot find host"), - msg); - g_free (msg); - - if (RUNNING_UNDER_GDM) - gdm_wm_center_window (GTK_WINDOW (dialog)); - - gdm_wm_no_login_focus_push (); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - gdm_wm_no_login_focus_pop (); - g_free (qa); -#ifdef ENABLE_IPV6 - g_free (qa6); -#endif - return; /* not a valid address */ - } - -#ifdef ENABLE_IPV6 - if (have_ipv6) { - memset (&sock6, 0, sizeof (struct sockaddr_in6)); - sock6.sin6_family = AF_INET6; - sock6.sin6_port = htons (XDM_UDP_PORT); - status = gdm_addr_known ((char *)&qa6->sin6_addr, AF_INET6); - if ( ! status) { - queryaddr = g_slist_append (queryaddr, qa6); - } - if (IN6_IS_ADDR_V4MAPPED (&qa6->sin6_addr)) { - memcpy (&qa->sin_addr, &(qa6->sin6_addr.s6_addr[12]), 4); - host = gdm_host_known ((char *) &qa->sin_addr, AF_INET); - } - else - host = gdm_host_known ((char *) &qa6->sin6_addr, AF_INET6); - } else -#endif - { - memset (&sock, 0, sizeof (struct sockaddr_in)); - sock.sin_family = AF_INET; - sock.sin_port = htons (XDM_UDP_PORT); - status = gdm_addr_known ((char *)&qa->sin_addr, AF_INET); - if ( ! status) { - queryaddr = g_slist_append (queryaddr, qa); - } - host = gdm_host_known ((char *) &qa->sin_addr, AF_INET); - } - - if (host != NULL) { - GtkTreeIter iter = {0}; - if (find_host_in_list (host, &iter)) { - GtkTreeSelection *selection; - GtkTreePath *path = gtk_tree_model_get_path (browser_model, &iter); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (browser)); - gtk_tree_selection_select_iter (selection, &iter); - gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (browser), - path, NULL, - FALSE, 0.0, 0.0); - gtk_tree_path_free (path); - gtk_widget_grab_focus (manage); - } else { - /* hmm, probably not willing, ping the host then for - good measure */ -#ifdef ENABLE_IPV6 - if (have_ipv6) { - memcpy (&sock6.sin6_addr, &qa6->sin6_addr, sizeof (qa6->sin6_addr)); - XdmcpFlush (sockfd, &querybuf, (XdmcpNetaddr) &sock6, (int) sizeof (struct sockaddr_in6)); - added6_addr = &qa6->sin6_addr; - if (IN6_IS_ADDR_V4MAPPED (added6_addr)) - added_addr = (struct in_addr *)&(qa6->sin6_addr.s6_addr[12]); - } else -#endif - { - sock.sin_addr.s_addr = qa->sin_addr.s_addr; - XdmcpFlush (sockfd, &querybuf, (XdmcpNetaddr) &sock, (int)sizeof (struct sockaddr_in)); - added_addr = &qa->sin_addr; - } - g_free (added_host); - added_host = g_strdup (name); - - if (add_check_handler > 0) - g_source_remove (add_check_handler); - add_check_handler = g_timeout_add (ADD_TIMEOUT, - add_check, NULL); - } - - /* empty the text entry to indicate success */ - gtk_entry_set_text (GTK_ENTRY (add_entry), ""); - g_free (qa); -#ifdef ENABLE_IPV6 - g_free (qa6); -#endif - return; - } -#ifdef ENABLE_IPV6 - if (have_ipv6) { - added6_addr = &qa6->sin6_addr; - - if (IN6_IS_ADDR_V4MAPPED (added6_addr)) - added_addr = (struct in_addr *)&(qa6->sin6_addr.s6_addr[12]); - - memcpy (&sock6.sin6_addr, &qa6->sin6_addr, sizeof (struct in6_addr)); - XdmcpFlush (sockfd, &querybuf, (XdmcpNetaddr) &sock6, (int)sizeof (struct sockaddr_in6)); - } else -#endif - { - added_addr = &qa->sin_addr; - - /* and send out the query */ - sock.sin_addr.s_addr = qa->sin_addr.s_addr; - XdmcpFlush (sockfd, &querybuf, (XdmcpNetaddr) &sock, (int)sizeof (struct sockaddr_in)); - } - g_free (added_host); - added_host = g_strdup (name); - if (add_check_handler > 0) - g_source_remove (add_check_handler); - add_check_handler = g_timeout_add (ADD_TIMEOUT, - add_check, NULL); - - /* empty the text entry to indicate success */ - gtk_entry_set_text (GTK_ENTRY (add_entry), ""); - - g_free (qa); -#ifdef ENABLE_IPV6 - g_free (qa6); -#endif -} - -void -gdm_chooser_add_entry_changed (void) -{ - const char *name; - - name = gtk_entry_get_text (GTK_ENTRY (add_entry)); - gtk_widget_set_sensitive (add_button, ! ve_string_empty (name)); -} - -void -gdm_chooser_cancel (int sig) -{ - if (scan_time_handler > 0) { - g_source_remove (scan_time_handler); - scan_time_handler = 0; - } - - /* exit rather gtk_main_quit, it's just safer this way we don't - have to worry about random whackiness happening */ - exit (EXIT_SUCCESS); -} - - -void -gdm_chooser_manage (GtkButton *button, gpointer data) -{ - if (scan_time_handler > 0) { - g_source_remove (scan_time_handler); - scan_time_handler = 0; - } - - if (curhost) - gdm_chooser_choose_host (curhost->name); - - /* exit rather gtk_main_quit, it's just safer this way we don't - have to worry about random whackiness happening */ - exit (EXIT_SUCCESS); -} - -static void -host_selected (GtkTreeSelection *selection, gpointer data) -{ - GtkTreeModel *tm = NULL; - GtkTreeIter iter = {0}; - - curhost = NULL; - - if (gtk_tree_selection_get_selected (selection, &tm, &iter)) { - gtk_tree_model_get (tm, &iter, CHOOSER_LIST_HOST_COLUMN, - &curhost, -1); - } - - gtk_widget_set_sensitive (manage, curhost != NULL); -} - -static void -row_activated (GtkTreeView *tree_view, - GtkTreePath *path, - GtkTreeViewColumn *column) -{ - if (curhost != NULL) - gdm_chooser_manage (NULL, NULL); -} - -void -display_chooser_information (void) -{ - GtkWidget *dialog; - - /* How to get HIG compliance? */ - dialog = gtk_message_dialog_new - (GTK_WINDOW (chooser) /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_INFO, - GTK_BUTTONS_OK, - _("The main area of this application shows the hosts on " - "the local network that have \"XDMCP\" enabled. This " - "allows users to login remotely to other computers as " - "if they were logged on using the console.\n\n" - "You can rescan the network for new hosts by clicking " - "\"Refresh\". When you have selected a host click " - "\"Connect\" to open a session to that computer.")); - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); - - if (RUNNING_UNDER_GDM) - gdm_wm_center_window (GTK_WINDOW (dialog)); - - gdm_wm_no_login_focus_push (); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - gdm_wm_no_login_focus_pop (); -} - -static void -gdm_chooser_gui_init (void) -{ - GtkTreeSelection *selection; - GtkTreeViewColumn *column; - gchar *defaulthosticon; - int width; - int height; - - /* Enable theme */ - if (RUNNING_UNDER_GDM) { - const char *theme_name; - - if ( ! ve_string_empty (gdm_config_get_string (GDM_KEY_GTKRC))) - gtk_rc_parse (gdm_config_get_string (GDM_KEY_GTKRC)); - - theme_name = g_getenv ("GDM_GTK_THEME"); - if (ve_string_empty (theme_name)) - theme_name = gdm_config_get_string (GDM_KEY_GTK_THEME); - - if ( ! ve_string_empty (theme_name)) { - gdm_set_theme (theme_name); - } - } - - defaulthosticon = gdm_config_get_string (GDM_KEY_DEFAULT_HOST_IMG); - - /* Load default host image */ - if (g_access (defaulthosticon, R_OK) != 0) { - gdm_common_error ("Could not open default host icon: %s", defaulthosticon); - /* bogus image */ - defhostimg = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - FALSE /* has_alpha */, - 8 /* bits_per_sample */, - 48 /* width */, - 48 /* height */); - } else { - defhostimg = gdk_pixbuf_new_from_file (defaulthosticon, NULL); - } - - /* Main window */ - chooser_app = glade_xml_new (GDM_GLADE_DIR "/gdmchooser.glade", - "gdmchooser_main", - NULL); - glade_xml_signal_autoconnect (chooser_app); - chooser = glade_xml_get_widget (chooser_app, "gdmchooser_main"); - manage = glade_xml_get_widget (chooser_app, "connect_button"); - rescan = glade_xml_get_widget (chooser_app, "rescan_button"); - cancel = glade_xml_get_widget (chooser_app, "quit_button"); - status_label = glade_xml_get_widget (chooser_app, "status_label"); - add_entry = glade_xml_get_widget (chooser_app, "add_entry"); - add_button = glade_xml_get_widget (chooser_app, "add_button"); - browser = glade_xml_get_widget (chooser_app, "chooser_iconlist"); - - gtk_dialog_set_has_separator (GTK_DIALOG (chooser), FALSE); - - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (browser), TRUE); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (browser)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - - g_signal_connect (selection, "changed", - G_CALLBACK (host_selected), - NULL); - g_signal_connect (browser, "row_activated", - G_CALLBACK (row_activated), - NULL); - - browser_model = (GtkTreeModel *)gtk_list_store_new (3, - GDK_TYPE_PIXBUF, - G_TYPE_STRING, - G_TYPE_POINTER); - gtk_tree_view_set_model (GTK_TREE_VIEW (browser), browser_model); - column = gtk_tree_view_column_new_with_attributes ("Icon", - gtk_cell_renderer_pixbuf_new (), - "pixbuf", CHOOSER_LIST_ICON_COLUMN, - NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (browser), column); - - column = gtk_tree_view_column_new_with_attributes ("Hostname", - gtk_cell_renderer_text_new (), - "markup", CHOOSER_LIST_LABEL_COLUMN, - NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (browser), column); - - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (browser_model), - CHOOSER_LIST_LABEL_COLUMN, - GTK_SORT_ASCENDING); - - - if ( ! gdm_config_get_bool (GDM_KEY_ALLOW_ADD)) { - GtkWidget *w = glade_xml_get_widget (chooser_app, "add_hbox"); - gtk_widget_hide (w); - } - - gtk_window_get_size (GTK_WINDOW (chooser), - &width, &height); - if (RUNNING_UNDER_GDM) { - if (width > gdm_wm_screen.width) - width = gdm_wm_screen.width; - if (height > gdm_wm_screen.height) - height = gdm_wm_screen.height; - } else { - if (width > gdk_screen_width ()) - width = gdk_screen_width (); - if (height > gdk_screen_height ()) - height = gdk_screen_height (); - } - gtk_widget_set_size_request (GTK_WIDGET (chooser), - width, height); - gtk_window_set_default_size (GTK_WINDOW (chooser), - width, height); - gtk_window_resize (GTK_WINDOW (chooser), - width, height); - - - /* cursor blinking is evil on remote displays, don't do it forever */ - gdm_common_setup_blinking (); - gdm_common_setup_blinking_entry (add_entry); - - if (RUNNING_UNDER_GDM) { - gtk_widget_show_now (chooser); - gdm_wm_center_window (GTK_WINDOW (chooser)); - } -} - -/* - * If new configuration keys are added to this program, make sure to add the - * key to the gdm_read_config and gdm_reread_config functions. - */ -static gboolean -gdm_read_config (void) -{ - /* Read config data in bulk */ - gdmcomm_comm_bulk_start (); - - /* - * Read all the keys at once and close sockets connection so we do - * not have to keep the socket open. - */ - gdm_config_get_string (GDM_KEY_HOSTS); - gdm_config_get_string (GDM_KEY_GTKRC); - gdm_config_get_string (GDM_KEY_GTK_THEME); - gdm_config_get_string (GDM_KEY_DEFAULT_HOST_IMG); - gdm_config_get_string (GDM_KEY_HOST_IMAGE_DIR); - gdm_config_get_string (GDM_KEY_MULTICAST_ADDR); - gdm_config_get_string (GDM_KEY_BACKGROUND_COLOR); - gdm_config_get_int (GDM_KEY_XINERAMA_SCREEN); - gdm_config_get_int (GDM_KEY_MAX_ICON_WIDTH); - gdm_config_get_int (GDM_KEY_MAX_ICON_HEIGHT); - gdm_config_get_int (GDM_KEY_SCAN_TIME); - gdm_config_get_int (GDM_KEY_BACKGROUND_TYPE); - gdm_config_get_bool (GDM_KEY_ALLOW_ADD); - gdm_config_get_bool (GDM_KEY_BROADCAST); - gdm_config_get_bool (GDM_KEY_MULTICAST); - - gdmcomm_comm_bulk_stop (); - - return FALSE; -} - -static gboolean -gdm_reread_config (int sig, gpointer data) -{ - /* reparse config stuff here. At least ones we care about */ - - /* Read config data in bulk */ - gdmcomm_comm_bulk_start (); - - /* FIXME: The following is evil, we should update on the fly rather - * then just restarting */ - /* Also we may not need to check ALL those keys but just a few */ - if (gdm_config_reload_string (GDM_KEY_HOSTS) || - gdm_config_reload_string (GDM_KEY_GTKRC) || - gdm_config_reload_string (GDM_KEY_GTK_THEME) || - gdm_config_reload_string (GDM_KEY_DEFAULT_HOST_IMG) || - gdm_config_reload_string (GDM_KEY_HOST_IMAGE_DIR) || - gdm_config_reload_string (GDM_KEY_MULTICAST_ADDR) || - gdm_config_reload_int (GDM_KEY_XINERAMA_SCREEN) || - gdm_config_reload_int (GDM_KEY_MAX_ICON_WIDTH) || - gdm_config_reload_int (GDM_KEY_MAX_ICON_HEIGHT) || - gdm_config_reload_int (GDM_KEY_SCAN_TIME) || - gdm_config_reload_bool (GDM_KEY_ALLOW_ADD) || - gdm_config_reload_bool (GDM_KEY_BROADCAST) || - gdm_config_reload_bool (GDM_KEY_MULTICAST)) { - - if (RUNNING_UNDER_GDM) { - /* Set busy cursor */ - gdm_common_setup_cursor (GDK_WATCH); - gdm_wm_save_wm_order (); - } - - /* we don't need to tell the slave that we're restarting - it doesn't care about our state. Unlike with the greeter */ - execvp (stored_argv[0], stored_argv); - _exit (DISPLAY_REMANAGE); - } - - /* we only use the color and do it for all types except NONE */ - if (gdm_config_reload_string (GDM_KEY_BACKGROUND_COLOR) || - gdm_config_reload_int (GDM_KEY_BACKGROUND_TYPE)) { - - if (gdm_config_get_int (GDM_KEY_BACKGROUND_TYPE) != GDM_BACKGROUND_NONE) { - gdm_common_setup_background_color (gdm_config_get_string - (GDM_KEY_BACKGROUND_COLOR)); - } - } - - gdmcomm_comm_bulk_stop (); - - return TRUE; -} - - -static void -gdm_chooser_signals_init (void) -{ - struct sigaction hup; - struct sigaction term; - sigset_t mask; - - ve_signal_add (SIGHUP, gdm_reread_config, NULL); - - hup.sa_handler = ve_signal_notify; - hup.sa_flags = 0; - sigemptyset (&hup.sa_mask); - sigaddset (&hup.sa_mask, SIGCHLD); - - term.sa_handler = gdm_chooser_cancel; - term.sa_flags = 0; - sigemptyset (&term.sa_mask); - - if (sigaction (SIGHUP, &hup, NULL) < 0) { - gdm_common_fail_exit ("%s: Error setting up %s signal handler: %s", - "gdm_signals_init", "HUP", strerror (errno)); - } - - if (sigaction (SIGINT, &term, NULL) < 0) { - gdm_common_fail_exit ("%s: Error setting up %s signal handler: %s", - "gdm_signals_init", "INT", strerror (errno)); - } - - if (sigaction (SIGTERM, &term, NULL) < 0) { - gdm_common_fail_exit ("%s: Error setting up %s signal handler: %s", - "gdm_signals_init", "TERM", strerror (errno)); - } - - sigfillset (&mask); - sigdelset (&mask, SIGTERM); - sigdelset (&mask, SIGHUP); - sigdelset (&mask, SIGINT); - - if (sigprocmask (SIG_SETMASK, &mask, NULL) == -1) - gdm_common_fail_exit ("Could not set signal mask!"); -} - -GOptionEntry chooser_options [] = { - { "xdmaddress", '\0', 0, G_OPTION_ARG_STRING, &xdm_address, - N_("Socket for xdm communication"), N_("SOCKET") }, - { "clientaddress", '\0', 0, G_OPTION_ARG_STRING, &client_address, - N_("Client address to return in response to xdm"), N_("ADDRESS") }, - { "connectionType", '\0', 0, G_OPTION_ARG_INT, &connection_type, - N_("Connection type to return in response to xdm"), N_("TYPE") }, - { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &chooser_hosts, - NULL, NULL }, - { NULL } -}; - -static gboolean -gdm_event (GSignalInvocationHint *ihint, - guint n_param_values, - const GValue *param_values, - gpointer data) -{ - GdkEvent *event; - - /* HAAAAAAAAAAAAAAAAACK */ - /* Since the user has not logged in yet and may have left/right - * mouse buttons switched, we just translate every right mouse click - * to a left mouse click */ - if (n_param_values != 2 || - !G_VALUE_HOLDS (¶m_values[1], GDK_TYPE_EVENT)) - return FALSE; - - event = g_value_get_boxed (¶m_values[1]); - if ((event->type == GDK_BUTTON_PRESS || - event->type == GDK_2BUTTON_PRESS || - event->type == GDK_3BUTTON_PRESS || - event->type == GDK_BUTTON_RELEASE) - && event->button.button == 3) - event->button.button = 1; - - return TRUE; -} - -int -main (int argc, char *argv[]) -{ - gchar *GdmHosts; - gchar **hosts_opt = NULL; - GOptionContext *ctx; - const char *gdm_version; - int i; - guint sid; - - stored_argv = g_new0 (char *, argc + 1); - for (i = 0; i < argc; i++) - stored_argv[i] = g_strdup (argv[i]); - stored_argv[i] = NULL; - stored_argc = argc; - - if (g_getenv ("RUNNING_UNDER_GDM") != NULL) - RUNNING_UNDER_GDM = TRUE; - - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - gtk_init (&argc, &argv); - - ctx = g_option_context_new (_("- gdm login chooser")); - g_option_context_add_main_entries(ctx, chooser_options, _("main options")); - g_option_context_parse(ctx, &argc, &argv, NULL); - g_option_context_free(ctx); - - glade_init (); - - gdm_common_log_init (); - gdm_common_log_set_debug (gdm_config_get_bool (GDM_KEY_DEBUG)); - - /* Read all configuration at once, so the values get cached */ - gdm_read_config (); - - GdmHosts = g_strdup (gdm_config_get_string (GDM_KEY_HOSTS)); - - /* if broadcasting, then append BROADCAST to hosts */ - if (gdm_config_get_bool (GDM_KEY_BROADCAST)) { - gchar *tmp; - if (ve_string_empty (GdmHosts)) { - tmp = "BROADCAST"; - } else { - tmp = g_strconcat (GdmHosts, ",BROADCAST", NULL); - } - g_free (GdmHosts); - GdmHosts = tmp; - } - -#ifdef ENABLE_IPV6 - if (gdm_config_get_bool (GDM_KEY_MULTICAST)) { - gchar *tmp; - if (ve_string_empty (GdmHosts)) { - tmp = "MULTICAST"; - } else { - tmp = g_strconcat (GdmHosts, ",MULTICAST", NULL); - } - g_free (GdmHosts); - GdmHosts = tmp; - } -#endif - - if (RUNNING_UNDER_GDM) - gdm_wm_screen_init (gdm_config_get_int (GDM_KEY_XINERAMA_SCREEN)); - - gdm_version = g_getenv ("GDM_VERSION"); - - /* Load the background as early as possible so GDM does not leave */ - /* the background unfilled. The cursor should be a watch already */ - /* but just in case */ - if (RUNNING_UNDER_GDM) { - if (gdm_config_get_int (GDM_KEY_BACKGROUND_TYPE) != GDM_BACKGROUND_NONE) - gdm_common_setup_background_color (gdm_config_get_string (GDM_KEY_BACKGROUND_COLOR)); - - gdm_common_setup_cursor (GDK_WATCH); - } - - if (RUNNING_UNDER_GDM && - gdm_version != NULL && - strcmp (gdm_version, VERSION) != 0) { - GtkWidget *dialog; - gchar *msg; - - gdm_wm_init (0); - - gdm_wm_focus_new_windows (TRUE); - - msg = g_strdup_printf (_("The chooser version (%s) does not match the daemon " - "version (%s). " - "You have probably just upgraded GDM. " - "Please restart the GDM daemon or the computer."), - VERSION, gdm_version); - - dialog = hig_dialog_new (NULL /* parent */, - GTK_DIALOG_MODAL /* flags */, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Cannot run chooser"), - msg); - g_free (msg); - - gtk_widget_show_all (dialog); - gdm_wm_center_window (GTK_WINDOW (dialog)); - - gdm_common_setup_cursor (GDK_LEFT_PTR); - - gtk_dialog_run (GTK_DIALOG (dialog)); - - return EXIT_SUCCESS; - } - - gtk_window_set_default_icon_from_file (DATADIR"/pixmaps/gdm-xnest.png", NULL); - - gdm_chooser_gui_init (); - gdm_chooser_signals_init (); - - /* when no hosts on the command line, take them from the config */ - if (hosts_opt == NULL || - hosts_opt[0] == NULL) { - int i; - hosts_opt = g_strsplit (GdmHosts, ",", -1); - for (i = 0; hosts_opt != NULL && hosts_opt[i] != NULL; i++) { - g_strstrip (hosts_opt[i]); - } - } - gdm_chooser_xdmcp_init (hosts_opt); - g_strfreev (hosts_opt); - - sid = g_signal_lookup ("event", - GTK_TYPE_WIDGET); - g_signal_add_emission_hook (sid, - 0 /* detail */, - gdm_event, - NULL /* data */, - NULL /* destroy_notify */); - - gtk_widget_queue_resize (chooser); - gtk_widget_show_now (chooser); - - if (RUNNING_UNDER_GDM) - gdm_wm_center_window (GTK_WINDOW (chooser)); - - if (RUNNING_UNDER_GDM && - /* can it ever happen that it'd be NULL here ??? */ - chooser->window != NULL) { - gdm_wm_init (GDK_WINDOW_XWINDOW (chooser->window)); - - /* Run the focus, note that this will work no matter what - * since gdm_wm_init will set the display to the gdk one - * if it fails */ - gdm_wm_focus_window (GDK_WINDOW_XWINDOW (chooser->window)); - } - - if (gdm_config_get_bool (GDM_KEY_ALLOW_ADD)) - gtk_widget_grab_focus (add_entry); - - gdm_chooser_add_entry_changed (); - - if (RUNNING_UNDER_GDM) { - gdm_wm_restore_wm_order (); - gdm_common_setup_cursor (GDK_LEFT_PTR); - } - - gtk_main (); - - exit (EXIT_SUCCESS); -} -/* EOF */ |