]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blobdiff - src/session.c
Don't reconnect a display server if already connected to it
[sojka/lightdm.git] / src / session.c
index a3c3578d0a42ade501fa25d7f3dd7d18047bc4b3..e2967b43a0da1b5a4373fc3ecbf0a4f18be16a85 100644 (file)
@@ -26,6 +26,7 @@
 #include "console-kit.h"
 #include "login1.h"
 #include "guest-account.h"
+#include "shared-data-manager.h"
 
 enum {
     GOT_MESSAGES,
@@ -37,8 +38,8 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 struct SessionPrivate
 {
-    /* Session type */
-    gchar *session_type;
+    /* Configuration for this session */
+    SessionConfig *config;
 
     /* Display server running on */
     DisplayServer *display_server;
@@ -83,9 +84,7 @@ struct SessionPrivate
 
     /* File to log to */
     gchar *log_filename;
-
-    /* Seat class */
-    gchar *class;
+    LogMode log_mode;
 
     /* tty this session is running on */
     gchar *tty;
@@ -101,8 +100,8 @@ struct SessionPrivate
     /* Console kit cookie */
     gchar *console_kit_cookie;
 
-    /* login1 session */
-    gchar *login1_session;
+    /* login1 session ID */
+    gchar *login1_session_id;
 
     /* Environment to set in child */
     GList *env;
@@ -133,18 +132,26 @@ session_new (void)
 }
 
 void
-session_set_session_type (Session *session, const gchar *session_type)
+session_set_config (Session *session, SessionConfig *config)
 {
     g_return_if_fail (session != NULL);
-    g_free (session->priv->session_type);
-    session->priv->session_type = g_strdup (session_type);
+
+    g_clear_object (&session->priv->config);
+    session->priv->config = g_object_ref (config);
+}
+
+SessionConfig *
+session_get_config (Session *session)
+{
+    g_return_val_if_fail (session != NULL, NULL);
+    return session->priv->config;
 }
 
 const gchar *
 session_get_session_type (Session *session)
 {
     g_return_val_if_fail (session != NULL, NULL);
-    return session->priv->session_type;
+    return session_config_get_session_type (session_get_config (session));
 }
 
 void
@@ -192,19 +199,12 @@ session_get_is_guest (Session *session)
 }
 
 void
-session_set_log_file (Session *session, const gchar *filename)
+session_set_log_file (Session *session, const gchar *filename, LogMode log_mode)
 {
     g_return_if_fail (session != NULL);
     g_free (session->priv->log_filename);
     session->priv->log_filename = g_strdup (filename);
-}
-
-void
-session_set_class (Session *session, const gchar *class)
-{
-    g_return_if_fail (session != NULL);
-    g_free (session->priv->class);
-    session->priv->class = g_strdup (class);
+    session->priv->log_mode = log_mode;
 }
 
 void
