2 * Copyright (C) 2010-2011 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
5 * This program is free software: you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option) any later
8 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
18 #include <glib/gi18n.h>
23 #include "configuration.h"
24 #include "display-manager.h"
25 #include "xdmcp-server.h"
26 #include "vnc-server.h"
27 #include "seat-xdmcp-session.h"
28 #include "seat-xvnc.h"
30 #include "pam-session.h"
33 static gchar *config_path = NULL;
34 static GMainLoop *loop = NULL;
35 static GTimer *log_timer;
36 static int log_fd = -1;
37 static gboolean debug = FALSE;
39 static DisplayManager *display_manager = NULL;
40 static XDMCPServer *xdmcp_server = NULL;
41 static VNCServer *vnc_server = NULL;
42 static GDBusConnection *bus = NULL;
44 static GDBusNodeInfo *seat_info;
45 static GHashTable *seat_bus_entries;
46 static guint seat_index = 0;
47 static GDBusNodeInfo *session_info;
48 static GHashTable *session_bus_entries;
49 static guint session_index = 0;
50 static gint exit_code = EXIT_SUCCESS;
56 gchar *removed_signal;
60 #define LIGHTDM_BUS_NAME "org.freedesktop.DisplayManager"
63 log_cb (const gchar *log_domain, GLogLevelFlags log_level,
64 const gchar *message, gpointer data)
66 /* Log everything to a file */
73 switch (log_level & G_LOG_LEVEL_MASK)
75 case G_LOG_LEVEL_ERROR:
78 case G_LOG_LEVEL_CRITICAL:
81 case G_LOG_LEVEL_WARNING:
84 case G_LOG_LEVEL_MESSAGE:
87 case G_LOG_LEVEL_INFO:
90 case G_LOG_LEVEL_DEBUG:
98 text = g_strdup_printf ("[%+.2fs] %s %s\n", g_timer_elapsed (log_timer, NULL), prefix, message);
99 n_written = write (log_fd, text, strlen (text));
101 ; /* Check result so compiler doesn't warn about it */
105 /* Only show debug if requested */
106 if (log_level & G_LOG_LEVEL_DEBUG) {
108 g_log_default_handler (log_domain, log_level, message, data);
111 g_log_default_handler (log_domain, log_level, message, data);
117 gchar *log_dir, *path;
119 log_timer = g_timer_new ();
122 log_dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
123 path = g_build_filename (log_dir, "lightdm.log", NULL);
126 log_fd = open (path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
127 g_log_set_default_handler (log_cb, NULL);
129 g_debug ("Logging to %s", path);
134 signal_cb (Process *process, int signum)
136 g_debug ("Caught %s signal, shutting down", g_strsignal (signum));
137 display_manager_stop (display_manager);
138 // FIXME: Stop XDMCP server
142 display_manager_stopped_cb (DisplayManager *display_manager)
144 g_debug ("Stopping Light Display Manager");
149 handle_display_manager_get_property (GDBusConnection *connection,
151 const gchar *object_path,
152 const gchar *interface_name,
153 const gchar *property_name,
157 GVariant *result = NULL;
159 if (g_strcmp0 (property_name, "Seats") == 0)
161 GVariantBuilder *builder;
165 builder = g_variant_builder_new (G_VARIANT_TYPE ("ao"));
166 g_hash_table_iter_init (&iter, seat_bus_entries);
167 while (g_hash_table_iter_next (&iter, NULL, &value))
169 BusEntry *entry = value;
170 g_variant_builder_add_value (builder, g_variant_new_object_path (entry->path));
172 result = g_variant_builder_end (builder);
173 g_variant_builder_unref (builder);
175 else if (g_strcmp0 (property_name, "Sessions") == 0)
177 GVariantBuilder *builder;
181 builder = g_variant_builder_new (G_VARIANT_TYPE ("ao"));
182 g_hash_table_iter_init (&iter, session_bus_entries);
183 while (g_hash_table_iter_next (&iter, NULL, &value))
185 BusEntry *entry = value;
186 g_variant_builder_add_value (builder, g_variant_new_object_path (entry->path));
188 result = g_variant_builder_end (builder);
189 g_variant_builder_unref (builder);
196 set_seat_properties (Seat *seat, const gchar *config_section)
201 keys = config_get_keys (config_get_instance (), "SeatDefaults");
202 for (i = 0; keys[i]; i++)
204 gchar *value = config_get_string (config_get_instance (), "SeatDefaults", keys[i]);
205 seat_set_property (seat, keys[i], value);
212 keys = config_get_keys (config_get_instance (), config_section);
213 for (i = 0; keys[i]; i++)
215 gchar *value = config_get_string (config_get_instance (), config_section, keys[i]);
216 seat_set_property (seat, keys[i], value);
224 handle_display_manager_call (GDBusConnection *connection,
226 const gchar *object_path,
227 const gchar *interface_name,
228 const gchar *method_name,
229 GVariant *parameters,
230 GDBusMethodInvocation *invocation,
233 if (g_strcmp0 (method_name, "AddSeat") == 0)
236 GVariantIter *property_iter;
240 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sa(ss))")))
243 g_variant_get (parameters, "(&sa(ss))", &type, &property_iter);
245 g_debug ("Adding seat of type %s", type);
247 seat = seat_new (type);
250 set_seat_properties (seat, NULL);
251 while (g_variant_iter_loop (property_iter, "(&s&s)", &name, &value))
252 seat_set_property (seat, name, value);
254 g_variant_iter_free (property_iter);
258 // FIXME: Need to make proper error
259 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Unable to create seat of type %s", type);
263 if (display_manager_add_seat (display_manager, seat))
267 entry = g_hash_table_lookup (seat_bus_entries, seat);
268 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", entry->path));
270 else// FIXME: Need to make proper error
271 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Failed to start seat");
273 else if (g_strcmp0 (method_name, "AddLocalXSeat") == 0)
278 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(i)")))
281 g_variant_get (parameters, "(i)", &display_number);
283 g_debug ("Adding local X seat :%d", display_number);
285 seat = seat_new ("xremote");
288 gchar *display_number_string;
290 set_seat_properties (seat, NULL);
291 display_number_string = g_strdup_printf ("%d", display_number);
292 seat_set_property (seat, "xserver-display-number", display_number_string);
293 g_free (display_number_string);
298 // FIXME: Need to make proper error
299 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Unable to create local X seat");
303 if (display_manager_add_seat (display_manager, seat))
307 entry = g_hash_table_lookup (seat_bus_entries, seat);
308 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", entry->path));
310 else// FIXME: Need to make proper error
311 g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Failed to start seat");
316 handle_seat_get_property (GDBusConnection *connection,
318 const gchar *object_path,
319 const gchar *interface_name,
320 const gchar *property_name,
324 Seat *seat = user_data;
325 GVariant *result = NULL;
327 if (g_strcmp0 (property_name, "CanSwitch") == 0)
328 result = g_variant_new_boolean (seat_get_can_switch (seat));
329 if (g_strcmp0 (property_name, "HasGuestAccount") == 0)
330 result = g_variant_new_boolean (seat_get_allow_guest (seat));
331 else if (g_strcmp0 (property_name, "Sessions") == 0)
333 GVariantBuilder *builder;
336 builder = g_variant_builder_new (G_VARIANT_TYPE ("ao"));
337 for (link = seat_get_displays (seat); link; link = link->next)
339 Display *display = link->data;
341 entry = g_hash_table_lookup (session_bus_entries, display_get_session (display));
343 g_variant_builder_add_value (builder, g_variant_new_object_path (entry->path));
345 result = g_variant_builder_end (builder);
346 g_variant_builder_unref (builder);
353 handle_seat_call (GDBusConnection *connection,
355 const gchar *object_path,
356 const gchar *interface_name,
357 const gchar *method_name,
358 GVariant *parameters,
359 GDBusMethodInvocation *invocation,
362 Seat *seat = user_data;
364 if (g_strcmp0 (method_name, "SwitchToGreeter") == 0)
366 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("()")))
369 seat_switch_to_greeter (seat);
370 g_dbus_method_invocation_return_value (invocation, NULL);
372 else if (g_strcmp0 (method_name, "SwitchToUser") == 0)
374 const gchar *username, *session_name;
376 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(ss)")))
379 g_variant_get (parameters, "(&s&s)", &username, &session_name);
380 if (strcmp (session_name, "") == 0)
383 seat_switch_to_user (seat, username, session_name);
384 g_dbus_method_invocation_return_value (invocation, NULL);
386 else if (g_strcmp0 (method_name, "SwitchToGuest") == 0)
388 const gchar *session_name;
390 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(s)")))
393 g_variant_get (parameters, "(&s)", &session_name);
394 if (strcmp (session_name, "") == 0)
397 seat_switch_to_guest (seat, session_name);
398 g_dbus_method_invocation_return_value (invocation, NULL);
403 handle_session_get_property (GDBusConnection *connection,
405 const gchar *object_path,
406 const gchar *interface_name,
407 const gchar *property_name,
411 Session *session = user_data;
414 entry = g_hash_table_lookup (session_bus_entries, session);
415 if (g_strcmp0 (property_name, "Seat") == 0)
416 return g_variant_new_object_path (entry ? entry->parent_path : "");
417 else if (g_strcmp0 (property_name, "UserName") == 0)
418 return g_variant_new_string (user_get_name (session_get_user (session)));
424 handle_session_call (GDBusConnection *connection,
426 const gchar *object_path,
427 const gchar *interface_name,
428 const gchar *method_name,
429 GVariant *parameters,
430 GDBusMethodInvocation *invocation,
436 bus_entry_new (const gchar *path, const gchar *parent_path, const gchar *removed_signal)
440 entry = g_malloc0 (sizeof (BusEntry));
441 entry->path = g_strdup (path);
442 entry->parent_path = g_strdup (parent_path);
443 entry->removed_signal = g_strdup (removed_signal);
449 bus_entry_free (gpointer data)
451 BusEntry *entry = data;
453 g_dbus_connection_unregister_object (bus, entry->bus_id);
455 g_dbus_connection_emit_signal (bus,
457 "/org/freedesktop/DisplayManager",
458 "org.freedesktop.DisplayManager",
459 entry->removed_signal,
460 g_variant_new ("(o)", entry->path),
463 g_free (entry->path);
464 g_free (entry->parent_path);
465 g_free (entry->removed_signal);
470 start_session_cb (Display *display, Seat *seat)
473 BusEntry *seat_entry;
476 session = display_get_session (display);
478 seat_entry = g_hash_table_lookup (seat_bus_entries, seat);
479 session_set_env (session, "XDG_SEAT_PATH", seat_entry->path);
481 path = g_strdup_printf ("/org/freedesktop/DisplayManager/Session%d", session_index);
483 session_set_env (session, "XDG_SESSION_PATH", path);
490 session_stopped_cb (Session *session, Seat *seat)
492 g_hash_table_remove (session_bus_entries, session);
496 session_started_cb (Display *display, Seat *seat)
498 static const GDBusInterfaceVTable session_vtable =
501 handle_session_get_property
504 BusEntry *seat_entry, *entry;
506 session = display_get_session (display);
508 g_signal_connect (session, "stopped", G_CALLBACK (session_stopped_cb), seat);
510 seat_entry = g_hash_table_lookup (seat_bus_entries, seat);
511 entry = bus_entry_new (session_get_env (session, "XDG_SESSION_PATH"), seat_entry ? seat_entry->path : NULL, "SessionRemoved");
512 g_hash_table_insert (session_bus_entries, g_object_ref (session), entry);
514 g_debug ("Registering session with bus path %s", entry->path);
516 entry->bus_id = g_dbus_connection_register_object (bus,
518 session_info->interfaces[0],
520 g_object_ref (session), g_object_unref,
522 g_dbus_connection_emit_signal (bus,
524 "/org/freedesktop/DisplayManager",
525 "org.freedesktop.DisplayManager",
527 g_variant_new ("(o)", entry->path),
534 display_added_cb (Seat *seat, Display *display)
536 g_signal_connect (display, "start-session", G_CALLBACK (start_session_cb), seat);
537 g_signal_connect_after (display, "start-session", G_CALLBACK (session_started_cb), seat);
541 seat_added_cb (DisplayManager *display_manager, Seat *seat)
543 static const GDBusInterfaceVTable seat_vtable =
546 handle_seat_get_property
552 g_signal_connect (seat, "display-added", G_CALLBACK (display_added_cb), NULL);
553 for (link = seat_get_displays (seat); link; link = link->next)
554 display_added_cb (seat, (Display *) link->data);
556 path = g_strdup_printf ("/org/freedesktop/DisplayManager/Seat%d", seat_index);
559 entry = bus_entry_new (path, NULL, "SeatRemoved");
561 g_hash_table_insert (seat_bus_entries, g_object_ref (seat), entry);
563 g_debug ("Registering seat with bus path %s", entry->path);
565 entry->bus_id = g_dbus_connection_register_object (bus,
567 seat_info->interfaces[0],
569 g_object_ref (seat), g_object_unref,
571 g_dbus_connection_emit_signal (bus,
573 "/org/freedesktop/DisplayManager",
574 "org.freedesktop.DisplayManager",
576 g_variant_new ("(o)", entry->path),
581 seat_removed_cb (DisplayManager *display_manager, Seat *seat)
583 g_hash_table_remove (seat_bus_entries, seat);
585 if (seat_get_boolean_property (seat, "exit-on-failure"))
587 g_debug ("Stopping lightdm, required seat has stopped");
588 exit_code = EXIT_FAILURE;
589 display_manager_stop (display_manager);
594 bus_acquired_cb (GDBusConnection *connection,
598 const gchar *display_manager_interface =
600 " <interface name='org.freedesktop.DisplayManager'>"
601 " <property name='Seats' type='ao' access='read'/>"
602 " <property name='Sessions' type='ao' access='read'/>"
603 " <method name='AddSeat'>"
604 " <arg name='type' direction='in' type='s'/>"
605 " <arg name='properties' direction='in' type='a(ss)'/>"
606 " <arg name='seat' direction='out' type='o'/>"
608 " <method name='AddLocalXSeat'>"
609 " <arg name='display-number' direction='in' type='i'/>"
610 " <arg name='seat' direction='out' type='o'/>"
612 " <signal name='SeatAdded'>"
613 " <arg name='seat' type='o'/>"
615 " <signal name='SeatRemoved'>"
616 " <arg name='seat' type='o'/>"
618 " <signal name='SessionAdded'>"
619 " <arg name='session' type='o'/>"
621 " <signal name='SessionRemoved'>"
622 " <arg name='session' type='o'/>"
626 static const GDBusInterfaceVTable display_manager_vtable =
628 handle_display_manager_call,
629 handle_display_manager_get_property
631 const gchar *seat_interface =
633 " <interface name='org.freedesktop.DisplayManager.Seat'>"
634 " <property name='CanSwitch' type='b' access='read'/>"
635 " <property name='HasGuestAccount' type='b' access='read'/>"
636 " <property name='Sessions' type='ao' access='read'/>"
637 " <method name='SwitchToGreeter'/>"
638 " <method name='SwitchToUser'>"
639 " <arg name='username' direction='in' type='s'/>"
640 " <arg name='session-name' direction='in' type='s'/>"
642 " <method name='SwitchToGuest'>"
643 " <arg name='session-name' direction='in' type='s'/>"
647 const gchar *session_interface =
649 " <interface name='org.freedesktop.DisplayManager.Session'>"
650 " <property name='Seat' type='o' access='read'/>"
651 " <property name='UserName' type='s' access='read'/>"
654 GDBusNodeInfo *display_manager_info;
657 g_debug ("Acquired bus name");
661 display_manager_info = g_dbus_node_info_new_for_xml (display_manager_interface, NULL);
662 g_assert (display_manager_info != NULL);
663 seat_info = g_dbus_node_info_new_for_xml (seat_interface, NULL);
664 g_assert (seat_info != NULL);
665 session_info = g_dbus_node_info_new_for_xml (session_interface, NULL);
666 g_assert (session_info != NULL);
668 bus_id = g_dbus_connection_register_object (connection,
669 "/org/freedesktop/DisplayManager",
670 display_manager_info->interfaces[0],
671 &display_manager_vtable,
675 seat_bus_entries = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, bus_entry_free);
676 session_bus_entries = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, bus_entry_free);
678 g_signal_connect (display_manager, "seat-added", G_CALLBACK (seat_added_cb), NULL);
679 g_signal_connect (display_manager, "seat-removed", G_CALLBACK (seat_removed_cb), NULL);
680 for (link = display_manager_get_seats (display_manager); link; link = link->next)
681 seat_added_cb (display_manager, (Seat *) link->data);
685 name_lost_cb (GDBusConnection *connection,
690 g_printerr ("Failed to use bus name " LIGHTDM_BUS_NAME ", do you have appropriate permissions?\n");
692 g_printerr ("Failed to get D-Bus connection\n");
698 path_make_absolute (gchar *path)
700 gchar *cwd, *abs_path;
705 if (g_path_is_absolute (path))
708 cwd = g_get_current_dir ();
709 abs_path = g_build_filename (cwd, path, NULL);
716 xdmcp_session_cb (XDMCPServer *server, XDMCPSession *session)
718 SeatXDMCPSession *seat;
721 seat = seat_xdmcp_session_new (session);
722 set_seat_properties (SEAT (seat), NULL);
723 result = display_manager_add_seat (display_manager, SEAT (seat));
724 g_object_unref (seat);
730 vnc_connection_cb (VNCServer *server, GSocket *connection)
734 seat = seat_xvnc_new (connection);
735 set_seat_properties (SEAT (seat), NULL);
736 display_manager_add_seat (display_manager, SEAT (seat));
737 g_object_unref (seat);
741 main (int argc, char **argv)
744 GOptionContext *option_context;
747 gboolean explicit_config = FALSE;
748 gboolean test_mode = FALSE;
749 gchar *pid_path = "/var/run/lightdm.pid";
750 gchar *xsessions_dir = NULL;
751 gchar *xgreeters_dir = NULL;
752 gchar *greeter_session = NULL;
753 gchar *user_session = NULL;
754 gchar *session_wrapper = NULL;
756 gchar *log_dir = NULL;
757 gchar *run_dir = NULL;
758 gchar *cache_dir = NULL;
759 gchar *default_log_dir = g_strdup (LOG_DIR);
760 gchar *default_run_dir = g_strdup (RUN_DIR);
761 gchar *default_cache_dir = g_strdup (CACHE_DIR);
762 gchar *minimum_vt = NULL;
763 gchar *minimum_display_number = NULL;
764 gboolean show_version = FALSE;
765 GOptionEntry options[] =
767 { "config", 'c', 0, G_OPTION_ARG_STRING, &config_path,
768 /* Help string for command line --config flag */
769 N_("Use configuration file"), "FILE" },
770 { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug,
771 /* Help string for command line --debug flag */
772 N_("Print debugging messages"), NULL },
773 { "test-mode", 0, 0, G_OPTION_ARG_NONE, &test_mode,
774 /* Help string for command line --test-mode flag */
775 N_("Run as unprivileged user, skipping things that require root access"), NULL },
776 { "pid-file", 0, 0, G_OPTION_ARG_STRING, &pid_path,
777 /* Help string for command line --pid-file flag */
778 N_("File to write PID into"), "FILE" },
779 { "greeter-session", 0, 0, G_OPTION_ARG_STRING, &greeter_session,
780 /* Help string for command line --greeter-session flag */
781 N_("Greeter session"), "SESSION" },
782 { "user-session", 0, 0, G_OPTION_ARG_STRING, &user_session,
783 /* Help string for command line --user-session flag */
784 N_("User session"), "SESSION" },
785 { "session-wrapper", 0, 0, G_OPTION_ARG_STRING, &session_wrapper,
786 /* Help string for command line --session-wrapper flag */
787 N_("Session wrapper"), "SESSION" },
788 { "minimum-vt", 0, 0, G_OPTION_ARG_STRING, &minimum_vt,
789 /* Help string for command line --minimum-vt flag */
790 N_("Minimum VT to use for X servers"), "NUMBER" },
791 { "minimum-display-number", 0, 0, G_OPTION_ARG_STRING, &minimum_display_number,
792 /* Help string for command line --minimum-display-number flag */
793 N_("Minimum display number to use for X servers"), "NUMBER" },
794 { "xsessions-dir", 0, 0, G_OPTION_ARG_STRING, &xsessions_dir,
795 /* Help string for command line --xsessions-dir flag */
796 N_("Directory to load X sessions from"), "DIRECTORY" },
797 { "xgreeters-dir", 0, 0, G_OPTION_ARG_STRING, &xgreeters_dir,
798 /* Help string for command line --xgreeters-dir flag */
799 N_("Directory to load X greeters from"), "DIRECTORY" },
800 { "log-dir", 0, 0, G_OPTION_ARG_STRING, &log_dir,
801 /* Help string for command line --log-dir flag */
802 N_("Directory to write logs to"), "DIRECTORY" },
803 { "run-dir", 0, 0, G_OPTION_ARG_STRING, &run_dir,
804 /* Help string for command line --run-dir flag */
805 N_("Directory to store running state"), "DIRECTORY" },
806 { "cache-dir", 0, 0, G_OPTION_ARG_STRING, &cache_dir,
807 /* Help string for command line --cache-dir flag */
808 N_("Directory to cached information"), "DIRECTORY" },
809 { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version,
810 /* Help string for command line --version flag */
811 N_("Show release version"), NULL },
814 GError *error = NULL;
816 g_thread_init (NULL);
819 g_signal_connect (process_get_current (), "got-signal", G_CALLBACK (signal_cb), NULL);
821 option_context = g_option_context_new (/* Arguments and description for --help test */
822 _("- Display Manager"));
823 g_option_context_add_main_entries (option_context, options, GETTEXT_PACKAGE);
824 if (!g_option_context_parse (option_context, &argc, &argv, &error))
827 fprintf (stderr, "%s\n", error->message);
828 fprintf (stderr, /* Text printed out when an unknown command-line argument provided */
829 _("Run '%s --help' to see a full list of available command line options."), argv[0]);
830 fprintf (stderr, "\n");
833 g_clear_error (&error);
837 /* NOTE: Is not translated so can be easily parsed */
838 g_printerr ("lightdm %s\n", VERSION);
844 config_dir = g_path_get_basename (config_path);
845 config_dir = path_make_absolute (config_dir);
846 explicit_config = TRUE;
850 config_dir = g_strdup (CONFIG_DIR);
851 config_path = g_build_filename (config_dir, "lightdm.conf", NULL);
853 config_set_string (config_get_instance (), "LightDM", "config-directory", config_dir);
856 if (!test_mode && getuid () != 0)
858 g_printerr ("Only root can run Light Display Manager. To run as a regular user for testing run with the --test-mode flag.\n");
862 /* If running inside an X server use Xephyr for display */
863 if (getenv ("DISPLAY") && getuid () != 0)
867 xserver_path = g_find_program_in_path ("Xephyr");
870 g_printerr ("Running inside an X server requires Xephyr to be installed but it cannot be found. Please install it or update your PATH environment variable.\n");
873 g_free (xserver_path);
876 /* Make sure the system binary directory (where the greeters are installed) is in the path */
879 const gchar *path = g_getenv ("PATH");
883 new_path = g_strdup_printf ("%s:%s", path, SBIN_DIR);
885 new_path = g_strdup (SBIN_DIR);
886 g_setenv ("PATH", new_path, TRUE);
891 pid_file = fopen (pid_path, "w");
894 fprintf (pid_file, "%d\n", getpid ());
898 /* Always use absolute directories as child processes may run from different locations */
899 xsessions_dir = path_make_absolute (xsessions_dir);
900 xgreeters_dir = path_make_absolute (xgreeters_dir);
902 /* If not running as root write output to directories we control */
905 g_free (default_log_dir);
906 default_log_dir = g_build_filename (g_get_user_cache_dir (), "lightdm", "log", NULL);
907 g_free (default_run_dir);
908 default_run_dir = g_build_filename (g_get_user_cache_dir (), "lightdm", "run", NULL);
909 g_free (default_cache_dir);
910 default_cache_dir = g_build_filename (g_get_user_cache_dir (), "lightdm", "cache", NULL);
913 /* Load config file */
914 if (!config_load_from_file (config_get_instance (), config_path, &error))
918 is_empty = error && g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
920 if (explicit_config || !is_empty)
923 g_printerr ("Failed to load configuration from %s: %s\n", config_path, error->message);
927 g_clear_error (&error);
929 /* Set default values */
930 if (!config_has_key (config_get_instance (), "LightDM", "start-default-seat"))
931 config_set_boolean (config_get_instance (), "LightDM", "start-default-seat", TRUE);
932 if (!config_has_key (config_get_instance (), "LightDM", "minimum-vt"))
933 config_set_integer (config_get_instance (), "LightDM", "minimum-vt", 7);
934 if (!config_has_key (config_get_instance (), "LightDM", "guest-account-script"))
935 config_set_string (config_get_instance (), "LightDM", "guest-account-script", "guest-account");
936 if (!config_has_key (config_get_instance (), "LightDM", "greeter-user"))
937 config_set_string (config_get_instance (), "LightDM", "greeter-user", GREETER_USER);
938 if (!config_has_key (config_get_instance (), "SeatDefaults", "type"))
939 config_set_string (config_get_instance (), "SeatDefaults", "type", "xlocal");
940 if (!config_has_key (config_get_instance (), "SeatDefaults", "xserver-command"))
941 config_set_string (config_get_instance (), "SeatDefaults", "xserver-command", "X");
942 if (!config_has_key (config_get_instance (), "SeatDefaults", "start-session"))
943 config_set_boolean (config_get_instance (), "SeatDefaults", "start-session", TRUE);
944 if (!config_has_key (config_get_instance (), "SeatDefaults", "allow-guest"))
945 config_set_boolean (config_get_instance (), "SeatDefaults", "allow-guest", TRUE);
946 if (!config_has_key (config_get_instance (), "SeatDefaults", "greeter-session"))
947 config_set_string (config_get_instance (), "SeatDefaults", "greeter-session", GREETER_SESSION);
948 if (!config_has_key (config_get_instance (), "SeatDefaults", "user-session"))
949 config_set_string (config_get_instance (), "SeatDefaults", "user-session", USER_SESSION);
950 if (!config_has_key (config_get_instance (), "SeatDefaults", "session-wrapper"))
951 config_set_string (config_get_instance (), "SeatDefaults", "session-wrapper", "lightdm-session");
952 if (!config_has_key (config_get_instance (), "LightDM", "log-directory"))
953 config_set_string (config_get_instance (), "LightDM", "log-directory", default_log_dir);
954 g_free (default_log_dir);
955 if (!config_has_key (config_get_instance (), "LightDM", "run-directory"))
956 config_set_string (config_get_instance (), "LightDM", "run-directory", default_run_dir);
957 g_free (default_run_dir);
958 if (!config_has_key (config_get_instance (), "LightDM", "cache-directory"))
959 config_set_string (config_get_instance (), "LightDM", "cache-directory", default_cache_dir);
960 g_free (default_cache_dir);
961 if (!config_has_key (config_get_instance (), "LightDM", "xsessions-directory"))
962 config_set_string (config_get_instance (), "LightDM", "xsessions-directory", XSESSIONS_DIR);
963 if (!config_has_key (config_get_instance (), "LightDM", "xgreeters-directory"))
964 config_set_string (config_get_instance (), "LightDM", "xgreeters-directory", XGREETERS_DIR);
966 /* Override defaults */
968 config_set_integer (config_get_instance (), "LightDM", "minimum-vt", atoi (minimum_vt));
970 if (minimum_display_number)
971 config_set_integer (config_get_instance (), "LightDM", "minimum-display-number", atoi (minimum_display_number));
972 g_free (minimum_display_number);
974 config_set_string (config_get_instance (), "LightDM", "log-directory", log_dir);
977 config_set_string (config_get_instance (), "LightDM", "run-directory", run_dir);
980 config_set_string (config_get_instance (), "LightDM", "cache-directory", cache_dir);
983 config_set_string (config_get_instance (), "LightDM", "xsessions-directory", xsessions_dir);
984 g_free (xsessions_dir);
986 config_set_string (config_get_instance (), "LightDM", "xgreeters-directory", xgreeters_dir);
987 g_free (xgreeters_dir);
989 config_set_string (config_get_instance (), "SeatDefaults", "greeter-session", greeter_session);
990 g_free (greeter_session);
992 config_set_string (config_get_instance (), "SeatDefaults", "user-session", user_session);
993 g_free (user_session);
995 config_set_string (config_get_instance (), "SeatDefaults", "session-wrapper", session_wrapper);
996 g_free (session_wrapper);
998 /* Create run and cache directories */
999 g_mkdir_with_parents (config_get_string (config_get_instance (), "LightDM", "log-directory"), S_IRWXU | S_IXGRP | S_IXOTH);
1000 g_mkdir_with_parents (config_get_string (config_get_instance (), "LightDM", "run-directory"), S_IRWXU | S_IXGRP | S_IXOTH);
1001 g_mkdir_with_parents (config_get_string (config_get_instance (), "LightDM", "cache-directory"), S_IRWXU | S_IXGRP | S_IXOTH);
1003 loop = g_main_loop_new (NULL, FALSE);
1007 g_debug ("Starting Light Display Manager %s, UID=%i PID=%i", VERSION, getuid (), getpid ());
1009 g_debug ("Loaded configuration from %s", config_path);
1010 g_free (config_path);
1012 g_debug ("Using D-Bus name %s", LIGHTDM_BUS_NAME);
1013 g_bus_own_name (getuid () == 0 ? G_BUS_TYPE_SYSTEM : G_BUS_TYPE_SESSION,
1015 G_BUS_NAME_OWNER_FLAGS_NONE,
1023 g_debug ("Running in user mode");
1024 if (getenv ("DISPLAY"))
1025 g_debug ("Using Xephyr for X servers");
1027 display_manager = display_manager_new ();
1028 g_signal_connect (display_manager, "stopped", G_CALLBACK (display_manager_stopped_cb), NULL);
1030 /* Load the static display entries */
1031 groups = config_get_groups (config_get_instance ());
1032 for (i = groups; *i; i++)
1034 gchar *config_section = *i;
1038 if (!g_str_has_prefix (config_section, "Seat:"))
1041 g_debug ("Loading seat %s", config_section);
1042 type = config_get_string (config_get_instance (), config_section, "type");
1044 type = config_get_string (config_get_instance (), "SeatDefaults", "type");
1045 seat = seat_new (type);
1049 set_seat_properties (seat, config_section);
1050 display_manager_add_seat (display_manager, seat);
1054 g_warning ("Failed to create seat %s", config_section);
1056 g_strfreev (groups);
1058 /* If no seats start a default one */
1059 if (n_seats == 0 && config_get_boolean (config_get_instance (), "LightDM", "start-default-seat"))
1064 g_debug ("Adding default seat");
1066 type = config_get_string (config_get_instance (), "SeatDefaults", "type");
1067 seat = seat_new (type);
1071 set_seat_properties (seat, NULL);
1072 seat_set_property (seat, "exit-on-failure", "true");
1073 display_manager_add_seat (display_manager, seat);
1076 g_warning ("Failed to create default seat");
1079 display_manager_start (display_manager);
1081 /* Start the XDMCP server */
1082 if (config_get_boolean (config_get_instance (), "XDMCPServer", "enabled"))
1084 gchar *key_name, *key = NULL;
1086 xdmcp_server = xdmcp_server_new ();
1087 if (config_has_key (config_get_instance (), "XDMCPServer", "port"))
1090 port = config_get_integer (config_get_instance (), "XDMCPServer", "port");
1092 xdmcp_server_set_port (xdmcp_server, port);
1094 g_signal_connect (xdmcp_server, "new-session", G_CALLBACK (xdmcp_session_cb), NULL);
1096 key_name = config_get_string (config_get_instance (), "XDMCPServer", "key");
1102 GError *error = NULL;
1104 dir = config_get_string (config_get_instance (), "LightDM", "config-directory");
1105 path = g_build_filename (dir, "keys.conf", NULL);
1108 keys = g_key_file_new ();
1109 result = g_key_file_load_from_file (keys, path, G_KEY_FILE_NONE, &error);
1111 g_debug ("Error getting key %s", error->message);
1112 g_clear_error (&error);
1116 if (g_key_file_has_key (keys, "keyring", key_name, NULL))
1117 key = g_key_file_get_string (keys, "keyring", key_name, NULL);
1119 g_debug ("Key %s not defined", key_name);
1122 g_key_file_free (keys);
1125 xdmcp_server_set_key (xdmcp_server, key);
1129 g_debug ("Starting XDMCP server on UDP/IP port %d", xdmcp_server_get_port (xdmcp_server));
1130 xdmcp_server_start (xdmcp_server);
1133 /* Start the VNC server */
1134 if (config_get_boolean (config_get_instance (), "VNCServer", "enabled"))
1138 path = g_find_program_in_path ("Xvnc");
1141 vnc_server = vnc_server_new ();
1142 if (config_has_key (config_get_instance (), "VNCServer", "port"))
1145 port = config_get_integer (config_get_instance (), "VNCServer", "port");
1147 vnc_server_set_port (vnc_server, port);
1149 g_signal_connect (vnc_server, "new-connection", G_CALLBACK (vnc_connection_cb), NULL);
1151 g_debug ("Starting VNC server on TCP/IP port %d", vnc_server_get_port (vnc_server));
1152 vnc_server_start (vnc_server);
1157 g_warning ("Can't start VNC server, Xvn is not in the path");
1160 g_main_loop_run (loop);
1162 return EXIT_SUCCESS;