summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2011-08-30 11:05:53 -0400
committerRay Strode <rstrode@redhat.com>2011-08-30 11:11:20 -0400
commit647cad5bf59a4ff3776ba1ae5cda6b1aaaa1cfb2 (patch)
tree7760192171859f09bfb7c196bca11a1ff9f47447 /daemon
parent2e6e88a4a47d81eb653da8c98e7166260ff49b1f (diff)
downloadgdm-647cad5bf59a4ff3776ba1ae5cda6b1aaaa1cfb2.tar.gz
daemon: run greeter in its own distinct session
Right now before launching the greeter, we create this little ad hoc session that only runs through some of the OS machinery for session registration. This means not only is there duplicate code with GDMs real session handling functions, but the greeter is potentially running in an incomplete session. This commit, inspired by the work of Lennart and Kay, changes GDM to run its greeter session through a session worker just like any other session.
Diffstat (limited to 'daemon')
-rw-r--r--daemon/Makefile.am15
-rw-r--r--daemon/gdm-session-direct.c167
-rw-r--r--daemon/gdm-session-worker.c218
-rw-r--r--daemon/gdm-session.c37
-rw-r--r--daemon/gdm-session.h20
-rw-r--r--daemon/gdm-welcome-session.c483
6 files changed, 577 insertions, 363 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 5b4796a8..98b95ce9 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -166,9 +166,15 @@ gdm_factory_slave_SOURCES = \
gdm-server.h \
gdm-session.c \
gdm-session.h \
+ gdm-session-direct.c \
+ gdm-session-direct.h \
gdm-session-private.h \
+ gdm-session-record.c \
+ gdm-session-record.h \
gdm-session-relay.c \
gdm-session-relay.h \
+ gdm-session-worker-job.c \
+ gdm-session-worker-job.h \
gdm-xerrors.h \
gdm-xerrors.c \
gdm-slave.c \
@@ -226,6 +232,15 @@ gdm_xdmcp_chooser_slave_SOURCES = \
gdm-chooser-server.h \
ck-connector.h \
ck-connector.c \
+ gdm-session.c \
+ gdm-session.h \
+ gdm-session-direct.c \
+ gdm-session-direct.h \
+ gdm-session-private.h \
+ gdm-session-record.c \
+ gdm-session-record.h \
+ gdm-session-worker-job.c \
+ gdm-session-worker-job.h \
gdm-welcome-session.c \
gdm-welcome-session.h \
gdm-chooser-session.c \
diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c
index e9774869..1d5c16a4 100644
--- a/daemon/gdm-session-direct.c
+++ b/daemon/gdm-session-direct.c
@@ -80,6 +80,7 @@ typedef struct
struct _GdmSessionDirectPrivate
{
/* per open scope */
+ char *selected_program;
char *selected_session;
char *saved_session;
char *selected_language;
@@ -1397,6 +1398,12 @@ do_introspect (DBusConnection *connection,
" <arg name=\"x11_authority_file\" type=\"s\"/>\n"
" <arg name=\"username\" type=\"s\"/>\n"
" </signal>\n"
+ " <signal name=\"SetupForProgram\">\n"
+ " <arg name=\"service_name\" type=\"s\"/>\n"
+ " <arg name=\"x11_display_name\" type=\"s\"/>\n"
+ " <arg name=\"x11_authority_file\" type=\"s\"/>\n"
+ " <arg name=\"log_file\" type=\"s\"/>\n"
+ " </signal>\n"
" <signal name=\"Authenticate\">\n"
" </signal>\n"
" <signal name=\"Authorize\">\n"
@@ -1415,6 +1422,9 @@ do_introspect (DBusConnection *connection,
" <signal name=\"SetSessionName\">\n"
" <arg name=\"session_name\" type=\"s\"/>\n"
" </signal>\n"
+ " <signal name=\"SetSessionType\">\n"
+ " <arg name=\"session_type\" type=\"s\"/>\n"
+ " </signal>\n"
" <signal name=\"StartProgram\">\n"
" <arg name=\"command\" type=\"s\"/>\n"
" </signal>\n"
@@ -2035,6 +2045,50 @@ send_setup_for_user (GdmSessionDirect *session,
}
static void
+send_setup_for_program (GdmSessionDirect *session,
+ const char *service_name,
+ const char *log_file)
+{
+ DBusMessage *message;
+ DBusMessageIter iter;
+ const char *display_name;
+ const char *display_x11_authority_file;
+ GdmSessionConversation *conversation;
+
+ g_assert (service_name != NULL);
+
+ if (session->priv->display_name != NULL) {
+ display_name = session->priv->display_name;
+ } else {
+ display_name = "";
+ }
+ if (session->priv->display_x11_authority_file != NULL) {
+ display_x11_authority_file = session->priv->display_x11_authority_file;
+ } else {
+ display_x11_authority_file = "";
+ }
+
+ g_debug ("GdmSessionDirect: Beginning setup for session for program with log '%s'", log_file);
+
+ message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+ GDM_SESSION_DBUS_INTERFACE,
+ "SetupForProgram");
+
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &log_file);
+
+ conversation = find_conversation_by_name (session, service_name);
+ if (conversation != NULL && ! send_dbus_message (conversation, message)) {
+ g_debug ("GdmSessionDirect: Could not send %s signal", "SetupForProgram");
+ }
+
+ dbus_message_unref (message);
+}
+
+static void
gdm_session_direct_setup (GdmSession *session,
const char *service_name)
{
@@ -2063,6 +2117,18 @@ gdm_session_direct_setup_for_user (GdmSession *session,
}
static void
+gdm_session_direct_setup_for_program (GdmSession *session,
+ const char *service_name,
+ const char *log_file)
+{
+ GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
+
+ g_return_if_fail (session != NULL);
+
+ send_setup_for_program (impl, service_name, log_file);
+}
+
+static void
gdm_session_direct_authenticate (GdmSession *session,
const char *service_name)
{
@@ -2194,33 +2260,34 @@ get_session_command (GdmSessionDirect *session)
}
static void
-gdm_session_direct_set_environment_variable (GdmSessionDirect *session,
- const char *key,
- const char *value)
+gdm_session_direct_set_environment_variable (GdmSession *session,
+ const char *key,
+ const char *value)
{
- g_return_if_fail (session != NULL);
- g_return_if_fail (session != NULL);
+ GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
+
g_return_if_fail (key != NULL);
g_return_if_fail (value != NULL);
- g_hash_table_replace (session->priv->environment,
+ g_hash_table_replace (impl->priv->environment,
g_strdup (key),
g_strdup (value));
}
static void
-setup_session_environment (GdmSessionDirect *session)
+setup_session_environment (GdmSessionDirect *session_direct)
{
+ GdmSession *session = GDM_SESSION (session_direct);
const char *locale;
gdm_session_direct_set_environment_variable (session,
"GDMSESSION",
- get_session_name (session));
+ get_session_name (session_direct));
gdm_session_direct_set_environment_variable (session,
"DESKTOP_SESSION",
- get_session_name (session));
+ get_session_name (session_direct));
- locale = get_language_name (session);
+ locale = get_language_name (session_direct);
if (locale != NULL && locale[0] != '\0') {
gdm_session_direct_set_environment_variable (session,
@@ -2233,12 +2300,12 @@ setup_session_environment (GdmSessionDirect *session)
gdm_session_direct_set_environment_variable (session,
"DISPLAY",
- session->priv->display_name);
+ session_direct->priv->display_name);
- if (session->priv->user_x11_authority_file != NULL) {
+ if (session_direct->priv->user_x11_authority_file != NULL) {
gdm_session_direct_set_environment_variable (session,
"XAUTHORITY",
- session->priv->user_x11_authority_file);
+ session_direct->priv->user_x11_authority_file);
}
if (g_getenv ("WINDOWPATH") != NULL) {
@@ -2336,16 +2403,20 @@ gdm_session_direct_start_session (GdmSession *session,
stop_all_other_conversations (impl, conversation);
- command = get_session_command (impl);
+ if (impl->priv->selected_program == NULL) {
+ command = get_session_command (impl);
- if (gdm_session_direct_bypasses_xsession (impl)) {
- program = g_strdup (command);
+ if (gdm_session_direct_bypasses_xsession (impl)) {
+ program = g_strdup (command);
+ } else {
+ program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command);
+ }
+
+ g_free (command);
} else {
- program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command);
+ program = g_strdup (impl->priv->selected_program);
}
- g_free (command);
-
setup_session_environment (impl);
send_environment (impl, conversation);
@@ -2495,6 +2566,35 @@ out:
}
static void
+gdm_session_direct_select_program (GdmSession *session,
+ const char *text)
+{
+ GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
+
+ g_free (impl->priv->selected_program);
+
+ impl->priv->selected_program = g_strdup (text);
+}
+
+static void
+gdm_session_direct_select_session_type (GdmSession *session,
+ const char *text)
+{
+ GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, impl->priv->conversations);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ GdmSessionConversation *conversation;
+
+ conversation = (GdmSessionConversation *) value;
+
+ send_dbus_string_signal (conversation, "SetSessionType",
+ text);
+ }
+}
+static void
gdm_session_direct_select_session (GdmSession *session,
const char *text)
{
@@ -2781,21 +2881,22 @@ gdm_session_direct_constructor (GType type,
session = GDM_SESSION_DIRECT (G_OBJECT_CLASS (gdm_session_direct_parent_class)->constructor (type,
n_construct_properties,
construct_properties));
+ if (session->priv->display_id != NULL) {
+ /* Always match the session id with the master */
+ id = NULL;
+ if (g_str_has_prefix (session->priv->display_id, "/org/gnome/DisplayManager/Display")) {
+ id = session->priv->display_id + strlen ("/org/gnome/DisplayManager/Display");
+ }
- /* Always match the session id with the master */
- id = NULL;
- if (g_str_has_prefix (session->priv->display_id, "/org/gnome/DisplayManager/Display")) {
- id = session->priv->display_id + strlen ("/org/gnome/DisplayManager/Display");
- }
-
- g_assert (id != NULL);
+ g_assert (id != NULL);
- session->priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Session%s", id);
- g_debug ("GdmSessionDirect: Registering %s", session->priv->id);
+ session->priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Session%s", id);
+ g_debug ("GdmSessionDirect: Registering %s", session->priv->id);
- res = register_session (session);
- if (! res) {
- g_warning ("Unable to register session with system bus");
+ res = register_session (session);
+ if (! res) {
+ g_warning ("Unable to register session with system bus");
+ }
}
return G_OBJECT (session);
@@ -2808,6 +2909,8 @@ gdm_session_iface_init (GdmSessionIface *iface)
iface->stop_conversation = gdm_session_direct_stop_conversation;
iface->setup = gdm_session_direct_setup;
iface->setup_for_user = gdm_session_direct_setup_for_user;
+ iface->setup_for_program = gdm_session_direct_setup_for_program;
+ iface->set_environment_variable = gdm_session_direct_set_environment_variable;
iface->authenticate = gdm_session_direct_authenticate;
iface->authorize = gdm_session_direct_authorize;
iface->accredit = gdm_session_direct_accredit;
@@ -2817,6 +2920,8 @@ gdm_session_iface_init (GdmSessionIface *iface)
iface->cancel = gdm_session_direct_cancel;
iface->start_session = gdm_session_direct_start_session;
iface->answer_query = gdm_session_direct_answer_query;
+ iface->select_program = gdm_session_direct_select_program;
+ iface->select_session_type = gdm_session_direct_select_session_type;
iface->select_session = gdm_session_direct_select_session;
iface->select_language = gdm_session_direct_select_language;
iface->select_user = gdm_session_direct_select_user;
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 1c44b172..2b46ca85 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -85,6 +85,7 @@
#endif
#define MAX_FILE_SIZE 65536
+#define MAX_LOGS 5
enum {
GDM_SESSION_WORKER_STATE_NONE = 0,
@@ -119,6 +120,8 @@ struct GdmSessionWorkerPrivate
char *display_device;
char *hostname;
char *username;
+ char *log_file;
+ char *session_type;
uid_t uid;
gid_t gid;
gboolean password_is_required;
@@ -128,6 +131,7 @@ struct GdmSessionWorkerPrivate
char **arguments;
guint32 cancelled : 1;
guint32 timed_out : 1;
+ guint32 is_program_session : 1;
guint state_change_idle_id;
char *server_address;
@@ -176,6 +180,7 @@ open_ck_session (GdmSessionWorker *worker)
const char *display_name;
const char *display_device;
const char *display_hostname;
+ const char *session_type;
gboolean is_local;
ret = FALSE;
@@ -196,6 +201,12 @@ open_ck_session (GdmSessionWorker *worker)
display_device = "";
}
+ if (worker->priv->session_type != NULL) {
+ session_type = worker->priv->session_type;
+ } else {
+ session_type = "";
+ }
+
g_assert (worker->priv->username != NULL);
/* FIXME: this isn't very good */
@@ -226,6 +237,7 @@ open_ck_session (GdmSessionWorker *worker)
"x11-display-device", &display_device,
"remote-host-name", &display_hostname,
"is-local", &is_local,
+ "session-type", &session_type,
NULL);
if (! res) {
@@ -931,6 +943,13 @@ gdm_session_worker_pam_new_messages_handler (int number_o
static void
gdm_session_worker_start_auditor (GdmSessionWorker *worker)
{
+ /* Use dummy auditor so program session doesn't pollute user audit logs
+ */
+ if (worker->priv->is_program_session) {
+ worker->priv->auditor = gdm_session_auditor_new (worker->priv->hostname,
+ worker->priv->display_device);
+ return;
+ }
/* FIXME: it may make sense at some point to keep a list of
* auditors, instead of assuming they are mutually exclusive
@@ -1238,7 +1257,7 @@ gdm_session_worker_authorize_user (GdmSessionWorker *worker,
/* it's possible that the user needs to change their password or pin code
*/
- if (error_code == PAM_NEW_AUTHTOK_REQD) {
+ if (error_code == PAM_NEW_AUTHTOK_REQD && !worker->priv->is_program_session) {
error_code = pam_chauthtok (worker->priv->pam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
gdm_session_worker_get_username (worker, NULL);
@@ -1624,8 +1643,85 @@ _is_loggable_file (const char* filename)
return S_ISREG (file_info.st_mode) && g_access (filename, R_OK | W_OK) == 0;
}
+static void
+rotate_logs (const char *path,
+ guint n_copies)
+{
+ int i;
+
+ for (i = n_copies - 1; i > 0; i--) {
+ char *name_n;
+ char *name_n1;
+
+ name_n = g_strdup_printf ("%s.%d", path, i);
+ if (i > 1) {
+ name_n1 = g_strdup_printf ("%s.%d", path, i - 1);
+ } else {
+ name_n1 = g_strdup (path);
+ }
+
+ g_unlink (name_n);
+ g_rename (name_n1, name_n);
+
+ g_free (name_n1);
+ g_free (name_n);
+ }
+
+ g_unlink (path);
+}
+
+static int
+_open_program_session_log (const char *filename)
+{
+ int fd;
+
+ rotate_logs (filename, MAX_LOGS);
+
+ fd = g_open (filename, O_RDWR | O_APPEND | O_CREAT, 0600);
+
+ if (fd < 0) {
+ char *temp_name;
+
+ close (fd);
+
+ temp_name = g_strdup_printf ("%s.XXXXXXXX", filename);
+
+ fd = g_mkstemp (temp_name);
+
+ if (fd < 0) {
+ g_free (temp_name);
+ goto out;
+ }
+
+ g_warning ("session log '%s' is not appendable, logging session to '%s' instead.\n", filename,
+ temp_name);
+ g_free (temp_name);
+ } else {
+ if (ftruncate (fd, 0) < 0) {
+ close (fd);
+ fd = -1;
+ goto out;
+ }
+ }
+
+ if (fchmod (fd, 0644) < 0) {
+ close (fd);
+ fd = -1;
+ goto out;
+ }
+
+
+out:
+ if (fd < 0) {
+ g_warning ("unable to log program session");
+ fd = g_open ("/dev/null", O_RDWR);
+ }
+
+ return fd;
+}
+
static int
-_open_session_log (const char *dir)
+_open_user_session_log (const char *dir)
{
int fd;
char *filename;
@@ -1687,8 +1783,8 @@ out:
}
static gboolean
-gdm_session_worker_start_user_session (GdmSessionWorker *worker,
- GError **error)
+gdm_session_worker_start_session (GdmSessionWorker *worker,
+ GError **error)
{
struct passwd *passwd_entry;
pid_t session_pid;
@@ -1697,8 +1793,13 @@ gdm_session_worker_start_user_session (GdmSessionWorker *worker,
register_ck_session (worker);
gdm_get_pwent_for_name (worker->priv->username, &passwd_entry);
- g_debug ("GdmSessionWorker: opening user session with program '%s'",
- worker->priv->arguments[0]);
+ if (worker->priv->is_program_session) {
+ g_debug ("GdmSessionWorker: opening session for program '%s'",
+ worker->priv->arguments[0]);
+ } else {
+ g_debug ("GdmSessionWorker: opening user session with program '%s'",
+ worker->priv->arguments[0]);
+ }
error_code = PAM_SUCCESS;
@@ -1743,7 +1844,11 @@ gdm_session_worker_start_user_session (GdmSessionWorker *worker,
dup2 (fd, STDIN_FILENO);
close (fd);
- fd = _open_session_log (home_dir);
+ if (worker->priv->is_program_session) {
+ fd = _open_program_session_log (worker->priv->log_file);
+ } else {
+ fd = _open_user_session_log (home_dir);
+ }
dup2 (fd, STDOUT_FILENO);
dup2 (fd, STDERR_FILENO);
close (fd);
@@ -1790,15 +1895,22 @@ gdm_session_worker_start_user_session (GdmSessionWorker *worker,
}
static gboolean
-gdm_session_worker_open_user_session (GdmSessionWorker *worker,
- GError **error)
+gdm_session_worker_open_session (GdmSessionWorker *worker,
+ GError **error)
{
int error_code;
+ int flags;
g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED);
g_assert (geteuid () == 0);
- error_code = pam_open_session (worker->priv->pam_handle, 0);
+ flags = 0;
+
+ if (worker->priv->is_program_session) {
+ flags |= PAM_SILENT;
+ }
+
+ error_code = pam_open_session (worker->priv->pam_handle, flags);
if (error_code != PAM_SUCCESS) {
g_set_error (error,
@@ -1926,6 +2038,36 @@ on_set_session_name (GdmSessionWorker *worker,
}
static void
+gdm_session_worker_set_session_type (GdmSessionWorker *worker,
+ const char *session_type)
+{
+ g_free (worker->priv->session_type);
+ worker->priv->session_type = g_strdup (session_type);
+}
+
+static void
+on_set_session_type (GdmSessionWorker *worker,
+ DBusMessage *message)
+{
+ DBusError error;
+ const char *session_type;
+ dbus_bool_t res;
+
+ dbus_error_init (&error);
+ res = dbus_message_get_args (message,
+ &error,
+ DBUS_TYPE_STRING, &session_type,
+ DBUS_TYPE_INVALID);
+ if (res) {
+ g_debug ("GdmSessionWorker: session type set to %s", session_type);
+ gdm_session_worker_set_session_type (worker, session_type);
+ } else {
+ g_warning ("Unable to get arguments: %s", error.message);
+ dbus_error_free (&error);
+ }
+}
+
+static void
gdm_session_worker_set_language_name (GdmSessionWorker *worker,
const char *language_name)
{
@@ -2060,8 +2202,10 @@ do_authenticate (GdmSessionWorker *worker)
/* we're authenticated. Let's make sure we've been given
* a valid username for the system
*/
- g_debug ("GdmSessionWorker: trying to get updated username");
- gdm_session_worker_update_username (worker);
+ if (!worker->priv->is_program_session) {
+ g_debug ("GdmSessionWorker: trying to get updated username");
+ gdm_session_worker_update_username (worker);
+ }
send_dbus_void_method (worker->priv->connection, "Authenticated");
}
@@ -2176,7 +2320,7 @@ do_open_session (GdmSessionWorker *worker)
gboolean res;
error = NULL;
- res = gdm_session_worker_open_user_session (worker, &error);
+ res = gdm_session_worker_open_session (worker, &error);
if (! res) {
send_dbus_string_method (worker->priv->connection,
"OpenFailed",
@@ -2195,7 +2339,7 @@ do_start_session (GdmSessionWorker *worker)
gboolean res;
error = NULL;
- res = gdm_session_worker_start_user_session (worker, &error);
+ res = gdm_session_worker_start_session (worker, &error);
if (! res) {
send_dbus_string_method (worker->priv->connection,
"StartFailed",
@@ -2447,6 +2591,48 @@ on_setup_for_user (GdmSessionWorker *worker,
}
static void
+on_setup_for_program (GdmSessionWorker *worker,
+ DBusMessage *message)
+{
+ DBusError error;
+ char *service;
+ char *x11_display_name;
+ char *x11_authority_file;
+ char *log_file;
+ dbus_bool_t res;
+
+ if (worker->priv->state != GDM_SESSION_WORKER_STATE_NONE) {
+ g_debug ("GdmSessionWorker: ignoring spurious setup for program while in state %s", get_state_name (worker->priv->state));
+ return;
+ }
+
+ dbus_error_init (&error);
+ res = dbus_message_get_args (message,
+ &error,
+ DBUS_TYPE_STRING, &service,
+ DBUS_TYPE_STRING, &x11_display_name,
+ DBUS_TYPE_STRING, &x11_authority_file,
+ DBUS_TYPE_STRING, &log_file,
+ DBUS_TYPE_INVALID);
+ if (res) {
+ g_debug ("GdmSessionWorker: program with log file '%s'", log_file);
+
+ queue_state_change (worker);
+ worker->priv->service = g_strdup (service);
+ worker->priv->username = g_strdup (GDM_USERNAME);
+ worker->priv->x11_display_name = g_strdup (x11_display_name);
+ worker->priv->x11_authority_file = g_strdup (x11_authority_file);
+ worker->priv->log_file = g_strdup (log_file);
+ worker->priv->is_program_session = TRUE;
+
+ queue_state_change (worker);
+ } else {
+ g_warning ("Unable to get arguments: %s", error.message);
+ dbus_error_free (&error);
+ }
+}
+
+static void
on_authenticate (GdmSessionWorker *worker,
DBusMessage *message)
{
@@ -2562,6 +2748,8 @@ worker_dbus_handle_message (DBusConnection *connection,
on_setup (worker, message);
} else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "SetupForUser")) {
on_setup_for_user (worker, message);
+ } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "SetupForProgram")) {
+ on_setup_for_program (worker, message);
} else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "Authenticate")) {
on_authenticate (worker, message);
} else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "Authorize")) {
@@ -2584,6 +2772,8 @@ worker_dbus_handle_message (DBusConnection *connection,
on_set_language_name (worker, message);
} else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "SetSessionName")) {
on_set_session_name (worker, message);
+ } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "SetSessionType")) {
+ on_set_session_type (worker, message);
} else {
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 200e3d76..5ba9fd1a 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -126,6 +126,26 @@ gdm_session_setup_for_user (GdmSession *session,
}
void
+gdm_session_setup_for_program (GdmSession *session,
+ const char *service_name,
+ const char *log_file)
+{
+ g_return_if_fail (GDM_IS_SESSION (session));
+
+ GDM_SESSION_GET_IFACE (session)->setup_for_program (session, service_name, log_file);
+}
+
+void
+gdm_session_set_environment_variable (GdmSession *session,
+ const char *key,
+ const char *value)
+{
+ g_return_if_fail (GDM_IS_SESSION (session));
+
+ GDM_SESSION_GET_IFACE (session)->set_environment_variable (session, key, value);
+}
+
+void
gdm_session_authenticate (GdmSession *session,
const char *service_name)
{
@@ -164,6 +184,23 @@ gdm_session_answer_query (GdmSession *session,
}
void
+gdm_session_select_program (GdmSession *session,
+ const char *text)
+{
+ g_return_if_fail (GDM_IS_SESSION (session));
+
+ GDM_SESSION_GET_IFACE (session)->select_program (session, text);
+}
+
+void
+gdm_session_select_session_type (GdmSession *session,
+ const char *text)
+{
+ g_return_if_fail (GDM_IS_SESSION (session));
+
+ GDM_SESSION_GET_IFACE (session)->select_session_type (session, text);
+}
+void
gdm_session_select_session (GdmSession *session,
const char *text)
{
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index ab160318..17accb28 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -56,6 +56,12 @@ struct _GdmSessionIface
void (* setup_for_user) (GdmSession *session,
const char *service_name,
const char *username);
+ void (* setup_for_program) (GdmSession *session,
+ const char *service_name,
+ const char *log_file);
+ void (* set_environment_variable) (GdmSession *session,
+ const char *key,
+ const char *value);
void (* reset) (GdmSession *session);
void (* authenticate) (GdmSession *session,
const char *service_name);
@@ -71,6 +77,10 @@ struct _GdmSessionIface
const char *text);
void (* select_language) (GdmSession *session,
const char *text);
+ void (* select_program) (GdmSession *session,
+ const char *text);
+ void (* select_session_type) (GdmSession *session,
+ const char *session_type);
void (* select_session) (GdmSession *session,
const char *text);
void (* select_user) (GdmSession *session,
@@ -157,6 +167,12 @@ void gdm_session_setup (GdmSession *session,
void gdm_session_setup_for_user (GdmSession *session,
const char *service_name,
const char *username);
+void gdm_session_setup_for_program (GdmSession *session,
+ const char *service_name,
+ const char *log_file);
+void gdm_session_set_environment_variable (GdmSession *session,
+ const char *key,
+ const char *value);
void gdm_session_reset (GdmSession *session);
void gdm_session_authenticate (GdmSession *session,
const char *service_name);
@@ -174,6 +190,10 @@ void gdm_session_close (GdmSession *session);
void gdm_session_answer_query (GdmSession *session,
const char *service_name,
const char *text);
+void gdm_session_select_program (GdmSession *session,
+ const char *command_line);
+void gdm_session_select_session_type (GdmSession *session,
+ const char *session_type);
void gdm_session_select_session (GdmSession *session,
const char *session_name);
void gdm_session_select_language (GdmSession *session,
diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c
index 04b3d077..63000f1c 100644
--- a/daemon/gdm-welcome-session.c
+++ b/daemon/gdm-welcome-session.c
@@ -44,6 +44,8 @@
#include "gdm-common.h"
#include "ck-connector.h"
+#include "gdm-session.h"
+#include "gdm-session-direct.h"
#include "gdm-welcome-session.h"
#define DBUS_LAUNCH_COMMAND BINDIR "/dbus-launch"
@@ -56,10 +58,8 @@ extern char **environ;
struct GdmWelcomeSessionPrivate
{
+ GdmSession *session;
char *command;
- GPid pid;
-
- CkConnector *ckc;
char *user_name;
char *group_name;
@@ -72,8 +72,6 @@ struct GdmWelcomeSessionPrivate
char *x11_authority_file;
gboolean x11_display_is_local;
- guint child_watch_id;
-
GPid dbus_pid;
char *dbus_bus_address;
char *server_dbus_path;
@@ -130,116 +128,6 @@ listify_hash (const char *key,
g_ptr_array_add (env, str);
}
-static gboolean
-open_welcome_session (GdmWelcomeSession *welcome_session)
-{
- struct passwd *pwent;
- const char *session_type;
- const char *hostname;
- const char *x11_display_device;
- int res;
- gboolean ret;
- DBusError error;
-
- ret = FALSE;
-
- g_debug ("GdmWelcomeSession: Registering session with ConsoleKit");
-
- session_type = "LoginWindow";
-
- gdm_get_pwent_for_name (welcome_session->priv->user_name, &pwent);
- if (pwent == NULL) {
- /* FIXME: */
- g_warning ("Couldn't look up uid");
- goto out;
- }
-
- welcome_session->priv->ckc = ck_connector_new ();
- if (welcome_session->priv->ckc == NULL) {
- g_warning ("Couldn't create new ConsoleKit connector");
- goto out;
- }
-
- if (welcome_session->priv->x11_display_hostname != NULL) {
- hostname = welcome_session->priv->x11_display_hostname;
- } else {
- hostname = "";
- }
-
- if (welcome_session->priv->x11_display_device != NULL) {
- x11_display_device = welcome_session->priv->x11_display_device;
- } else {
- x11_display_device = "";
- }
-
- g_debug ("GdmWelcomeSession: Opening ConsoleKit session for user:%d x11-display:'%s' x11-display-device:'%s' remote-host-name:'%s' is-local:%d",
- pwent->pw_uid,
- welcome_session->priv->x11_display_name,
- x11_display_device,
- hostname,
- welcome_session->priv->x11_display_is_local);
-
- dbus_error_init (&error);
- res = ck_connector_open_session_with_parameters (welcome_session->priv->ckc,
- &error,
- "unix-user", &pwent->pw_uid,
- "session-type", &session_type,
- "x11-display", &welcome_session->priv->x11_display_name,
- "x11-display-device", &x11_display_device,
- "remote-host-name", &hostname,
- "is-local", &welcome_session->priv->x11_display_is_local,
- NULL);
- if (! res) {
- if (dbus_error_is_set (&error)) {
- g_warning ("%s\n", error.message);
- dbus_error_free (&error);
- } else {
- g_warning ("cannot open CK session: OOM, D-Bus system bus not available,\n"
- "ConsoleKit not available or insufficient privileges.\n");
- }
- goto out;
- }
-
- ret = TRUE;
-
- out:
- return ret;
-}
-
-static gboolean
-close_welcome_session (GdmWelcomeSession *welcome_session)
-{
- int res;
- gboolean ret;
- DBusError error;
-
- ret = FALSE;
-
- if (welcome_session->priv->ckc == NULL) {
- return FALSE;
- }
-
- g_debug ("GdmWelcomeSession: De-registering session from ConsoleKit");
-
- dbus_error_init (&error);
- res = ck_connector_close_session (welcome_session->priv->ckc, &error);
- if (! res) {
- if (dbus_error_is_set (&error)) {
- g_warning ("%s\n", error.message);
- dbus_error_free (&error);
- } else {
- g_warning ("cannot open CK session: OOM, D-Bus system bus not available,\n"
- "ConsoleKit not available or insufficient privileges.\n");
- }
- goto out;
- }
-
- ret = TRUE;
- out:
-
- return ret;
-}
-
static void
load_lang_config_file (const char *config_file,
const char **str_array)
@@ -343,11 +231,10 @@ next_line:
g_free (contents);
}
-static GPtrArray *
-get_welcome_environment (GdmWelcomeSession *welcome_session,
- gboolean start_session)
+static GHashTable *
+build_welcome_environment (GdmWelcomeSession *welcome_session,
+ gboolean start_session)
{
- GPtrArray *env;
GHashTable *hash;
struct passwd *pwent;
static const char * const optional_environment[] = {
@@ -362,7 +249,6 @@ get_welcome_environment (GdmWelcomeSession *welcome_session,
load_lang_config_file (LANG_CONFIG_FILE,
(const char **) optional_environment);
- 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);
@@ -400,14 +286,6 @@ get_welcome_environment (GdmWelcomeSession *welcome_session,
g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (welcome_session->priv->x11_authority_file));
g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (welcome_session->priv->x11_display_name));
- if (welcome_session->priv->ckc != NULL) {
- const char *cookie;
- cookie = ck_connector_get_cookie (welcome_session->priv->ckc);
- if (cookie != NULL) {
- g_hash_table_insert (hash, g_strdup ("XDG_SESSION_COOKIE"), g_strdup (cookie));
- }
- }
-
g_hash_table_insert (hash, g_strdup ("LOGNAME"), g_strdup (welcome_session->priv->user_name));
g_hash_table_insert (hash, g_strdup ("USER"), g_strdup (welcome_session->priv->user_name));
g_hash_table_insert (hash, g_strdup ("USERNAME"), g_strdup (welcome_session->priv->user_name));
@@ -445,6 +323,19 @@ get_welcome_environment (GdmWelcomeSession *welcome_session,
g_hash_table_insert (hash, g_strdup ("GVFS_DISABLE_FUSE"), g_strdup ("1"));
g_hash_table_insert (hash, g_strdup ("DCONF_PROFILE"), g_strdup ("gdm"));
+ return hash;
+}
+
+static GPtrArray *
+get_welcome_environment (GdmWelcomeSession *welcome_session,
+ gboolean start_session)
+{
+ GHashTable *hash;
+ GPtrArray *env;
+
+ hash = build_welcome_environment (welcome_session, start_session);
+
+ env = g_ptr_array_new ();
g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
g_hash_table_destroy (hash);
@@ -453,7 +344,6 @@ get_welcome_environment (GdmWelcomeSession *welcome_session,
return env;
}
-
static gboolean
stop_dbus_daemon (GdmWelcomeSession *welcome_session)
{
@@ -472,37 +362,6 @@ stop_dbus_daemon (GdmWelcomeSession *welcome_session)
}
static void
-welcome_session_child_watch (GPid pid,
- int status,
- GdmWelcomeSession *session)
-{
- g_debug ("GdmWelcomeSession: child (pid:%d) done (%s:%d)",
- (int) pid,
- WIFEXITED (status) ? "status"
- : WIFSIGNALED (status) ? "signal"
- : "unknown",
- WIFEXITED (status) ? WEXITSTATUS (status)
- : WIFSIGNALED (status) ? WTERMSIG (status)
- : -1);
-
- if (WIFEXITED (status)) {
- int code = WEXITSTATUS (status);
- g_signal_emit (session, signals [EXITED], 0, code);
- } else if (WIFSIGNALED (status)) {
- int num = WTERMSIG (status);
- g_signal_emit (session, signals [DIED], 0, num);
- }
-
- g_spawn_close_pid (session->priv->pid);
- session->priv->pid = -1;
-
- if (session->priv->ckc != NULL) {
- close_welcome_session (session);
- }
- stop_dbus_daemon (session);
-}
-
-static void
rotate_logs (const char *path,
guint n_copies)
{
@@ -712,62 +571,6 @@ spawn_command_line_sync_as_user (const char *command_line,
}
static gboolean
-spawn_command_line_async_as_user (const char *command_line,
- const char *user_name,
- const char *group_name,
- const char *seat_id,
- const char *runtime_dir,
- const char *log_file,
- char **env,
- GPid *child_pid,
- GError **error)
-{
- char **argv;
- GError *local_error;
- gboolean ret;
- gboolean res;
- SpawnChildData data;
-
- ret = FALSE;
-
- argv = NULL;
- local_error = NULL;
- if (! g_shell_parse_argv (command_line, NULL, &argv, &local_error)) {
- g_warning ("Could not parse command: %s", local_error->message);
- g_propagate_error (error, local_error);
- goto out;
- }
-
- data.user_name = user_name;
- data.group_name = group_name;
- data.runtime_dir = runtime_dir;
- data.log_file = log_file;
- data.seat_id = seat_id;
-
- local_error = NULL;
- res = g_spawn_async (NULL,
- argv,
- env,
- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
- (GSpawnChildSetupFunc)spawn_child_setup,
- &data,
- child_pid,
- &local_error);
-
- if (! res) {
- g_warning ("Could not spawn command: %s", local_error->message);
- g_propagate_error (error, local_error);
- goto out;
- }
-
- ret = TRUE;
- out:
- g_strfreev (argv);
-
- return ret;
-}
-
-static gboolean
parse_value_as_integer (const char *value,
int *intval)
{
@@ -895,69 +698,105 @@ start_dbus_daemon (GdmWelcomeSession *welcome_session)
return res;
}
-static gboolean
-gdm_welcome_session_spawn (GdmWelcomeSession *welcome_session)
+static void
+on_session_setup_complete (GdmSession *session,
+ const char *service_name,
+ GdmWelcomeSession *welcome_session)
{
- GError *error;
- GPtrArray *env;
- gboolean ret;
- gboolean res;
- char *log_path;
- char *log_file;
+ GHashTable *hash;
+ GHashTableIter iter;
+ gpointer key, value;
- ret = FALSE;
-
- g_debug ("GdmWelcomeSession: Running welcome_session process: %s", welcome_session->priv->command);
+ hash = build_welcome_environment (welcome_session, TRUE);
- if (welcome_session->priv->register_ck_session) {
- open_welcome_session (welcome_session);
+ g_hash_table_iter_init (&iter, hash);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ gdm_session_set_environment_variable (GDM_SESSION (welcome_session->priv->session), key, value);
}
+ g_hash_table_destroy (hash);
- res = start_dbus_daemon (welcome_session);
- if (! res) {
- /* FIXME: */
- }
+ gdm_session_select_session_type (GDM_SESSION (welcome_session->priv->session), "LoginWindow");
- env = get_welcome_environment (welcome_session, TRUE);
+ gdm_session_authenticate (GDM_SESSION (welcome_session->priv->session), service_name);
+}
- error = NULL;
+static void
+on_session_authenticated (GdmSession *session,
+ const char *service_name,
+ GdmWelcomeSession *welcome_session)
+{
+ gdm_session_authorize (GDM_SESSION (welcome_session->priv->session),
+ service_name);
+}
- log_file = g_strdup_printf ("%s-greeter.log", welcome_session->priv->x11_display_name);
- log_path = g_build_filename (LOGDIR, log_file, NULL);
- g_free (log_file);
+static void
+on_session_authorized (GdmSession *session,
+ const char *service_name,
+ GdmWelcomeSession *welcome_session)
+{
+ gdm_session_accredit (GDM_SESSION (welcome_session->priv->session),
+ service_name,
+ GDM_SESSION_CRED_ESTABLISH);
+}
- ret = spawn_command_line_async_as_user (welcome_session->priv->command,
- welcome_session->priv->user_name,
- welcome_session->priv->group_name,
- welcome_session->priv->x11_display_seat_id,
- welcome_session->priv->runtime_dir,
- log_path,
- (char **)env->pdata,
- &welcome_session->priv->pid,
- &error);
+static void
+on_session_accredited (GdmSession *session,
+ const char *service_name,
+ GdmWelcomeSession *welcome_session)
+{
+ gdm_session_open_session (GDM_SESSION (welcome_session->priv->session), service_name);
+}
- g_ptr_array_foreach (env, (GFunc)g_free, NULL);
- g_ptr_array_free (env, TRUE);
+static void
+on_session_opened (GdmSession *session,
+ const char *service_name,
+ GdmWelcomeSession *welcome_session)
+{
+ gdm_session_start_session (GDM_SESSION (welcome_session->priv->session),
+ service_name);
+}
- g_free (log_path);
+static void
+on_session_started (GdmSession *session,
+ const char *service_name,
+ int pid,
+ GdmWelcomeSession *welcome_session)
+{
+ g_signal_emit (G_OBJECT (welcome_session), signals [STARTED], 0);
+}
- if (! ret) {
- g_warning ("Could not start command '%s': %s",
- welcome_session->priv->command,
- error->message);
- g_error_free (error);
- goto out;
- } else {
- g_debug ("GdmWelcomeSession: WelcomeSession on pid %d", (int)welcome_session->priv->pid);
- }
+static void
+on_session_exited (GdmSession *session,
+ int exit_code,
+ GdmWelcomeSession *welcome_session)
+{
+ g_signal_emit (G_OBJECT (welcome_session), signals [EXITED], 0, exit_code);
+}
+
+static void
+on_session_died (GdmSession *session,
+ int signal_number,
+ GdmWelcomeSession *welcome_session)
+{
+ g_signal_emit (G_OBJECT (welcome_session), signals [DIED], 0, signal_number);
+}
- welcome_session->priv->child_watch_id = g_child_watch_add (welcome_session->priv->pid,
- (GChildWatchFunc)welcome_session_child_watch,
- welcome_session);
+static void
+on_conversation_started (GdmSession *session,
+ const char *service_name,
+ GdmWelcomeSession *welcome_session)
+{
+ char *log_path;
+ char *log_file;
- out:
+ log_file = g_strdup_printf ("%s-greeter.log", welcome_session->priv->x11_display_name);
+ log_path = g_build_filename (LOGDIR, log_file, NULL);
+ g_free (log_file);
- return ret;
+ gdm_session_setup_for_program (GDM_SESSION (welcome_session->priv->session),
+ "gdm-welcome",
+ log_path);
+ g_free (log_path);
}
/**
@@ -969,66 +808,76 @@ gdm_welcome_session_spawn (GdmWelcomeSession *welcome_session)
gboolean
gdm_welcome_session_start (GdmWelcomeSession *welcome_session)
{
- gboolean res;
+ gboolean res;
g_debug ("GdmWelcomeSession: Starting welcome...");
+ res = start_dbus_daemon (welcome_session);
- res = gdm_welcome_session_spawn (welcome_session);
-
- if (res) {
-
- }
-
-
- return res;
-}
-
-static void
-welcome_session_died (GdmWelcomeSession *welcome_session)
-{
- int exit_status;
-
- g_debug ("GdmWelcomeSession: Waiting on process %d", welcome_session->priv->pid);
- exit_status = gdm_wait_on_pid (welcome_session->priv->pid);
-
- if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
- g_debug ("GdmWelcomeSession: Wait on child process failed");
- } else {
- /* exited normally */
+ if (!res) {
+ return FALSE;
}
- g_spawn_close_pid (welcome_session->priv->pid);
- welcome_session->priv->pid = -1;
-
- g_debug ("GdmWelcomeSession: WelcomeSession died");
+ welcome_session->priv->session = GDM_SESSION (gdm_session_direct_new (NULL,
+ welcome_session->priv->x11_display_name,
+ welcome_session->priv->x11_display_hostname,
+ welcome_session->priv->x11_display_device,
+ welcome_session->priv->x11_authority_file,
+ welcome_session->priv->x11_display_is_local));
+
+ g_signal_connect (GDM_SESSION (welcome_session->priv->session),
+ "conversation-started",
+ G_CALLBACK (on_conversation_started),
+ welcome_session);
+ g_signal_connect (welcome_session->priv->session,
+ "setup-complete",
+ G_CALLBACK (on_session_setup_complete),
+ welcome_session);
+ g_signal_connect (welcome_session->priv->session,
+ "authenticated",
+ G_CALLBACK (on_session_authenticated),
+ welcome_session);
+ g_signal_connect (welcome_session->priv->session,
+ "authorized",
+ G_CALLBACK (on_session_authorized),
+ welcome_session);
+ g_signal_connect (welcome_session->priv->session,
+ "accredited",
+ G_CALLBACK (on_session_accredited),
+ welcome_session);
+ g_signal_connect (welcome_session->priv->session,
+ "session-opened",
+ G_CALLBACK (on_session_opened),
+ welcome_session);
+ g_signal_connect (GDM_SESSION (welcome_session->priv->session),
+ "session-started",
+ G_CALLBACK (on_session_started),
+ welcome_session);
+ g_signal_connect (GDM_SESSION (welcome_session->priv->session),
+ "session-exited",
+ G_CALLBACK (on_session_exited),
+ welcome_session);
+ g_signal_connect (GDM_SESSION (welcome_session->priv->session),
+ "session-died",
+ G_CALLBACK (on_session_died),
+ welcome_session);
+
+ gdm_session_start_conversation (GDM_SESSION (welcome_session->priv->session),
+ "gdm-welcome");
+ gdm_session_select_program (GDM_SESSION (welcome_session->priv->session),
+ welcome_session->priv->command);
+ return TRUE;
}
gboolean
gdm_welcome_session_stop (GdmWelcomeSession *welcome_session)
{
- int res;
-
- if (welcome_session->priv->pid <= 1) {
- return TRUE;
- }
-
- /* remove watch source before we can wait on child */
- if (welcome_session->priv->child_watch_id > 0) {
- g_source_remove (welcome_session->priv->child_watch_id);
- welcome_session->priv->child_watch_id = 0;
- }
+ if (welcome_session->priv->session != NULL) {
+ gdm_session_stop_conversation (GDM_SESSION (welcome_session->priv->session),
+ "gdm-welcome");
+ gdm_session_close (GDM_SESSION (welcome_session->priv->session));
- g_debug ("GdmWelcomeSession: Stopping welcome_session");
-
- res = gdm_signal_pid (welcome_session->priv->pid, SIGTERM);
- if (res < 0) {
- g_warning ("Unable to kill welcome session process");
- } else {
- welcome_session_died (welcome_session);
- }
-
- if (welcome_session->priv->ckc != NULL) {
- close_welcome_session (welcome_session);
+ g_object_unref (welcome_session->priv->session);
+ welcome_session->priv->session = NULL;
}
stop_dbus_daemon (welcome_session);
@@ -1085,7 +934,6 @@ _gdm_welcome_session_set_x11_display_is_local (GdmWelcomeSession *welcome_sessio
welcome_session->priv->x11_display_is_local = is_local;
}
-
static void
_gdm_welcome_session_set_x11_authority_file (GdmWelcomeSession *welcome_session,
const char *file)
@@ -1447,9 +1295,8 @@ gdm_welcome_session_init (GdmWelcomeSession *welcome_session)
welcome_session->priv = GDM_WELCOME_SESSION_GET_PRIVATE (welcome_session);
- welcome_session->priv->pid = -1;
-
welcome_session->priv->command = NULL;
+ welcome_session->priv->session = NULL;
}
static void
@@ -1466,8 +1313,8 @@ gdm_welcome_session_finalize (GObject *object)
gdm_welcome_session_stop (welcome_session);
- if (welcome_session->priv->ckc != NULL) {
- ck_connector_unref (welcome_session->priv->ckc);
+ if (welcome_session->priv->session) {
+ g_object_unref (welcome_session->priv->session);
}
g_free (welcome_session->priv->command);