]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blobdiff - src/x-server-local.c
Remove display_server_get_name and make better logging prefixes
[sojka/lightdm.git] / src / x-server-local.c
index edbdabd71fbfb62a9c1098a6a4152ce8084a0cf0..f251823707f18994ff5ac9be0506caedcc7e2a4c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2010-2011 Robert Ancell.
  * Author: Robert Ancell <robert.ancell@canonical.com>
- * 
+ *
  * This program is free software: you can redistribute it and/or modify it under
  * the terms of the GNU General Public License as published by the Free Software
  * Foundation, either version 3 of the License, or (at your option) any later
@@ -12,7 +12,6 @@
 #include <config.h>
 #include <string.h>
 #include <fcntl.h>
-#include <unistd.h>
 #include <sys/stat.h>
 #include <errno.h>
 #include <glib/gstdio.h>
@@ -27,19 +26,19 @@ struct XServerLocalPrivate
 {
     /* X server process */
     Process *x_server_process;
-  
-    /* File to log to */
-    gchar *log_file;    
 
     /* Command to run the X server */
     gchar *command;
 
+    /* Display number to use */
+    guint display_number;
+
     /* Config file to use */
     gchar *config_file;
 
     /* Server layout to use */
     gchar *layout;
-    
+
     /* Value for -seat argument */
     gchar *xdg_seat;
 
@@ -58,12 +57,6 @@ struct XServerLocalPrivate
     /* XDMCP key to use */
     gchar *xdmcp_key;
 
-    /* ID to report to Mir */
-    gchar *mir_id;
-
-    /* Filename of socket Mir is listening on */
-    gchar *mir_socket;
-
     /* TRUE when received ready signal */
     gboolean got_signal;
 
@@ -75,10 +68,70 @@ struct XServerLocalPrivate
     gchar *background;
 };
 
-G_DEFINE_TYPE (XServerLocal, x_server_local, X_SERVER_TYPE);
+static void x_server_local_logger_iface_init (LoggerInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (XServerLocal, x_server_local, X_SERVER_TYPE,
+                         G_IMPLEMENT_INTERFACE (LOGGER_TYPE, x_server_local_logger_iface_init));
 
+static gchar *version = NULL;
+static guint version_major = 0, version_minor = 0;
 static GList *display_numbers = NULL;
 
+#define XORG_VERSION_PREFIX "X.Org X Server "
+
+static gchar *
+find_version (const gchar *line)
+{
+    if (!g_str_has_prefix (line, XORG_VERSION_PREFIX))
+        return NULL;
+
+    return g_strdup (line + strlen (XORG_VERSION_PREFIX));
+}
+
+const gchar *
+x_server_local_get_version (void)
+{
+    gchar *stderr_text;
+    gint exit_status;
+    gchar **tokens;
+    guint n_tokens;
+
+    if (version)
+        return version;
+
+    if (!g_spawn_command_line_sync ("X -version", NULL, &stderr_text, &exit_status, NULL))
+        return NULL;
+    if (exit_status == EXIT_SUCCESS)
+    {
+        gchar **lines;
+        int i;
+
+        lines = g_strsplit (stderr_text, "\n", -1);
+        for (i = 0; lines[i] && !version; i++)
+            version = find_version (lines[i]);
+        g_strfreev (lines);
+    }
+    g_free (stderr_text);
+
+    tokens = g_strsplit (version, ".", 3);
+    n_tokens = g_strv_length (tokens);
+    version_major = n_tokens > 0 ? atoi (tokens[0]) : 0;
+    version_minor = n_tokens > 1 ? atoi (tokens[1]) : 0;
+    g_strfreev (tokens);
+
+    return version;
+}
+
+gint
+x_server_local_version_compare (guint major, guint minor)
+{
+    x_server_local_get_version ();
+    if (major == version_major)
+        return version_minor - minor;
+    else
+        return version_major - major;
+}
+
 static gboolean
 display_number_in_use (guint display_number)
 {
@@ -113,7 +166,7 @@ display_number_in_use (guint display_number)
     }
 
     g_free (path);
-  
+
     return in_use;
 }
 
@@ -140,7 +193,7 @@ x_server_local_release_display_number (guint display_number)
         guint number = GPOINTER_TO_UINT (link->data);
         if (number == display_number)
         {
-            display_numbers = g_list_remove_link (display_numbers, link);
+            display_numbers = g_list_delete_link (display_numbers, link);
             return;
         }
     }