@@ -212,6 +212,10 @@ session_set_display_server (Session *session, DisplayServer *display_server)
 {
     g_return_if_fail (session != NULL);
     g_return_if_fail (display_server != NULL);
+
+    if (session->priv->display_server == display_server)
+        return;
+
     if (session->priv->display_server)
     {
         display_server_disconnect_session (session->priv->display_server, session);
@@ -247,11 +251,7 @@ void
 session_set_x_authority (Session *session, XAuthority *authority, gboolean use_system_location)
 {
     g_return_if_fail (session != NULL);
-    if (session->priv->x_authority)
-    {
-        g_object_unref (session->priv->x_authority);
-        session->priv->x_authority = NULL;
-    }
+    g_clear_object (&session->priv->x_authority);
     if (authority)
         session->priv->x_authority = g_object_ref (authority);
     session->priv->x_authority_use_system_location = use_system_location;
@@ -311,7 +311,7 @@ session_get_env (Session *session, const gchar *name)
     link = find_env_entry (session, name);
     if (!link)
         return NULL;
-  
+
     entry = link->data;
 
     return entry + strlen (name) + 1;
@@ -323,13 +323,13 @@ session_unset_env (Session *session, const gchar *name)
     GList *link;
 
     g_return_if_fail (session != NULL);
-  
+
     link = find_env_entry (session, name);
     if (!link)
         return;
 
     g_free (link->data);
-    session->priv->env = g_list_remove_link (session->priv->env, link);
+    session->priv->env = g_list_delete_link (session->priv->env, link);
 }
 
 void
@@ -433,6 +433,8 @@ session_watch_cb (GPid pid, gint status, gpointer data)
 {
     Session *session = data;
 
+    session->priv->child_watch = 0;
+
     if (WIFEXITED (status))
         l_debug (session, "Exited with return value %d", WEXITSTATUS (status));
     else if (WIFSIGNALED (status))
@@ -483,9 +485,7 @@ from_child_cb (GIOChannel *source, GIOCondition condition, gpointer data)
     {
         g_free (session->priv->username);
         session->priv->username = username;
-        if (session->priv->user)
-            g_object_unref (session->priv->user);
-        session->priv->user = NULL;
+        g_clear_object (&session->priv->user);
     }
     else
         g_free (username);
@@ -557,6 +557,7 @@ session_real_start (Session *session)
     int version;
     int to_child_pipe[2], from_child_pipe[2];
     int to_child_output, from_child_input;
+    gchar *arg0, *arg1;
 
     g_return_val_if_fail (session->priv->pid == 0, FALSE);
 
@@ -589,24 +590,26 @@ session_real_start (Session *session)
     }
 
     /* Run the child */
+    arg0 = g_strdup_printf ("%d", to_child_output);
+    arg1 = g_strdup_printf ("%d", from_child_input);
     session->priv->pid = fork ();
-    if (session->priv->pid < 0)
-    {
-        g_debug ("Failed to fork session child process: %s", strerror (errno));
-        return FALSE;
-    }
-
     if (session->priv->pid == 0)
     {
         /* Run us again in session child mode */
         execlp ("lightdm",
                 "lightdm",
                 "--session-child",
-                g_strdup_printf ("%d", to_child_output),
-                g_strdup_printf ("%d", from_child_input),
-                NULL);
+                arg0, arg1, NULL);
         _exit (EXIT_FAILURE);
     }
+    g_free (arg0);
+    g_free (arg1);
+
+    if (session->priv->pid < 0)
+    {
+        g_debug ("Failed to fork session child process: %s", strerror (errno));
+        return FALSE;
+    }
 
     /* Hold a reference on this object until the child process terminates so we
      * can handle the watch callback even if it is no longer used. Otherwise a
@@ -622,7 +625,7 @@ session_real_start (Session *session)
     close (from_child_input);
 
     /* Indicate what version of the protocol we are using */
-    version = 1;
+    version = 3;
     write_data (session, &version, sizeof (version));
 
     /* Send configuration */
@@ -630,7 +633,7 @@ session_real_start (Session *session)
     write_string (session, session->priv->username);
     write_data (session, &session->priv->do_authenticate, sizeof (session->priv->do_authenticate));
     write_data (session, &session->priv->is_interactive, sizeof (session->priv->is_interactive));
-    write_string (session, session->priv->class);
+    write_string (session, NULL); /* Used to be class, now we just use the environment variable */
     write_string (session, session->priv->tty);
     write_string (session, session->priv->remote_host_name);
     write_string (session, session->priv->xdisplay);
@@ -648,6 +651,13 @@ session_get_username (Session *session)
     return session->priv->username;
 }
 
+const gchar *
+session_get_login1_session_id (Session *session)
+{
+    g_return_val_if_fail (session != NULL, NULL);
+    return session->priv->login1_session_id;
+}
+
 const gchar *
 session_get_console_kit_cookie (Session *session)
 {
@@ -773,9 +783,21 @@ session_real_run (Session *session)
     else
         x_authority_filename = g_build_filename (user_get_home_directory (session_get_user (session)), ".Xauthority", NULL);
 
+    /* Make sure shared user directory for this user exists */
+    if (!session->priv->remote_host_name)
+    {
+        gchar *data_dir = shared_data_manager_ensure_user_dir (shared_data_manager_get_instance (), session->priv->username);
+        if (data_dir)
+        {
+            session_set_env (session, "XDG_GREETER_DATA_DIR", data_dir);
+            g_free (data_dir);
+        }
+    }
+
     if (session->priv->log_filename)
         l_debug (session, "Logging to %s", session->priv->log_filename);
     write_string (session, session->priv->log_filename);
+    write_data (session, &session->priv->log_mode, sizeof (session->priv->log_mode));
     write_string (session, session->priv->tty);
     write_string (session, x_authority_filename);
     g_free (x_authority_filename);
@@ -790,10 +812,8 @@ session_real_run (Session *session)
     for (i = 0; i < argc; i++)
         write_string (session, session->priv->argv[i]);
 
-    if (login1_is_running ())
-        session->priv->login1_session = read_string_from_child (session);
-    if (!session->priv->login1_session)
-        session->priv->console_kit_cookie = read_string_from_child (session);
+    session->priv->login1_session_id = read_string_from_child (session);
+    session->priv->console_kit_cookie = read_string_from_child (session);
 }
 
 void
@@ -802,8 +822,8 @@ session_lock (Session *session)
     g_return_if_fail (session != NULL);
     if (getuid () == 0)
     {
-        if (session->priv->login1_session)
-            login1_lock_session (session->priv->login1_session);
+        if (session->priv->login1_session_id)
+            login1_service_lock_session (login1_service_get_instance (), session->priv->login1_session_id);
         else if (session->priv->console_kit_cookie)
             ck_lock_session (session->priv->console_kit_cookie);
     }
