Back to index

lightdm  1.3.2
dm-tool.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2010-2011 Robert Ancell.
00003  * Author: Robert Ancell <robert.ancell@canonical.com>
00004  * 
00005  * This program is free software: you can redistribute it and/or modify it under
00006  * the terms of the GNU General Public License as published by the Free Software
00007  * Foundation, either version 3 of the License, or (at your option) any later
00008  * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
00009  * license.
00010  */
00011 
00012 #include <config.h>
00013 
00014 #include <stdlib.h>
00015 #include <glib.h>
00016 #include <glib/gi18n.h>
00017 #include <gio/gio.h>
00018 
00019 static GDBusProxy *dm_proxy, *seat_proxy;
00020 
00021 static gint xephyr_display_number;
00022 static GPid xephyr_pid;
00023 
00024 static void
00025 usage ()
00026 {
00027     g_printerr (/* Text printed out when an unknown command-line argument provided */
00028                 _("Run 'dm-tool --help' to see a full list of available command line options."));
00029     g_printerr ("\n");
00030 }
00031 
00032 static void
00033 xephyr_setup_cb (gpointer user_data)
00034 {
00035     signal (SIGUSR1, SIG_IGN);
00036 }
00037 
00038 static void
00039 xephyr_signal_cb (int signum)
00040 {
00041     gchar *path;
00042     GVariant *result;
00043     GError *error = NULL;
00044 
00045     result = g_dbus_proxy_call_sync (dm_proxy,
00046                                      "AddLocalXSeat",
00047                                      g_variant_new ("(i)", xephyr_display_number),
00048                                      G_DBUS_CALL_FLAGS_NONE,
00049                                      -1,
00050                                      NULL,
00051                                      &error);
00052     if (!result)
00053     {
00054         g_printerr ("Unable to add seat: %s\n", error->message);
00055         kill (xephyr_pid, SIGQUIT);
00056         exit (EXIT_FAILURE);
00057     }
00058 
00059     if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(o)")))
00060     {
00061         g_printerr ("Unexpected response to AddSeat: %s\n", g_variant_get_type_string (result));
00062         exit (EXIT_FAILURE);
00063     }
00064 
00065     g_variant_get (result, "(&o)", &path);
00066     g_print ("%s\n", path);
00067 
00068     exit (EXIT_SUCCESS);
00069 }
00070 
00071 int
00072 main (int argc, char **argv)
00073 {
00074     gchar *command;
00075     gint n_options;
00076     gchar **options;
00077     GError *error = NULL;
00078     gint arg_index;
00079     GBusType bus_type = G_BUS_TYPE_SYSTEM;
00080 
00081     g_type_init ();
00082 
00083     for (arg_index = 1; arg_index < argc; arg_index++)
00084     {
00085         gchar *arg = argv[arg_index];
00086 
00087         if (!g_str_has_prefix (arg, "-"))
00088             break;
00089       
00090         if (strcmp (arg, "-h") == 0 || strcmp (arg, "--help") == 0)
00091         {
00092             g_printerr ("Usage:\n"
00093                         "  dm-tool [OPTION...] COMMAND [ARGS...] - Display Manager tool\n"
00094                         "\n"
00095                         "Options:\n"
00096                         "  -h, --help        Show help options\n"
00097                         "  -v, --version     Show release version\n"
00098                         "  --session-bus     Use session D-Bus\n"
00099                         "\n"
00100                         "Commands:\n"
00101                         "  switch-to-greeter                   Switch to the greeter\n"
00102                         "  switch-to-user USERNAME [SESSION]   Switch to a user session\n"
00103                         "  switch-to-guest [SESSION]           Switch to a guest session\n"
00104                         "  lock                                Lock the current seat\n"
00105                         "  list-seats                          List the active seats\n"
00106                         "  add-nested-seat                     Start a nested display\n"
00107                         "  add-local-x-seat DISPLAY_NUMBER     Add a local X seat\n"
00108                         "  add-seat TYPE [NAME=VALUE...]       Add a dynamic seat\n");
00109             return EXIT_SUCCESS;
00110         }
00111         else if (strcmp (arg, "-v") == 0 || strcmp (arg, "--version") == 0)
00112         {
00113             /* NOTE: Is not translated so can be easily parsed */
00114             g_printerr ("lightdm %s\n", VERSION);
00115             return EXIT_SUCCESS;
00116         }
00117         else if (strcmp (arg, "--session-bus") == 0)
00118             bus_type = G_BUS_TYPE_SESSION;
00119         else
00120         {
00121             g_printerr ("Unknown option %s\n", arg);
00122             usage ();
00123             return EXIT_FAILURE;
00124         }
00125     }
00126 
00127     if (arg_index >= argc)
00128     {
00129         g_printerr ("Missing command\n");
00130         usage ();
00131         return EXIT_FAILURE;
00132     }
00133 
00134     dm_proxy = g_dbus_proxy_new_for_bus_sync (bus_type,
00135                                               G_DBUS_PROXY_FLAGS_NONE,
00136                                               NULL,
00137                                               "org.freedesktop.DisplayManager",
00138                                               "/org/freedesktop/DisplayManager",
00139                                               "org.freedesktop.DisplayManager",
00140                                               NULL,
00141                                               &error);
00142     if (!dm_proxy)
00143     {
00144         g_printerr ("Unable to contact display manager: %s\n", error->message);
00145         return EXIT_FAILURE;
00146     }
00147     g_clear_error (&error);
00148   
00149     if (!g_getenv ("XDG_SEAT_PATH"))
00150     {
00151         g_printerr ("Not running inside a display manager, XDG_SEAT_PATH not defined\n");
00152         return EXIT_FAILURE;
00153     }
00154 
00155     seat_proxy = g_dbus_proxy_new_for_bus_sync (bus_type,
00156                                                 G_DBUS_PROXY_FLAGS_NONE,
00157                                                 NULL,
00158                                                 "org.freedesktop.DisplayManager",
00159                                                 g_getenv ("XDG_SEAT_PATH"),
00160                                                 "org.freedesktop.DisplayManager.Seat",
00161                                                 NULL,
00162                                                 &error);
00163     if (!seat_proxy)
00164     {
00165         g_printerr ("Unable to contact display manager: %s\n", error->message);
00166         return EXIT_FAILURE;
00167     }
00168     g_clear_error (&error);
00169 
00170     command = argv[arg_index];
00171     arg_index++;
00172     n_options = argc - arg_index;
00173     options = argv + arg_index;
00174     if (strcmp (command, "switch-to-greeter") == 0)
00175     {
00176         if (n_options != 0)
00177         {
00178             g_printerr ("Usage switch-to-greeter\n");
00179             usage ();
00180             return EXIT_FAILURE;
00181         }
00182 
00183         if (!g_dbus_proxy_call_sync (seat_proxy,
00184                                      "SwitchToGreeter",
00185                                      g_variant_new ("()"),
00186                                      G_DBUS_CALL_FLAGS_NONE,
00187                                      -1,
00188                                      NULL,
00189                                      &error))
00190         {
00191             g_printerr ("Unable to switch to greeter: %s\n", error->message);
00192             return EXIT_FAILURE;
00193         }
00194         return EXIT_SUCCESS;
00195     }
00196     else if (strcmp (command, "switch-to-user") == 0)
00197     {
00198         gchar *username, *session = "";
00199 
00200         if (n_options > 1)
00201         {
00202             g_printerr ("Usage switch-to-user USERNAME [SESSION]\n");
00203             usage ();
00204             return EXIT_FAILURE;
00205         }
00206 
00207         username = options[0];
00208         if (n_options == 2)
00209             session = options[1];
00210 
00211         if (!g_dbus_proxy_call_sync (seat_proxy,
00212                                      "SwitchToUser",
00213                                      g_variant_new ("(ss)", username, session),
00214                                      G_DBUS_CALL_FLAGS_NONE,
00215                                      -1,
00216                                      NULL,
00217                                      &error))
00218         {
00219             g_printerr ("Unable to switch to user %s: %s\n", username, error->message);
00220             return EXIT_FAILURE;
00221         }
00222         return EXIT_SUCCESS;
00223     }
00224     else if (strcmp (command, "switch-to-guest") == 0)
00225     {
00226         gchar *session = "";
00227 
00228         if (n_options > 1)
00229         {
00230             g_printerr ("Usage switch-to-guest [SESSION]\n");
00231             usage ();
00232             return EXIT_FAILURE;
00233         }
00234 
00235         if (n_options == 1)
00236             session = options[0];
00237 
00238         if (!g_dbus_proxy_call_sync (seat_proxy,
00239                                      "SwitchToGuest",
00240                                      g_variant_new ("(s)", session),
00241                                      G_DBUS_CALL_FLAGS_NONE,
00242                                      -1,
00243                                      NULL,
00244                                      &error))
00245         {
00246             g_printerr ("Unable to switch to guest: %s\n", error->message);
00247             return EXIT_FAILURE;
00248         }
00249         return EXIT_SUCCESS;
00250     }
00251     else if (strcmp (command, "lock") == 0)
00252     {
00253         if (n_options != 0)
00254         {
00255             g_printerr ("Usage lock\n");
00256             usage ();
00257             return EXIT_FAILURE;
00258         }
00259 
00260         if (!g_dbus_proxy_call_sync (seat_proxy,
00261                                      "Lock",
00262                                      g_variant_new ("()"),
00263                                      G_DBUS_CALL_FLAGS_NONE,
00264                                      -1,
00265                                      NULL,
00266                                      &error))
00267         {
00268             g_printerr ("Unable to lock seat: %s\n", error->message);
00269             return EXIT_FAILURE;
00270         }
00271         return EXIT_SUCCESS;
00272     }
00273     else if (strcmp (command, "list-seats") == 0)
00274     {
00275         GVariant *seats, *sessions;
00276         GVariantIter *seat_iter;
00277         gchar *seat_path;
00278 
00279         if (!g_dbus_proxy_get_name_owner (dm_proxy))
00280         {
00281             g_printerr ("Unable to contact display manager\n");
00282             return EXIT_FAILURE;
00283         }
00284         seats = g_dbus_proxy_get_cached_property (dm_proxy, "Seats");
00285 
00286         g_variant_get (seats, "ao", &seat_iter);
00287         while (g_variant_iter_loop (seat_iter, "&o", &seat_path))
00288         {
00289             gchar *seat_name;
00290             GDBusProxy *seat_proxy;
00291             gchar **property_names;
00292             GVariant *sessions;
00293             GVariantIter *session_iter;
00294             gchar *session_path;
00295             gint i;
00296 
00297             if (g_str_has_prefix (seat_path, "/org/freedesktop/DisplayManager/"))
00298                 seat_name = seat_path + strlen ("/org/freedesktop/DisplayManager/");
00299             else
00300                 seat_name = seat_path;
00301 
00302             seat_proxy = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (dm_proxy),
00303                                                 G_DBUS_PROXY_FLAGS_NONE,
00304                                                 NULL,
00305                                                 "org.freedesktop.DisplayManager",
00306                                                 seat_path,
00307                                                 "org.freedesktop.DisplayManager.Seat",
00308                                                 NULL,
00309                                                 NULL);
00310             if (!seat_proxy || !g_dbus_proxy_get_name_owner (seat_proxy))
00311                 continue;
00312 
00313             g_print ("%s\n", seat_name);
00314             property_names = g_dbus_proxy_get_cached_property_names (seat_proxy);
00315             for (i = 0; property_names[i]; i++)
00316             {
00317                 GVariant *value;
00318 
00319                 if (strcmp (property_names[i], "Sessions") == 0)
00320                     continue;
00321 
00322                 value = g_dbus_proxy_get_cached_property (seat_proxy, property_names[i]);
00323                 g_print ("  %s=%s\n", property_names[i], g_variant_print (value, FALSE));
00324                 g_variant_unref (value);
00325             }
00326 
00327             sessions = g_dbus_proxy_get_cached_property (seat_proxy, "Sessions");
00328             if (!sessions)
00329                 continue;
00330 
00331             g_variant_get (sessions, "ao", &session_iter);
00332             while (g_variant_iter_loop (session_iter, "&o", &session_path))
00333             {
00334                 GDBusProxy *session_proxy;
00335                 gchar *session_name;
00336 
00337                 if (g_str_has_prefix (session_path, "/org/freedesktop/DisplayManager/"))
00338                     session_name = session_path + strlen ("/org/freedesktop/DisplayManager/");
00339                 else
00340                     session_name = session_path;
00341 
00342                 session_proxy = g_dbus_proxy_new_sync (g_dbus_proxy_get_connection (dm_proxy),
00343                                                        G_DBUS_PROXY_FLAGS_NONE,
00344                                                        NULL,
00345                                                        "org.freedesktop.DisplayManager",
00346                                                        session_path,
00347                                                        "org.freedesktop.DisplayManager.Session",
00348                                                        NULL,
00349                                                        NULL);
00350                 if (!session_proxy || !g_dbus_proxy_get_name_owner (session_proxy))
00351                     continue;
00352 
00353                 g_print ("  %s\n", session_name);
00354                 property_names = g_dbus_proxy_get_cached_property_names (session_proxy);
00355                 for (i = 0; property_names[i]; i++)
00356                 {
00357                     GVariant *value;
00358 
00359                     if (strcmp (property_names[i], "Seat") == 0)
00360                         continue;
00361 
00362                     value = g_dbus_proxy_get_cached_property (session_proxy, property_names[i]);
00363                     g_print ("    %s=%s\n", property_names[i], g_variant_print (value, FALSE));
00364                     g_variant_unref (value);
00365                 }
00366 
00367                 g_object_unref (session_proxy);
00368             }
00369             g_variant_iter_free (session_iter);
00370 
00371             g_object_unref (seat_proxy);
00372         }
00373         g_variant_iter_free (seat_iter);
00374 
00375         return EXIT_SUCCESS;
00376     }
00377     else if (strcmp (command, "add-nested-seat") == 0)
00378     {
00379         gchar *path, *xephyr_command, **xephyr_argv;
00380         GMainLoop *loop;
00381 
00382         path = g_find_program_in_path ("Xephyr");
00383         if (!path)
00384         {
00385             g_printerr ("Unable to find Xephyr, please install it\n");
00386             return EXIT_FAILURE;
00387         }
00388 
00389         /* Get a unique display number.  It's racy, but the only reliable method to get one */
00390         xephyr_display_number = 0;
00391         while (TRUE)
00392         {
00393             gchar *lock_name;
00394             gboolean has_lock;
00395 
00396             lock_name = g_strdup_printf ("/tmp/.X%d-lock", xephyr_display_number);
00397             has_lock = g_file_test (lock_name, G_FILE_TEST_EXISTS);
00398             g_free (lock_name);
00399           
00400             if (has_lock)
00401                 xephyr_display_number++;
00402             else
00403                 break;
00404         }
00405 
00406         /* Wait for signal from Xephyr is ready */
00407         signal (SIGUSR1, xephyr_signal_cb);
00408 
00409         xephyr_command = g_strdup_printf ("Xephyr :%d", xephyr_display_number);
00410         if (!g_shell_parse_argv (xephyr_command, NULL, &xephyr_argv, &error) ||
00411             !g_spawn_async (NULL, xephyr_argv, NULL,
00412                             G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
00413                             xephyr_setup_cb, NULL,
00414                             &xephyr_pid, &error))
00415         {
00416             g_printerr ("Error running Xephyr: %s\n", error->message);
00417             exit (EXIT_FAILURE);
00418         }
00419         g_clear_error (&error);
00420 
00421         /* Block until ready */
00422         loop = g_main_loop_new (NULL, FALSE);
00423         g_main_loop_run (loop);
00424     }
00425     else if (strcmp (command, "add-local-x-seat") == 0)
00426     {
00427         GVariant *result;
00428         gint display_number;
00429         const gchar *path;
00430 
00431         if (n_options != 1)
00432         {
00433             g_printerr ("Usage add-seat DISPLAY_NUMBER\n");
00434             usage ();
00435             return EXIT_FAILURE;
00436         }
00437 
00438         display_number = atoi (options[0]);
00439 
00440         result = g_dbus_proxy_call_sync (dm_proxy,
00441                                          "AddLocalXSeat",
00442                                          g_variant_new ("(i)", display_number),
00443                                          G_DBUS_CALL_FLAGS_NONE,
00444                                          -1,
00445                                          NULL,
00446                                          &error);
00447         if (!result)
00448         {
00449             g_printerr ("Unable to add local X seat: %s\n", error->message);
00450             return EXIT_FAILURE;
00451         }
00452 
00453         if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(o)")))
00454         {
00455             g_printerr ("Unexpected response to AddLocalXSeat: %s\n", g_variant_get_type_string (result));
00456             return EXIT_FAILURE;
00457         }
00458 
00459         g_variant_get (result, "(&o)", &path);
00460         g_print ("%s\n", path);
00461 
00462         return EXIT_SUCCESS; 
00463     }
00464     else if (strcmp (command, "add-seat") == 0)
00465     {
00466         GVariant *result;
00467         gchar *type, *path;
00468         GVariantBuilder *properties;
00469         gint i;
00470 
00471         if (n_options < 1)
00472         {
00473             g_printerr ("Usage add-seat TYPE [NAME=VALUE...]\n");
00474             usage ();
00475             return EXIT_FAILURE;
00476         }
00477 
00478         type = options[0];
00479         properties = g_variant_builder_new (G_VARIANT_TYPE ("a(ss)"));
00480       
00481         for (i = 1; i < n_options; i++)
00482         {
00483             gchar *property, *name, *value;
00484 
00485             property = g_strdup (options[i]);
00486             name = property;
00487             value = strchr (property, '=');
00488             if (value)
00489             {
00490                 *value = '\0';
00491                 value++;
00492             }
00493             else
00494                value = "";
00495 
00496             g_variant_builder_add_value (properties, g_variant_new ("(ss)", name, value));
00497             g_free (property);
00498         }
00499       
00500         result = g_dbus_proxy_call_sync (dm_proxy,
00501                                          "AddSeat",
00502                                          g_variant_new ("(sa(ss))", type, properties),
00503                                          G_DBUS_CALL_FLAGS_NONE,
00504                                          -1,
00505                                          NULL,
00506                                          &error);
00507         g_variant_builder_unref (properties);
00508         if (!result)
00509         {
00510             g_printerr ("Unable to add seat: %s\n", error->message);
00511             return EXIT_FAILURE;
00512         }
00513 
00514         if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(o)")))
00515         {
00516             g_printerr ("Unexpected response to AddSeat: %s\n", g_variant_get_type_string (result));
00517             return EXIT_FAILURE;
00518         }
00519 
00520         g_variant_get (result, "(&o)", &path);
00521         g_print ("%s\n", path);
00522 
00523         return EXIT_SUCCESS;
00524     }
00525 
00526     g_printerr ("Unknown command %s\n", command);
00527     usage ();
00528     return EXIT_FAILURE;
00529 }