@@ -149,21 +202,7 @@ x_server_local_release_display_number (guint display_number)
 XServerLocal *
 x_server_local_new (void)
 {
-    XServerLocal *self = g_object_new (X_SERVER_LOCAL_TYPE, NULL);
-    gchar hostname[1024], *number, *name;
-
-    x_server_set_display_number (X_SERVER (self), x_server_local_get_unused_display_number ());
-
-    gethostname (hostname, 1024);
-    number = g_strdup_printf ("%d", x_server_get_display_number (X_SERVER (self)));
-    x_server_set_authority (X_SERVER (self), x_authority_new_cookie (XAUTH_FAMILY_LOCAL, (guint8*) hostname, strlen (hostname), number));
-    g_free (number);
-
-    name = g_strdup_printf ("x-%d", x_server_get_display_number (X_SERVER (self)));
-    display_server_set_name (DISPLAY_SERVER (self), name);
-    g_free (name);
-
-    return self;
+    return g_object_new (X_SERVER_LOCAL_TYPE, NULL);
 }
 
 void
@@ -178,7 +217,7 @@ void
 x_server_local_set_vt (XServerLocal *server, gint vt)
 {
     g_return_if_fail (server != NULL);
-    if (server->priv->vt > 0)
+    if (server->priv->have_vt_ref)
         vt_unref (server->priv->vt);
     server->priv->have_vt_ref = FALSE;
     server->priv->vt = vt;
@@ -266,32 +305,15 @@ x_server_local_set_background (XServerLocal *server, const gchar *background)
     server->priv->background = g_strdup (background);
 }
 
-void
-x_server_local_set_mir_id (XServerLocal *server, const gchar *id)
-{
-    g_return_if_fail (server != NULL);
-    g_free (server->priv->mir_id);
-    server->priv->mir_id = g_strdup (id);
-}
-
-const gchar *x_server_local_get_mir_id (XServerLocal *server)
+static guint
+x_server_local_get_display_number (XServer *server)
 {
-    g_return_val_if_fail (server != NULL, NULL);
-    return server->priv->mir_id; 
-}
-
-void
-x_server_local_set_mir_socket (XServerLocal *server, const gchar *socket)
-{
-    g_return_if_fail (server != NULL);
-    g_free (server->priv->mir_socket);
-    server->priv->mir_socket = g_strdup (socket);
+    return X_SERVER_LOCAL (server)->priv->display_number;
 }
 
 static gint
 x_server_local_get_vt (DisplayServer *server)
 {
-    g_return_val_if_fail (server != NULL, 0);
     return X_SERVER_LOCAL (server)->priv->vt;
 }
 
@@ -326,7 +348,7 @@ get_absolute_command (const gchar *command)
 }
 
 static void