@@ -815,18 +835,49 @@ session_unlock (Session *session)
     g_return_if_fail (session != NULL);
     if (getuid () == 0)
     {
-        if (session->priv->login1_session)
-            login1_unlock_session (session->priv->login1_session);
+        if (session->priv->login1_session_id)
+            login1_service_unlock_session (login1_service_get_instance (), session->priv->login1_session_id);
         else if (session->priv->console_kit_cookie)
             ck_unlock_session (session->priv->console_kit_cookie);
     }
 }
 
+void
+session_activate (Session *session)
+{
+    g_return_if_fail (session != NULL);
+    if (getuid () == 0)
+    {
+        if (session->priv->login1_session_id)
+            login1_service_activate_session (login1_service_get_instance (), session->priv->login1_session_id);
+        else if (session->priv->console_kit_cookie)
+            ck_activate_session (session->priv->console_kit_cookie);
+    }
+}
+
 void
 session_stop (Session *session)
 {
     g_return_if_fail (session != NULL);
 
+    /* If can cleanly stop then do that */
+    if (session_get_is_authenticated (session) && !session->priv->command_run)
+    {
+        gsize n = 0;
+        LogMode log_mode = LOG_MODE_INVALID;
+
+        session->priv->command_run = TRUE;
+        write_string (session, NULL); // log filename
+        write_data (session, &log_mode, sizeof (log_mode)); // log mode
+        write_string (session, NULL); // tty
+        write_string (session, NULL); // xauth filename
+        write_string (session, NULL); // xdisplay
+        write_xauth (session, NULL); // xauth
+        write_data (session, &n, sizeof (n)); // environment
+        write_data (session, &n, sizeof (n)); // command
+        return;
+    }
+
     if (session->priv->stopping)
         return;
     session->priv->stopping = TRUE;
@@ -861,6 +912,9 @@ session_init (Session *session)
 {
     session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate);
     session->priv->log_filename = g_strdup (".xsession-errors");
+    session->priv->log_mode = LOG_MODE_BACKUP_AND_TRUNCATE;
+    session->priv->to_child_input = -1;
+    session->priv->from_child_output = -1;
 }
 
 static void
@@ -869,11 +923,12 @@ session_finalize (GObject *object)
     Session *self = SESSION (object);
     int i;
 
-    g_free (self->priv->session_type);
-    if (self->priv->display_server)
-        g_object_unref (self->priv->display_server);
+    g_clear_object (&self->priv->config);
+    g_clear_object (&self->priv->display_server);
     if (self->priv->pid)
         kill (self->priv->pid, SIGKILL);
+    close (self->priv->to_child_input);
+    close (self->priv->from_child_output);
     if (self->priv->from_child_channel)
         g_io_channel_unref (self->priv->from_child_channel);
     if (self->priv->from_child_watch)
@@ -881,21 +936,18 @@ session_finalize (GObject *object)
     if (self->priv->child_watch)
         g_source_remove (self->priv->child_watch);
     g_free (self->priv->username);
-    if (self->priv->user)
-        g_object_unref (self->priv->user);
+    g_clear_object (&self->priv->user);
     g_free (self->priv->pam_service);
     for (i = 0; i < self->priv->messages_length; i++)
         g_free ((char *) self->priv->messages[i].msg);
     g_free (self->priv->messages);
     g_free (self->priv->authentication_result_string);
     g_free (self->priv->log_filename);
-    g_free (self->priv->class);
     g_free (self->priv->tty);
     g_free (self->priv->xdisplay);
-    if (self->priv->x_authority)
-        g_object_unref (self->priv->x_authority);
+    g_clear_object (&self->priv->x_authority);
     g_free (self->priv->remote_host_name);
-    g_free (self->priv->login1_session);
+    g_free (self->priv->login1_session_id);
     g_free (self->priv->console_kit_cookie);
     g_list_free_full (self->priv->env, g_free);
     g_strfreev (self->priv->argv);
@@ -916,7 +968,7 @@ session_class_init (SessionClass *klass)
     g_type_class_add_private (klass, sizeof (SessionPrivate));
 
     signals[GOT_MESSAGES] =
-        g_signal_new ("got-messages",
+        g_signal_new (SESSION_SIGNAL_GOT_MESSAGES,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (SessionClass, got_messages),
@@ -925,7 +977,7 @@ session_class_init (SessionClass *klass)
                       G_TYPE_NONE, 0);
 
     signals[AUTHENTICATION_COMPLETE] =
-        g_signal_new ("authentication-complete",
+        g_signal_new (SESSION_SIGNAL_AUTHENTICATION_COMPLETE,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (SessionClass, authentication_complete),
@@ -934,7 +986,7 @@ session_class_init (SessionClass *klass)
                       G_TYPE_NONE, 0);
 
     signals[STOPPED] =
-        g_signal_new ("stopped",
+        g_signal_new (SESSION_SIGNAL_STOPPED,
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (SessionClass, stopped),