summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Jon McCann <mccann@src.gnome.org>2007-06-08 01:18:08 +0000
committerWilliam Jon McCann <mccann@src.gnome.org>2007-06-08 01:18:08 +0000
commitc4adefa73913fb5d448c6dd74dc58eb3a67c7376 (patch)
treedda3f1a3696ee8ea5917a751277ad0dbca008de6
parentfd6e91f3fee22b0c9389ffe91265f4099e688501 (diff)
downloadgdm-c4adefa73913fb5d448c6dd74dc58eb3a67c7376.tar.gz
Make the session object talk to the greeter!
svn path=/branches/mccann-gobject/; revision=4973
-rw-r--r--common/gdm-settings-client.c4
-rw-r--r--common/gdm-settings-keys.h4
-rw-r--r--daemon/Makefile.am4
-rw-r--r--daemon/gdm-greeter-proxy.c1130
-rw-r--r--daemon/gdm-greeter-proxy.h71
-rw-r--r--daemon/gdm-greeter.c1331
-rw-r--r--daemon/gdm-greeter.h57
-rw-r--r--daemon/gdm-session.c3
-rw-r--r--daemon/gdm-session.h34
-rw-r--r--daemon/gdm-slave.c213
-rw-r--r--daemon/gdm-socket-protocol.h3
-rw-r--r--daemon/test-session.c4
-rw-r--r--gui/Makefile.am21
-rw-r--r--gui/gdm-greeter.c240
-rw-r--r--gui/gdm-greeter.h31
-rw-r--r--gui/gdm-greeter.xml5
-rw-r--r--gui/greeter/Makefile.am6
-rw-r--r--gui/greeter/gdm-themed-greeter.c1087
-rw-r--r--gui/greeter/gdm-themed-greeter.h58
-rw-r--r--gui/greeter/greeter.c1509
-rw-r--r--gui/greeter/greeter_item_customlist.c7
-rw-r--r--gui/greeter/greeter_item_pam.c17
-rw-r--r--gui/greeter/greeter_item_pam.h3
-rw-r--r--gui/greeter/greeter_item_timed.c3
-rw-r--r--gui/greeter/greeter_item_ulist.c7
-rw-r--r--gui/greeter/greeter_system.c11
-rw-r--r--utils/Makefile.am11
-rw-r--r--utils/gdmaskpass.c58
28 files changed, 2960 insertions, 2972 deletions
diff --git a/common/gdm-settings-client.c b/common/gdm-settings-client.c
index b5cef069..aaeedf9a 100644
--- a/common/gdm-settings-client.c
+++ b/common/gdm-settings-client.c
@@ -79,10 +79,10 @@ get_value (const char *key,
G_TYPE_INVALID);
if (! res) {
if (error != NULL) {
- g_debug ("Failed to get value for %s: %s", key, error->message);
+ /*g_debug ("Failed to get value for %s: %s", key, error->message);*/
g_error_free (error);
} else {
- g_debug ("Failed to get value for %s", key);
+ /*g_debug ("Failed to get value for %s", key);*/
}
return FALSE;
diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h
index a349564a..576c6b3d 100644
--- a/common/gdm-settings-keys.h
+++ b/common/gdm-settings-keys.h
@@ -25,6 +25,10 @@
G_BEGIN_DECLS
+/* List delimiter for config file lists */
+#define GDM_DELIMITER_MODULES ":"
+#define GDM_DELIMITER_THEMES "/:"
+
#define GDM_KEY_CHOOSER "daemon/Chooser"
#define GDM_KEY_AUTOMATIC_LOGIN_ENABLE "daemon/AutomaticLoginEnable"
#define GDM_KEY_AUTOMATIC_LOGIN "daemon/AutomaticLogin"
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 3b573889..7a298075 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -69,8 +69,8 @@ libexec_PROGRAMS = \
gdm_slave_SOURCES = \
slave-main.c \
- gdm-greeter.c \
- gdm-greeter.h \
+ gdm-greeter-proxy.c \
+ gdm-greeter-proxy.h \
gdm-server.c \
gdm-server.h \
gdm-session.c \
diff --git a/daemon/gdm-greeter-proxy.c b/daemon/gdm-greeter-proxy.c
new file mode 100644
index 00000000..1467e240
--- /dev/null
+++ b/daemon/gdm-greeter-proxy.c
@@ -0,0 +1,1130 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; 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 <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 <X11/Xlib.h> /* for Display */
+
+#include "gdm-common.h"
+#include "filecheck.h"
+
+#include "gdm-greeter-proxy.h"
+
+#define GDM_GREETER_SERVER_DBUS_PATH "/org/gnome/DisplayManager/GreeterServer"
+#define GDM_GREETER_SERVER_DBUS_INTERFACE "org.gnome.DisplayManager.GreeterServer"
+
+
+extern char **environ;
+
+#define GDM_GREETER_PROXY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER_PROXY, GdmGreeterProxyPrivate))
+
+struct GdmGreeterProxyPrivate
+{
+ char *command;
+ GPid pid;
+
+ char *user_name;
+ char *group_name;
+
+ char *x11_display_name;
+ char *x11_authority_file;
+
+ int user_max_filesize;
+
+ gboolean interrupted;
+ gboolean always_restart_greeter;
+
+ guint child_watch_id;
+
+ DBusServer *server;
+ char *server_address;
+ DBusConnection *greeter_connection;
+};
+
+enum {
+ PROP_0,
+ PROP_X11_DISPLAY_NAME,
+ PROP_X11_AUTHORITY_FILE,
+ PROP_USER_NAME,
+ PROP_GROUP_NAME,
+};
+
+enum {
+ ANSWER,
+ STARTED,
+ STOPPED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void gdm_greeter_proxy_class_init (GdmGreeterProxyClass *klass);
+static void gdm_greeter_proxy_init (GdmGreeterProxy *greeter_proxy);
+static void gdm_greeter_proxy_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmGreeterProxy, gdm_greeter_proxy, G_TYPE_OBJECT)
+
+static gboolean
+send_dbus_message (DBusConnection *connection,
+ DBusMessage *message)
+{
+ gboolean is_connected;
+ gboolean sent;
+
+ g_return_val_if_fail (message != NULL, FALSE);
+
+ if (connection == NULL) {
+ g_debug ("There is no valid connection");
+ return FALSE;
+ }
+
+ is_connected = dbus_connection_get_is_connected (connection);
+ if (! is_connected) {
+ g_warning ("Not connected!");
+ return FALSE;
+ }
+
+ sent = dbus_connection_send (connection, message, NULL);
+
+ return sent;
+}
+
+static void
+send_dbus_string_signal (GdmGreeterProxy *greeter_proxy,
+ const char *name,
+ const char *text)
+{
+ DBusMessage *message;
+ DBusMessageIter iter;
+
+ g_return_if_fail (greeter_proxy != NULL);
+
+ message = dbus_message_new_signal (GDM_GREETER_SERVER_DBUS_PATH,
+ GDM_GREETER_SERVER_DBUS_INTERFACE,
+ name);
+
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &text);
+
+ if (! send_dbus_message (greeter_proxy->priv->greeter_connection, message)) {
+ g_debug ("Could not send %s signal", name);
+ }
+
+ dbus_message_unref (message);
+}
+
+gboolean
+gdm_greeter_proxy_info_query (GdmGreeterProxy *greeter_proxy,
+ const char *text)
+{
+ send_dbus_string_signal (greeter_proxy, "InfoQuery", text);
+
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_proxy_secret_info_query (GdmGreeterProxy *greeter_proxy,
+ const char *text)
+{
+ send_dbus_string_signal (greeter_proxy, "SecretInfoQuery", text);
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_proxy_info (GdmGreeterProxy *greeter_proxy,
+ const char *text)
+{
+ send_dbus_string_signal (greeter_proxy, "Info", text);
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_proxy_problem (GdmGreeterProxy *greeter_proxy,
+ const char *text)
+{
+ send_dbus_string_signal (greeter_proxy, "Problem", text);
+ return TRUE;
+}
+
+static void
+change_user (GdmGreeterProxy *greeter_proxy)
+
+{
+ struct passwd *pwent;
+ struct group *grent;
+
+ if (greeter_proxy->priv->user_name == NULL) {
+ return;
+ }
+
+ pwent = getpwnam (greeter_proxy->priv->user_name);
+ if (pwent == NULL) {
+ g_warning (_("GreeterProxy was to be spawned by user %s but that user doesn't exist"),
+ greeter_proxy->priv->user_name);
+ _exit (1);
+ }
+
+ grent = getgrnam (greeter_proxy->priv->group_name);
+ if (grent == NULL) {
+ g_warning (_("GreeterProxy was to be spawned by group %s but that user doesn't exist"),
+ greeter_proxy->priv->group_name);
+ _exit (1);
+ }
+
+ g_debug ("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);
+ }
+}
+
+static void
+greeter_proxy_child_setup (GdmGreeterProxy *greeter_proxy)
+{
+ change_user (greeter_proxy);
+}
+
+static void
+listify_hash (const char *key,
+ const char *value,
+ GPtrArray *env)
+{
+ char *str;
+ str = g_strdup_printf ("%s=%s", key, value);
+ g_ptr_array_add (env, str);
+}
+
+static GPtrArray *
+get_greeter_environment (GdmGreeterProxy *greeter_proxy)
+{
+ GPtrArray *env;
+ char **l;
+ 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 0
+ for (l = environ; *l != NULL; l++) {
+ char **str;
+ str = g_strsplit (*l, "=", 2);
+ g_hash_table_insert (hash, str[0], str[1]);
+ }
+#endif
+
+ g_hash_table_insert (hash, g_strdup ("GDM_GREETER_DBUS_ADDRESS"), g_strdup (greeter_proxy->priv->server_address));
+
+ g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (greeter_proxy->priv->x11_authority_file));
+ g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (greeter_proxy->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 (greeter_proxy->priv->user_name));
+ g_hash_table_insert (hash, g_strdup ("USER"), g_strdup (greeter_proxy->priv->user_name));
+ g_hash_table_insert (hash, g_strdup ("USERNAME"), g_strdup (greeter_proxy->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 (greeter_proxy->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));
+ }
+
+#if 0
+ defaultpath = gdm_daemon_config_get_value_string (GDM_KEY_PATH);
+ if (ve_string_empty (g_getenv ("PATH"))) {
+ g_setenv ("PATH", defaultpath, TRUE);
+ } else if ( ! ve_string_empty (defaultpath)) {
+ gchar *temp_string = g_strconcat (g_getenv ("PATH"),
+ ":", defaultpath, NULL);
+ g_setenv ("PATH", temp_string, TRUE);
+ g_free (temp_string);
+ }
+#endif
+
+ g_hash_table_insert (hash, g_strdup ("RUNNING_UNDER_GDM"), g_strdup ("true"));
+
+#if 0
+ if ( ! ve_string_empty (d->theme_name))
+ g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
+ if (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG_GESTURES)) {
+ g_setenv ("G_DEBUG_GESTURES", "true", TRUE);
+ }
+#endif
+
+#if 0
+ if (SERVER_IS_FLEXI (d)) {
+ g_setenv ("GDM_FLEXI_SERVER", "yes", TRUE);
+ } else {
+ g_unsetenv ("GDM_FLEXI_SERVER");
+ }
+#endif
+
+
+ g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
+ g_hash_table_destroy (hash);
+
+ g_ptr_array_add (env, NULL);
+
+ return env;
+}
+
+static void
+gdm_slave_whack_temp_auth_file (GdmGreeterProxy *greeter_proxy)
+{
+#if 0
+ uid_t old;
+
+ old = geteuid ();
+ if (old != 0)
+ seteuid (0);
+ if (d->parent_temp_auth_file != NULL) {
+ VE_IGNORE_EINTR (g_unlink (d->parent_temp_auth_file));
+ }
+ g_free (d->parent_temp_auth_file);
+ d->parent_temp_auth_file = NULL;
+ if (old != 0)
+ seteuid (old);
+#endif
+}
+
+
+static void
+create_temp_auth_file (GdmGreeterProxy *greeter_proxy)
+{
+#if 0
+ if (d->type == TYPE_FLEXI_XNEST &&
+ d->parent_auth_file != NULL) {
+ if (d->parent_temp_auth_file != NULL) {
+ VE_IGNORE_EINTR (g_unlink (d->parent_temp_auth_file));
+ }
+ g_free (d->parent_temp_auth_file);
+ d->parent_temp_auth_file =
+ copy_auth_file (d->server_uid,
+ gdm_daemon_config_get_gdmuid (),
+ d->parent_auth_file);
+ }
+#endif
+}
+
+static void
+gdm_slave_quick_exit (GdmGreeterProxy *greeter_proxy)
+{
+ /* FIXME */
+ _exit (1);
+}
+
+static void
+greeter_proxy_child_watch (GPid pid,
+ int status,
+ GdmGreeterProxy *greeter_proxy)
+{
+ g_debug ("child (pid:%d) done (%s:%d)",
+ (int) pid,
+ WIFEXITED (status) ? "status"
+ : WIFSIGNALED (status) ? "signal"
+ : "unknown",
+ WIFEXITED (status) ? WEXITSTATUS (status)
+ : WIFSIGNALED (status) ? WTERMSIG (status)
+ : -1);
+
+ g_spawn_close_pid (greeter_proxy->priv->pid);
+ greeter_proxy->priv->pid = -1;
+}
+
+/* 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-greeter-%s", tmp);
+#else
+ path = g_strdup ("unix:tmpdir=/tmp/gdm-greeter");
+#endif
+
+ return path;
+}
+
+static DBusHandlerResult
+greeter_handle_child_message (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GdmGreeterProxy *greeter_proxy = GDM_GREETER_PROXY (user_data);
+
+ if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "AnswerQuery")) {
+ 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 ("AnswerQuery: %s", text);
+
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (connection, reply, NULL);
+ dbus_message_unref (reply);
+
+ g_signal_emit (greeter_proxy, signals [ANSWER], 0, text);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult
+do_introspect (DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+ GString *xml;
+ char *xml_string;
+
+ g_debug ("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.GreeterServer\">\n"
+ " <method name=\"AnswerQuery\">\n"
+ " <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
+ " </method>\n"
+ " <signal name=\"Info\">\n"
+ " <arg name=\"text\" type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"Problem\">\n"
+ " <arg name=\"text\" type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"InfoQuery\">\n"
+ " <arg name=\"text\" type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"SecretInfoQuery\">\n"
+ " <arg name=\"text\" type=\"s\"/>\n"
+ " </signal>\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
+greeter_server_message_handler (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GdmGreeterProxy *greeter_proxy = GDM_GREETER_PROXY (user_data);
+
+ g_debug ("greeter_server_message_handler: destination=%s obj_path=%s interface=%s method=%s",
+ dbus_message_get_destination (message),
+ dbus_message_get_path (message),
+ dbus_message_get_interface (message),
+ dbus_message_get_member (message));
+
+
+ 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 greeter_handle_child_message (connection, message, user_data);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+greeter_server_unregister_handler (DBusConnection *connection,
+ void *user_data)
+{
+ GdmGreeterProxy *greeter_proxy = GDM_GREETER_PROXY (user_data);
+
+ g_debug ("greeter_server_unregister_handler");
+}
+
+static DBusHandlerResult
+connection_filter_function (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GdmGreeterProxy *greeter_proxy = GDM_GREETER_PROXY (user_data);
+ const char *path;
+
+ path = dbus_message_get_path (message);
+
+ g_debug ("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_debug ("Disconnected");
+
+ dbus_connection_unref (connection);
+ greeter_proxy->priv->greeter_connection = NULL;
+ } else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
+
+
+ } else {
+ return greeter_server_message_handler (connection, message, user_data);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static dbus_bool_t
+allow_user_function (DBusConnection *connection,
+ unsigned long uid,
+ void *data)
+{
+ GdmGreeterProxy *greeter_proxy = GDM_GREETER_PROXY (data);
+ struct passwd *pwent;
+
+ if (greeter_proxy->priv->user_name == NULL) {
+ return FALSE;
+ }
+
+ pwent = getpwnam (greeter_proxy->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)
+{
+ GdmGreeterProxy *greeter_proxy = GDM_GREETER_PROXY (user_data);
+
+ g_debug ("Handing new connection");
+
+ if (greeter_proxy->priv->greeter_connection == NULL) {
+ DBusObjectPathVTable vtable = { &greeter_server_unregister_handler,
+ &greeter_server_message_handler,
+ NULL, NULL, NULL, NULL
+ };
+
+ greeter_proxy->priv->greeter_connection = new_connection;
+ dbus_connection_ref (new_connection);
+ dbus_connection_setup_with_g_main (new_connection, NULL);
+
+ g_debug ("greeter connection is %p", new_connection);
+#if 1
+ dbus_connection_add_filter (new_connection,
+ connection_filter_function,
+ greeter_proxy,
+ NULL);
+#endif
+ dbus_connection_set_unix_user_function (new_connection,
+ allow_user_function,
+ greeter_proxy,
+ NULL);
+
+ dbus_connection_register_object_path (new_connection,
+ GDM_GREETER_SERVER_DBUS_PATH,
+ &vtable,
+ greeter_proxy);
+
+ g_signal_emit (greeter_proxy, signals[STARTED], 0);
+
+ }
+}
+
+static gboolean
+create_dbus_server (GdmGreeterProxy *greeter_proxy)
+{
+ DBusServer *server;
+ DBusError error;
+ gboolean ret;
+ char *address;
+ char *server_address;
+ const char *auth_mechanisms[] = {"EXTERNAL", NULL};
+
+ ret = FALSE;
+
+ g_debug ("Creating D-Bus server for greeter");
+
+ address = generate_address ();
+
+ dbus_error_init (&error);
+ server = dbus_server_listen (address, &error);
+ g_free (address);
+
+ if (server == NULL) {
+ g_warning ("Cannot create D-BUS server for the greeter: %s", error.message);
+ goto out;
+ }
+
+ dbus_server_setup_with_g_main (server, NULL);
+ dbus_server_set_auth_mechanisms (server, auth_mechanisms);
+ dbus_server_set_new_connection_function (server,
+ handle_connection,
+ greeter_proxy,
+ NULL);
+ ret = TRUE;
+
+ g_free (greeter_proxy->priv->server_address);
+ greeter_proxy->priv->server_address = dbus_server_get_address (server);
+
+ g_debug ("D-Bus server listening on %s", greeter_proxy->priv->server_address);
+
+ out:
+
+ return ret;
+}
+
+static gboolean
+gdm_greeter_proxy_spawn (GdmGreeterProxy *greeter_proxy)
+{
+ gchar **argv;
+ GError *error;
+ GPtrArray *env;
+ gboolean ret;
+
+ ret = FALSE;
+
+ create_temp_auth_file (greeter_proxy);
+
+ g_debug ("Running greeter_proxy process: %s", greeter_proxy->priv->command);
+
+ argv = NULL;
+ if (! g_shell_parse_argv (greeter_proxy->priv->command, NULL, &argv, &error)) {
+ g_warning ("Could not parse command: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ create_dbus_server (greeter_proxy);
+
+ env = get_greeter_environment (greeter_proxy);
+
+ error = NULL;
+ ret = g_spawn_async_with_pipes (NULL,
+ argv,
+ (char **)env->pdata,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+ (GSpawnChildSetupFunc)greeter_proxy_child_setup,
+ greeter_proxy,
+ &greeter_proxy->priv->pid,
+ NULL,
+ NULL,
+ NULL,
+ &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",
+ greeter_proxy->priv->command,
+ error->message);
+ g_error_free (error);
+ } else {
+ g_debug ("gdm_slave_greeter_proxy: GreeterProxy on pid %d", (int)greeter_proxy->priv->pid);
+ }
+
+ greeter_proxy->priv->child_watch_id = g_child_watch_add (greeter_proxy->priv->pid,
+ (GChildWatchFunc)greeter_proxy_child_watch,
+ greeter_proxy);
+
+ g_strfreev (argv);
+ out:
+
+ return ret;
+}
+
+/**
+ * gdm_greeter_proxy_start:
+ * @disp: Pointer to a GdmDisplay structure
+ *
+ * Starts a local X greeter_proxy. Handles retries and fatal errors properly.
+ */
+
+gboolean
+gdm_greeter_proxy_start (GdmGreeterProxy *greeter_proxy)
+{
+ gboolean res;
+
+ g_debug ("Starting greeter...");
+
+ res = gdm_greeter_proxy_spawn (greeter_proxy);
+
+ if (res) {
+
+ }
+
+
+ return res;
+}
+
+static int
+signal_pid (int pid,
+ int signal)
+{
+ int status = -1;
+
+ /* perhaps block sigchld */
+
+ status = kill (pid, signal);
+
+ if (status < 0) {
+ if (errno == ESRCH) {
+ g_warning ("Child process %lu was already dead.",
+ (unsigned long) pid);
+ } else {
+ g_warning ("Couldn't kill child process %lu: %s",
+ (unsigned long) pid,
+ g_strerror (errno));
+ }
+ }
+
+ /* perhaps unblock sigchld */
+
+ return status;
+}
+
+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 ("waitpid () should not fail");
+ }
+ }
+
+ return status;
+}
+
+static void
+greeter_proxy_died (GdmGreeterProxy *greeter_proxy)
+{
+ int exit_status;
+
+ g_debug ("Waiting on process %d", greeter_proxy->priv->pid);
+ exit_status = wait_on_child (greeter_proxy->priv->pid);
+
+ if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
+ g_debug ("Wait on child process failed");
+ } else {
+ /* exited normally */
+ }
+
+ g_spawn_close_pid (greeter_proxy->priv->pid);
+ greeter_proxy->priv->pid = -1;
+
+ g_debug ("GreeterProxy died");
+}
+
+gboolean
+gdm_greeter_proxy_stop (GdmGreeterProxy *greeter_proxy)
+{
+
+ if (greeter_proxy->priv->pid <= 1) {
+ return TRUE;
+ }
+
+ /* remove watch source before we can wait on child */
+ if (greeter_proxy->priv->child_watch_id > 0) {
+ g_source_remove (greeter_proxy->priv->child_watch_id);
+ greeter_proxy->priv->child_watch_id = 0;
+ }
+
+ g_debug ("Stopping greeter_proxy");
+
+ signal_pid (greeter_proxy->priv->pid, SIGTERM);
+ greeter_proxy_died (greeter_proxy);
+
+ return TRUE;
+}
+
+
+static void
+_gdm_greeter_proxy_set_x11_display_name (GdmGreeterProxy *greeter_proxy,
+ const char *name)
+{
+ g_free (greeter_proxy->priv->x11_display_name);
+ greeter_proxy->priv->x11_display_name = g_strdup (name);
+}
+
+static void
+_gdm_greeter_proxy_set_x11_authority_file (GdmGreeterProxy *greeter_proxy,
+ const char *file)
+{
+ g_free (greeter_proxy->priv->x11_authority_file);
+ greeter_proxy->priv->x11_authority_file = g_strdup (file);
+}
+
+static void
+_gdm_greeter_proxy_set_user_name (GdmGreeterProxy *greeter_proxy,
+ const char *name)
+{
+ g_free (greeter_proxy->priv->user_name);
+ greeter_proxy->priv->user_name = g_strdup (name);
+}
+
+static void
+_gdm_greeter_proxy_set_group_name (GdmGreeterProxy *greeter_proxy,
+ const char *name)
+{
+ g_free (greeter_proxy->priv->group_name);
+ greeter_proxy->priv->group_name = g_strdup (name);
+}
+
+static void
+gdm_greeter_proxy_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdmGreeterProxy *self;
+
+ self = GDM_GREETER_PROXY (object);
+
+ switch (prop_id) {
+ case PROP_X11_DISPLAY_NAME:
+ _gdm_greeter_proxy_set_x11_display_name (self, g_value_get_string (value));
+ break;
+ case PROP_X11_AUTHORITY_FILE:
+ _gdm_greeter_proxy_set_x11_authority_file (self, g_value_get_string (value));
+ break;
+ case PROP_USER_NAME:
+ _gdm_greeter_proxy_set_user_name (self, g_value_get_string (value));
+ break;
+ case PROP_GROUP_NAME:
+ _gdm_greeter_proxy_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_greeter_proxy_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdmGreeterProxy *self;
+
+ self = GDM_GREETER_PROXY (object);
+
+ switch (prop_id) {
+ case PROP_X11_DISPLAY_NAME:
+ g_value_set_string (value, self->priv->x11_display_name);
+ 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;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+gdm_greeter_proxy_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GdmGreeterProxy *greeter_proxy;
+ GdmGreeterProxyClass *klass;
+
+ klass = GDM_GREETER_PROXY_CLASS (g_type_class_peek (GDM_TYPE_GREETER_PROXY));
+
+ greeter_proxy = GDM_GREETER_PROXY (G_OBJECT_CLASS (gdm_greeter_proxy_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (greeter_proxy);
+}
+
+static void
+gdm_greeter_proxy_class_init (GdmGreeterProxyClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gdm_greeter_proxy_get_property;
+ object_class->set_property = gdm_greeter_proxy_set_property;
+ object_class->constructor = gdm_greeter_proxy_constructor;
+ object_class->finalize = gdm_greeter_proxy_finalize;
+
+ g_type_class_add_private (klass, sizeof (GdmGreeterProxyPrivate));
+
+ 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_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));
+ signals [ANSWER] =
+ g_signal_new ("answer",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmGreeterProxyClass, answer),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+ signals [STARTED] =
+ g_signal_new ("started",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmGreeterProxyClass, 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 (GdmGreeterProxyClass, stopped),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+static void
+gdm_greeter_proxy_init (GdmGreeterProxy *greeter_proxy)
+{
+
+ greeter_proxy->priv = GDM_GREETER_PROXY_GET_PRIVATE (greeter_proxy);
+
+ greeter_proxy->priv->pid = -1;
+
+ greeter_proxy->priv->command = g_strdup (LIBEXECDIR "/gdmgreeter");
+ greeter_proxy->priv->user_max_filesize = 65536;
+}
+
+static void
+gdm_greeter_proxy_finalize (GObject *object)
+{
+ GdmGreeterProxy *greeter_proxy;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_GREETER_PROXY (object));
+
+ greeter_proxy = GDM_GREETER_PROXY (object);
+
+ g_return_if_fail (greeter_proxy->priv != NULL);
+
+ gdm_greeter_proxy_stop (greeter_proxy);
+
+ G_OBJECT_CLASS (gdm_greeter_proxy_parent_class)->finalize (object);
+}
+
+GdmGreeterProxy *
+gdm_greeter_proxy_new (const char *display_name)
+{
+ GObject *object;
+
+ object = g_object_new (GDM_TYPE_GREETER_PROXY,
+ "x11-display-name", display_name,
+ NULL);
+
+ return GDM_GREETER_PROXY (object);
+}
diff --git a/daemon/gdm-greeter-proxy.h b/daemon/gdm-greeter-proxy.h
new file mode 100644
index 00000000..4458b64b
--- /dev/null
+++ b/daemon/gdm-greeter-proxy.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; 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_GREETER_PROXY_H
+#define __GDM_GREETER_PROXY_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_GREETER_PROXY (gdm_greeter_proxy_get_type ())
+#define GDM_GREETER_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_GREETER_PROXY, GdmGreeterProxy))
+#define GDM_GREETER_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_GREETER_PROXY, GdmGreeterProxyClass))
+#define GDM_IS_GREETER_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_GREETER_PROXY))
+#define GDM_IS_GREETER_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_GREETER_PROXY))
+#define GDM_GREETER_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_GREETER_PROXY, GdmGreeterProxyClass))
+
+typedef struct GdmGreeterProxyPrivate GdmGreeterProxyPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GdmGreeterProxyPrivate *priv;
+} GdmGreeterProxy;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ void (* answer) (GdmGreeterProxy *greeter_proxy,
+ const char *text);
+ void (* started) (GdmGreeterProxy *greeter_proxy);
+ void (* stopped) (GdmGreeterProxy *greeter_proxy);
+} GdmGreeterProxyClass;
+
+GType gdm_greeter_proxy_get_type (void);
+GdmGreeterProxy * gdm_greeter_proxy_new (const char *display_id);
+gboolean gdm_greeter_proxy_start (GdmGreeterProxy *greeter_proxy);
+gboolean gdm_greeter_proxy_stop (GdmGreeterProxy *greeter_proxy);
+
+
+gboolean gdm_greeter_proxy_info_query (GdmGreeterProxy *greeter_proxy,
+ const char *text);
+gboolean gdm_greeter_proxy_secret_info_query (GdmGreeterProxy *greeter_proxy,
+ const char *text);
+gboolean gdm_greeter_proxy_info (GdmGreeterProxy *greeter_proxy,
+ const char *text);
+gboolean gdm_greeter_proxy_problem (GdmGreeterProxy *greeter_proxy,
+ const char *text);
+
+G_END_DECLS
+
+#endif /* __GDM_GREETER_PROXY_H */
diff --git a/daemon/gdm-greeter.c b/daemon/gdm-greeter.c
deleted file mode 100644
index 58e8326f..00000000
--- a/daemon/gdm-greeter.c
+++ /dev/null
@@ -1,1331 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; 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 <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>
-
-#include <X11/Xlib.h> /* for Display */
-
-#include "gdm-common.h"
-#include "filecheck.h"
-
-#include "gdm-greeter.h"
-#include "gdm-socket-protocol.h"
-
-extern char **environ;
-
-#define GDM_GREETER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER, GdmGreeterPrivate))
-
-struct GdmGreeterPrivate
-{
- char *command;
- GPid pid;
-
- char *user_name;
- char *group_name;
-
- int pipe1[2];
- int pipe2[2];
-
- int greeter_fd_in;
- int greeter_fd_out;
-
- char *x11_display_name;
- char *x11_authority_file;
-
- int user_max_filesize;
-
- gboolean interrupted;
- gboolean always_restart_greeter;
-
- guint child_watch_id;
-};
-
-enum {
- PROP_0,
- PROP_X11_DISPLAY_NAME,
- PROP_X11_AUTHORITY_FILE,
- PROP_USER_NAME,
- PROP_GROUP_NAME,
-};
-
-static void gdm_greeter_class_init (GdmGreeterClass *klass);
-static void gdm_greeter_init (GdmGreeter *greeter);
-static void gdm_greeter_finalize (GObject *object);
-
-G_DEFINE_TYPE (GdmGreeter, gdm_greeter, G_TYPE_OBJECT)
-
-static void
-change_user (GdmGreeter *greeter)
-
-{
- struct passwd *pwent;
- struct group *grent;
-
- if (greeter->priv->user_name == NULL) {
- return;
- }
-
- pwent = getpwnam (greeter->priv->user_name);
- if (pwent == NULL) {
- g_warning (_("Greeter was to be spawned by user %s but that user doesn't exist"),
- greeter->priv->user_name);
- _exit (1);
- }
-
- grent = getgrnam (greeter->priv->group_name);
- if (grent == NULL) {
- g_warning (_("Greeter was to be spawned by group %s but that user doesn't exist"),
- greeter->priv->group_name);
- _exit (1);
- }
-
- g_debug ("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);
- }
-}
-
-static void
-greeter_child_setup (GdmGreeter *greeter)
-{
-
- /* Plumbing */
- VE_IGNORE_EINTR (close (greeter->priv->pipe1[1]));
- VE_IGNORE_EINTR (close (greeter->priv->pipe2[0]));
-
- VE_IGNORE_EINTR (dup2 (greeter->priv->pipe1[0], STDIN_FILENO));
- VE_IGNORE_EINTR (dup2 (greeter->priv->pipe2[1], STDOUT_FILENO));
-
- gdm_close_all_descriptors (2 /* from */,
- -1 /* except */,
- -1 /* except2 */);
-
- gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */
-
- change_user (greeter);
-}
-
-static void
-listify_hash (const char *key,
- const char *value,
- GPtrArray *env)
-{
- char *str;
- str = g_strdup_printf ("%s=%s", key, value);
- g_ptr_array_add (env, str);
-}
-
-static GPtrArray *
-get_greeter_environment (GdmGreeter *greeter)
-{
- GPtrArray *env;
- char **l;
- 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 0
- for (l = environ; *l != NULL; l++) {
- char **str;
- str = g_strsplit (*l, "=", 2);
- g_hash_table_insert (hash, str[0], str[1]);
- }
-#endif
-
- g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (greeter->priv->x11_authority_file));
- g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (greeter->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 (greeter->priv->user_name));
- g_hash_table_insert (hash, g_strdup ("USER"), g_strdup (greeter->priv->user_name));
- g_hash_table_insert (hash, g_strdup ("USERNAME"), g_strdup (greeter->priv->user_name));
-
- g_hash_table_insert (hash, g_strdup ("GDM_GREETER_PROTOCOL_VERSION"), g_strdup (GDM_GREETER_PROTOCOL_VERSION));
- 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 (greeter->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));
- }
-
-#if 0
- defaultpath = gdm_daemon_config_get_value_string (GDM_KEY_PATH);
- if (ve_string_empty (g_getenv ("PATH"))) {
- g_setenv ("PATH", defaultpath, TRUE);
- } else if ( ! ve_string_empty (defaultpath)) {
- gchar *temp_string = g_strconcat (g_getenv ("PATH"),
- ":", defaultpath, NULL);
- g_setenv ("PATH", temp_string, TRUE);
- g_free (temp_string);
- }
-#endif
-
- g_hash_table_insert (hash, g_strdup ("RUNNING_UNDER_GDM"), g_strdup ("true"));
-
-#if 0
- if ( ! ve_string_empty (d->theme_name))
- g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
- if (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG_GESTURES)) {
- g_setenv ("G_DEBUG_GESTURES", "true", TRUE);
- }
-#endif
-
-#if 0
- if (SERVER_IS_FLEXI (d)) {
- g_setenv ("GDM_FLEXI_SERVER", "yes", TRUE);
- } else {
- g_unsetenv ("GDM_FLEXI_SERVER");
- }
-#endif
-
-
- g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
- g_hash_table_destroy (hash);
-
- g_ptr_array_add (env, NULL);
-
- return env;
-}
-
-static void
-gdm_slave_whack_temp_auth_file (GdmGreeter *greeter)
-{
-#if 0
- uid_t old;
-
- old = geteuid ();
- if (old != 0)
- seteuid (0);
- if (d->parent_temp_auth_file != NULL) {
- VE_IGNORE_EINTR (g_unlink (d->parent_temp_auth_file));
- }
- g_free (d->parent_temp_auth_file);
- d->parent_temp_auth_file = NULL;
- if (old != 0)
- seteuid (old);
-#endif
-}
-
-
-static void
-create_temp_auth_file (GdmGreeter *greeter)
-{
-#if 0
- if (d->type == TYPE_FLEXI_XNEST &&
- d->parent_auth_file != NULL) {
- if (d->parent_temp_auth_file != NULL) {
- VE_IGNORE_EINTR (g_unlink (d->parent_temp_auth_file));
- }
- g_free (d->parent_temp_auth_file);
- d->parent_temp_auth_file =
- copy_auth_file (d->server_uid,
- gdm_daemon_config_get_gdmuid (),
- d->parent_auth_file);
- }
-#endif
-}
-
-static void
-whack_greeter_fds (GdmGreeter *greeter)
-{
- if (greeter->priv->greeter_fd_out > 0)
- VE_IGNORE_EINTR (close (greeter->priv->greeter_fd_out));
- greeter->priv->greeter_fd_out = -1;
- if (greeter->priv->greeter_fd_in > 0)
- VE_IGNORE_EINTR (close (greeter->priv->greeter_fd_in));
- greeter->priv->greeter_fd_in = -1;
-}
-
-/* return true for "there was an interruption received",
- and interrupted will be TRUE if we are actually interrupted from doing what
- we want. If FALSE is returned, just continue on as we would normally */
-static gboolean
-check_for_interruption (GdmGreeter *greeter,
- const char *msg)
-{
- /* Hell yeah we were interrupted, the greeter died */
- if (msg == NULL) {
- greeter->priv->interrupted = TRUE;
- return TRUE;
- }
-
- if (msg[0] == BEL) {
- /* Different interruptions come here */
- /* Note that we don't want to actually do anything. We want
- * to just set some flag and go on and schedule it after we
- * dump out of the login in the main login checking loop */
-#if 0
- switch (msg[1]) {
- case GDM_INTERRUPT_TIMED_LOGIN:
- /* only allow timed login if display is local,
- * it is allowed for this display (it's only allowed
- * for the first local display) and if it's set up
- * correctly */
- if ((d->attached || gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN))
- && d->timed_login_ok &&
- ! ve_string_empty (ParsedTimedLogin) &&
- strcmp (ParsedTimedLogin, gdm_root_user ()) != 0 &&
- gdm_daemon_config_get_value_int (GDM_KEY_TIMED_LOGIN_DELAY) > 0) {
- do_timed_login = TRUE;
- }
- break;
- case GDM_INTERRUPT_CONFIGURE:
- if (d->attached &&
- gdm_daemon_config_get_value_bool_per_display (GDM_KEY_CONFIG_AVAILABLE, d->name) &&
- gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, d->name) &&
- ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_CONFIGURATOR))) {
- do_configurator = TRUE;
- }
- break;
- case GDM_INTERRUPT_SUSPEND:
- if (d->attached &&
- gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, d->name) &&
- ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND))) {
- gchar *msg = g_strdup_printf ("%s %ld",
- GDM_SOP_SUSPEND_MACHINE,
- (long)getpid ());
-
- gdm_slave_send (msg, FALSE /* wait_for_ack */);
- g_free (msg);
- }
- /* Not interrupted, continue reading input,
- * just proxy this to the master server */
- return TRUE;
- case GDM_INTERRUPT_LOGIN_SOUND:
- if (d->attached &&
- ! play_login_sound (gdm_daemon_config_get_value_string (GDM_KEY_SOUND_ON_LOGIN_FILE))) {
- gdm_error (_("Login sound requested on non-local display or the play software "
- "cannot be run or the sound does not exist"));
- }
- return TRUE;
- case GDM_INTERRUPT_SELECT_USER:
- gdm_verify_select_user (&msg[2]);
- break;
- case GDM_INTERRUPT_CANCEL:
- do_cancel = TRUE;
- break;
- case GDM_INTERRUPT_CUSTOM_CMD:
- if (d->attached &&
- ! ve_string_empty (&msg[2])) {
- gchar *message = g_strdup_printf ("%s %ld %s",
- GDM_SOP_CUSTOM_CMD,
- (long)getpid (), &msg[2]);
-
- gdm_slave_send (message, TRUE);
- g_free (message);
- }
- return TRUE;
- case GDM_INTERRUPT_THEME:
- g_free (d->theme_name);
- d->theme_name = NULL;
- if ( ! ve_string_empty (&msg[2]))
- d->theme_name = g_strdup (&msg[2]);
- gdm_slave_send_string (GDM_SOP_CHOSEN_THEME, &msg[2]);
- return TRUE;
- case GDM_INTERRUPT_SELECT_LANG:
- if (msg + 2) {
- const char *locale;
- const char *gdm_system_locale;
-
- locale = (gchar*)(msg + 3);
- gdm_system_locale = setlocale (LC_CTYPE, NULL);
-
- greeter->priv->always_restart_greeter = (gboolean)(*(msg + 2));
- ve_clearenv ();
- if (!strcmp (locale, DEFAULT_LANGUAGE)) {
- locale = gdm_system_locale;
- }
- g_setenv ("GDM_LANG", locale, TRUE);
- g_setenv ("LANG", locale, TRUE);
- g_unsetenv ("LC_ALL");
- g_unsetenv ("LC_MESSAGES");
- setlocale (LC_ALL, "");
- setlocale (LC_MESSAGES, "");
- gdm_saveenv ();
-
- do_restart_greeter = TRUE;
- }
- break;
- default:
- break;
- }
-#endif
- /* this was an interruption, if it wasn't
- * handled then the user will just get an error as if he
- * entered an invalid login or passward. Seriously BEL
- * cannot be part of a login/password really */
- greeter->priv->interrupted = TRUE;
- return TRUE;
- }
- return FALSE;
-}
-
-static char *
-gdm_slave_greeter_ctl (GdmGreeter *greeter,
- char cmd,
- const char *str)
-{
- char *buf = NULL;
- int c;
-
- if ( ! ve_string_empty (str)) {
- gdm_fdprintf (greeter->priv->greeter_fd_out, "%c%c%s\n", STX, cmd, str);
- } else {
- gdm_fdprintf (greeter->priv->greeter_fd_out, "%c%c\n", STX, cmd);
- }
-
-#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD)
- /* let the other process (greeter) do its stuff */
- sched_yield ();
-#endif
-
- do {
- g_free (buf);
- buf = NULL;
- /* Skip random junk that might have accumulated */
- do {
- c = gdm_fdgetc (greeter->priv->greeter_fd_in);
- } while (c != EOF && c != STX);
-
- if (c == EOF ||
- (buf = gdm_fdgets (greeter->priv->greeter_fd_in)) == NULL) {
- greeter->priv->interrupted = TRUE;
- /* things don't seem well with the greeter, it probably died */
- return NULL;
- }
- } while (check_for_interruption (greeter, buf) && ! greeter->priv->interrupted);
-
- if ( ! ve_string_empty (buf)) {
- return buf;
- } else {
- g_free (buf);
- return NULL;
- }
-}
-
-static void
-gdm_slave_greeter_ctl_no_ret (GdmGreeter *greeter,
- char cmd,
- const char *str)
-{
- g_free (gdm_slave_greeter_ctl (greeter, cmd, str));
-}
-
-/**
- * check_user_file
- * check_global_file
- * is_in_trusted_pic_dir
- * get_facefile_from_gnome2_dir_config
- * path_is_local
- * gdm_daemon_config_get_facefile_from_home
- * gdm_daemon_config_get_facefile_from_global
- *
- * These functions are used for accessing the user's face image from their
- * home directory.
- */
-static gboolean
-check_user_file (const char *path,
- guint uid)
-{
- char *dir;
- char *file;
- gboolean is_ok;
-
- if (path == NULL)
- return FALSE;
-
- if (g_access (path, R_OK) != 0)
- return FALSE;
-
- dir = g_path_get_dirname (path);
- file = g_path_get_basename (path);
-
- is_ok = gdm_file_check ("run_pictures",
- uid,
- dir,
- file,
- TRUE, TRUE,
- 0,
- 0);
- g_free (dir);
- g_free (file);
-
- return is_ok;
-}
-
-static gboolean
-check_global_file (const char *path,
- guint uid)
-{
- if (path == NULL)
- return FALSE;
-
- if (g_access (path, R_OK) != 0)
- return FALSE;
-
- return TRUE;
-}
-
-/* If path starts with a "trusted" directory, don't sanity check things */
-/* This is really somewhat "outdated" as we now really want things in
- * the picture dir or in ~/.gnome2/photo */
-static gboolean
-is_in_trusted_pic_dir (const char *path)
-{
- /* our own pixmap dir is trusted */
- if (strncmp (path, PIXMAPDIR, sizeof (PIXMAPDIR)) == 0)
- return TRUE;
-
- return FALSE;
-}
-
-static gchar *
-get_facefile_from_gnome2_dir_config (const char *homedir,
- guint uid)
-{
- char *picfile = NULL;
- char *cfgdir;
-
- /* Sanity check on ~user/.gnome2/gdm */
- cfgdir = g_build_filename (homedir, ".gnome2", "gdm", NULL);
- if (G_LIKELY (check_user_file (cfgdir, uid))) {
- GKeyFile *cfg;
- char *cfgfile;
-
- cfgfile = g_build_filename (homedir, ".gnome2", "gdm", NULL);
- cfg = g_key_file_new ();
- g_key_file_load_from_file (cfg, cfgfile, 0, NULL);
- g_free (cfgfile);
-
- if (cfg != NULL) {
- picfile = g_key_file_get_string (cfg, "face", "picture", NULL);
- g_key_file_free (cfg);
- }
-
- /* must exist and be absolute (note that this check
- * catches empty strings)*/
- /* Note that these days we just set ~/.face */
- if G_UNLIKELY (picfile != NULL &&
- (picfile[0] != '/' ||
- /* this catches readability by user */
- g_access (picfile, R_OK) != 0)) {
- g_free (picfile);
- picfile = NULL;
- }
-
- if (picfile != NULL) {
- char buf[PATH_MAX];
- if (realpath (picfile, buf) == NULL) {
- g_free (picfile);
- picfile = NULL;
- } else {
- g_free (picfile);
- picfile = g_strdup (buf);
- }
- }
-
- if G_UNLIKELY (picfile != NULL) {
- if (! is_in_trusted_pic_dir (picfile)) {
- /* if not in trusted dir, check it out */
-
- /* Note that strict permissions checking is done
- * on this file. Even if it may not even be owned by the
- * user. This setting should ONLY point to pics in trusted
- * dirs. */
- if (! check_user_file (picfile, uid)) {
- g_free (picfile);
- picfile = NULL;
- }
- }
- }
- }
- g_free (cfgdir);
-
- return picfile;
-}
-
-static GHashTable *fstype_hash = NULL;
-extern char *filesystem_type (char *path, char *relpath, struct stat *statp);
-
-static gboolean
-path_is_local (const char *path)
-{
- gpointer local = NULL;
-
- if (path == NULL)
- return FALSE;
-
- if (fstype_hash == NULL)
- fstype_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- else
- local = g_hash_table_lookup (fstype_hash, path);
-
- if (local == NULL) {
- struct stat statbuf;
-
- if (g_stat (path, &statbuf) == 0) {
- char *type = filesystem_type ((char *)path, (char *)path, &statbuf);
- gboolean is_local = ((strcmp (ve_sure_string (type), "nfs") != 0) &&
- (strcmp (ve_sure_string (type), "afs") != 0) &&
- (strcmp (ve_sure_string (type), "autofs") != 0) &&
- (strcmp (ve_sure_string (type), "unknown") != 0) &&
- (strcmp (ve_sure_string (type), "ncpfs") != 0));
- local = GINT_TO_POINTER (is_local ? 1 : -1);
- g_hash_table_insert (fstype_hash, g_strdup (path), local);
- }
- }
-
- return GPOINTER_TO_INT (local) > 0;
-}
-
-static char *
-gdm_daemon_config_get_facefile_from_home (const char *homedir,
- guint uid)
-{
- char *picfile = NULL;
- char *path;
- gboolean is_local;
-
- /* special case: look at parent of home to detect autofs
- this is so we don't try to trigger an automount */
- path = g_path_get_dirname (homedir);
- is_local = path_is_local (path);
- g_free (path);
-
- /* now check that home dir itself is local */
- if (is_local) {
- is_local = path_is_local (homedir);
- }
-
- /* Only look at local home directories so we don't try to
- read from remote (e.g. NFS) volumes */
- if (! is_local)
- return NULL;
-
- picfile = g_build_filename (homedir, ".face", NULL);
-
- if (check_user_file (picfile, uid))
- return picfile;
- else {
- g_free (picfile);
- picfile = NULL;
- }
-
- picfile = g_build_filename (homedir, ".face.icon", NULL);
-
- if (check_user_file (picfile, uid))
- return picfile;
- else {
- g_free (picfile);
- picfile = NULL;
- }
-
- picfile = get_facefile_from_gnome2_dir_config (homedir, uid);
- if (check_user_file (picfile, uid))
- return picfile;
- else {
- g_free (picfile);
- picfile = NULL;
- }
-
- /* Nothing found yet, try the old locations */
-
- picfile = g_build_filename (homedir, ".gnome2", "photo", NULL);
- if (check_user_file (picfile, uid))
- return picfile;
- else {
- g_free (picfile);
- picfile = NULL;
- }
-
- picfile = g_build_filename (homedir, ".gnome", "photo", NULL);
- if (check_user_file (picfile, uid))
- return picfile;
- else {
- g_free (picfile);
- picfile = NULL;
- }
-
- return NULL;
-}
-
-static char *
-gdm_daemon_config_get_facefile_from_global (const char *username,
- guint uid)
-{
-#if 0
- char *picfile = NULL;
- const char *facedir;
-
- facedir = gdm_daemon_config_get_value_string (GDM_KEY_GLOBAL_FACE_DIR);
-
- /* Try the global face directory */
-
- picfile = g_build_filename (facedir, username, NULL);
-
- if (check_global_file (picfile, uid))
- return picfile;
-
- g_free (picfile);
- picfile = gdm_make_filename (facedir, username, ".png");
-
- if (check_global_file (picfile, uid))
- return picfile;
-
- g_free (picfile);
-#endif
- return NULL;
-}
-
-static void
-gdm_slave_quick_exit (GdmGreeter *greeter)
-{
- /* FIXME */
- _exit (1);
-}
-
-/* This is VERY evil! */
-static void
-run_pictures (GdmGreeter *greeter)
-{
- char *response;
- int max_write;
- char buf[1024];
- size_t bytes;
- struct passwd *pwent;
- char *picfile;
- FILE *fp;
-
- response = NULL;
- for (;;) {
- struct stat s;
- char *tmp, *ret;
- int i, r;
-
- g_free (response);
- response = gdm_slave_greeter_ctl (greeter, GDM_NEEDPIC, "");
- if (ve_string_empty (response)) {
- g_free (response);
- return;
- }
-
- pwent = getpwnam (response);
- if G_UNLIKELY (pwent == NULL) {
- gdm_slave_greeter_ctl_no_ret (greeter, GDM_READPIC, "");
- continue;
- }
-
- picfile = NULL;
-
- NEVER_FAILS_seteuid (0);
- if G_UNLIKELY (setegid (pwent->pw_gid) != 0 ||
- seteuid (pwent->pw_uid) != 0) {
- gdm_slave_greeter_ctl_no_ret (greeter, GDM_READPIC, "");
- continue;
- }
-
- picfile = gdm_daemon_config_get_facefile_from_home (pwent->pw_dir, pwent->pw_uid);
-
- if (! picfile)
- picfile = gdm_daemon_config_get_facefile_from_global (pwent->pw_name, pwent->pw_uid);
-
- if (! picfile) {
- gdm_slave_greeter_ctl_no_ret (greeter, GDM_READPIC, "");
- continue;
- }
-
- VE_IGNORE_EINTR (r = g_stat (picfile, &s));
- if G_UNLIKELY (r < 0 || s.st_size > greeter->priv->user_max_filesize) {
- gdm_slave_greeter_ctl_no_ret (greeter, GDM_READPIC, "");
- continue;
- }
-
- VE_IGNORE_EINTR (fp = fopen (picfile, "r"));
- g_free (picfile);
- if G_UNLIKELY (fp == NULL) {
- gdm_slave_greeter_ctl_no_ret (greeter, GDM_READPIC, "");
- continue;
- }
-
- tmp = g_strdup_printf ("buffer:%d", (int)s.st_size);
- ret = gdm_slave_greeter_ctl (greeter, GDM_READPIC, tmp);
- g_free (tmp);
-
- if G_UNLIKELY (ret == NULL || strcmp (ret, "OK") != 0) {
- VE_IGNORE_EINTR (fclose (fp));
- g_free (ret);
- continue;
- }
- g_free (ret);
-
- gdm_fdprintf (greeter->priv->greeter_fd_out, "%c", STX);
-
-#ifdef PIPE_BUF
- max_write = MIN (PIPE_BUF, sizeof (buf));
-#else
- /* apparently Hurd doesn't have PIPE_BUF */
- max_write = fpathconf (greeter->priv->greeter_fd_out, _PC_PIPE_BUF);
- /* could return -1 if no limit */
- if (max_write > 0)
- max_write = MIN (max_write, sizeof (buf));
- else
- max_write = sizeof (buf);
-#endif
-
- i = 0;
- while (i < s.st_size) {
- int written;
-
- VE_IGNORE_EINTR (bytes = fread (buf, sizeof (char),
- max_write, fp));
-
- if (bytes <= 0)
- break;
-
- if G_UNLIKELY (i + bytes > s.st_size)
- bytes = s.st_size - i;
-
- /* write until we succeed in writing something */
- VE_IGNORE_EINTR (written = write (greeter->priv->greeter_fd_out, buf, bytes));
- if G_UNLIKELY (written < 0 &&
- (errno == EPIPE || errno == EBADF)) {
- /* something very, very bad has happened */
-
- gdm_slave_quick_exit (greeter);
- }
-
- if G_UNLIKELY (written < 0)
- written = 0;
-
- /* write until we succeed in writing everything */
- while (written < bytes) {
- int n;
- VE_IGNORE_EINTR (n = write (greeter->priv->greeter_fd_out, &buf[written], bytes-written));
- if G_UNLIKELY (n < 0 &&
- (errno == EPIPE || errno == EBADF)) {
-
- /* something very, very bad has happened */
- gdm_slave_quick_exit (greeter);
-
- } else if G_LIKELY (n > 0) {
- written += n;
- }
- }
-
- /* we have written bytes bytes if it likes it or not */
- i += bytes;
- }
-
- VE_IGNORE_EINTR (fclose (fp));
-
- /* eek, this "could" happen, so just send some garbage */
- while G_UNLIKELY (i < s.st_size) {
- bytes = MIN (sizeof (buf), s.st_size - i);
- errno = 0;
- bytes = write (greeter->priv->greeter_fd_out, buf, bytes);
- if G_UNLIKELY (bytes < 0 && (errno == EPIPE || errno == EBADF)) {
-
- /* something very, very bad has happened */
- gdm_slave_quick_exit (greeter);
-
- }
- if (bytes > 0)
- i += bytes;
- }
-
- gdm_slave_greeter_ctl_no_ret (greeter, GDM_READPIC, "done");
-
- }
-
- g_free (response); /* not reached */
-}
-
-static void
-greeter_child_watch (GPid pid,
- int status,
- GdmGreeter *greeter)
-{
- g_debug ("child (pid:%d) done (%s:%d)",
- (int) pid,
- WIFEXITED (status) ? "status"
- : WIFSIGNALED (status) ? "signal"
- : "unknown",
- WIFEXITED (status) ? WEXITSTATUS (status)
- : WIFSIGNALED (status) ? WTERMSIG (status)
- : -1);
-
- g_spawn_close_pid (greeter->priv->pid);
- greeter->priv->pid = -1;
-}
-
-static gboolean
-gdm_greeter_spawn (GdmGreeter *greeter)
-{
- gchar **argv;
- GError *error;
- GPtrArray *env;
- gboolean ret;
-
- ret = FALSE;
-
- /* Open a pipe for greeter communications */
- if (pipe (greeter->priv->pipe1) < 0) {
- g_warning ("Can't init pipe to gdmgreeter");
- exit (1);
- }
-
- if (pipe (greeter->priv->pipe2) < 0) {
- VE_IGNORE_EINTR (close (greeter->priv->pipe1[0]));
- VE_IGNORE_EINTR (close (greeter->priv->pipe1[1]));
- g_warning ("Can't init pipe to gdmgreeter");
- exit (1);
- }
-
- create_temp_auth_file (greeter);
-
- g_debug ("Running greeter process: %s", greeter->priv->command);
-
- argv = NULL;
- if (! g_shell_parse_argv (greeter->priv->command, NULL, &argv, &error)) {
- g_warning ("Could not parse command: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- env = get_greeter_environment (greeter);
-
- error = NULL;
- ret = g_spawn_async_with_pipes (NULL,
- argv,
- (char **)env->pdata,
- G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD,
- (GSpawnChildSetupFunc)greeter_child_setup,
- greeter,
- &greeter->priv->pid,
- NULL,
- NULL,
- NULL,
- &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",
- greeter->priv->command,
- error->message);
- g_error_free (error);
- } else {
-
- whack_greeter_fds (greeter);
-
- greeter->priv->greeter_fd_out = greeter->priv->pipe1[1];
- greeter->priv->greeter_fd_in = greeter->priv->pipe2[0];
-
- g_debug ("gdm_slave_greeter: Greeter on pid %d", (int)greeter->priv->pid);
- }
-
- greeter->priv->child_watch_id = g_child_watch_add (greeter->priv->pid,
- (GChildWatchFunc)greeter_child_watch,
- greeter);
-
- g_strfreev (argv);
- out:
-
- return ret;
-}
-
-/**
- * gdm_greeter_start:
- * @disp: Pointer to a GdmDisplay structure
- *
- * Starts a local X greeter. Handles retries and fatal errors properly.
- */
-
-gboolean
-gdm_greeter_start (GdmGreeter *greeter)
-{
- gboolean res;
- const char *gdmlang;
-
- res = gdm_greeter_spawn (greeter);
-
- if (res) {
- run_pictures (greeter); /* Append pictures to greeter if browsing is on */
-
- if (greeter->priv->always_restart_greeter)
- gdm_slave_greeter_ctl_no_ret (greeter, GDM_ALWAYS_RESTART, "Y");
- else
- gdm_slave_greeter_ctl_no_ret (greeter, GDM_ALWAYS_RESTART, "N");
-
- gdmlang = g_getenv ("GDM_LANG");
- if (gdmlang)
- gdm_slave_greeter_ctl_no_ret (greeter, GDM_SETLANG, gdmlang);
- }
-
-
- return res;
-}
-
-static int
-signal_pid (int pid,
- int signal)
-{
- int status = -1;
-
- /* perhaps block sigchld */
-
- status = kill (pid, signal);
-
- if (status < 0) {
- if (errno == ESRCH) {
- g_warning ("Child process %lu was already dead.",
- (unsigned long) pid);
- } else {
- g_warning ("Couldn't kill child process %lu: %s",
- (unsigned long) pid,
- g_strerror (errno));
- }
- }
-
- /* perhaps unblock sigchld */
-
- return status;
-}
-
-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 ("waitpid () should not fail");
- }
- }
-
- return status;
-}
-
-static void
-greeter_died (GdmGreeter *greeter)
-{
- int exit_status;
-
- g_debug ("Waiting on process %d", greeter->priv->pid);
- exit_status = wait_on_child (greeter->priv->pid);
-
- if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
- g_debug ("Wait on child process failed");
- } else {
- /* exited normally */
- }
-
- g_spawn_close_pid (greeter->priv->pid);
- greeter->priv->pid = -1;
-
- g_debug ("Greeter died");
-}
-
-gboolean
-gdm_greeter_stop (GdmGreeter *greeter)
-{
-
- if (greeter->priv->pid <= 1) {
- return TRUE;
- }
-
- /* remove watch source before we can wait on child */
- if (greeter->priv->child_watch_id > 0) {
- g_source_remove (greeter->priv->child_watch_id);
- greeter->priv->child_watch_id = 0;
- }
-
- g_debug ("Stopping greeter");
-
- signal_pid (greeter->priv->pid, SIGTERM);
- greeter_died (greeter);
-
- return TRUE;
-}
-
-
-static void
-_gdm_greeter_set_x11_display_name (GdmGreeter *greeter,
- const char *name)
-{
- g_free (greeter->priv->x11_display_name);
- greeter->priv->x11_display_name = g_strdup (name);
-}
-
-static void
-_gdm_greeter_set_x11_authority_file (GdmGreeter *greeter,
- const char *file)
-{
- g_free (greeter->priv->x11_authority_file);
- greeter->priv->x11_authority_file = g_strdup (file);
-}
-
-static void
-_gdm_greeter_set_user_name (GdmGreeter *greeter,
- const char *name)
-{
- g_free (greeter->priv->user_name);
- greeter->priv->user_name = g_strdup (name);
-}
-
-static void
-_gdm_greeter_set_group_name (GdmGreeter *greeter,
- const char *name)
-{
- g_free (greeter->priv->group_name);
- greeter->priv->group_name = g_strdup (name);
-}
-
-static void
-gdm_greeter_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GdmGreeter *self;
-
- self = GDM_GREETER (object);
-
- switch (prop_id) {
- case PROP_X11_DISPLAY_NAME:
- _gdm_greeter_set_x11_display_name (self, g_value_get_string (value));
- break;
- case PROP_X11_AUTHORITY_FILE:
- _gdm_greeter_set_x11_authority_file (self, g_value_get_string (value));
- break;
- case PROP_USER_NAME:
- _gdm_greeter_set_user_name (self, g_value_get_string (value));
- break;
- case PROP_GROUP_NAME:
- _gdm_greeter_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_greeter_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GdmGreeter *self;
-
- self = GDM_GREETER (object);
-
- switch (prop_id) {
- case PROP_X11_DISPLAY_NAME:
- g_value_set_string (value, self->priv->x11_display_name);
- 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;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static GObject *
-gdm_greeter_constructor (GType type,
- guint n_construct_properties,
- GObjectConstructParam *construct_properties)
-{
- GdmGreeter *greeter;
- GdmGreeterClass *klass;
-
- klass = GDM_GREETER_CLASS (g_type_class_peek (GDM_TYPE_GREETER));
-
- greeter = GDM_GREETER (G_OBJECT_CLASS (gdm_greeter_parent_class)->constructor (type,
- n_construct_properties,
- construct_properties));
-
- return G_OBJECT (greeter);
-}
-
-static void
-gdm_greeter_class_init (GdmGreeterClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->get_property = gdm_greeter_get_property;
- object_class->set_property = gdm_greeter_set_property;
- object_class->constructor = gdm_greeter_constructor;
- object_class->finalize = gdm_greeter_finalize;
-
- g_type_class_add_private (klass, sizeof (GdmGreeterPrivate));
-
- 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_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));
-}
-
-static void
-gdm_greeter_init (GdmGreeter *greeter)
-{
-
- greeter->priv = GDM_GREETER_GET_PRIVATE (greeter);
-
- greeter->priv->pid = -1;
-
- greeter->priv->command = g_strdup (LIBEXECDIR "/gdmgreeter");
- greeter->priv->user_max_filesize = 65536;
-}
-
-static void
-gdm_greeter_finalize (GObject *object)
-{
- GdmGreeter *greeter;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (GDM_IS_GREETER (object));
-
- greeter = GDM_GREETER (object);
-
- g_return_if_fail (greeter->priv != NULL);
-
- gdm_greeter_stop (greeter);
-
- G_OBJECT_CLASS (gdm_greeter_parent_class)->finalize (object);
-}
-
-GdmGreeter *
-gdm_greeter_new (const char *display_name)
-{
- GObject *object;
-
- object = g_object_new (GDM_TYPE_GREETER,
- "x11-display-name", display_name,
- NULL);
-
- return GDM_GREETER (object);
-}
diff --git a/daemon/gdm-greeter.h b/daemon/gdm-greeter.h
deleted file mode 100644
index 8a000342..00000000
--- a/daemon/gdm-greeter.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; 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_GREETER_H
-#define __GDM_GREETER_H
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define GDM_TYPE_GREETER (gdm_greeter_get_type ())
-#define GDM_GREETER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_GREETER, GdmGreeter))
-#define GDM_GREETER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_GREETER, GdmGreeterClass))
-#define GDM_IS_GREETER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_GREETER))
-#define GDM_IS_GREETER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_GREETER))
-#define GDM_GREETER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_GREETER, GdmGreeterClass))
-
-typedef struct GdmGreeterPrivate GdmGreeterPrivate;
-
-typedef struct
-{
- GObject parent;
- GdmGreeterPrivate *priv;
-} GdmGreeter;
-
-typedef struct
-{
- GObjectClass parent_class;
-
-} GdmGreeterClass;
-
-GType gdm_greeter_get_type (void);
-GdmGreeter * gdm_greeter_new (const char *display_id);
-gboolean gdm_greeter_start (GdmGreeter *greeter);
-gboolean gdm_greeter_stop (GdmGreeter *greeter);
-
-G_END_DECLS
-
-#endif /* __GDM_GREETER_H */
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index f1af3a46..472e3fe8 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -630,7 +630,8 @@ gdm_session_class_install_signals (GdmSessionClass *session_class)
session_class->info = NULL;
gdm_session_signals[PROBLEM] =
- g_signal_new ("problem", G_OBJECT_CLASS_TYPE (object_class),
+ g_signal_new ("problem",
+ G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GdmSessionClass, problem),
NULL,
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index 2a272bc9..49510d1e 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -35,8 +35,6 @@ G_BEGIN_DECLS
#define GDM_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SESSION, GdmSessionClass))
#define GDM_SESSION_ERROR (gdm_session_error_quark ())
-typedef enum _GdmSessionError GdmSessionError;
-
typedef struct _GdmSessionPrivate GdmSessionPrivate;
typedef struct
@@ -82,7 +80,7 @@ typedef struct
int signal_number);
} GdmSessionClass;
-enum _GdmSessionError {
+typedef enum _GdmSessionError {
GDM_SESSION_ERROR_GENERIC = 0,
GDM_SESSION_ERROR_WITH_SESSION_COMMAND,
GDM_SESSION_ERROR_FORKING,
@@ -94,43 +92,43 @@ enum _GdmSessionError {
GDM_SESSION_ERROR_OPENING_LOG_FILE,
GDM_SESSION_ERROR_OPENING_SESSION,
GDM_SESSION_ERROR_GIVING_CREDENTIALS
-};
+} GdmSessionError;
GType gdm_session_get_type (void);
GQuark gdm_session_error_quark (void);
GdmSession * gdm_session_new (void) G_GNUC_MALLOC;
-gboolean gdm_session_open (GdmSession *session,
+gboolean gdm_session_open (GdmSession *session,
const char *service_name,
const char *hostname,
const char *console_name,
- int standard_output_fd,
- int standard_error_fd,
- GError **error);
+ int standard_output_fd,
+ int standard_error_fd,
+ GError **error);
gboolean gdm_session_open_for_user (GdmSession *session,
const char *service_name,
const char *username,
const char *hostname,
const char *console_name,
- int standard_output_fd,
- int standard_error_fd,
- GError **error);
-void gdm_session_start_program (GdmSession *session,
+ int standard_output_fd,
+ int standard_error_fd,
+ GError **error);
+void gdm_session_start_program (GdmSession *session,
const char * const * args);
void gdm_session_set_environment_variable (GdmSession *session,
- const char *key,
- const char *value);
+ const char *key,
+ const char *value);
void gdm_session_answer_query (GdmSession *session,
- const char *answer);
+ const char *answer);
-char * gdm_session_get_username (GdmSession *session);
+char * gdm_session_get_username (GdmSession *session);
-void gdm_session_close (GdmSession *session);
-gboolean gdm_session_is_running (GdmSession *session);
+void gdm_session_close (GdmSession *session);
+gboolean gdm_session_is_running (GdmSession *session);
G_END_DECLS
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index a9752583..6722ab9b 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -49,7 +49,8 @@
#include "gdm-slave-glue.h"
#include "gdm-server.h"
-#include "gdm-greeter.h"
+#include "gdm-session.h"
+#include "gdm-greeter-proxy.h"
extern char **environ;
@@ -89,7 +90,8 @@ struct GdmSlavePrivate
GdmServer *server;
- GdmGreeter *greeter;
+ GdmGreeterProxy *greeter;
+ GdmSession *session;
DBusGProxy *display_proxy;
DBusGConnection *connection;
};
@@ -612,6 +614,133 @@ gdm_slave_exec_script (GdmSlave *slave,
}
static void
+on_session_started (GdmSession *session,
+ GPid pid,
+ GdmSlave *slave)
+{
+ g_debug ("session started on pid %d\n", (int) pid);
+}
+
+static void
+on_session_exited (GdmSession *session,
+ int exit_code,
+ GdmSlave *slave)
+{
+ g_debug ("session exited with code %d\n", exit_code);
+ exit (0);
+}
+
+static void
+on_session_died (GdmSession *session,
+ int signal_number,
+ GdmSlave *slave)
+{
+ g_debug ("session died with signal %d, (%s)",
+ signal_number,
+ g_strsignal (signal_number));
+ exit (1);
+}
+
+static void
+on_user_verified (GdmSession *session,
+ GdmSlave *slave)
+{
+ char *username;
+ const char *args[] = { "/usr/bin/gedit", "/tmp/foo.log", NULL };
+
+ username = gdm_session_get_username (session);
+
+ g_debug ("%s%ssuccessfully authenticated\n",
+ username ? username : "",
+ username ? " " : "");
+ g_free (username);
+
+ gdm_session_start_program (session, args);
+}
+
+static void
+on_user_verification_error (GdmSession *session,
+ GError *error,
+ GdmSlave *slave)
+{
+ char *username;
+
+ username = gdm_session_get_username (session);
+
+ g_debug ("%s%scould not be successfully authenticated: %s\n",
+ username ? username : "",
+ username ? " " : "",
+ error->message);
+
+ g_free (username);
+}
+
+static void
+on_info (GdmSession *session,
+ const char *text,
+ GdmSlave *slave)
+{
+ g_debug ("Info: %s", text);
+ gdm_greeter_proxy_info (slave->priv->greeter, text);
+}
+
+static void
+on_problem (GdmSession *session,
+ const char *text,
+ GdmSlave *slave)
+{
+ g_debug ("Problem: %s", text);
+ gdm_greeter_proxy_problem (slave->priv->greeter, text);
+}
+
+static void
+on_info_query (GdmSession *session,
+ const char *text,
+ GdmSlave *slave)
+{
+
+ g_debug ("Info query: %s", text);
+ gdm_greeter_proxy_info_query (slave->priv->greeter, text);
+}
+
+static void
+on_secret_info_query (GdmSession *session,
+ const char *text,
+ GdmSlave *slave)
+{
+ g_debug ("Secret info query: %s", text);
+ gdm_greeter_proxy_secret_info_query (slave->priv->greeter, text);
+}
+
+static void
+on_greeter_answer (GdmGreeterProxy *greeter,
+ const char *text,
+ GdmSlave *slave)
+{
+ gdm_session_answer_query (slave->priv->session, text);
+}
+
+static void
+on_greeter_start (GdmGreeterProxy *greeter,
+ GdmSlave *slave)
+{
+ g_debug ("Greeter started");
+
+ gdm_session_open (slave->priv->session,
+ "gdm",
+ NULL /* hostname */,
+ "/dev/console",
+ STDOUT_FILENO,
+ STDERR_FILENO,
+ NULL);
+
+ /* If XDMCP stop pinging */
+ if ( ! slave->priv->display_is_local) {
+ alarm (0);
+ }
+}
+
+static void
run_greeter (GdmSlave *slave)
{
@@ -647,16 +776,66 @@ run_greeter (GdmSlave *slave)
GDMCONFDIR"/Init",
"gdm");
- slave->priv->greeter = gdm_greeter_new (slave->priv->display_name);
+ slave->priv->session = gdm_session_new ();
+
+ g_signal_connect (slave->priv->session,
+ "info",
+ G_CALLBACK (on_info),
+ slave);
+
+ g_signal_connect (slave->priv->session,
+ "problem",
+ G_CALLBACK (on_problem),
+ slave);
+
+ g_signal_connect (slave->priv->session,
+ "info-query",
+ G_CALLBACK (on_info_query),
+ slave);
+
+ g_signal_connect (slave->priv->session,
+ "secret-info-query",
+ G_CALLBACK (on_secret_info_query),
+ slave);
+
+ g_signal_connect (slave->priv->session,
+ "user-verified",
+ G_CALLBACK (on_user_verified),
+ slave);
+
+ g_signal_connect (slave->priv->session,
+ "user-verification-error",
+ G_CALLBACK (on_user_verification_error),
+ slave);
+
+ g_signal_connect (slave->priv->session,
+ "session-started",
+ G_CALLBACK (on_session_started),
+ slave);
+
+ g_signal_connect (slave->priv->session,
+ "session-exited",
+ G_CALLBACK (on_session_exited),
+ slave);
+
+ g_signal_connect (slave->priv->session,
+ "session-died",
+ G_CALLBACK (on_session_died),
+ slave);
+
+ slave->priv->greeter = gdm_greeter_proxy_new (slave->priv->display_name);
+ g_signal_connect (slave->priv->greeter,
+ "answer",
+ G_CALLBACK (on_greeter_answer),
+ slave);
+ g_signal_connect (slave->priv->greeter,
+ "started",
+ G_CALLBACK (on_greeter_start),
+ slave);
g_object_set (slave->priv->greeter,
"x11-authority-file", slave->priv->display_x11_authority_file,
NULL);
- gdm_greeter_start (slave->priv->greeter);
-
- /* If XDMCP stop pinging */
- if ( ! slave->priv->display_is_local) {
- alarm (0);
- }
+ gdm_greeter_proxy_start (slave->priv->greeter);
}
static void
@@ -922,11 +1101,17 @@ gdm_slave_stop (GdmSlave *slave)
g_debug ("Stopping slave");
if (slave->priv->greeter != NULL) {
- gdm_greeter_stop (slave->priv->greeter);
+ gdm_greeter_proxy_stop (slave->priv->greeter);
g_object_unref (slave->priv->greeter);
slave->priv->greeter = NULL;
}
+ if (slave->priv->session != NULL) {
+ gdm_session_close (slave->priv->session);
+ g_object_unref (slave->priv->session);
+ slave->priv->session = NULL;
+ }
+
if (slave->priv->server != NULL) {
gdm_server_stop (slave->priv->server);
g_object_unref (slave->priv->server);
@@ -950,7 +1135,7 @@ _gdm_slave_set_display_id (GdmSlave *slave,
static void
gdm_slave_set_property (GObject *object,
- guint prop_id,
+ guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
@@ -970,9 +1155,9 @@ gdm_slave_set_property (GObject *object,
static void
gdm_slave_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GdmSlave *self;
diff --git a/daemon/gdm-socket-protocol.h b/daemon/gdm-socket-protocol.h
index d1ea3b68..2623c2ff 100644
--- a/daemon/gdm-socket-protocol.h
+++ b/daemon/gdm-socket-protocol.h
@@ -76,9 +76,6 @@
#define GDM_INTERRUPT_CANCEL 'X'
#define GDM_INTERRUPT_SELECT_LANG 'O'
-/* List delimiter for config file lists */
-#define GDM_DELIMITER_MODULES ":"
-#define GDM_DELIMITER_THEMES "/:"
/*
diff --git a/daemon/test-session.c b/daemon/test-session.c
index 8babaf53..ec807e67 100644
--- a/daemon/test-session.c
+++ b/daemon/test-session.c
@@ -100,8 +100,8 @@ on_info_query (GdmSession *session,
answer[strlen(answer) - 1] = '\0';
if (answer[0] == '\0') {
- gdm_session_close (session);
- g_main_loop_quit (loop);
+ gdm_session_close (session);
+ g_main_loop_quit (loop);
} else {
gdm_session_answer_query (session, answer);
}
diff --git a/gui/Makefile.am b/gui/Makefile.am
index 3b0ddac9..c4c416c3 100644
--- a/gui/Makefile.am
+++ b/gui/Makefile.am
@@ -1,6 +1,7 @@
NULL =
-SUBDIRS = \
+SUBDIRS =
+ . \
greeter \
modules \
faces \
@@ -41,15 +42,11 @@ INCLUDES = \
# -DGNOME_DISABLE_DEPRECATED \
#
-BUILT_SOURCES = \
- gdm-greeter-glue.h \
+noinst_LIBRARIES = \
+ libgdmwm.a \
+ libgdmguicommon.a \
$(NULL)
-gdm-greeter-glue.h: gdm-greeter.xml Makefile.am
- dbus-binding-tool --prefix=gdm_greeter --mode=glib-server --output=gdm-greeter-glue.h gdm-greeter.xml
-
-noinst_LIBRARIES = libgdmwm.a libgdmcommon.a
-
libexec_PROGRAMS = \
@GDMCHOOSER@ \
$(NULL)
@@ -77,7 +74,7 @@ libgdmwm_a_SOURCES = \
gdmwm.h \
$(NULL)
-libgdmcommon_a_SOURCES = \
+libgdmguicommon_a_SOURCES = \
gdm-greeter.c \
gdm-greeter.h \
gdmlanguages.c \
@@ -102,7 +99,7 @@ gdmchooser_LDFLAGS = -export-dynamic
gdmchooser_LDADD = \
$(EXTRA_CHOOSER_LIBS) \
libgdmwm.a \
- libgdmcommon.a \
+ libgdmguicommon.a \
$(GUIGLADE_LIBS) \
$(INTLLIBS) \
$(GLIB_LIBS) \
@@ -120,7 +117,7 @@ gdmchooser_LDADD = \
$(NULL)
gdmXnestchooser_LDADD = \
- libgdmcommon.a \
+ libgdmguicommon.a \
$(GUI_LIBS) \
$(INTLLIBS) \
$(GLIB_LIBS) \
@@ -135,7 +132,7 @@ gdmXnestchooser_LDADD = \
$(NULL)
gdmflexiserver_LDADD = \
- libgdmcommon.a \
+ libgdmguicommon.a \
$(GUI_LIBS) \
$(INTLLIBS) \
$(GLIB_LIBS) \
diff --git a/gui/gdm-greeter.c b/gui/gdm-greeter.c
index 65ffff0f..2d8c3772 100644
--- a/gui/gdm-greeter.c
+++ b/gui/gdm-greeter.c
@@ -32,44 +32,33 @@
#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-greeter.h"
-#include "gdm-greeter-glue.h"
-
#define GDM_GREETER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_GREETER, GdmGreeterPrivate))
-#define GDM_DBUS_PATH "/org/gnome/DisplayGreeter"
-#define GDM_GREETER_DBUS_PATH GDM_DBUS_PATH "/Greeter"
-#define GDM_GREETER_DBUS_NAME "org.gnome.DisplayGreeter.Greeter"
-
struct GdmGreeterPrivate
{
- DBusGProxy *bus_proxy;
- DBusGConnection *connection;
+ gpointer dummy;
};
enum {
- PROP_0
+ PROP_0,
};
enum {
- FOO,
+ QUERY_ANSWER,
LAST_SIGNAL
};
static guint signals [LAST_SIGNAL] = { 0, };
+
static void gdm_greeter_class_init (GdmGreeterClass *klass);
static void gdm_greeter_init (GdmGreeter *greeter);
static void gdm_greeter_finalize (GObject *object);
-static gpointer greeter_object = NULL;
-
-G_DEFINE_TYPE (GdmGreeter, gdm_greeter, G_TYPE_OBJECT)
+G_DEFINE_ABSTRACT_TYPE (GdmGreeter, gdm_greeter, G_TYPE_OBJECT)
GQuark
gdm_greeter_error_quark (void)
@@ -82,12 +71,162 @@ gdm_greeter_error_quark (void)
return ret;
}
+static gboolean
+gdm_greeter_real_start (GdmGreeter *greeter)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_start (GdmGreeter *greeter)
+{
+ gboolean ret;
+
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ g_object_ref (greeter);
+ ret = GDM_GREETER_GET_CLASS (greeter)->start (greeter);
+ g_object_unref (greeter);
+
+ return ret;
+}
+
+static gboolean
+gdm_greeter_real_stop (GdmGreeter *greeter)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_stop (GdmGreeter *greeter)
+{
+ gboolean ret;
+
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ g_object_ref (greeter);
+ ret = GDM_GREETER_GET_CLASS (greeter)->stop (greeter);
+ g_object_unref (greeter);
+
+ return ret;
+}
+
+static gboolean
+gdm_greeter_real_info (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_info (GdmGreeter *greeter,
+ const char *text)
+{
+ gboolean ret;
+
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ g_object_ref (greeter);
+ ret = GDM_GREETER_GET_CLASS (greeter)->info (greeter, text);
+ g_object_unref (greeter);
+
+ return ret;
+}
+
+static gboolean
+gdm_greeter_real_problem (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_problem (GdmGreeter *greeter,
+ const char *text)
+{
+ gboolean ret;
+
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ g_object_ref (greeter);
+ ret = GDM_GREETER_GET_CLASS (greeter)->problem (greeter, text);
+ g_object_unref (greeter);
+
+ return ret;
+}
+
+static gboolean
+gdm_greeter_real_info_query (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_info_query (GdmGreeter *greeter,
+ const char *text)
+{
+ gboolean ret;
+
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ g_object_ref (greeter);
+ ret = GDM_GREETER_GET_CLASS (greeter)->info_query (greeter, text);
+ g_object_unref (greeter);
+
+ return ret;
+}
+
+static gboolean
+gdm_greeter_real_secret_info_query (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_secret_info_query (GdmGreeter *greeter,
+ const char *text)
+{
+ gboolean ret;
+
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ g_object_ref (greeter);
+ ret = GDM_GREETER_GET_CLASS (greeter)->secret_info_query (greeter, text);
+ g_object_unref (greeter);
+
+ return ret;
+}
+
+gboolean
+gdm_greeter_answer_query (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ g_debug ("Answer query: %s", text);
+
+ g_signal_emit (greeter, signals[QUERY_ANSWER], 0, text);
+}
static void
-gdm_greeter_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+gdm_greeter_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
GdmGreeter *self;
@@ -101,10 +240,10 @@ gdm_greeter_set_property (GObject *object,
}
static void
-gdm_greeter_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+gdm_greeter_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GdmGreeter *self;
@@ -124,6 +263,7 @@ gdm_greeter_constructor (GType type,
{
GdmGreeter *greeter;
GdmGreeterClass *klass;
+ gboolean res;
klass = GDM_GREETER_CLASS (g_type_class_peek (GDM_TYPE_GREETER));
@@ -135,18 +275,49 @@ gdm_greeter_constructor (GType type,
}
static void
+gdm_greeter_dispose (GObject *object)
+{
+ GdmGreeter *greeter;
+
+ greeter = GDM_GREETER (object);
+
+ g_debug ("Disposing greeter");
+ gdm_greeter_stop (greeter);
+
+ G_OBJECT_CLASS (gdm_greeter_parent_class)->dispose (object);
+}
+
+static void
gdm_greeter_class_init (GdmGreeterClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = gdm_greeter_get_property;
object_class->set_property = gdm_greeter_set_property;
- object_class->constructor = gdm_greeter_constructor;
+ object_class->constructor = gdm_greeter_constructor;
+ object_class->dispose = gdm_greeter_dispose;
object_class->finalize = gdm_greeter_finalize;
- g_type_class_add_private (klass, sizeof (GdmGreeterPrivate));
+ klass->start = gdm_greeter_real_start;
+ klass->stop = gdm_greeter_real_stop;
+ klass->info = gdm_greeter_real_info;
+ klass->problem = gdm_greeter_real_problem;
+ klass->info_query = gdm_greeter_real_info_query;
+ klass->secret_info_query = gdm_greeter_real_secret_info_query;
+
+
+ signals [QUERY_ANSWER] =
+ g_signal_new ("query-answer",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GdmGreeterClass, query_answer),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
- dbus_g_object_type_install_info (GDM_TYPE_GREETER, &dbus_glib_gdm_greeter_object_info);
+ g_type_class_add_private (klass, sizeof (GdmGreeterPrivate));
}
static void
@@ -169,20 +340,5 @@ gdm_greeter_finalize (GObject *object)
g_return_if_fail (greeter->priv != NULL);
-
G_OBJECT_CLASS (gdm_greeter_parent_class)->finalize (object);
}
-
-GdmGreeter *
-gdm_greeter_new (void)
-{
- if (greeter_object != NULL) {
- g_object_ref (greeter_object);
- } else {
- greeter_object = g_object_new (GDM_TYPE_GREETER, NULL);
- g_object_add_weak_pointer (greeter_object,
- (gpointer *) &greeter_object);
- }
-
- return GDM_GREETER (greeter_object);
-}
diff --git a/gui/gdm-greeter.h b/gui/gdm-greeter.h
index 1019770d..59b20e5c 100644
--- a/gui/gdm-greeter.h
+++ b/gui/gdm-greeter.h
@@ -45,6 +45,22 @@ typedef struct
{
GObjectClass parent_class;
+ /* signals */
+ void (* query_answer) (GdmGreeter *greeter,
+ const char *text);
+ /* methods */
+ gboolean (*start) (GdmGreeter *greeter);
+ gboolean (*stop) (GdmGreeter *greeter);
+
+ gboolean (*info_query) (GdmGreeter *greeter,
+ const char *text);
+ gboolean (*secret_info_query) (GdmGreeter *greeter,
+ const char *text);
+ gboolean (*info) (GdmGreeter *greeter,
+ const char *text);
+ gboolean (*problem) (GdmGreeter *greeter,
+ const char *text);
+
} GdmGreeterClass;
typedef enum
@@ -57,7 +73,20 @@ typedef enum
GQuark gdm_greeter_error_quark (void);
GType gdm_greeter_get_type (void);
-GdmGreeter * gdm_greeter_new (void);
+gboolean gdm_greeter_start (GdmGreeter *greeter);
+gboolean gdm_greeter_stop (GdmGreeter *greeter);
+
+gboolean gdm_greeter_answer_query (GdmGreeter *greeter,
+ const char *text);
+
+gboolean gdm_greeter_info_query (GdmGreeter *greeter,
+ const char *text);
+gboolean gdm_greeter_secret_info_query (GdmGreeter *greeter,
+ const char *text);
+gboolean gdm_greeter_info (GdmGreeter *greeter,
+ const char *text);
+gboolean gdm_greeter_problem (GdmGreeter *greeter,
+ const char *text);
G_END_DECLS
diff --git a/gui/gdm-greeter.xml b/gui/gdm-greeter.xml
deleted file mode 100644
index c1a63100..00000000
--- a/gui/gdm-greeter.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<!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.Greeter">
- </interface>
-</node>
diff --git a/gui/greeter/Makefile.am b/gui/greeter/Makefile.am
index 938362fc..3a072cc7 100644
--- a/gui/greeter/Makefile.am
+++ b/gui/greeter/Makefile.am
@@ -17,6 +17,7 @@ INCLUDES = \
-DSBINDIR=\""$(sbindir)"\" \
-DPIXMAPDIR=\""$(pixmapdir)"\" \
$(GUI_CFLAGS) \
+ $(DBUS_CFLAGS) \
$(PANGO_CFLAGS) \
$(PANGOFT_CFLAGS) \
$(GREETER_CFLAGS)
@@ -44,6 +45,8 @@ gdmthemetester: $(srcdir)/gdmthemetester.in
gdmgreeter_SOURCES = \
greeter.c \
greeter.h \
+ gdm-themed-greeter.c \
+ gdm-themed-greeter.h \
greeter_canvas_text.c \
greeter_canvas_text.h \
greeter_canvas_item.c \
@@ -78,9 +81,10 @@ gdmgreeter_LDADD = \
$(EXTRA_GREETER_LIBS) \
-L$(top_builddir)/gui \
-lgdmwm \
- -lgdmcommon \
+ -lgdmguicommon \
$(top_builddir)/common/libgdmcommon.a \
$(GLIB_LIBS) \
+ $(DBUS_LIBS) \
$(GOBJECT_LIBS) \
$(PANGO_LIBS) \
$(PANGOFT_LIBS) \
diff --git a/gui/greeter/gdm-themed-greeter.c b/gui/greeter/gdm-themed-greeter.c
new file mode 100644
index 00000000..5d44b22d
--- /dev/null
+++ b/gui/greeter/gdm-themed-greeter.c
@@ -0,0 +1,1087 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; 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 <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include "gdm-greeter.h"
+#include "gdm-themed-greeter.h"
+#include "gdm-common.h"
+#include "gdm-settings-client.h"
+#include "gdm-settings-keys.h"
+
+#include <libgnomecanvas/libgnomecanvas.h>
+
+#if HAVE_PAM
+#include <security/pam_appl.h>
+#define PW_ENTRY_SIZE PAM_MAX_RESP_SIZE
+#else
+#define PW_ENTRY_SIZE GDM_MAX_PASS
+#endif
+
+
+#include "gdm.h"
+#include "gdmwm.h"
+#include "gdmcommon.h"
+#include "gdmsession.h"
+#include "gdmlanguages.h"
+#include "greeter.h"
+#include "greeter_configuration.h"
+#include "greeter_parser.h"
+#include "greeter_geometry.h"
+#include "greeter_item_clock.h"
+#include "greeter_item_pam.h"
+#include "greeter_item_ulist.h"
+#include "greeter_item_customlist.h"
+#include "greeter_item_capslock.h"
+#include "greeter_item_timed.h"
+#include "greeter_events.h"
+#include "greeter_session.h"
+#include "greeter_system.h"
+
+#define GDM_THEMED_GREETER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_THEMED_GREETER, GdmThemedGreeterPrivate))
+
+/* FIXME: hack */
+extern gboolean session_dir_whacked_out;
+extern gboolean require_quarter;
+extern gint gdm_timed_delay;
+extern GtkButton *gtk_ok_button;
+extern GtkButton *gtk_start_again_button;
+
+gboolean greeter_probably_login_prompt = FALSE;
+static gboolean first_prompt = TRUE;
+
+static gboolean ignore_buttons = FALSE;
+
+gboolean GdmHaltFound = FALSE;
+gboolean GdmRebootFound = FALSE;
+gboolean *GdmCustomCmdsFound = FALSE;
+gboolean GdmAnyCustomCmdsFound = FALSE;
+gboolean GdmSuspendFound = FALSE;
+gboolean GdmConfiguratorFound = FALSE;
+GreeterItemInfo *welcome_string_info;
+GreeterItemInfo *root;
+GtkWidget *window = NULL;
+GtkWidget *canvas = NULL;
+
+enum {
+ RESPONSE_RESTART,
+ RESPONSE_REBOOT,
+ RESPONSE_CLOSE
+};
+
+struct GdmThemedGreeterPrivate
+{
+};
+
+enum {
+ PROP_0,
+};
+
+static void gdm_themed_greeter_class_init (GdmThemedGreeterClass *klass);
+static void gdm_themed_greeter_init (GdmThemedGreeter *themed_greeter);
+static void gdm_themed_greeter_finalize (GObject *object);
+
+G_DEFINE_TYPE (GdmThemedGreeter, gdm_themed_greeter, GDM_TYPE_GREETER)
+
+void
+greeter_ignore_buttons (gboolean val)
+{
+ ignore_buttons = val;
+}
+
+static GtkWidget *
+hig_dialog_new (GtkWindow *parent,
+ GtkDialogFlags flags,
+ GtkMessageType type,
+ GtkButtonsType buttons,
+ const gchar *primary_message,
+ const gchar *secondary_message)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ type,
+ buttons,
+ "%s", primary_message);
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", secondary_message);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), "");
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+ gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14);
+
+ return dialog;
+}
+
+/* If in random theme mode then grab a random theme from those selected */
+static char *
+get_random_theme ()
+{
+ char **vec;
+ char *themes_list;
+ char *theme;
+ int size;
+ int i;
+
+ theme = NULL;
+
+ gdm_settings_client_get_string (GDM_KEY_GRAPHICAL_THEMES, &themes_list);
+
+ if (ve_string_empty (themes_list)) {
+ goto out;
+ }
+
+ vec = g_strsplit (themes_list, GDM_DELIMITER_THEMES, -1);
+ if (vec == NULL) {
+ goto out;
+ }
+
+ /* Get Number of elements in vector */
+ for (size = 0; vec[size] != NULL; size++) {}
+
+ /* Get Random Theme from list */
+ srand (time (NULL));
+ i = rand () % size;
+ theme = g_strdup (vec[i]);
+ g_strfreev (vec);
+
+ out:
+ g_free (themes_list);
+
+ return theme;
+}
+
+/*
+ * The buttons with these handlers never appear in the F10 menu,
+ * so they can make use of callback data.
+ */
+static void
+greeter_ok_handler (GreeterItemInfo *info,
+ gpointer user_data)
+{
+ if (ignore_buttons == FALSE) {
+ GreeterItemInfo *entry_info = greeter_lookup_id ("user-pw-entry");
+ if (entry_info && entry_info->item &&
+ GNOME_IS_CANVAS_WIDGET (entry_info->item) &&
+ GTK_IS_ENTRY (GNOME_CANVAS_WIDGET (entry_info->item)->widget))
+ {
+ GtkWidget *entry;
+ entry = GNOME_CANVAS_WIDGET (entry_info->item)->widget;
+ greeter_ignore_buttons (TRUE);
+ greeter_item_pam_login (GTK_ENTRY (entry), entry_info);
+ }
+ }
+}
+
+static void
+greeter_cancel_handler (GreeterItemInfo *info,
+ gpointer user_data)
+{
+ if (ignore_buttons == FALSE) {
+ greeter_item_ulist_unset_selected_user ();
+ greeter_item_ulist_disable ();
+ greeter_ignore_buttons (TRUE);
+#if 0
+ printf ("%c%c%c\n", STX, BEL, GDM_INTERRUPT_CANCEL);
+ fflush (stdout);
+#endif
+
+ }
+}
+
+static void
+greeter_language_handler (GreeterItemInfo *info,
+ gpointer user_data)
+{
+ gdm_lang_handler (user_data);
+}
+
+static void
+greeter_setup_items (GdmThemedGreeter *greeter)
+{
+ greeter_item_clock_setup ();
+ greeter_item_pam_setup (GDM_GREETER (greeter));
+
+#if 0
+ /* This will query the daemon for pictures through stdin/stdout! */
+ greeter_item_ulist_setup ();
+#endif
+
+ greeter_item_capslock_setup (window);
+ greeter_item_timed_setup ();
+ greeter_item_register_action_callback ("ok_button",
+ greeter_ok_handler,
+ (gpointer) window);
+ greeter_item_register_action_callback ("cancel_button",
+ greeter_cancel_handler,
+ (gpointer) window);
+ greeter_item_register_action_callback ("language_button",
+ greeter_language_handler,
+ NULL);
+ greeter_item_register_action_callback ("disconnect_button",
+ (ActionFunc)gtk_main_quit,
+ NULL);
+ greeter_item_system_setup ();
+ greeter_item_session_setup ();
+
+ /* Setup the custom widgets */
+ greeter_item_customlist_setup ();
+}
+
+static void
+gdm_set_welcomemsg (GdmThemedGreeter *greeter)
+{
+ char *welcomemsg = gdm_common_get_welcomemsg ();
+
+ if (welcome_string_info->data.text.orig_text != NULL)
+ g_free (welcome_string_info->data.text.orig_text);
+
+ welcome_string_info->data.text.orig_text = welcomemsg;
+ greeter_item_update_text (welcome_string_info);
+}
+
+static void
+greeter_done (int sig)
+{
+ _exit (EXIT_SUCCESS);
+}
+
+static char *
+get_theme_greeter (const gchar *file,
+ const char *fallback)
+{
+ GKeyFile *config;
+ gchar *s;
+
+ config = g_key_file_new ();
+ if (! g_key_file_load_from_file (config, file, 0, NULL)) {
+ return NULL;
+ }
+
+ s = g_key_file_get_locale_string (config, "GdmGreeterTheme", "Greeter", NULL, NULL);
+
+ if (s == NULL || s[0] == '\0') {
+ g_free (s);
+ s = g_strdup_printf ("%s.xml", fallback);
+ }
+
+ g_key_file_free (config);
+
+ return s;
+}
+static char *
+get_theme_file (const char *in, char **theme_dir)
+{
+ char *file, *dir, *info, *s;
+
+ if (in == NULL)
+ in = "circles";
+
+ *theme_dir = NULL;
+
+ if (g_path_is_absolute (in)) {
+ dir = g_strdup (in);
+ } else {
+ char *graphical_theme_dir;
+
+ gdm_settings_client_get_string (GDM_KEY_GRAPHICAL_THEME_DIR, &graphical_theme_dir);
+ dir = g_build_filename (graphical_theme_dir, in, NULL);
+ g_free (graphical_theme_dir);
+ }
+
+ *theme_dir = dir;
+
+ info = g_build_filename (dir, "GdmGreeterTheme.desktop", NULL);
+ if (g_access (info, F_OK) != 0) {
+ g_free (info);
+ info = g_build_filename (dir, "GdmGreeterTheme.info", NULL);
+ }
+ if (g_access (info, F_OK) != 0) {
+ char *base = g_path_get_basename (in);
+ /* just guess the name, we have no info about the theme at
+ * this point */
+ g_free (info);
+ file = g_strdup_printf ("%s/%s.xml", dir, base);
+ g_free (base);
+ return file;
+ }
+
+ s = get_theme_greeter (info, in);
+ file = g_build_filename (dir, s, NULL);
+
+ g_free (info);
+ g_free (s);
+
+ return file;
+}
+
+/* The reaping stuff */
+static time_t last_reap_delay = 0;
+
+static gboolean
+delay_reaping (GSignalInvocationHint *ihint,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer data)
+{
+ last_reap_delay = time (NULL);
+ return TRUE;
+}
+
+static gboolean
+reap_flexiserver (gpointer data)
+{
+ int reapminutes;
+
+ gdm_settings_client_get_int (GDM_KEY_FLEXI_REAP_DELAY_MINUTES, &reapminutes);
+
+ if (reapminutes > 0 &&
+ ((time (NULL) - last_reap_delay) / 60) > reapminutes) {
+ _exit (DISPLAY_REMANAGE);
+ }
+ return TRUE;
+}
+
+static gboolean
+gdm_event (GSignalInvocationHint *ihint,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer data)
+{
+ GdkEvent *event;
+
+ /* HAAAAAAAAAAAAAAAAACK */
+ /* Since the user has not logged in yet and may have left/right
+ * mouse buttons switched, we just translate every right mouse click
+ * to a left mouse click */
+ if (n_param_values != 2 ||
+ !G_VALUE_HOLDS (&param_values[1], GDK_TYPE_EVENT))
+ return FALSE;
+
+ event = g_value_get_boxed (&param_values[1]);
+ if ((event->type == GDK_BUTTON_PRESS ||
+ event->type == GDK_2BUTTON_PRESS ||
+ event->type == GDK_3BUTTON_PRESS ||
+ event->type == GDK_BUTTON_RELEASE)
+ && event->button.button == 3)
+ event->button.button = 1;
+
+ /* Support Ctrl-U for blanking the username/password entry */
+ if (event->type == GDK_KEY_PRESS &&
+ (event->key.state & GDK_CONTROL_MASK) &&
+ (event->key.keyval == GDK_u ||
+ event->key.keyval == GDK_U)) {
+
+ GreeterItemInfo *entry_info = greeter_lookup_id ("user-pw-entry");
+ if (entry_info && entry_info->item &&
+ GNOME_IS_CANVAS_WIDGET (entry_info->item) &&
+ GTK_IS_ENTRY (GNOME_CANVAS_WIDGET (entry_info->item)->widget))
+ {
+ GtkWidget *entry;
+ entry = GNOME_CANVAS_WIDGET (entry_info->item)->widget;
+ gtk_entry_set_text (GTK_ENTRY (entry), "");
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+gdm_themed_greeter_start (GdmGreeter *greeter)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ GDM_GREETER_CLASS (gdm_themed_greeter_parent_class)->start (greeter);
+
+ return TRUE;
+}
+
+static gboolean
+gdm_themed_greeter_stop (GdmGreeter *greeter)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ GDM_GREETER_CLASS (gdm_themed_greeter_parent_class)->stop (greeter);
+
+ return TRUE;
+}
+
+static gboolean
+gdm_themed_greeter_info (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ GDM_GREETER_CLASS (gdm_themed_greeter_parent_class)->info (greeter, text);
+
+ g_debug ("THEMED GREETER: info: %s", text);
+
+ greeter_item_pam_message (text);
+
+ return TRUE;
+}
+
+static gboolean
+gdm_themed_greeter_problem (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ GDM_GREETER_CLASS (gdm_themed_greeter_parent_class)->problem (greeter, text);
+
+ g_debug ("THEMED GREETER: problem: %s", text);
+
+ greeter_item_pam_error (text);
+
+ return TRUE;
+}
+
+static gboolean
+gdm_themed_greeter_info_query (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ GDM_GREETER_CLASS (gdm_themed_greeter_parent_class)->info_query (greeter, text);
+
+ g_debug ("THEMED GREETER: info query: %s", text);
+
+ if (text != NULL && strcmp (text, _("Username:")) == 0) {
+#if 0
+ gdm_common_login_sound (gdm_config_get_string (GDM_KEY_SOUND_PROGRAM),
+ gdm_config_get_string (GDM_KEY_SOUND_ON_LOGIN_FILE),
+ gdm_config_get_bool (GDM_KEY_SOUND_ON_LOGIN));
+#endif
+ greeter_probably_login_prompt = TRUE;
+ }
+
+ if (gtk_ok_button != NULL)
+ gtk_widget_set_sensitive (GTK_WIDGET (gtk_ok_button), FALSE);
+
+ if (gtk_start_again_button != NULL)
+ gtk_widget_set_sensitive (GTK_WIDGET (gtk_start_again_button), !first_prompt);
+
+ first_prompt = FALSE;
+
+ greeter_ignore_buttons (FALSE);
+
+ greeter_item_pam_prompt (text, PW_ENTRY_SIZE, TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+gdm_themed_greeter_secret_info_query (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ GDM_GREETER_CLASS (gdm_themed_greeter_parent_class)->secret_info_query (greeter, text);
+
+ g_debug ("THEMED GREETER: secret info query: %s", text);
+
+ greeter_probably_login_prompt = FALSE;
+
+ if (gtk_ok_button != NULL)
+ gtk_widget_set_sensitive (GTK_WIDGET (gtk_ok_button), FALSE);
+
+ if (gtk_start_again_button != NULL)
+ gtk_widget_set_sensitive (GTK_WIDGET (gtk_start_again_button), !first_prompt);
+
+ first_prompt = FALSE;
+
+ greeter_ignore_buttons (FALSE);
+ greeter_item_pam_prompt (text, PW_ENTRY_SIZE, FALSE);
+
+ return TRUE;
+}
+
+static void
+gdm_themed_greeter_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GdmThemedGreeter *self;
+
+ self = GDM_THEMED_GREETER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdm_themed_greeter_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GdmThemedGreeter *self;
+
+ self = GDM_THEMED_GREETER (object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+create_greeter (GdmThemedGreeter *greeter)
+{
+ char *bg_color;
+ struct sigaction hup;
+ struct sigaction term;
+ sigset_t mask;
+ GError *error;
+ char *theme_file;
+ char *theme_dir;
+ char *gdm_graphical_theme;
+ char *gdm_gtk_theme;
+ guint sid;
+ int r;
+ gint i;
+ int delay;
+ gboolean rand_theme;
+
+ gdm_common_setup_cursor (GDK_WATCH);
+
+ {
+ char *gtkrc;
+ gdm_settings_client_get_string (GDM_KEY_GTKRC, &gtkrc);
+ if (gtkrc != NULL) {
+ gtk_rc_parse (gtkrc);
+ }
+ g_free (gtkrc);
+ }
+
+ gdm_gtk_theme = g_strdup (g_getenv ("GDM_GTK_THEME"));
+ if (ve_string_empty (gdm_gtk_theme)) {
+ gdm_settings_client_get_string (GDM_KEY_GTK_THEME, &gdm_gtk_theme);
+ }
+
+ if ( ! ve_string_empty (gdm_gtk_theme)) {
+ gdm_set_theme (gdm_gtk_theme);
+ }
+ g_free (gdm_gtk_theme);
+
+ {
+ int screen;
+ gdm_settings_client_get_int (GDM_KEY_XINERAMA_SCREEN, &screen);
+ gdm_wm_screen_init (screen);
+ }
+
+ /* Load the background as early as possible so GDM does not leave */
+ /* the background unfilled. The cursor should be a watch already */
+ /* but just in case */
+ bg_color = NULL;
+ gdm_settings_client_get_string (GDM_KEY_GRAPHICAL_THEMED_COLOR, &bg_color);
+
+ /* If a graphical theme color does not exist fallback to the plain color */
+ if (ve_string_empty (bg_color)) {
+ g_free (bg_color);
+ bg_color = NULL;
+ gdm_settings_client_get_string (GDM_KEY_BACKGROUND_COLOR, &bg_color);
+ }
+ gdm_common_setup_background_color (bg_color);
+ g_free (bg_color);
+
+ greeter_session_init ();
+
+ {
+ char *locale_file;
+ gdm_settings_client_get_string (GDM_KEY_LOCALE_FILE, &locale_file);
+ gdm_lang_initialize_model (locale_file);
+ g_free (locale_file);
+ }
+
+ hup.sa_handler = ve_signal_notify;
+ hup.sa_flags = 0;
+ sigemptyset (&hup.sa_mask);
+ sigaddset (&hup.sa_mask, SIGCHLD);
+
+ if (sigaction (SIGHUP, &hup, NULL) < 0) {
+ gdm_common_fail_greeter ("%s: Error setting up %s signal handler: %s", "main",
+ "HUP", strerror (errno));
+ }
+
+ term.sa_handler = greeter_done;
+ term.sa_flags = 0;
+ sigemptyset (&term.sa_mask);
+ sigaddset (&term.sa_mask, SIGCHLD);
+
+ if G_UNLIKELY (sigaction (SIGINT, &term, NULL) < 0) {
+ gdm_common_fail_greeter ("%s: Error setting up %s signal handler: %s", "main",
+ "INT", strerror (errno));
+ }
+
+ if G_UNLIKELY (sigaction (SIGTERM, &term, NULL) < 0) {
+ gdm_common_fail_greeter ("%s: Error setting up %s signal handler: %s", "main",
+ "TERM", strerror (errno));
+ }
+
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGTERM);
+ sigaddset (&mask, SIGHUP);
+ sigaddset (&mask, SIGINT);
+
+ if G_UNLIKELY (sigprocmask (SIG_UNBLOCK, &mask, NULL) == -1) {
+ gdm_common_fail_greeter ("Could not set signal mask!");
+ }
+
+ /* ignore SIGCHLD */
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGCHLD);
+
+ if G_UNLIKELY (sigprocmask (SIG_BLOCK, &mask, NULL) == -1) {
+ gdm_common_fail_greeter ("Could not set signal mask!");
+ }
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ canvas = gnome_canvas_new_aa ();
+ GTK_WIDGET_UNSET_FLAGS (canvas, GTK_CAN_FOCUS);
+ gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas),
+ 0.0, 0.0,
+ (double) gdm_wm_screen.width,
+ (double) gdm_wm_screen.height);
+ gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
+ gtk_window_set_default_size (GTK_WINDOW (window),
+ gdm_wm_screen.width,
+ gdm_wm_screen.height);
+ gtk_container_add (GTK_CONTAINER (window), canvas);
+
+ /*
+ * Initialize the value with the default value so the first time it
+ * is displayed it doesn't show as 0. Also determine if the Halt,
+ * Reboot, Suspend and Configurator commands work.
+ */
+ gdm_settings_client_get_int (GDM_KEY_TIMED_LOGIN_DELAY, &gdm_timed_delay);
+
+ {
+ char *halt;
+ char *reboot;
+ char *suspend;
+ char *configurator;
+
+ gdm_settings_client_get_string (GDM_KEY_HALT, &halt);
+ gdm_settings_client_get_string (GDM_KEY_REBOOT, &reboot);
+ gdm_settings_client_get_string (GDM_KEY_SUSPEND, &suspend);
+ gdm_settings_client_get_string (GDM_KEY_CONFIGURATOR, &configurator);
+ GdmHaltFound = gdm_working_command_exists (halt);
+ GdmRebootFound = gdm_working_command_exists (reboot);
+ GdmSuspendFound = gdm_working_command_exists (suspend);
+ GdmConfiguratorFound = gdm_working_command_exists (configurator);
+
+ g_free (configurator);
+ g_free (suspend);
+ g_free (reboot);
+ g_free (halt);
+ }
+
+ GdmCustomCmdsFound = g_new0 (gboolean, GDM_CUSTOM_COMMAND_MAX);
+ for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
+ char *key_string = NULL;
+ char *val;
+
+ /* For each possible custom command */
+ key_string = g_strdup_printf ("%s%d", GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
+
+ gdm_settings_client_get_string (key_string, &val);
+ GdmCustomCmdsFound[i] = gdm_working_command_exists (val);
+ if (GdmCustomCmdsFound[i])
+ GdmAnyCustomCmdsFound = TRUE;
+
+ g_free (val);
+ g_free (key_string);
+ }
+
+ gdm_settings_client_get_boolean (GDM_KEY_GRAPHICAL_THEME_RAND, &rand_theme);
+ if (g_getenv ("GDM_THEME") != NULL) {
+ gdm_graphical_theme = g_strdup (g_getenv ("GDM_THEME"));
+ } else if (rand_theme) {
+ gdm_graphical_theme = get_random_theme ();
+ } else {
+ gdm_settings_client_get_string (GDM_KEY_GRAPHICAL_THEME, &gdm_graphical_theme);
+ }
+
+ theme_file = get_theme_file (gdm_graphical_theme, &theme_dir);
+
+ error = NULL;
+ root = greeter_parse (theme_file,
+ theme_dir,
+ GNOME_CANVAS (canvas),
+ gdm_wm_screen.width,
+ gdm_wm_screen.height,
+ &error);
+
+ if (root == NULL) {
+ GtkWidget *dialog;
+ char *s;
+ char *tmp;
+
+ gdm_wm_init (0);
+ gdm_wm_focus_new_windows (TRUE);
+
+ tmp = ve_filename_to_utf8 (ve_sure_string (gdm_graphical_theme));
+ s = g_strdup_printf (_("There was an error loading the "
+ "theme %s"), tmp);
+ g_free (tmp);
+ dialog = hig_dialog_new (NULL /* parent */,
+ GTK_DIALOG_MODAL /* flags */,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ s,
+ (error && error->message) ? error->message : "");
+ g_free (s);
+
+ gtk_widget_show_all (dialog);
+ gdm_wm_center_window (GTK_WINDOW (dialog));
+
+ gdm_common_setup_cursor (GDK_LEFT_PTR);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ }
+
+ g_free (gdm_graphical_theme);
+
+ if G_UNLIKELY (error)
+ g_clear_error (&error);
+
+ /* Try circles.xml */
+ if (root == NULL) {
+ g_free (theme_file);
+ g_free (theme_dir);
+ theme_file = get_theme_file ("circles", &theme_dir);
+ root = greeter_parse (theme_file,
+ theme_dir,
+ GNOME_CANVAS (canvas),
+ gdm_wm_screen.width,
+ gdm_wm_screen.height,
+ NULL);
+ }
+
+ g_free (theme_file);
+
+ if (root != NULL && greeter_lookup_id ("user-pw-entry") == NULL) {
+ GtkWidget *dialog;
+
+ gdm_wm_init (0);
+ gdm_wm_focus_new_windows (TRUE);
+
+ dialog = hig_dialog_new (NULL /* parent */,
+ GTK_DIALOG_MODAL /* flags */,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("The greeter theme is corrupt"),
+ _("The theme does not contain "
+ "definition for the username/password "
+ "entry element."));
+
+ gtk_widget_show_all (dialog);
+ gdm_wm_center_window (GTK_WINDOW (dialog));
+
+ gdm_common_setup_cursor (GDK_LEFT_PTR);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ root = NULL;
+ }
+
+ if (root == NULL) {
+ GtkWidget *dialog;
+
+ gdm_wm_init (0);
+ gdm_wm_focus_new_windows (TRUE);
+
+ dialog = hig_dialog_new (NULL /* parent */,
+ GTK_DIALOG_MODAL /* flags */,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("There was an error loading the "
+ "theme, and the default theme "
+ "could not be loaded. "
+ "Attempting to start the "
+ "standard greeter"),
+ "");
+
+ gtk_widget_show_all (dialog);
+ gdm_wm_center_window (GTK_WINDOW (dialog));
+
+ gdm_common_setup_cursor (GDK_LEFT_PTR);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ execl (LIBEXECDIR "/gdmlogin", LIBEXECDIR "/gdmlogin", NULL);
+ execlp ("gdmlogin", "gdmlogin", NULL);
+
+ dialog = hig_dialog_new (NULL /* parent */,
+ GTK_DIALOG_MODAL /* flags */,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("The GTK+ greeter could not be started. "
+ "This display will abort and you may "
+ "have to login another way and fix the "
+ "installation of GDM"),
+ "");
+
+ gtk_widget_show_all (dialog);
+ gdm_wm_center_window (GTK_WINDOW (dialog));
+
+ gdm_common_setup_cursor (GDK_LEFT_PTR);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ _exit (DISPLAY_ABORT);
+ }
+
+ greeter_layout (root, GNOME_CANVAS (canvas));
+
+ greeter_setup_items (greeter);
+
+
+ gdm_common_setup_blinking ();
+
+ gtk_widget_show_all (window);
+ gtk_window_move (GTK_WINDOW (window), gdm_wm_screen.x, gdm_wm_screen.y);
+ gtk_widget_show_now (window);
+
+ greeter_item_ulist_unset_selected_user ();
+ greeter_item_ulist_enable ();
+ greeter_item_ulist_check_show_userlist ();
+
+ /* can it ever happen that it'd be NULL here ??? */
+ if (window->window != NULL) {
+ gdm_wm_init (GDK_WINDOW_XWINDOW (window->window));
+
+ /* Run the focus, note that this will work no matter what
+ * since gdm_wm_init will set the display to the gdk one
+ * if it fails */
+ gdm_wm_focus_window (GDK_WINDOW_XWINDOW (window->window));
+ }
+
+ if G_UNLIKELY (session_dir_whacked_out) {
+ GtkWidget *dialog;
+
+ gdm_wm_focus_new_windows (TRUE);
+
+ dialog = hig_dialog_new (NULL /* parent */,
+ GTK_DIALOG_MODAL /* flags */,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("Session directory is missing"),
+ _("Your session directory is missing or empty! "
+ "There are two available sessions you can use, but "
+ "you should log in and correct the gdm configuration."));
+ gtk_widget_show_all (dialog);
+ gdm_wm_center_window (GTK_WINDOW (dialog));
+
+ gdm_common_setup_cursor (GDK_LEFT_PTR);
+
+ gdm_wm_no_login_focus_push ();
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ gdm_wm_no_login_focus_pop ();
+ }
+
+ if G_UNLIKELY (g_getenv ("GDM_WHACKED_GREETER_CONFIG") != NULL) {
+ GtkWidget *dialog;
+
+ gdm_wm_focus_new_windows (TRUE);
+
+ dialog = hig_dialog_new (NULL /* parent */,
+ GTK_DIALOG_MODAL /* flags */,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("Configuration is not correct"),
+ _("The configuration file contains an invalid command "
+ "line for the login dialog, so running the "
+ "default command. Please fix your configuration."));
+
+ gtk_widget_show_all (dialog);
+ gdm_wm_center_window (GTK_WINDOW (dialog));
+
+ gdm_common_setup_cursor (GDK_LEFT_PTR);
+
+ gdm_wm_no_login_focus_push ();
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ gdm_wm_no_login_focus_pop ();
+ }
+
+ /* if a flexiserver, reap self after some time */
+ gdm_settings_client_get_int (GDM_KEY_FLEXI_REAP_DELAY_MINUTES, &delay);
+ if (delay > 0 && ! ve_string_empty (g_getenv ("GDM_FLEXI_SERVER")) &&
+ /* but don't reap Xnest flexis */
+ ve_string_empty (g_getenv ("GDM_PARENT_DISPLAY"))) {
+ sid = g_signal_lookup ("activate",
+ GTK_TYPE_MENU_ITEM);
+ g_signal_add_emission_hook (sid,
+ 0 /* detail */,
+ delay_reaping,
+ NULL /* data */,
+ NULL /* destroy_notify */);
+
+ sid = g_signal_lookup ("key_press_event",
+ GTK_TYPE_WIDGET);
+ g_signal_add_emission_hook (sid,
+ 0 /* detail */,
+ delay_reaping,
+ NULL /* data */,
+ NULL /* destroy_notify */);
+
+ sid = g_signal_lookup ("button_press_event",
+ GTK_TYPE_WIDGET);
+ g_signal_add_emission_hook (sid,
+ 0 /* detail */,
+ delay_reaping,
+ NULL /* data */,
+ NULL /* destroy_notify */);
+
+ last_reap_delay = time (NULL);
+ g_timeout_add (60*1000, reap_flexiserver, NULL);
+ }
+
+ sid = g_signal_lookup ("event",
+ GTK_TYPE_WIDGET);
+ g_signal_add_emission_hook (sid,
+ 0 /* detail */,
+ gdm_event,
+ NULL /* data */,
+ NULL /* destroy_notify */);
+
+ gdm_wm_restore_wm_order ();
+
+ {
+ char *msg_file;
+ char *msg_font;
+
+ gdm_settings_client_get_string (GDM_KEY_INFO_MSG_FILE, &msg_file);
+ gdm_settings_client_get_string (GDM_KEY_INFO_MSG_FONT, &msg_font);
+
+ gdm_wm_show_info_msg_dialog (msg_file, msg_font);
+ g_free (msg_font);
+ g_free (msg_file);
+ }
+
+ gdm_common_setup_cursor (GDK_LEFT_PTR);
+ gdm_wm_center_cursor ();
+ gdm_common_pre_fetch_launch ();
+}
+
+static GObject *
+gdm_themed_greeter_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GdmThemedGreeter *greeter;
+ GdmThemedGreeterClass *klass;
+
+ klass = GDM_THEMED_GREETER_CLASS (g_type_class_peek (GDM_TYPE_THEMED_GREETER));
+
+ greeter = GDM_GREETER (G_OBJECT_CLASS (gdm_themed_greeter_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+ create_greeter (greeter);
+
+ return G_OBJECT (greeter);
+}
+
+static void
+gdm_themed_greeter_class_init (GdmThemedGreeterClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdmGreeterClass *greeter_class = GDM_GREETER_CLASS (klass);
+
+ object_class->get_property = gdm_themed_greeter_get_property;
+ object_class->set_property = gdm_themed_greeter_set_property;
+ object_class->constructor = gdm_themed_greeter_constructor;
+ object_class->finalize = gdm_themed_greeter_finalize;
+
+ greeter_class->start = gdm_themed_greeter_start;
+ greeter_class->stop = gdm_themed_greeter_stop;
+ greeter_class->info = gdm_themed_greeter_info;
+ greeter_class->problem = gdm_themed_greeter_problem;
+ greeter_class->info_query = gdm_themed_greeter_info_query;
+ greeter_class->secret_info_query = gdm_themed_greeter_secret_info_query;
+
+ g_type_class_add_private (klass, sizeof (GdmThemedGreeterPrivate));
+}
+
+static void
+gdm_themed_greeter_init (GdmThemedGreeter *themed_greeter)
+{
+
+ themed_greeter->priv = GDM_THEMED_GREETER_GET_PRIVATE (themed_greeter);
+
+}
+
+static void
+gdm_themed_greeter_finalize (GObject *object)
+{
+ GdmThemedGreeter *themed_greeter;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GDM_IS_THEMED_GREETER (object));
+
+ themed_greeter = GDM_THEMED_GREETER (object);
+
+ g_return_if_fail (themed_greeter->priv != NULL);
+
+ G_OBJECT_CLASS (gdm_themed_greeter_parent_class)->finalize (object);
+}
+
+GdmGreeter *
+gdm_themed_greeter_new (void)
+{
+ GObject *object;
+
+ object = g_object_new (GDM_TYPE_THEMED_GREETER,
+ NULL);
+
+ return GDM_GREETER (object);
+}
diff --git a/gui/greeter/gdm-themed-greeter.h b/gui/greeter/gdm-themed-greeter.h
new file mode 100644
index 00000000..0b49b26c
--- /dev/null
+++ b/gui/greeter/gdm-themed-greeter.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; 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_THEMED_GREETER_H
+#define __GDM_THEMED_GREETER_H
+
+#include <glib-object.h>
+
+#include "gdm-greeter.h"
+
+G_BEGIN_DECLS
+
+#define GDM_TYPE_THEMED_GREETER (gdm_themed_greeter_get_type ())
+#define GDM_THEMED_GREETER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_THEMED_GREETER, GdmThemedGreeter))
+#define GDM_THEMED_GREETER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_THEMED_GREETER, GdmThemedGreeterClass))
+#define GDM_IS_THEMED_GREETER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_THEMED_GREETER))
+#define GDM_IS_THEMED_GREETER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_THEMED_GREETER))
+#define GDM_THEMED_GREETER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_THEMED_GREETER, GdmThemedGreeterClass))
+
+typedef struct GdmThemedGreeterPrivate GdmThemedGreeterPrivate;
+
+typedef struct
+{
+ GdmGreeter parent;
+ GdmThemedGreeterPrivate *priv;
+} GdmThemedGreeter;
+
+typedef struct
+{
+ GdmGreeterClass parent_class;
+
+} GdmThemedGreeterClass;
+
+GType gdm_themed_greeter_get_type (void);
+GdmGreeter * gdm_themed_greeter_new (void);
+
+
+G_END_DECLS
+
+#endif /* __GDM_THEMED_GREETER_H */
diff --git a/gui/greeter/greeter.c b/gui/greeter/greeter.c
index 63bc4c86..3a0ec4ff 100644
--- a/gui/greeter/greeter.c
+++ b/gui/greeter/greeter.c
@@ -20,6 +20,7 @@
#include "config.h"
+#include <stdlib.h>
#include <libintl.h>
#include <locale.h>
#include <string.h>
@@ -36,985 +37,101 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
-
-#include <libgnomecanvas/libgnomecanvas.h>
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
#include "gdm-common.h"
-#include "gdm-socket-protocol.h"
#include "gdm-settings-client.h"
#include "gdm-settings-keys.h"
-#include "gdm.h"
-#include "gdmwm.h"
-#include "gdmcommon.h"
-#include "gdmsession.h"
-#include "gdmlanguages.h"
-
-#include "greeter.h"
-#include "greeter_configuration.h"
-#include "greeter_parser.h"
-#include "greeter_geometry.h"
-#include "greeter_item_clock.h"
-#include "greeter_item_pam.h"
-#include "greeter_item_ulist.h"
-#include "greeter_item_customlist.h"
-#include "greeter_item_capslock.h"
-#include "greeter_item_timed.h"
-#include "greeter_events.h"
-#include "greeter_session.h"
-#include "greeter_system.h"
-
-gboolean DOING_GDM_DEVELOPMENT = FALSE;
-
-GtkWidget *window;
-GtkWidget *canvas;
-
-gboolean GDM_IS_LOCAL = FALSE;
-static gboolean ignore_buttons = FALSE;
-gboolean GdmHaltFound = FALSE;
-gboolean GdmRebootFound = FALSE;
-gboolean *GdmCustomCmdsFound = NULL;
-gboolean GdmAnyCustomCmdsFound = FALSE;
-gboolean GdmSuspendFound = FALSE;
-gboolean GdmConfiguratorFound = FALSE;
-
-/* FIXME: hack */
-GreeterItemInfo *welcome_string_info = NULL;
-GreeterItemInfo *root = NULL;
-
-extern gboolean session_dir_whacked_out;
-extern gboolean require_quarter;
-extern gint gdm_timed_delay;
-extern GtkButton *gtk_ok_button;
-extern GtkButton *gtk_start_again_button;
-
-gboolean greeter_probably_login_prompt = FALSE;
-static gboolean first_prompt = TRUE;
-
-static void process_operation (guchar opcode, const gchar *args);
-
-void
-greeter_ignore_buttons (gboolean val)
-{
- ignore_buttons = val;
-}
-
-/* If in random theme mode then grab a random theme from those selected */
-static char *
-get_random_theme ()
-{
- char **vec;
- char *themes_list;
- char *theme;
- int size;
- int i;
-
- theme = NULL;
-
- gdm_settings_client_get_string (GDM_KEY_GRAPHICAL_THEMES, &themes_list);
-
- if (ve_string_empty (themes_list)) {
- goto out;
- }
-
- vec = g_strsplit (themes_list, GDM_DELIMITER_THEMES, -1);
- if (vec == NULL) {
- goto out;
- }
-
- /* Get Number of elements in vector */
- for (size = 0; vec[size] != NULL; size++) {}
+#include "gdm-themed-greeter.h"
- /* Get Random Theme from list */
- srand (time (NULL));
- i = rand () % size;
- theme = g_strdup (vec[i]);
- g_strfreev (vec);
-
- out:
- g_free (themes_list);
-
- return theme;
-}
-
-static gboolean
-greeter_ctrl_handler (GIOChannel *source,
- GIOCondition cond,
- gint fd)
-{
- gchar buf[PIPE_SIZE];
- gchar *p;
- gsize len;
-
- /* If this is not incoming i/o then return */
- if (cond != G_IO_IN)
- return TRUE;
-
- /* Read random garbage from i/o channel until first STX is found */
- do {
- g_io_channel_read_chars (source, buf, 1, &len, NULL);
-
- if (len != 1)
- return TRUE;
- } while (buf[0] && buf[0] != STX);
-
- memset (buf, '\0', sizeof (buf));
- if (g_io_channel_read_chars (source, buf, sizeof (buf) - 1, &len, NULL) !=
- G_IO_STATUS_NORMAL)
- return TRUE;
-
- p = memchr (buf, STX, len);
- if (p != NULL) {
- len = p - buf;
- g_io_channel_seek_position (source, -((sizeof (buf) - 1) - len), G_SEEK_CUR, NULL);
- memset (buf + len, '\0', (sizeof (buf) - 1) - len);
- }
- buf[len - 1] = '\0';
-
- process_operation ((guchar) buf[0], buf + 1);
- return TRUE;
-}
-
-static GtkWidget *
-hig_dialog_new (GtkWindow *parent,
- GtkDialogFlags flags,
- GtkMessageType type,
- GtkButtonsType buttons,
- const gchar *primary_message,
- const gchar *secondary_message)
-{
- GtkWidget *dialog;
-
- dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- type,
- buttons,
- "%s", primary_message);
-
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- "%s", secondary_message);
+#include "gdmcommon.h"
- gtk_window_set_title (GTK_WINDOW (dialog), "");
- gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
- gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14);
+#define SERVER_DBUS_PATH "/org/gnome/DisplayManager/GreeterServer"
+#define SERVER_DBUS_INTERFACE "org.gnome.DisplayManager.GreeterServer"
- return dialog;
-}
+static DBusGProxy *settings_proxy = NULL;
+static DBusGConnection *connection = NULL;
+static GdmThemedGreeter *greeter = NULL;
+static DBusGProxy *server_proxy = NULL;
static void
-process_operation (guchar op_code,
- const gchar *args)
+on_info (DBusGProxy *proxy,
+ const char *text,
+ gpointer data)
{
- GtkWidget *dlg;
- char *tmp;
- char *session;
- GreeterItemInfo *conversation_info;
- static GnomeCanvasItem *disabled_cover = NULL;
- gint lookup_status = SESSION_LOOKUP_SUCCESS;
- gchar *firstmsg = NULL;
- gchar *secondmsg = NULL;
- gint save_session = GTK_RESPONSE_NO;
-
- /* Parse opcode */
- switch (op_code) {
- case GDM_SETLOGIN:
- /* somebody is trying to fool us this is the user that
- * wants to log in, and well, we are the gullible kind */
-
- greeter_item_pam_set_user (args);
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- case GDM_PROMPT:
- tmp = ve_locale_to_utf8 (args);
- if (tmp != NULL && strcmp (tmp, _("Username:")) == 0) {
- char *sound_prog;
- char *sound_file;
- gboolean sound_on_login;
-
- gdm_settings_client_get_string (GDM_KEY_SOUND_PROGRAM, &sound_prog);
- gdm_settings_client_get_string (GDM_KEY_SOUND_ON_LOGIN_FILE, &sound_file);
- gdm_settings_client_get_boolean (GDM_KEY_SOUND_ON_LOGIN, &sound_on_login);
-
- gdm_common_login_sound (sound_prog, sound_file, sound_on_login);
- g_free (sound_file);
- g_free (sound_prog);
-
- greeter_probably_login_prompt = TRUE;
- }
- if (gtk_ok_button != NULL)
- gtk_widget_set_sensitive (GTK_WIDGET (gtk_ok_button), FALSE);
-
- if (gtk_start_again_button != NULL)
- gtk_widget_set_sensitive (GTK_WIDGET (gtk_start_again_button), !first_prompt);
-
- first_prompt = FALSE;
-
- greeter_ignore_buttons (FALSE);
-
- greeter_item_pam_prompt (tmp, PW_ENTRY_SIZE, TRUE);
- g_free (tmp);
- break;
-
- case GDM_NOECHO:
- tmp = ve_locale_to_utf8 (args);
-
- greeter_probably_login_prompt = FALSE;
-
- if (gtk_ok_button != NULL)
- gtk_widget_set_sensitive (GTK_WIDGET (gtk_ok_button), FALSE);
-
- if (gtk_start_again_button != NULL)
- gtk_widget_set_sensitive (GTK_WIDGET (gtk_start_again_button), !first_prompt);
-
- first_prompt = FALSE;
-
- greeter_ignore_buttons (FALSE);
- greeter_item_pam_prompt (tmp, PW_ENTRY_SIZE, FALSE);
- g_free (tmp);
-
- break;
-
- case GDM_MSG:
- tmp = ve_locale_to_utf8 (args);
- greeter_item_pam_message (tmp);
- g_free (tmp);
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- case GDM_ERRBOX:
- tmp = ve_locale_to_utf8 (args);
- greeter_item_pam_error (tmp);
- g_free (tmp);
-
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- case GDM_ERRDLG:
- /* we should be now fine for focusing new windows */
- gdm_wm_focus_new_windows (TRUE);
-
- tmp = ve_locale_to_utf8 (args);
- dlg = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- tmp,
- "");
- g_free (tmp);
-
- gdm_wm_center_window (GTK_WINDOW (dlg));
-
- gdm_wm_no_login_focus_push ();
- gtk_dialog_run (GTK_DIALOG (dlg));
- gtk_widget_destroy (dlg);
- gdm_wm_no_login_focus_pop ();
-
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- case GDM_SESS:
- tmp = ve_locale_to_utf8 (args);
- session = gdm_session_lookup (tmp, &lookup_status);
- if (lookup_status != SESSION_LOOKUP_SUCCESS) {
- switch (lookup_status) {
- case SESSION_LOOKUP_PREFERRED_MISSING:
- firstmsg = g_strdup_printf (_("Do you wish to make %s the default for "
- "future sessions?"),
- gdm_session_name (tmp));
- secondmsg = g_strdup_printf (_("Your preferred session type %s is not "
- "installed on this computer."),
- gdm_session_name (gdm_get_default_session ()));
- save_session = gdm_wm_query_dialog (firstmsg, secondmsg,
- _("Make _Default"), _("Just _Log In"), TRUE);
-
- g_free (firstmsg);
- g_free (secondmsg);
- gdm_set_save_session (save_session);
- break;
-
- case SESSION_LOOKUP_DEFAULT_MISMATCH:
- firstmsg = g_strdup_printf (_("Do you wish to make %s the default for "
- "future sessions?"),
- gdm_session_name (session));
- secondmsg = g_strdup_printf (_("You have chosen %s for this "
- "session, but your default "
- "setting is %s."),
- gdm_session_name (session),
- gdm_session_name (tmp));
- save_session = gdm_wm_query_dialog (firstmsg, secondmsg,
- _("Make _Default"), _("Just For _This Session"), TRUE);
-
- g_free (firstmsg);
- g_free (secondmsg);
- gdm_set_save_session (save_session);
- break;
- case SESSION_LOOKUP_USE_SWITCHDESK:
- firstmsg = g_strdup_printf (_("You have chosen %s for this "
- "session"),
- gdm_session_name (session));
- secondmsg = g_strdup_printf (_("If you wish to make %s "
- "the default for future sessions, "
- "run the 'switchdesk' utility "
- "(System->Desktop Switching Tool from "
- "the panel menu)."),
- gdm_session_name (session));
- gdm_wm_message_dialog (firstmsg, secondmsg);
- g_free (firstmsg);
- g_free (secondmsg);
- break;
-
- default:
- break;
- }
- }
- g_free (tmp);
- if (gdm_get_save_session () == GTK_RESPONSE_CANCEL) {
- printf ("%c%s\n", STX, GDM_RESPONSE_CANCEL);
- } else {
- tmp = ve_locale_from_utf8 (session);
- printf ("%c%s\n", STX, tmp);
- g_free (tmp);
- }
- fflush (stdout);
- g_free (session);
- break;
-
- case GDM_LANG:
- gdm_lang_op_lang (args);
- break;
-
- case GDM_SSESS:
- if (gdm_get_save_session () == GTK_RESPONSE_YES)
- printf ("%cY\n", STX);
- else
- printf ("%c\n", STX);
- fflush (stdout);
-
- break;
-
- case GDM_SLANG:
- gdm_lang_op_slang (args);
- break;
-
- case GDM_SETLANG:
- gdm_lang_op_setlang (args);
- break;
-
- case GDM_ALWAYS_RESTART:
- gdm_lang_op_always_restart (args);
- break;
-
- case GDM_RESET:
- /* fall thru to reset */
-
- case GDM_RESETOK:
-
- if (gtk_ok_button != NULL)
- gtk_widget_set_sensitive (GTK_WIDGET (gtk_ok_button), FALSE);
- if (gtk_start_again_button != NULL)
- gtk_widget_set_sensitive (GTK_WIDGET (gtk_start_again_button), FALSE);
-
- first_prompt = TRUE;
-
- conversation_info = greeter_lookup_id ("pam-conversation");
-
- if (conversation_info) {
- tmp = ve_locale_to_utf8 (args);
- g_object_set (G_OBJECT (conversation_info->item),
- "text", tmp,
- NULL);
- g_free (tmp);
- }
+ g_debug ("GREETER INFO: %s", text);
- printf ("%c\n", STX);
- fflush (stdout);
- greeter_ignore_buttons (FALSE);
- greeter_item_ulist_enable ();
-
- break;
-
- case GDM_QUIT:
- greeter_item_timed_stop ();
-
- if (require_quarter) {
- /* we should be now fine for focusing new windows */
- gdm_wm_focus_new_windows (TRUE);
-
- dlg = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_OK,
- /* translators: This is a nice and evil eggie text, translate
- * to your favourite currency */
- _("Please insert 25 cents "
- "to log in."),
- "");
- gdm_wm_center_window (GTK_WINDOW (dlg));
-
- gdm_wm_no_login_focus_push ();
- gtk_dialog_run (GTK_DIALOG (dlg));
- gtk_widget_destroy (dlg);
- gdm_wm_no_login_focus_pop ();
- }
-
- greeter_item_pam_leftover_messages ();
-
- gdk_flush ();
-
- if (greeter_show_only_background (root)) {
- GdkPixbuf *background;
- int width, height;
-
- gtk_window_get_size (GTK_WINDOW (window), &width, &height);
- background = gdk_pixbuf_get_from_drawable (NULL, gtk_widget_get_root_window(window), NULL, 0, 0, 0, 0 ,width, height);
- if (background) {
- gdm_common_set_root_background (background);
- g_object_unref (background);
- }
- }
-
- printf ("%c\n", STX);
- fflush (stdout);
-
- /* screw gtk_main_quit, we want to make sure we definately die */
- _exit (EXIT_SUCCESS);
- break;
-
- case GDM_STARTTIMER:
- greeter_item_timed_start ();
-
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- case GDM_STOPTIMER:
- greeter_item_timed_stop ();
-
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- case GDM_DISABLE:
- gtk_widget_set_sensitive (window, FALSE);
-
- if (disabled_cover == NULL)
- {
- disabled_cover = gnome_canvas_item_new
- (gnome_canvas_root (GNOME_CANVAS (canvas)),
- GNOME_TYPE_CANVAS_RECT,
- "x1", 0.0,
- "y1", 0.0,
- "x2", (double)canvas->allocation.width,
- "y2", (double)canvas->allocation.height,
- "fill_color_rgba", (guint)0x00000088,
- NULL);
- }
-
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- case GDM_ENABLE:
- gtk_widget_set_sensitive (window, TRUE);
-
- if (disabled_cover != NULL)
- {
- gtk_object_destroy (GTK_OBJECT (disabled_cover));
- disabled_cover = NULL;
- }
-
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- /* These are handled separately so ignore them here and send
- * back a NULL response so that the daemon quits sending them */
- case GDM_NEEDPIC:
- case GDM_READPIC:
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- case GDM_NOFOCUS:
- gdm_wm_no_login_focus_push ();
-
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- case GDM_FOCUS:
- gdm_wm_no_login_focus_pop ();
-
- printf ("%c\n", STX);
- fflush (stdout);
- break;
-
- case GDM_SAVEDIE:
- /* Set busy cursor */
- gdm_common_setup_cursor (GDK_WATCH);
-
- gdm_wm_save_wm_order ();
-
- gdk_flush ();
-
- _exit (EXIT_SUCCESS);
-
- case GDM_QUERY_CAPSLOCK:
- if (greeter_is_capslock_on ())
- printf ("%cY\n", STX);
- else
- printf ("%c\n", STX);
- fflush (stdout);
-
- break;
-
- default:
- gdm_common_fail_greeter ("Unexpected greeter command received: '%c'", op_code);
- break;
- }
-}
-
-static gboolean
-key_press_event (GtkWidget *widget, GdkEventKey *key, gpointer data)
-{
- if (DOING_GDM_DEVELOPMENT && (key->keyval == GDK_Escape)) {
- process_operation (GDM_QUIT, NULL);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-/*
- * The buttons with these handlers never appear in the F10 menu,
- * so they can make use of callback data.
- */
-static void
-greeter_ok_handler (GreeterItemInfo *info,
- gpointer user_data)
-{
- if (ignore_buttons == FALSE) {
- GreeterItemInfo *entry_info = greeter_lookup_id ("user-pw-entry");
- if (entry_info && entry_info->item &&
- GNOME_IS_CANVAS_WIDGET (entry_info->item) &&
- GTK_IS_ENTRY (GNOME_CANVAS_WIDGET (entry_info->item)->widget))
- {
- GtkWidget *entry;
- entry = GNOME_CANVAS_WIDGET (entry_info->item)->widget;
- greeter_ignore_buttons (TRUE);
- greeter_item_pam_login (GTK_ENTRY (entry), entry_info);
- }
- }
+ gdm_greeter_info (GDM_GREETER (greeter), text);
}
static void
-greeter_cancel_handler (GreeterItemInfo *info,
- gpointer user_data)
+on_problem (DBusGProxy *proxy,
+ const char *text,
+ gpointer data)
{
- if (ignore_buttons == FALSE) {
- greeter_item_ulist_unset_selected_user ();
- greeter_item_ulist_disable ();
- greeter_ignore_buttons (TRUE);
- printf ("%c%c%c\n", STX, BEL, GDM_INTERRUPT_CANCEL);
- fflush (stdout);
- }
-}
+ g_debug ("GREETER PROBLEM: %s", text);
-static void
-greeter_language_handler (GreeterItemInfo *info,
- gpointer user_data)
-{
- gdm_lang_handler (user_data);
+ gdm_greeter_problem (GDM_GREETER (greeter), text);
}
static void
-greeter_setup_items (void)
+on_info_query (DBusGProxy *proxy,
+ const char *text,
+ gpointer data)
{
- greeter_item_clock_setup ();
- greeter_item_pam_setup ();
-
- /* This will query the daemon for pictures through stdin/stdout! */
- greeter_item_ulist_setup ();
-
- greeter_item_capslock_setup (window);
- greeter_item_timed_setup ();
- greeter_item_register_action_callback ("ok_button",
- greeter_ok_handler,
- (gpointer) window);
- greeter_item_register_action_callback ("cancel_button",
- greeter_cancel_handler,
- (gpointer) window);
- greeter_item_register_action_callback ("language_button",
- greeter_language_handler,
- NULL);
- greeter_item_register_action_callback ("disconnect_button",
- (ActionFunc)gtk_main_quit,
- NULL);
- greeter_item_system_setup ();
- greeter_item_session_setup ();
+ g_debug ("GREETER Info query: %s", text);
- /* Setup the custom widgets */
- greeter_item_customlist_setup ();
-}
-
-enum {
- RESPONSE_RESTART,
- RESPONSE_REBOOT,
- RESPONSE_CLOSE
-};
-
-static int
-verify_gdm_version (void)
-{
- const char *gdm_version;
- const char *gdm_protocol_version;
-
- g_debug ("Checking GDM version");
-
- gdm_version = g_getenv ("GDM_VERSION");
- gdm_protocol_version = g_getenv ("GDM_GREETER_PROTOCOL_VERSION");
-
- if (! DOING_GDM_DEVELOPMENT &&
- ((gdm_protocol_version != NULL &&
- strcmp (gdm_protocol_version, GDM_GREETER_PROTOCOL_VERSION) != 0) ||
- (gdm_protocol_version == NULL &&
- (gdm_version == NULL ||
- strcmp (gdm_version, VERSION) != 0))) &&
- (g_getenv ("GDM_IS_LOCAL") != NULL)) {
- GtkWidget *dialog;
- gchar *msg;
-
- gdm_wm_init (0);
- gdm_wm_focus_new_windows (TRUE);
-
- msg = g_strdup_printf (_("The greeter version (%s) does not match the daemon "
- "version. "
- "You have probably just upgraded GDM. "
- "Please restart the GDM daemon or the computer."),
- VERSION);
-
- dialog = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("Cannot start the greeter"),
- msg);
- g_free (msg);
-
- gtk_widget_show_all (dialog);
- gdm_wm_center_window (GTK_WINDOW (dialog));
-
- gdm_common_setup_cursor (GDK_LEFT_PTR);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-
- return EXIT_SUCCESS;
- }
-
- if (! DOING_GDM_DEVELOPMENT &&
- gdm_protocol_version == NULL &&
- gdm_version == NULL) {
- GtkWidget *dialog;
- gchar *msg;
-
- gdm_wm_init (0);
- gdm_wm_focus_new_windows (TRUE);
-
- msg = g_strdup_printf (_("The greeter version (%s) does not match the daemon "
- "version. "
- "You have probably just upgraded GDM. "
- "Please restart the GDM daemon or the computer."),
- VERSION);
-
- dialog = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_WARNING,
- GTK_BUTTONS_NONE,
- _("Cannot start the greeter"),
- msg);
- g_free (msg);
-
- gtk_dialog_add_buttons (GTK_DIALOG (dialog),
- _("Restart Machine"),
- RESPONSE_REBOOT,
- GTK_STOCK_CLOSE,
- RESPONSE_CLOSE,
- NULL);
-
- gtk_widget_show_all (dialog);
- gdm_wm_center_window (GTK_WINDOW (dialog));
-
- gdm_common_setup_cursor (GDK_LEFT_PTR);
-
- switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
- case RESPONSE_REBOOT:
- gtk_widget_destroy (dialog);
- return DISPLAY_REBOOT;
- default:
- gtk_widget_destroy (dialog);
- return DISPLAY_ABORT;
- }
- }
-
- if (! DOING_GDM_DEVELOPMENT &&
- ((gdm_protocol_version != NULL &&
- strcmp (gdm_protocol_version, GDM_GREETER_PROTOCOL_VERSION) != 0) ||
- (gdm_protocol_version == NULL &&
- strcmp (gdm_version, VERSION) != 0))) {
- GtkWidget *dialog;
- gchar *msg;
-
- gdm_wm_init (0);
- gdm_wm_focus_new_windows (TRUE);
-
- msg = g_strdup_printf (_("The greeter version (%s) does not match the daemon "
- "version (%s). "
- "You have probably just upgraded GDM. "
- "Please restart the GDM daemon or the computer."),
- VERSION, gdm_version);
-
- dialog = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_WARNING,
- GTK_BUTTONS_NONE,
- _("Cannot start the greeter"),
- msg);
- g_free (msg);
-
- gtk_dialog_add_buttons (GTK_DIALOG (dialog),
- _("Restart GDM"),
- RESPONSE_RESTART,
- _("Restart Machine"),
- RESPONSE_REBOOT,
- GTK_STOCK_CLOSE,
- RESPONSE_CLOSE,
- NULL);
-
- gtk_widget_show_all (dialog);
- gdm_wm_center_window (GTK_WINDOW (dialog));
-
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), RESPONSE_RESTART);
-
- gdm_common_setup_cursor (GDK_LEFT_PTR);
-
- switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
- case RESPONSE_RESTART:
- gtk_widget_destroy (dialog);
- return DISPLAY_RESTARTGDM;
- case RESPONSE_REBOOT:
- gtk_widget_destroy (dialog);
- return DISPLAY_REBOOT;
- default:
- gtk_widget_destroy (dialog);
- return DISPLAY_ABORT;
- }
- }
-
- return 0;
+ gdm_greeter_info_query (GDM_GREETER (greeter), text);
}
static void
-gdm_set_welcomemsg (void)
+on_secret_info_query (DBusGProxy *proxy,
+ const char *text,
+ gpointer data)
{
- char *welcomemsg = gdm_common_get_welcomemsg ();
+ g_debug ("GREETER Secret info query: %s", text);
- if (welcome_string_info->data.text.orig_text != NULL)
- g_free (welcome_string_info->data.text.orig_text);
-
- welcome_string_info->data.text.orig_text = welcomemsg;
- greeter_item_update_text (welcome_string_info);
+ gdm_greeter_secret_info_query (GDM_GREETER (greeter), text);
}
static void
-greeter_done (int sig)
-{
- _exit (EXIT_SUCCESS);
-}
-
-static char *
-get_theme_greeter (const gchar *file,
- const char *fallback)
-{
- GKeyFile *config;
- gchar *s;
-
- config = g_key_file_new ();
- if (! g_key_file_load_from_file (config, file, 0, NULL)) {
- return NULL;
- }
-
- s = g_key_file_get_locale_string (config, "GdmGreeterTheme", "Greeter", NULL, NULL);
-
- if (s == NULL || s[0] == '\0') {
- g_free (s);
- s = g_strdup_printf ("%s.xml", fallback);
- }
-
- g_key_file_free (config);
-
- return s;
-}
-static char *
-get_theme_file (const char *in, char **theme_dir)
+on_query_answer (GdmGreeter *greeter,
+ const char *text,
+ gpointer data)
{
- char *file, *dir, *info, *s;
-
- if (in == NULL)
- in = "circles";
+ gboolean res;
+ GError *error;
- *theme_dir = NULL;
-
- if (g_path_is_absolute (in)) {
- dir = g_strdup (in);
- } else {
- dir = NULL;
- if (DOING_GDM_DEVELOPMENT) {
- if (g_access (in, F_OK) == 0) {
- dir = g_strdup (in);
- } else {
- dir = g_build_filename ("themes", in, NULL);
- if (g_access (dir, F_OK) != 0) {
- g_free (dir);
- dir = NULL;
- }
- }
- }
+ g_debug ("GREETER answer: %s", text);
- if (dir == NULL) {
- char *graphical_theme_dir;
-
- gdm_settings_client_get_string (GDM_KEY_GRAPHICAL_THEME_DIR, &graphical_theme_dir);
- dir = g_build_filename (graphical_theme_dir, in, NULL);
- g_free (graphical_theme_dir);
- }
- }
-
- *theme_dir = dir;
-
- info = g_build_filename (dir, "GdmGreeterTheme.desktop", NULL);
- if (g_access (info, F_OK) != 0) {
- g_free (info);
- info = g_build_filename (dir, "GdmGreeterTheme.info", NULL);
- }
- if (g_access (info, F_OK) != 0) {
- char *base = g_path_get_basename (in);
- /* just guess the name, we have no info about the theme at
- * this point */
- g_free (info);
- file = g_strdup_printf ("%s/%s.xml", dir, base);
- g_free (base);
- return file;
- }
-
- s = get_theme_greeter (info, in);
- file = g_build_filename (dir, s, NULL);
-
- g_free (info);
- g_free (s);
-
- return file;
-}
-
-/* The reaping stuff */
-static time_t last_reap_delay = 0;
-
-static gboolean
-delay_reaping (GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue *param_values,
- gpointer data)
-{
- last_reap_delay = time (NULL);
- return TRUE;
-}
-
-static gboolean
-reap_flexiserver (gpointer data)
-{
- int reapminutes;
-
- gdm_settings_client_get_int (GDM_KEY_FLEXI_REAP_DELAY_MINUTES, &reapminutes);
-
- if (reapminutes > 0 &&
- ((time (NULL) - last_reap_delay) / 60) > reapminutes) {
- _exit (DISPLAY_REMANAGE);
+ error = NULL;
+ res = dbus_g_proxy_call (server_proxy,
+ "AnswerQuery",
+ &error,
+ G_TYPE_STRING, text,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (! res) {
+ g_warning ("Unable to send AnswerQuery: %s", error->message);
+ g_error_free (error);
}
- return TRUE;
}
-static gboolean
-gdm_event (GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue *param_values,
- gpointer data)
+static void
+proxy_destroyed (GObject *object,
+ gpointer data)
{
- GdkEvent *event;
-
- /* HAAAAAAAAAAAAAAAAACK */
- /* Since the user has not logged in yet and may have left/right
- * mouse buttons switched, we just translate every right mouse click
- * to a left mouse click */
- if (n_param_values != 2 ||
- !G_VALUE_HOLDS (&param_values[1], GDK_TYPE_EVENT))
- return FALSE;
-
- event = g_value_get_boxed (&param_values[1]);
- if ((event->type == GDK_BUTTON_PRESS ||
- event->type == GDK_2BUTTON_PRESS ||
- event->type == GDK_3BUTTON_PRESS ||
- event->type == GDK_BUTTON_RELEASE)
- && event->button.button == 3)
- event->button.button = 1;
-
- /* Support Ctrl-U for blanking the username/password entry */
- if (event->type == GDK_KEY_PRESS &&
- (event->key.state & GDK_CONTROL_MASK) &&
- (event->key.keyval == GDK_u ||
- event->key.keyval == GDK_U)) {
-
- GreeterItemInfo *entry_info = greeter_lookup_id ("user-pw-entry");
- if (entry_info && entry_info->item &&
- GNOME_IS_CANVAS_WIDGET (entry_info->item) &&
- GTK_IS_ENTRY (GNOME_CANVAS_WIDGET (entry_info->item)->widget))
- {
- GtkWidget *entry;
- entry = GNOME_CANVAS_WIDGET (entry_info->item)->widget;
- gtk_entry_set_text (GTK_ENTRY (entry), "");
- }
- }
-
- return TRUE;
+ g_debug ("GREETER Proxy disconnected");
}
int
main (int argc, char *argv[])
{
- char *bg_color;
- struct sigaction hup;
- struct sigaction term;
- sigset_t mask;
- GIOChannel *ctrlch;
- GError *error;
- char *theme_file;
- char *theme_dir;
- char *gdm_graphical_theme;
- char *gdm_gtk_theme;
- guint sid;
- int r;
- gint i;
- int delay;
- gboolean rand_theme;
-
- if (g_getenv ("DOING_GDM_DEVELOPMENT") != NULL)
- DOING_GDM_DEVELOPMENT = TRUE;
+ GError *error;
+ const char *address;
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
@@ -1022,11 +139,6 @@ main (int argc, char *argv[])
setlocale (LC_ALL, "");
- if (ve_string_empty (g_getenv ("GDM_IS_LOCAL")))
- GDM_IS_LOCAL = FALSE;
- else
- GDM_IS_LOCAL = TRUE;
-
g_type_init ();
if (! gdm_settings_client_init (GDMCONFDIR "/gdm.schemas", "/")) {
@@ -1039,477 +151,82 @@ main (int argc, char *argv[])
* because the atk-bridge will crash.
*/
gdk_init (&argc, &argv);
- if (! DOING_GDM_DEVELOPMENT) {
- gdm_common_atspi_launch ();
- }
-
+ gdm_common_atspi_launch ();
gtk_init (&argc, &argv);
- gdm_common_setup_cursor (GDK_WATCH);
-
gdm_common_log_init ();
/*gdm_common_log_set_debug (gdm_settings_client_get_bool (GDM_KEY_DEBUG));*/
gdm_common_log_set_debug (TRUE);
- {
- char *gtkrc;
- gdm_settings_client_get_string (GDM_KEY_GTKRC, &gtkrc);
- if (gtkrc != NULL) {
- gtk_rc_parse (gtkrc);
- }
- g_free (gtkrc);
- }
-
- gdm_gtk_theme = g_strdup (g_getenv ("GDM_GTK_THEME"));
- if (ve_string_empty (gdm_gtk_theme)) {
- gdm_settings_client_get_string (GDM_KEY_GTK_THEME, &gdm_gtk_theme);
- }
-
- if ( ! ve_string_empty (gdm_gtk_theme)) {
- gdm_set_theme (gdm_gtk_theme);
- }
- g_free (gdm_gtk_theme);
-
- {
- int screen;
- gdm_settings_client_get_int (GDM_KEY_XINERAMA_SCREEN, &screen);
- gdm_wm_screen_init (screen);
- }
-
- r = verify_gdm_version ();
- if (r != 0)
- return r;
-
- /* Load the background as early as possible so GDM does not leave */
- /* the background unfilled. The cursor should be a watch already */
- /* but just in case */
- bg_color = NULL;
- gdm_settings_client_get_string (GDM_KEY_GRAPHICAL_THEMED_COLOR, &bg_color);
-
- /* If a graphical theme color does not exist fallback to the plain color */
- if (ve_string_empty (bg_color)) {
- g_free (bg_color);
- bg_color = NULL;
- gdm_settings_client_get_string (GDM_KEY_BACKGROUND_COLOR, &bg_color);
- }
- gdm_common_setup_background_color (bg_color);
- g_free (bg_color);
-
- greeter_session_init ();
-
- {
- char *locale_file;
- gdm_settings_client_get_string (GDM_KEY_LOCALE_FILE, &locale_file);
- gdm_lang_initialize_model (locale_file);
- g_free (locale_file);
- }
-
- hup.sa_handler = ve_signal_notify;
- hup.sa_flags = 0;
- sigemptyset (&hup.sa_mask);
- sigaddset (&hup.sa_mask, SIGCHLD);
-
- if (sigaction (SIGHUP, &hup, NULL) < 0) {
- gdm_common_fail_greeter ("%s: Error setting up %s signal handler: %s", "main",
- "HUP", strerror (errno));
- }
-
- term.sa_handler = greeter_done;
- term.sa_flags = 0;
- sigemptyset (&term.sa_mask);
- sigaddset (&term.sa_mask, SIGCHLD);
-
- if G_UNLIKELY (sigaction (SIGINT, &term, NULL) < 0) {
- gdm_common_fail_greeter ("%s: Error setting up %s signal handler: %s", "main",
- "INT", strerror (errno));
- }
-
- if G_UNLIKELY (sigaction (SIGTERM, &term, NULL) < 0) {
- gdm_common_fail_greeter ("%s: Error setting up %s signal handler: %s", "main",
- "TERM", strerror (errno));
- }
-
- sigemptyset (&mask);
- sigaddset (&mask, SIGTERM);
- sigaddset (&mask, SIGHUP);
- sigaddset (&mask, SIGINT);
-
- if G_UNLIKELY (sigprocmask (SIG_UNBLOCK, &mask, NULL) == -1) {
- gdm_common_fail_greeter ("Could not set signal mask!");
- }
-
- /* ignore SIGCHLD */
- sigemptyset (&mask);
- sigaddset (&mask, SIGCHLD);
-
- if G_UNLIKELY (sigprocmask (SIG_BLOCK, &mask, NULL) == -1) {
- gdm_common_fail_greeter ("Could not set signal mask!");
- }
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- if G_UNLIKELY (DOING_GDM_DEVELOPMENT) {
- g_signal_connect (G_OBJECT (window), "key_press_event",
- G_CALLBACK (key_press_event), NULL);
- }
-
- canvas = gnome_canvas_new_aa ();
- GTK_WIDGET_UNSET_FLAGS (canvas, GTK_CAN_FOCUS);
- gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas),
- 0.0, 0.0,
- (double) gdm_wm_screen.width,
- (double) gdm_wm_screen.height);
- gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
- gtk_window_set_default_size (GTK_WINDOW (window),
- gdm_wm_screen.width,
- gdm_wm_screen.height);
- gtk_container_add (GTK_CONTAINER (window), canvas);
-
- /*
- * Initialize the value with the default value so the first time it
- * is displayed it doesn't show as 0. Also determine if the Halt,
- * Reboot, Suspend and Configurator commands work.
- */
- gdm_settings_client_get_int (GDM_KEY_TIMED_LOGIN_DELAY, &gdm_timed_delay);
-
- {
- char *halt;
- char *reboot;
- char *suspend;
- char *configurator;
-
- gdm_settings_client_get_string (GDM_KEY_HALT, &halt);
- gdm_settings_client_get_string (GDM_KEY_REBOOT, &reboot);
- gdm_settings_client_get_string (GDM_KEY_SUSPEND, &suspend);
- gdm_settings_client_get_string (GDM_KEY_CONFIGURATOR, &configurator);
- GdmHaltFound = gdm_working_command_exists (halt);
- GdmRebootFound = gdm_working_command_exists (reboot);
- GdmSuspendFound = gdm_working_command_exists (suspend);
- GdmConfiguratorFound = gdm_working_command_exists (configurator);
-
- g_free (configurator);
- g_free (suspend);
- g_free (reboot);
- g_free (halt);
- }
-
- GdmCustomCmdsFound = g_new0 (gboolean, GDM_CUSTOM_COMMAND_MAX);
- for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
- char *key_string = NULL;
- char *val;
-
- /* For each possible custom command */
- key_string = g_strdup_printf ("%s%d", GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
-
- gdm_settings_client_get_string (key_string, &val);
- GdmCustomCmdsFound[i] = gdm_working_command_exists (val);
- if (GdmCustomCmdsFound[i])
- GdmAnyCustomCmdsFound = TRUE;
-
- g_free (val);
- g_free (key_string);
- }
-
- gdm_settings_client_get_boolean (GDM_KEY_GRAPHICAL_THEME_RAND, &rand_theme);
- if (g_getenv ("GDM_THEME") != NULL) {
- gdm_graphical_theme = g_strdup (g_getenv ("GDM_THEME"));
- } else if (rand_theme) {
- gdm_graphical_theme = get_random_theme ();
- } else {
- gdm_settings_client_get_string (GDM_KEY_GRAPHICAL_THEME, &gdm_graphical_theme);
+ address = g_getenv ("GDM_GREETER_DBUS_ADDRESS");
+ if (address == NULL) {
+ g_warning ("GDM_GREETER_DBUS_ADDRESS not set");
+ exit (1);
}
- theme_file = get_theme_file (gdm_graphical_theme, &theme_dir);
-
- error = NULL;
- root = greeter_parse (theme_file,
- theme_dir,
- GNOME_CANVAS (canvas),
- gdm_wm_screen.width,
- gdm_wm_screen.height,
- &error);
-
- if G_UNLIKELY (root == NULL) {
- GtkWidget *dialog;
- char *s;
- char *tmp;
-
- gdm_wm_init (0);
- gdm_wm_focus_new_windows (TRUE);
-
- tmp = ve_filename_to_utf8 (ve_sure_string (gdm_graphical_theme));
- s = g_strdup_printf (_("There was an error loading the "
- "theme %s"), tmp);
- g_free (tmp);
- dialog = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- s,
- (error && error->message) ? error->message : "");
- g_free (s);
-
- gtk_widget_show_all (dialog);
- gdm_wm_center_window (GTK_WINDOW (dialog));
-
- gdm_common_setup_cursor (GDK_LEFT_PTR);
+ g_debug ("GREETER connecting to address: %s", address);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-
- if (DOING_GDM_DEVELOPMENT) {
- exit (1);
+ error = NULL;
+ connection = dbus_g_connection_open (address, &error);
+ if (connection == NULL) {
+ if (error != NULL) {
+ g_warning ("error opening connection: %s", error->message);
+ g_error_free (error);
+ } else {
+ g_warning ("Unable to open connection");
}
- }
-
- g_free (gdm_graphical_theme);
-
- if G_UNLIKELY (error)
- g_clear_error (&error);
-
- /* Try circles.xml */
- if G_UNLIKELY (root == NULL) {
- g_free (theme_file);
- g_free (theme_dir);
- theme_file = get_theme_file ("circles", &theme_dir);
- root = greeter_parse (theme_file,
- theme_dir,
- GNOME_CANVAS (canvas),
- gdm_wm_screen.width,
- gdm_wm_screen.height,
- NULL);
- }
-
- g_free (theme_file);
-
- if G_UNLIKELY (root != NULL && greeter_lookup_id ("user-pw-entry") == NULL) {
- GtkWidget *dialog;
-
- gdm_wm_init (0);
- gdm_wm_focus_new_windows (TRUE);
-
- dialog = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("The greeter theme is corrupt"),
- _("The theme does not contain "
- "definition for the username/password "
- "entry element."));
-
- gtk_widget_show_all (dialog);
- gdm_wm_center_window (GTK_WINDOW (dialog));
-
- gdm_common_setup_cursor (GDK_LEFT_PTR);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-
- root = NULL;
- }
-
- /* FIXME: beter information should be printed */
- if G_UNLIKELY (DOING_GDM_DEVELOPMENT && root == NULL) {
- g_warning ("No theme could be loaded");
exit (1);
- }
-
- if G_UNLIKELY (root == NULL) {
- GtkWidget *dialog;
-
- gdm_wm_init (0);
- gdm_wm_focus_new_windows (TRUE);
-
- dialog = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("There was an error loading the "
- "theme, and the default theme "
- "could not be loaded. "
- "Attempting to start the "
- "standard greeter"),
- "");
-
- gtk_widget_show_all (dialog);
- gdm_wm_center_window (GTK_WINDOW (dialog));
-
- gdm_common_setup_cursor (GDK_LEFT_PTR);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-
- execl (LIBEXECDIR "/gdmlogin", LIBEXECDIR "/gdmlogin", NULL);
- execlp ("gdmlogin", "gdmlogin", NULL);
-
- dialog = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("The GTK+ greeter could not be started. "
- "This display will abort and you may "
- "have to login another way and fix the "
- "installation of GDM"),
- "");
-
- gtk_widget_show_all (dialog);
- gdm_wm_center_window (GTK_WINDOW (dialog));
-
- gdm_common_setup_cursor (GDK_LEFT_PTR);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-
- _exit (DISPLAY_ABORT);
- }
-
- greeter_layout (root, GNOME_CANVAS (canvas));
-
- greeter_setup_items ();
-
- if G_LIKELY (! DOING_GDM_DEVELOPMENT) {
- ctrlch = g_io_channel_unix_new (STDIN_FILENO);
- g_io_channel_set_encoding (ctrlch, NULL, NULL);
- g_io_channel_set_buffered (ctrlch, TRUE);
- g_io_channel_set_flags (ctrlch,
- g_io_channel_get_flags (ctrlch) | G_IO_FLAG_NONBLOCK,
- NULL);
- g_io_add_watch (ctrlch,
- G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) greeter_ctrl_handler,
- NULL);
- g_io_channel_unref (ctrlch);
- }
-
- gdm_common_setup_blinking ();
-
- gtk_widget_show_all (window);
- gtk_window_move (GTK_WINDOW (window), gdm_wm_screen.x, gdm_wm_screen.y);
- gtk_widget_show_now (window);
-
- greeter_item_ulist_unset_selected_user ();
- greeter_item_ulist_enable ();
- greeter_item_ulist_check_show_userlist ();
-
- /* can it ever happen that it'd be NULL here ??? */
- if G_UNLIKELY (window->window != NULL) {
- gdm_wm_init (GDK_WINDOW_XWINDOW (window->window));
-
- /* Run the focus, note that this will work no matter what
- * since gdm_wm_init will set the display to the gdk one
- * if it fails */
- gdm_wm_focus_window (GDK_WINDOW_XWINDOW (window->window));
- }
-
- if G_UNLIKELY (session_dir_whacked_out) {
- GtkWidget *dialog;
-
- gdm_wm_focus_new_windows (TRUE);
-
- dialog = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("Session directory is missing"),
- _("Your session directory is missing or empty! "
- "There are two available sessions you can use, but "
- "you should log in and correct the gdm configuration."));
- gtk_widget_show_all (dialog);
- gdm_wm_center_window (GTK_WINDOW (dialog));
-
- gdm_common_setup_cursor (GDK_LEFT_PTR);
-
- gdm_wm_no_login_focus_push ();
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- gdm_wm_no_login_focus_pop ();
- }
-
- if G_UNLIKELY (g_getenv ("GDM_WHACKED_GREETER_CONFIG") != NULL) {
- GtkWidget *dialog;
-
- gdm_wm_focus_new_windows (TRUE);
-
- dialog = hig_dialog_new (NULL /* parent */,
- GTK_DIALOG_MODAL /* flags */,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- _("Configuration is not correct"),
- _("The configuration file contains an invalid command "
- "line for the login dialog, so running the "
- "default command. Please fix your configuration."));
-
- gtk_widget_show_all (dialog);
- gdm_wm_center_window (GTK_WINDOW (dialog));
-
- gdm_common_setup_cursor (GDK_LEFT_PTR);
-
- gdm_wm_no_login_focus_push ();
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- gdm_wm_no_login_focus_pop ();
- }
-
- /* if a flexiserver, reap self after some time */
- gdm_settings_client_get_int (GDM_KEY_FLEXI_REAP_DELAY_MINUTES, &delay);
- if (delay > 0 && ! ve_string_empty (g_getenv ("GDM_FLEXI_SERVER")) &&
- /* but don't reap Xnest flexis */
- ve_string_empty (g_getenv ("GDM_PARENT_DISPLAY"))) {
- sid = g_signal_lookup ("activate",
- GTK_TYPE_MENU_ITEM);
- g_signal_add_emission_hook (sid,
- 0 /* detail */,
- delay_reaping,
- NULL /* data */,
- NULL /* destroy_notify */);
-
- sid = g_signal_lookup ("key_press_event",
- GTK_TYPE_WIDGET);
- g_signal_add_emission_hook (sid,
- 0 /* detail */,
- delay_reaping,
- NULL /* data */,
- NULL /* destroy_notify */);
-
- sid = g_signal_lookup ("button_press_event",
- GTK_TYPE_WIDGET);
- g_signal_add_emission_hook (sid,
- 0 /* detail */,
- delay_reaping,
- NULL /* data */,
- NULL /* destroy_notify */);
+ }
- last_reap_delay = time (NULL);
- g_timeout_add (60*1000, reap_flexiserver, NULL);
+ g_debug ("GREETER creating proxy for peer: %s", SERVER_DBUS_PATH);
+ server_proxy = dbus_g_proxy_new_for_peer (connection,
+ SERVER_DBUS_PATH,
+ SERVER_DBUS_INTERFACE);
+ if (server_proxy == NULL) {
+ g_warning ("Unable to create proxy for peer");
+ exit (1);
}
- sid = g_signal_lookup ("event",
- GTK_TYPE_WIDGET);
- g_signal_add_emission_hook (sid,
- 0 /* detail */,
- gdm_event,
- NULL /* data */,
- NULL /* destroy_notify */);
-
- gdm_wm_restore_wm_order ();
-
- {
- char *msg_file;
- char *msg_font;
-
- gdm_settings_client_get_string (GDM_KEY_INFO_MSG_FILE, &msg_file);
- gdm_settings_client_get_string (GDM_KEY_INFO_MSG_FONT, &msg_font);
+ g_signal_connect (server_proxy, "destroy", G_CALLBACK (proxy_destroyed), NULL);
+
+ /* FIXME: not sure why introspection isn't working */
+ dbus_g_proxy_add_signal (server_proxy, "InfoQuery", G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (server_proxy, "SecretInfoQuery", G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (server_proxy, "Info", G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (server_proxy, "Problem", G_TYPE_STRING, G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal (server_proxy,
+ "InfoQuery",
+ G_CALLBACK (on_info_query),
+ NULL,
+ NULL);
+ dbus_g_proxy_connect_signal (server_proxy,
+ "SecretInfoQuery",
+ G_CALLBACK (on_secret_info_query),
+ NULL,
+ NULL);
+ dbus_g_proxy_connect_signal (server_proxy,
+ "Info",
+ G_CALLBACK (on_info),
+ NULL,
+ NULL);
+ dbus_g_proxy_connect_signal (server_proxy,
+ "Problem",
+ G_CALLBACK (on_problem),
+ NULL,
+ NULL);
+
+ greeter = gdm_themed_greeter_new ();
+ g_signal_connect (greeter,
+ "query-answer",
+ G_CALLBACK (on_query_answer),
+ NULL);
+ gtk_main ();
- gdm_wm_show_info_msg_dialog (msg_file, msg_font);
- g_free (msg_font);
- g_free (msg_file);
+ if (greeter != NULL) {
+ g_object_unref (greeter);
}
- gdm_common_setup_cursor (GDK_LEFT_PTR);
- gdm_wm_center_cursor ();
- gdm_common_pre_fetch_launch ();
- gtk_main ();
-
return 0;
}
diff --git a/gui/greeter/greeter_item_customlist.c b/gui/greeter/greeter_item_customlist.c
index b2713269..6db0dac5 100644
--- a/gui/greeter/greeter_item_customlist.c
+++ b/gui/greeter/greeter_item_customlist.c
@@ -33,7 +33,6 @@
#include "gdm-common.h"
#include "gdm-settings-client.h"
#include "gdm-settings-keys.h"
-#include "gdm-socket-protocol.h"
#include "greeter_item.h"
#include "greeter_configuration.h"
@@ -467,9 +466,6 @@ combo_selected (GtkComboBox *combo, GreeterItemInfo *item)
} else {
char *authdir;
- if (DOING_GDM_DEVELOPMENT)
- return;
-
id = gtk_combo_box_get_active_text (combo);
gdm_settings_client_get_string (GDM_KEY_SERV_AUTHDIR, &authdir);
@@ -546,9 +542,6 @@ list_selected (GtkTreeSelection *selection, GreeterItemInfo *item)
} else {
char *authdir;
- if (DOING_GDM_DEVELOPMENT)
- return;
-
gdm_settings_client_get_string (GDM_KEY_SERV_AUTHDIR, &authdir);
file = g_strdup_printf ("%s/%s.GreeterInfo",
ve_sure_string (authdir),
diff --git a/gui/greeter/greeter_item_pam.c b/gui/greeter/greeter_item_pam.c
index d3b9a11d..08d3df78 100644
--- a/gui/greeter/greeter_item_pam.c
+++ b/gui/greeter/greeter_item_pam.c
@@ -24,7 +24,7 @@
#include <gdk/gdkkeysyms.h>
#include "gdm-common.h"
-#include "gdm-socket-protocol.h"
+#include "gdm-greeter.h"
#include "greeter.h"
#include "greeter_item.h"
@@ -38,6 +38,7 @@
#include "gdmwm.h"
#include "gdmcommon.h"
+static GdmGreeter *greeter_object = NULL;
static gboolean messages_to_give = FALSE;
static gboolean replace_msg = TRUE;
static guint err_box_clear_handler = 0;
@@ -141,6 +142,7 @@ greeter_item_pam_login (GtkEntry *entry, GreeterItemInfo *info)
return;
}
+#if 0
if (greeter_probably_login_prompt &&
ve_string_empty (str) &&
greeter_item_timed_is_timed ())
@@ -150,6 +152,7 @@ greeter_item_pam_login (GtkEntry *entry, GreeterItemInfo *info)
fflush (stdout);
return;
}
+#endif
gtk_widget_set_sensitive (GTK_WIDGET (entry), FALSE);
@@ -165,10 +168,15 @@ greeter_item_pam_login (GtkEntry *entry, GreeterItemInfo *info)
set_text (error_info, "");
}
+#if 0
tmp = ve_locale_from_utf8 (str);
printf ("%c%s\n", STX, tmp);
fflush (stdout);
g_free (tmp);
+#endif
+
+ gdm_greeter_answer_query (greeter_object, str);
+
}
static gboolean
@@ -208,10 +216,12 @@ pam_key_release_event (GtkWidget *entry, GdkEventKey *event, gpointer data)
}
gboolean
-greeter_item_pam_setup (void)
+greeter_item_pam_setup (GdmGreeter *greeter)
{
GreeterItemInfo *entry_info;
+ greeter_object = greeter;
+
greeter_item_pam_error_set (FALSE);
entry_info = greeter_lookup_id ("user-pw-entry");
@@ -222,8 +232,7 @@ greeter_item_pam_setup (void)
GtkWidget *entry = GNOME_CANVAS_WIDGET (entry_info->item)->widget;
gtk_widget_grab_focus (entry);
- if ( ! DOING_GDM_DEVELOPMENT)
- {
+ {
/* hack. For some reason if we leave it blank,
* we'll get a little bit of activity on first keystroke,
* this way we get rid of it, it will be cleared for the
diff --git a/gui/greeter/greeter_item_pam.h b/gui/greeter/greeter_item_pam.h
index 0d1d3a6e..325329a4 100644
--- a/gui/greeter/greeter_item_pam.h
+++ b/gui/greeter/greeter_item_pam.h
@@ -20,8 +20,9 @@
#define GREETER_ITEM_PAM_H
#include "greeter_item.h"
+#include "gdm-greeter.h"
-gboolean greeter_item_pam_setup (void);
+gboolean greeter_item_pam_setup (GdmGreeter *greeter);
void greeter_item_pam_prompt (const char *message,
int entry_len,
gboolean entry_visible);
diff --git a/gui/greeter/greeter_item_timed.c b/gui/greeter/greeter_item_timed.c
index c5b99693..3aa39d79 100644
--- a/gui/greeter/greeter_item_timed.c
+++ b/gui/greeter/greeter_item_timed.c
@@ -26,7 +26,6 @@
#include "gdm.h"
#include "gdm-common.h"
-#include "gdm-socket-protocol.h"
#include "gdm-settings-client.h"
#include "gdm-settings-keys.h"
@@ -60,8 +59,10 @@ gdm_timer (gpointer data)
gdm_timed_delay--;
if (gdm_timed_delay <= 0) {
/* timed interruption */
+#if 0
printf ("%c%c%c\n", STX, BEL, GDM_INTERRUPT_TIMED_LOGIN);
fflush (stdout);
+#endif
}
return TRUE;
}
diff --git a/gui/greeter/greeter_item_ulist.c b/gui/greeter/greeter_item_ulist.c
index 40b309c0..1217eb61 100644
--- a/gui/greeter/greeter_item_ulist.c
+++ b/gui/greeter/greeter_item_ulist.c
@@ -38,7 +38,6 @@
#include "gdmuser.h"
#include "gdm-common.h"
-#include "gdm-socket-protocol.h"
#include "gdm-settings-client.h"
#include "gdm-settings-keys.h"
@@ -151,8 +150,8 @@ gdm_greeter_users_init (void)
NULL,
defface,
&size_of_users,
- GDM_IS_LOCAL,
- !DOING_GDM_DEVELOPMENT);
+ TRUE,
+ TRUE);
}
static void
@@ -204,10 +203,12 @@ greeter_populate_user_list (GtkTreeModel *tm)
void
greeter_item_ulist_select_user (gchar *login)
{
+#if 0
printf ("%c%c%c%s\n", STX, BEL,
GDM_INTERRUPT_SELECT_USER, login);
fflush (stdout);
+#endif
}
static void
diff --git a/gui/greeter/greeter_system.c b/gui/greeter/greeter_system.c
index 7785508d..2cd4c31f 100644
--- a/gui/greeter/greeter_system.c
+++ b/gui/greeter/greeter_system.c
@@ -37,7 +37,6 @@
#include "misc.h"
#include "gdm-common.h"
-#include "gdm-socket-protocol.h"
#include "gdm-settings-client.h"
#include "gdm-settings-keys.h"
@@ -102,8 +101,10 @@ query_greeter_custom_cmd_handler (GtkWidget *widget, gpointer data)
gdm_settings_client_get_string (key_string, &val);
if (gdm_wm_warn_dialog (val, "", GTK_STOCK_OK, NULL, TRUE) == GTK_RESPONSE_YES) {
+#if 0
printf ("%c%c%c%d\n", STX, BEL, GDM_INTERRUPT_CUSTOM_CMD, *cmd_id);
fflush (stdout);
+#endif
}
g_free (val);
g_free (key_string);
@@ -125,8 +126,10 @@ query_greeter_suspend_handler (void)
if (gdm_wm_warn_dialog (_("Are you sure you want to suspend the computer?"), "",
_("_Suspend"), NULL, TRUE) == GTK_RESPONSE_YES) {
/* suspend interruption */
+#if 0
printf ("%c%c%c\n", STX, BEL, GDM_INTERRUPT_SUSPEND);
fflush (stdout);
+#endif
}
}
@@ -139,8 +142,10 @@ greeter_restart_handler (void)
static void
greeter_custom_cmd_handler (gint cmd_id)
{
+#if 0
printf ("%c%c%c%d\n", STX, BEL, GDM_INTERRUPT_CUSTOM_CMD, cmd_id);
fflush (stdout);
+#endif
}
static void
@@ -152,8 +157,10 @@ greeter_halt_handler (void)
static void
greeter_suspend_handler (void)
{
+#if 0
printf ("%c%c%c\n", STX, BEL, GDM_INTERRUPT_SUSPEND);
fflush (stdout);
+#endif
}
static void
@@ -167,9 +174,11 @@ greeter_config_handler (void)
/* we should be now fine for focusing new windows */
gdm_wm_focus_new_windows (TRUE);
+#if 0
/* configure interruption */
printf ("%c%c%c\n", STX, BEL, GDM_INTERRUPT_CONFIGURE);
fflush (stdout);
+#endif
}
static void
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 22fa8b56..35f31f77 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -47,7 +47,6 @@ libexec_SCRIPTS = \
@GDMSSHSESSION@
libexec_PROGRAMS = \
- @GDMASKPASS@ \
@GDMOPEN@ \
@GDMPREFETCH@ \
gdmtranslate
@@ -57,10 +56,7 @@ bin_PROGRAMS = gdm-dmx-reconnect-proxy
endif
EXTRA_SCRIPTS = gdm-ssh-session
-EXTRA_PROGRAMS = gdmaskpass gdmopen gdmprefetch
-
-gdmaskpass_SOURCES = \
- gdmaskpass.c
+EXTRA_PROGRAMS = gdmopen gdmprefetch
gdmtranslate_SOURCES = \
gdmtranslate.c
@@ -71,11 +67,6 @@ gdmopen_SOURCES = \
gdmprefetch_SOURCES = \
gdmprefetch.c
-gdmaskpass_LDADD = \
- $(INTLLIBS) \
- -lpam \
- $(EXTRA_GDMASKPASS_LIBS)
-
gdmopen_LDADD = \
$(INTLLIBS)
diff --git a/utils/gdmaskpass.c b/utils/gdmaskpass.c
deleted file mode 100644
index 206b9eda..00000000
--- a/utils/gdmaskpass.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Simple pam thingie to ask the root password, for use in XKeepsCrashing
- * script. */
-#include "config.h"
-#include <glib/gi18n.h>
-#include <stdio.h>
-#include <locale.h>
-#include <unistd.h>
-#include <security/pam_appl.h>
-#include <security/pam_misc.h>
-
-static struct pam_conv conv = {
- misc_conv,
- NULL
-};
-
-int
-main (int argc, char *argv[])
-{
- pam_handle_t *pamh;
- const char *username = "root";
- int retval;
- int tries = 3;
-
- if (getuid () != geteuid () ||
- getuid () != 0) {
- fprintf (stderr, _("gdmaskpass only runs as root\n"));
- return 1;
- }
-
- if (argc >= 2) {
- username = argv[1];
- }
-
- setlocale (LC_ALL, "");
- bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
- textdomain (GETTEXT_PACKAGE);
-
- for (tries = 3; tries > 0; tries --) {
- if ((retval = pam_start ("gdm", username, &conv, &pamh)) != PAM_SUCCESS) {
- pam_end (pamh, retval);
- pamh = NULL;
- printf (_("Authentication failure!\n"));
- continue;
- }
- if ((retval = pam_authenticate (pamh, 0)) != PAM_SUCCESS) {
- pam_end (pamh, retval);
- pamh = NULL;
- printf (_("Authentication failure!\n"));
- continue;
- }
- break;
- }
-
- if (pamh != NULL)
- pam_end (pamh, retval);
-
- return (retval == PAM_SUCCESS) ? 0 : 1;
-}