summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Jon McCann <mccann@jhu.edu>2008-01-31 00:51:46 +0000
committerWilliam Jon McCann <mccann@src.gnome.org>2008-01-31 00:51:46 +0000
commit98917b1ee7d15660bafd4ab8d2441f78afa974c1 (patch)
tree5aeff2f3cbabe5081e89b56cfcd13487fad3768e
parent17014d50d4e48c6145660df86c27324f566621b4 (diff)
downloadgdm-98917b1ee7d15660bafd4ab8d2441f78afa974c1.tar.gz
Initial support for XDMCP IndirectQuery choosers. Also fix broken
2008-01-30 William Jon McCann <mccann@jhu.edu> * common/gdm-address.c: (add_local_siocgifconf), (add_local_addrinfo), (gdm_address_peek_local_list): * daemon/Makefile.am: * daemon/gdm-chooser-server.c: (generate_address), (handle_select_hostname), (handle_disconnect), (chooser_handle_child_message), (do_introspect), (chooser_server_message_handler), (chooser_server_unregister_handler), (connection_filter_function), (allow_user_function), (handle_connection), (gdm_chooser_server_start), (gdm_chooser_server_stop), (gdm_chooser_server_get_address), (_gdm_chooser_server_set_display_id), (_gdm_chooser_server_set_user_name), (_gdm_chooser_server_set_group_name), (gdm_chooser_server_set_property), (gdm_chooser_server_get_property), (gdm_chooser_server_constructor), (gdm_chooser_server_class_init), (gdm_chooser_server_init), (gdm_chooser_server_finalize), (gdm_chooser_server_new): * daemon/gdm-chooser-server.h: * daemon/gdm-chooser-session.c: (listify_hash), (get_chooser_environment), (chooser_session_child_watch), (spawn_child_setup), (spawn_command_line_sync_as_user), (spawn_command_line_async_as_user), (parse_value_as_integer), (parse_dbus_launch_output), (start_dbus_daemon), (stop_dbus_daemon), (gdm_chooser_session_spawn), (gdm_chooser_session_start), (wait_on_child), (chooser_session_died), (gdm_chooser_session_stop), (gdm_chooser_session_set_server_address), (_gdm_chooser_session_set_x11_display_name), (_gdm_chooser_session_set_x11_display_hostname), (_gdm_chooser_session_set_x11_display_device), (_gdm_chooser_session_set_x11_authority_file), (_gdm_chooser_session_set_user_name), (_gdm_chooser_session_set_group_name), (gdm_chooser_session_set_property), (gdm_chooser_session_get_property), (gdm_chooser_session_constructor), (gdm_chooser_session_class_init), (gdm_chooser_session_init), (gdm_chooser_session_finalize), (gdm_chooser_session_new): * daemon/gdm-chooser-session.h: * daemon/gdm-display.c: (gdm_display_real_set_slave_bus_name), (gdm_display_set_slave_bus_name), (gdm_display_class_init): * daemon/gdm-display.h: * daemon/gdm-display.xml: * daemon/gdm-factory-slave.c: * daemon/gdm-greeter-server.c: * daemon/gdm-greeter-session.c: (gdm_greeter_session_init): * daemon/gdm-product-slave.c: * daemon/gdm-simple-slave.c: * daemon/gdm-slave.c: (gdm_slave_set_slave_bus_name), (gdm_slave_real_start), (register_slave), (gdm_slave_constructor): * daemon/gdm-xdmcp-chooser-display.c: (on_hostname_selected), (gdm_xdmcp_chooser_display_set_slave_bus_name), (gdm_xdmcp_chooser_display_manage), (gdm_xdmcp_chooser_display_class_init), (gdm_xdmcp_chooser_display_init), (gdm_xdmcp_chooser_display_finalize), (gdm_xdmcp_chooser_display_new): * daemon/gdm-xdmcp-chooser-display.h: * daemon/gdm-xdmcp-chooser-display.xml: * daemon/gdm-xdmcp-chooser-slave.c: (on_chooser_session_start), (on_chooser_session_stop), (on_chooser_session_exited), (on_chooser_session_died), (on_chooser_hostname_selected), (on_chooser_disconnected), (on_chooser_connected), (setup_server), (run_chooser), (idle_connect_to_display), (gdm_xdmcp_chooser_slave_run), (gdm_xdmcp_chooser_slave_start), (gdm_xdmcp_chooser_slave_stop), (gdm_xdmcp_chooser_slave_set_property), (gdm_xdmcp_chooser_slave_get_property), (gdm_xdmcp_chooser_slave_constructor), (gdm_xdmcp_chooser_slave_class_init), (gdm_xdmcp_chooser_slave_init), (gdm_xdmcp_chooser_slave_finalize), (gdm_xdmcp_chooser_slave_new): * daemon/gdm-xdmcp-chooser-slave.h: * daemon/gdm-xdmcp-display-factory.c: (set_port_for_request), (gdm_xdmcp_send_forward_query), (indirect_client_create), (indirect_client_destroy), (indirect_client_lookup_by_chosen), (indirect_client_lookup), (gdm_xdmcp_handle_indirect_query), (forward_query_destroy), (remove_oldest_forward), (forward_query_create), (forward_query_lookup), (gdm_xdmcp_handle_forward_query), (gdm_xdmcp_send_decline), (on_hostname_selected), (gdm_xdmcp_display_create), (gdm_xdmcp_handle_request), (gdm_xdmcp_send_refuse), (gdm_xdmcp_handle_manage), (gdm_xdmcp_handle_managed_forward): * daemon/gdm-xdmcp-display.c: (gdm_xdmcp_display_class_init), (gdm_xdmcp_display_finalize): * daemon/gdm-xdmcp-display.h: * daemon/gdm-xdmcp-display.xml: * daemon/gdm-xdmcp-greeter-display.c: (gdm_xdmcp_greeter_display_class_init), (gdm_xdmcp_greeter_display_init), (gdm_xdmcp_greeter_display_finalize), (gdm_xdmcp_greeter_display_new): * daemon/gdm-xdmcp-greeter-display.h: * daemon/xdmcp-chooser-slave-main.c: (get_system_bus), (signal_cb), (on_slave_stopped), (main): * data/gdm.conf: * gui/simple-chooser/Makefile.am: * gui/simple-chooser/chooser-main.c: (assistive_registry_launch), (filter_watch), (filter_timeout), (assistive_registry_start), (at_set_gtk_modules), (load_a11y), (main): * gui/simple-chooser/gdm-chooser-client.c: (gdm_chooser_client_error_quark), (send_dbus_string_method), (send_dbus_void_method), (gdm_chooser_client_call_select_hostname), (gdm_chooser_client_call_disconnect), (client_dbus_handle_message), (client_dbus_filter_function), (gdm_chooser_client_start), (gdm_chooser_client_stop), (gdm_chooser_client_set_property), (gdm_chooser_client_get_property), (gdm_chooser_client_constructor), (gdm_chooser_client_dispose), (gdm_chooser_client_class_init), (gdm_chooser_client_init), (gdm_chooser_client_finalize), (gdm_chooser_client_new): * gui/simple-chooser/gdm-chooser-client.h: * gui/simple-chooser/gdm-chooser-session.c: (launch_compiz), (launch_metacity), (start_window_manager), (start_settings_daemon), (on_dialog_response), (gdm_chooser_session_start), (gdm_chooser_session_stop), (gdm_chooser_session_set_property), (gdm_chooser_session_get_property), (gdm_chooser_session_constructor), (gdm_chooser_session_dispose), (gdm_chooser_session_class_init), (gdm_chooser_session_init), (gdm_chooser_session_finalize), (gdm_chooser_session_new): * gui/simple-chooser/gdm-chooser-session.h: * gui/simple-chooser/test-host-chooser.c: (assistive_registry_launch), (filter_watch), (filter_timeout), (assistive_registry_start), (at_set_gtk_modules), (load_a11y), (main): * gui/simple-greeter/greeter-main.c: (load_a11y), (main): Initial support for XDMCP IndirectQuery choosers. Also fix broken gdm_address_is_local. svn path=/trunk/; revision=5645
-rw-r--r--ChangeLog132
-rw-r--r--common/gdm-address.c116
-rw-r--r--daemon/Makefile.am40
-rw-r--r--daemon/gdm-chooser-server.c628
-rw-r--r--daemon/gdm-chooser-server.h63
-rw-r--r--daemon/gdm-chooser-session.c948
-rw-r--r--daemon/gdm-chooser-session.h67
-rw-r--r--daemon/gdm-display.c52
-rw-r--r--daemon/gdm-display.h7
-rw-r--r--daemon/gdm-display.xml3
-rw-r--r--daemon/gdm-factory-slave.c2
-rw-r--r--daemon/gdm-greeter-server.c3
-rw-r--r--daemon/gdm-greeter-session.c6
-rw-r--r--daemon/gdm-product-slave.c2
-rw-r--r--daemon/gdm-simple-slave.c2
-rw-r--r--daemon/gdm-slave.c34
-rw-r--r--daemon/gdm-xdmcp-chooser-display.c234
-rw-r--r--daemon/gdm-xdmcp-chooser-display.h68
-rw-r--r--daemon/gdm-xdmcp-chooser-display.xml5
-rw-r--r--daemon/gdm-xdmcp-chooser-slave.c432
-rw-r--r--daemon/gdm-xdmcp-chooser-slave.h58
-rw-r--r--daemon/gdm-xdmcp-display-factory.c438
-rw-r--r--daemon/gdm-xdmcp-display.c27
-rw-r--r--daemon/gdm-xdmcp-display.h6
-rw-r--r--daemon/gdm-xdmcp-greeter-display.c120
-rw-r--r--daemon/gdm-xdmcp-greeter-display.h65
-rw-r--r--daemon/gdm-xdmcp-greeter-display.xml (renamed from daemon/gdm-xdmcp-display.xml)0
-rw-r--r--daemon/xdmcp-chooser-slave-main.c229
-rw-r--r--data/gdm.conf2
-rw-r--r--gui/simple-chooser/Makefile.am29
-rw-r--r--gui/simple-chooser/chooser-main.c233
-rw-r--r--gui/simple-chooser/gdm-chooser-client.c414
-rw-r--r--gui/simple-chooser/gdm-chooser-client.h69
-rw-r--r--gui/simple-chooser/gdm-chooser-session.c318
-rw-r--r--gui/simple-chooser/gdm-chooser-session.h58
-rw-r--r--gui/simple-chooser/test-host-chooser.c263
-rw-r--r--gui/simple-greeter/greeter-main.c42
-rw-r--r--po/ChangeLog8
-rw-r--r--po/POTFILES.in2
39 files changed, 4998 insertions, 227 deletions
diff --git a/ChangeLog b/ChangeLog
index 7d7950b5..f487e2ad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,135 @@
+2008-01-30 William Jon McCann <mccann@jhu.edu>
+
+ * common/gdm-address.c: (add_local_siocgifconf),
+ (add_local_addrinfo), (gdm_address_peek_local_list):
+ * daemon/Makefile.am:
+ * daemon/gdm-chooser-server.c: (generate_address),
+ (handle_select_hostname), (handle_disconnect),
+ (chooser_handle_child_message), (do_introspect),
+ (chooser_server_message_handler),
+ (chooser_server_unregister_handler), (connection_filter_function),
+ (allow_user_function), (handle_connection),
+ (gdm_chooser_server_start), (gdm_chooser_server_stop),
+ (gdm_chooser_server_get_address),
+ (_gdm_chooser_server_set_display_id),
+ (_gdm_chooser_server_set_user_name),
+ (_gdm_chooser_server_set_group_name),
+ (gdm_chooser_server_set_property),
+ (gdm_chooser_server_get_property),
+ (gdm_chooser_server_constructor), (gdm_chooser_server_class_init),
+ (gdm_chooser_server_init), (gdm_chooser_server_finalize),
+ (gdm_chooser_server_new):
+ * daemon/gdm-chooser-server.h:
+ * daemon/gdm-chooser-session.c: (listify_hash),
+ (get_chooser_environment), (chooser_session_child_watch),
+ (spawn_child_setup), (spawn_command_line_sync_as_user),
+ (spawn_command_line_async_as_user), (parse_value_as_integer),
+ (parse_dbus_launch_output), (start_dbus_daemon),
+ (stop_dbus_daemon), (gdm_chooser_session_spawn),
+ (gdm_chooser_session_start), (wait_on_child),
+ (chooser_session_died), (gdm_chooser_session_stop),
+ (gdm_chooser_session_set_server_address),
+ (_gdm_chooser_session_set_x11_display_name),
+ (_gdm_chooser_session_set_x11_display_hostname),
+ (_gdm_chooser_session_set_x11_display_device),
+ (_gdm_chooser_session_set_x11_authority_file),
+ (_gdm_chooser_session_set_user_name),
+ (_gdm_chooser_session_set_group_name),
+ (gdm_chooser_session_set_property),
+ (gdm_chooser_session_get_property),
+ (gdm_chooser_session_constructor),
+ (gdm_chooser_session_class_init), (gdm_chooser_session_init),
+ (gdm_chooser_session_finalize), (gdm_chooser_session_new):
+ * daemon/gdm-chooser-session.h:
+ * daemon/gdm-display.c: (gdm_display_real_set_slave_bus_name),
+ (gdm_display_set_slave_bus_name), (gdm_display_class_init):
+ * daemon/gdm-display.h:
+ * daemon/gdm-display.xml:
+ * daemon/gdm-factory-slave.c:
+ * daemon/gdm-greeter-server.c:
+ * daemon/gdm-greeter-session.c: (gdm_greeter_session_init):
+ * daemon/gdm-product-slave.c:
+ * daemon/gdm-simple-slave.c:
+ * daemon/gdm-slave.c: (gdm_slave_set_slave_bus_name),
+ (gdm_slave_real_start), (register_slave), (gdm_slave_constructor):
+ * daemon/gdm-xdmcp-chooser-display.c: (on_hostname_selected),
+ (gdm_xdmcp_chooser_display_set_slave_bus_name),
+ (gdm_xdmcp_chooser_display_manage),
+ (gdm_xdmcp_chooser_display_class_init),
+ (gdm_xdmcp_chooser_display_init),
+ (gdm_xdmcp_chooser_display_finalize),
+ (gdm_xdmcp_chooser_display_new):
+ * daemon/gdm-xdmcp-chooser-display.h:
+ * daemon/gdm-xdmcp-chooser-display.xml:
+ * daemon/gdm-xdmcp-chooser-slave.c: (on_chooser_session_start),
+ (on_chooser_session_stop), (on_chooser_session_exited),
+ (on_chooser_session_died), (on_chooser_hostname_selected),
+ (on_chooser_disconnected), (on_chooser_connected), (setup_server),
+ (run_chooser), (idle_connect_to_display),
+ (gdm_xdmcp_chooser_slave_run), (gdm_xdmcp_chooser_slave_start),
+ (gdm_xdmcp_chooser_slave_stop),
+ (gdm_xdmcp_chooser_slave_set_property),
+ (gdm_xdmcp_chooser_slave_get_property),
+ (gdm_xdmcp_chooser_slave_constructor),
+ (gdm_xdmcp_chooser_slave_class_init),
+ (gdm_xdmcp_chooser_slave_init), (gdm_xdmcp_chooser_slave_finalize),
+ (gdm_xdmcp_chooser_slave_new):
+ * daemon/gdm-xdmcp-chooser-slave.h:
+ * daemon/gdm-xdmcp-display-factory.c: (set_port_for_request),
+ (gdm_xdmcp_send_forward_query), (indirect_client_create),
+ (indirect_client_destroy), (indirect_client_lookup_by_chosen),
+ (indirect_client_lookup), (gdm_xdmcp_handle_indirect_query),
+ (forward_query_destroy), (remove_oldest_forward),
+ (forward_query_create), (forward_query_lookup),
+ (gdm_xdmcp_handle_forward_query), (gdm_xdmcp_send_decline),
+ (on_hostname_selected), (gdm_xdmcp_display_create),
+ (gdm_xdmcp_handle_request), (gdm_xdmcp_send_refuse),
+ (gdm_xdmcp_handle_manage), (gdm_xdmcp_handle_managed_forward):
+ * daemon/gdm-xdmcp-display.c: (gdm_xdmcp_display_class_init),
+ (gdm_xdmcp_display_finalize):
+ * daemon/gdm-xdmcp-display.h:
+ * daemon/gdm-xdmcp-display.xml:
+ * daemon/gdm-xdmcp-greeter-display.c:
+ (gdm_xdmcp_greeter_display_class_init),
+ (gdm_xdmcp_greeter_display_init),
+ (gdm_xdmcp_greeter_display_finalize),
+ (gdm_xdmcp_greeter_display_new):
+ * daemon/gdm-xdmcp-greeter-display.h:
+ * daemon/xdmcp-chooser-slave-main.c: (get_system_bus), (signal_cb),
+ (on_slave_stopped), (main):
+ * data/gdm.conf:
+ * gui/simple-chooser/Makefile.am:
+ * gui/simple-chooser/chooser-main.c: (assistive_registry_launch),
+ (filter_watch), (filter_timeout), (assistive_registry_start),
+ (at_set_gtk_modules), (load_a11y), (main):
+ * gui/simple-chooser/gdm-chooser-client.c:
+ (gdm_chooser_client_error_quark), (send_dbus_string_method),
+ (send_dbus_void_method), (gdm_chooser_client_call_select_hostname),
+ (gdm_chooser_client_call_disconnect), (client_dbus_handle_message),
+ (client_dbus_filter_function), (gdm_chooser_client_start),
+ (gdm_chooser_client_stop), (gdm_chooser_client_set_property),
+ (gdm_chooser_client_get_property),
+ (gdm_chooser_client_constructor), (gdm_chooser_client_dispose),
+ (gdm_chooser_client_class_init), (gdm_chooser_client_init),
+ (gdm_chooser_client_finalize), (gdm_chooser_client_new):
+ * gui/simple-chooser/gdm-chooser-client.h:
+ * gui/simple-chooser/gdm-chooser-session.c: (launch_compiz),
+ (launch_metacity), (start_window_manager), (start_settings_daemon),
+ (on_dialog_response), (gdm_chooser_session_start),
+ (gdm_chooser_session_stop), (gdm_chooser_session_set_property),
+ (gdm_chooser_session_get_property),
+ (gdm_chooser_session_constructor), (gdm_chooser_session_dispose),
+ (gdm_chooser_session_class_init), (gdm_chooser_session_init),
+ (gdm_chooser_session_finalize), (gdm_chooser_session_new):
+ * gui/simple-chooser/gdm-chooser-session.h:
+ * gui/simple-chooser/test-host-chooser.c:
+ (assistive_registry_launch), (filter_watch), (filter_timeout),
+ (assistive_registry_start), (at_set_gtk_modules), (load_a11y),
+ (main):
+ * gui/simple-greeter/greeter-main.c: (load_a11y), (main):
+ Initial support for XDMCP IndirectQuery choosers.
+ Also fix broken gdm_address_is_local.
+
2008-01-29 William Jon McCann <mccann@jhu.edu>
* configure.ac:
diff --git a/common/gdm-address.c b/common/gdm-address.c
index 490b7fcc..9e23f1a0 100644
--- a/common/gdm-address.c
+++ b/common/gdm-address.c
@@ -30,6 +30,8 @@
#include <sys/socket.h>
#endif
#include <netdb.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
#ifndef G_OS_WIN32
#include <sys/socket.h>
@@ -280,25 +282,71 @@ gdm_address_is_loopback (GdmAddress *address)
return FALSE;
}
-const GList *
-gdm_address_peek_local_list (void)
+static void
+add_local_siocgifconf (GList **list)
{
- static GList *the_list = NULL;
- static time_t last_time = 0;
- char hostbuf[BUFSIZ];
- struct addrinfo *result;
- struct addrinfo *res;
+ struct ifconf ifc;
+ struct ifreq ifreq;
+ struct ifreq *ifr;
+ struct ifreq *the_end;
+ int sock;
+ char buf[BUFSIZ];
+
+ if ((sock = socket (PF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror ("socket");
+ return;
+ }
- /* Don't check more then every 5 seconds */
- if (last_time + 5 > time (NULL)) {
- return the_list;
+ ifc.ifc_len = sizeof (buf);
+ ifc.ifc_buf = buf;
+ if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0) {
+ perror ("SIOCGIFCONF");
+ close (sock);
+ return;
}
- g_list_foreach (the_list, (GFunc)gdm_address_free, NULL);
- g_list_free (the_list);
- the_list = NULL;
+ /* Get IP address of each active IP network interface. */
+ the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+
+ for (ifr = ifc.ifc_req; ifr < the_end; ifr++) {
+ if (ifr->ifr_addr.sa_family == AF_INET) {
+ /* IP net interface */
+ ifreq = *ifr;
+
+ if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
+ perror("SIOCGIFFLAGS");
+ } else if (ifreq.ifr_flags & IFF_UP) { /* active interface */
+ if (ioctl (sock, SIOCGIFADDR, (char *) &ifreq) < 0) {
+ perror("SIOCGIFADDR");
+ } else {
+ GdmAddress *address;
+ address = gdm_address_new_from_sockaddr ((struct sockaddr *)&ifreq.ifr_addr,
+ sizeof (struct sockaddr));
+
+ gdm_address_debug (address);
+
+ *list = g_list_append (*list, address);
+ }
+ }
+ }
+
+ /* Support for variable-length addresses. */
+#ifdef HAS_SA_LEN
+ ifr = (struct ifreq *) ((caddr_t) ifr
+ + ifr->ifr_addr.sa_len - sizeof(struct sockaddr));
+#endif
+ }
- last_time = time (NULL);
+ close (sock);
+}
+
+static void
+add_local_addrinfo (GList **list)
+{
+ char hostbuf[BUFSIZ];
+ struct addrinfo *result;
+ struct addrinfo *res;
+ struct addrinfo hints;
hostbuf[BUFSIZ-1] = '\0';
if (gethostname (hostbuf, BUFSIZ-1) != 0) {
@@ -306,26 +354,58 @@ gdm_address_peek_local_list (void)
snprintf (hostbuf, BUFSIZ-1, "localhost");
}
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_CANONNAME;
+
+ g_debug ("GdmAddress: looking up hostname: %s", hostbuf);
result = NULL;
- if (getaddrinfo (hostbuf, NULL, NULL, &result) != 0) {
+ if (getaddrinfo (hostbuf, NULL, &hints, &result) != 0) {
g_debug ("%s: Could not get address from hostname!", "gdm_peek_local_address_list");
- return NULL;
+ return;
}
for (res = result; res != NULL; res = res->ai_next) {
GdmAddress *address;
+ g_debug ("family=%d sock_type=%d protocol=%d flags=0x%x canonname=%s\n",
+ res->ai_family,
+ res->ai_socktype,
+ res->ai_protocol,
+ res->ai_flags,
+ res->ai_canonname);
address = gdm_address_new_from_sockaddr (res->ai_addr, res->ai_addrlen);
- the_list = g_list_append (the_list, address);
+ *list = g_list_append (*list, address);
}
if (result != NULL) {
freeaddrinfo (result);
result = NULL;
}
+}
+
+const GList *
+gdm_address_peek_local_list (void)
+{
+ static GList *list = NULL;
+ static time_t last_time = 0;
+
+ /* Don't check more then every 5 seconds */
+ if (last_time + 5 > time (NULL)) {
+ return list;
+ }
+
+ g_list_foreach (list, (GFunc)gdm_address_free, NULL);
+ g_list_free (list);
+ list = NULL;
+
+ last_time = time (NULL);
+
+ add_local_siocgifconf (&list);
+ add_local_addrinfo (&list);
- return the_list;
+ return list;
}
gboolean
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 81b2b718..2e9c10bd 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -32,9 +32,11 @@ BUILT_SOURCES = \
gdm-simple-slave-glue.h \
gdm-factory-slave-glue.h \
gdm-product-slave-glue.h \
+ gdm-xdmcp-chooser-slave-glue.h \
gdm-manager-glue.h \
gdm-display-glue.h \
- gdm-xdmcp-display-glue.h \
+ gdm-xdmcp-greeter-display-glue.h \
+ gdm-xdmcp-chooser-display-glue.h \
gdm-static-display-glue.h \
gdm-transient-display-glue.h \
gdm-local-display-factory-glue.h \
@@ -52,10 +54,14 @@ gdm-factory-slave-glue.h: gdm-factory-slave.xml Makefile.am
dbus-binding-tool --prefix=gdm_factory_slave --mode=glib-server --output=gdm-factory-slave-glue.h $(srcdir)/gdm-factory-slave.xml
gdm-product-slave-glue.h: gdm-product-slave.xml Makefile.am
dbus-binding-tool --prefix=gdm_product_slave --mode=glib-server --output=gdm-product-slave-glue.h $(srcdir)/gdm-product-slave.xml
+gdm-xdmcp-chooser-slave-glue.h: gdm-xdmcp-chooser-slave.xml Makefile.am
+ dbus-binding-tool --prefix=gdm_xdmcp_chooser_slave --mode=glib-server --output=gdm-xdmcp-chooser-slave-glue.h $(srcdir)/gdm-xdmcp-chooser-slave.xml
gdm-display-glue.h: gdm-display.xml Makefile.am
dbus-binding-tool --prefix=gdm_display --mode=glib-server --output=gdm-display-glue.h $(srcdir)/gdm-display.xml
-gdm-xdmcp-display-glue.h: gdm-xdmcp-display.xml Makefile.am
- dbus-binding-tool --prefix=gdm_xdmcp_display --mode=glib-server --output=gdm-xdmcp-display-glue.h $(srcdir)/gdm-xdmcp-display.xml
+gdm-xdmcp-greeter-display-glue.h: gdm-xdmcp-greeter-display.xml Makefile.am
+ dbus-binding-tool --prefix=gdm_xdmcp_greeter_display --mode=glib-server --output=gdm-xdmcp-greeter-display-glue.h $(srcdir)/gdm-xdmcp-greeter-display.xml
+gdm-xdmcp-chooser-display-glue.h: gdm-xdmcp-chooser-display.xml Makefile.am
+ dbus-binding-tool --prefix=gdm_xdmcp_chooser_display --mode=glib-server --output=gdm-xdmcp-chooser-display-glue.h $(srcdir)/gdm-xdmcp-chooser-display.xml
gdm-static-display-glue.h: gdm-static-display.xml Makefile.am
dbus-binding-tool --prefix=gdm_static_display --mode=glib-server --output=gdm-static-display-glue.h $(srcdir)/gdm-static-display.xml
gdm-transient-display-glue.h: gdm-transient-display.xml Makefile.am
@@ -106,6 +112,7 @@ libexec_PROGRAMS = \
gdm-simple-slave \
gdm-factory-slave \
gdm-product-slave \
+ gdm-xdmcp-chooser-slave \
gdm-session-worker \
$(NULL)
@@ -208,6 +215,25 @@ gdm_product_slave_LDADD = \
$(top_builddir)/common/libgdmcommon.la \
$(NULL)
+gdm_xdmcp_chooser_slave_SOURCES = \
+ xdmcp-chooser-slave-main.c \
+ gdm-chooser-server.c \
+ gdm-chooser-server.h \
+ gdm-chooser-session.c \
+ gdm-chooser-session.h \
+ gdm-slave.c \
+ gdm-slave.h \
+ gdm-xdmcp-chooser-slave.c \
+ gdm-xdmcp-chooser-slave.h \
+ $(NULL)
+
+gdm_xdmcp_chooser_slave_LDADD = \
+ $(XLIB_LIBS) \
+ $(DAEMON_LIBS) \
+ $(EXTRA_DAEMON_LIBS) \
+ $(top_builddir)/common/libgdmcommon.la \
+ $(NULL)
+
gdm_session_worker_SOURCES = \
session-worker-main.c \
gdm-session-worker.h \
@@ -241,6 +267,10 @@ gdm_binary_SOURCES = \
gdm-display.h \
gdm-xdmcp-display.c \
gdm-xdmcp-display.h \
+ gdm-xdmcp-greeter-display.c \
+ gdm-xdmcp-greeter-display.h \
+ gdm-xdmcp-chooser-display.c \
+ gdm-xdmcp-chooser-display.h \
gdm-static-display.c \
gdm-static-display.h \
gdm-transient-display.c \
@@ -309,9 +339,11 @@ EXTRA_DIST = \
gdm-simple-slave.xml \
gdm-factory-slave.xml \
gdm-product-slave.xml \
+ gdm-xdmcp-chooser-slave.xml \
gdm-manager.xml \
gdm-display.xml \
- gdm-xdmcp-display.xml \
+ gdm-xdmcp-greeter-display.xml \
+ gdm-xdmcp-chooser-display.xml \
gdm-static-display.xml \
gdm-transient-display.xml \
gdm-local-display-factory.xml \
diff --git a/daemon/gdm-chooser-server.c b/daemon/gdm-chooser-server.c
new file mode 100644
index 00000000..c53e7927
--- /dev/null
+++ b/daemon/gdm-chooser-server.c
@@ -0,0 +1,628 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+
+#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD)
+#include <sched.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "gdm-chooser-server.h"
+
+#define GDM_CHOOSER_SERVER_DBUS_PATH "/org/gnome/DisplayManager/ChooserServer"
+#define GDM_CHOOSER_SERVER_DBUS_INTERFACE "org.gnome.DisplayManager.ChooserServer"
+
+#define GDM_CHOOSER_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CHOOSER_SERVER, GdmChooserServerPrivate))
+
+struct GdmChooserServerPrivate
+{
+ char *user_name;
+ char *group_name;
+ char *display_id;
+
+ DBusServer *server;
+ char *server_address;
+ DBusConnection *chooser_connection;
+};
+
+enum {
+ PROP_0,
+ PROP_USER_NAME,
+ PROP_GROUP_NAME,
+ PROP_DISPLAY_ID,
+};
+
+enum {
+ HOSTNAME_SELECTED,
+ CONNECTED,
+ DISCONNECTED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void gdm_chooser_server_class_init (GdmChooserServerClass *klass);
+static void gdm_chooser_server_init (GdmChooserServer *chooser_server);
+static void gdm_chooser_server_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmChooserServer, gdm_chooser_server, G_TYPE_OBJECT)
+
+/* Note: Use abstract sockets like dbus does by default on Linux. Abstract
+ * sockets are only available on Linux.
+ */
+static char *
+generate_address (void)
+{
+ char *path;
+#if defined (__linux__)
+ int i;
+ char tmp[9];
+
+ for (i = 0; i < 8; i++) {
+ if (g_random_int_range (0, 2) == 0) {
+ tmp[i] = g_random_int_range ('a', 'z' + 1);
+ } else {
+ tmp[i] = g_random_int_range ('A', 'Z' + 1);
+ }
+ }
+ tmp[8] = '\0';
+
+ path = g_strdup_printf ("unix:abstract=/tmp/gdm-chooser-%s", tmp);
+#else
+ path = g_strdup ("unix:tmpdir=/tmp");
+#endif
+
+ return path;
+}
+
+static DBusHandlerResult
+handle_select_hostname (GdmChooserServer *chooser_server,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+ DBusError error;
+ const char *text;
+
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
+ }
+
+ g_debug ("ChooserServer: SelectHostname: %s", text);
+
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ g_signal_emit (chooser_server, signals [HOSTNAME_SELECTED], 0, text);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+handle_disconnect (GdmChooserServer *chooser_server,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ g_signal_emit (chooser_server, signals [DISCONNECTED], 0);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+chooser_handle_child_message (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GdmChooserServer *chooser_server = GDM_CHOOSER_SERVER (user_data);
+
+ if (dbus_message_is_method_call (message, GDM_CHOOSER_SERVER_DBUS_INTERFACE, "SelectHostname")) {
+ return handle_select_hostname (chooser_server, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_CHOOSER_SERVER_DBUS_INTERFACE, "Disconnect")) {
+ return handle_disconnect (chooser_server, connection, message);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult
+do_introspect (DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+ GString *xml;
+ char *xml_string;
+
+ g_debug ("ChooserServer: Do introspect");
+
+ /* standard header */
+ xml = g_string_new ("<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
+ "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
+ "<node>\n"
+ " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
+ " <method name=\"Introspect\">\n"
+ " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
+ " </method>\n"
+ " </interface>\n");
+
+ /* interface */
+ xml = g_string_append (xml,
+ " <interface name=\"org.gnome.DisplayManager.ChooserServer\">\n"
+ " <method name=\"SelectHostname\">\n"
+ " <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
+ " </method>\n"
+ " <method name=\"Disconnect\">\n"
+ " </method>\n"
+ " </interface>\n");
+
+ reply = dbus_message_new_method_return (message);
+
+ xml = g_string_append (xml, "</node>\n");
+ xml_string = g_string_free (xml, FALSE);
+
+ dbus_message_append_args (reply,
+ DBUS_TYPE_STRING, &xml_string,
+ DBUS_TYPE_INVALID);
+
+ g_free (xml_string);
+
+ if (reply == NULL) {
+ g_error ("No memory");
+ }
+
+ if (! dbus_connection_send (connection, reply, NULL)) {
+ g_error ("No memory");
+ }
+
+ dbus_message_unref (reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+chooser_server_message_handler (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ const char *dbus_destination = dbus_message_get_destination (message);
+ const char *dbus_path = dbus_message_get_path (message);
+ const char *dbus_interface = dbus_message_get_interface (message);
+ const char *dbus_member = dbus_message_get_member (message);
+
+ g_debug ("chooser_server_message_handler: destination=%s obj_path=%s interface=%s method=%s",
+ dbus_destination ? dbus_destination : "(null)",
+ dbus_path ? dbus_path : "(null)",
+ dbus_interface ? dbus_interface : "(null)",
+ dbus_member ? dbus_member : "(null)");
+
+ if (dbus_message_is_method_call (message, "org.freedesktop.DBus", "AddMatch")) {
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ if (reply == NULL) {
+ g_error ("No memory");
+ }
+
+ if (! dbus_connection_send (connection, reply, NULL)) {
+ g_error ("No memory");
+ }
+
+ dbus_message_unref (reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ } else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
+ strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
+
+ /*dbus_connection_unref (connection);*/
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ } else if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
+ return do_introspect (connection, message);
+ } else {
+ return chooser_handle_child_message (connection, message, user_data);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+chooser_server_unregister_handler (DBusConnection *connection,
+ void *user_data)
+{
+ g_debug ("chooser_server_unregister_handler");
+}
+
+static DBusHandlerResult
+connection_filter_function (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GdmChooserServer *chooser_server = GDM_CHOOSER_SERVER (user_data);
+ const char *dbus_path = dbus_message_get_path (message);
+ const char *dbus_interface = dbus_message_get_interface (message);
+ const char *dbus_message = dbus_message_get_member (message);
+
+ g_debug ("ChooserServer: obj_path=%s interface=%s method=%s",
+ dbus_path ? dbus_path : "(null)",
+ dbus_interface ? dbus_interface : "(null)",
+ dbus_message ? dbus_message : "(null)");
+
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")
+ && strcmp (dbus_path, DBUS_PATH_LOCAL) == 0) {
+
+ g_debug ("ChooserServer: Disconnected");
+
+ dbus_connection_unref (connection);
+ chooser_server->priv->chooser_connection = NULL;
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static dbus_bool_t
+allow_user_function (DBusConnection *connection,
+ unsigned long uid,
+ void *data)
+{
+ GdmChooserServer *chooser_server = GDM_CHOOSER_SERVER (data);
+ struct passwd *pwent;
+
+ if (chooser_server->priv->user_name == NULL) {
+ return FALSE;
+ }
+
+ pwent = getpwnam (chooser_server->priv->user_name);
+ if (pwent == NULL) {
+ return FALSE;
+ }
+
+ if (pwent->pw_uid == uid) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+handle_connection (DBusServer *server,
+ DBusConnection *new_connection,
+ void *user_data)
+{
+ GdmChooserServer *chooser_server = GDM_CHOOSER_SERVER (user_data);
+
+ g_debug ("ChooserServer: Handing new connection");
+
+ if (chooser_server->priv->chooser_connection == NULL) {
+ DBusObjectPathVTable vtable = { &chooser_server_unregister_handler,
+ &chooser_server_message_handler,
+ NULL, NULL, NULL, NULL
+ };
+
+ chooser_server->priv->chooser_connection = new_connection;
+ dbus_connection_ref (new_connection);
+ dbus_connection_setup_with_g_main (new_connection, NULL);
+
+ g_debug ("ChooserServer: chooser connection is %p", new_connection);
+
+ dbus_connection_add_filter (new_connection,
+ connection_filter_function,
+ chooser_server,
+ NULL);
+
+ dbus_connection_set_unix_user_function (new_connection,
+ allow_user_function,
+ chooser_server,
+ NULL);
+
+ dbus_connection_register_object_path (new_connection,
+ GDM_CHOOSER_SERVER_DBUS_PATH,
+ &vtable,
+ chooser_server);
+
+ g_signal_emit (chooser_server, signals[CONNECTED], 0);
+
+ }
+}
+
+gboolean
+gdm_chooser_server_start (GdmChooserServer *chooser_server)
+{
+ DBusError error;
+ gboolean ret;
+ char *address;
+ const char *auth_mechanisms[] = {"EXTERNAL", NULL};
+
+ ret = FALSE;
+
+ g_debug ("ChooserServer: Creating D-Bus server for chooser");
+
+ address = generate_address ();
+
+ dbus_error_init (&error);
+ chooser_server->priv->server = dbus_server_listen (address, &error);
+ g_free (address);
+
+ if (chooser_server->priv->server == NULL) {
+ g_warning ("Cannot create D-BUS server for the chooser: %s", error.message);
+ /* FIXME: should probably fail if we can't create the socket */
+ goto out;
+ }
+
+ dbus_server_setup_with_g_main (chooser_server->priv->server, NULL);
+ dbus_server_set_auth_mechanisms (chooser_server->priv->server, auth_mechanisms);
+ dbus_server_set_new_connection_function (chooser_server->priv->server,
+ handle_connection,
+ chooser_server,
+ NULL);
+ ret = TRUE;
+
+ g_free (chooser_server->priv->server_address);
+ chooser_server->priv->server_address = dbus_server_get_address (chooser_server->priv->server);
+
+ g_debug ("ChooserServer: D-Bus server listening on %s", chooser_server->priv->server_address);
+
+ out:
+
+ return ret;
+}
+
+gboolean
+gdm_chooser_server_stop (GdmChooserServer *chooser_server)
+{
+ gboolean ret;
+
+ ret = FALSE;
+
+ g_debug ("ChooserServer: Stopping chooser server...");
+
+ return ret;
+}
+
+char *
+gdm_chooser_server_get_address (GdmChooserServer *chooser_server)
+{
+ return g_strdup (chooser_server->priv->server_address);
+}
+
+static void
+_gdm_chooser_server_set_display_id (GdmChooserServer *chooser_server,
+ const char *display_id)
+{
+ g_free (chooser_server->priv->display_id);
+ chooser_server->priv->display_id = g_strdup (display_id);
+}
+
+static void
+_gdm_chooser_server_set_user_name (GdmChooserServer *chooser_server,
+ const char *name)
+{
+ g_free (chooser_server->priv->user_name);
+ chooser_server->priv->user_name = g_strdup (name);
+}
+
+static void
+_gdm_chooser_server_set_group_name (GdmChooserServer *chooser_server,
+ const char *name)
+{
+ g_free (chooser_server->priv->group_name);
+ chooser_server->priv->group_name = g_strdup (name);
+}
+
+static void
+gdm_chooser_server_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdmChooserServer *self;
+
+ self = GDM_CHOOSER_SERVER (object);
+
+ switch (prop_id) {
+ case PROP_DISPLAY_ID:
+ _gdm_chooser_server_set_display_id (self, g_value_get_string (value));
+ break;
+ case PROP_USER_NAME:
+ _gdm_chooser_server_set_user_name (self, g_value_get_string (value));
+ break;
+ case PROP_GROUP_NAME:
+ _gdm_chooser_server_set_group_name (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdm_chooser_server_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdmChooserServer *self;
+
+ self = GDM_CHOOSER_SERVER (object);
+
+ switch (prop_id) {
+ case PROP_DISPLAY_ID:
+ g_value_set_string (value, self->priv->display_id);
+ break;
+ case PROP_USER_NAME:
+ g_value_set_string (value, self->priv->user_name);
+ break;
+ case PROP_GROUP_NAME:
+ g_value_set_string (value, self->priv->group_name);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gdm_chooser_server_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GdmChooserServer *chooser_server;
+ GdmChooserServerClass *klass;
+
+ klass = GDM_CHOOSER_SERVER_CLASS (g_type_class_peek (GDM_TYPE_CHOOSER_SERVER));
+
+ chooser_server = GDM_CHOOSER_SERVER (G_OBJECT_CLASS (gdm_chooser_server_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (chooser_server);
+}
+
+static void
+gdm_chooser_server_class_init (GdmChooserServerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gdm_chooser_server_get_property;
+ object_class->set_property = gdm_chooser_server_set_property;
+ object_class->constructor = gdm_chooser_server_constructor;
+ object_class->finalize = gdm_chooser_server_finalize;
+
+ g_type_class_add_private (klass, sizeof (GdmChooserServerPrivate));
+
+ g_object_class_install_property (object_class,
+ PROP_DISPLAY_ID,
+ g_param_spec_string ("display-id",
+ "display id",
+ "display id",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
+ PROP_USER_NAME,
+ g_param_spec_string ("user-name",
+ "user name",
+ "user name",
+ "gdm",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
+ PROP_GROUP_NAME,
+ g_param_spec_string ("group-name",
+ "group name",
+ "group name",
+ "gdm",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ signals [HOSTNAME_SELECTED] =
+ g_signal_new ("hostname-selected",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmChooserServerClass, hostname_selected),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+ signals [CONNECTED] =
+ g_signal_new ("connected",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmChooserServerClass, connected),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ signals [DISCONNECTED] =
+ g_signal_new ("disconnected",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmChooserServerClass, disconnected),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+static void
+gdm_chooser_server_init (GdmChooserServer *chooser_server)
+{
+
+ chooser_server->priv = GDM_CHOOSER_SERVER_GET_PRIVATE (chooser_server);
+}
+
+static void
+gdm_chooser_server_finalize (GObject *object)
+{
+ GdmChooserServer *chooser_server;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_CHOOSER_SERVER (object));
+
+ chooser_server = GDM_CHOOSER_SERVER (object);
+
+ g_return_if_fail (chooser_server->priv != NULL);
+
+ gdm_chooser_server_stop (chooser_server);
+
+ G_OBJECT_CLASS (gdm_chooser_server_parent_class)->finalize (object);
+}
+
+GdmChooserServer *
+gdm_chooser_server_new (const char *display_id)
+{
+ GObject *object;
+
+ object = g_object_new (GDM_TYPE_CHOOSER_SERVER,
+ "display-id", display_id,
+ NULL);
+
+ return GDM_CHOOSER_SERVER (object);
+}
diff --git a/daemon/gdm-chooser-server.h b/daemon/gdm-chooser-server.h
new file mode 100644
index 00000000..e5d4fee5
--- /dev/null
+++ b/daemon/gdm-chooser-server.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * 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.
+ *
+ */
+
+
+#ifndef __GDM_CHOOSER_SERVER_H
+#define __GDM_CHOOSER_SERVER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_CHOOSER_SERVER (gdm_chooser_server_get_type ())
+#define GDM_CHOOSER_SERVER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_CHOOSER_SERVER, GdmChooserServer))
+#define GDM_CHOOSER_SERVER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_CHOOSER_SERVER, GdmChooserServerClass))
+#define GDM_IS_CHOOSER_SERVER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_CHOOSER_SERVER))
+#define GDM_IS_CHOOSER_SERVER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_CHOOSER_SERVER))
+#define GDM_CHOOSER_SERVER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_CHOOSER_SERVER, GdmChooserServerClass))
+
+typedef struct GdmChooserServerPrivate GdmChooserServerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GdmChooserServerPrivate *priv;
+} GdmChooserServer;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ void (* hostname_selected) (GdmChooserServer *chooser_server,
+ const char *hostname);
+ void (* connected) (GdmChooserServer *chooser_server);
+ void (* disconnected) (GdmChooserServer *chooser_server);
+} GdmChooserServerClass;
+
+GType gdm_chooser_server_get_type (void);
+GdmChooserServer * gdm_chooser_server_new (const char *display_id);
+
+gboolean gdm_chooser_server_start (GdmChooserServer *chooser_server);
+gboolean gdm_chooser_server_stop (GdmChooserServer *chooser_server);
+char * gdm_chooser_server_get_address (GdmChooserServer *chooser_server);
+
+G_END_DECLS
+
+#endif /* __GDM_CHOOSER_SERVER_H */
diff --git a/daemon/gdm-chooser-session.c b/daemon/gdm-chooser-session.c
new file mode 100644
index 00000000..0c2c04e8
--- /dev/null
+++ b/daemon/gdm-chooser-session.c
@@ -0,0 +1,948 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+#include <signal.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "gdm-common.h"
+
+#include "gdm-chooser-session.h"
+
+#define DBUS_LAUNCH_COMMAND BINDIR "/dbus-launch --exit-with-session"
+
+#define GDM_CHOOSER_SERVER_DBUS_PATH "/org/gnome/DisplayManager/ChooserServer"
+#define GDM_CHOOSER_SERVER_DBUS_INTERFACE "org.gnome.DisplayManager.ChooserServer"
+
+extern char **environ;
+
+#define GDM_CHOOSER_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CHOOSER_SESSION, GdmChooserSessionPrivate))
+
+struct GdmChooserSessionPrivate
+{
+ char *command;
+ GPid pid;
+
+ char *user_name;
+ char *group_name;
+
+ char *x11_display_name;
+ char *x11_display_device;
+ char *x11_display_hostname;
+ char *x11_authority_file;
+
+ guint child_watch_id;
+
+ GPid dbus_pid;
+ char *dbus_bus_address;
+
+ char *server_address;
+};
+
+enum {
+ PROP_0,
+ PROP_X11_DISPLAY_NAME,
+ PROP_X11_DISPLAY_DEVICE,
+ PROP_X11_DISPLAY_HOSTNAME,
+ PROP_X11_AUTHORITY_FILE,
+ PROP_USER_NAME,
+ PROP_GROUP_NAME,
+ PROP_SERVER_ADDRESS,
+};
+
+enum {
+ STARTED,
+ STOPPED,
+ EXITED,
+ DIED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void gdm_chooser_session_class_init (GdmChooserSessionClass *klass);
+static void gdm_chooser_session_init (GdmChooserSession *chooser_session);
+static void gdm_chooser_session_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmChooserSession, gdm_chooser_session, G_TYPE_OBJECT)
+
+static void
+listify_hash (const char *key,
+ const char *value,
+ GPtrArray *env)
+{
+ char *str;
+ str = g_strdup_printf ("%s=%s", key, value);
+ g_debug ("GdmChooserSession: chooser environment: %s", str);
+ g_ptr_array_add (env, str);
+}
+
+static GPtrArray *
+get_chooser_environment (GdmChooserSession *chooser_session)
+{
+ GPtrArray *env;
+ GHashTable *hash;
+ struct passwd *pwent;
+
+ env = g_ptr_array_new ();
+
+ /* create a hash table of current environment, then update keys has necessary */
+ hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ if (chooser_session->priv->dbus_bus_address != NULL) {
+ g_hash_table_insert (hash, g_strdup ("DBUS_SESSION_BUS_ADDRESS"), g_strdup (chooser_session->priv->dbus_bus_address));
+ }
+ if (chooser_session->priv->server_address != NULL) {
+ g_hash_table_insert (hash, g_strdup ("GDM_CHOOSER_DBUS_ADDRESS"), g_strdup (chooser_session->priv->server_address));
+ }
+
+ g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (chooser_session->priv->x11_authority_file));
+ g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (chooser_session->priv->x11_display_name));
+
+#if 0
+ /* hackish ain't it */
+ set_xnest_parent_stuff ();
+#endif
+
+ g_hash_table_insert (hash, g_strdup ("LOGNAME"), g_strdup (chooser_session->priv->user_name));
+ g_hash_table_insert (hash, g_strdup ("USER"), g_strdup (chooser_session->priv->user_name));
+ g_hash_table_insert (hash, g_strdup ("USERNAME"), g_strdup (chooser_session->priv->user_name));
+
+ g_hash_table_insert (hash, g_strdup ("GDM_VERSION"), g_strdup (VERSION));
+ g_hash_table_remove (hash, "MAIL");
+
+ g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup ("/"));
+ g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup ("/"));
+ g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup ("/bin/sh"));
+
+ pwent = getpwnam (chooser_session->priv->user_name);
+ if (pwent != NULL) {
+ if (pwent->pw_dir != NULL && pwent->pw_dir[0] != '\0') {
+ g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup (pwent->pw_dir));
+ g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup (pwent->pw_dir));
+ }
+
+ g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup (pwent->pw_shell));
+ }
+
+
+ g_hash_table_insert (hash, g_strdup ("PATH"), g_strdup (g_getenv ("PATH")));
+
+ g_hash_table_insert (hash, g_strdup ("RUNNING_UNDER_GDM"), g_strdup ("true"));
+
+ g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
+ g_hash_table_destroy (hash);
+
+ g_ptr_array_add (env, NULL);
+
+ return env;
+}
+
+static void
+chooser_session_child_watch (GPid pid,
+ int status,
+ GdmChooserSession *session)
+{
+ g_debug ("GdmChooserSession: child (pid:%d) done (%s:%d)",
+ (int) pid,
+ WIFEXITED (status) ? "status"
+ : WIFSIGNALED (status) ? "signal"
+ : "unknown",
+ WIFEXITED (status) ? WEXITSTATUS (status)
+ : WIFSIGNALED (status) ? WTERMSIG (status)
+ : -1);
+
+ if (WIFEXITED (status)) {
+ int code = WEXITSTATUS (status);
+ g_signal_emit (session, signals [EXITED], 0, code);
+ } else if (WIFSIGNALED (status)) {
+ int num = WTERMSIG (status);
+ g_signal_emit (session, signals [DIED], 0, num);
+ }
+
+ g_spawn_close_pid (session->priv->pid);
+ session->priv->pid = -1;
+}
+
+typedef struct {
+ const char *user_name;
+ const char *group_name;
+} SpawnChildData;
+
+static void
+spawn_child_setup (SpawnChildData *data)
+{
+ struct passwd *pwent;
+ struct group *grent;
+
+ if (data->user_name == NULL) {
+ return;
+ }
+
+ pwent = getpwnam (data->user_name);
+ if (pwent == NULL) {
+ g_warning (_("User %s doesn't exist"),
+ data->user_name);
+ _exit (1);
+ }
+
+ grent = getgrnam (data->group_name);
+ if (grent == NULL) {
+ g_warning (_("Group %s doesn't exist"),
+ data->group_name);
+ _exit (1);
+ }
+
+ g_debug ("GdmChooserSession: Changing (uid:gid) for child process to (%d:%d)",
+ pwent->pw_uid,
+ grent->gr_gid);
+
+ if (pwent->pw_uid != 0) {
+ if (setgid (grent->gr_gid) < 0) {
+ g_warning (_("Couldn't set groupid to %d"),
+ grent->gr_gid);
+ _exit (1);
+ }
+
+ if (initgroups (pwent->pw_name, pwent->pw_gid) < 0) {
+ g_warning (_("initgroups () failed for %s"),
+ pwent->pw_name);
+ _exit (1);
+ }
+
+ if (setuid (pwent->pw_uid) < 0) {
+ g_warning (_("Couldn't set userid to %d"),
+ (int)pwent->pw_uid);
+ _exit (1);
+ }
+ } else {
+ gid_t groups[1] = { 0 };
+
+ if (setgid (0) < 0) {
+ g_warning (_("Couldn't set groupid to 0"));
+ /* Don't error out, it's not fatal, if it fails we'll
+ * just still be */
+ }
+
+ /* this will get rid of any suplementary groups etc... */
+ setgroups (1, groups);
+ }
+
+ if (setsid () < 0) {
+ g_debug ("GdmChooserSession: could not set pid '%u' as leader of new session and process group - %s",
+ (guint) getpid (), g_strerror (errno));
+ _exit (2);
+ }
+}
+
+static gboolean
+spawn_command_line_sync_as_user (const char *command_line,
+ const char *user_name,
+ const char *group_name,
+ char **env,
+ char **std_output,
+ char **std_error,
+ int *exit_status,
+ GError **error)
+{
+ char **argv;
+ GError *local_error;
+ gboolean ret;
+ gboolean res;
+ SpawnChildData data;
+
+ ret = FALSE;
+
+ argv = NULL;
+ local_error = NULL;
+ if (! g_shell_parse_argv (command_line, NULL, &argv, &local_error)) {
+ g_warning ("Could not parse command: %s", local_error->message);
+ g_propagate_error (error, local_error);
+ goto out;
+ }
+
+ data.user_name = user_name;
+ data.group_name = group_name;
+
+ local_error = NULL;
+ res = g_spawn_sync (NULL,
+ argv,
+ env,
+ G_SPAWN_SEARCH_PATH,
+ (GSpawnChildSetupFunc)spawn_child_setup,
+ &data,
+ std_output,
+ std_error,
+ exit_status,
+ &local_error);
+
+ if (! res) {
+ g_warning ("Could not spawn command: %s", local_error->message);
+ g_propagate_error (error, local_error);
+ goto out;
+ }
+
+ ret = TRUE;
+ out:
+ g_strfreev (argv);
+
+ return ret;
+}
+
+static gboolean
+spawn_command_line_async_as_user (const char *command_line,
+ const char *user_name,
+ const char *group_name,
+ char **env,
+ GPid *child_pid,
+ GError **error)
+{
+ char **argv;
+ GError *local_error;
+ gboolean ret;
+ gboolean res;
+ SpawnChildData data;
+
+ ret = FALSE;
+
+ argv = NULL;
+ local_error = NULL;
+ if (! g_shell_parse_argv (command_line, NULL, &argv, &local_error)) {
+ g_warning ("Could not parse command: %s", local_error->message);
+ g_propagate_error (error, local_error);
+ goto out;
+ }
+
+ data.user_name = user_name;
+ data.group_name = group_name;
+
+ local_error = NULL;
+ res = g_spawn_async (NULL,
+ argv,
+ env,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+ (GSpawnChildSetupFunc)spawn_child_setup,
+ &data,
+ child_pid,
+ &local_error);
+ if (! res) {
+ g_warning ("Could not spawn command: %s", local_error->message);
+ g_propagate_error (error, local_error);
+ goto out;
+ }
+
+ ret = TRUE;
+ out:
+ g_strfreev (argv);
+
+ return ret;
+}
+
+static gboolean
+parse_value_as_integer (const char *value,
+ int *intval)
+{
+ char *end_of_valid_int;
+ glong long_value;
+ gint int_value;
+
+ errno = 0;
+ long_value = strtol (value, &end_of_valid_int, 10);
+
+ if (*value == '\0' || *end_of_valid_int != '\0') {
+ return FALSE;
+ }
+
+ int_value = long_value;
+ if (int_value != long_value || errno == ERANGE) {
+ return FALSE;
+ }
+
+ *intval = int_value;
+
+ return TRUE;
+}
+
+static gboolean
+parse_dbus_launch_output (const char *output,
+ char **addressp,
+ GPid *pidp)
+{
+ GRegex *re;
+ GMatchInfo *match_info;
+ gboolean ret;
+ gboolean res;
+ GError *error;
+
+ ret = FALSE;
+
+ error = NULL;
+ re = g_regex_new ("DBUS_SESSION_BUS_ADDRESS=(.+)\nDBUS_SESSION_BUS_PID=([0-9]+)", 0, 0, &error);
+ if (re == NULL) {
+ g_critical (error->message);
+ }
+
+ g_regex_match (re, output, 0, &match_info);
+
+ res = g_match_info_matches (match_info);
+ if (! res) {
+ g_warning ("Unable to parse output: %s", output);
+ goto out;
+ }
+
+ if (addressp != NULL) {
+ *addressp = g_strdup (g_match_info_fetch (match_info, 1));
+ }
+
+ if (pidp != NULL) {
+ int pid;
+ gboolean res;
+ res = parse_value_as_integer (g_match_info_fetch (match_info, 2), &pid);
+ if (res) {
+ *pidp = pid;
+ } else {
+ *pidp = 0;
+ }
+ }
+
+ ret = TRUE;
+
+ out:
+ g_match_info_free (match_info);
+ g_regex_unref (re);
+
+ return ret;
+}
+
+static gboolean
+start_dbus_daemon (GdmChooserSession *chooser_session)
+{
+ gboolean res;
+ char *std_out;
+ char *std_err;
+ int exit_status;
+ GError *error;
+ GPtrArray *env;
+
+ env = get_chooser_environment (chooser_session);
+
+ error = NULL;
+ res = spawn_command_line_sync_as_user (DBUS_LAUNCH_COMMAND,
+ chooser_session->priv->user_name,
+ chooser_session->priv->group_name,
+ (char **)env->pdata,
+ &std_out,
+ &std_err,
+ &exit_status,
+ &error);
+ g_ptr_array_foreach (env, (GFunc)g_free, NULL);
+ g_ptr_array_free (env, TRUE);
+
+ if (! res) {
+ g_warning ("Unable to launch D-Bus daemon: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* pull the address and pid from the output */
+ res = parse_dbus_launch_output (std_out,
+ &chooser_session->priv->dbus_bus_address,
+ &chooser_session->priv->dbus_pid);
+ if (! res) {
+ g_warning ("Unable to parse D-Bus launch output");
+ } else {
+ g_debug ("GdmChooserSession: Started D-Bus daemon on pid %d", chooser_session->priv->dbus_pid);
+ }
+ out:
+ return res;
+}
+
+static gboolean
+stop_dbus_daemon (GdmChooserSession *chooser_session)
+{
+ if (chooser_session->priv->dbus_pid > 0) {
+ gdm_signal_pid (-1 * chooser_session->priv->dbus_pid, SIGTERM);
+ chooser_session->priv->dbus_pid = 0;
+ }
+ return TRUE;
+}
+
+static gboolean
+gdm_chooser_session_spawn (GdmChooserSession *chooser_session)
+{
+ GError *error;
+ GPtrArray *env;
+ gboolean ret;
+ gboolean res;
+
+ ret = FALSE;
+
+ g_debug ("GdmChooserSession: Running chooser_session process: %s", chooser_session->priv->command);
+
+ res = start_dbus_daemon (chooser_session);
+ if (! res) {
+ /* FIXME: */
+ }
+
+ env = get_chooser_environment (chooser_session);
+
+ error = NULL;
+
+ ret = spawn_command_line_async_as_user (chooser_session->priv->command,
+ chooser_session->priv->user_name,
+ chooser_session->priv->group_name,
+ (char **)env->pdata,
+ &chooser_session->priv->pid,
+ &error);
+
+ g_ptr_array_foreach (env, (GFunc)g_free, NULL);
+ g_ptr_array_free (env, TRUE);
+
+ if (! ret) {
+ g_warning ("Could not start command '%s': %s",
+ chooser_session->priv->command,
+ error->message);
+ g_error_free (error);
+ goto out;
+ } else {
+ g_debug ("GdmChooserSession: ChooserSession on pid %d", (int)chooser_session->priv->pid);
+ }
+
+ chooser_session->priv->child_watch_id = g_child_watch_add (chooser_session->priv->pid,
+ (GChildWatchFunc)chooser_session_child_watch,
+ chooser_session);
+
+ out:
+
+ return ret;
+}
+
+/**
+ * gdm_chooser_session_start:
+ * @disp: Pointer to a GdmDisplay structure
+ *
+ * Starts a local X chooser_session. Handles retries and fatal errors properly.
+ */
+gboolean
+gdm_chooser_session_start (GdmChooserSession *chooser_session)
+{
+ gboolean res;
+
+ g_debug ("GdmChooserSession: Starting chooser...");
+
+ res = gdm_chooser_session_spawn (chooser_session);
+
+ if (res) {
+
+ }
+
+
+ return res;
+}
+
+static int
+wait_on_child (int pid)
+{
+ int status;
+
+ wait_again:
+ if (waitpid (pid, &status, 0) < 0) {
+ if (errno == EINTR) {
+ goto wait_again;
+ } else if (errno == ECHILD) {
+ ; /* do nothing, child already reaped */
+ } else {
+ g_debug ("GdmChooserSession: waitpid () should not fail");
+ }
+ }
+
+ return status;
+}
+
+static void
+chooser_session_died (GdmChooserSession *chooser_session)
+{
+ int exit_status;
+
+ g_debug ("GdmChooserSession: Waiting on process %d", chooser_session->priv->pid);
+ exit_status = wait_on_child (chooser_session->priv->pid);
+
+ if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
+ g_debug ("GdmChooserSession: Wait on child process failed");
+ } else {
+ /* exited normally */
+ }
+
+ g_spawn_close_pid (chooser_session->priv->pid);
+ chooser_session->priv->pid = -1;
+
+ g_debug ("GdmChooserSession: ChooserSession died");
+}
+
+gboolean
+gdm_chooser_session_stop (GdmChooserSession *chooser_session)
+{
+
+ if (chooser_session->priv->pid <= 1) {
+ return TRUE;
+ }
+
+ /* remove watch source before we can wait on child */
+ if (chooser_session->priv->child_watch_id > 0) {
+ g_source_remove (chooser_session->priv->child_watch_id);
+ chooser_session->priv->child_watch_id = 0;
+ }
+
+ g_debug ("GdmChooserSession: Stopping chooser_session");
+
+ gdm_signal_pid (-1 * chooser_session->priv->pid, SIGTERM);
+ chooser_session_died (chooser_session);
+
+ stop_dbus_daemon (chooser_session);
+
+ return TRUE;
+}
+
+void
+gdm_chooser_session_set_server_address (GdmChooserSession *chooser_session,
+ const char *address)
+{
+ g_return_if_fail (GDM_IS_CHOOSER_SESSION (chooser_session));
+
+ g_free (chooser_session->priv->server_address);
+ chooser_session->priv->server_address = g_strdup (address);
+}
+
+static void
+_gdm_chooser_session_set_x11_display_name (GdmChooserSession *chooser_session,
+ const char *name)
+{
+ g_free (chooser_session->priv->x11_display_name);
+ chooser_session->priv->x11_display_name = g_strdup (name);
+}
+
+static void
+_gdm_chooser_session_set_x11_display_hostname (GdmChooserSession *chooser_session,
+ const char *name)
+{
+ g_free (chooser_session->priv->x11_display_hostname);
+ chooser_session->priv->x11_display_hostname = g_strdup (name);
+}
+
+static void
+_gdm_chooser_session_set_x11_display_device (GdmChooserSession *chooser_session,
+ const char *name)
+{
+ g_free (chooser_session->priv->x11_display_device);
+ chooser_session->priv->x11_display_device = g_strdup (name);
+}
+
+static void
+_gdm_chooser_session_set_x11_authority_file (GdmChooserSession *chooser_session,
+ const char *file)
+{
+ g_free (chooser_session->priv->x11_authority_file);
+ chooser_session->priv->x11_authority_file = g_strdup (file);
+}
+
+static void
+_gdm_chooser_session_set_user_name (GdmChooserSession *chooser_session,
+ const char *name)
+{
+ g_free (chooser_session->priv->user_name);
+ chooser_session->priv->user_name = g_strdup (name);
+}
+
+static void
+_gdm_chooser_session_set_group_name (GdmChooserSession *chooser_session,
+ const char *name)
+{
+ g_free (chooser_session->priv->group_name);
+ chooser_session->priv->group_name = g_strdup (name);
+}
+
+static void
+gdm_chooser_session_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdmChooserSession *self;
+
+ self = GDM_CHOOSER_SESSION (object);
+
+ switch (prop_id) {
+ case PROP_X11_DISPLAY_NAME:
+ _gdm_chooser_session_set_x11_display_name (self, g_value_get_string (value));
+ break;
+ case PROP_X11_DISPLAY_HOSTNAME:
+ _gdm_chooser_session_set_x11_display_hostname (self, g_value_get_string (value));
+ break;
+ case PROP_X11_DISPLAY_DEVICE:
+ _gdm_chooser_session_set_x11_display_device (self, g_value_get_string (value));
+ break;
+ case PROP_X11_AUTHORITY_FILE:
+ _gdm_chooser_session_set_x11_authority_file (self, g_value_get_string (value));
+ break;
+ case PROP_USER_NAME:
+ _gdm_chooser_session_set_user_name (self, g_value_get_string (value));
+ break;
+ case PROP_GROUP_NAME:
+ _gdm_chooser_session_set_group_name (self, g_value_get_string (value));
+ break;
+ case PROP_SERVER_ADDRESS:
+ gdm_chooser_session_set_server_address (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdm_chooser_session_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdmChooserSession *self;
+
+ self = GDM_CHOOSER_SESSION (object);
+
+ switch (prop_id) {
+ case PROP_X11_DISPLAY_NAME:
+ g_value_set_string (value, self->priv->x11_display_name);
+ break;
+ case PROP_X11_DISPLAY_HOSTNAME:
+ g_value_set_string (value, self->priv->x11_display_hostname);
+ break;
+ case PROP_X11_DISPLAY_DEVICE:
+ g_value_set_string (value, self->priv->x11_display_device);
+ break;
+ case PROP_X11_AUTHORITY_FILE:
+ g_value_set_string (value, self->priv->x11_authority_file);
+ break;
+ case PROP_USER_NAME:
+ g_value_set_string (value, self->priv->user_name);
+ break;
+ case PROP_GROUP_NAME:
+ g_value_set_string (value, self->priv->group_name);
+ break;
+ case PROP_SERVER_ADDRESS:
+ g_value_set_string (value, self->priv->server_address);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gdm_chooser_session_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GdmChooserSession *chooser_session;
+ GdmChooserSessionClass *klass;
+
+ klass = GDM_CHOOSER_SESSION_CLASS (g_type_class_peek (GDM_TYPE_CHOOSER_SESSION));
+
+ chooser_session = GDM_CHOOSER_SESSION (G_OBJECT_CLASS (gdm_chooser_session_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (chooser_session);
+}
+
+static void
+gdm_chooser_session_class_init (GdmChooserSessionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gdm_chooser_session_get_property;
+ object_class->set_property = gdm_chooser_session_set_property;
+ object_class->constructor = gdm_chooser_session_constructor;
+ object_class->finalize = gdm_chooser_session_finalize;
+
+ g_type_class_add_private (klass, sizeof (GdmChooserSessionPrivate));
+
+ g_object_class_install_property (object_class,
+ PROP_X11_DISPLAY_NAME,
+ g_param_spec_string ("x11-display-name",
+ "name",
+ "name",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_X11_DISPLAY_HOSTNAME,
+ g_param_spec_string ("x11-display-hostname",
+ "hostname",
+ "hostname",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_X11_DISPLAY_DEVICE,
+ g_param_spec_string ("x11-display-device",
+ "device",
+ "device",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_X11_AUTHORITY_FILE,
+ g_param_spec_string ("x11-authority-file",
+ "authority file",
+ "authority file",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
+ PROP_USER_NAME,
+ g_param_spec_string ("user-name",
+ "user name",
+ "user name",
+ "gdm",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
+ PROP_GROUP_NAME,
+ g_param_spec_string ("group-name",
+ "group name",
+ "group name",
+ "gdm",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
+ PROP_SERVER_ADDRESS,
+ g_param_spec_string ("server-address",
+ "server address",
+ "server address",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ signals [STARTED] =
+ g_signal_new ("started",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmChooserSessionClass, started),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ signals [STOPPED] =
+ g_signal_new ("stopped",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmChooserSessionClass, stopped),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ signals [EXITED] =
+ g_signal_new ("exited",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmChooserSessionClass, exited),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_INT);
+ signals [DIED] =
+ g_signal_new ("died",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmChooserSessionClass, died),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_INT);
+}
+
+static void
+gdm_chooser_session_init (GdmChooserSession *chooser_session)
+{
+
+ chooser_session->priv = GDM_CHOOSER_SESSION_GET_PRIVATE (chooser_session);
+
+ chooser_session->priv->pid = -1;
+
+ chooser_session->priv->command = g_strdup (LIBEXECDIR "/gdm-simple-chooser");
+}
+
+static void
+gdm_chooser_session_finalize (GObject *object)
+{
+ GdmChooserSession *chooser_session;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_CHOOSER_SESSION (object));
+
+ chooser_session = GDM_CHOOSER_SESSION (object);
+
+ g_return_if_fail (chooser_session->priv != NULL);
+
+ gdm_chooser_session_stop (chooser_session);
+
+ g_free (chooser_session->priv->command);
+ g_free (chooser_session->priv->user_name);
+ g_free (chooser_session->priv->group_name);
+ g_free (chooser_session->priv->x11_display_name);
+ g_free (chooser_session->priv->x11_display_device);
+ g_free (chooser_session->priv->x11_display_hostname);
+ g_free (chooser_session->priv->x11_authority_file);
+ g_free (chooser_session->priv->server_address);
+
+ G_OBJECT_CLASS (gdm_chooser_session_parent_class)->finalize (object);
+}
+
+GdmChooserSession *
+gdm_chooser_session_new (const char *display_name,
+ const char *display_device,
+ const char *display_hostname)
+{
+ GObject *object;
+
+ object = g_object_new (GDM_TYPE_CHOOSER_SESSION,
+ "x11-display-name", display_name,
+ "x11-display-device", display_device,
+ "x11-display-hostname", display_hostname,
+ NULL);
+
+ return GDM_CHOOSER_SESSION (object);
+}
diff --git a/daemon/gdm-chooser-session.h b/daemon/gdm-chooser-session.h
new file mode 100644
index 00000000..c2999b2a
--- /dev/null
+++ b/daemon/gdm-chooser-session.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * 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.
+ *
+ */
+
+
+#ifndef __GDM_CHOOSER_SESSION_H
+#define __GDM_CHOOSER_SESSION_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_CHOOSER_SESSION (gdm_chooser_session_get_type ())
+#define GDM_CHOOSER_SESSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_CHOOSER_SESSION, GdmChooserSession))
+#define GDM_CHOOSER_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_CHOOSER_SESSION, GdmChooserSessionClass))
+#define GDM_IS_CHOOSER_SESSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_CHOOSER_SESSION))
+#define GDM_IS_CHOOSER_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_CHOOSER_SESSION))
+#define GDM_CHOOSER_SESSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_CHOOSER_SESSION, GdmChooserSessionClass))
+
+typedef struct GdmChooserSessionPrivate GdmChooserSessionPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GdmChooserSessionPrivate *priv;
+} GdmChooserSession;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ void (* started) (GdmChooserSession *chooser_session);
+ void (* stopped) (GdmChooserSession *chooser_session);
+ void (* exited) (GdmChooserSession *chooser_session,
+ int exit_code);
+ void (* died) (GdmChooserSession *chooser_session,
+ int signal_number);
+} GdmChooserSessionClass;
+
+GType gdm_chooser_session_get_type (void);
+GdmChooserSession * gdm_chooser_session_new (const char *display_name,
+ const char *display_device,
+ const char *display_hostname);
+void gdm_chooser_session_set_server_address (GdmChooserSession *chooser_session,
+ const char *server_address);
+gboolean gdm_chooser_session_start (GdmChooserSession *chooser_session);
+gboolean gdm_chooser_session_stop (GdmChooserSession *chooser_session);
+
+G_END_DECLS
+
+#endif /* __GDM_CHOOSER_SESSION_H */
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index e952e36f..fbae90b9 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -47,25 +47,25 @@ static guint32 display_serial = 1;
struct GdmDisplayPrivate
{
- char *id;
- char *seat_id;
+ char *id;
+ char *seat_id;
- char *remote_hostname;
- int x11_display_number;
- char *x11_display_name;
- int status;
- time_t creation_time;
- char *slave_command;
+ char *remote_hostname;
+ int x11_display_number;
+ char *x11_display_name;
+ int status;
+ time_t creation_time;
+ char *slave_command;
char *x11_cookie;
gsize x11_cookie_size;
GdmDisplayAccessFile *access_file;
- gboolean is_local;
- guint finish_idle_id;
+ gboolean is_local;
+ guint finish_idle_id;
- GdmSlaveProxy *slave_proxy;
- DBusGConnection *connection;
+ GdmSlaveProxy *slave_proxy;
+ DBusGConnection *connection;
GdmDisplayAccessFile *user_access_file;
};
@@ -263,6 +263,33 @@ gdm_display_add_user_authorization (GdmDisplay *display,
}
static gboolean
+gdm_display_real_set_slave_bus_name (GdmDisplay *display,
+ const char *name,
+ GError **error)
+{
+
+ return TRUE;
+}
+
+gboolean
+gdm_display_set_slave_bus_name (GdmDisplay *display,
+ const char *name,
+ GError **error)
+{
+ gboolean ret;
+
+ g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE);
+
+ g_debug ("Setting slave bus name:%s on display %s", name, display->priv->x11_display_name);
+
+ g_object_ref (display);
+ ret = GDM_DISPLAY_GET_CLASS (display)->set_slave_bus_name (display, name, error);
+ g_object_unref (display);
+
+ return ret;
+}
+
+static gboolean
gdm_display_real_remove_user_authorization (GdmDisplay *display,
const char *username,
GError **error)
@@ -802,6 +829,7 @@ gdm_display_class_init (GdmDisplayClass *klass)
klass->create_authority = gdm_display_real_create_authority;
klass->add_user_authorization = gdm_display_real_add_user_authorization;
klass->remove_user_authorization = gdm_display_real_remove_user_authorization;
+ klass->set_slave_bus_name = gdm_display_real_set_slave_bus_name;
klass->manage = gdm_display_real_manage;
klass->finish = gdm_display_real_finish;
klass->unmanage = gdm_display_real_unmanage;
diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h
index 4647ce07..87e274bc 100644
--- a/daemon/gdm-display.h
+++ b/daemon/gdm-display.h
@@ -61,10 +61,12 @@ typedef struct
gboolean (*remove_user_authorization) (GdmDisplay *display,
const char *username,
GError **error);
+ gboolean (*set_slave_bus_name) (GdmDisplay *display,
+ const char *name,
+ GError **error);
gboolean (*manage) (GdmDisplay *display);
gboolean (*finish) (GdmDisplay *display);
gboolean (*unmanage) (GdmDisplay *display);
-
} GdmDisplayClass;
typedef enum
@@ -123,6 +125,9 @@ gboolean gdm_display_add_user_authorization (GdmDisplay *disp
gboolean gdm_display_remove_user_authorization (GdmDisplay *display,
const char *username,
GError **error);
+gboolean gdm_display_set_slave_bus_name (GdmDisplay *display,
+ const char *name,
+ GError **error);
G_END_DECLS
diff --git a/daemon/gdm-display.xml b/daemon/gdm-display.xml
index 239ad763..97d236b6 100644
--- a/daemon/gdm-display.xml
+++ b/daemon/gdm-display.xml
@@ -32,5 +32,8 @@
<method name="RemoveUserAuthorization">
<arg name="username" direction="in" type="s"/>
</method>
+ <method name="SetSlaveBusName">
+ <arg name="name" direction="in" type="s"/>
+ </method>
</interface>
</node>
diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c
index 971b2c39..ecda3225 100644
--- a/daemon/gdm-factory-slave.c
+++ b/daemon/gdm-factory-slave.c
@@ -67,8 +67,6 @@ struct GdmFactorySlavePrivate
{
char *id;
GPid pid;
- guint output_watch_id;
- guint error_watch_id;
guint greeter_reset_id;
GPid server_pid;
diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c
index 68e9b349..612ded08 100644
--- a/daemon/gdm-greeter-server.c
+++ b/daemon/gdm-greeter-server.c
@@ -56,9 +56,6 @@ struct GdmGreeterServerPrivate
char *group_name;
char *display_id;
- gboolean interrupted;
- gboolean always_restart_greeter;
-
DBusServer *server;
char *server_address;
DBusConnection *greeter_connection;
diff --git a/daemon/gdm-greeter-session.c b/daemon/gdm-greeter-session.c
index a7a7d368..48891e7c 100644
--- a/daemon/gdm-greeter-session.c
+++ b/daemon/gdm-greeter-session.c
@@ -71,11 +71,6 @@ struct GdmGreeterSessionPrivate
CkConnector *ckc;
- int user_max_filesize;
-
- gboolean interrupted;
- gboolean always_restart_greeter;
-
guint child_watch_id;
GPid dbus_pid;
@@ -1030,7 +1025,6 @@ gdm_greeter_session_init (GdmGreeterSession *greeter_session)
greeter_session->priv->pid = -1;
greeter_session->priv->command = g_strdup (LIBEXECDIR "/gdm-simple-greeter");
- greeter_session->priv->user_max_filesize = 65536;
}
static void
diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c
index 40e16bc6..3289fb3c 100644
--- a/daemon/gdm-product-slave.c
+++ b/daemon/gdm-product-slave.c
@@ -66,8 +66,6 @@ struct GdmProductSlavePrivate
{
char *id;
GPid pid;
- guint output_watch_id;
- guint error_watch_id;
char *relay_address;
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index ce83180f..6f0564f2 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -62,8 +62,6 @@ struct GdmSimpleSlavePrivate
{
char *id;
GPid pid;
- guint output_watch_id;
- guint error_watch_id;
guint greeter_reset_id;
guint start_session_id;
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index b25cbff4..e8164f27 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -417,6 +417,35 @@ display_proxy_destroyed_cb (DBusGProxy *display_proxy,
}
static gboolean
+gdm_slave_set_slave_bus_name (GdmSlave *slave)
+{
+ gboolean res;
+ GError *error;
+ const char *name;
+
+ name = dbus_bus_get_unique_name (dbus_g_connection_get_connection (slave->priv->connection));
+
+ error = NULL;
+ res = dbus_g_proxy_call (slave->priv->display_proxy,
+ "SetSlaveBusName",
+ &error,
+ G_TYPE_STRING, name,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+
+ if (! res) {
+ if (error != NULL) {
+ g_warning ("Failed to set slave bus name on parent: %s", error->message);
+ g_error_free (error);
+ } else {
+ g_warning ("Failed to set slave bus name on parent");
+ }
+ }
+
+ return res;
+}
+
+static gboolean
gdm_slave_real_start (GdmSlave *slave)
{
gboolean res;
@@ -475,6 +504,8 @@ gdm_slave_real_start (GdmSlave *slave)
exit (1);
}
+ gdm_slave_set_slave_bus_name (slave);
+
/* cache some values up front */
error = NULL;
res = dbus_g_proxy_call (slave->priv->display_proxy,
@@ -1123,7 +1154,7 @@ gdm_slave_get_property (GObject *object,
static gboolean
register_slave (GdmSlave *slave)
{
- GError *error = NULL;
+ GError *error;
error = NULL;
slave->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
@@ -1155,6 +1186,7 @@ gdm_slave_constructor (GType type,
slave = GDM_SLAVE (G_OBJECT_CLASS (gdm_slave_parent_class)->constructor (type,
n_construct_properties,
construct_properties));
+ /* Always match the slave id with the master */
id = NULL;
if (g_str_has_prefix (slave->priv->display_id, "/org/gnome/DisplayManager/Display")) {
diff --git a/daemon/gdm-xdmcp-chooser-display.c b/daemon/gdm-xdmcp-chooser-display.c
new file mode 100644
index 00000000..85bd3b71
--- /dev/null
+++ b/daemon/gdm-xdmcp-chooser-display.c
@@ -0,0 +1,234 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+
+#include "gdm-display.h"
+#include "gdm-xdmcp-chooser-display.h"
+#include "gdm-xdmcp-chooser-display-glue.h"
+
+#include "gdm-common.h"
+#include "gdm-address.h"
+
+#define DEFAULT_SLAVE_COMMAND LIBEXECDIR"/gdm-xdmcp-chooser-slave"
+
+#define GDM_DBUS_NAME "/org/gnome/DisplayManager"
+#define GDM_XDMCP_CHOOSER_SLAVE_DBUS_INTERFACE "org.gnome.DisplayManager.XdmcpChooserSlave"
+
+#define GDM_XDMCP_CHOOSER_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_XDMCP_CHOOSER_DISPLAY, GdmXdmcpChooserDisplayPrivate))
+
+struct GdmXdmcpChooserDisplayPrivate
+{
+ DBusGProxy *slave_proxy;
+};
+
+enum {
+ PROP_0,
+};
+
+enum {
+ HOSTNAME_SELECTED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void gdm_xdmcp_chooser_display_class_init (GdmXdmcpChooserDisplayClass *klass);
+static void gdm_xdmcp_chooser_display_init (GdmXdmcpChooserDisplay *xdmcp_chooser_display);
+static void gdm_xdmcp_chooser_display_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmXdmcpChooserDisplay, gdm_xdmcp_chooser_display, GDM_TYPE_XDMCP_DISPLAY)
+
+static void
+on_hostname_selected (DBusGProxy *proxy,
+ const char *hostname,
+ GdmXdmcpChooserDisplay *display)
+{
+ g_debug ("GdmXdmcpChooserDisplay: hostname selected: %s", hostname);
+ g_signal_emit (display, signals [HOSTNAME_SELECTED], 0, hostname);
+}
+
+static gboolean
+gdm_xdmcp_chooser_display_set_slave_bus_name (GdmDisplay *display,
+ const char *name,
+ GError **error)
+{
+ char *display_id;
+ const char *slave_num;
+ char *slave_id;
+ DBusGConnection *connection;
+ GError *local_error;
+ GdmXdmcpChooserDisplay *chooser_display;
+
+ display_id = NULL;
+ slave_id = NULL;
+ slave_num = NULL;
+
+ chooser_display = GDM_XDMCP_CHOOSER_DISPLAY (display);
+ if (chooser_display->priv->slave_proxy != NULL) {
+ g_object_unref (chooser_display->priv->slave_proxy);
+ }
+
+ g_object_get (display, "id", &display_id, NULL);
+
+ if (g_str_has_prefix (display_id, "/org/gnome/DisplayManager/Display")) {
+ slave_num = display_id + strlen ("/org/gnome/DisplayManager/Display");
+ }
+
+ slave_id = g_strdup_printf ("/org/gnome/DisplayManager/Slave%s", slave_num);
+
+ local_error = NULL;
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &local_error);
+ if (connection == NULL) {
+ if (local_error != NULL) {
+ g_critical ("error getting system bus: %s", local_error->message);
+ g_error_free (local_error);
+ }
+ }
+
+ g_debug ("GdmXdmcpChooserDisplay: creating proxy for %s on %s", slave_id, name);
+
+ chooser_display->priv->slave_proxy = dbus_g_proxy_new_for_name (connection,
+ name,
+ slave_id,
+ GDM_XDMCP_CHOOSER_SLAVE_DBUS_INTERFACE);
+ if (chooser_display->priv->slave_proxy == NULL) {
+ g_warning ("Failed to connect to the slave object");
+ goto out;
+ }
+ dbus_g_proxy_add_signal (chooser_display->priv->slave_proxy,
+ "HostnameSelected",
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (chooser_display->priv->slave_proxy,
+ "HostnameSelected",
+ G_CALLBACK (on_hostname_selected),
+ display,
+ NULL);
+ out:
+
+ g_free (display_id);
+ g_free (slave_id);
+
+ return GDM_DISPLAY_CLASS (gdm_xdmcp_chooser_display_parent_class)->set_slave_bus_name (display, name, error);
+}
+
+static gboolean
+gdm_xdmcp_chooser_display_manage (GdmDisplay *display)
+{
+ g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE);
+
+ GDM_DISPLAY_CLASS (gdm_xdmcp_chooser_display_parent_class)->manage (display);
+
+ return TRUE;
+}
+
+static void
+gdm_xdmcp_chooser_display_class_init (GdmXdmcpChooserDisplayClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdmDisplayClass *display_class = GDM_DISPLAY_CLASS (klass);
+
+ object_class->finalize = gdm_xdmcp_chooser_display_finalize;
+
+ display_class->manage = gdm_xdmcp_chooser_display_manage;
+ display_class->set_slave_bus_name = gdm_xdmcp_chooser_display_set_slave_bus_name;
+
+ signals [HOSTNAME_SELECTED] =
+ g_signal_new ("hostname-selected",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmXdmcpChooserDisplayClass, hostname_selected),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+
+ g_type_class_add_private (klass, sizeof (GdmXdmcpChooserDisplayPrivate));
+
+ dbus_g_object_type_install_info (GDM_TYPE_XDMCP_CHOOSER_DISPLAY, &dbus_glib_gdm_xdmcp_chooser_display_object_info);
+}
+
+static void
+gdm_xdmcp_chooser_display_init (GdmXdmcpChooserDisplay *xdmcp_chooser_display)
+{
+
+ xdmcp_chooser_display->priv = GDM_XDMCP_CHOOSER_DISPLAY_GET_PRIVATE (xdmcp_chooser_display);
+}
+
+static void
+gdm_xdmcp_chooser_display_finalize (GObject *object)
+{
+ GdmXdmcpChooserDisplay *chooser_display;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_XDMCP_CHOOSER_DISPLAY (object));
+
+ chooser_display = GDM_XDMCP_CHOOSER_DISPLAY (object);
+
+ g_return_if_fail (chooser_display->priv != NULL);
+
+ if (chooser_display->priv->slave_proxy != NULL) {
+ g_object_unref (chooser_display->priv->slave_proxy);
+ }
+
+ G_OBJECT_CLASS (gdm_xdmcp_chooser_display_parent_class)->finalize (object);
+}
+
+GdmDisplay *
+gdm_xdmcp_chooser_display_new (const char *hostname,
+ int number,
+ GdmAddress *address,
+ gint32 session_number)
+{
+ GObject *object;
+ char *x11_display;
+
+ x11_display = g_strdup_printf ("%s:%d", hostname, number);
+ object = g_object_new (GDM_TYPE_XDMCP_CHOOSER_DISPLAY,
+ "slave-command", DEFAULT_SLAVE_COMMAND,
+ "remote-hostname", hostname,
+ "x11-display-number", number,
+ "x11-display-name", x11_display,
+ "is-local", FALSE,
+ "remote-address", address,
+ "session-number", session_number,
+ NULL);
+ g_free (x11_display);
+
+ return GDM_DISPLAY (object);
+}
diff --git a/daemon/gdm-xdmcp-chooser-display.h b/daemon/gdm-xdmcp-chooser-display.h
new file mode 100644
index 00000000..8ab17b8d
--- /dev/null
+++ b/daemon/gdm-xdmcp-chooser-display.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * 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.
+ *
+ */
+
+
+#ifndef __GDM_XDMCP_CHOOSER_DISPLAY_H
+#define __GDM_XDMCP_CHOOSER_DISPLAY_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#include "gdm-xdmcp-display.h"
+#include "gdm-address.h"
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_XDMCP_CHOOSER_DISPLAY (gdm_xdmcp_chooser_display_get_type ())
+#define GDM_XDMCP_CHOOSER_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_XDMCP_CHOOSER_DISPLAY, GdmXdmcpChooserDisplay))
+#define GDM_XDMCP_CHOOSER_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_XDMCP_CHOOSER_DISPLAY, GdmXdmcpChooserDisplayClass))
+#define GDM_IS_XDMCP_CHOOSER_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_XDMCP_CHOOSER_DISPLAY))
+#define GDM_IS_XDMCP_CHOOSER_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_XDMCP_CHOOSER_DISPLAY))
+#define GDM_XDMCP_CHOOSER_DISPLAY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_XDMCP_CHOOSER_DISPLAY, GdmXdmcpChooserDisplayClass))
+
+typedef struct GdmXdmcpChooserDisplayPrivate GdmXdmcpChooserDisplayPrivate;
+
+typedef struct
+{
+ GdmXdmcpDisplay parent;
+ GdmXdmcpChooserDisplayPrivate *priv;
+} GdmXdmcpChooserDisplay;
+
+typedef struct
+{
+ GdmXdmcpDisplayClass parent_class;
+
+ void (* hostname_selected) (GdmXdmcpChooserDisplay *display,
+ const char *hostname);
+} GdmXdmcpChooserDisplayClass;
+
+GType gdm_xdmcp_chooser_display_get_type (void);
+
+
+GdmDisplay * gdm_xdmcp_chooser_display_new (const char *hostname,
+ int number,
+ GdmAddress *addr,
+ gint32 serial_number);
+
+G_END_DECLS
+
+#endif /* __GDM_XDMCP_CHOOSER_DISPLAY_H */
diff --git a/daemon/gdm-xdmcp-chooser-display.xml b/daemon/gdm-xdmcp-chooser-display.xml
new file mode 100644
index 00000000..194168f8
--- /dev/null
+++ b/daemon/gdm-xdmcp-chooser-display.xml
@@ -0,0 +1,5 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.gnome.DisplayManager.XdmcpChooserDisplay">
+ </interface>
+</node>
diff --git a/daemon/gdm-xdmcp-chooser-slave.c b/daemon/gdm-xdmcp-chooser-slave.c
new file mode 100644
index 00000000..39e62c83
--- /dev/null
+++ b/daemon/gdm-xdmcp-chooser-slave.c
@@ -0,0 +1,432 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <glib-object.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <X11/Xlib.h> /* for Display */
+
+#include "gdm-common.h"
+
+#include "gdm-xdmcp-chooser-slave.h"
+#include "gdm-xdmcp-chooser-slave-glue.h"
+
+#include "gdm-server.h"
+#include "gdm-chooser-server.h"
+#include "gdm-chooser-session.h"
+
+#define GDM_XDMCP_CHOOSER_SLAVE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_XDMCP_CHOOSER_SLAVE, GdmXdmcpChooserSlavePrivate))
+
+#define GDM_DBUS_NAME "org.gnome.DisplayManager"
+#define GDM_DBUS_DISPLAY_INTERFACE "org.gnome.DisplayManager.Display"
+
+#define MAX_CONNECT_ATTEMPTS 10
+
+struct GdmXdmcpChooserSlavePrivate
+{
+ char *id;
+ GPid pid;
+
+ int ping_interval;
+
+ guint connection_attempts;
+
+ GdmChooserServer *chooser_server;
+ GdmChooserSession *chooser;
+};
+
+enum {
+ PROP_0,
+};
+
+enum {
+ HOSTNAME_SELECTED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void gdm_xdmcp_chooser_slave_class_init (GdmXdmcpChooserSlaveClass *klass);
+static void gdm_xdmcp_chooser_slave_init (GdmXdmcpChooserSlave *xdmcp_chooser_slave);
+static void gdm_xdmcp_chooser_slave_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmXdmcpChooserSlave, gdm_xdmcp_chooser_slave, GDM_TYPE_SLAVE)
+
+
+static void
+on_chooser_session_start (GdmChooserSession *chooser,
+ GdmXdmcpChooserSlave *slave)
+{
+ g_debug ("GdmXdmcpChooserSlave: Chooser started");
+}
+
+static void
+on_chooser_session_stop (GdmChooserSession *chooser,
+ GdmXdmcpChooserSlave *slave)
+{
+ g_debug ("GdmXdmcpChooserSlave: Chooser stopped");
+ gdm_slave_stopped (GDM_SLAVE (slave));
+}
+
+static void
+on_chooser_session_exited (GdmChooserSession *chooser,
+ int code,
+ GdmXdmcpChooserSlave *slave)
+{
+ g_debug ("GdmXdmcpChooserSlave: Chooser exited: %d", code);
+ gdm_slave_stopped (GDM_SLAVE (slave));
+}
+
+static void
+on_chooser_session_died (GdmChooserSession *chooser,
+ int signal,
+ GdmXdmcpChooserSlave *slave)
+{
+ g_debug ("GdmXdmcpChooserSlave: Chooser died: %d", signal);
+ gdm_slave_stopped (GDM_SLAVE (slave));
+}
+
+static void
+on_chooser_hostname_selected (GdmChooserServer *chooser_server,
+ const char *name,
+ GdmXdmcpChooserSlave *slave)
+{
+ g_debug ("GdmXdmcpChooserSlave: emitting hostname selected: %s", name);
+ g_signal_emit (slave, signals [HOSTNAME_SELECTED], 0, name);
+}
+
+static void
+on_chooser_disconnected (GdmChooserServer *chooser_server,
+ GdmXdmcpChooserSlave *slave)
+{
+ g_debug ("GdmXdmcpChooserSlave: Chooser disconnected");
+
+ /* stop pinging */
+ alarm (0);
+
+ gdm_slave_stopped (GDM_SLAVE (slave));
+}
+
+static void
+on_chooser_connected (GdmChooserServer *chooser_server,
+ GdmXdmcpChooserSlave *slave)
+{
+ g_debug ("GdmXdmcpChooserSlave: Chooser connected");
+}
+
+static void
+setup_server (GdmXdmcpChooserSlave *slave)
+{
+ /* Set the busy cursor */
+ gdm_slave_set_busy_cursor (GDM_SLAVE (slave));
+}
+
+static void
+run_chooser (GdmXdmcpChooserSlave *slave)
+{
+ char *display_id;
+ char *display_name;
+ char *display_device;
+ char *display_hostname;
+ char *auth_file;
+ char *address;
+
+ g_debug ("GdmXdmcpChooserSlave: Running chooser");
+
+ display_id = NULL;
+ display_name = NULL;
+ auth_file = NULL;
+ display_device = NULL;
+ display_hostname = NULL;
+
+ g_object_get (slave,
+ "display-id", &display_id,
+ "display-name", &display_name,
+ "display-hostname", &display_hostname,
+ "display-x11-authority-file", &auth_file,
+ NULL);
+
+ g_debug ("GdmXdmcpChooserSlave: Creating chooser for %s %s", display_name, display_hostname);
+
+ /* FIXME: send a signal back to the master */
+
+ /* If XDMCP setup pinging */
+ if (slave->priv->ping_interval > 0) {
+ alarm (slave->priv->ping_interval);
+ }
+
+ /* Run the init script. gdmslave suspends until script has terminated */
+ gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/Init", "gdm");
+
+ slave->priv->chooser_server = gdm_chooser_server_new (display_id);
+ g_signal_connect (slave->priv->chooser_server,
+ "hostname-selected",
+ G_CALLBACK (on_chooser_hostname_selected),
+ slave);
+ g_signal_connect (slave->priv->chooser_server,
+ "disconnected",
+ G_CALLBACK (on_chooser_disconnected),
+ slave);
+ g_signal_connect (slave->priv->chooser_server,
+ "connected",
+ G_CALLBACK (on_chooser_connected),
+ slave);
+ gdm_chooser_server_start (slave->priv->chooser_server);
+
+ address = gdm_chooser_server_get_address (slave->priv->chooser_server);
+
+ g_debug ("GdmXdmcpChooserSlave: Creating chooser on %s %s %s", display_name, display_device, display_hostname);
+ slave->priv->chooser = gdm_chooser_session_new (display_name,
+ display_device,
+ display_hostname);
+ g_signal_connect (slave->priv->chooser,
+ "started",
+ G_CALLBACK (on_chooser_session_start),
+ slave);
+ g_signal_connect (slave->priv->chooser,
+ "stopped",
+ G_CALLBACK (on_chooser_session_stop),
+ slave);
+ g_signal_connect (slave->priv->chooser,
+ "exited",
+ G_CALLBACK (on_chooser_session_exited),
+ slave);
+ g_signal_connect (slave->priv->chooser,
+ "died",
+ G_CALLBACK (on_chooser_session_died),
+ slave);
+ g_object_set (slave->priv->chooser,
+ "x11-authority-file", auth_file,
+ NULL);
+ gdm_chooser_session_set_server_address (slave->priv->chooser, address);
+ gdm_chooser_session_start (slave->priv->chooser);
+
+ g_free (display_id);
+ g_free (display_name);
+ g_free (display_device);
+ g_free (display_hostname);
+ g_free (auth_file);
+}
+
+static gboolean
+idle_connect_to_display (GdmXdmcpChooserSlave *slave)
+{
+ gboolean res;
+
+ slave->priv->connection_attempts++;
+
+ res = gdm_slave_connect_to_x11_display (GDM_SLAVE (slave));
+ if (res) {
+ /* FIXME: handle wait-for-go */
+
+ setup_server (slave);
+ run_chooser (slave);
+ } else {
+ if (slave->priv->connection_attempts >= MAX_CONNECT_ATTEMPTS) {
+ g_warning ("Unable to connect to display after %d tries - bailing out", slave->priv->connection_attempts);
+ exit (1);
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gdm_xdmcp_chooser_slave_run (GdmXdmcpChooserSlave *slave)
+{
+ char *display_name;
+ char *auth_file;
+
+ g_object_get (slave,
+ "display-name", &display_name,
+ "display-x11-authority-file", &auth_file,
+ NULL);
+
+ g_timeout_add (500, (GSourceFunc)idle_connect_to_display, slave);
+
+ g_free (display_name);
+ g_free (auth_file);
+
+ return TRUE;
+}
+
+static gboolean
+gdm_xdmcp_chooser_slave_start (GdmSlave *slave)
+{
+ gboolean res;
+
+ res = GDM_SLAVE_CLASS (gdm_xdmcp_chooser_slave_parent_class)->start (slave);
+
+ gdm_xdmcp_chooser_slave_run (GDM_XDMCP_CHOOSER_SLAVE (slave));
+
+ return TRUE;
+}
+
+static gboolean
+gdm_xdmcp_chooser_slave_stop (GdmSlave *slave)
+{
+ gboolean res;
+
+ g_debug ("GdmXdmcpChooserSlave: Stopping xdmcp_chooser_slave");
+
+ res = GDM_SLAVE_CLASS (gdm_xdmcp_chooser_slave_parent_class)->stop (slave);
+
+ if (GDM_XDMCP_CHOOSER_SLAVE (slave)->priv->chooser != NULL) {
+ gdm_chooser_session_stop (GDM_XDMCP_CHOOSER_SLAVE (slave)->priv->chooser);
+ g_object_unref (GDM_XDMCP_CHOOSER_SLAVE (slave)->priv->chooser);
+ GDM_XDMCP_CHOOSER_SLAVE (slave)->priv->chooser = NULL;
+ }
+
+ return TRUE;
+}
+
+static void
+gdm_xdmcp_chooser_slave_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdmXdmcpChooserSlave *self;
+
+ self = GDM_XDMCP_CHOOSER_SLAVE (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdm_xdmcp_chooser_slave_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdmXdmcpChooserSlave *self;
+
+ self = GDM_XDMCP_CHOOSER_SLAVE (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gdm_xdmcp_chooser_slave_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GdmXdmcpChooserSlave *xdmcp_chooser_slave;
+ GdmXdmcpChooserSlaveClass *klass;
+
+ klass = GDM_XDMCP_CHOOSER_SLAVE_CLASS (g_type_class_peek (GDM_TYPE_XDMCP_CHOOSER_SLAVE));
+
+ xdmcp_chooser_slave = GDM_XDMCP_CHOOSER_SLAVE (G_OBJECT_CLASS (gdm_xdmcp_chooser_slave_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (xdmcp_chooser_slave);
+}
+
+static void
+gdm_xdmcp_chooser_slave_class_init (GdmXdmcpChooserSlaveClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdmSlaveClass *slave_class = GDM_SLAVE_CLASS (klass);
+
+ object_class->get_property = gdm_xdmcp_chooser_slave_get_property;
+ object_class->set_property = gdm_xdmcp_chooser_slave_set_property;
+ object_class->constructor = gdm_xdmcp_chooser_slave_constructor;
+ object_class->finalize = gdm_xdmcp_chooser_slave_finalize;
+
+ slave_class->start = gdm_xdmcp_chooser_slave_start;
+ slave_class->stop = gdm_xdmcp_chooser_slave_stop;
+
+ signals [HOSTNAME_SELECTED] =
+ g_signal_new ("hostname-selected",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmXdmcpChooserSlaveClass, hostname_selected),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+
+ g_type_class_add_private (klass, sizeof (GdmXdmcpChooserSlavePrivate));
+
+ dbus_g_object_type_install_info (GDM_TYPE_XDMCP_CHOOSER_SLAVE, &dbus_glib_gdm_xdmcp_chooser_slave_object_info);
+}
+
+static void
+gdm_xdmcp_chooser_slave_init (GdmXdmcpChooserSlave *slave)
+{
+ slave->priv = GDM_XDMCP_CHOOSER_SLAVE_GET_PRIVATE (slave);
+}
+
+static void
+gdm_xdmcp_chooser_slave_finalize (GObject *object)
+{
+ GdmXdmcpChooserSlave *xdmcp_chooser_slave;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_XDMCP_CHOOSER_SLAVE (object));
+
+ xdmcp_chooser_slave = GDM_XDMCP_CHOOSER_SLAVE (object);
+
+ g_return_if_fail (xdmcp_chooser_slave->priv != NULL);
+
+ gdm_xdmcp_chooser_slave_stop (GDM_SLAVE (xdmcp_chooser_slave));
+
+ G_OBJECT_CLASS (gdm_xdmcp_chooser_slave_parent_class)->finalize (object);
+}
+
+GdmSlave *
+gdm_xdmcp_chooser_slave_new (const char *id)
+{
+ GObject *object;
+
+ object = g_object_new (GDM_TYPE_XDMCP_CHOOSER_SLAVE,
+ "display-id", id,
+ NULL);
+
+ return GDM_SLAVE (object);
+}
diff --git a/daemon/gdm-xdmcp-chooser-slave.h b/daemon/gdm-xdmcp-chooser-slave.h
new file mode 100644
index 00000000..61cdd137
--- /dev/null
+++ b/daemon/gdm-xdmcp-chooser-slave.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * 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.
+ *
+ */
+
+
+#ifndef __GDM_XDMCP_CHOOSER_SLAVE_H
+#define __GDM_XDMCP_CHOOSER_SLAVE_H
+
+#include <glib-object.h>
+#include "gdm-slave.h"
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_XDMCP_CHOOSER_SLAVE (gdm_xdmcp_chooser_slave_get_type ())
+#define GDM_XDMCP_CHOOSER_SLAVE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_XDMCP_CHOOSER_SLAVE, GdmXdmcpChooserSlave))
+#define GDM_XDMCP_CHOOSER_SLAVE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_XDMCP_CHOOSER_SLAVE, GdmXdmcpChooserSlaveClass))
+#define GDM_IS_XDMCP_CHOOSER_SLAVE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_XDMCP_CHOOSER_SLAVE))
+#define GDM_IS_XDMCP_CHOOSER_SLAVE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_XDMCP_CHOOSER_SLAVE))
+#define GDM_XDMCP_CHOOSER_SLAVE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_XDMCP_CHOOSER_SLAVE, GdmXdmcpChooserSlaveClass))
+
+typedef struct GdmXdmcpChooserSlavePrivate GdmXdmcpChooserSlavePrivate;
+
+typedef struct
+{
+ GdmSlave parent;
+ GdmXdmcpChooserSlavePrivate *priv;
+} GdmXdmcpChooserSlave;
+
+typedef struct
+{
+ GdmSlaveClass parent_class;
+
+ void (* hostname_selected) (GdmXdmcpChooserSlave *slave,
+ const char *hostname);
+} GdmXdmcpChooserSlaveClass;
+
+GType gdm_xdmcp_chooser_slave_get_type (void);
+GdmSlave * gdm_xdmcp_chooser_slave_new (const char *id);
+
+G_END_DECLS
+
+#endif /* __GDM_XDMCP_CHOOSER_SLAVE_H */
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
index 4f6fe1f4..33ce282a 100644
--- a/daemon/gdm-xdmcp-display-factory.c
+++ b/daemon/gdm-xdmcp-display-factory.c
@@ -52,7 +52,8 @@
#include <X11/Xdmcp.h>
#include "gdm-common.h"
-#include "gdm-xdmcp-display.h"
+#include "gdm-xdmcp-greeter-display.h"
+#include "gdm-xdmcp-chooser-display.h"
#include "gdm-display-factory.h"
#include "gdm-xdmcp-display-factory.h"
#include "gdm-display-store.h"
@@ -136,17 +137,24 @@ static XdmAuthRec serv_authlist = {
};
/* NOTE: Timeout and max are hardcoded */
-typedef struct _GdmForwardQuery {
+typedef struct _ForwardQuery {
time_t acctime;
GdmAddress *dsp_address;
GdmAddress *from_address;
-} GdmForwardQuery;
+} ForwardQuery;
+
+typedef struct _IndirectClient {
+ int id;
+ GdmAddress *dsp_address;
+ GdmAddress *chosen_address;
+ time_t acctime;
+} IndirectClient;
typedef struct {
- int times;
- guint handler;
- GdmAddress *manager;
- GdmAddress *origin;
+ int times;
+ guint handler;
+ GdmAddress *manager;
+ GdmAddress *origin;
GdmXdmcpDisplayFactory *xdmcp_display_factory;
} ManagedForward;
@@ -154,6 +162,7 @@ struct GdmXdmcpDisplayFactoryPrivate
{
GSList *forward_queries;
GSList *managed_forwards;
+ GSList *indirect_clients;
int socket_fd;
gint32 session_serial;
@@ -873,8 +882,6 @@ gdm_xdmcp_send_unwilling (GdmXdmcpDisplayFactory *factory,
#define SIN(__s) ((struct sockaddr_in *) __s)
#define SIN6(__s) ((struct sockaddr_in6 *) __s)
-#if 0
-/* FIXME: Add chooser support */
static void
set_port_for_request (GdmAddress *address,
ARRAY8 *port)
@@ -898,7 +905,6 @@ set_port_for_request (GdmAddress *address,
break;
}
}
-#endif
static void
set_address_for_request (GdmAddress *address,
@@ -925,11 +931,9 @@ set_address_for_request (GdmAddress *address,
}
-#if 0
-/* FIXME: Add chooser support */
static void
gdm_xdmcp_send_forward_query (GdmXdmcpDisplayFactory *factory,
- GdmIndirectDisplay *id,
+ IndirectClient *ic,
GdmAddress *address,
GdmAddress *display_address,
ARRAYofARRAY8Ptr authlist)
@@ -941,11 +945,11 @@ gdm_xdmcp_send_forward_query (GdmXdmcpDisplayFactory *factory,
char *host;
char *serv;
- g_assert (id != NULL);
- g_assert (id->chosen_host != NULL);
+ g_assert (ic != NULL);
+ g_assert (ic->chosen_address != NULL);
host = NULL;
- gdm_address_get_numeric_info (id->chosen_host, &host, NULL);
+ gdm_address_get_numeric_info (ic->chosen_address, &host, NULL);
g_debug ("GdmXdmcpDisplayFactory: Sending forward query to %s",
host);
g_free (host);
@@ -978,13 +982,12 @@ gdm_xdmcp_send_forward_query (GdmXdmcpDisplayFactory *factory,
XdmcpFlush (factory->priv->socket_fd,
&factory->priv->buf,
- (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (id->chosen_host),
+ (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (ic->chosen_address),
(int)sizeof (struct sockaddr_storage));
g_free (port.data);
g_free (addr.data);
}
-#endif
static void
handle_any_query (GdmXdmcpDisplayFactory *factory,
@@ -1051,15 +1054,167 @@ gdm_xdmcp_handle_query (GdmXdmcpDisplayFactory *factory,
}
}
+static IndirectClient *
+indirect_client_create (GdmXdmcpDisplayFactory *factory,
+ GdmAddress *dsp_address)
+{
+ IndirectClient *ic;
+ int count;
+
+ count = g_slist_length (factory->priv->indirect_clients);
+
+ ic = g_new0 (IndirectClient, 1);
+ ic->dsp_address = gdm_address_copy (dsp_address);
+
+ factory->priv->indirect_clients = g_slist_prepend (factory->priv->indirect_clients, ic);
+
+ return ic;
+}
+
+static void
+indirect_client_destroy (GdmXdmcpDisplayFactory *factory,
+ IndirectClient *ic)
+{
+ if (ic == NULL) {
+ return;
+ }
+
+ factory->priv->indirect_clients = g_slist_remove (factory->priv->indirect_clients, ic);
+
+ ic->acctime = 0;
+
+ {
+ char *host;
+
+ host = NULL;
+ gdm_address_get_numeric_info (ic->dsp_address, &host, NULL);
+ g_debug ("GdmXdmcpDisplayFactory: Disposing IndirectClient for %s", host);
+ g_free (host);
+ }
+
+ g_free (ic->dsp_address);
+ ic->dsp_address = NULL;
+ g_free (ic->chosen_address);
+ ic->chosen_address = NULL;
+
+ g_free (ic);
+}
+
+static IndirectClient *
+indirect_client_lookup_by_chosen (GdmXdmcpDisplayFactory *factory,
+ GdmAddress *chosen_address,
+ GdmAddress *origin_address)
+{
+ GSList *li;
+ char *host;
+ IndirectClient *ret;
+
+ g_assert (chosen_address != NULL);
+ g_assert (origin_address != NULL);
+
+ ret = NULL;
+
+ for (li = factory->priv->indirect_clients; li != NULL; li = li->next) {
+ IndirectClient *ic = li->data;
+
+ if (ic != NULL
+ && ic->chosen_address != NULL
+ && gdm_address_equal (ic->chosen_address, chosen_address)) {
+ if (gdm_address_equal (ic->dsp_address, origin_address)) {
+ ret = ic;
+ goto out;
+ } else if (gdm_address_is_loopback (ic->dsp_address)
+ && gdm_address_is_local (origin_address)) {
+ ret = ic;
+ goto out;
+ }
+ }
+ }
+
+ gdm_address_get_numeric_info (chosen_address, &host, NULL);
+
+ g_debug ("GdmXdmcpDisplayFactory: Chosen %s host not found", host);
+ g_free (host);
+ out:
+ return ret;
+}
+
+/* lookup by origin */
+static IndirectClient *
+indirect_client_lookup (GdmXdmcpDisplayFactory *factory,
+ GdmAddress *address)
+{
+ GSList *li;
+ GSList *qlist;
+ IndirectClient *ret;
+ time_t curtime;
+
+ g_assert (address != NULL);
+
+ curtime = time (NULL);
+ ret = NULL;
+
+ qlist = g_slist_copy (factory->priv->indirect_clients);
+
+ for (li = qlist; li != NULL; li = li->next) {
+ IndirectClient *ic;
+ char *host;
+ char *serv;
+
+ ic = (IndirectClient *) li->data;
+
+ if (ic == NULL) {
+ continue;
+ }
+
+ host = NULL;
+ serv = NULL;
+ gdm_address_get_numeric_info (ic->dsp_address, &host, &serv);
+
+ g_debug ("GdmXdmcpDisplayFactory: comparing %s:%s", host, serv);
+ if (gdm_address_equal (ic->dsp_address, address)) {
+ ret = ic;
+ g_free (host);
+ g_free (serv);
+ break;
+ }
+
+ if (ic->acctime > 0 && curtime > ic->acctime + factory->priv->max_wait) {
+ g_debug ("GdmXdmcpDisplayFactory: Disposing stale forward query from %s:%s",
+ host, serv);
+
+ indirect_client_destroy (factory, ic);
+ }
+
+ g_free (host);
+ g_free (serv);
+ }
+
+ g_slist_free (qlist);
+
+ if (ret == NULL) {
+ char *host;
+
+ host = NULL;
+ gdm_address_get_numeric_info (address, &host, NULL);
+ g_debug ("GdmXdmcpDisplayFactory: Host %s not found",
+ host);
+ g_free (host);
+ }
+
+ return ret;
+}
+
static void
gdm_xdmcp_handle_indirect_query (GdmXdmcpDisplayFactory *factory,
GdmAddress *address,
int len)
{
- ARRAYofARRAY8 clnt_authlist;
- int expected_len;
- int i;
- int res;
+ ARRAYofARRAY8 clnt_authlist;
+ int expected_len;
+ int i;
+ int res;
+ IndirectClient *ic;
if (! gdm_xdmcp_host_allow (address)) {
/* ignore the request */
@@ -1071,6 +1226,13 @@ gdm_xdmcp_handle_indirect_query (GdmXdmcpDisplayFactory *factory,
return;
}
+ if (factory->priv->num_sessions > factory->priv->max_displays ||
+ (!gdm_address_is_local (address) &&
+ gdm_xdmcp_num_displays_from_host (factory, address) > factory->priv->max_displays_per_host)) {
+ g_debug ("GdmXdmcpDisplayFactory: reached maximum number of clients - ignoring indirect query");
+ return;
+ }
+
res = XdmcpReadARRAYofARRAY8 (&factory->priv->buf, &clnt_authlist);
if G_UNLIKELY (! res) {
g_warning (_("Could not extract authlist from packet"));
@@ -1085,7 +1247,7 @@ gdm_xdmcp_handle_indirect_query (GdmXdmcpDisplayFactory *factory,
/* Try to look up the display in
* the pending list. If found send a FORWARD_QUERY to the
- * chosen factory. Otherwise alloc a new indirect display. */
+ * chosen manager. Otherwise alloc a new indirect display. */
if (len != expected_len) {
g_warning (_("Error in checksum"));
@@ -1093,18 +1255,16 @@ gdm_xdmcp_handle_indirect_query (GdmXdmcpDisplayFactory *factory,
}
-#if 0
- GdmIndirectDisplay *id;
- /* FIXME: Add chooser support */
+ ic = indirect_client_lookup (factory, address);
- id = gdm_choose_indirect_lookup (address);
-
- if (id != NULL && id->chosen_host != NULL) {
+ if (ic != NULL && ic->chosen_address != NULL) {
/* if user chose us, then just send willing */
- if (gdm_address_is_local (id->chosen_host)) {
+ if (gdm_address_is_local (ic->chosen_address)) {
+ g_debug ("GdmXdmcpDisplayFactory: the chosen address is local - dropping indirect");
+
/* get rid of indirect, so that we don't get
* the chooser */
- gdm_choose_indirect_dispose (id);
+ indirect_client_destroy (factory, ic);
gdm_xdmcp_send_willing (factory, address);
} else if (gdm_address_is_loopback (address)) {
/* woohoo! fun, I have no clue how to get
@@ -1112,13 +1272,15 @@ gdm_xdmcp_handle_indirect_query (GdmXdmcpDisplayFactory *factory,
* queries with all the different IPs */
const GList *list = gdm_address_peek_local_list ();
+ g_debug ("GdmXdmcpDisplayFactory: the chosen address is a loopback");
+
while (list != NULL) {
GdmAddress *saddr = list->data;
if (! gdm_address_is_loopback (saddr)) {
/* forward query to * chosen host */
gdm_xdmcp_send_forward_query (factory,
- id,
+ ic,
address,
saddr,
&clnt_authlist);
@@ -1129,28 +1291,27 @@ gdm_xdmcp_handle_indirect_query (GdmXdmcpDisplayFactory *factory,
} else {
/* or send forward query to chosen host */
gdm_xdmcp_send_forward_query (factory,
- id,
+ ic,
address,
address,
&clnt_authlist);
}
- } else if (id == NULL) {
- id = gdm_choose_indirect_alloc (address);
- if (id != NULL) {
+ } else if (ic == NULL) {
+ ic = indirect_client_create (factory, address);
+ if (ic != NULL) {
gdm_xdmcp_send_willing (factory, address);
}
} else {
gdm_xdmcp_send_willing (factory, address);
}
-#endif
out:
XdmcpDisposeARRAYofARRAY8 (&clnt_authlist);
}
static void
-gdm_forward_query_dispose (GdmXdmcpDisplayFactory *factory,
- GdmForwardQuery *q)
+forward_query_destroy (GdmXdmcpDisplayFactory *factory,
+ ForwardQuery *q)
{
if (q == NULL) {
return;
@@ -1180,11 +1341,11 @@ gdm_forward_query_dispose (GdmXdmcpDisplayFactory *factory,
static gboolean
remove_oldest_forward (GdmXdmcpDisplayFactory *factory)
{
- GSList *li;
- GdmForwardQuery *oldest = NULL;
+ GSList *li;
+ ForwardQuery *oldest = NULL;
for (li = factory->priv->forward_queries; li != NULL; li = li->next) {
- GdmForwardQuery *query = li->data;
+ ForwardQuery *query = li->data;
if (oldest == NULL || query->acctime < oldest->acctime) {
oldest = query;
@@ -1192,20 +1353,20 @@ remove_oldest_forward (GdmXdmcpDisplayFactory *factory)
}
if (oldest != NULL) {
- gdm_forward_query_dispose (factory, oldest);
+ forward_query_destroy (factory, oldest);
return TRUE;
} else {
return FALSE;
}
}
-static GdmForwardQuery *
-gdm_forward_query_alloc (GdmXdmcpDisplayFactory *factory,
+static ForwardQuery *
+forward_query_create (GdmXdmcpDisplayFactory *factory,
GdmAddress *mgr_address,
GdmAddress *dsp_address)
{
- GdmForwardQuery *q;
- int count;
+ ForwardQuery *q;
+ int count;
count = g_slist_length (factory->priv->forward_queries);
@@ -1213,7 +1374,7 @@ gdm_forward_query_alloc (GdmXdmcpDisplayFactory *factory,
count--;
}
- q = g_new0 (GdmForwardQuery, 1);
+ q = g_new0 (ForwardQuery, 1);
q->dsp_address = gdm_address_copy (dsp_address);
q->from_address = gdm_address_copy (mgr_address);
@@ -1222,14 +1383,14 @@ gdm_forward_query_alloc (GdmXdmcpDisplayFactory *factory,
return q;
}
-static GdmForwardQuery *
-gdm_forward_query_lookup (GdmXdmcpDisplayFactory *factory,
+static ForwardQuery *
+forward_query_lookup (GdmXdmcpDisplayFactory *factory,
GdmAddress *address)
{
- GSList *li;
- GSList *qlist;
- GdmForwardQuery *ret;
- time_t curtime;
+ GSList *li;
+ GSList *qlist;
+ ForwardQuery *ret;
+ time_t curtime;
curtime = time (NULL);
ret = NULL;
@@ -1237,11 +1398,11 @@ gdm_forward_query_lookup (GdmXdmcpDisplayFactory *factory,
qlist = g_slist_copy (factory->priv->forward_queries);
for (li = qlist; li != NULL; li = li->next) {
- GdmForwardQuery *q;
- char *host;
- char *serv;
+ ForwardQuery *q;
+ char *host;
+ char *serv;
- q = (GdmForwardQuery *) li->data;
+ q = (ForwardQuery *) li->data;
if (q == NULL) {
continue;
@@ -1263,7 +1424,7 @@ gdm_forward_query_lookup (GdmXdmcpDisplayFactory *factory,
g_debug ("GdmXdmcpDisplayFactory: Disposing stale forward query from %s:%s",
host, serv);
- gdm_forward_query_dispose (factory, q);
+ forward_query_destroy (factory, q);
}
g_free (host);
@@ -1482,14 +1643,14 @@ gdm_xdmcp_handle_forward_query (GdmXdmcpDisplayFactory *factory,
/* Check with tcp_wrappers if display is allowed to access */
if (gdm_xdmcp_host_allow (disp_address)) {
- GdmForwardQuery *q;
+ ForwardQuery *q;
- q = gdm_forward_query_lookup (factory, disp_address);
+ q = forward_query_lookup (factory, disp_address);
if (q != NULL) {
- gdm_forward_query_dispose (factory, q);
+ forward_query_destroy (factory, q);
}
- gdm_forward_query_alloc (factory, address, disp_address);
+ forward_query_create (factory, address, disp_address);
gdm_xdmcp_send_willing (factory, disp_address);
}
@@ -1751,7 +1912,7 @@ gdm_xdmcp_send_decline (GdmXdmcpDisplayFactory *factory,
ARRAY8 authentype;
ARRAY8 authendata;
ARRAY8 status;
- GdmForwardQuery *fq;
+ ForwardQuery *fq;
char *host;
host = NULL;
@@ -1786,28 +1947,100 @@ gdm_xdmcp_send_decline (GdmXdmcpDisplayFactory *factory,
/* Send MANAGED_FORWARD to indicate that the connection
* reached some sort of resolution */
- fq = gdm_forward_query_lookup (factory, address);
+ fq = forward_query_lookup (factory, address);
if (fq != NULL) {
gdm_xdmcp_send_managed_forward (factory, fq->from_address, address);
- gdm_forward_query_dispose (factory, fq);
+ forward_query_destroy (factory, fq);
}
}
+static void
+on_hostname_selected (GdmXdmcpChooserDisplay *display,
+ const char *hostname,
+ GdmXdmcpDisplayFactory *factory)
+{
+ struct addrinfo hints;
+ struct addrinfo *ai_list;
+ struct addrinfo *ai;
+ int gaierr;
+ GdmAddress *address;
+ IndirectClient *ic;
+
+ g_debug ("GdmXdmcpDisplayFactory: hostname selected: %s", hostname);
+
+ address = gdm_xdmcp_display_get_remote_address (GDM_XDMCP_DISPLAY (display));
+
+ g_assert (address != NULL);
+
+ ic = indirect_client_lookup (factory, address);
+
+ if (ic->chosen_address != NULL) {
+ gdm_address_free (ic->chosen_address);
+ ic->chosen_address = NULL;
+ }
+
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = gdm_address_get_family_type (address);
+ hints.ai_flags = AI_V4MAPPED; /* this should convert IPv4 address to IPv6 if needed */
+ if ((gaierr = getaddrinfo (hostname, NULL, &hints, &ai_list)) != 0) {
+ g_warning ("Unable get address: %s", gai_strerror (gaierr));
+ return;
+ }
+
+ /* just take the first one */
+ ai = ai_list;
+
+ if (ai != NULL) {
+ char *ip;
+ ic->chosen_address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
+
+ ip = NULL;
+ gdm_address_get_numeric_info (ic->chosen_address, &ip, NULL);
+ g_debug ("GdmXdmcpDisplayFactory: hostname resolves to %s", ip);
+ g_free (ip);
+ }
+
+ freeaddrinfo (ai_list);
+}
+
static GdmDisplay *
-gdm_xdmcp_display_alloc (GdmXdmcpDisplayFactory *factory,
- const char *hostname,
- GdmAddress *address,
- int displaynum)
+gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
+ const char *hostname,
+ GdmAddress *address,
+ int displaynum)
{
GdmDisplay *display;
GdmDisplayStore *store;
+ gboolean use_chooser;
g_debug ("GdmXdmcpDisplayFactory: Creating xdmcp display for %s:%d", hostname, displaynum);
- display = gdm_xdmcp_display_new (hostname,
- displaynum,
- address,
- get_next_session_serial (factory));
+ use_chooser = FALSE;
+ if (factory->priv->honor_indirect) {
+ IndirectClient *ic;
+
+ ic = indirect_client_lookup (factory, address);
+
+ /* This was an indirect thingie and nothing was yet chosen,
+ * use a chooser */
+ if (ic != NULL && ic->chosen_address == NULL) {
+ use_chooser = TRUE;
+ }
+ }
+
+ if (use_chooser) {
+ display = gdm_xdmcp_chooser_display_new (hostname,
+ displaynum,
+ address,
+ get_next_session_serial (factory));
+ g_signal_connect (display, "hostname-selected", G_CALLBACK (on_hostname_selected), factory);
+ } else {
+ display = gdm_xdmcp_greeter_display_new (hostname,
+ displaynum,
+ address,
+ get_next_session_serial (factory));
+ }
+
if (display == NULL) {
goto out;
}
@@ -2036,10 +2269,10 @@ gdm_xdmcp_handle_request (GdmXdmcpDisplayFactory *factory,
} else {
GdmDisplay *display;
- display = gdm_xdmcp_display_alloc (factory,
- hostname,
- address,
- clnt_dspnum);
+ display = gdm_xdmcp_display_create (factory,
+ hostname,
+ address,
+ clnt_dspnum);
if (display != NULL) {
ARRAY8 authentication_name;
@@ -2196,8 +2429,8 @@ gdm_xdmcp_send_refuse (GdmXdmcpDisplayFactory *factory,
GdmAddress *address,
CARD32 sessid)
{
- XdmcpHeader header;
- GdmForwardQuery *fq;
+ XdmcpHeader header;
+ ForwardQuery *fq;
g_debug ("GdmXdmcpDisplayFactory: Sending REFUSE to %ld",
(long)sessid);
@@ -2218,10 +2451,10 @@ gdm_xdmcp_send_refuse (GdmXdmcpDisplayFactory *factory,
* This was from a forwarded query quite apparently so
* send MANAGED_FORWARD
*/
- fq = gdm_forward_query_lookup (factory, address);
+ fq = forward_query_lookup (factory, address);
if (fq != NULL) {
gdm_xdmcp_send_managed_forward (factory, fq->from_address, address);
- gdm_forward_query_dispose (factory, fq);
+ forward_query_destroy (factory, fq);
}
}
@@ -2234,7 +2467,7 @@ gdm_xdmcp_handle_manage (GdmXdmcpDisplayFactory *factory,
CARD16 clnt_dspnum;
ARRAY8 clnt_dspclass;
GdmDisplay *display;
- GdmForwardQuery *fq;
+ ForwardQuery *fq;
char *host;
host = NULL;
@@ -2292,36 +2525,34 @@ gdm_xdmcp_handle_manage (GdmXdmcpDisplayFactory *factory,
g_debug ("GdmXdmcpDisplayFactory: Looked up %s", name);
g_free (name);
-#if 0
- /* FIXME: Add chooser support */
if (factory->priv->honor_indirect) {
- GdmIndirectDisplay *id;
+ IndirectClient *ic;
- id = gdm_choose_indirect_lookup (address);
+ ic = indirect_client_lookup (factory, address);
/* This was an indirect thingie and nothing was yet chosen,
* use a chooser */
- if (id != NULL &&
- id->chosen_host == NULL) {
- d->use_chooser = TRUE;
- d->indirect_id = id->id;
+ if (ic != NULL && ic->chosen_address == NULL) {
+ g_debug ("GdmXdmcpDisplayFactory: use chooser");
+ /*d->use_chooser = TRUE;
+ d->indirect_id = ic->id;*/
} else {
- d->indirect_id = 0;
- d->use_chooser = FALSE;
- if (id != NULL) {
- gdm_choose_indirect_dispose (id);
+ /*d->indirect_id = 0;
+ d->use_chooser = FALSE;*/
+ if (ic != NULL) {
+ indirect_client_destroy (factory, ic);
}
}
} else {
}
-#endif
+
/* this was from a forwarded query quite apparently so
* send MANAGED_FORWARD */
- fq = gdm_forward_query_lookup (factory, address);
+ fq = forward_query_lookup (factory, address);
if (fq != NULL) {
gdm_xdmcp_send_managed_forward (factory, fq->from_address, address);
- gdm_forward_query_dispose (factory, fq);
+ forward_query_destroy (factory, fq);
}
factory->priv->num_sessions++;
@@ -2355,6 +2586,7 @@ gdm_xdmcp_handle_managed_forward (GdmXdmcpDisplayFactory *factory,
ARRAY8 clnt_address;
char *host;
GdmAddress *disp_address;
+ IndirectClient *ic;
host = NULL;
gdm_address_get_numeric_info (address, &host, NULL);
@@ -2384,14 +2616,10 @@ gdm_xdmcp_handle_managed_forward (GdmXdmcpDisplayFactory *factory,
return;
}
-#if 0
- GdmIndirectDisplay *id;
- /* FIXME: Add chooser support */
- id = gdm_choose_indirect_lookup_by_chosen (address, disp_address);
- if (id != NULL) {
- gdm_choose_indirect_dispose (id);
+ ic = indirect_client_lookup_by_chosen (factory, address, disp_address);
+ if (ic != NULL) {
+ indirect_client_destroy (factory, ic);
}
-#endif
/* Note: we send GOT even on not found, just in case our previous
* didn't get through and this was a second managed forward */
diff --git a/daemon/gdm-xdmcp-display.c b/daemon/gdm-xdmcp-display.c
index c6c44ace..2e40305f 100644
--- a/daemon/gdm-xdmcp-display.c
+++ b/daemon/gdm-xdmcp-display.c
@@ -37,7 +37,6 @@
#include "gdm-display.h"
#include "gdm-xdmcp-display.h"
-#include "gdm-xdmcp-display-glue.h"
#include "gdm-common.h"
#include "gdm-address.h"
@@ -60,7 +59,7 @@ static void gdm_xdmcp_display_class_init (GdmXdmcpDisplayClass *klass);
static void gdm_xdmcp_display_init (GdmXdmcpDisplay *xdmcp_display);
static void gdm_xdmcp_display_finalize (GObject *object);
-G_DEFINE_TYPE (GdmXdmcpDisplay, gdm_xdmcp_display, GDM_TYPE_DISPLAY)
+G_DEFINE_ABSTRACT_TYPE (GdmXdmcpDisplay, gdm_xdmcp_display, GDM_TYPE_DISPLAY)
gint32
gdm_xdmcp_display_get_session_number (GdmXdmcpDisplay *display)
@@ -218,7 +217,6 @@ gdm_xdmcp_display_class_init (GdmXdmcpDisplayClass *klass)
0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- dbus_g_object_type_install_info (GDM_TYPE_XDMCP_DISPLAY, &dbus_glib_gdm_xdmcp_display_object_info);
}
static void
@@ -242,26 +240,3 @@ gdm_xdmcp_display_finalize (GObject *object)
G_OBJECT_CLASS (gdm_xdmcp_display_parent_class)->finalize (object);
}
-
-GdmDisplay *
-gdm_xdmcp_display_new (const char *hostname,
- int number,
- GdmAddress *address,
- gint32 session_number)
-{
- GObject *object;
- char *x11_display;
-
- x11_display = g_strdup_printf ("%s:%d", hostname, number);
- object = g_object_new (GDM_TYPE_XDMCP_DISPLAY,
- "remote-hostname", hostname,
- "x11-display-number", number,
- "x11-display-name", x11_display,
- "is-local", FALSE,
- "remote-address", address,
- "session-number", session_number,
- NULL);
- g_free (x11_display);
-
- return GDM_DISPLAY (object);
-}
diff --git a/daemon/gdm-xdmcp-display.h b/daemon/gdm-xdmcp-display.h
index 1748bc96..db9b4014 100644
--- a/daemon/gdm-xdmcp-display.h
+++ b/daemon/gdm-xdmcp-display.h
@@ -55,12 +55,6 @@ typedef struct
GType gdm_xdmcp_display_get_type (void);
-
-GdmDisplay * gdm_xdmcp_display_new (const char *hostname,
- int number,
- GdmAddress *addr,
- gint32 serial_number);
-
gint32 gdm_xdmcp_display_get_session_number (GdmXdmcpDisplay *display);
GdmAddress * gdm_xdmcp_display_get_remote_address (GdmXdmcpDisplay *display);
diff --git a/daemon/gdm-xdmcp-greeter-display.c b/daemon/gdm-xdmcp-greeter-display.c
new file mode 100644
index 00000000..2273f4b3
--- /dev/null
+++ b/daemon/gdm-xdmcp-greeter-display.c
@@ -0,0 +1,120 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+
+#include "gdm-xdmcp-display.h"
+#include "gdm-xdmcp-greeter-display.h"
+#include "gdm-xdmcp-greeter-display-glue.h"
+
+#include "gdm-common.h"
+#include "gdm-address.h"
+
+#define GDM_XDMCP_GREETER_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_XDMCP_GREETER_DISPLAY, GdmXdmcpGreeterDisplayPrivate))
+
+struct GdmXdmcpGreeterDisplayPrivate
+{
+ GdmAddress *remote_address;
+ gint32 session_number;
+};
+
+enum {
+ PROP_0,
+ PROP_REMOTE_ADDRESS,
+ PROP_SESSION_NUMBER,
+};
+
+static void gdm_xdmcp_greeter_display_class_init (GdmXdmcpGreeterDisplayClass *klass);
+static void gdm_xdmcp_greeter_display_init (GdmXdmcpGreeterDisplay *xdmcp_greeter_display);
+static void gdm_xdmcp_greeter_display_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmXdmcpGreeterDisplay, gdm_xdmcp_greeter_display, GDM_TYPE_XDMCP_DISPLAY)
+
+static void
+gdm_xdmcp_greeter_display_class_init (GdmXdmcpGreeterDisplayClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gdm_xdmcp_greeter_display_finalize;
+
+ g_type_class_add_private (klass, sizeof (GdmXdmcpGreeterDisplayPrivate));
+
+ dbus_g_object_type_install_info (GDM_TYPE_XDMCP_GREETER_DISPLAY, &dbus_glib_gdm_xdmcp_greeter_display_object_info);
+}
+
+static void
+gdm_xdmcp_greeter_display_init (GdmXdmcpGreeterDisplay *xdmcp_greeter_display)
+{
+
+ xdmcp_greeter_display->priv = GDM_XDMCP_GREETER_DISPLAY_GET_PRIVATE (xdmcp_greeter_display);
+}
+
+static void
+gdm_xdmcp_greeter_display_finalize (GObject *object)
+{
+ GdmXdmcpGreeterDisplay *xdmcp_greeter_display;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_XDMCP_GREETER_DISPLAY (object));
+
+ xdmcp_greeter_display = GDM_XDMCP_GREETER_DISPLAY (object);
+
+ g_return_if_fail (xdmcp_greeter_display->priv != NULL);
+
+ G_OBJECT_CLASS (gdm_xdmcp_greeter_display_parent_class)->finalize (object);
+}
+
+GdmDisplay *
+gdm_xdmcp_greeter_display_new (const char *hostname,
+ int number,
+ GdmAddress *address,
+ gint32 session_number)
+{
+ GObject *object;
+ char *x11_display;
+
+ x11_display = g_strdup_printf ("%s:%d", hostname, number);
+ object = g_object_new (GDM_TYPE_XDMCP_GREETER_DISPLAY,
+ "remote-hostname", hostname,
+ "x11-display-number", number,
+ "x11-display-name", x11_display,
+ "is-local", FALSE,
+ "remote-address", address,
+ "session-number", session_number,
+ NULL);
+ g_free (x11_display);
+
+ return GDM_DISPLAY (object);
+}
diff --git a/daemon/gdm-xdmcp-greeter-display.h b/daemon/gdm-xdmcp-greeter-display.h
new file mode 100644
index 00000000..c4c82a50
--- /dev/null
+++ b/daemon/gdm-xdmcp-greeter-display.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GDM_XDMCP_GREETER_DISPLAY_H
+#define __GDM_XDMCP_GREETER_DISPLAY_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#include "gdm-xdmcp-display.h"
+#include "gdm-address.h"
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_XDMCP_GREETER_DISPLAY (gdm_xdmcp_greeter_display_get_type ())
+#define GDM_XDMCP_GREETER_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_XDMCP_GREETER_DISPLAY, GdmXdmcpGreeterDisplay))
+#define GDM_XDMCP_GREETER_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_XDMCP_GREETER_DISPLAY, GdmXdmcpGreeterDisplayClass))
+#define GDM_IS_XDMCP_GREETER_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_XDMCP_GREETER_DISPLAY))
+#define GDM_IS_XDMCP_GREETER_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_XDMCP_GREETER_DISPLAY))
+#define GDM_XDMCP_GREETER_DISPLAY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_XDMCP_GREETER_DISPLAY, GdmXdmcpGreeterDisplayClass))
+
+typedef struct GdmXdmcpGreeterDisplayPrivate GdmXdmcpGreeterDisplayPrivate;
+
+typedef struct
+{
+ GdmXdmcpDisplay parent;
+ GdmXdmcpGreeterDisplayPrivate *priv;
+} GdmXdmcpGreeterDisplay;
+
+typedef struct
+{
+ GdmXdmcpDisplayClass parent_class;
+
+} GdmXdmcpGreeterDisplayClass;
+
+GType gdm_xdmcp_greeter_display_get_type (void);
+
+
+GdmDisplay * gdm_xdmcp_greeter_display_new (const char *hostname,
+ int number,
+ GdmAddress *addr,
+ gint32 serial_number);
+
+G_END_DECLS
+
+#endif /* __GDM_XDMCP_GREETER_DISPLAY_H */
diff --git a/daemon/gdm-xdmcp-display.xml b/daemon/gdm-xdmcp-greeter-display.xml
index 512019ce..512019ce 100644
--- a/daemon/gdm-xdmcp-display.xml
+++ b/daemon/gdm-xdmcp-greeter-display.xml
diff --git a/daemon/xdmcp-chooser-slave-main.c b/daemon/xdmcp-chooser-slave-main.c
new file mode 100644
index 00000000..2f7996d1
--- /dev/null
+++ b/daemon/xdmcp-chooser-slave-main.c
@@ -0,0 +1,229 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "gdm-signal-handler.h"
+#include "gdm-log.h"
+#include "gdm-common.h"
+#include "gdm-xdmcp-chooser-slave.h"
+
+static int gdm_return_code = 0;
+
+static DBusGConnection *
+get_system_bus (void)
+{
+ GError *error;
+ DBusGConnection *bus;
+ DBusConnection *connection;
+
+ error = NULL;
+ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (bus == NULL) {
+ g_warning ("Couldn't connect to system bus: %s",
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ connection = dbus_g_connection_get_connection (bus);
+ dbus_connection_set_exit_on_disconnect (connection, FALSE);
+
+ out:
+ return bus;
+}
+
+static gboolean
+signal_cb (int signo,
+ gpointer data)
+{
+ int ret;
+
+ g_debug ("Got callback for signal %d", signo);
+
+ ret = TRUE;
+
+ switch (signo) {
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGILL:
+ case SIGABRT:
+ g_debug ("Caught signal %d.", signo);
+
+ ret = FALSE;
+ break;
+
+ case SIGFPE:
+ case SIGPIPE:
+ /* let the fatal signals interrupt us */
+ g_debug ("Caught signal %d, shutting down abnormally.", signo);
+ ret = FALSE;
+
+ break;
+
+ case SIGINT:
+ case SIGTERM:
+ /* let the fatal signals interrupt us */
+ g_debug ("Caught signal %d, shutting down normally.", signo);
+ ret = FALSE;
+
+ break;
+
+ case SIGHUP:
+ g_debug ("Got HUP signal");
+ /* FIXME:
+ * Reread config stuff like system config files, VPN service files, etc
+ */
+ ret = TRUE;
+
+ break;
+
+ case SIGUSR1:
+ g_debug ("Got USR1 signal");
+ /* FIXME:
+ * Play with log levels or something
+ */
+ ret = TRUE;
+
+ break;
+
+ default:
+ g_debug ("Caught unhandled signal %d", signo);
+ ret = TRUE;
+
+ break;
+ }
+
+ return ret;
+}
+
+static void
+on_slave_stopped (GdmSlave *slave,
+ GMainLoop *main_loop)
+{
+ g_debug ("slave finished");
+ gdm_return_code = 0;
+ g_main_loop_quit (main_loop);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ GMainLoop *main_loop;
+ GOptionContext *context;
+ DBusGConnection *connection;
+ GdmSlave *slave;
+ static char *display_id = NULL;
+ GdmSignalHandler *signal_handler;
+ static GOptionEntry entries [] = {
+ { "display-id", 0, 0, G_OPTION_ARG_STRING, &display_id, N_("Display ID"), N_("id") },
+ { NULL }
+ };
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ textdomain (GETTEXT_PACKAGE);
+ setlocale (LC_ALL, "");
+
+ gdm_set_fatal_warnings_if_unstable ();
+
+ g_type_init ();
+
+ context = g_option_context_new (_("GNOME Display Manager Slave"));
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ g_option_context_parse (context, &argc, &argv, NULL);
+ g_option_context_free (context);
+
+ connection = get_system_bus ();
+ if (connection == NULL) {
+ goto out;
+ }
+
+ gdm_log_init ();
+
+ gdm_log_set_debug (TRUE);
+
+ if (display_id == NULL) {
+ g_critical ("No display ID set");
+ exit (1);
+ }
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+
+ signal_handler = gdm_signal_handler_new ();
+ gdm_signal_handler_set_main_loop (signal_handler, main_loop);
+ gdm_signal_handler_add (signal_handler, SIGTERM, signal_cb, NULL);
+ gdm_signal_handler_add (signal_handler, SIGINT, signal_cb, NULL);
+ gdm_signal_handler_add (signal_handler, SIGILL, signal_cb, NULL);
+ gdm_signal_handler_add (signal_handler, SIGBUS, signal_cb, NULL);
+ gdm_signal_handler_add (signal_handler, SIGFPE, signal_cb, NULL);
+ gdm_signal_handler_add (signal_handler, SIGHUP, signal_cb, NULL);
+ gdm_signal_handler_add (signal_handler, SIGSEGV, signal_cb, NULL);
+ gdm_signal_handler_add (signal_handler, SIGABRT, signal_cb, NULL);
+ gdm_signal_handler_add (signal_handler, SIGUSR1, signal_cb, NULL);
+
+ slave = gdm_xdmcp_chooser_slave_new (display_id);
+ if (slave == NULL) {
+ goto out;
+ }
+ g_signal_connect (slave,
+ "stopped",
+ G_CALLBACK (on_slave_stopped),
+ main_loop);
+ gdm_slave_start (slave);
+
+ g_main_loop_run (main_loop);
+
+ if (slave != NULL) {
+ g_object_unref (slave);
+ }
+
+ if (signal_handler != NULL) {
+ g_object_unref (signal_handler);
+ }
+
+ g_main_loop_unref (main_loop);
+
+ out:
+
+ g_debug ("Slave finished");
+
+ return gdm_return_code;
+}
diff --git a/data/gdm.conf b/data/gdm.conf
index 343ed88f..bdcdd6da 100644
--- a/data/gdm.conf
+++ b/data/gdm.conf
@@ -27,6 +27,8 @@
send_member="AddUserAuthoritization"/>
<deny send_interface="org.gnome.DisplayManager.Display"
send_member="RemoveUserAuthoritization"/>
+ <deny send_interface="org.gnome.DisplayManager.Display"
+ send_member="SetSlaveBusName"/>
<deny send_interface="org.gnome.DisplayManager.Settings"
send_member="SetValue"/>
</policy>
diff --git a/gui/simple-chooser/Makefile.am b/gui/simple-chooser/Makefile.am
index 32543b07..8fabe53f 100644
--- a/gui/simple-chooser/Makefile.am
+++ b/gui/simple-chooser/Makefile.am
@@ -11,6 +11,10 @@ INCLUDES = \
-DLIBEXECDIR=\""$(libexecdir)"\" \
-DSBINDIR=\""$(sbindir)"\" \
-DPIXMAPDIR=\""$(pixmapdir)"\" \
+ -DAT_SPI_REGISTRYD_DIR="\"$(AT_SPI_REGISTRYD_DIR)\"" \
+ $(GTK_CFLAGS) \
+ $(XDMCP_CFLAGS) \
+ $(EXTRA_CHOOSER_CFLAGS) \
$(SIMPLE_CHOOSER_CFLAGS) \
$(NULL)
@@ -18,15 +22,40 @@ libexec_PROGRAMS = \
gdm-simple-chooser \
$(NULL)
+noinst_PROGRAMS = \
+ test-host-chooser \
+ $(NULL)
+
gdm_simple_chooser_SOURCES = \
chooser-main.c \
gdm-host-chooser-widget.c \
gdm-host-chooser-widget.h \
gdm-host-chooser-dialog.c \
gdm-host-chooser-dialog.h \
+ gdm-chooser-client.c \
+ gdm-chooser-client.h \
+ gdm-chooser-session.c \
+ gdm-chooser-session.h \
$(NULL)
gdm_simple_chooser_LDADD = \
+ $(GTK_LIBS) \
+ $(EXTRA_CHOOSER_LIBS) \
+ $(SIMPLE_CHOOSER_LIBS) \
+ $(XDMCP_LIBS) \
+ $(top_builddir)/common/libgdmcommon.la \
+ $(NULL)
+
+test_host_chooser_SOURCES = \
+ test-host-chooser.c \
+ gdm-host-chooser-widget.c \
+ gdm-host-chooser-widget.h \
+ gdm-host-chooser-dialog.c \
+ gdm-host-chooser-dialog.h \
+ $(NULL)
+
+test_host_chooser_LDADD = \
+ $(GTK_LIBS) \
$(EXTRA_CHOOSER_LIBS) \
$(SIMPLE_CHOOSER_LIBS) \
$(XDMCP_LIBS) \
diff --git a/gui/simple-chooser/chooser-main.c b/gui/simple-chooser/chooser-main.c
index 459bc0d2..17d7765b 100644
--- a/gui/simple-chooser/chooser-main.c
+++ b/gui/simple-chooser/chooser-main.c
@@ -28,22 +28,204 @@
#include <errno.h>
#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
#include <gtk/gtk.h>
-#define DBUS_API_SUBJECT_TO_CHANGE
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
+#include <gconf/gconf-client.h>
#include "gdm-common.h"
#include "gdm-log.h"
#include "gdm-settings-client.h"
#include "gdm-settings-keys.h"
-#include "gdm-host-chooser-dialog.h"
+#include "gdm-chooser-session.h"
+
+#define ACCESSIBILITY_KEY "/desktop/gnome/interface/accessibility"
+
+static Atom AT_SPI_IOR;
+
+
+static gboolean
+assistive_registry_launch (void)
+{
+ GPid pid;
+ GError *error;
+ const char *command;
+ char **argv;
+ gboolean res;
+
+ command = AT_SPI_REGISTRYD_DIR "/at-spi-registryd";
+
+ argv = NULL;
+ error = NULL;
+ res = g_shell_parse_argv (command, NULL, &argv, &error);
+ if (! res) {
+ g_warning ("Unable to parse command: %s", error->message);
+ return FALSE;
+ }
+
+ error = NULL;
+ res = g_spawn_async (NULL,
+ argv,
+ NULL,
+ G_SPAWN_SEARCH_PATH
+ | G_SPAWN_STDOUT_TO_DEV_NULL
+ | G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL,
+ NULL,
+ &pid,
+ &error);
+ g_strfreev (argv);
+
+ if (! res) {
+ g_warning ("Unable to run command %s: %s", command, error->message);
+ return FALSE;
+ }
+
+ if (kill (pid, 0) < 0) {
+ g_warning ("at-spi-registryd not running");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GdkFilterReturn
+filter_watch (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ XEvent *xev = (XEvent *)xevent;
+
+ if (xev->xany.type == PropertyNotify
+ && xev->xproperty.atom == AT_SPI_IOR) {
+ gtk_main_quit ();
+
+ return GDK_FILTER_REMOVE;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static gboolean
+filter_timeout (gpointer data)
+{
+ g_warning ("The accessibility registry was not found.");
+
+ gtk_main_quit ();
+
+ return FALSE;
+}
+
+static void
+assistive_registry_start (void)
+{
+ GdkWindow *root;
+ guint tid;
+
+ root = gdk_get_default_root_window ();
+
+ if ( ! AT_SPI_IOR) {
+ AT_SPI_IOR = XInternAtom (GDK_DISPLAY (), "AT_SPI_IOR", False);
+ }
+
+ gdk_window_set_events (root, GDK_PROPERTY_CHANGE_MASK);
+
+ if ( ! assistive_registry_launch ()) {
+ g_warning ("The accessibility registry could not be started.");
+ return;
+ }
+
+ gdk_window_add_filter (root, filter_watch, NULL);
+ tid = g_timeout_add_seconds (5, filter_timeout, NULL);
+
+ gtk_main ();
+
+ gdk_window_remove_filter (root, filter_watch, NULL);
+ g_source_remove (tid);
+}
+
+static void
+at_set_gtk_modules (void)
+{
+ GSList *modules_list;
+ GSList *l;
+ const char *old;
+ char **modules;
+ gboolean found_gail;
+ gboolean found_atk_bridge;
+ int n;
+
+ n = 0;
+ modules_list = NULL;
+ found_gail = FALSE;
+ found_atk_bridge = FALSE;
+
+ if ((old = g_getenv ("GTK_MODULES")) != NULL) {
+ modules = g_strsplit (old, ":", -1);
+ for (n = 0; modules[n]; n++) {
+ if (!strcmp (modules[n], "gail")) {
+ found_gail = TRUE;
+ } else if (!strcmp (modules[n], "atk-bridge")) {
+ found_atk_bridge = TRUE;
+ }
+
+ modules_list = g_slist_prepend (modules_list, modules[n]);
+ modules[n] = NULL;
+ }
+ g_free (modules);
+ }
+
+ if (!found_gail) {
+ modules_list = g_slist_prepend (modules_list, "gail");
+ ++n;
+ }
+
+ if (!found_atk_bridge) {
+ modules_list = g_slist_prepend (modules_list, "atk-bridge");
+ ++n;
+ }
+
+ modules = g_new (char *, n + 1);
+ modules[n--] = NULL;
+ for (l = modules_list; l; l = l->next) {
+ modules[n--] = g_strdup (l->data);
+ }
+
+ g_setenv ("GTK_MODULES", g_strjoinv (":", modules), TRUE);
+ g_strfreev (modules);
+ g_slist_free (modules_list);
+}
+
+static void
+load_a11y (void)
+{
+ const char *env_a_t_support;
+ gboolean a_t_support;
+ GConfClient *gconf_client;
+
+ gconf_client = gconf_client_get_default ();
+
+ env_a_t_support = g_getenv ("GNOME_ACCESSIBILITY");
+ if (env_a_t_support) {
+ a_t_support = atoi (env_a_t_support);
+ } else {
+ a_t_support = gconf_client_get_bool (gconf_client, ACCESSIBILITY_KEY, NULL);
+ }
+
+ if (a_t_support) {
+ assistive_registry_start ();
+ at_set_gtk_modules ();
+ }
+
+ g_object_unref (gconf_client);
+}
int
main (int argc, char *argv[])
{
- GtkWidget *chooser;
+ GdmChooserSession *session;
+ gboolean res;
+ GError *error;
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
@@ -51,29 +233,42 @@ main (int argc, char *argv[])
setlocale (LC_ALL, "");
+ gdm_set_fatal_warnings_if_unstable ();
+
g_type_init ();
- g_debug ("Chooser for display %s xauthority:%s", g_getenv ("DISPLAY"), g_getenv ("XAUTHORITY"));
+ gdm_log_init ();
+ gdm_log_set_debug (TRUE);
+
+ g_debug ("Chooser for display %s xauthority:%s",
+ g_getenv ("DISPLAY"),
+ g_getenv ("XAUTHORITY"));
- /*
- * gdm_common_atspi_launch () needs gdk initialized.
- * We cannot start gtk before the registry is running
- * because the atk-bridge will crash.
- */
gdk_init (&argc, &argv);
- /*gdm_common_atspi_launch ();*/
+
+ load_a11y ();
+
gtk_init (&argc, &argv);
- chooser = gdm_host_chooser_dialog_new ();
- if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_OK) {
- char *hostname;
+ session = gdm_chooser_session_new ();
+ if (session == NULL) {
+ g_critical ("Unable to create chooser session");
+ exit (1);
+ }
- hostname = gdm_host_chooser_dialog_get_current_hostname (GDM_HOST_CHOOSER_DIALOG (chooser));
- g_print ("hostname: %s\n", hostname);
- g_free (hostname);
+ error = NULL;
+ res = gdm_chooser_session_start (session, &error);
+ if (! res) {
+ g_warning ("Unable to start chooser session: %s", error->message);
+ g_error_free (error);
+ exit (1);
}
- gtk_widget_destroy (chooser);
+ gtk_main ();
+
+ if (session != NULL) {
+ g_object_unref (session);
+ }
return 0;
}
diff --git a/gui/simple-chooser/gdm-chooser-client.c b/gui/simple-chooser/gdm-chooser-client.c
new file mode 100644
index 00000000..268fddf2
--- /dev/null
+++ b/gui/simple-chooser/gdm-chooser-client.c
@@ -0,0 +1,414 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "gdm-chooser-client.h"
+
+#define GDM_CHOOSER_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CHOOSER_CLIENT, GdmChooserClientPrivate))
+
+#define CHOOSER_SERVER_DBUS_PATH "/org/gnome/DisplayManager/ChooserServer"
+#define CHOOSER_SERVER_DBUS_INTERFACE "org.gnome.DisplayManager.ChooserServer"
+
+#define GDM_DBUS_NAME "org.gnome.DisplayManager"
+#define GDM_DBUS_DISPLAY_INTERFACE "org.gnome.DisplayManager.Display"
+
+struct GdmChooserClientPrivate
+{
+ DBusConnection *connection;
+ char *address;
+};
+
+enum {
+ PROP_0,
+};
+
+static void gdm_chooser_client_class_init (GdmChooserClientClass *klass);
+static void gdm_chooser_client_init (GdmChooserClient *chooser_client);
+static void gdm_chooser_client_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmChooserClient, gdm_chooser_client, G_TYPE_OBJECT)
+
+static gpointer client_object = NULL;
+
+GQuark
+gdm_chooser_client_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (error_quark == 0)
+ error_quark = g_quark_from_static_string ("gdm-chooser-client");
+
+ return error_quark;
+}
+
+static gboolean
+send_dbus_string_method (DBusConnection *connection,
+ const char *method,
+ const char *payload)
+{
+ DBusError error;
+ DBusMessage *message;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ const char *str;
+
+ if (payload != NULL) {
+ str = payload;
+ } else {
+ str = "";
+ }
+
+ g_debug ("GdmChooserClient: Calling %s", method);
+ message = dbus_message_new_method_call (NULL,
+ CHOOSER_SERVER_DBUS_PATH,
+ CHOOSER_SERVER_DBUS_INTERFACE,
+ method);
+ if (message == NULL) {
+ g_warning ("Couldn't allocate the D-Bus message");
+ return FALSE;
+ }
+
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter,
+ DBUS_TYPE_STRING,
+ &str);
+
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (connection,
+ message,
+ -1,
+ &error);
+
+ dbus_message_unref (message);
+
+ if (dbus_error_is_set (&error)) {
+ g_warning ("%s %s raised: %s\n",
+ method,
+ error.name,
+ error.message);
+ return FALSE;
+ }
+ dbus_message_unref (reply);
+ dbus_connection_flush (connection);
+
+ return TRUE;
+}
+
+
+static gboolean
+send_dbus_void_method (DBusConnection *connection,
+ const char *method)
+{
+ DBusError error;
+ DBusMessage *message;
+ DBusMessage *reply;
+
+ g_debug ("GdmChooserClient: Calling %s", method);
+ message = dbus_message_new_method_call (NULL,
+ CHOOSER_SERVER_DBUS_PATH,
+ CHOOSER_SERVER_DBUS_INTERFACE,
+ method);
+ if (message == NULL) {
+ g_warning ("Couldn't allocate the D-Bus message");
+ return FALSE;
+ }
+
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (connection,
+ message,
+ -1,
+ &error);
+
+ dbus_message_unref (message);
+
+ if (dbus_error_is_set (&error)) {
+ g_warning ("%s %s raised: %s\n",
+ method,
+ error.name,
+ error.message);
+ return FALSE;
+ }
+ dbus_message_unref (reply);
+ dbus_connection_flush (connection);
+
+ return TRUE;
+}
+
+void
+gdm_chooser_client_call_select_hostname (GdmChooserClient *client,
+ const char *text)
+{
+ send_dbus_string_method (client->priv->connection,
+ "SelectHostname",
+ text);
+}
+
+void
+gdm_chooser_client_call_disconnect (GdmChooserClient *client)
+{
+ send_dbus_void_method (client->priv->connection,
+ "Disconnect");
+}
+
+static DBusHandlerResult
+client_dbus_handle_message (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data,
+ dbus_bool_t local_interface)
+{
+
+#if 0
+ g_message ("obj_path=%s interface=%s method=%s destination=%s",
+ dbus_message_get_path (message),
+ dbus_message_get_interface (message),
+ dbus_message_get_member (message),
+ dbus_message_get_destination (message));
+#endif
+
+ g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+ g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+client_dbus_filter_function (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GdmChooserClient *client = GDM_CHOOSER_CLIENT (user_data);
+ const char *path;
+
+ path = dbus_message_get_path (message);
+
+ g_debug ("GdmChooserClient: obj_path=%s interface=%s method=%s",
+ dbus_message_get_path (message),
+ dbus_message_get_interface (message),
+ dbus_message_get_member (message));
+
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")
+ && strcmp (path, DBUS_PATH_LOCAL) == 0) {
+
+ g_message ("Got disconnected from the session message bus");
+
+ dbus_connection_unref (connection);
+ client->priv->connection = NULL;
+
+ } else if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged")) {
+ g_debug ("GdmChooserClient: Name owner changed?");
+ } else {
+ return client_dbus_handle_message (connection, message, user_data, FALSE);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+gboolean
+gdm_chooser_client_start (GdmChooserClient *client,
+ GError **error)
+{
+ gboolean ret;
+ DBusError local_error;
+
+ g_return_val_if_fail (GDM_IS_CHOOSER_CLIENT (client), FALSE);
+
+ ret = FALSE;
+
+ if (client->priv->address == NULL) {
+ g_warning ("GDM_CHOOSER_DBUS_ADDRESS not set");
+ g_set_error (error,
+ GDM_CHOOSER_CLIENT_ERROR,
+ GDM_CHOOSER_CLIENT_ERROR_GENERIC,
+ "GDM_CHOOSER_DBUS_ADDRESS not set");
+ goto out;
+ }
+
+ g_debug ("GdmChooserClient: connecting to address: %s", client->priv->address);
+
+ dbus_error_init (&local_error);
+ client->priv->connection = dbus_connection_open (client->priv->address, &local_error);
+ if (client->priv->connection == NULL) {
+ if (dbus_error_is_set (&local_error)) {
+ g_warning ("error opening connection: %s", local_error.message);
+ g_set_error (error,
+ GDM_CHOOSER_CLIENT_ERROR,
+ GDM_CHOOSER_CLIENT_ERROR_GENERIC,
+ local_error.message);
+ dbus_error_free (&local_error);
+ } else {
+ g_warning ("Unable to open connection");
+ }
+ goto out;
+ }
+
+ dbus_connection_setup_with_g_main (client->priv->connection, NULL);
+ dbus_connection_set_exit_on_disconnect (client->priv->connection, TRUE);
+
+ dbus_connection_add_filter (client->priv->connection,
+ client_dbus_filter_function,
+ client,
+ NULL);
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+void
+gdm_chooser_client_stop (GdmChooserClient *client)
+{
+ g_return_if_fail (GDM_IS_CHOOSER_CLIENT (client));
+
+}
+
+static void
+gdm_chooser_client_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdmChooserClient *self;
+
+ self = GDM_CHOOSER_CLIENT (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdm_chooser_client_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdmChooserClient *self;
+
+ self = GDM_CHOOSER_CLIENT (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gdm_chooser_client_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GdmChooserClient *chooser_client;
+ GdmChooserClientClass *klass;
+
+ klass = GDM_CHOOSER_CLIENT_CLASS (g_type_class_peek (GDM_TYPE_CHOOSER_CLIENT));
+
+ chooser_client = GDM_CHOOSER_CLIENT (G_OBJECT_CLASS (gdm_chooser_client_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (chooser_client);
+}
+
+static void
+gdm_chooser_client_dispose (GObject *object)
+{
+ GdmChooserClient *chooser_client;
+
+ chooser_client = GDM_CHOOSER_CLIENT (object);
+
+ g_debug ("GdmChooserClient: Disposing chooser_client");
+
+ G_OBJECT_CLASS (gdm_chooser_client_parent_class)->dispose (object);
+}
+
+static void
+gdm_chooser_client_class_init (GdmChooserClientClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gdm_chooser_client_get_property;
+ object_class->set_property = gdm_chooser_client_set_property;
+ object_class->constructor = gdm_chooser_client_constructor;
+ object_class->dispose = gdm_chooser_client_dispose;
+ object_class->finalize = gdm_chooser_client_finalize;
+
+ g_type_class_add_private (klass, sizeof (GdmChooserClientPrivate));
+}
+
+static void
+gdm_chooser_client_init (GdmChooserClient *client)
+{
+
+ client->priv = GDM_CHOOSER_CLIENT_GET_PRIVATE (client);
+
+ client->priv->address = g_strdup (g_getenv ("GDM_CHOOSER_DBUS_ADDRESS"));
+}
+
+static void
+gdm_chooser_client_finalize (GObject *object)
+{
+ GdmChooserClient *client;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_CHOOSER_CLIENT (object));
+
+ client = GDM_CHOOSER_CLIENT (object);
+
+ g_return_if_fail (client->priv != NULL);
+
+ g_free (client->priv->address);
+
+ G_OBJECT_CLASS (gdm_chooser_client_parent_class)->finalize (object);
+}
+
+GdmChooserClient *
+gdm_chooser_client_new (void)
+{
+ if (client_object != NULL) {
+ g_object_ref (client_object);
+ } else {
+ client_object = g_object_new (GDM_TYPE_CHOOSER_CLIENT, NULL);
+ g_object_add_weak_pointer (client_object,
+ (gpointer *) &client_object);
+ }
+
+ return GDM_CHOOSER_CLIENT (client_object);
+}
diff --git a/gui/simple-chooser/gdm-chooser-client.h b/gui/simple-chooser/gdm-chooser-client.h
new file mode 100644
index 00000000..540040d1
--- /dev/null
+++ b/gui/simple-chooser/gdm-chooser-client.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GDM_CHOOSER_CLIENT_H
+#define __GDM_CHOOSER_CLIENT_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_CHOOSER_CLIENT (gdm_chooser_client_get_type ())
+#define GDM_CHOOSER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_CHOOSER_CLIENT, GdmChooserClient))
+#define GDM_CHOOSER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_CHOOSER_CLIENT, GdmChooserClientClass))
+#define GDM_IS_CHOOSER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_CHOOSER_CLIENT))
+#define GDM_IS_CHOOSER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_CHOOSER_CLIENT))
+#define GDM_CHOOSER_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_CHOOSER_CLIENT, GdmChooserClientClass))
+
+typedef struct GdmChooserClientPrivate GdmChooserClientPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GdmChooserClientPrivate *priv;
+} GdmChooserClient;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GdmChooserClientClass;
+
+#define GDM_CHOOSER_CLIENT_ERROR (gdm_chooser_client_error_quark ())
+
+typedef enum _GdmChooserClientError {
+ GDM_CHOOSER_CLIENT_ERROR_GENERIC = 0,
+} GdmChooserClientError;
+
+GType gdm_chooser_client_get_type (void);
+GQuark gdm_chooser_client_error_quark (void);
+
+GdmChooserClient * gdm_chooser_client_new (void);
+
+gboolean gdm_chooser_client_start (GdmChooserClient *client,
+ GError **error);
+void gdm_chooser_client_stop (GdmChooserClient *client);
+
+void gdm_chooser_client_call_disconnect (GdmChooserClient *client);
+void gdm_chooser_client_call_select_hostname (GdmChooserClient *client,
+ const char *text);
+
+G_END_DECLS
+
+#endif /* __GDM_CHOOSER_CLIENT_H */
diff --git a/gui/simple-chooser/gdm-chooser-session.c b/gui/simple-chooser/gdm-chooser-session.c
new file mode 100644
index 00000000..47f35790
--- /dev/null
+++ b/gui/simple-chooser/gdm-chooser-session.c
@@ -0,0 +1,318 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+
+#include "gdm-chooser-session.h"
+#include "gdm-chooser-client.h"
+
+#include "gdm-host-chooser-dialog.h"
+
+#define GDM_CHOOSER_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CHOOSER_SESSION, GdmChooserSessionPrivate))
+
+struct GdmChooserSessionPrivate
+{
+ GdmChooserClient *client;
+ GtkWidget *chooser_dialog;
+};
+
+enum {
+ PROP_0,
+};
+
+static void gdm_chooser_session_class_init (GdmChooserSessionClass *klass);
+static void gdm_chooser_session_init (GdmChooserSession *chooser_session);
+static void gdm_chooser_session_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmChooserSession, gdm_chooser_session, G_TYPE_OBJECT)
+
+static gpointer session_object = NULL;
+
+static gboolean
+launch_compiz (GdmChooserSession *session)
+{
+ GError *error;
+ gboolean ret;
+
+ g_debug ("GdmChooserSession: Launching compiz");
+
+ ret = FALSE;
+
+ error = NULL;
+ g_spawn_command_line_async ("gtk-window-decorator --replace", &error);
+ if (error != NULL) {
+ g_warning ("Error starting WM: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ error = NULL;
+ g_spawn_command_line_async ("compiz --replace", &error);
+ if (error != NULL) {
+ g_warning ("Error starting WM: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ ret = TRUE;
+
+ /* FIXME: should try to detect if it actually works */
+
+ out:
+ return ret;
+}
+
+static gboolean
+launch_metacity (GdmChooserSession *session)
+{
+ GError *error;
+ gboolean ret;
+
+ g_debug ("GdmChooserSession: Launching metacity");
+
+ ret = FALSE;
+
+ error = NULL;
+ g_spawn_command_line_async ("metacity --replace", &error);
+ if (error != NULL) {
+ g_warning ("Error starting WM: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+static void
+start_window_manager (GdmChooserSession *session)
+{
+ if (! launch_metacity (session)) {
+ launch_compiz (session);
+ }
+}
+
+static gboolean
+start_settings_daemon (GdmChooserSession *session)
+{
+ GError *error;
+ gboolean ret;
+
+ g_debug ("GdmChooserSession: Launching settings daemon");
+
+ ret = FALSE;
+
+ error = NULL;
+ g_spawn_command_line_async (LIBEXECDIR "/gnome-settings-daemon --gconf-prefix=/apps/gdm/simple-chooser/settings-manager-plugins", &error);
+ if (error != NULL) {
+ g_warning ("Error starting settings daemon: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+static void
+on_dialog_response (GtkDialog *dialog,
+ int response_id,
+ GdmChooserSession *session)
+{
+ char *hostname;
+
+ hostname = NULL;
+ switch (response_id) {
+ case GTK_RESPONSE_OK:
+ hostname = gdm_host_chooser_dialog_get_current_hostname (GDM_HOST_CHOOSER_DIALOG (dialog));
+ case GTK_RESPONSE_NONE:
+ /* delete event */
+ default:
+ break;
+ }
+
+ if (hostname != NULL) {
+ g_debug ("GdmChooserSession: Selected hostname '%s'", hostname);
+ gdm_chooser_client_call_select_hostname (session->priv->client, hostname);
+ g_free (hostname);
+ }
+
+ gdm_chooser_client_call_disconnect (session->priv->client);
+}
+
+gboolean
+gdm_chooser_session_start (GdmChooserSession *session,
+ GError **error)
+{
+ gboolean res;
+
+ g_return_val_if_fail (GDM_IS_CHOOSER_SESSION (session), FALSE);
+
+ res = gdm_chooser_client_start (session->priv->client, error);
+
+ if (res) {
+ start_settings_daemon (session);
+ start_window_manager (session);
+
+ session->priv->chooser_dialog = gdm_host_chooser_dialog_new ();
+ g_signal_connect (session->priv->chooser_dialog,
+ "response",
+ G_CALLBACK (on_dialog_response),
+ session);
+ gtk_widget_show (session->priv->chooser_dialog);
+ }
+
+ return res;
+}
+
+void
+gdm_chooser_session_stop (GdmChooserSession *session)
+{
+ g_return_if_fail (GDM_IS_CHOOSER_SESSION (session));
+
+}
+
+static void
+gdm_chooser_session_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdmChooserSession *self;
+
+ self = GDM_CHOOSER_SESSION (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdm_chooser_session_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdmChooserSession *self;
+
+ self = GDM_CHOOSER_SESSION (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gdm_chooser_session_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GdmChooserSession *chooser_session;
+ GdmChooserSessionClass *klass;
+
+ klass = GDM_CHOOSER_SESSION_CLASS (g_type_class_peek (GDM_TYPE_CHOOSER_SESSION));
+
+ chooser_session = GDM_CHOOSER_SESSION (G_OBJECT_CLASS (gdm_chooser_session_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (chooser_session);
+}
+
+static void
+gdm_chooser_session_dispose (GObject *object)
+{
+ GdmChooserSession *chooser_session;
+
+ chooser_session = GDM_CHOOSER_SESSION (object);
+
+ g_debug ("GdmChooserSession: Disposing chooser_session");
+
+ G_OBJECT_CLASS (gdm_chooser_session_parent_class)->dispose (object);
+}
+
+static void
+gdm_chooser_session_class_init (GdmChooserSessionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gdm_chooser_session_get_property;
+ object_class->set_property = gdm_chooser_session_set_property;
+ object_class->constructor = gdm_chooser_session_constructor;
+ object_class->dispose = gdm_chooser_session_dispose;
+ object_class->finalize = gdm_chooser_session_finalize;
+
+ g_type_class_add_private (klass, sizeof (GdmChooserSessionPrivate));
+}
+
+static void
+gdm_chooser_session_init (GdmChooserSession *session)
+{
+
+ session->priv = GDM_CHOOSER_SESSION_GET_PRIVATE (session);
+
+ session->priv->client = gdm_chooser_client_new ();
+}
+
+static void
+gdm_chooser_session_finalize (GObject *object)
+{
+ GdmChooserSession *chooser_session;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_CHOOSER_SESSION (object));
+
+ chooser_session = GDM_CHOOSER_SESSION (object);
+
+ g_return_if_fail (chooser_session->priv != NULL);
+
+ G_OBJECT_CLASS (gdm_chooser_session_parent_class)->finalize (object);
+}
+
+GdmChooserSession *
+gdm_chooser_session_new (void)
+{
+ if (session_object != NULL) {
+ g_object_ref (session_object);
+ } else {
+ session_object = g_object_new (GDM_TYPE_CHOOSER_SESSION, NULL);
+ g_object_add_weak_pointer (session_object,
+ (gpointer *) &session_object);
+ }
+
+ return GDM_CHOOSER_SESSION (session_object);
+}
diff --git a/gui/simple-chooser/gdm-chooser-session.h b/gui/simple-chooser/gdm-chooser-session.h
new file mode 100644
index 00000000..ebb12021
--- /dev/null
+++ b/gui/simple-chooser/gdm-chooser-session.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __GDM_CHOOSER_SESSION_H
+#define __GDM_CHOOSER_SESSION_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_CHOOSER_SESSION (gdm_chooser_session_get_type ())
+#define GDM_CHOOSER_SESSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_CHOOSER_SESSION, GdmChooserSession))
+#define GDM_CHOOSER_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_CHOOSER_SESSION, GdmChooserSessionClass))
+#define GDM_IS_CHOOSER_SESSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_CHOOSER_SESSION))
+#define GDM_IS_CHOOSER_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_CHOOSER_SESSION))
+#define GDM_CHOOSER_SESSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_CHOOSER_SESSION, GdmChooserSessionClass))
+
+typedef struct GdmChooserSessionPrivate GdmChooserSessionPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GdmChooserSessionPrivate *priv;
+} GdmChooserSession;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GdmChooserSessionClass;
+
+GType gdm_chooser_session_get_type (void);
+
+GdmChooserSession * gdm_chooser_session_new (void);
+
+gboolean gdm_chooser_session_start (GdmChooserSession *session,
+ GError **error);
+void gdm_chooser_session_stop (GdmChooserSession *session);
+
+G_END_DECLS
+
+#endif /* __GDM_CHOOSER_SESSION_H */
diff --git a/gui/simple-chooser/test-host-chooser.c b/gui/simple-chooser/test-host-chooser.c
new file mode 100644
index 00000000..31e94005
--- /dev/null
+++ b/gui/simple-chooser/test-host-chooser.c
@@ -0,0 +1,263 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <libintl.h>
+#include <locale.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <gconf/gconf-client.h>
+
+#include "gdm-common.h"
+#include "gdm-log.h"
+#include "gdm-settings-client.h"
+#include "gdm-settings-keys.h"
+
+#include "gdm-host-chooser-dialog.h"
+
+#define ACCESSIBILITY_KEY "/desktop/gnome/interface/accessibility"
+
+static Atom AT_SPI_IOR;
+
+
+static gboolean
+assistive_registry_launch (void)
+{
+ GPid pid;
+ GError *error;
+ const char *command;
+ char **argv;
+ gboolean res;
+
+ command = AT_SPI_REGISTRYD_DIR "/at-spi-registryd";
+
+ argv = NULL;
+ error = NULL;
+ res = g_shell_parse_argv (command, NULL, &argv, &error);
+ if (! res) {
+ g_warning ("Unable to parse command: %s", error->message);
+ return FALSE;
+ }
+
+ error = NULL;
+ res = g_spawn_async (NULL,
+ argv,
+ NULL,
+ G_SPAWN_SEARCH_PATH
+ | G_SPAWN_STDOUT_TO_DEV_NULL
+ | G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL,
+ NULL,
+ &pid,
+ &error);
+ g_strfreev (argv);
+
+ if (! res) {
+ g_warning ("Unable to run command %s: %s", command, error->message);
+ return FALSE;
+ }
+
+ if (kill (pid, 0) < 0) {
+ g_warning ("at-spi-registryd not running");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GdkFilterReturn
+filter_watch (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ XEvent *xev = (XEvent *)xevent;
+
+ if (xev->xany.type == PropertyNotify
+ && xev->xproperty.atom == AT_SPI_IOR) {
+ gtk_main_quit ();
+
+ return GDK_FILTER_REMOVE;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static gboolean
+filter_timeout (gpointer data)
+{
+ g_warning ("The accessibility registry was not found.");
+
+ gtk_main_quit ();
+
+ return FALSE;
+}
+
+static void
+assistive_registry_start (void)
+{
+ GdkWindow *root;
+ guint tid;
+
+ root = gdk_get_default_root_window ();
+
+ if ( ! AT_SPI_IOR) {
+ AT_SPI_IOR = XInternAtom (GDK_DISPLAY (), "AT_SPI_IOR", False);
+ }
+
+ gdk_window_set_events (root, GDK_PROPERTY_CHANGE_MASK);
+
+ if ( ! assistive_registry_launch ()) {
+ g_warning ("The accessibility registry could not be started.");
+ return;
+ }
+
+ gdk_window_add_filter (root, filter_watch, NULL);
+ tid = g_timeout_add_seconds (5, filter_timeout, NULL);
+
+ gtk_main ();
+
+ gdk_window_remove_filter (root, filter_watch, NULL);
+ g_source_remove (tid);
+}
+
+static void
+at_set_gtk_modules (void)
+{
+ GSList *modules_list;
+ GSList *l;
+ const char *old;
+ char **modules;
+ gboolean found_gail;
+ gboolean found_atk_bridge;
+ int n;
+
+ n = 0;
+ modules_list = NULL;
+ found_gail = FALSE;
+ found_atk_bridge = FALSE;
+
+ if ((old = g_getenv ("GTK_MODULES")) != NULL) {
+ modules = g_strsplit (old, ":", -1);
+ for (n = 0; modules[n]; n++) {
+ if (!strcmp (modules[n], "gail")) {
+ found_gail = TRUE;
+ } else if (!strcmp (modules[n], "atk-bridge")) {
+ found_atk_bridge = TRUE;
+ }
+
+ modules_list = g_slist_prepend (modules_list, modules[n]);
+ modules[n] = NULL;
+ }
+ g_free (modules);
+ }
+
+ if (!found_gail) {
+ modules_list = g_slist_prepend (modules_list, "gail");
+ ++n;
+ }
+
+ if (!found_atk_bridge) {
+ modules_list = g_slist_prepend (modules_list, "atk-bridge");
+ ++n;
+ }
+
+ modules = g_new (char *, n + 1);
+ modules[n--] = NULL;
+ for (l = modules_list; l; l = l->next) {
+ modules[n--] = g_strdup (l->data);
+ }
+
+ g_setenv ("GTK_MODULES", g_strjoinv (":", modules), TRUE);
+ g_strfreev (modules);
+ g_slist_free (modules_list);
+}
+
+static void
+load_a11y (void)
+{
+ const char *env_a_t_support;
+ gboolean a_t_support;
+ GConfClient *gconf_client;
+
+ gconf_client = gconf_client_get_default ();
+
+ env_a_t_support = g_getenv ("GNOME_ACCESSIBILITY");
+ if (env_a_t_support) {
+ a_t_support = atoi (env_a_t_support);
+ } else {
+ a_t_support = gconf_client_get_bool (gconf_client, ACCESSIBILITY_KEY, NULL);
+ }
+
+ if (a_t_support) {
+ assistive_registry_start ();
+ at_set_gtk_modules ();
+ }
+
+ g_object_unref (gconf_client);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *chooser;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ setlocale (LC_ALL, "");
+
+ gdm_set_fatal_warnings_if_unstable ();
+
+ g_type_init ();
+
+ gdm_log_init ();
+ gdm_log_set_debug (TRUE);
+
+ g_debug ("Chooser for display %s xauthority:%s",
+ g_getenv ("DISPLAY"),
+ g_getenv ("XAUTHORITY"));
+
+ gdk_init (&argc, &argv);
+
+ load_a11y ();
+
+ gtk_init (&argc, &argv);
+
+ chooser = gdm_host_chooser_dialog_new ();
+ if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_OK) {
+ char *hostname;
+
+ hostname = gdm_host_chooser_dialog_get_current_hostname (GDM_HOST_CHOOSER_DIALOG (chooser));
+ g_print ("hostname: %s\n", hostname);
+ g_free (hostname);
+ }
+
+ gtk_widget_destroy (chooser);
+
+ return 0;
+}
diff --git a/gui/simple-greeter/greeter-main.c b/gui/simple-greeter/greeter-main.c
index dc9891e9..d2ffbe56 100644
--- a/gui/simple-greeter/greeter-main.c
+++ b/gui/simple-greeter/greeter-main.c
@@ -194,15 +194,36 @@ at_set_gtk_modules (void)
g_slist_free (modules_list);
}
+static void
+load_a11y (void)
+{
+ const char *env_a_t_support;
+ gboolean a_t_support;
+ GConfClient *gconf_client;
+
+ gconf_client = gconf_client_get_default ();
+
+ env_a_t_support = g_getenv ("GNOME_ACCESSIBILITY");
+ if (env_a_t_support) {
+ a_t_support = atoi (env_a_t_support);
+ } else {
+ a_t_support = gconf_client_get_bool (gconf_client, ACCESSIBILITY_KEY, NULL);
+ }
+
+ if (a_t_support) {
+ assistive_registry_start ();
+ at_set_gtk_modules ();
+ }
+
+ g_object_unref (gconf_client);
+}
+
int
main (int argc, char *argv[])
{
GError *error;
GdmGreeterSession *session;
gboolean res;
- const char *env_a_t_support;
- gboolean a_t_support;
- GConfClient *gconf_client;
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
@@ -231,19 +252,7 @@ main (int argc, char *argv[])
gdk_init (&argc, &argv);
- gconf_client = gconf_client_get_default ();
-
- env_a_t_support = g_getenv ("GNOME_ACCESSIBILITY");
- if (env_a_t_support) {
- a_t_support = atoi (env_a_t_support);
- } else {
- a_t_support = gconf_client_get_bool (gconf_client, ACCESSIBILITY_KEY, NULL);
- }
-
- if (a_t_support) {
- assistive_registry_start ();
- at_set_gtk_modules ();
- }
+ load_a11y ();
gtk_init (&argc, &argv);
@@ -253,6 +262,7 @@ main (int argc, char *argv[])
exit (1);
}
+ error = NULL;
res = gdm_greeter_session_start (session, &error);
if (! res) {
g_warning ("Unable to start greeter session: %s", error->message);
diff --git a/po/ChangeLog b/po/ChangeLog
index c1d2def7..d8f2e7ac 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,3 +1,7 @@
+2008-01-30 William Jon McCann <mccann@jhu.edu>
+
+ * POTFILES.in: Add missing files.
+
2007-01-29 Yair Hershkovitz <yairhr@gmail.com>
* he.po: Updated Hebrew translation by Mark Krapviner.
@@ -73,8 +77,6 @@
2007-12-21 William Jon McCann <mccann@jhu.edu>
- reviewed by: <delete if not using a buddy>
-
* POTFILES.in:
2007-12-20 Kjartan Maraas <kmaraas@gnome.org>
@@ -138,8 +140,6 @@
2007-10-29 William Jon McCann <mccann@jhu.edu>
- reviewed by: <delete if not using a buddy>
-
* POTFILES.in:
2007-10-29 Kjartan Maraas <kmaraas@gnome.org>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c2fa6c7b..297808cd 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -15,6 +15,7 @@ common/test-log.c
common/test-settings-client.c
common/test-settings-server.c
daemon/factory-slave-main.c
+daemon/gdm-chooser-session.c
daemon/gdm-display.c
daemon/gdm-display-access-file.c
daemon/gdm-display-store.c
@@ -43,6 +44,7 @@ daemon/product-slave-main.c
daemon/session-worker-main.c
daemon/simple-slave-main.c
daemon/test-session.c
+daemon/xdmcp-chooser-slave-main.c
data/gdm.schemas.in.in
gui/simple-chooser/gdm-host-chooser-widget.c
gui/simple-greeter/gdm-chooser-widget.c