summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/gdm-settings-desktop-backend.c4
-rw-r--r--common/gdm-settings-direct.c2
-rw-r--r--common/gdm-settings-utils.c2
-rw-r--r--common/gdm-settings.c2
-rw-r--r--configure.ac2
-rw-r--r--daemon/gdm-greeter-proxy.c180
-rw-r--r--daemon/gdm-greeter-proxy.h12
-rw-r--r--daemon/gdm-session.c219
-rw-r--r--daemon/gdm-session.h61
-rw-r--r--daemon/gdm-slave.c528
-rw-r--r--daemon/gdm-slave.h8
-rw-r--r--daemon/slave-main.c40
-rw-r--r--daemon/test-session.c6
-rw-r--r--gui/Makefile.am4
-rw-r--r--gui/gdm-greeter.c51
-rw-r--r--gui/gdm-greeter.h11
-rw-r--r--gui/greeter/greeter.c55
17 files changed, 785 insertions, 402 deletions
diff --git a/common/gdm-settings-desktop-backend.c b/common/gdm-settings-desktop-backend.c
index d710f481..f69c83a7 100644
--- a/common/gdm-settings-desktop-backend.c
+++ b/common/gdm-settings-desktop-backend.c
@@ -76,7 +76,7 @@ parse_key_string (const char *keystring,
g = k = v = l = NULL;
split1 = split2 = NULL;
- g_debug ("Attempting to parse key string: %s", keystring);
+ /*g_debug ("Attempting to parse key string: %s", keystring);*/
split1 = g_strsplit (keystring, "/", 2);
if (split1 == NULL || split1 [0] == NULL || split1 [1] == NULL) {
@@ -147,7 +147,7 @@ gdm_settings_desktop_backend_get_value (GdmSettingsBackend *backend,
return FALSE;
}
- g_debug ("Getting key: %s %s %s", g, k, l);
+ /*g_debug ("Getting key: %s %s %s", g, k, l);*/
local_error = NULL;
val = g_key_file_get_value (GDM_SETTINGS_DESKTOP_BACKEND (backend)->priv->key_file,
g,
diff --git a/common/gdm-settings-direct.c b/common/gdm-settings-direct.c
index 38e004b2..0b9385ab 100644
--- a/common/gdm-settings-direct.c
+++ b/common/gdm-settings-direct.c
@@ -78,10 +78,8 @@ get_value (const char *key,
res = gdm_settings_get_value (settings_object, key, &str, &error);
if (! res) {
if (error != NULL) {
- 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);
}
return FALSE;
diff --git a/common/gdm-settings-utils.c b/common/gdm-settings-utils.c
index 65e979e7..82293c98 100644
--- a/common/gdm-settings-utils.c
+++ b/common/gdm-settings-utils.c
@@ -123,7 +123,7 @@ start_element_cb (GMarkupParseContext *ctx,
static void
add_schema_entry (ParserInfo *info)
{
- g_debug ("Inserting entry %s", info->entry->key);
+ /*g_debug ("Inserting entry %s", info->entry->key);*/
info->list = g_slist_prepend (info->list, info->entry);
}
diff --git a/common/gdm-settings.c b/common/gdm-settings.c
index ee8f0864..07bb3776 100644
--- a/common/gdm-settings.c
+++ b/common/gdm-settings.c
@@ -94,8 +94,6 @@ gdm_settings_get_value (GdmSettings *settings,
g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE);
g_return_val_if_fail (key != NULL, FALSE);
- g_debug ("Getting key %s", key);
-
local_error = NULL;
res = gdm_settings_backend_get_value (settings->priv->backend,
key,
diff --git a/configure.ac b/configure.ac
index c82c9b6e..10f2d1f5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,7 +11,7 @@ IT_PROG_INTLTOOL([0.35.0])
GNOME_DOC_INIT
DBUS_REQUIRED=0.30
-GLIB_REQUIRED=2.8.0
+GLIB_REQUIRED=2.13.0
GTK_REQUIRED=2.6.0
PANGO_REQUIRED=1.3.0
LIBGLADE_REQUIRED=1.99.2
diff --git a/daemon/gdm-greeter-proxy.c b/daemon/gdm-greeter-proxy.c
index 1467e240..98cc5acd 100644
--- a/daemon/gdm-greeter-proxy.c
+++ b/daemon/gdm-greeter-proxy.c
@@ -60,21 +60,21 @@ extern char **environ;
struct GdmGreeterProxyPrivate
{
- char *command;
- GPid pid;
+ char *command;
+ GPid pid;
- char *user_name;
- char *group_name;
+ char *user_name;
+ char *group_name;
- char *x11_display_name;
- char *x11_authority_file;
+ char *x11_display_name;
+ char *x11_authority_file;
- int user_max_filesize;
+ int user_max_filesize;
- gboolean interrupted;
- gboolean always_restart_greeter;
+ gboolean interrupted;
+ gboolean always_restart_greeter;
- guint child_watch_id;
+ guint child_watch_id;
DBusServer *server;
char *server_address;
@@ -90,7 +90,9 @@ enum {
};
enum {
- ANSWER,
+ QUERY_ANSWER,
+ SESSION_SELECTED,
+ LANGUAGE_SELECTED,
STARTED,
STOPPED,
LAST_SIGNAL
@@ -267,7 +269,6 @@ static GPtrArray *
get_greeter_environment (GdmGreeterProxy *greeter_proxy)
{
GPtrArray *env;
- char **l;
GHashTable *hash;
struct passwd *pwent;
@@ -276,14 +277,6 @@ get_greeter_environment (GdmGreeterProxy *greeter_proxy)
/* 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));
@@ -446,6 +439,87 @@ generate_address (void)
}
static DBusHandlerResult
+handle_answer_query (GdmGreeterProxy *greeter_proxy,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+ DBusError error;
+ const char *text;
+
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
+ }
+
+ g_debug ("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 [QUERY_ANSWER], 0, text);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+handle_select_session (GdmGreeterProxy *greeter_proxy,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+ DBusError error;
+ const char *text;
+
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
+ }
+
+ g_debug ("SelectSession: %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 [SESSION_SELECTED], 0, text);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+handle_select_language (GdmGreeterProxy *greeter_proxy,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+ DBusError error;
+ const char *text;
+
+ dbus_error_init (&error);
+ if (! dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID)) {
+ g_warning ("ERROR: %s", error.message);
+ }
+
+ g_debug ("SelectLanguage: %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 [LANGUAGE_SELECTED], 0, text);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
greeter_handle_child_message (DBusConnection *connection,
DBusMessage *message,
void *user_data)
@@ -453,26 +527,11 @@ greeter_handle_child_message (DBusConnection *connection,
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 handle_answer_query (greeter_proxy, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "SelectSession")) {
+ return handle_select_session (greeter_proxy, connection, message);
+ } else if (dbus_message_is_method_call (message, GDM_GREETER_SERVER_DBUS_INTERFACE, "SelectSession")) {
+ return handle_select_language (greeter_proxy, connection, message);
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -504,6 +563,12 @@ do_introspect (DBusConnection *connection,
" <method name=\"AnswerQuery\">\n"
" <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
" </method>\n"
+ " <method name=\"SelectSession\">\n"
+ " <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
+ " </method>\n"
+ " <method name=\"SelectLanguage\">\n"
+ " <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
+ " </method>\n"
" <signal name=\"Info\">\n"
" <arg name=\"text\" type=\"s\"/>\n"
" </signal>\n"
@@ -547,8 +612,6 @@ 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),
@@ -591,8 +654,6 @@ 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");
}
@@ -700,7 +761,6 @@ create_dbus_server (GdmGreeterProxy *greeter_proxy)
DBusError error;
gboolean ret;
char *address;
- char *server_address;
const char *auth_mechanisms[] = {"EXTERNAL", NULL};
ret = FALSE;
@@ -1055,11 +1115,33 @@ gdm_greeter_proxy_class_init (GdmGreeterProxyClass *klass)
"group name",
"gdm",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- signals [ANSWER] =
- g_signal_new ("answer",
+ signals [QUERY_ANSWER] =
+ g_signal_new ("query-answer",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmGreeterProxyClass, query_answer),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+ signals [SESSION_SELECTED] =
+ g_signal_new ("session-selected",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmGreeterProxyClass, session_selected),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+ signals [LANGUAGE_SELECTED] =
+ g_signal_new ("language-selected",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (GdmGreeterProxyClass, answer),
+ G_STRUCT_OFFSET (GdmGreeterProxyClass, language_selected),
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
@@ -1096,7 +1178,7 @@ gdm_greeter_proxy_init (GdmGreeterProxy *greeter_proxy)
greeter_proxy->priv->pid = -1;
- greeter_proxy->priv->command = g_strdup (LIBEXECDIR "/gdmgreeter");
+ greeter_proxy->priv->command = g_strdup (LIBEXECDIR "/gdmgreeter --g-fatal-warnings");
greeter_proxy->priv->user_max_filesize = 65536;
}
diff --git a/daemon/gdm-greeter-proxy.h b/daemon/gdm-greeter-proxy.h
index 4458b64b..6e8eb28f 100644
--- a/daemon/gdm-greeter-proxy.h
+++ b/daemon/gdm-greeter-proxy.h
@@ -45,10 +45,14 @@ typedef struct
{
GObjectClass parent_class;
- void (* answer) (GdmGreeterProxy *greeter_proxy,
- const char *text);
- void (* started) (GdmGreeterProxy *greeter_proxy);
- void (* stopped) (GdmGreeterProxy *greeter_proxy);
+ void (* query_answer) (GdmGreeterProxy *greeter_proxy,
+ const char *text);
+ void (* session_selected) (GdmGreeterProxy *greeter_proxy,
+ const char *name);
+ void (* language_selected) (GdmGreeterProxy *greeter_proxy,
+ const char *name);
+ void (* started) (GdmGreeterProxy *greeter_proxy);
+ void (* stopped) (GdmGreeterProxy *greeter_proxy);
} GdmGreeterProxyClass;
GType gdm_greeter_proxy_get_type (void);
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 472e3fe8..996c4067 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -2091,7 +2091,7 @@ gdm_session_worker_pam_new_messages_handler (int number_o
sizeof (struct pam_response));
for (i = 0; i < number_of_messages; i++) {
gboolean got_response;
- char *response_text;
+ char *response_text;
response_text = NULL;
got_response = gdm_session_worker_process_pam_message (worker,
@@ -2331,7 +2331,8 @@ gdm_session_worker_set_environment_variable (GdmSessionWorker *worker,
* better?
*/
g_hash_table_replace (worker->environment,
- key_and_value[0], key_and_value[1]);
+ key_and_value[0],
+ key_and_value[1]);
/* We are calling g_free instead of g_strfreev because the
* hash table is taking over ownership of the individual
@@ -2663,6 +2664,177 @@ gdm_session_worker_watch_child (GdmSessionWorker *worker)
g_source_unref (worker->child_watch_source);
}
+/* adapted from glib script_execute */
+static void
+script_execute (const gchar *file,
+ char **argv,
+ char **envp,
+ gboolean search_path)
+{
+ /* Count the arguments. */
+ int argc = 0;
+
+ while (argv[argc])
+ ++argc;
+
+ /* Construct an argument list for the shell. */
+ {
+ char **new_argv;
+
+ new_argv = g_new0 (gchar*, argc + 2); /* /bin/sh and NULL */
+
+ new_argv[0] = (char *) "/bin/sh";
+ new_argv[1] = (char *) file;
+ while (argc > 0) {
+ new_argv[argc + 1] = argv[argc];
+ --argc;
+ }
+
+ /* Execute the shell. */
+ if (envp)
+ execve (new_argv[0], new_argv, envp);
+ else
+ execv (new_argv[0], new_argv);
+
+ g_free (new_argv);
+ }
+}
+
+static char *
+my_strchrnul (const char *str, char c)
+{
+ char *p = (char*) str;
+ while (*p && (*p != c))
+ ++p;
+
+ return p;
+}
+
+/* adapted from glib g_execute */
+static gint
+gdm_session_execute (const char *file,
+ char **argv,
+ char **envp,
+ gboolean search_path)
+{
+ if (*file == '\0') {
+ /* We check the simple case first. */
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (!search_path || strchr (file, '/') != NULL) {
+ /* Don't search when it contains a slash. */
+ if (envp)
+ execve (file, argv, envp);
+ else
+ execv (file, argv);
+
+ if (errno == ENOEXEC)
+ script_execute (file, argv, envp, FALSE);
+ } else {
+ gboolean got_eacces = 0;
+ const char *path, *p;
+ char *name, *freeme;
+ gsize len;
+ gsize pathlen;
+
+ path = g_getenv ("PATH");
+ if (path == NULL) {
+ /* There is no `PATH' in the environment. The default
+ * search path in libc is the current directory followed by
+ * the path `confstr' returns for `_CS_PATH'.
+ */
+
+ /* In GLib we put . last, for security, and don't use the
+ * unportable confstr(); UNIX98 does not actually specify
+ * what to search if PATH is unset. POSIX may, dunno.
+ */
+
+ path = "/bin:/usr/bin:.";
+ }
+
+ len = strlen (file) + 1;
+ pathlen = strlen (path);
+ freeme = name = g_malloc (pathlen + len + 1);
+
+ /* Copy the file name at the top, including '\0' */
+ memcpy (name + pathlen + 1, file, len);
+ name = name + pathlen;
+ /* And add the slash before the filename */
+ *name = '/';
+
+ p = path;
+ do {
+ char *startp;
+
+ path = p;
+ p = my_strchrnul (path, ':');
+
+ if (p == path)
+ /* Two adjacent colons, or a colon at the beginning or the end
+ * of `PATH' means to search the current directory.
+ */
+ startp = name + 1;
+ else
+ startp = memcpy (name - (p - path), path, p - path);
+
+ /* Try to execute this name. If it works, execv will not return. */
+ if (envp)
+ execve (startp, argv, envp);
+ else
+ execv (startp, argv);
+
+ if (errno == ENOEXEC)
+ script_execute (startp, argv, envp, search_path);
+
+ switch (errno) {
+ case EACCES:
+ /* Record the we got a `Permission denied' error. If we end
+ * up finding no executable we can use, we want to diagnose
+ * that we did find one but were denied access.
+ */
+ got_eacces = TRUE;
+
+ /* FALL THRU */
+
+ case ENOENT:
+#ifdef ESTALE
+ case ESTALE:
+#endif
+#ifdef ENOTDIR
+ case ENOTDIR:
+#endif
+ /* Those errors indicate the file is missing or not executable
+ * by us, in which case we want to just try the next path
+ * directory.
+ */
+ break;
+
+ default:
+ /* Some other error means we found an executable file, but
+ * something went wrong executing it; return the error to our
+ * caller.
+ */
+ g_free (freeme);
+ return -1;
+ }
+ } while (*p++ != '\0');
+
+ /* We tried every element and none of them worked. */
+ if (got_eacces)
+ /* At least one failure was due to permissions, so report that
+ * error.
+ */
+ errno = EACCES;
+
+ g_free (freeme);
+ }
+
+ /* Return the error from the last attempt (probably ENOENT). */
+ return -1;
+}
+
static gboolean
gdm_session_worker_open_user_session (GdmSessionWorker *worker,
GError **error)
@@ -2707,12 +2879,10 @@ gdm_session_worker_open_user_session (GdmSessionWorker *worker,
char *home_dir;
int fd;
- worker->inherited_fd_list =
- g_slist_append (NULL,
- GINT_TO_POINTER (worker->standard_output_fd));
- worker->inherited_fd_list =
- g_slist_append (worker->inherited_fd_list,
- GINT_TO_POINTER (worker->standard_error_fd));
+ worker->inherited_fd_list = g_slist_append (NULL,
+ GINT_TO_POINTER (worker->standard_output_fd));
+ worker->inherited_fd_list = g_slist_append (worker->inherited_fd_list,
+ GINT_TO_POINTER (worker->standard_error_fd));
#if 0
gdm_session_worker_close_open_fds (worker);
@@ -2763,10 +2933,14 @@ gdm_session_worker_open_user_session (GdmSessionWorker *worker,
g_chdir ("/");
}
- execve (worker->arguments[0], worker->arguments, environment);
+ gdm_session_execute (worker->arguments[0],
+ worker->arguments,
+ environment,
+ TRUE);
g_debug ("child '%s' could not be started - %s",
- worker->arguments[0], g_strerror (errno));
+ worker->arguments[0],
+ g_strerror (errno));
g_strfreev (environment);
_exit (127);
@@ -2890,7 +3064,7 @@ gdm_session_worker_handle_verification_message (GdmSessionWorker *w
}
static void
-gdm_session_worker_handle_start_program_message (GdmSessionWorker *worker,
+gdm_session_worker_handle_start_program_message (GdmSessionWorker *worker,
GdmSessionStartProgramMessage *message)
{
GError *start_error;
@@ -3814,26 +3988,29 @@ gdm_session_open_for_user (GdmSession *session,
}
void
-gdm_session_start_program (GdmSession *session,
- const char * const *args)
+gdm_session_start_program (GdmSession *session,
+ int argc,
+ const char **argv)
{
GdmSessionMessage *message;
- int argc, i;
+ int i;
g_return_if_fail (session != NULL);
g_return_if_fail (session != NULL);
g_return_if_fail (gdm_session_is_running (session) == FALSE);
- g_return_if_fail (args != NULL);
- g_return_if_fail (args[0] != NULL);
+ g_return_if_fail (argv != NULL);
+ g_return_if_fail (argv[0] != NULL);
- argc = g_strv_length ((char **) args);
session->priv->arguments = g_new0 (char *, (argc + 1));
- for (i = 0; args[i] != NULL; i++)
- session->priv->arguments[i] = g_strdup (args[i]);
+ for (i = 0; argv[i] != NULL; i++) {
+ session->priv->arguments[i] = g_strdup (argv[i]);
+ }
- message = gdm_session_start_program_message_new (args);
- gdm_write_message (session->priv->worker_message_pipe_fd, message, message->size,
+ message = gdm_session_start_program_message_new (argv);
+ gdm_write_message (session->priv->worker_message_pipe_fd,
+ message,
+ message->size,
NULL);
gdm_session_message_free (message);
}
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index 49510d1e..cd5c0867 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -99,36 +99,37 @@ GQuark gdm_session_error_quark (void);
GdmSession * gdm_session_new (void) G_GNUC_MALLOC;
-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);
-
-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,
- const char * const * args);
-
-void gdm_session_set_environment_variable (GdmSession *session,
- const char *key,
- const char *value);
-
-void gdm_session_answer_query (GdmSession *session,
- const char *answer);
-
-char * gdm_session_get_username (GdmSession *session);
-
-void gdm_session_close (GdmSession *session);
-gboolean gdm_session_is_running (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);
+
+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 argc,
+ const char **argv);
+
+void gdm_session_set_environment_variable (GdmSession *session,
+ const char *key,
+ const char *value);
+
+void gdm_session_answer_query (GdmSession *session,
+ const char *answer);
+
+char * gdm_session_get_username (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 6722ab9b..cb0c3422 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -88,6 +88,9 @@ struct GdmSlavePrivate
char *parent_display_name;
char *parent_display_x11_authority_file;
+ /* user selected */
+ char *selected_session;
+ char *selected_language;
GdmServer *server;
GdmGreeterProxy *greeter;
@@ -101,271 +104,21 @@ enum {
PROP_DISPLAY_ID,
};
+enum {
+ SESSION_STARTED,
+ SESSION_EXITED,
+ SESSION_DIED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
static void gdm_slave_class_init (GdmSlaveClass *klass);
static void gdm_slave_init (GdmSlave *slave);
static void gdm_slave_finalize (GObject *object);
G_DEFINE_TYPE (GdmSlave, gdm_slave, G_TYPE_OBJECT)
-/* adapted from gspawn.c */
-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 in 'GdmSpawn'");
- }
- }
-
- return status;
-}
-
-static void
-slave_died (GdmSlave *slave)
-{
- int exit_status;
-
- g_debug ("Waiting on process %d", slave->priv->pid);
- exit_status = wait_on_child (slave->priv->pid);
-
- if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
- g_debug ("Wait on child process failed");
- } else {
- /* exited normally */
- }
-
- g_spawn_close_pid (slave->priv->pid);
- slave->priv->pid = -1;
-
- g_debug ("Slave died");
-}
-
-static gboolean
-output_watch (GIOChannel *source,
- GIOCondition condition,
- GdmSlave *slave)
-{
- gboolean finished = FALSE;
-
- if (condition & G_IO_IN) {
- GIOStatus status;
- GError *error = NULL;
- char *line;
-
- line = NULL;
- status = g_io_channel_read_line (source, &line, NULL, NULL, &error);
-
- switch (status) {
- case G_IO_STATUS_NORMAL:
- {
- char *p;
-
- g_debug ("command output: %s", line);
-
- if ((p = strstr (line, "ADDRESS=")) != NULL) {
- char *address;
-
- address = g_strdup (p + strlen ("ADDRESS="));
- g_debug ("Got address %s", address);
-
- g_free (address);
- }
- }
- break;
- case G_IO_STATUS_EOF:
- finished = TRUE;
- break;
- case G_IO_STATUS_ERROR:
- finished = TRUE;
- g_debug ("Error reading from child: %s\n", error->message);
- return FALSE;
- case G_IO_STATUS_AGAIN:
- default:
- break;
- }
-
- g_free (line);
- } else if (condition & G_IO_HUP) {
- finished = TRUE;
- }
-
- if (finished) {
- slave_died (slave);
-
- slave->priv->output_watch_id = 0;
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* just for debugging */
-static gboolean
-error_watch (GIOChannel *source,
- GIOCondition condition,
- GdmSlave *slave)
-{
- gboolean finished = FALSE;
-
- if (condition & G_IO_IN) {
- GIOStatus status;
- GError *error = NULL;
- char *line;
-
- line = NULL;
- status = g_io_channel_read_line (source, &line, NULL, NULL, &error);
-
- switch (status) {
- case G_IO_STATUS_NORMAL:
- g_debug ("command error output: %s", line);
- break;
- case G_IO_STATUS_EOF:
- finished = TRUE;
- break;
- case G_IO_STATUS_ERROR:
- finished = TRUE;
- g_debug ("Error reading from child: %s\n", error->message);
- return FALSE;
- case G_IO_STATUS_AGAIN:
- default:
- break;
- }
- g_free (line);
- } else if (condition & G_IO_HUP) {
- finished = TRUE;
- }
-
- if (finished) {
- slave->priv->error_watch_id = 0;
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-spawn_slave (GdmSlave *slave)
-{
- char *command;
- char **argv;
- gboolean result;
- GIOChannel *channel;
- GError *error = NULL;
- int standard_output;
- int standard_error;
-
-
- result = FALSE;
-
- command = g_strdup_printf ("%s --id %s", GDM_SLAVE_COMMAND, slave->priv->display_id);
-
- if (! g_shell_parse_argv (command, NULL, &argv, &error)) {
- g_warning ("Could not parse command: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- error = NULL;
- result = g_spawn_async_with_pipes (NULL,
- argv,
- NULL,
- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
- NULL,
- NULL,
- &slave->priv->pid,
- NULL,
- &standard_output,
- &standard_error,
- &error);
-
- if (! result) {
- g_warning ("Could not start command '%s': %s", command, error->message);
- g_error_free (error);
- g_strfreev (argv);
- goto out;
- }
-
- g_strfreev (argv);
-
- /* output channel */
- channel = g_io_channel_unix_new (standard_output);
- g_io_channel_set_close_on_unref (channel, TRUE);
- g_io_channel_set_flags (channel,
- g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK,
- NULL);
- slave->priv->output_watch_id = g_io_add_watch (channel,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- (GIOFunc)output_watch,
- slave);
- g_io_channel_unref (channel);
-
- /* error channel */
- channel = g_io_channel_unix_new (standard_error);
- g_io_channel_set_close_on_unref (channel, TRUE);
- g_io_channel_set_flags (channel,
- g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK,
- NULL);
- slave->priv->error_watch_id = g_io_add_watch (channel,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- (GIOFunc)error_watch,
- slave);
- g_io_channel_unref (channel);
-
- result = TRUE;
-
- out:
- g_free (command);
-
- return result;
-}
-
-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 void
-kill_slave (GdmSlave *slave)
-{
- if (slave->priv->pid <= 1) {
- return;
- }
-
- signal_pid (slave->priv->pid, SIGTERM);
-
- /* watch should call slave_died */
-}
-
static void
set_busy_cursor (GdmSlave *slave)
{
@@ -435,7 +188,6 @@ get_script_environment (GdmSlave *slave,
const char *username)
{
GPtrArray *env;
- char **l;
GHashTable *hash;
struct passwd *pwent;
char *x_servers_file;
@@ -445,14 +197,6 @@ get_script_environment (GdmSlave *slave,
/* 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
-
/* modify environment here */
g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup ("/"));
g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup ("/"));
@@ -619,6 +363,7 @@ on_session_started (GdmSession *session,
GdmSlave *slave)
{
g_debug ("session started on pid %d\n", (int) pid);
+ g_signal_emit (slave, signals [SESSION_STARTED], 0, pid);
}
static void
@@ -627,7 +372,7 @@ on_session_exited (GdmSession *session,
GdmSlave *slave)
{
g_debug ("session exited with code %d\n", exit_code);
- exit (0);
+ g_signal_emit (slave, signals [SESSION_EXITED], 0, exit_code);
}
static void
@@ -638,15 +383,159 @@ on_session_died (GdmSession *session,
g_debug ("session died with signal %d, (%s)",
signal_number,
g_strsignal (signal_number));
- exit (1);
+ g_signal_emit (slave, signals [SESSION_DIED], 0, signal_number);
+}
+
+static gboolean
+is_prog_in_path (const char *prog)
+{
+ char *f;
+ gboolean ret;
+
+ f = g_find_program_in_path (prog);
+ ret = (f != NULL);
+ g_free (f);
+ return ret;
+}
+
+static gboolean
+get_session_command (const char *file,
+ char **command)
+{
+ GKeyFile *key_file;
+ GError *error;
+ char *full_path;
+ char *exec;
+ gboolean ret;
+ gboolean res;
+ const char *search_dirs[] = {
+ "/etc/X11/sessions/",
+ DMCONFDIR "/Sessions/",
+ DATADIR "/gdm/BuiltInSessions/",
+ DATADIR "/xsessions/",
+ NULL
+ };
+
+ exec = NULL;
+ ret = FALSE;
+ if (command != NULL) {
+ *command = NULL;
+ }
+
+ key_file = g_key_file_new ();
+
+ error = NULL;
+ full_path = NULL;
+ res = g_key_file_load_from_dirs (key_file,
+ file,
+ search_dirs,
+ &full_path,
+ G_KEY_FILE_NONE,
+ &error);
+ if (! res) {
+ g_debug ("File '%s' not found: %s", file, error->message);
+ g_error_free (error);
+ if (command != NULL) {
+ *command = NULL;
+ }
+ goto out;
+ }
+
+ error = NULL;
+ res = g_key_file_get_boolean (key_file,
+ G_KEY_FILE_DESKTOP_GROUP,
+ G_KEY_FILE_DESKTOP_KEY_HIDDEN,
+ &error);
+ if (error == NULL && res) {
+ g_debug ("Session %s is marked as hidden", file);
+ goto out;
+ }
+
+ error = NULL;
+ exec = g_key_file_get_string (key_file,
+ G_KEY_FILE_DESKTOP_GROUP,
+ G_KEY_FILE_DESKTOP_KEY_TRY_EXEC,
+ &error);
+ if (exec == NULL) {
+ g_debug ("%s key not found", G_KEY_FILE_DESKTOP_KEY_TRY_EXEC);
+ goto out;
+ }
+
+ res = is_prog_in_path (exec);
+ g_free (exec);
+
+ if (! res) {
+ g_debug ("Command not found: %s", G_KEY_FILE_DESKTOP_KEY_TRY_EXEC);
+ goto out;
+ }
+
+ error = NULL;
+ exec = g_key_file_get_string (key_file,
+ G_KEY_FILE_DESKTOP_GROUP,
+ G_KEY_FILE_DESKTOP_KEY_EXEC,
+ &error);
+ if (error != NULL) {
+ g_debug ("%s key not found: %s",
+ G_KEY_FILE_DESKTOP_KEY_EXEC,
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ if (command != NULL) {
+ *command = g_strdup (exec);
+ }
+ ret = TRUE;
+
+out:
+ g_free (exec);
+
+ return ret;
+}
+
+static void
+setup_session_environment (GdmSlave *slave)
+{
+
+ gdm_session_set_environment_variable (slave->priv->session,
+ "GDMSESSION",
+ slave->priv->selected_session);
+ gdm_session_set_environment_variable (slave->priv->session,
+ "DESKTOP_SESSION",
+ slave->priv->selected_session);
+
+ gdm_session_set_environment_variable (slave->priv->session,
+ "LANG",
+ slave->priv->selected_language);
+ gdm_session_set_environment_variable (slave->priv->session,
+ "GDM_LANG",
+ slave->priv->selected_language);
+
+ gdm_session_set_environment_variable (slave->priv->session,
+ "DISPLAY",
+ slave->priv->display_name);
+ gdm_session_set_environment_variable (slave->priv->session,
+ "XAUTHORITY",
+ slave->priv->display_x11_authority_file);
+
+ gdm_session_set_environment_variable (slave->priv->session,
+ "PATH",
+ "/bin:/usr/bin:" BINDIR);
}
static void
on_user_verified (GdmSession *session,
GdmSlave *slave)
{
- char *username;
- const char *args[] = { "/usr/bin/gedit", "/tmp/foo.log", NULL };
+ char *username;
+ int argc;
+ char **argv;
+ char *command;
+ char *filename;
+ GError *error;
+ gboolean res;
+
+ gdm_greeter_proxy_stop (slave->priv->greeter);
username = gdm_session_get_username (session);
@@ -655,7 +544,34 @@ on_user_verified (GdmSession *session,
username ? " " : "");
g_free (username);
- gdm_session_start_program (session, args);
+ if (slave->priv->selected_session != NULL) {
+ filename = g_strdup (slave->priv->selected_session);
+ } else {
+ filename = g_strdup ("gnome.desktop");
+ }
+
+ setup_session_environment (slave);
+
+ res = get_session_command (filename, &command);
+ if (! res) {
+ g_warning ("Could find session file: %s", filename);
+ return;
+ }
+
+ error = NULL;
+ res = g_shell_parse_argv (command, &argc, &argv, &error);
+ if (! res) {
+ g_warning ("Could not parse command: %s", error->message);
+ g_error_free (error);
+ }
+
+ gdm_session_start_program (session,
+ argc,
+ (const char **)argv);
+
+ g_free (filename);
+ g_free (command);
+ g_strfreev (argv);
}
static void
@@ -721,6 +637,24 @@ on_greeter_answer (GdmGreeterProxy *greeter,
}
static void
+on_greeter_session_selected (GdmGreeterProxy *greeter,
+ const char *text,
+ GdmSlave *slave)
+{
+ g_free (slave->priv->selected_session);
+ slave->priv->selected_session = g_strdup (text);
+}
+
+static void
+on_greeter_language_selected (GdmGreeterProxy *greeter,
+ const char *text,
+ GdmSlave *slave)
+{
+ g_free (slave->priv->selected_language);
+ slave->priv->selected_language = g_strdup (text);
+}
+
+static void
on_greeter_start (GdmGreeterProxy *greeter,
GdmSlave *slave)
{
@@ -812,12 +746,10 @@ run_greeter (GdmSlave *slave)
"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),
@@ -825,10 +757,18 @@ run_greeter (GdmSlave *slave)
slave->priv->greeter = gdm_greeter_proxy_new (slave->priv->display_name);
g_signal_connect (slave->priv->greeter,
- "answer",
+ "query-answer",
G_CALLBACK (on_greeter_answer),
slave);
g_signal_connect (slave->priv->greeter,
+ "session-selected",
+ G_CALLBACK (on_greeter_session_selected),
+ slave);
+ g_signal_connect (slave->priv->greeter,
+ "language-selected",
+ G_CALLBACK (on_greeter_language_selected),
+ slave);
+ g_signal_connect (slave->priv->greeter,
"started",
G_CALLBACK (on_greeter_start),
slave);
@@ -1246,6 +1186,42 @@ gdm_slave_class_init (GdmSlaveClass *klass)
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ signals [SESSION_STARTED] =
+ g_signal_new ("session-started",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmSlaveClass, session_started),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_INT);
+
+ signals [SESSION_EXITED] =
+ g_signal_new ("session-exited",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmSlaveClass, session_exited),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_INT);
+
+ signals [SESSION_DIED] =
+ g_signal_new ("session-died",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GdmSlaveClass, session_exited),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_INT);
+
dbus_g_object_type_install_info (GDM_TYPE_SLAVE, &dbus_glib_gdm_slave_object_info);
}
diff --git a/daemon/gdm-slave.h b/daemon/gdm-slave.h
index ffc198ae..8c96d6cb 100644
--- a/daemon/gdm-slave.h
+++ b/daemon/gdm-slave.h
@@ -37,7 +37,7 @@ typedef struct GdmSlavePrivate GdmSlavePrivate;
typedef struct
{
- GObject parent;
+ GObject parent;
GdmSlavePrivate *priv;
} GdmSlave;
@@ -45,6 +45,12 @@ typedef struct
{
GObjectClass parent_class;
+ void (* session_started) (GdmSlave *slave,
+ GPid pid);
+ void (* session_exited) (GdmSlave *slave,
+ int exit_code);
+ void (* session_died) (GdmSlave *slave,
+ int signal_number);
} GdmSlaveClass;
GType gdm_slave_get_type (void);
diff --git a/daemon/slave-main.c b/daemon/slave-main.c
index aa9fef5f..c75651ef 100644
--- a/daemon/slave-main.c
+++ b/daemon/slave-main.c
@@ -42,6 +42,8 @@
#include "gdm-log.h"
#include "gdm-slave.h"
+static int gdm_return_code = 0;
+
static DBusGConnection *
get_system_bus (void)
{
@@ -129,6 +131,28 @@ signal_cb (int signo,
return ret;
}
+static void
+on_session_exited (GdmSlave *slave,
+ int exit_code,
+ GMainLoop *main_loop)
+{
+ g_debug ("session exited with code %d\n", exit_code);
+ gdm_return_code = exit_code;
+ g_main_loop_quit (main_loop);
+}
+
+static void
+on_session_died (GdmSlave *slave,
+ int signal_number,
+ GMainLoop *main_loop)
+{
+ g_debug ("session died with signal %d, (%s)",
+ signal_number,
+ g_strsignal (signal_number));
+ gdm_return_code = 1;
+ g_main_loop_quit (main_loop);
+}
+
int
main (int argc,
char **argv)
@@ -136,7 +160,6 @@ main (int argc,
GMainLoop *main_loop;
GOptionContext *context;
DBusGConnection *connection;
- int ret;
GdmSlave *slave;
static char *display_id = NULL;
GdmSignalHandler *signal_handler;
@@ -149,8 +172,6 @@ main (int argc,
textdomain (GETTEXT_PACKAGE);
setlocale (LC_ALL, "");
- ret = 1;
-
g_type_init ();
context = g_option_context_new (_("GNOME Display Manager Slave"));
@@ -191,6 +212,15 @@ main (int argc,
if (slave == NULL) {
goto out;
}
+ g_signal_connect (slave,
+ "session-exited",
+ G_CALLBACK (on_session_exited),
+ main_loop);
+ g_signal_connect (slave,
+ "session-died",
+ G_CALLBACK (on_session_died),
+ main_loop);
+
gdm_slave_start (slave);
g_main_loop_run (main_loop);
@@ -205,11 +235,9 @@ main (int argc,
g_main_loop_unref (main_loop);
- ret = 0;
-
out:
g_debug ("Slave finished");
- return ret;
+ return gdm_return_code;
}
diff --git a/daemon/test-session.c b/daemon/test-session.c
index ec807e67..73c7ab4d 100644
--- a/daemon/test-session.c
+++ b/daemon/test-session.c
@@ -61,7 +61,7 @@ static void
on_user_verified (GdmSession *session)
{
char *username;
- const char *args[] = { "/usr/bin/gedit", "/tmp/foo.log", NULL };
+ const char *argv[] = { "/usr/bin/gedit", "/tmp/foo.log", NULL };
username = gdm_session_get_username (session);
@@ -69,7 +69,7 @@ on_user_verified (GdmSession *session)
username? username : "", username? " " : "");
g_free (username);
- gdm_session_start_program (session, args);
+ gdm_session_start_program (session, 2, argv);
}
static void
@@ -169,8 +169,6 @@ main (int argc,
GdmSession *session;
char *username;
int exit_code;
- char **args;
- int i;
exit_code = 0;
diff --git a/gui/Makefile.am b/gui/Makefile.am
index c4c416c3..b26f4e69 100644
--- a/gui/Makefile.am
+++ b/gui/Makefile.am
@@ -1,6 +1,6 @@
NULL =
-SUBDIRS =
+SUBDIRS = \
. \
greeter \
modules \
@@ -24,7 +24,7 @@ DEFS = @DEFS@ \
-DSBINDIR=\"@sbindir@\" \
$(NULL)
-INCLUDES = \
+INCLUDES = \
-I. \
-I.. \
-I$(top_srcdir)/daemon \
diff --git a/gui/gdm-greeter.c b/gui/gdm-greeter.c
index 2d8c3772..8667d1e4 100644
--- a/gui/gdm-greeter.c
+++ b/gui/gdm-greeter.c
@@ -48,6 +48,8 @@ enum {
enum {
QUERY_ANSWER,
+ SESSION_SELECTED,
+ LANGUAGE_SELECTED,
LAST_SIGNAL
};
@@ -220,6 +222,34 @@ gdm_greeter_answer_query (GdmGreeter *greeter,
g_debug ("Answer query: %s", text);
g_signal_emit (greeter, signals[QUERY_ANSWER], 0, text);
+
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_select_session (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ g_debug ("Select session: %s", text);
+
+ g_signal_emit (greeter, signals[SESSION_SELECTED], 0, text);
+
+ return TRUE;
+}
+
+gboolean
+gdm_greeter_select_language (GdmGreeter *greeter,
+ const char *text)
+{
+ g_return_val_if_fail (GDM_IS_GREETER (greeter), FALSE);
+
+ g_debug ("Select language: %s", text);
+
+ g_signal_emit (greeter, signals[LANGUAGE_SELECTED], 0, text);
+
+ return TRUE;
}
static void
@@ -263,7 +293,6 @@ gdm_greeter_constructor (GType type,
{
GdmGreeter *greeter;
GdmGreeterClass *klass;
- gboolean res;
klass = GDM_GREETER_CLASS (g_type_class_peek (GDM_TYPE_GREETER));
@@ -316,6 +345,26 @@ gdm_greeter_class_init (GdmGreeterClass *klass)
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE,
1, G_TYPE_STRING);
+ signals [LANGUAGE_SELECTED] =
+ g_signal_new ("language-selected",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GdmGreeterClass, language_selected),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+ signals [SESSION_SELECTED] =
+ g_signal_new ("session-selected",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GdmGreeterClass, session_selected),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
g_type_class_add_private (klass, sizeof (GdmGreeterPrivate));
}
diff --git a/gui/gdm-greeter.h b/gui/gdm-greeter.h
index 59b20e5c..c54f6baf 100644
--- a/gui/gdm-greeter.h
+++ b/gui/gdm-greeter.h
@@ -48,6 +48,11 @@ typedef struct
/* signals */
void (* query_answer) (GdmGreeter *greeter,
const char *text);
+ void (* session_selected) (GdmGreeter *greeter,
+ const char *text);
+ void (* language_selected) (GdmGreeter *greeter,
+ const char *text);
+
/* methods */
gboolean (*start) (GdmGreeter *greeter);
gboolean (*stop) (GdmGreeter *greeter);
@@ -76,9 +81,15 @@ GType gdm_greeter_get_type (void);
gboolean gdm_greeter_start (GdmGreeter *greeter);
gboolean gdm_greeter_stop (GdmGreeter *greeter);
+/* emit signals */
gboolean gdm_greeter_answer_query (GdmGreeter *greeter,
const char *text);
+gboolean gdm_greeter_select_session (GdmGreeter *greeter,
+ const char *text);
+gboolean gdm_greeter_select_language (GdmGreeter *greeter,
+ const char *text);
+/* actions */
gboolean gdm_greeter_info_query (GdmGreeter *greeter,
const char *text);
gboolean gdm_greeter_secret_info_query (GdmGreeter *greeter,
diff --git a/gui/greeter/greeter.c b/gui/greeter/greeter.c
index 3a0ec4ff..b7a83674 100644
--- a/gui/greeter/greeter.c
+++ b/gui/greeter/greeter.c
@@ -121,6 +121,52 @@ on_query_answer (GdmGreeter *greeter,
}
static void
+on_select_session (GdmGreeter *greeter,
+ const char *text,
+ gpointer data)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("GREETER session selected: %s", text);
+
+ error = NULL;
+ res = dbus_g_proxy_call (server_proxy,
+ "SelectSession",
+ &error,
+ G_TYPE_STRING, text,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (! res) {
+ g_warning ("Unable to send SelectSession: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+on_select_language (GdmGreeter *greeter,
+ const char *text,
+ gpointer data)
+{
+ gboolean res;
+ GError *error;
+
+ g_debug ("GREETER session selected: %s", text);
+
+ error = NULL;
+ res = dbus_g_proxy_call (server_proxy,
+ "SelectLanguage",
+ &error,
+ G_TYPE_STRING, text,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (! res) {
+ g_warning ("Unable to send SelectLanguage: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
proxy_destroyed (GObject *object,
gpointer data)
{
@@ -222,6 +268,15 @@ main (int argc, char *argv[])
"query-answer",
G_CALLBACK (on_query_answer),
NULL);
+ g_signal_connect (greeter,
+ "session-selected",
+ G_CALLBACK (on_select_session),
+ NULL);
+ g_signal_connect (greeter,
+ "language-selected",
+ G_CALLBACK (on_select_language),
+ NULL);
+
gtk_main ();
if (greeter != NULL) {