]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blobdiff - src/greeter.c
Load all users only when really needed
[sojka/lightdm.git] / src / greeter.c
index 72eaa2e7dc57668b1c131de3206bb39b14e61f83..1ec5bd9c008848455efc29f011c8aedd60784ee3 100644 (file)
@@ -12,8 +12,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-#include <fcntl.h>
 #include <gcrypt.h>
 
 #include "greeter.h"
 #include "shared-data-manager.h"
 
 enum {
-    PROP_0,
-    PROP_ACTIVE_USERNAME,
+    PROP_ACTIVE_USERNAME = 1,
 };
 
 enum {
     CONNECTED,
+    DISCONNECTED,  
     CREATE_SESSION,
     START_SESSION,
     LAST_SIGNAL
@@ -118,29 +116,22 @@ greeter_new (void)
     return g_object_new (GREETER_TYPE, NULL);
 }
 
-gboolean
-greeter_start (Greeter *greeter, gboolean (*setup_child_cb)(Greeter *greeter, int input_fd, int output_fd, gpointer user_data), gpointer user_data)
+void
+greeter_set_file_descriptors (Greeter *greeter, int to_greeter_fd, int from_greeter_fd)
 {
-    int to_greeter_pipe[2], from_greeter_pipe[2];
-    int to_greeter_output, from_greeter_input;
-    gboolean result;
     GError *error = NULL;
 
-    /* Create a pipe to talk with the greeter */
-    if (pipe (to_greeter_pipe) != 0 || pipe (from_greeter_pipe) != 0)
-    {
-        g_warning ("Failed to create pipes: %s", strerror (errno));
-        return FALSE;
-    }
-    to_greeter_output = to_greeter_pipe[0];
-    greeter->priv->to_greeter_input = to_greeter_pipe[1];
+    g_return_if_fail (greeter != NULL);
+    g_return_if_fail (greeter->priv->to_greeter_input < 0);
+    g_return_if_fail (greeter->priv->from_greeter_output < 0);
+
+    greeter->priv->to_greeter_input = to_greeter_fd;  
     greeter->priv->to_greeter_channel = g_io_channel_unix_new (greeter->priv->to_greeter_input);
     g_io_channel_set_encoding (greeter->priv->to_greeter_channel, NULL, &error);
     if (error)
         g_warning ("Failed to set encoding on to greeter channel to binary: %s\n", error->message);
     g_clear_error (&error);
-    greeter->priv->from_greeter_output = from_greeter_pipe[0];
-    from_greeter_input = from_greeter_pipe[1];
+    greeter->priv->from_greeter_output = from_greeter_fd;
     greeter->priv->from_greeter_channel = g_io_channel_unix_new (greeter->priv->from_greeter_output);
     g_io_channel_set_encoding (greeter->priv->from_greeter_channel, NULL, &error);
     if (error)
@@ -148,18 +139,6 @@ greeter_start (Greeter *greeter, gboolean (*setup_child_cb)(Greeter *greeter, in
     g_clear_error (&error);
     g_io_channel_set_buffered (greeter->priv->from_greeter_channel, FALSE);
     greeter->priv->from_greeter_watch = g_io_add_watch (greeter->priv->from_greeter_channel, G_IO_IN | G_IO_HUP, read_cb, greeter);
-
-    /* Don't allow the daemon end of the pipes to be accessed in child processes */
-    fcntl (greeter->priv->to_greeter_input, F_SETFD, FD_CLOEXEC);
-    fcntl (greeter->priv->from_greeter_output, F_SETFD, FD_CLOEXEC);
-
-    result = setup_child_cb (greeter, from_greeter_input, to_greeter_output, user_data);
-
-    /* Close the session ends of the pipe */
-    close (from_greeter_input);
-    close (to_greeter_output);
-
-    return result;
 }
 
 void
@@ -476,7 +455,7 @@ reset_session (Greeter *greeter)
 }
 
 static void
-handle_login (Greeter *greeter, guint32 sequence_number, const gchar *username)
+handle_authenticate (Greeter *greeter, guint32 sequence_number, const gchar *username)
 {
     const gchar *autologin_username, *service;
     gboolean is_interactive;
@@ -529,7 +508,7 @@ handle_login (Greeter *greeter, guint32 sequence_number, const gchar *username)
 }
 
 static void
-handle_login_as_guest (Greeter *greeter, guint32 sequence_number)
+handle_authenticate_as_guest (Greeter *greeter, guint32 sequence_number)
 {
     g_debug ("Greeter start authentication for guest account");
 
@@ -582,7 +561,7 @@ get_remote_session_service (const gchar *session_name)
 }
 
 static void
-handle_login_remote (Greeter *greeter, const gchar *session_name, const gchar *username, guint32 sequence_number)
+handle_authenticate_remote (Greeter *greeter, const gchar *session_name, const gchar *username, guint32 sequence_number)
 {
     gchar *service;
 
@@ -857,6 +836,7 @@ read_cb (GIOChannel *source, GIOCondition condition, gpointer data)
     {
         g_debug ("Greeter closed communication channel");
         greeter->priv->from_greeter_watch = 0;
+        g_signal_emit (greeter, signals[DISCONNECTED], 0);
         return FALSE;
     }
 
@@ -879,7 +859,14 @@ read_cb (GIOChannel *source, GIOCondition condition, gpointer data)
     if (error)
         g_warning ("Error reading from greeter: %s", error->message);
     g_clear_error (&error);
-    if (status != G_IO_STATUS_NORMAL)
+    if (status == G_IO_STATUS_EOF)
+    {
+        g_debug ("Greeter closed communication channel");
+        greeter->priv->from_greeter_watch = 0;
+        g_signal_emit (greeter, signals[DISCONNECTED], 0);
+        return FALSE;
+    }
+    else if (status != G_IO_STATUS_NORMAL)
         return TRUE;
 
     greeter->priv->n_read += n_read;
@@ -913,18 +900,18 @@ read_cb (GIOChannel *source, GIOCondition condition, gpointer data)
     case GREETER_MESSAGE_AUTHENTICATE:
         sequence_number = read_int (greeter, &offset);
         username = read_string (greeter, &offset);
-        handle_login (greeter, sequence_number, username);
+        handle_authenticate (greeter, sequence_number, username);
         g_free (username);
         break;
     case GREETER_MESSAGE_AUTHENTICATE_AS_GUEST:
         sequence_number = read_int (greeter, &offset);
-        handle_login_as_guest (greeter, sequence_number);
+        handle_authenticate_as_guest (greeter, sequence_number);
         break;
     case GREETER_MESSAGE_AUTHENTICATE_REMOTE:
         sequence_number = read_int (greeter, &offset);
         session_name = read_string (greeter, &offset);
         username = read_string (greeter, &offset);
-        handle_login_remote (greeter, session_name, username, sequence_number);
+        handle_authenticate_remote (greeter, session_name, username, sequence_number);
         break;
     case GREETER_MESSAGE_CONTINUE_AUTHENTICATION:
         n_secrets = read_int (greeter, &offset);
@@ -980,10 +967,18 @@ greeter_get_guest_authenticated (Greeter *greeter)
 }
 
 Session *
-greeter_get_authentication_session (Greeter *greeter)
+greeter_take_authentication_session (Greeter *greeter)
 {
+    Session *session;
+
     g_return_val_if_fail (greeter != NULL, NULL);
-    return greeter->priv->authentication_session;
+
+    session = greeter->priv->authentication_session;
+    if (greeter->priv->authentication_session)
+        g_signal_handlers_disconnect_matched (greeter->priv->authentication_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, greeter);
+    greeter->priv->authentication_session = NULL;
+
+    return session;
 }
 
 gboolean
@@ -1105,6 +1100,15 @@ greeter_class_init (GreeterClass *klass)
                       NULL,
                       G_TYPE_NONE, 0);
 
+    signals[DISCONNECTED] =
+        g_signal_new (GREETER_SIGNAL_DISCONNECTED,
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (GreeterClass, disconnected),
+                      NULL, NULL,
+                      NULL,
+                      G_TYPE_NONE, 0);
+
     signals[CREATE_SESSION] =
         g_signal_new (GREETER_SIGNAL_CREATE_SESSION,
                       G_TYPE_FROM_CLASS (klass),