-run_cb (Process *process, XServerLocal *server)
+x_server_local_run (Process *process, gpointer user_data)
 {
     int fd;
 
@@ -335,40 +357,29 @@ run_cb (Process *process, XServerLocal *server)
     dup2 (fd, STDIN_FILENO);
     close (fd);
 
-    /* Redirect output to logfile */
-    if (server->priv->log_file)
-    {
-         int fd;
-         gchar *old_filename;
-
-         /* Move old file out of the way */
-         old_filename = g_strdup_printf ("%s.old", server->priv->log_file);
-         rename (server->priv->log_file, old_filename);
-         g_free (old_filename);
-
-         /* Create new file and log to it */
-         fd = g_open (server->priv->log_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
-         if (fd < 0)
-             l_warning (server, "Failed to open log file %s: %s", server->priv->log_file, g_strerror (errno));
-         else
-         {
-             dup2 (fd, STDOUT_FILENO);
-             dup2 (fd, STDERR_FILENO);
-             close (fd);
-         }
-    }
-
     /* Set SIGUSR1 to ignore so the X server can indicate it when it is ready */
     signal (SIGUSR1, SIG_IGN);
 }
 
+static ProcessRunFunc
+x_server_local_get_run_function (XServerLocal *server)
+{
+    return x_server_local_run;
+}
+
+static gboolean
+x_server_local_get_log_stdout (XServerLocal *server)
+{
+    return TRUE;
+}
+
 static void
 got_signal_cb (Process *process, int signum, XServerLocal *server)
 {
     if (signum == SIGUSR1 && !server->priv->got_signal)
     {
         server->priv->got_signal = TRUE;
-        l_debug (server, "Got signal from X server :%d", x_server_get_display_number (X_SERVER (server)));
+        l_debug (server, "Got signal from X server :%d", server->priv->display_number);
 
         // FIXME: Check return value
         DISPLAY_SERVER_CLASS (x_server_local_parent_class)->start (DISPLAY_SERVER (server));
@@ -386,8 +397,8 @@ stopped_cb (Process *process, XServerLocal *server)
         vt_unref (server->priv->vt);
         server->priv->have_vt_ref = FALSE;
     }
-    x_server_local_release_display_number (x_server_get_display_number (X_SERVER (server)));
-  
+    x_server_local_release_display_number (server->priv->display_number);
+
     if (x_server_get_authority (X_SERVER (server)) && server->priv->authority_file)
     {
         l_debug (server, "Removing X server authority %s", server->priv->authority_file);
@@ -415,7 +426,7 @@ write_authority_file (XServerLocal *server)
     if (!server->priv->authority_file)
     {
         gchar *run_dir, *dir;
-      
+
         run_dir = config_get_string (config_get_instance (), "LightDM", "run-directory");
         dir = g_build_filename (run_dir, "root", NULL);
         g_free (run_dir);
@@ -438,8 +449,9 @@ static gboolean
 x_server_local_start (DisplayServer *display_server)
 {
     XServerLocal *server = X_SERVER_LOCAL (display_server);
-    gboolean result;
-    gchar *filename, *dir, *absolute_command;
+    ProcessRunFunc run_cb;
+    gboolean result, backup_logs;
+    gchar *filename, *dir, *log_file, *absolute_command;
     GString *command;
 
     g_return_val_if_fail (server->priv->x_server_process == NULL, FALSE);
@@ -448,17 +460,20 @@ x_server_local_start (DisplayServer *display_server)
 
     g_return_val_if_fail (server->priv->command != NULL, FALSE);
 
-    server->priv->x_server_process = process_new ();
+    run_cb = X_SERVER_LOCAL_GET_CLASS (server)->get_run_function (server);
+    server->priv->x_server_process = process_new (run_cb, server);
     process_set_clear_environment (server->priv->x_server_process, TRUE);
-    g_signal_connect (server->priv->x_server_process, "run", G_CALLBACK (run_cb), server);
-    g_signal_connect (server->priv->x_server_process, "got-signal", G_CALLBACK (got_signal_cb), server);
-    g_signal_connect (server->priv->x_server_process, "stopped", G_CALLBACK (stopped_cb), server);
+    g_signal_connect (server->priv->x_server_process, PROCESS_SIGNAL_GOT_SIGNAL, G_CALLBACK (got_signal_cb), server);
+    g_signal_connect (server->priv->x_server_process, PROCESS_SIGNAL_STOPPED, G_CALLBACK (stopped_cb), server);
 
     /* Setup logging */
-    filename = g_strdup_printf ("%s.log", display_server_get_name (display_server));
+    filename = g_strdup_printf ("x-%d.log", x_server_get_display_number (X_SERVER (server)));
     dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
-    server->priv->log_file = g_build_filename (dir, filename, NULL);
-    l_debug (display_server, "Logging to %s", server->priv->log_file);
+    log_file = g_build_filename (dir, filename, NULL);
+    backup_logs = config_get_boolean (config_get_instance (), "LightDM", "backup-logs");
+    process_set_log_file (server->priv->x_server_process, log_file, X_SERVER_LOCAL_GET_CLASS (server)->get_log_stdout (server), backup_logs ? LOG_MODE_BACKUP_AND_TRUNCATE : LOG_MODE_APPEND);
+    l_debug (display_server, "Logging to %s", log_file);
+    g_free (log_file);
     g_free (filename);
     g_free (dir);
 
@@ -472,14 +487,14 @@ x_server_local_start (DisplayServer *display_server)
     command = g_string_new (absolute_command);
     g_free (absolute_command);
 
-    g_string_append_printf (command, " :%d", x_server_get_display_number (X_SERVER (server)));
+    g_string_append_printf (command, " :%d", server->priv->display_number);
 
     if (server->priv->config_file)
         g_string_append_printf (command, " -config %s", server->priv->config_file);
 
     if (server->priv->layout)
         g_string_append_printf (command, " -layout %s", server->priv->layout);
-        
+
     if (server->priv->xdg_seat)
         g_string_append_printf (command, " -seat %s", server->priv->xdg_seat);
 
@@ -487,13 +502,6 @@ x_server_local_start (DisplayServer *display_server)
     if (server->priv->authority_file)
         g_string_append_printf (command, " -auth %s", server->priv->authority_file);
 
-    /* Setup for running inside Mir */
-    if (server->priv->mir_id)
-        g_string_append_printf (command, " -mir %s", server->priv->mir_id);
-
-    if (server->priv->mir_socket)
-        g_string_append_printf (command, " -mirSocket %s", server->priv->mir_socket);
-
     /* Connect to a remote server using XDMCP */
     if (server->priv->xdmcp_server != NULL)
     {
@@ -503,7 +511,12 @@ x_server_local_start (DisplayServer *display_server)
         if (server->priv->xdmcp_key)
             g_string_append_printf (command, " -cookie %s", server->priv->xdmcp_key);
     }
-    else if (!server->priv->allow_tcp)
+    else if (server->priv->allow_tcp)
+    {
+        if (x_server_local_version_compare (1, 17) >= 0)
+            g_string_append (command, " -listen tcp");
+    }
+    else
         g_string_append (command, " -nolisten tcp");
 
     if (server->priv->vt >= 0)
@@ -512,6 +525,10 @@ x_server_local_start (DisplayServer *display_server)
     if (server->priv->background)
         g_string_append_printf (command, " -background %s", server->priv->background);
 
+    /* Allow sub-classes to add arguments */
+    if (X_SERVER_LOCAL_GET_CLASS (server)->add_args)
+        X_SERVER_LOCAL_GET_CLASS (server)->add_args (server, command);
+
     process_set_command (server->priv->x_server_process, command->str);
     g_string_free (command, TRUE);
 
@@ -543,14 +560,14 @@ x_server_local_start (DisplayServer *display_server)
     result = process_start (server->priv->x_server_process, FALSE);
 
     if (result)
-        l_debug (display_server, "Waiting for ready signal from X server :%d", x_server_get_display_number (X_SERVER (server)));
+        l_debug (display_server, "Waiting for ready signal from X server :%d", server->priv->display_number);
 
     if (!result)
         stopped_cb (server->priv->x_server_process, X_SERVER_LOCAL (server));
 
     return result;
 }
+
 static void
 x_server_local_stop (DisplayServer *server)
 {
@@ -563,30 +580,27 @@ x_server_local_init (XServerLocal *server)
     server->priv = G_TYPE_INSTANCE_GET_PRIVATE (server, X_SERVER_LOCAL_TYPE, XServerLocalPrivate);
     server->priv->vt = -1;
     server->priv->command = g_strdup ("X");
+    server->priv->display_number = x_server_local_get_unused_display_number ();
 }
 
 static void
 x_server_local_finalize (GObject *object)
 {
-    XServerLocal *self;
+    XServerLocal *self = X_SERVER_LOCAL (object);
 
-    self = X_SERVER_LOCAL (object);  
-
-    if (self->priv->x_server_process) 
+    if (self->priv->x_server_process)
     {
         g_signal_handlers_disconnect_matched (self->priv->x_server_process, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
         g_object_unref (self->priv->x_server_process);
     }
-    g_free (self->priv->log_file);
     g_free (self->priv->command);
     g_free (self->priv->config_file);
     g_free (self->priv->layout);
+    g_free (self->priv->xdg_seat);
     g_free (self->priv->xdmcp_server);
     g_free (self->priv->xdmcp_key);
-    g_free (self->priv->mir_id);
-    g_free (self->priv->mir_socket);
     g_free (self->priv->authority_file);
-    if (self->priv->vt > 0)
+    if (self->priv->have_vt_ref)
         vt_unref (self->priv->vt);
     g_free (self->priv->background);
 
@@ -597,12 +611,29 @@ static void
 x_server_local_class_init (XServerLocalClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    XServerClass *x_server_class = X_SERVER_CLASS (klass);
     DisplayServerClass *display_server_class = DISPLAY_SERVER_CLASS (klass);
 
+    klass->get_run_function = x_server_local_get_run_function;
+    klass->get_log_stdout = x_server_local_get_log_stdout;
+    x_server_class->get_display_number = x_server_local_get_display_number;
     display_server_class->get_vt = x_server_local_get_vt;
-    display_server_class->start = x_server_local_start;
+    display_server_class->start = klass->start = x_server_local_start;
     display_server_class->stop = x_server_local_stop;
     object_class->finalize = x_server_local_finalize;
 
     g_type_class_add_private (klass, sizeof (XServerLocalPrivate));
 }
+
+static gint
+x_server_local_real_logprefix (Logger *self, gchar *buf, gulong buflen)
+{
+    XServerLocal *server = X_SERVER_LOCAL (self);
+    return g_snprintf (buf, buflen, "XServer %d: ", server->priv->display_number);
+}
+
+static void
+x_server_local_logger_iface_init (LoggerInterface *iface)
+{
+    iface->logprefix = &x_server_local_real_logprefix;
+}