Back to index

lightdm  1.3.2
Classes | Functions | Variables
xserver-local.c File Reference
#include <config.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <glib/gstdio.h>
#include "xserver-local.h"
#include "configuration.h"
#include "process.h"
#include "vt.h"
#include "plymouth.h"

Go to the source code of this file.

Classes

struct  XServerLocalPrivate

Functions

 G_DEFINE_TYPE (XServerLocal, xserver_local, XSERVER_TYPE)
static gboolean display_number_in_use (guint display_number)
guint xserver_local_get_unused_display_number (void)
void xserver_local_release_display_number (guint display_number)
XServerLocalxserver_local_new (void)
void xserver_local_set_command (XServerLocal *server, const gchar *command)
void xserver_local_set_config (XServerLocal *server, const gchar *path)
void xserver_local_set_layout (XServerLocal *server, const gchar *layout)
void xserver_local_set_allow_tcp (XServerLocal *server, gboolean allow_tcp)
void xserver_local_set_xdmcp_server (XServerLocal *server, const gchar *hostname)
const gchar * xserver_local_get_xdmcp_server (XServerLocal *server)
void xserver_local_set_xdmcp_port (XServerLocal *server, guint port)
guint xserver_local_get_xdmcp_port (XServerLocal *server)
void xserver_local_set_xdmcp_key (XServerLocal *server, const gchar *key)
gint xserver_local_get_vt (XServerLocal *server)
gchar * xserver_local_get_authority_file_path (XServerLocal *server)
static gchar * get_absolute_command (const gchar *command)
static void run_cb (Process *process, XServerLocal *server)
static void got_signal_cb (Process *process, int signum, XServerLocal *server)
static void stopped_cb (Process *process, XServerLocal *server)
static void write_authority_file (XServerLocal *server)
static gboolean xserver_local_start (DisplayServer *display_server)
static void xserver_local_stop (DisplayServer *server)
static gboolean xserver_local_get_is_stopped (DisplayServer *server)
static void xserver_local_init (XServerLocal *server)
static void xserver_local_finalize (GObject *object)
static void xserver_local_class_init (XServerLocalClass *klass)

Variables

static GList * display_numbers = NULL

Class Documentation

struct XServerLocalPrivate

Definition at line 25 of file xserver-local.c.

Collaboration diagram for XServerLocalPrivate:
Class Members
gboolean allow_tcp
GFile * authority_file
gchar * command
gchar * config_file
gboolean got_signal
gchar * layout
gchar * log_file
gboolean replacing_plymouth
gint vt
gchar * xdmcp_key
guint xdmcp_port
gchar * xdmcp_server
Process * xserver_process

Function Documentation

static gboolean display_number_in_use ( guint  display_number) [static]

Definition at line 72 of file xserver-local.c.

{
    GList *link;
    gchar *path;
    gboolean result;

    for (link = display_numbers; link; link = link->next)
    {
        guint number = GPOINTER_TO_UINT (link->data);
        if (number == display_number)
            return TRUE;
    }

    path = g_strdup_printf ("/tmp/.X%d-lock", display_number);
    result = g_file_test (path, G_FILE_TEST_EXISTS);
    g_free (path);

    return result;
}

Here is the caller graph for this function:

G_DEFINE_TYPE ( XServerLocal  ,
xserver_local  ,
XSERVER_TYPE   
)
static gchar* get_absolute_command ( const gchar *  command) [static]

Definition at line 241 of file xserver-local.c.

{
    gchar **tokens;
    gchar *absolute_binary, *absolute_command = NULL;

    tokens = g_strsplit (command, " ", 2);

    absolute_binary = g_find_program_in_path (tokens[0]);
    if (absolute_binary)
    {
        if (tokens[1])
            absolute_command = g_strjoin (" ", absolute_binary, tokens[1], NULL);
        else
            absolute_command = g_strdup (absolute_binary);
    }
    g_free (absolute_binary);

    g_strfreev (tokens);

    return absolute_command;
}

Here is the caller graph for this function:

static void got_signal_cb ( Process process,
int  signum,
XServerLocal server 
) [static]

Definition at line 294 of file xserver-local.c.

