Back to index

lightdm  1.3.2
Functions | Variables
dm-tool.c File Reference
#include <config.h>
#include <stdlib.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <gio/gio.h>

Go to the source code of this file.

Functions

static void usage ()
static void xephyr_setup_cb (gpointer user_data)
static void xephyr_signal_cb (int signum)
int main (int argc, char **argv)

Variables

static GDBusProxy * dm_proxy
static GDBusProxy * seat_proxy
static gint xephyr_display_number
static GPid xephyr_pid

Function Documentation

int main ( int  argc,
char **  argv 
)

Definition at line 72 of file dm-tool.c.

{
    gchar *command;
    gint n_options;
    gchar **options;
    GError *error = NULL;
    gint arg_index;
    GBusType bus_type = G_BUS_TYPE_SYSTEM;

    g_type_init ();

    for (arg_index = 1; arg_index < argc; arg_index++)
    {
        gchar *arg = argv[arg_index];

        if (!g_str_has_prefix (arg, "-"))
            break;
      
        if (strcmp (arg, "-h") == 0 || strcmp (arg, "--help") == 0)
        {
            g_printerr ("Usage:\n"
                        "  dm-tool [OPTION...] COMMAND [ARGS...] - Display Manager tool\n"
                        "\n"
                        "Options:\n"
                        "  -h, --help        Show help options\n"
                        "  -v, --version     Show release version\n"
                        "  --session-bus     Use session D-Bus\n"
                        "\n"
                        "Commands:\n"
                        "  switch-to-greeter                   Switch to the greeter\n"
                        "  switch-to-user USERNAME [SESSION]   Switch to a user session\n"
                        "  switch-to-guest [SESSION]           Switch to a guest session\n"
                        "  lock                                Lock the current seat\n"
                        "  list-seats                          List the active seats\n"
                        "  add-nested-seat                     Start a nested display\n"
                        "  add-local-x-seat DISPLAY_NUMBER     Add a local X seat\n"
                        "  add-seat TYPE [NAME=VALUE...]       Add a dynamic seat\n");
            return EXIT_SUCCESS;
        }
        else if (strcmp (arg, "-v") == 0 || strcmp (arg, "--version") == 0)
        {
            /* NOTE: Is not translated so can be easily parsed */
            g_printerr ("lightdm %s\n", VERSION);
            return EXIT_SUCCESS;
        }
        else if (strcmp (arg, "--session-bus") == 0)
            bus_type = G_BUS_TYPE_SESSION;
        else
        {
            g_printerr ("Unknown option %s\n", arg);
            usage ();
            return EXIT_FAILURE;
        }
    }

    if (arg_index >= argc)
    {
        g_printerr ("Missing command\n");
        usage ();
        return EXIT_FAILURE;
    }

    dm_proxy = g_dbus_proxy_new_for_bus_sync (bus_type,
                                              G_DBUS_PROXY_FLAGS_NONE,
                                              NULL,
                                              "org.freedesktop.DisplayManager",
                                              "/org/freedesktop/DisplayManager",
                                              "org.freedesktop.DisplayManager",
                                              NULL,
                                              &error);
    if (!dm_proxy)
    {
        g_printerr ("Unable to contact display manager: %s\n", error->message);
        return EXIT_FAILURE;
    }
    g_clear_error (&error);
  
    if (!g_getenv ("XDG_SEAT_PATH"))
    {
        g_printerr ("Not running inside a display manager, XDG_SEAT_PATH not defined\n");
        return EXIT_FAILURE;
    }

    seat_proxy = g_dbus_proxy_new_for_bus_sync (bus_type,
                                                G_DBUS_PROXY_FLAGS_NONE,
                                                NULL,
                                                "org.freedesktop.DisplayManager",
                                                g_getenv ("XDG_SEAT_PATH"),
                                                "org.freedesktop.DisplayManager.Seat",
                                                NULL,
                                                &error);
    if (!seat_proxy)
    {
        g_printerr ("Unable to contact display manager: %s\n", error->message);
        return EXIT_FAILURE;
    }
    g_clear_error (&error);

    command = argv[arg_index];
    arg_index++;
    n_options = argc - arg_index;
    options = argv + arg_index;
    if (strcmp (command, "switch-to-greeter") == 0)
    {
        if (n_options != 0)
        {
            g_printerr ("Usage switch-to-greeter\n");
            usage ();
            return EXIT_FAILURE;
        }

        if (!g_dbus_proxy_call_sync (seat_proxy,
                                     "SwitchToGreeter",
                                     g_variant_new ("()"),
                                     G_DBUS_CALL_FLAGS_NONE,
                                     -1,
                                     NULL,
                                     &error))
        {
            g_printerr ("Unable to switch to greeter: %s\n", error->message);
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;
    }
    else if (strcmp (command, "switch-to-user") == 0)
    {
        gchar *username, *session = "";

        if (n_options > 1)
        {
            g_printerr ("Usage switch-to-user USERNAME [SESSION]\n");
            usage ();
            return EXIT_FAILURE;
        }

        username = options[0];
        if (n_options == 2)
            session = options[1];

        if (!g_dbus_proxy_call_sync (seat_proxy,
                                     "SwitchToUser",
                                     g_variant_new ("(ss)", username, session),
                                     G_DBUS_CALL_FLAGS_NONE,
                                     -1,
                                     NULL,
                                     &error))
        {
            g_printerr ("Unable to switch to user %s: %s\n", username, error->message);
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;
    }
    else if (strcmp (command, "switch-to-guest") == 0)
    {
        gchar *session = "";

        if (n_options > 1)
        {
            g_printerr ("Usage switch-to-guest [SESSION]\n");
            usage ();
            return EXIT_FAILURE;
        }

        if (n_options == 1)
            session = options[0];

        if (!g_dbus_proxy_call_sync (seat_proxy,
                                     "SwitchToGuest",
                                     g_variant_new ("(s)", session),
                                     G_DBUS_CALL_FLAGS_NONE,
                                     -1,
                                     NULL,
                                     &error))
        {
            g_printerr ("Unable to switch to guest: %s\n", error->message);
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;
    }
    else if (strcmp (command, "lock") == 0)
    {
        if (n_options != 0)
        {
            g_printerr ("Usage lock\n");
            usage ();
            return EXIT_FAILURE;
        }

        if (!g_dbus_proxy_call_sync (seat_proxy,
                                     "Lock",
                                     g_variant_new ("()"),
                                     G_DBUS_CALL_FLAGS_NONE,
                                     -1,
                                     NULL,
                                     &error))
        {
            g_printerr ("Unable to lock seat: %s\n", error->message);
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;
    }
    else if (strcmp (command, "list-seats") == 0)
    {
        GVariant *seats, *sessions;
        GVariantIter *seat_iter;
        gchar *seat_path;

        if (!g_dbus_proxy_get_name_owner (dm_proxy))
        {
            g_printerr ("Unable to contact display manager\n");
            return EXIT_FAILURE;
        }
        seats = g_dbus_proxy_get_cached_property (dm_proxy, "Seats");

        g_variant_get (seats, "ao", &seat_iter);
        while (g_variant_iter_loop (seat_iter, "&o", &seat_path))
        {
            gchar *seat_name;
            GDBusProxy *seat_proxy;
            gchar **property_names;
            GVariant *sessions;
            GVariantIter *session_iter;
            gchar *session_path;
            gint i;

            if (g_str_has_prefix (seat_path, "/org/freedesktop/DisplayManager/"))
                seat_name = seat_path + strlen ("/org/freedesktop/DisplayManager/");
            else
                seat_name = seat_path;

            seat_proxy = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (dm_proxy),
                                                G_DBUS_PROXY_FLAGS_NONE,
                                                NULL,
                                                "org.freedesktop.DisplayManager",
                                                seat_path,
                                                "org.freedesktop.DisplayManager.Seat",
                                                NULL,
                                                NULL);
            if (!seat_proxy || !g_dbus_proxy_get_name_owner (seat_proxy))
                continue;

            g_print ("%s\n", seat_name);
            property_names = g_dbus_proxy_get_cached_property_names (seat_proxy);
            for (i = 0; property_names[i]; i++)
            {
                GVariant *value;

                if (strcmp (property_names[i], "Sessions") == 0)
                    continue;

                value = g_dbus_proxy_get_cached_property (seat_proxy, property_names[i]);
                g_print ("  %s=%s\n", property_names[i], g_variant_print (value, FALSE));
                g_variant_unref (value);
            }

            sessions = g_dbus_proxy_get_cached_property (seat_proxy, "Sessions");
            if (!sessions)
                continue;

            g_variant_get (sessions, "ao", &session_iter);
            while (g_variant_iter_loop (session_iter, "&o", &session_path))
            {
                GDBusProxy *session_proxy;
                gchar *session_name;

                if (g_str_has_prefix (session_path, "/org/freedesktop/DisplayManager/"))
                    session_name = session_path + strlen ("/org/freedesktop/DisplayManager/");
                else
                    session_name = session_path;

                session_proxy = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (dm_proxy),
                                                       G_DBUS_PROXY_FLAGS_NONE,
                                                       NULL,
                                                       "org.freedesktop.DisplayManager",
                                                       session_path,
                                                       "org.freedesktop.DisplayManager.Session",
                                                       NULL,
                                                       NULL);
                if (!session_proxy || !g_dbus_proxy_get_name_owner (session_proxy))
                    continue;

                g_print ("  %s\n", session_name);
                property_names = g_dbus_proxy_get_cached_property_names (session_proxy);
                for (i = 0; property_names[i]; i++)
                {
                    GVariant *value;

                    if (strcmp (property_names[i], "Seat") == 0)
                        continue;

                    value = g_dbus_proxy_get_cached_property (session_proxy, property_names[i]);
                    g_print ("    %s=%s\n", property_names[i], g_variant_print (value, FALSE));
                    g_variant_unref (value);
                }

                g_object_unref (session_proxy);
            }
            g_variant_iter_free (session_iter);

            g_object_unref (seat_proxy);
        }
        g_variant_iter_free (seat_iter);

        return EXIT_SUCCESS;
    }
    else if (strcmp (command, "add-nested-seat") == 0)
    {
        gchar *path, *xephyr_command, **xephyr_argv;
        GMainLoop *loop;

        path = g_find_program_in_path ("Xephyr");
        if (!path)
        {
            g_printerr ("Unable to find Xephyr, please install it\n");
            return EXIT_FAILURE;
        }

        /* Get a unique display number.  It's racy, but the only reliable method to get one */
        xephyr_display_number = 0;
        while (TRUE)
        {
            gchar *lock_name;
            gboolean has_lock;

            lock_name = g_strdup_printf ("/tmp/.X%d-lock", xephyr_display_number);
            has_lock = g_file_test (lock_name, G_FILE_TEST_EXISTS);
            g_free (lock_name);
          
            if (has_lock)
                xephyr_display_number++;
            else
                break;
        }

        /* Wait for signal from Xephyr is ready */
        signal (SIGUSR1, xephyr_signal_cb);

        xephyr_command = g_strdup_printf ("Xephyr :%d", xephyr_display_number);
        if (!g_shell_parse_argv (xephyr_command, NULL, &xephyr_argv, &error) ||
            !g_spawn_async (NULL, xephyr_argv, NULL,
                            G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
                            xephyr_setup_cb, NULL,
                            &xephyr_pid, &error))
        {
            g_printerr ("Error running Xephyr: %s\n", error->message);
            exit (EXIT_FAILURE);
        }
        g_clear_error (&error);

        /* Block until ready */
        loop = g_main_loop_new (NULL, FALSE);
        g_main_loop_run (loop);
    }
    else if (strcmp (command, "add-local-x-seat") == 0)
    {
        GVariant *result;
        gint display_number;
        const gchar *path;

        if (n_options != 1)
        {
            g_printerr ("Usage add-seat DISPLAY_NUMBER\n");
            usage ();
            return EXIT_FAILURE;
        }

        display_number = atoi (options[0]);

        result = g_dbus_proxy_call_sync (dm_proxy,
                                         "AddLocalXSeat",
                                         g_variant_new ("(i)", display_number),
                                         G_DBUS_CALL_FLAGS_NONE,
                                         -1,
                                         NULL,
                                         &error);
        if (!result)
        {
            g_printerr ("Unable to add local X seat: %s\n", error->message);
            return EXIT_FAILURE;
        }

        if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(o)")))
        {
            g_printerr ("Unexpected response to AddLocalXSeat: %s\n", g_variant_get_type_string (result));
            return EXIT_FAILURE;
        }

        g_variant_get (result, "(&o)", &path);
        g_print ("%s\n", path);

        return EXIT_SUCCESS; 
    }
    else if (strcmp (command, "add-seat") == 0)
    {
        GVariant *result;
        gchar *type, *path;
        GVariantBuilder *properties;
        gint i;

        if (n_options < 1)
        {
            g_printerr ("Usage add-seat TYPE [NAME=VALUE...]\n");
            usage ();
            return EXIT_FAILURE;
        }

        type = options[0];
        properties = g_variant_builder_new (G_VARIANT_TYPE ("a(ss)"));
      
        for (i = 1; i < n_options; i++)
        {
            gchar *property, *name, *value;

            property = g_strdup (options[i]);
            name = property;
            value = strchr (property, '=');
            if (value)
            {
                *value = '\0';
                value++;
            }
            else
               value = "";

            g_variant_builder_add_value (properties, g_variant_new ("(ss)", name, value));
            g_free (property);
        }
      
        result = g_dbus_proxy_call_sync (dm_proxy,
                                         "AddSeat",
                                         g_variant_new ("(sa(ss))", type, properties),
                                         G_DBUS_CALL_FLAGS_NONE,
                                         -1,
                                         NULL,
                                         &error);
        g_variant_builder_unref (properties);
        if (!result)
        {
            g_printerr ("Unable to add seat: %s\n", error->message);
            return EXIT_FAILURE;
        }

        if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(o)")))
        {
            g_printerr ("Unexpected response to AddSeat: %s\n", g_variant_get_type_string (result));
            return EXIT_FAILURE;
        }

        g_variant_get (result, "(&o)", &path);
        g_print ("%s\n", path);

        return EXIT_SUCCESS;
    }

    g_printerr ("Unknown command %s\n", command);
    usage ();
    return EXIT_FAILURE;
}

Here is the call graph for this function:

static void usage ( ) [static]

Definition at line 25 of file dm-tool.c.

{
    g_printerr (/* Text printed out when an unknown command-line argument provided */
                _("Run 'dm-tool --help' to see a full list of available command line options."));
    g_printerr ("\n");
}

Here is the caller graph for this function:

static void xephyr_setup_cb ( gpointer  user_data) [static]

Definition at line 33 of file dm-tool.c.

{
    signal (SIGUSR1, SIG_IGN);
}

Here is the caller graph for this function:

static void xephyr_signal_cb ( int  signum) [static]

Definition at line 39 of file dm-tool.c.

{
    gchar *path;
    GVariant *result;
    GError *error = NULL;

    result = g_dbus_proxy_call_sync (dm_proxy,
                                     "AddLocalXSeat",
                                     g_variant_new ("(i)", xephyr_display_number),
                                     G_DBUS_CALL_FLAGS_NONE,
                                     -1,
                                     NULL,
                                     &error);
    if (!result)
    {
        g_printerr ("Unable to add seat: %s\n", error->message);
        kill (xephyr_pid, SIGQUIT);
        exit (EXIT_FAILURE);
    }

    if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(o)")))
    {
        g_printerr ("Unexpected response to AddSeat: %s\n", g_variant_get_type_string (result));
        exit (EXIT_FAILURE);
    }

    g_variant_get (result, "(&o)", &path);
    g_print ("%s\n", path);

    exit (EXIT_SUCCESS);
}

Here is the caller graph for this function:


Variable Documentation

GDBusProxy* dm_proxy [static]

Definition at line 19 of file dm-tool.c.

GDBusProxy * seat_proxy [static]

Definition at line 19 of file dm-tool.c.

gint xephyr_display_number [static]

Definition at line 21 of file dm-tool.c.

GPid xephyr_pid [static]

Definition at line 22 of file dm-tool.c.