2 * Copyright (C) 2010 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
5 * This library is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Lesser General Public License as published by the Free
7 * Software Foundation; either version 3 of the License, or (at your option) any
8 * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the
16 #include <sys/utsname.h>
18 #include <gio/gdesktopappinfo.h>
19 #include <security/pam_appl.h>
20 #include <libxklavier/xklavier.h>
22 #include "lightdm/greeter.h"
23 #include "user-private.h"
24 #include "greeter-protocol.h"
31 PROP_DEFAULT_LANGUAGE,
36 PROP_TIMED_LOGIN_USER,
37 PROP_TIMED_LOGIN_DELAY,
38 PROP_AUTHENTICATION_USER,
39 PROP_IN_AUTHENTICATION,
40 PROP_IS_AUTHENTICATED,
52 AUTHENTICATION_COMPLETE,
60 static guint signals[LAST_SIGNAL] = { 0 };
62 struct _LdmGreeterPrivate
64 GDBusConnection *lightdm_bus;
66 GDBusConnection *system_bus;
68 GDBusProxy *lightdm_proxy;
70 GIOChannel *to_server_channel, *from_server_channel;
78 /* Configuration file */
84 /* File monitor for password file */
85 GFileMonitor *passwd_monitor;
87 /* TRUE if have scanned users */
93 gboolean have_languages;
96 XklEngine *xkl_engine;
97 XklConfigRec *xkl_config;
98 gboolean have_layouts;
102 gboolean have_sessions;
104 gchar *default_session;
106 gchar *authentication_user;
107 gboolean in_authentication;
108 gboolean is_authenticated;
113 gboolean guest_account_supported;
117 G_DEFINE_TYPE (LdmGreeter, ldm_greeter, G_TYPE_OBJECT);
119 #define HEADER_SIZE 8
120 #define MAX_MESSAGE_LENGTH 1024
125 * Create a new greeter.
127 * Return value: the new #LdmGreeter
132 return g_object_new (LDM_TYPE_GREETER, NULL);
136 timed_login_cb (gpointer data)
138 LdmGreeter *greeter = data;
140 greeter->priv->login_timeout = 0;
141 g_signal_emit (G_OBJECT (greeter), signals[TIMED_LOGIN], 0, greeter->priv->timed_user);
153 write_message (LdmGreeter *greeter, guint8 *message, gint message_length)
155 GError *error = NULL;
156 if (g_io_channel_write_chars (greeter->priv->to_server_channel, (gchar *) message, message_length, NULL, NULL) != G_IO_STATUS_NORMAL)
157 g_warning ("Error writing to daemon: %s", error->message);
158 g_clear_error (&error);
159 g_io_channel_flush (greeter->priv->to_server_channel, NULL);
163 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset)
165 if (*offset + 4 >= buffer_length)
167 buffer[*offset] = value >> 24;
168 buffer[*offset+1] = (value >> 16) & 0xFF;
169 buffer[*offset+2] = (value >> 8) & 0xFF;
170 buffer[*offset+3] = value & 0xFF;
175 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset)
177 gint length = strlen (value);
178 write_int (buffer, buffer_length, length, offset);
179 if (*offset + length >= buffer_length)
181 memcpy (buffer + *offset, value, length);
186 read_int (LdmGreeter *greeter, gsize *offset)
190 if (greeter->priv->n_read - *offset < int_length ())
192 g_warning ("Not enough space for int, need %i, got %zi", int_length (), greeter->priv->n_read - *offset);
195 buffer = greeter->priv->read_buffer + *offset;
196 value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
197 *offset += int_length ();
202 read_string (LdmGreeter *greeter, gsize *offset)
207 length = read_int (greeter, offset);
208 if (greeter->priv->n_read - *offset < length)
210 g_warning ("Not enough space for string, need %u, got %zu", length, greeter->priv->n_read - *offset);
211 return g_strdup ("");
214 value = g_malloc (sizeof (gchar) * (length + 1));
215 memcpy (value, greeter->priv->read_buffer + *offset, length);
216 value[length] = '\0';
223 string_length (const gchar *value)
225 return int_length () + strlen (value);
229 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset)
231 write_int (buffer, buffer_length, id, offset);
232 write_int (buffer, buffer_length, length, offset);
235 static guint32 get_packet_length (LdmGreeter *greeter)
238 return read_int (greeter, &offset);
242 handle_prompt_authentication (LdmGreeter *greeter, gsize *offset)
246 n_messages = read_int (greeter, offset);
247 g_debug ("Prompt user with %d message(s)", n_messages);
249 for (i = 0; i < n_messages; i++)
254 msg_style = read_int (greeter, offset);
255 msg = read_string (greeter, offset);
257 // FIXME: Should stop on prompts?
260 case PAM_PROMPT_ECHO_OFF:
261 case PAM_PROMPT_ECHO_ON:
262 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, msg);
265 g_signal_emit (G_OBJECT (greeter), signals[SHOW_ERROR], 0, msg);
268 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, msg);
277 read_packet (LdmGreeter *greeter, gboolean block)
279 gsize n_to_read, n_read;
280 GError *error = NULL;
282 /* Read the header, or the whole packet if we already have that */
283 n_to_read = HEADER_SIZE;
284 if (greeter->priv->n_read >= HEADER_SIZE)
285 n_to_read += get_packet_length (greeter);
290 status = g_io_channel_read_chars (greeter->priv->from_server_channel,
291 (gchar *) greeter->priv->read_buffer + greeter->priv->n_read,
292 n_to_read - greeter->priv->n_read,
295 if (status == G_IO_STATUS_ERROR)
296 g_warning ("Error reading from server: %s", error->message);
297 g_clear_error (&error);
298 if (status != G_IO_STATUS_NORMAL)
301 greeter->priv->n_read += n_read;
302 } while (greeter->priv->n_read < n_to_read && block);
304 /* Stop if haven't got all the data we want */
305 if (greeter->priv->n_read != n_to_read)
308 /* If have header, rerun for content */
309 if (greeter->priv->n_read == HEADER_SIZE)
311 n_to_read = get_packet_length (greeter);
314 greeter->priv->read_buffer = g_realloc (greeter->priv->read_buffer, HEADER_SIZE + n_to_read);
315 return read_packet (greeter, block);
323 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
325 LdmGreeter *greeter = data;
327 guint32 id, return_code;
329 if (!read_packet (greeter, FALSE))
333 id = read_int (greeter, &offset);
334 read_int (greeter, &offset);
337 case GREETER_MESSAGE_CONNECTED:
338 greeter->priv->theme = read_string (greeter, &offset);
339 greeter->priv->default_session = read_string (greeter, &offset);
340 greeter->priv->timed_user = read_string (greeter, &offset);
341 greeter->priv->login_delay = read_int (greeter, &offset);
342 greeter->priv->guest_account_supported = read_int (greeter, &offset) != 0;
343 greeter->priv->greeter_count = read_int (greeter, &offset);
345 g_debug ("Connected theme=%s default-session=%s timed-user=%s login-delay=%d guest-account-supported=%s greeter-count=%d",
346 greeter->priv->theme,
347 greeter->priv->default_session,
348 greeter->priv->timed_user, greeter->priv->login_delay,
349 greeter->priv->guest_account_supported ? "true" : "false",
350 greeter->priv->greeter_count);
352 /* Set timeout for default login */
353 if (greeter->priv->timed_user[0] != '\0' && greeter->priv->login_delay > 0)
355 g_debug ("Logging in as %s in %d seconds", greeter->priv->timed_user, greeter->priv->login_delay);
356 greeter->priv->login_timeout = g_timeout_add (greeter->priv->login_delay * 1000, timed_login_cb, greeter);
358 g_signal_emit (G_OBJECT (greeter), signals[CONNECTED], 0);
360 case GREETER_MESSAGE_QUIT:
361 g_debug ("Got quit request from server");
362 g_signal_emit (G_OBJECT (greeter), signals[QUIT], 0);
364 case GREETER_MESSAGE_PROMPT_AUTHENTICATION:
365 handle_prompt_authentication (greeter, &offset);
367 case GREETER_MESSAGE_END_AUTHENTICATION:
368 return_code = read_int (greeter, &offset);
369 g_debug ("Authentication complete with return code %d", return_code);
370 greeter->priv->is_authenticated = (return_code == 0);
371 if (!greeter->priv->is_authenticated)
373 g_free (greeter->priv->authentication_user);
374 greeter->priv->authentication_user = NULL;
376 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
377 greeter->priv->in_authentication = FALSE;
380 g_warning ("Unknown message from server: %d", id);
384 greeter->priv->n_read = 0;
390 * ldm_greeter_connect_to_server:
391 * @greeter: The greeter to connect
393 * Connects the greeter to the display manager.
395 * Return value: TRUE if successfully connected
398 ldm_greeter_connect_to_server (LdmGreeter *greeter)
400 GError *error = NULL;
401 const gchar *bus_address, *fd;
402 guint8 message[MAX_MESSAGE_LENGTH];
404 GBusType bus_type = G_BUS_TYPE_SYSTEM;
406 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
408 greeter->priv->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
409 if (!greeter->priv->system_bus)
410 g_warning ("Failed to connect to system bus: %s", error->message);
411 g_clear_error (&error);
413 bus_address = getenv ("LDM_BUS");
414 if (bus_address && strcmp (bus_address, "SESSION") == 0)
415 bus_type = G_BUS_TYPE_SESSION;
417 greeter->priv->lightdm_bus = g_bus_get_sync (bus_type, NULL, &error);
418 if (!greeter->priv->lightdm_bus)
419 g_warning ("Failed to connect to LightDM bus: %s", error->message);
420 g_clear_error (&error);
421 if (!greeter->priv->lightdm_bus)
424 fd = getenv ("LDM_TO_SERVER_FD");
427 g_warning ("No LDM_TO_SERVER_FD environment variable");
430 greeter->priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
431 g_io_channel_set_encoding (greeter->priv->to_server_channel, NULL, NULL);
433 fd = getenv ("LDM_FROM_SERVER_FD");
436 g_warning ("No LDM_FROM_SERVER_FD environment variable");
439 greeter->priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
440 g_io_channel_set_encoding (greeter->priv->from_server_channel, NULL, NULL);
441 g_io_add_watch (greeter->priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
443 greeter->priv->lightdm_proxy = g_dbus_proxy_new_sync (greeter->priv->lightdm_bus,
444 G_DBUS_PROXY_FLAGS_NONE,
446 "org.freedesktop.DisplayManager",
447 "/org/freedesktop/DisplayManager",
448 "org.freedesktop.DisplayManager",
451 g_debug ("Connecting to display manager...");
452 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, 0, &offset);
453 write_message (greeter, message, offset);
459 * ldm_greeter_get_hostname:
460 * @greeter: a #LdmGreeter
462 * Return value: The host this greeter is displaying
465 ldm_greeter_get_hostname (LdmGreeter *greeter)
467 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
469 if (!greeter->priv->hostname)
473 greeter->priv->hostname = g_strdup (info.nodename);
476 return greeter->priv->hostname;
480 * ldm_greeter_get_theme:
481 * @greeter: a #LdmGreeter
483 * Return value: The theme this greeter is using
486 ldm_greeter_get_theme (LdmGreeter *greeter)
488 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
489 return greeter->priv->theme;
493 load_theme (LdmGreeter *greeter)
495 GError *error = NULL;
497 if (greeter->priv->theme_file)
500 greeter->priv->theme_file = g_key_file_new ();
501 if (!g_key_file_load_from_file (greeter->priv->theme_file, greeter->priv->theme, G_KEY_FILE_NONE, &error))
502 g_warning ("Failed to read theme file: %s", error->message);
503 g_clear_error (&error);
507 * ldm_greeter_get_string_property:
508 * @greeter: a #LdmGreeter
509 * @name: the name of the property to get
511 * Return value: The value of this property or NULL if it is not defined
514 ldm_greeter_get_string_property (LdmGreeter *greeter, const gchar *name)
516 GError *error = NULL;
519 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
520 g_return_val_if_fail (name != NULL, NULL);
522 load_theme (greeter);
524 result = g_key_file_get_string (greeter->priv->theme_file, "theme", name, &error);
526 g_warning ("Error reading theme property: %s", error->message); // FIXME: Can handle G_KEY_FILE_ERROR_KEY_NOT_FOUND and G_KEY_FILE_ERROR_GROUP_NOT_FOUND
527 g_clear_error (&error);
533 * ldm_greeter_get_integer_property:
534 * @greeter: a #LdmGreeter
535 * @name: the name of the property to get
537 * Return value: The value of this property or 0 if it is not defined
540 ldm_greeter_get_integer_property (LdmGreeter *greeter, const gchar *name)
542 GError *error = NULL;
545 g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
546 g_return_val_if_fail (name != NULL, 0);
548 load_theme (greeter);
550 result = g_key_file_get_integer (greeter->priv->theme_file, "theme", name, &error);
552 g_warning ("Error reading theme property: %s", error->message); // FIXME: Can handle G_KEY_FILE_ERROR_KEY_NOT_FOUND and G_KEY_FILE_ERROR_GROUP_NOT_FOUND
553 g_clear_error (&error);
559 * ldm_greeter_get_boolean_property:
560 * @greeter: a #LdmGreeter
561 * @name: the name of the property to get
563 * Return value: The value of this property or FALSE if it is not defined
566 ldm_greeter_get_boolean_property (LdmGreeter *greeter, const gchar *name)
568 GError *error = NULL;
571 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
572 g_return_val_if_fail (name != NULL, FALSE);
574 load_theme (greeter);
576 result = g_key_file_get_boolean (greeter->priv->theme_file, "theme", name, &error);
578 g_warning ("Error reading theme property: %s", error->message); // FIXME: Can handle G_KEY_FILE_ERROR_KEY_NOT_FOUND and G_KEY_FILE_ERROR_GROUP_NOT_FOUND
579 g_clear_error (&error);
585 get_user_by_name (LdmGreeter *greeter, const gchar *username)
589 for (link = greeter->priv->users; link; link = link->next)
591 LdmUser *user = link->data;
592 if (strcmp (ldm_user_get_name (user), username) == 0)
600 compare_user (gconstpointer a, gconstpointer b)
602 LdmUser *user_a = (LdmUser *) a, *user_b = (LdmUser *) b;
603 return strcmp (ldm_user_get_display_name (user_a), ldm_user_get_display_name (user_b));
607 load_config (LdmGreeter *greeter)
610 const gchar *config_path = NULL;
612 if (greeter->priv->config)
615 result = g_dbus_proxy_get_cached_property (greeter->priv->lightdm_proxy,
619 g_warning ("No ConfigFile property");
623 if (g_variant_is_of_type (result, G_VARIANT_TYPE_STRING))
624 config_path = g_variant_get_string (result, NULL);
626 g_warning ("Invalid type for config file: %s, expected string", g_variant_get_type_string (result));
630 GError *error = NULL;
632 g_debug ("Loading config from %s", config_path);
634 greeter->priv->config = g_key_file_new ();
635 if (!g_key_file_load_from_file (greeter->priv->config, config_path, G_KEY_FILE_NONE, &error))
636 g_warning ("Failed to load configuration from %s: %s", config_path, error->message); // FIXME: Don't make warning on no file, just info
637 g_clear_error (&error);
640 g_variant_unref (result);
644 load_users (LdmGreeter *greeter)
646 gchar **hidden_users, **hidden_shells;
649 GList *users = NULL, *old_users, *new_users = NULL, *changed_users = NULL, *link;
651 load_config (greeter);
653 if (g_key_file_has_key (greeter->priv->config, "UserManager", "minimum-uid", NULL))
654 minimum_uid = g_key_file_get_integer (greeter->priv->config, "UserManager", "minimum-uid", NULL);
658 value = g_key_file_get_string (greeter->priv->config, "UserManager", "hidden-users", NULL);
660 value = g_strdup ("nobody nobody4 noaccess");
661 hidden_users = g_strsplit (value, " ", -1);
664 value = g_key_file_get_string (greeter->priv->config, "UserManager", "hidden-shells", NULL);
666 value = g_strdup ("/bin/false /usr/sbin/nologin");
667 hidden_shells = g_strsplit (value, " ", -1);
674 struct passwd *entry;
677 gchar *real_name, *image_path, *image;
685 /* Ignore system users */
686 if (entry->pw_uid < minimum_uid)
689 /* Ignore users disabled by shell */
692 for (i = 0; hidden_shells[i] && strcmp (entry->pw_shell, hidden_shells[i]) != 0; i++);
693 if (hidden_shells[i])
697 /* Ignore certain users */
698 for (i = 0; hidden_users[i] && strcmp (entry->pw_name, hidden_users[i]) != 0; i++);
702 tokens = g_strsplit (entry->pw_gecos, ",", -1);
703 if (tokens[0] != NULL && tokens[0][0] != '\0')
704 real_name = g_strdup (tokens[0]);
709 image_path = g_build_filename (entry->pw_dir, ".face", NULL);
710 if (!g_file_test (image_path, G_FILE_TEST_EXISTS))
713 image_path = g_build_filename (entry->pw_dir, ".face.icon", NULL);
714 if (!g_file_test (image_path, G_FILE_TEST_EXISTS))
721 image = g_filename_to_uri (image_path, NULL, NULL);
726 user = ldm_user_new (greeter, entry->pw_name, real_name, entry->pw_dir, image, FALSE);
730 /* Update existing users if have them */
731 for (link = greeter->priv->users; link; link = link->next)
733 LdmUser *info = link->data;
734 if (strcmp (ldm_user_get_name (info), ldm_user_get_name (user)) == 0)
736 if (ldm_user_update (info, ldm_user_get_real_name (user), ldm_user_get_home_directory (user), ldm_user_get_image (user), ldm_user_get_logged_in (user)))
737 changed_users = g_list_insert_sorted (changed_users, info, compare_user);
738 g_object_unref (user);
745 /* Only notify once we have loaded the user list */
746 if (greeter->priv->have_users)
747 new_users = g_list_insert_sorted (new_users, user, compare_user);
749 users = g_list_insert_sorted (users, user, compare_user);
751 g_strfreev (hidden_users);
752 g_strfreev (hidden_shells);
755 g_warning ("Failed to read password database: %s", strerror (errno));
759 /* Use new user list */
760 old_users = greeter->priv->users;
761 greeter->priv->users = users;
763 /* Notify of changes */
764 for (link = new_users; link; link = link->next)
766 LdmUser *info = link->data;
767 g_debug ("User %s added", ldm_user_get_name (info));
768 g_signal_emit (greeter, signals[USER_ADDED], 0, info);
770 g_list_free (new_users);
771 for (link = changed_users; link; link = link->next)
773 LdmUser *info = link->data;
774 g_debug ("User %s changed", ldm_user_get_name (info));
775 g_signal_emit (greeter, signals[USER_CHANGED], 0, info);
777 g_list_free (changed_users);
778 for (link = old_users; link; link = link->next)
782 /* See if this user is in the current list */
783 for (new_link = greeter->priv->users; new_link; new_link = new_link->next)
785 if (new_link->data == link->data)
791 LdmUser *info = link->data;
792 g_debug ("User %s removed", ldm_user_get_name (info));
793 g_signal_emit (greeter, signals[USER_REMOVED], 0, info);
794 g_object_unref (info);
797 g_list_free (old_users);
801 passwd_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, LdmGreeter *greeter)
803 if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
805 g_debug ("%s changed, reloading user list", g_file_get_path (file));
806 load_users (greeter);
811 update_users (LdmGreeter *greeter)
814 GError *error = NULL;
816 if (greeter->priv->have_users)
819 load_config (greeter);
821 /* User listing is disabled */
822 if (g_key_file_has_key (greeter->priv->config, "UserManager", "load-users", NULL) &&
823 !g_key_file_get_boolean (greeter->priv->config, "UserManager", "load-users", NULL))
825 greeter->priv->have_users = TRUE;
829 load_users (greeter);
831 /* Watch for changes to user list */
832 passwd_file = g_file_new_for_path ("/etc/passwd");
833 greeter->priv->passwd_monitor = g_file_monitor (passwd_file, G_FILE_MONITOR_NONE, NULL, &error);
834 g_object_unref (passwd_file);
835 if (!greeter->priv->passwd_monitor)
836 g_warning ("Error monitoring /etc/passwd: %s", error->message);
838 g_signal_connect (greeter->priv->passwd_monitor, "changed", G_CALLBACK (passwd_changed_cb), greeter);
839 g_clear_error (&error);
841 greeter->priv->have_users = TRUE;
845 * ldm_greeter_get_num_users:
846 * @greeter: a #LdmGreeter
848 * Return value: The number of users able to log in
851 ldm_greeter_get_num_users (LdmGreeter *greeter)
853 g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
854 update_users (greeter);
855 return g_list_length (greeter->priv->users);
859 * ldm_greeter_get_users:
860 * @greeter: A #LdmGreeter
862 * Get a list of users to present to the user. This list may be a subset of the
863 * available users and may be empty depending on the server configuration.
865 * Return value: (element-type LdmUser): A list of #LdmUser that should be presented to the user.
868 ldm_greeter_get_users (LdmGreeter *greeter)
870 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
871 update_users (greeter);
872 return greeter->priv->users;
876 * ldm_greeter_get_user_by_name:
877 * @greeter: A #LdmGreeter
878 * @username: Name of user to get.
880 * Get infomation about a given user or NULL if this user doesn't exist.
882 * Return value: (allow-none): A #LdmUser entry for the given user.
885 ldm_greeter_get_user_by_name (LdmGreeter *greeter, const gchar *username)
887 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
889 update_users (greeter);
891 return get_user_by_name (greeter, username);
895 update_languages (LdmGreeter *greeter)
897 gchar *stdout_text = NULL, *stderr_text = NULL;
900 GError *error = NULL;
902 if (greeter->priv->have_languages)
905 result = g_spawn_command_line_sync ("locale -a", &stdout_text, &stderr_text, &exit_status, &error);
906 if (!result || exit_status != 0)
907 g_warning ("Failed to get languages, locale -a returned %d: %s", exit_status, error->message);
913 tokens = g_strsplit_set (stdout_text, "\n\r", -1);
914 for (i = 0; tokens[i]; i++)
916 LdmLanguage *language;
919 code = g_strchug (tokens[i]);
923 /* Ignore the non-interesting languages */
924 if (strcmp (code, "C") == 0 || strcmp (code, "POSIX") == 0)
927 language = ldm_language_new (code);
928 greeter->priv->languages = g_list_append (greeter->priv->languages, language);
934 g_clear_error (&error);
935 g_free (stdout_text);
936 g_free (stderr_text);
938 greeter->priv->have_languages = TRUE;
942 * ldm_greeter_get_default_language:
943 * @greeter: A #LdmGreeter
945 * Get the default language.
947 * Return value: The default language.
950 ldm_greeter_get_default_language (LdmGreeter *greeter)
953 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
954 lang = getenv ("LANG");
962 * ldm_greeter_get_languages:
963 * @greeter: A #LdmGreeter
965 * Get a list of languages to present to the user.
967 * Return value: (element-type LdmLanguage): A list of #LdmLanguage that should be presented to the user.
970 ldm_greeter_get_languages (LdmGreeter *greeter)
972 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
973 update_languages (greeter);
974 return greeter->priv->languages;
978 layout_cb (XklConfigRegistry *config,
979 const XklConfigItem *item,
982 LdmGreeter *greeter = data;
985 layout = ldm_layout_new (item->name, item->short_description, item->description);
986 greeter->priv->layouts = g_list_append (greeter->priv->layouts, layout);
990 setup_display (LdmGreeter *greeter)
992 if (!greeter->priv->display)
993 greeter->priv->display = XOpenDisplay (NULL);
997 setup_xkl (LdmGreeter *greeter)
999 setup_display (greeter);
1000 greeter->priv->xkl_engine = xkl_engine_get_instance (greeter->priv->display);
1001 greeter->priv->xkl_config = xkl_config_rec_new ();
1002 if (!xkl_config_rec_get_from_server (greeter->priv->xkl_config, greeter->priv->xkl_engine))
1003 g_warning ("Failed to get Xkl configuration from server");
1004 greeter->priv->layout = g_strdup (greeter->priv->xkl_config->layouts[0]);
1008 * ldm_greeter_get_layouts:
1009 * @greeter: A #LdmGreeter
1011 * Get a list of keyboard layouts to present to the user.
1013 * Return value: (element-type LdmLayout): A list of #LdmLayout that should be presented to the user.
1016 ldm_greeter_get_layouts (LdmGreeter *greeter)
1018 XklConfigRegistry *registry;
1020 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1022 if (greeter->priv->have_layouts)
1023 return greeter->priv->layouts;
1025 setup_xkl (greeter);
1027 registry = xkl_config_registry_get_instance (greeter->priv->xkl_engine);
1028 xkl_config_registry_load (registry, FALSE);
1029 xkl_config_registry_foreach_layout (registry, layout_cb, greeter);
1030 g_object_unref (registry);
1031 greeter->priv->have_layouts = TRUE;
1033 return greeter->priv->layouts;
1037 * ldm_greeter_set_layout:
1038 * @greeter: A #LdmGreeter
1039 * @layout: The layout to use
1041 * Set the layout for this session.
1044 ldm_greeter_set_layout (LdmGreeter *greeter, const gchar *layout)
1046 XklConfigRec *config;
1048 g_return_if_fail (LDM_IS_GREETER (greeter));
1049 g_return_if_fail (layout != NULL);
1051 g_debug ("Setting keyboard layout to %s", layout);
1053 setup_xkl (greeter);
1055 config = xkl_config_rec_new ();
1056 config->layouts = g_malloc (sizeof (gchar *) * 2);
1057 config->model = g_strdup (greeter->priv->xkl_config->model);
1058 config->layouts[0] = g_strdup (layout);
1059 config->layouts[1] = NULL;
1060 if (!xkl_config_rec_activate (config, greeter->priv->xkl_engine))
1061 g_warning ("Failed to activate XKL config");
1063 greeter->priv->layout = g_strdup (layout);
1064 g_object_unref (config);
1068 * ldm_greeter_get_layout:
1069 * @greeter: A #LdmGreeter
1071 * Get the current keyboard layout.
1073 * Return value: The currently active layout for this user.
1076 ldm_greeter_get_layout (LdmGreeter *greeter)
1078 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1079 setup_xkl (greeter);
1080 return greeter->priv->layout;
1084 update_sessions (LdmGreeter *greeter)
1087 GError *error = NULL;
1089 if (greeter->priv->have_sessions)
1092 directory = g_dir_open (XSESSIONS_DIR, 0, &error);
1094 g_warning ("Failed to open sessions directory: %s", error->message);
1095 g_clear_error (&error);
1101 const gchar *filename;
1106 filename = g_dir_read_name (directory);
1107 if (filename == NULL)
1110 if (!g_str_has_suffix (filename, ".desktop"))
1113 key = g_strndup (filename, strlen (filename) - strlen (".desktop"));
1114 path = g_build_filename (XSESSIONS_DIR, filename, NULL);
1115 g_debug ("Loading session %s", path);
1117 key_file = g_key_file_new ();
1118 result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
1120 g_warning ("Failed to load session file %s: %s:", path, error->message);
1121 g_clear_error (&error);
1123 if (result && !g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, NULL))
1125 gchar *domain, *name, *comment;
1127 #ifdef G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN
1128 domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN, NULL);
1130 domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL);
1132 name = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, domain, NULL);
1133 comment = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, domain, NULL);
1135 comment = g_strdup ("");
1138 g_debug ("Loaded session %s (%s, %s)", key, name, comment);
1139 greeter->priv->sessions = g_list_append (greeter->priv->sessions, ldm_session_new (key, name, comment));
1142 g_warning ("Invalid session %s: %s", path, error->message);
1143 g_clear_error (&error);
1151 g_key_file_free (key_file);
1154 g_dir_close (directory);
1156 greeter->priv->have_sessions = TRUE;
1160 * ldm_greeter_get_sessions:
1161 * @greeter: A #LdmGreeter
1163 * Get the available sessions.
1165 * Return value: (element-type LdmSession): A list of #LdmSession
1168 ldm_greeter_get_sessions (LdmGreeter *greeter)
1170 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1171 update_sessions (greeter);
1172 return greeter->priv->sessions;
1176 * ldm_greeter_get_default_session:
1177 * @greeter: A #LdmGreeter
1179 * Get the default session to use.
1181 * Return value: The session name
1184 ldm_greeter_get_default_session (LdmGreeter *greeter)
1186 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1187 return greeter->priv->default_session;
1191 * ldm_greeter_get_has_guest_session:
1192 * @greeter: A #LdmGreeter
1194 * Check if guest sessions are supported.
1196 * Return value: TRUE if guest sessions are supported.
1199 ldm_greeter_get_has_guest_session (LdmGreeter *greeter)
1201 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1202 return greeter->priv->guest_account_supported;
1206 * ldm_greeter_get_is_first:
1207 * @greeter: A #LdmGreeter
1209 * Check if this is the first time a greeter has been shown on this display.
1211 * Return value: TRUE if this is the first greeter on this display.
1214 ldm_greeter_get_is_first (LdmGreeter *greeter)
1216 g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
1217 return greeter->priv->greeter_count == 0;
1221 * ldm_greeter_get_timed_login_user:
1222 * @greeter: A #LdmGreeter
1224 * Get the user to log in by as default.
1226 * Return value: A username
1229 ldm_greeter_get_timed_login_user (LdmGreeter *greeter)
1231 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1232 return greeter->priv->timed_user;
1236 * ldm_greeter_get_timed_login_delay:
1237 * @greeter: A #LdmGreeter
1239 * Get the number of seconds to wait until logging in as the default user.
1241 * Return value: The number of seconds before logging in as the default user
1244 ldm_greeter_get_timed_login_delay (LdmGreeter *greeter)
1246 g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
1247 return greeter->priv->login_delay;
1251 * ldm_greeter_cancel_timed_login:
1252 * @greeter: A #LdmGreeter
1254 * Cancel the login as the default user.
1257 ldm_greeter_cancel_timed_login (LdmGreeter *greeter)
1259 g_return_if_fail (LDM_IS_GREETER (greeter));
1261 if (greeter->priv->login_timeout)
1262 g_source_remove (greeter->priv->login_timeout);
1263 greeter->priv->login_timeout = 0;
1267 * ldm_greeter_login:
1268 * @greeter: A #LdmGreeter
1269 * @username: (allow-none): A username or NULL to prompt for a username.
1271 * Starts the authentication procedure for a user.
1274 ldm_greeter_login (LdmGreeter *greeter, const char *username)
1276 guint8 message[MAX_MESSAGE_LENGTH];
1279 g_return_if_fail (LDM_IS_GREETER (greeter));
1284 greeter->priv->in_authentication = TRUE;
1285 greeter->priv->is_authenticated = FALSE;
1286 g_free (greeter->priv->authentication_user);
1287 greeter->priv->authentication_user = g_strdup (username);
1288 g_debug ("Starting authentication for user %s...", username);
1289 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_LOGIN, string_length (username), &offset);
1290 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1291 write_message (greeter, message, offset);
1295 * ldm_greeter_login_with_user_promp:
1296 * @greeter: A #LdmGreeter
1298 * Starts the authentication procedure, prompting the greeter for a username.
1301 ldm_greeter_login_with_user_prompt (LdmGreeter *greeter)
1303 ldm_greeter_login (greeter, NULL);
1307 * ldm_greeter_login_as_guest:
1308 * @greeter: A #LdmGreeter
1310 * Starts the authentication procedure for the guest user.
1313 ldm_greeter_login_as_guest (LdmGreeter *greeter)
1315 guint8 message[MAX_MESSAGE_LENGTH];
1318 g_return_if_fail (LDM_IS_GREETER (greeter));
1320 greeter->priv->in_authentication = TRUE;
1321 greeter->priv->is_authenticated = FALSE;
1322 g_free (greeter->priv->authentication_user);
1323 greeter->priv->authentication_user = NULL;
1324 g_debug ("Starting authentication for guest account...");
1325 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_LOGIN_AS_GUEST, 0, &offset);
1326 write_message (greeter, message, offset);
1330 * ldm_greeter_respond:
1331 * @greeter: A #LdmGreeter
1332 * @response: Response to a prompt
1334 * Provide response to a prompt.
1337 ldm_greeter_respond (LdmGreeter *greeter, const gchar *response)
1339 guint8 message[MAX_MESSAGE_LENGTH];
1342 g_return_if_fail (LDM_IS_GREETER (greeter));
1343 g_return_if_fail (response != NULL);
1345 g_debug ("Providing response to display manager");
1346 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, int_length () + string_length (response), &offset);
1347 // FIXME: Could be multiple responses required
1348 write_int (message, MAX_MESSAGE_LENGTH, 1, &offset);
1349 write_string (message, MAX_MESSAGE_LENGTH, response, &offset);
1350 write_message (greeter, message, offset);
1354 * ldm_greeter_cancel_authentication:
1355 * @greeter: A #LdmGreeter
1357 * Cancel the current user authentication.
1360 ldm_greeter_cancel_authentication (LdmGreeter *greeter)
1362 guint8 message[MAX_MESSAGE_LENGTH];
1365 g_return_if_fail (LDM_IS_GREETER (greeter));
1367 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset);
1368 write_message (greeter, message, offset);
1372 * ldm_greeter_get_in_authentication:
1373 * @greeter: A #LdmGreeter
1375 * Checks if the greeter is in the process of authenticating.
1377 * Return value: TRUE if the greeter is authenticating a user.
1380 ldm_greeter_get_in_authentication (LdmGreeter *greeter)
1382 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1383 return greeter->priv->in_authentication;
1387 * ldm_greeter_get_is_authenticated:
1388 * @greeter: A #LdmGreeter
1390 * Checks if the greeter has successfully authenticated.
1392 * Return value: TRUE if the greeter is authenticated for login.
1395 ldm_greeter_get_is_authenticated (LdmGreeter *greeter)
1397 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1398 return greeter->priv->is_authenticated;
1402 * ldm_greeter_get_authentication_user:
1403 * @greeter: A #LdmGreeter
1405 * Get the user that is being authenticated.
1407 * Return value: The username of the authentication user being authenticated or NULL if no authentication in progress.
1410 ldm_greeter_get_authentication_user (LdmGreeter *greeter)
1412 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1413 return greeter->priv->authentication_user;
1417 * ldm_greeter_start_session:
1418 * @greeter: A #LdmGreeter
1419 * @session: (allow-none): The session to log into or NULL to use the default
1421 * Start a session for the logged in user.
1424 ldm_greeter_start_session (LdmGreeter *greeter, const gchar *session)
1426 guint8 message[MAX_MESSAGE_LENGTH];
1429 g_return_if_fail (LDM_IS_GREETER (greeter));
1434 g_debug ("Starting session %s", session);
1435 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset);
1436 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
1437 write_message (greeter, message, offset);
1441 * ldm_greeter_start_session_with_defaults:
1442 * @greeter: A #LdmGreeter
1444 * Login a user to a session using default settings for that user.
1447 ldm_greeter_start_default_session (LdmGreeter *greeter)
1449 ldm_greeter_start_session (greeter, NULL);
1453 upower_call_function (LdmGreeter *greeter, const gchar *function, gboolean has_result)
1457 GError *error = NULL;
1458 gboolean function_result = FALSE;
1460 if (!greeter->priv->system_bus)
1463 proxy = g_dbus_proxy_new_sync (greeter->priv->system_bus,
1464 G_DBUS_PROXY_FLAGS_NONE,
1466 "org.freedesktop.UPower",
1467 "/org/freedesktop/UPower",
1468 "org.freedesktop.UPower",
1470 result = g_dbus_proxy_call_sync (proxy,
1473 G_DBUS_CALL_FLAGS_NONE,
1477 g_object_unref (proxy);
1480 g_warning ("Error calling UPower function %s: %s", function, error->message);
1481 g_clear_error (&error);
1485 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(b)")))
1486 g_variant_get (result, "(b)", &function_result);
1488 g_variant_unref (result);
1489 return function_result;
1493 * ldm_greeter_get_can_suspend:
1494 * @greeter: A #LdmGreeter
1496 * Checks if the greeter is authorized to do a system suspend.
1498 * Return value: TRUE if the greeter can suspend the system
1501 ldm_greeter_get_can_suspend (LdmGreeter *greeter)
1503 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1504 return upower_call_function (greeter, "SuspendAllowed", TRUE);
1508 * ldm_greeter_suspend:
1509 * @greeter: A #LdmGreeter
1511 * Triggers a system suspend.
1514 ldm_greeter_suspend (LdmGreeter *greeter)
1516 g_return_if_fail (LDM_IS_GREETER (greeter));
1517 upower_call_function (greeter, "Suspend", FALSE);
1521 * ldm_greeter_get_can_hibernate:
1522 * @greeter: A #LdmGreeter
1524 * Checks if the greeter is authorized to do a system hibernate.
1526 * Return value: TRUE if the greeter can hibernate the system
1529 ldm_greeter_get_can_hibernate (LdmGreeter *greeter)
1531 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1532 return upower_call_function (greeter, "HibernateAllowed", TRUE);
1536 * ldm_greeter_hibernate:
1537 * @greeter: A #LdmGreeter
1539 * Triggers a system hibernate.
1542 ldm_greeter_hibernate (LdmGreeter *greeter)
1544 g_return_if_fail (LDM_IS_GREETER (greeter));
1545 upower_call_function (greeter, "Hibernate", FALSE);
1549 ck_call_function (LdmGreeter *greeter, const gchar *function, gboolean has_result)
1553 GError *error = NULL;
1554 gboolean function_result = FALSE;
1556 if (!greeter->priv->system_bus)
1559 proxy = g_dbus_proxy_new_sync (greeter->priv->system_bus,
1560 G_DBUS_PROXY_FLAGS_NONE,
1562 "org.freedesktop.ConsoleKit",
1563 "/org/freedesktop/ConsoleKit/Manager",
1564 "org.freedesktop.ConsoleKit.Manager",
1566 result = g_dbus_proxy_call_sync (proxy,
1569 G_DBUS_CALL_FLAGS_NONE,
1573 g_object_unref (proxy);
1576 g_warning ("Error calling ConsoleKit function %s: %s", function, error->message);
1577 g_clear_error (&error);
1581 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(b)")))
1582 g_variant_get (result, "(b)", &function_result);
1584 g_variant_unref (result);
1585 return function_result;
1589 * ldm_greeter_get_can_restart:
1590 * @greeter: A #LdmGreeter
1592 * Checks if the greeter is authorized to do a system restart.
1594 * Return value: TRUE if the greeter can restart the system
1597 ldm_greeter_get_can_restart (LdmGreeter *greeter)
1599 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1600 return ck_call_function (greeter, "CanRestart", TRUE);
1604 * ldm_greeter_restart:
1605 * @greeter: A #LdmGreeter
1607 * Triggers a system restart.
1610 ldm_greeter_restart (LdmGreeter *greeter)
1612 g_return_if_fail (LDM_IS_GREETER (greeter));
1613 ck_call_function (greeter, "Restart", FALSE);
1617 * ldm_greeter_get_can_shutdown:
1618 * @greeter: A #LdmGreeter
1620 * Checks if the greeter is authorized to do a system shutdown.
1622 * Return value: TRUE if the greeter can shutdown the system
1625 ldm_greeter_get_can_shutdown (LdmGreeter *greeter)
1627 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1628 return ck_call_function (greeter, "CanStop", TRUE);
1632 * ldm_greeter_shutdown:
1633 * @greeter: A #LdmGreeter
1635 * Triggers a system shutdown.
1638 ldm_greeter_shutdown (LdmGreeter *greeter)
1640 g_return_if_fail (LDM_IS_GREETER (greeter));
1641 ck_call_function (greeter, "Stop", FALSE);
1645 * ldm_greeter_get_user_defaults:
1646 * @greeter: A #LdmGreeter
1647 * @username: The user to check
1648 * @language: (out): Default language for this user.
1649 * @layout: (out): Default keyboard layout for this user.
1650 * @session: (out): Default session for this user.
1652 * Get the default settings for a given user. If the user does not exist FALSE
1653 * is returned and language, layout and session are not set.
1655 * Return value: TRUE if this user exists.
1658 ldm_greeter_get_user_defaults (LdmGreeter *greeter, const gchar *username, gchar **language, gchar **layout, gchar **session)
1662 guint8 message[MAX_MESSAGE_LENGTH];
1664 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1665 g_return_val_if_fail (username != NULL, FALSE);
1668 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_GET_USER_DEFAULTS, string_length (username), &offset);
1669 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1670 write_message (greeter, message, offset);
1672 if (!read_packet (greeter, TRUE))
1674 g_warning ("Error reading user defaults from server");
1679 id = read_int (greeter, &offset);
1680 g_assert (id == GREETER_MESSAGE_USER_DEFAULTS);
1681 read_int (greeter, &offset);
1682 *language = read_string (greeter, &offset);
1683 *layout = read_string (greeter, &offset);
1684 *session = read_string (greeter, &offset);
1686 g_debug ("User defaults for %s: language=%s, layout=%s, session=%s", username, *language, *layout, *session);
1688 greeter->priv->n_read = 0;
1694 ldm_greeter_init (LdmGreeter *greeter)
1696 greeter->priv = G_TYPE_INSTANCE_GET_PRIVATE (greeter, LDM_TYPE_GREETER, LdmGreeterPrivate);
1697 greeter->priv->read_buffer = g_malloc (HEADER_SIZE);
1699 g_debug ("default-language=%s", ldm_greeter_get_default_language (greeter));
1703 ldm_greeter_set_property (GObject *object,
1705 const GValue *value,
1710 self = LDM_GREETER (object);
1714 ldm_greeter_set_layout(self, g_value_get_string (value));
1717 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1723 ldm_greeter_get_property (GObject *object,
1730 self = LDM_GREETER (object);
1734 g_value_set_string (value, ldm_greeter_get_hostname (self));
1736 case PROP_NUM_USERS:
1737 g_value_set_int (value, ldm_greeter_get_num_users (self));
1741 case PROP_DEFAULT_LANGUAGE:
1742 g_value_set_string (value, ldm_greeter_get_default_language (self));
1747 g_value_set_string (value, ldm_greeter_get_layout (self));
1751 case PROP_DEFAULT_SESSION:
1752 g_value_set_string (value, ldm_greeter_get_default_session (self));
1754 case PROP_TIMED_LOGIN_USER:
1755 g_value_set_string (value, ldm_greeter_get_timed_login_user (self));
1757 case PROP_TIMED_LOGIN_DELAY:
1758 g_value_set_int (value, ldm_greeter_get_timed_login_delay (self));
1760 case PROP_AUTHENTICATION_USER:
1761 g_value_set_string (value, ldm_greeter_get_authentication_user (self));
1763 case PROP_IN_AUTHENTICATION:
1764 g_value_set_boolean (value, ldm_greeter_get_in_authentication (self));
1766 case PROP_IS_AUTHENTICATED:
1767 g_value_set_boolean (value, ldm_greeter_get_is_authenticated (self));
1769 case PROP_CAN_SUSPEND:
1770 g_value_set_boolean (value, ldm_greeter_get_can_suspend (self));
1772 case PROP_CAN_HIBERNATE:
1773 g_value_set_boolean (value, ldm_greeter_get_can_hibernate (self));
1775 case PROP_CAN_RESTART:
1776 g_value_set_boolean (value, ldm_greeter_get_can_restart (self));
1778 case PROP_CAN_SHUTDOWN:
1779 g_value_set_boolean (value, ldm_greeter_get_can_shutdown (self));
1782 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1788 ldm_greeter_class_init (LdmGreeterClass *klass)
1790 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1792 g_type_class_add_private (klass, sizeof (LdmGreeterPrivate));
1794 object_class->set_property = ldm_greeter_set_property;
1795 object_class->get_property = ldm_greeter_get_property;
1797 g_object_class_install_property (object_class,
1799 g_param_spec_string ("hostname",
1801 "Hostname displaying greeter for",
1804 g_object_class_install_property (object_class,
1806 g_param_spec_int ("num-users",
1808 "Number of login users",
1811 /*g_object_class_install_property (object_class,
1813 g_param_spec_list ("users",
1815 "Users that can login"));
1816 g_object_class_install_property (object_class,
1817 PROP_DEFAULT_LANGUAGE,
1818 g_param_spec_string ("default-language",
1822 G_PARAM_READWRITE));
1823 g_object_class_install_property (object_class,
1825 g_param_spec_list ("layouts",
1827 "Available keyboard layouts"));*/
1828 g_object_class_install_property (object_class,
1830 g_param_spec_string ("layout",
1832 "Current keyboard layout",
1834 G_PARAM_READWRITE));
1835 /*g_object_class_install_property (object_class,
1837 g_param_spec_list ("sessions",
1839 "Available sessions"));*/
1840 g_object_class_install_property (object_class,
1841 PROP_DEFAULT_SESSION,
1842 g_param_spec_string ("default-session",
1846 G_PARAM_READWRITE));
1847 g_object_class_install_property (object_class,
1848 PROP_TIMED_LOGIN_USER,
1849 g_param_spec_string ("timed-login-user",
1851 "User to login as when timed expires",
1854 g_object_class_install_property (object_class,
1855 PROP_TIMED_LOGIN_DELAY,
1856 g_param_spec_int ("login-delay",
1858 "Number of seconds until logging in as default user",
1859 G_MININT, G_MAXINT, 0,
1861 g_object_class_install_property (object_class,
1862 PROP_AUTHENTICATION_USER,
1863 g_param_spec_string ("authentication-user",
1864 "authentication-user",
1865 "The user being authenticated",
1868 g_object_class_install_property (object_class,
1869 PROP_IN_AUTHENTICATION,
1870 g_param_spec_boolean ("in-authentication",
1871 "in-authentication",
1872 "TRUE if a user is being authenticated",
1875 g_object_class_install_property (object_class,
1876 PROP_IS_AUTHENTICATED,
1877 g_param_spec_boolean ("is-authenticated",
1879 "TRUE if the selected user is authenticated",
1882 g_object_class_install_property (object_class,
1884 g_param_spec_boolean ("can-suspend",
1886 "TRUE if allowed to suspend the system",
1889 g_object_class_install_property (object_class,
1891 g_param_spec_boolean ("can-hibernate",
1893 "TRUE if allowed to hibernate the system",
1896 g_object_class_install_property (object_class,
1898 g_param_spec_boolean ("can-restart",
1900 "TRUE if allowed to restart the system",
1903 g_object_class_install_property (object_class,
1905 g_param_spec_boolean ("can-shutdown",
1907 "TRUE if allowed to shutdown the system",
1912 * LdmGreeter::connected:
1913 * @greeter: A #LdmGreeter
1915 * The ::connected signal gets emitted when the greeter connects to the
1918 signals[CONNECTED] =
1919 g_signal_new ("connected",
1920 G_TYPE_FROM_CLASS (klass),
1922 G_STRUCT_OFFSET (LdmGreeterClass, connected),
1924 g_cclosure_marshal_VOID__VOID,
1928 * LdmGreeter::show-prompt:
1929 * @greeter: A #LdmGreeter
1930 * @text: Prompt text
1932 * The ::show-prompt signal gets emitted when the greeter should show a
1933 * prompt to the user. The given text should be displayed and an input
1934 * field for the user to provide a response.
1936 * Call ldm_greeter_respond() with the resultant input or
1937 * ldm_greeter_cancel_authentication() to abort the authentication.
1939 signals[SHOW_PROMPT] =
1940 g_signal_new ("show-prompt",
1941 G_TYPE_FROM_CLASS (klass),
1943 G_STRUCT_OFFSET (LdmGreeterClass, show_prompt),
1945 g_cclosure_marshal_VOID__STRING,
1946 G_TYPE_NONE, 1, G_TYPE_STRING);
1949 * LdmGreeter::show-message:
1950 * @greeter: A #LdmGreeter
1951 * @text: Message text
1953 * The ::show-message signal gets emitted when the greeter
1954 * should show an informational message to the user.
1956 signals[SHOW_MESSAGE] =
1957 g_signal_new ("show-message",
1958 G_TYPE_FROM_CLASS (klass),
1960 G_STRUCT_OFFSET (LdmGreeterClass, show_message),
1962 g_cclosure_marshal_VOID__STRING,
1963 G_TYPE_NONE, 1, G_TYPE_STRING);
1966 * LdmGreeter::show-error:
1967 * @greeter: A #LdmGreeter
1968 * @text: Message text
1970 * The ::show-error signal gets emitted when the greeter
1971 * should show an error message to the user.
1973 signals[SHOW_ERROR] =
1974 g_signal_new ("show-error",
1975 G_TYPE_FROM_CLASS (klass),
1977 G_STRUCT_OFFSET (LdmGreeterClass, show_error),
1979 g_cclosure_marshal_VOID__STRING,
1980 G_TYPE_NONE, 1, G_TYPE_STRING);
1983 * LdmGreeter::authentication-complete:
1984 * @greeter: A #LdmGreeter
1986 * The ::authentication-complete signal gets emitted when the greeter
1987 * has completed authentication.
1989 * Call ldm_greeter_get_is_authenticated() to check if the authentication
1992 signals[AUTHENTICATION_COMPLETE] =
1993 g_signal_new ("authentication-complete",
1994 G_TYPE_FROM_CLASS (klass),
1996 G_STRUCT_OFFSET (LdmGreeterClass, authentication_complete),
1998 g_cclosure_marshal_VOID__VOID,
2002 * LdmGreeter::timed-login:
2003 * @greeter: A #LdmGreeter
2004 * @username: A username
2006 * The ::timed-login signal gets emitted when the default user timer
2009 signals[TIMED_LOGIN] =
2010 g_signal_new ("timed-login",
2011 G_TYPE_FROM_CLASS (klass),
2013 G_STRUCT_OFFSET (LdmGreeterClass, timed_login),
2015 g_cclosure_marshal_VOID__STRING,
2016 G_TYPE_NONE, 1, G_TYPE_STRING);
2019 * LdmGreeter::user-added:
2020 * @greeter: A #LdmGreeter
2022 * The ::user-added signal gets emitted when a user account is created.
2024 signals[USER_ADDED] =
2025 g_signal_new ("user-added",
2026 G_TYPE_FROM_CLASS (klass),
2028 G_STRUCT_OFFSET (LdmGreeterClass, user_added),
2030 g_cclosure_marshal_VOID__OBJECT,
2031 G_TYPE_NONE, 1, LDM_TYPE_USER);
2034 * LdmGreeter::user-changed:
2035 * @greeter: A #LdmGreeter
2037 * The ::user-changed signal gets emitted when a user account is modified.
2039 signals[USER_CHANGED] =
2040 g_signal_new ("user-changed",
2041 G_TYPE_FROM_CLASS (klass),
2043 G_STRUCT_OFFSET (LdmGreeterClass, user_changed),
2045 g_cclosure_marshal_VOID__OBJECT,
2046 G_TYPE_NONE, 1, LDM_TYPE_USER);
2049 * LdmGreeter::user-removed:
2050 * @greeter: A #LdmGreeter
2052 * The ::user-removed signal gets emitted when a user account is removed.
2054 signals[USER_REMOVED] =
2055 g_signal_new ("user-removed",
2056 G_TYPE_FROM_CLASS (klass),
2058 G_STRUCT_OFFSET (LdmGreeterClass, user_removed),
2060 g_cclosure_marshal_VOID__OBJECT,
2061 G_TYPE_NONE, 1, LDM_TYPE_USER);
2065 * @greeter: A #LdmGreeter
2067 * The ::quit signal gets emitted when the greeter should exit.
2070 g_signal_new ("quit",
2071 G_TYPE_FROM_CLASS (klass),
2073 G_STRUCT_OFFSET (LdmGreeterClass, quit),
2075 g_cclosure_marshal_VOID__VOID,