{
    if (signum == SIGUSR1 && !server->priv->got_signal)
    {
        server->priv->got_signal = TRUE;
        g_debug ("Got signal from X server :%d", xserver_get_display_number (XSERVER (server)));

        if (server->priv->replacing_plymouth)
        {
            g_debug ("Stopping Plymouth, X server is ready");
            server->priv->replacing_plymouth = FALSE;
            plymouth_quit (TRUE);
        }

        // FIXME: Check return value
        DISPLAY_SERVER_CLASS (xserver_local_parent_class)->start (DISPLAY_SERVER (server));
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void run_cb ( Process process,
XServerLocal server 
) [static]

Definition at line 264 of file xserver-local.c.

{
    int fd;

    /* Make input non-blocking */
    fd = open ("/dev/null", O_RDONLY);
    dup2 (fd, STDIN_FILENO);
    close (fd);

    /* Redirect output to logfile */
    if (server->priv->log_file)
    {
         int fd;

         fd = g_open (server->priv->log_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
         if (fd < 0)
             g_warning ("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);
}

Here is the caller graph for this function:

static void stopped_cb ( Process process,
XServerLocal server 
) [static]

Definition at line 314 of file xserver-local.c.

{
    g_debug ("X server stopped");

    g_object_unref (server->priv->xserver_process);
    server->priv->xserver_process = NULL;

    xserver_local_release_display_number (xserver_get_display_number (XSERVER (server)));
  
    if (xserver_get_authority (XSERVER (server)) && server->priv->authority_file)
    {
        GError *error = NULL;
        gchar *path;

        path = g_file_get_path (server->priv->authority_file);      
        g_debug ("Removing X server authority %s", path);
        g_free (path);

        g_file_delete (server->priv->authority_file, NULL, &error);
        if (error)
            g_debug ("Error removing authority: %s", error->message);
        g_clear_error (&error);

        g_object_unref (server->priv->authority_file);
        server->priv->authority_file = NULL;
    }

    if (server->priv->vt >= 0)
    {
        vt_unref (server->priv->vt);
        server->priv->vt = -1;
    }

    if (server->priv->replacing_plymouth && plymouth_get_is_running ())
    {
        g_debug ("Stopping Plymouth, X server failed to start");
        server->priv->replacing_plymouth = FALSE;
        plymouth_quit (FALSE);
    }

    DISPLAY_SERVER_CLASS (xserver_local_parent_class)->stop (DISPLAY_SERVER (server));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void write_authority_file ( XServerLocal server) [static]

Definition at line 358 of file xserver-local.c.

{
    XAuthority *authority;
    gchar *path;
    GError *error = NULL;

    authority = xserver_get_authority (XSERVER (server));
    if (!authority)
        return;

    /* Get file to write to if have authority */
    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);
        g_mkdir_with_parents (dir, S_IRWXU);

        path = g_build_filename (dir, xserver_get_address (XSERVER (server)), NULL);
        g_free (dir);
        server->priv->authority_file = g_file_new_for_path (path);
        g_free (path);
    }

    path = g_file_get_path (server->priv->authority_file);
    g_debug ("Writing X server authority to %s", path);
    g_free (path);

    xauth_write (authority, XAUTH_WRITE_MODE_REPLACE, server->priv->authority_file, &error);
    if (error)
        g_warning ("Failed to write authority: %s", error->message);
    g_clear_error (&error);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void xserver_local_class_init ( XServerLocalClass klass) [static]

Definition at line 553 of file xserver-local.c.

{
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
    DisplayServerClass *display_server_class = DISPLAY_SERVER_CLASS (klass);

    display_server_class->start = xserver_local_start;
    display_server_class->stop = xserver_local_stop;
    display_server_class->get_is_stopped = xserver_local_get_is_stopped;
    object_class->finalize = xserver_local_finalize;

    g_type_class_add_private (klass, sizeof (XServerLocalPrivate));
}

Here is the call graph for this function:

static void xserver_local_finalize ( GObject *  object) [static]

Definition at line 530 of file xserver-local.c.

{
    XServerLocal *self;

    self = XSERVER_LOCAL (object);  

    if (self->priv->xserver_process)
        g_object_unref (self->priv->xserver_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->xdmcp_server);
    g_free (self->priv->xdmcp_key);
    if (self->priv->authority_file)
        g_object_unref (self->priv->authority_file);
    if (self->priv->vt >= 0)
        vt_unref (self->priv->vt);

    G_OBJECT_CLASS (xserver_local_parent_class)->finalize (object);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 232 of file xserver-local.c.

{
    g_return_val_if_fail (server != NULL, 0);
    if (server->priv->authority_file)
        return g_file_get_path (server->priv->authority_file);
    return NULL;
}

Here is the caller graph for this function:

static gboolean xserver_local_get_is_stopped ( DisplayServer server) [static]

Definition at line 516 of file xserver-local.c.

{
    return process_get_pid (XSERVER_LOCAL (server)->priv->xserver_process) == 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 93 of file xserver-local.c.

{
    guint number;

    number = config_get_integer (config_get_instance (), "LightDM", "minimum-display-number");
    while (display_number_in_use (number))
        number++;

    display_numbers = g_list_append (display_numbers, GUINT_TO_POINTER (number));

    return number;
}

Here is the call graph for this function:

Here is the caller graph for this function:

gint xserver_local_get_vt ( XServerLocal server)

Definition at line 225 of file xserver-local.c.

{
    g_return_val_if_fail (server != NULL, 0);
    return server->priv->vt;
}

Here is the caller graph for this function:

Definition at line 210 of file xserver-local.c.

{
    g_return_val_if_fail (server != NULL, 0);
    return server->priv->xdmcp_port;
}
const gchar* xserver_local_get_xdmcp_server ( XServerLocal server)

Definition at line 196 of file xserver-local.c.

{
    g_return_val_if_fail (server != NULL, 0);
    return server->priv->xdmcp_server;
}
static void xserver_local_init ( XServerLocal server) [static]

Definition at line 522 of file xserver-local.c.

{
    server->priv = G_TYPE_INSTANCE_GET_PRIVATE (server, XSERVER_LOCAL_TYPE, XServerLocalPrivate);
    server->priv->vt = -1;
    server->priv->command = g_strdup ("X");
}

Definition at line 122 of file xserver-local.c.

{
    XServerLocal *self = g_object_new (XSERVER_LOCAL_TYPE, NULL);
    gchar *name;

    xserver_set_display_number (XSERVER (self), xserver_local_get_unused_display_number ());

    name = g_strdup_printf ("x-%d", xserver_get_display_number (XSERVER (self)));
    display_server_set_name (DISPLAY_SERVER (self), name);
    g_free (name);

    /* Replace Plymouth if it is running */
    if (plymouth_get_is_active () && plymouth_has_active_vt ())
    {
        gint active_vt = vt_get_active ();
        if (active_vt >= vt_get_min ())
        {
            g_debug ("X server %s will replace Plymouth", xserver_get_address (XSERVER (self)));
            self->priv->replacing_plymouth = TRUE;
            self->priv->vt = active_vt;
            plymouth_deactivate ();
        }
        else
            g_debug ("Plymouth is running on VT %d, but this is less than the configured minimum of %d so not replacing it", active_vt, vt_get_min ());
    }
    if (self->priv->vt < 0)
        self->priv->vt = vt_get_unused ();
    if (self->priv->vt >= 0)
        vt_ref (self->priv->vt);

    return self;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void xserver_local_release_display_number ( guint  display_number)

Definition at line 107 of file xserver-local.c.

{
    GList *link;
    for (link = display_numbers; link; link = link->next)
    {
        guint number = GPOINTER_TO_UINT (link->data);
        if (number == display_number)
        {
            display_numbers = g_list_remove_link (display_numbers, link);
            return;
        }
    }
}

Here is the caller graph for this function:

void xserver_local_set_allow_tcp ( XServerLocal server,
gboolean  allow_tcp 
)

Definition at line 180 of file xserver-local.c.

{
    g_return_if_fail (server != NULL);
    server->priv->allow_tcp = allow_tcp;
}

Here is the caller graph for this function:

void xserver_local_set_command ( XServerLocal server,
const gchar *  command 
)

Definition at line 156 of file xserver-local.c.

{
    g_return_if_fail (server != NULL);
    g_free (server->priv->command);
    server->priv->command = g_strdup (command);
}

Here is the caller graph for this function:

void xserver_local_set_config ( XServerLocal server,
const gchar *  path 
)

Definition at line 164 of file xserver-local.c.

{
    g_return_if_fail (server != NULL);
    g_free (server->priv->config_file);
    server->priv->config_file = g_strdup (path);
}

Here is the caller graph for this function:

void xserver_local_set_layout ( XServerLocal server,
const gchar *  layout 
)

Definition at line 172 of file xserver-local.c.

{
    g_return_if_fail (server != NULL);
    g_free (server->priv->layout);
    server->priv->layout = g_strdup (layout);
}

Here is the caller graph for this function:

void xserver_local_set_xdmcp_key ( XServerLocal server,
const gchar *  key 
)

Definition at line 217 of file xserver-local.c.

{
    g_return_if_fail (server != NULL);
    g_free (server->priv->xdmcp_key);
    server->priv->xdmcp_key = g_strdup (key);
}

Here is the caller graph for this function:

void xserver_local_set_xdmcp_port ( XServerLocal server,
guint  port 
)

Definition at line 203 of file xserver-local.c.

{
    g_return_if_fail (server != NULL);
    server->priv->xdmcp_port = port;
}

Here is the caller graph for this function:

void xserver_local_set_xdmcp_server ( XServerLocal server,
const gchar *  hostname 
)

Definition at line 187 of file xserver-local.c.

{
    g_return_if_fail (server != NULL);
    g_free (server->priv->xdmcp_server);
    server->priv->xdmcp_server = g_strdup (hostname);
    display_server_set_start_local_sessions (DISPLAY_SERVER (server), hostname == NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean xserver_local_start ( DisplayServer display_server) [static]

Definition at line 395 of file xserver-local.c.

{
    XServerLocal *server = XSERVER_LOCAL (display_server);
    gboolean result;
    gchar *filename, *dir, *absolute_command;
    gchar hostname[1024], *number;
    GString *command;

    g_return_val_if_fail (server->priv->xserver_process == NULL, FALSE);

    server->priv->got_signal = FALSE;

    g_return_val_if_fail (server->priv->command != NULL, FALSE);

    server->priv->xserver_process = process_new ();
    process_set_clear_environment (server->priv->xserver_process, TRUE);
    g_signal_connect (server->priv->xserver_process, "run", G_CALLBACK (run_cb), server);  
    g_signal_connect (server->priv->xserver_process, "got-signal", G_CALLBACK (got_signal_cb), server);
    g_signal_connect (server->priv->xserver_process, "stopped", G_CALLBACK (stopped_cb), server);

    /* Setup logging */
    filename = g_strdup_printf ("%s.log", display_server_get_name (display_server));
    dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
    server->priv->log_file = g_build_filename (dir, filename, NULL);
    g_debug ("Logging to %s", server->priv->log_file);
    g_free (filename);
    g_free (dir);

    absolute_command = get_absolute_command (server->priv->command);
    if (!absolute_command)
    {
        g_debug ("Can't launch X server %s, not found in path", server->priv->command);
        stopped_cb (server->priv->xserver_process, XSERVER_LOCAL (server));
        return FALSE;
    }
    command = g_string_new (absolute_command);
    g_free (absolute_command);

    g_string_append_printf (command, " :%d", xserver_get_display_number (XSERVER (server)));

    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);

    gethostname (hostname, 1024);
    number = g_strdup_printf ("%d", xserver_get_display_number (XSERVER (server)));
    if (!server->priv->xdmcp_key)
        xserver_set_authority (XSERVER (server), xauth_new_cookie (XAUTH_FAMILY_LOCAL, (guint8*) hostname, strlen (hostname), number));
    g_free (number);
    write_authority_file (server);
    if (server->priv->authority_file)
    {
        gchar *path = g_file_get_path (server->priv->authority_file);
        g_string_append_printf (command, " -auth %s", path);
        g_free (path);
    }

    /* Connect to a remote server using XDMCP */
    if (server->priv->xdmcp_server != NULL)
    {
        if (server->priv->xdmcp_port != 0)
            g_string_append_printf (command, " -port %d", server->priv->xdmcp_port);
        g_string_append_printf (command, " -query %s", server->priv->xdmcp_server);
        if (server->priv->xdmcp_key)
            g_string_append_printf (command, " -cookie %s", server->priv->xdmcp_key);
    }
    else if (!server->priv->allow_tcp)
        g_string_append (command, " -nolisten tcp");

    if (server->priv->vt >= 0)
        g_string_append_printf (command, " vt%d -novtswitch", server->priv->vt);

    if (server->priv->replacing_plymouth)
        g_string_append (command, " -background none");
    process_set_command (server->priv->xserver_process, command->str);
    g_string_free (command, TRUE);

    g_debug ("Launching X Server");

    /* If running inside another display then pass through those variables */
    if (g_getenv ("DISPLAY"))
    {
        process_set_env (server->priv->xserver_process, "DISPLAY", g_getenv ("DISPLAY"));
        if (g_getenv ("XAUTHORITY"))
            process_set_env (server->priv->xserver_process, "XAUTHORITY", g_getenv ("XAUTHORITY"));
        else
        {
            gchar *path;
            path = g_build_filename (g_get_home_dir (), ".Xauthority", NULL);
            process_set_env (server->priv->xserver_process, "XAUTHORITY", path);
        }
    }

    /* Variable required for regression tests */
    if (g_getenv ("LIGHTDM_TEST_ROOT"))
    {
        process_set_env (server->priv->xserver_process, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
        process_set_env (server->priv->xserver_process, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
        process_set_env (server->priv->xserver_process, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
    }

    result = process_start (server->priv->xserver_process);

    if (result)
        g_debug ("Waiting for ready signal from X server :%d", xserver_get_display_number (XSERVER (server)));

    if (!result)
        stopped_cb (server->priv->xserver_process, XSERVER_LOCAL (server));

    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void xserver_local_stop ( DisplayServer server) [static]

Definition at line 510 of file xserver-local.c.

{
    process_stop (XSERVER_LOCAL (server)->priv->xserver_process);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

GList* display_numbers = NULL [static]

Definition at line 69 of file xserver-local.c.