/*
* Copyright (C) 2013 Canonical Ltd.
* 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
#include "unity-system-compositor.h"
#include "configuration.h"
#include "process.h"
+#include "greeter-session.h"
#include "vt.h"
struct UnitySystemCompositorPrivate
{
/* Compositor process */
Process *process;
-
- /* File to log to */
- gchar *log_file;
/* Command to run the compositor */
gchar *command;
/* TRUE when received ready signal */
gboolean is_ready;
+
+ /* Counters for Mir IDs to use */
+ int next_session_id;
+ int next_greeter_id;
};
-G_DEFINE_TYPE (UnitySystemCompositor, unity_system_compositor, DISPLAY_SERVER_TYPE);
+static void unity_system_compositor_logger_iface_init (LoggerInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (UnitySystemCompositor, unity_system_compositor, DISPLAY_SERVER_TYPE,
+ G_IMPLEMENT_INTERFACE (LOGGER_TYPE, unity_system_compositor_logger_iface_init));
typedef enum
{
unity_system_compositor_set_command (UnitySystemCompositor *compositor, const gchar *command)
{
g_return_if_fail (compositor != NULL);
+ g_return_if_fail (command != NULL);
+
g_free (compositor->priv->command);
compositor->priv->command = g_strdup (command);
}
data[1] = id & 0xFF;
data[2] = payload_length >> 8;
data[3] = payload_length & 0xFF;
- memcpy (data + 4, payload, payload_length);
+ if (payload)
+ memcpy (data + 4, payload, payload_length);
errno = 0;
if (write (compositor->priv->to_compositor_pipe[1], data, data_length) != data_length)
l_warning (compositor, "Failed to write to compositor: %s", strerror (errno));
+
+ g_free (data);
}
void
return UNITY_SYSTEM_COMPOSITOR (server)->priv->vt;
}
+static void
+unity_system_compositor_connect_session (DisplayServer *display_server, Session *session)
+{
+ UnitySystemCompositor *compositor = UNITY_SYSTEM_COMPOSITOR (display_server);
+
+ session_set_env (session, "XDG_SESSION_TYPE", "mir");
+
+ if (compositor->priv->socket)
+ session_set_env (session, "MIR_SERVER_HOST_SOCKET", compositor->priv->socket);
+
+ if (!session_get_env (session, "MIR_SERVER_NAME"))
+ {
+ gchar *name;
+ if (IS_GREETER_SESSION (session))
+ {
+ name = g_strdup_printf ("greeter-%d", compositor->priv->next_greeter_id);
+ compositor->priv->next_greeter_id++;
+ }
+ else
+ {
+ name = g_strdup_printf ("session-%d", compositor->priv->next_session_id);
+ compositor->priv->next_session_id++;
+ }
+ session_set_env (session, "MIR_SERVER_NAME", name);
+ g_free (name);
+ }
+
+ if (compositor->priv->vt >= 0)
+ {
+ gchar *value = g_strdup_printf ("%d", compositor->priv->vt);
+ session_set_env (session, "XDG_VTNR", value);
+ g_free (value);
+ }
+}
+
+static void
+unity_system_compositor_disconnect_session (DisplayServer *display_server, Session *session)
+{
+ session_unset_env (session, "XDG_SESSION_TYPE");
+ session_unset_env (session, "MIR_SERVER_HOST_SOCKET");
+ session_unset_env (session, "MIR_SERVER_NAME");
+ session_unset_env (session, "XDG_VTNR");
+}
+
static gchar *
get_absolute_command (const gchar *command)
{
gsize n_to_read = 0;
guint16 id, payload_length;
/*guint8 *payload;*/
-
+
if (condition == G_IO_HUP)
{
l_debug (compositor, "Compositor closed communication channel");
+ compositor->priv->from_compositor_watch = 0;
return FALSE;
}
}
static void
-run_cb (Process *process, UnitySystemCompositor *compositor)
+run_cb (Process *process, gpointer user_data)
{
int fd;
fd = open ("/dev/null", O_RDONLY);
dup2 (fd, STDIN_FILENO);
close (fd);
-
- /* Redirect output to logfile */
- if (compositor->priv->log_file)
- {
- int fd;
- gchar *old_filename;
-
- /* Move old file out of the way */
- old_filename = g_strdup_printf ("%s.old", compositor->priv->log_file);
- rename (compositor->priv->log_file, old_filename);
- g_free (old_filename);
-
- /* Create new file and log to it */
- fd = g_open (compositor->priv->log_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (fd < 0)
- l_warning (compositor, "Failed to open log file %s: %s", compositor->priv->log_file, g_strerror (errno));
- else
- {
- dup2 (fd, STDOUT_FILENO);
- dup2 (fd, STDERR_FILENO);
- close (fd);
- }
- }
}
static gboolean
unity_system_compositor_start (DisplayServer *server)
{
UnitySystemCompositor *compositor = UNITY_SYSTEM_COMPOSITOR (server);
- gboolean result;
- gchar *dir, *command, *absolute_command, *value;
+ gboolean result, backup_logs;
+ GString *command;
+ gchar *dir, *log_file, *absolute_command, *value;
g_return_val_if_fail (compositor->priv->process == NULL, FALSE);
/* Setup logging */
dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
- compositor->priv->log_file = g_build_filename (dir, "unity-system-compositor.log", NULL);
- l_debug (compositor, "Logging to %s", compositor->priv->log_file);
+ log_file = g_build_filename (dir, "unity-system-compositor.log", NULL);
+ l_debug (compositor, "Logging to %s", log_file);
g_free (dir);
/* Setup environment */
- compositor->priv->process = process_new ();
+ compositor->priv->process = process_new (run_cb, compositor);
+ backup_logs = config_get_boolean (config_get_instance (), "LightDM", "backup-logs");
+ process_set_log_file (compositor->priv->process, log_file, TRUE, backup_logs ? LOG_MODE_BACKUP_AND_TRUNCATE : LOG_MODE_APPEND);
+ g_free (log_file);
process_set_clear_environment (compositor->priv->process, TRUE);
process_set_env (compositor->priv->process, "XDG_SEAT", "seat0");
value = g_strdup_printf ("%d", compositor->priv->vt);
process_set_env (compositor->priv->process, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
}
- command = g_strdup_printf ("%s --file '%s' --from-dm-fd %d --to-dm-fd %d --vt %d", compositor->priv->command, compositor->priv->socket, compositor->priv->to_compositor_pipe[0], compositor->priv->from_compositor_pipe[1], compositor->priv->vt);
- absolute_command = get_absolute_command (command);
- g_free (command);
+ /* Generate command line to run */
+ absolute_command = get_absolute_command (compositor->priv->command);
+ if (!absolute_command)
+ {
+ l_debug (compositor, "Can't launch compositor %s, not found in path", compositor->priv->command);
+ return FALSE;
+ }
+ command = g_string_new (absolute_command);
+ g_free (absolute_command);
+ g_string_append_printf (command, " --file '%s'", compositor->priv->socket);
+ g_string_append_printf (command, " --from-dm-fd %d --to-dm-fd %d", compositor->priv->to_compositor_pipe[0], compositor->priv->from_compositor_pipe[1]);
+ if (compositor->priv->vt > 0)
+ g_string_append_printf (command, " --vt %d", compositor->priv->vt);
+ process_set_command (compositor->priv->process, command->str);
+ g_string_free (command, TRUE);
/* Start the compositor */
- process_set_command (compositor->priv->process, absolute_command);
- g_free (absolute_command);
- g_signal_connect (compositor->priv->process, "stopped", G_CALLBACK (stopped_cb), compositor);
- g_signal_connect (compositor->priv->process, "run", G_CALLBACK (run_cb), compositor);
+ g_signal_connect (compositor->priv->process, PROCESS_SIGNAL_STOPPED, G_CALLBACK (stopped_cb), compositor);
result = process_start (compositor->priv->process, FALSE);
/* Close compostor ends of the pipes */
close (compositor->priv->to_compositor_pipe[0]);
- compositor->priv->to_compositor_pipe[0] = 0;
+ compositor->priv->to_compositor_pipe[0] = -1;
close (compositor->priv->from_compositor_pipe[1]);
- compositor->priv->from_compositor_pipe[1] = 0;
+ compositor->priv->from_compositor_pipe[1] = -1;
if (!result)
return FALSE;
return TRUE;
}
-
+
static void
unity_system_compositor_stop (DisplayServer *server)
{
compositor->priv = G_TYPE_INSTANCE_GET_PRIVATE (compositor, UNITY_SYSTEM_COMPOSITOR_TYPE, UnitySystemCompositorPrivate);
compositor->priv->vt = -1;
compositor->priv->command = g_strdup ("unity-system-compositor");
- compositor->priv->socket = g_strdup ("/tmp/mir_socket");
+ compositor->priv->socket = g_strdup ("/run/mir_socket");
compositor->priv->timeout = -1;
+ compositor->priv->to_compositor_pipe[0] = -1;
+ compositor->priv->to_compositor_pipe[1] = -1;
+ compositor->priv->from_compositor_pipe[0] = -1;
+ compositor->priv->from_compositor_pipe[1] = -1;
}
static void
unity_system_compositor_finalize (GObject *object)
{
- UnitySystemCompositor *self;
-
- self = UNITY_SYSTEM_COMPOSITOR (object);
+ UnitySystemCompositor *self = UNITY_SYSTEM_COMPOSITOR (object);
if (self->priv->process)
{
g_signal_handlers_disconnect_matched (self->priv->process, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
g_object_unref (self->priv->process);
}
- g_free (self->priv->log_file);
g_free (self->priv->command);
g_free (self->priv->socket);
if (self->priv->have_vt_ref)
close (self->priv->from_compositor_pipe[0]);
close (self->priv->from_compositor_pipe[1]);
g_io_channel_unref (self->priv->from_compositor_channel);
- g_source_remove (self->priv->from_compositor_watch);
+ if (self->priv->from_compositor_watch)
+ g_source_remove (self->priv->from_compositor_watch);
g_free (self->priv->read_buffer);
- if (self->priv->timeout_source != 0)
+ if (self->priv->timeout_source)
g_source_remove (self->priv->timeout_source);
G_OBJECT_CLASS (unity_system_compositor_parent_class)->finalize (object);
DisplayServerClass *display_server_class = DISPLAY_SERVER_CLASS (klass);
display_server_class->get_vt = unity_system_compositor_get_vt;
+ display_server_class->connect_session = unity_system_compositor_connect_session;
+ display_server_class->disconnect_session = unity_system_compositor_disconnect_session;
display_server_class->start = unity_system_compositor_start;
display_server_class->stop = unity_system_compositor_stop;
object_class->finalize = unity_system_compositor_finalize;
g_type_class_add_private (klass, sizeof (UnitySystemCompositorPrivate));
}
+
+static gint
+unity_system_compositor_real_logprefix (Logger *self, gchar *buf, gulong buflen)
+{
+ return g_snprintf (buf, buflen, "Unity System Compositor: ");
+}
+
+static void
+unity_system_compositor_logger_iface_init (LoggerInterface *iface)
+{
+ iface->logprefix = &unity_system_compositor_real_logprefix;
+}