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
18 #include <sys/utsname.h>
20 #include <gio/gdesktopappinfo.h>
21 #include <security/pam_appl.h>
22 #include <libxklavier/xklavier.h>
24 #include "lightdm/greeter.h"
25 #include "user-private.h"
32 PROP_DEFAULT_LANGUAGE,
36 PROP_DEFAULT_SESSION_HINT,
38 PROP_HAS_GUEST_ACCOUNT_HINT,
39 PROP_SELECT_USER_HINT,
40 PROP_SELECT_GUEST_HINT,
41 PROP_AUTOLOGIN_USER_HINT,
42 PROP_AUTOLOGIN_GUEST_HINT,
43 PROP_AUTOLOGIN_TIMEOUT_HINT,
44 PROP_AUTHENTICATION_USER,
45 PROP_IN_AUTHENTICATION,
46 PROP_IS_AUTHENTICATED,
57 AUTHENTICATION_COMPLETE,
59 AUTOLOGIN_TIMER_EXPIRED,
66 static guint signals[LAST_SIGNAL] = { 0 };
70 GDBusConnection *lightdm_bus;
72 GDBusConnection *system_bus;
74 GIOChannel *to_server_channel, *from_server_channel;
82 /* File monitor for password file */
83 GFileMonitor *passwd_monitor;
85 /* TRUE if have scanned users */
91 gboolean have_languages;
94 XklEngine *xkl_engine;
95 XklConfigRec *xkl_config;
96 gboolean have_layouts;
100 gboolean have_sessions;
103 gchar *authentication_user;
104 gboolean in_authentication;
105 gboolean is_authenticated;
106 guint32 authenticate_sequence_number;
107 gboolean cancelling_authentication;
114 G_DEFINE_TYPE (LdmGreeter, ldm_greeter, G_TYPE_OBJECT);
116 #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LDM_TYPE_GREETER, LdmGreeterPrivate)
118 #define HEADER_SIZE 8
119 #define MAX_MESSAGE_LENGTH 1024
121 #define PASSWD_FILE "/etc/passwd"
122 #define USER_CONFIG_FILE "/etc/lightdm/users.conf"
124 /* Messages from the greeter to the server */
127 GREETER_MESSAGE_CONNECT = 0,
128 GREETER_MESSAGE_LOGIN,
129 GREETER_MESSAGE_LOGIN_AS_GUEST,
130 GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
131 GREETER_MESSAGE_START_SESSION,
132 GREETER_MESSAGE_CANCEL_AUTHENTICATION
135 /* Messages from the server to the greeter */
138 SERVER_MESSAGE_CONNECTED = 0,
140 SERVER_MESSAGE_PROMPT_AUTHENTICATION,
141 SERVER_MESSAGE_END_AUTHENTICATION,
142 SERVER_MESSAGE_SESSION_FAILED,
148 * Create a new greeter.
150 * Return value: the new #LdmGreeter
155 return g_object_new (LDM_TYPE_GREETER, NULL);
159 timed_login_cb (gpointer data)
161 LdmGreeter *greeter = data;
162 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
164 priv->login_timeout = 0;
165 g_signal_emit (G_OBJECT (greeter), signals[AUTOLOGIN_TIMER_EXPIRED], 0);
177 write_message (LdmGreeter *greeter, guint8 *message, gsize message_length)
179 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
180 GError *error = NULL;
182 if (g_io_channel_write_chars (priv->to_server_channel, (gchar *) message, message_length, NULL, NULL) != G_IO_STATUS_NORMAL)
183 g_warning ("Error writing to daemon: %s", error->message);
185 g_debug ("Wrote %zi bytes to daemon", message_length);
186 g_clear_error (&error);
187 g_io_channel_flush (priv->to_server_channel, NULL);
191 write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset)
193 if (*offset + 4 >= buffer_length)
195 buffer[*offset] = value >> 24;
196 buffer[*offset+1] = (value >> 16) & 0xFF;
197 buffer[*offset+2] = (value >> 8) & 0xFF;
198 buffer[*offset+3] = value & 0xFF;
203 write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset)
205 gint length = strlen (value);
206 write_int (buffer, buffer_length, length, offset);
207 if (*offset + length >= buffer_length)
209 memcpy (buffer + *offset, value, length);
214 read_int (LdmGreeter *greeter, gsize *offset)
216 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
220 if (priv->n_read - *offset < int_length ())
222 g_warning ("Not enough space for int, need %i, got %zi", int_length (), priv->n_read - *offset);
226 buffer = priv->read_buffer + *offset;
227 value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
228 *offset += int_length ();
234 read_string (LdmGreeter *greeter, gsize *offset)
236 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
240 length = read_int (greeter, offset);
241 if (priv->n_read - *offset < length)
243 g_warning ("Not enough space for string, need %u, got %zu", length, priv->n_read - *offset);
244 return g_strdup ("");
247 value = g_malloc (sizeof (gchar) * (length + 1));
248 memcpy (value, priv->read_buffer + *offset, length);
249 value[length] = '\0';
256 string_length (const gchar *value)
258 return int_length () + strlen (value);
262 write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset)
264 write_int (buffer, buffer_length, id, offset);
265 write_int (buffer, buffer_length, length, offset);
268 static guint32 get_packet_length (LdmGreeter *greeter)
271 return read_int (greeter, &offset);
275 handle_connected (LdmGreeter *greeter, guint32 length, gsize *offset)
277 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
279 GString *hint_string;
282 version = read_string (greeter, offset);
283 hint_string = g_string_new ("");
284 while (*offset < length)
288 name = read_string (greeter, offset);
289 value = read_string (greeter, offset);
290 g_hash_table_insert (priv->hints, name, value);
291 g_string_append_printf (hint_string, " %s=%s", name, value);
294 g_debug ("Connected version=%s%s", version, hint_string->str);
296 g_string_free (hint_string, TRUE);
298 /* Set timeout for default login */
299 timeout = ldm_greeter_get_autologin_timeout_hint (greeter);
302 g_debug ("Setting autologin timer for %d seconds", timeout);
303 priv->login_timeout = g_timeout_add (timeout * 1000, timed_login_cb, greeter);
305 g_signal_emit (G_OBJECT (greeter), signals[CONNECTED], 0);
309 handle_prompt_authentication (LdmGreeter *greeter, gsize *offset)
311 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
312 guint32 sequence_number, n_messages, i;
314 sequence_number = read_int (greeter, offset);
315 if (sequence_number != priv->authenticate_sequence_number)
317 g_debug ("Ignoring prompt authentication with invalid sequence number %d", sequence_number);
321 if (priv->cancelling_authentication)
323 g_debug ("Ignoring prompt authentication as waiting for it to cancel");
327 n_messages = read_int (greeter, offset);
328 g_debug ("Prompt user with %d message(s)", n_messages);
330 for (i = 0; i < n_messages; i++)
335 msg_style = read_int (greeter, offset);
336 msg = read_string (greeter, offset);
338 // FIXME: Should stop on prompts?
341 case PAM_PROMPT_ECHO_OFF:
342 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, msg, LDM_PROMPT_TYPE_SECRET);
344 case PAM_PROMPT_ECHO_ON:
345 g_signal_emit (G_OBJECT (greeter), signals[SHOW_PROMPT], 0, msg, LDM_PROMPT_TYPE_QUESTION);
348 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, msg, LDM_MESSAGE_TYPE_ERROR);
351 g_signal_emit (G_OBJECT (greeter), signals[SHOW_MESSAGE], 0, msg, LDM_MESSAGE_TYPE_INFO);
360 handle_end_authentication (LdmGreeter *greeter, gsize *offset)
362 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
363 guint32 sequence_number, return_code;
365 sequence_number = read_int (greeter, offset);
366 return_code = read_int (greeter, offset);
368 if (sequence_number != priv->authenticate_sequence_number)
370 g_debug ("Ignoring end authentication with invalid sequence number %d", sequence_number);
374 g_debug ("Authentication complete with return code %d", return_code);
375 priv->cancelling_authentication = FALSE;
376 priv->is_authenticated = (return_code == 0);
377 if (!priv->is_authenticated)
379 g_free (priv->authentication_user);
380 priv->authentication_user = NULL;
382 g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
383 priv->in_authentication = FALSE;
387 handle_session_failed (LdmGreeter *greeter, gsize *offset)
389 g_debug ("Session failed to start");
390 g_signal_emit (G_OBJECT (greeter), signals[SESSION_FAILED], 0);
394 handle_quit (LdmGreeter *greeter, gsize *offset)
396 g_debug ("Got quit request from server");
397 g_signal_emit (G_OBJECT (greeter), signals[QUIT], 0);
401 read_packet (LdmGreeter *greeter, gboolean block)
403 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
404 gsize n_to_read, n_read;
405 GError *error = NULL;
407 /* Read the header, or the whole packet if we already have that */
408 n_to_read = HEADER_SIZE;
409 if (priv->n_read >= HEADER_SIZE)
410 n_to_read += get_packet_length (greeter);
415 status = g_io_channel_read_chars (priv->from_server_channel,
416 (gchar *) priv->read_buffer + priv->n_read,
417 n_to_read - priv->n_read,
420 if (status == G_IO_STATUS_ERROR)
421 g_warning ("Error reading from server: %s", error->message);
422 g_clear_error (&error);
423 if (status != G_IO_STATUS_NORMAL)
426 g_debug ("Read %zi bytes from daemon", n_read);
428 priv->n_read += n_read;
429 } while (priv->n_read < n_to_read && block);
431 /* Stop if haven't got all the data we want */
432 if (priv->n_read != n_to_read)
435 /* If have header, rerun for content */
436 if (priv->n_read == HEADER_SIZE)
438 n_to_read = get_packet_length (greeter);
441 priv->read_buffer = g_realloc (priv->read_buffer, HEADER_SIZE + n_to_read);
442 return read_packet (greeter, block);
450 from_server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
452 LdmGreeter *greeter = data;
453 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
457 if (!read_packet (greeter, FALSE))
461 id = read_int (greeter, &offset);
462 length = read_int (greeter, &offset);
465 case SERVER_MESSAGE_CONNECTED:
466 handle_connected (greeter, length, &offset);
468 case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
469 handle_prompt_authentication (greeter, &offset);
471 case SERVER_MESSAGE_END_AUTHENTICATION:
472 handle_end_authentication (greeter, &offset);
474 case SERVER_MESSAGE_SESSION_FAILED:
475 handle_session_failed (greeter, &offset);
477 case SERVER_MESSAGE_QUIT:
478 handle_quit (greeter, &offset);
481 g_warning ("Unknown message from server: %d", id);
491 * ldm_greeter_connect_to_server:
492 * @greeter: The greeter to connect
494 * Connects the greeter to the display manager.
496 * Return value: TRUE if successfully connected
499 ldm_greeter_connect_to_server (LdmGreeter *greeter)
501 LdmGreeterPrivate *priv;
502 GError *error = NULL;
503 const gchar *bus_address, *fd;
504 guint8 message[MAX_MESSAGE_LENGTH];
506 GBusType bus_type = G_BUS_TYPE_SYSTEM;
508 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
510 priv = GET_PRIVATE (greeter);
512 priv->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
513 if (!priv->system_bus)
514 g_warning ("Failed to connect to system bus: %s", error->message);
515 g_clear_error (&error);
517 bus_address = getenv ("LDM_BUS");
518 if (bus_address && strcmp (bus_address, "SESSION") == 0)
519 bus_type = G_BUS_TYPE_SESSION;
521 priv->lightdm_bus = g_bus_get_sync (bus_type, NULL, &error);
522 if (!priv->lightdm_bus)
523 g_warning ("Failed to connect to LightDM bus: %s", error->message);
524 g_clear_error (&error);
525 if (!priv->lightdm_bus)
528 fd = getenv ("LIGHTDM_TO_SERVER_FD");
531 g_warning ("No LIGHTDM_TO_SERVER_FD environment variable");
534 priv->to_server_channel = g_io_channel_unix_new (atoi (fd));
535 g_io_channel_set_encoding (priv->to_server_channel, NULL, NULL);
537 fd = getenv ("LIGHTDM_FROM_SERVER_FD");
540 g_warning ("No LIGHTDM_FROM_SERVER_FD environment variable");
543 priv->from_server_channel = g_io_channel_unix_new (atoi (fd));
544 g_io_channel_set_encoding (priv->from_server_channel, NULL, NULL);
545 g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
547 g_debug ("Connecting to display manager...");
548 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION), &offset);
549 write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
550 write_message (greeter, message, offset);
556 * ldm_greeter_get_hostname:
557 * @greeter: a #LdmGreeter
559 * Return value: The host this greeter is displaying
562 ldm_greeter_get_hostname (LdmGreeter *greeter)
564 LdmGreeterPrivate *priv;
566 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
568 priv = GET_PRIVATE (greeter);
574 priv->hostname = g_strdup (info.nodename);
577 return priv->hostname;
581 get_user_by_name (LdmGreeter *greeter, const gchar *username)
583 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
586 for (link = priv->users; link; link = link->next)
588 LdmUser *user = link->data;
589 if (strcmp (ldm_user_get_name (user), username) == 0)
597 compare_user (gconstpointer a, gconstpointer b)
599 LdmUser *user_a = (LdmUser *) a, *user_b = (LdmUser *) b;
600 return strcmp (ldm_user_get_display_name (user_a), ldm_user_get_display_name (user_b));
604 load_users (LdmGreeter *greeter)
606 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
610 gchar **hidden_users, **hidden_shells;
611 GList *users = NULL, *old_users, *new_users = NULL, *changed_users = NULL, *link;
612 GError *error = NULL;
614 g_debug ("Loading user config from %s", USER_CONFIG_FILE);
616 config = g_key_file_new ();
617 if (!g_key_file_load_from_file (config, USER_CONFIG_FILE, G_KEY_FILE_NONE, &error) &&
618 !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
619 g_warning ("Failed to load configuration from %s: %s", USER_CONFIG_FILE, error->message); // FIXME: Don't make warning on no file, just info
620 g_clear_error (&error);
622 if (g_key_file_has_key (config, "UserAccounts", "minimum-uid", NULL))
623 minimum_uid = g_key_file_get_integer (config, "UserAccounts", "minimum-uid", NULL);
627 value = g_key_file_get_string (config, "UserAccounts", "hidden-users", NULL);
629 value = g_strdup ("nobody nobody4 noaccess");
630 hidden_users = g_strsplit (value, " ", -1);
633 value = g_key_file_get_string (config, "UserAccounts", "hidden-shells", NULL);
635 value = g_strdup ("/bin/false /usr/sbin/nologin");
636 hidden_shells = g_strsplit (value, " ", -1);
639 g_key_file_free (config);
645 struct passwd *entry;
648 gchar *real_name, *image_path, *image;
656 /* Ignore system users */
657 if (entry->pw_uid < minimum_uid)
660 /* Ignore users disabled by shell */
663 for (i = 0; hidden_shells[i] && strcmp (entry->pw_shell, hidden_shells[i]) != 0; i++);
664 if (hidden_shells[i])
668 /* Ignore certain users */
669 for (i = 0; hidden_users[i] && strcmp (entry->pw_name, hidden_users[i]) != 0; i++);
673 tokens = g_strsplit (entry->pw_gecos, ",", -1);
674 if (tokens[0] != NULL && tokens[0][0] != '\0')
675 real_name = g_strdup (tokens[0]);
680 image_path = g_build_filename (entry->pw_dir, ".face", NULL);
681 if (!g_file_test (image_path, G_FILE_TEST_EXISTS))
684 image_path = g_build_filename (entry->pw_dir, ".face.icon", NULL);
685 if (!g_file_test (image_path, G_FILE_TEST_EXISTS))
692 image = g_filename_to_uri (image_path, NULL, NULL);
697 user = ldm_user_new (greeter, entry->pw_name, real_name, entry->pw_dir, image, FALSE);
701 /* Update existing users if have them */
702 for (link = priv->users; link; link = link->next)
704 LdmUser *info = link->data;
705 if (strcmp (ldm_user_get_name (info), ldm_user_get_name (user)) == 0)
707 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)))
708 changed_users = g_list_insert_sorted (changed_users, info, compare_user);
709 g_object_unref (user);
716 /* Only notify once we have loaded the user list */
717 if (priv->have_users)
718 new_users = g_list_insert_sorted (new_users, user, compare_user);
720 users = g_list_insert_sorted (users, user, compare_user);
722 g_strfreev (hidden_users);
723 g_strfreev (hidden_shells);
726 g_warning ("Failed to read password database: %s", strerror (errno));
730 /* Use new user list */
731 old_users = priv->users;
734 /* Notify of changes */
735 for (link = new_users; link; link = link->next)
737 LdmUser *info = link->data;
738 g_debug ("User %s added", ldm_user_get_name (info));
739 g_signal_emit (greeter, signals[USER_ADDED], 0, info);
741 g_list_free (new_users);
742 for (link = changed_users; link; link = link->next)
744 LdmUser *info = link->data;
745 g_debug ("User %s changed", ldm_user_get_name (info));
746 g_signal_emit (greeter, signals[USER_CHANGED], 0, info);
748 g_list_free (changed_users);
749 for (link = old_users; link; link = link->next)
753 /* See if this user is in the current list */
754 for (new_link = priv->users; new_link; new_link = new_link->next)
756 if (new_link->data == link->data)
762 LdmUser *info = link->data;
763 g_debug ("User %s removed", ldm_user_get_name (info));
764 g_signal_emit (greeter, signals[USER_REMOVED], 0, info);
765 g_object_unref (info);
768 g_list_free (old_users);
772 passwd_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, LdmGreeter *greeter)
774 if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
776 g_debug ("%s changed, reloading user list", g_file_get_path (file));
777 load_users (greeter);
782 update_users (LdmGreeter *greeter)
784 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
786 GError *error = NULL;
788 if (priv->have_users)
791 load_users (greeter);
793 /* Watch for changes to user list */
794 passwd_file = g_file_new_for_path (PASSWD_FILE);
795 priv->passwd_monitor = g_file_monitor (passwd_file, G_FILE_MONITOR_NONE, NULL, &error);
796 g_object_unref (passwd_file);
797 if (!priv->passwd_monitor)
798 g_warning ("Error monitoring %s: %s", PASSWD_FILE, error->message);
800 g_signal_connect (priv->passwd_monitor, "changed", G_CALLBACK (passwd_changed_cb), greeter);
801 g_clear_error (&error);
803 priv->have_users = TRUE;
807 * ldm_greeter_get_num_users:
808 * @greeter: a #LdmGreeter
810 * Return value: The number of users able to log in
813 ldm_greeter_get_num_users (LdmGreeter *greeter)
815 g_return_val_if_fail (LDM_IS_GREETER (greeter), 0);
816 update_users (greeter);
817 return g_list_length (GET_PRIVATE (greeter)->users);
821 * ldm_greeter_get_users:
822 * @greeter: A #LdmGreeter
824 * Get a list of users to present to the user. This list may be a subset of the
825 * available users and may be empty depending on the server configuration.
827 * Return value: (element-type LdmUser) (transfer none): A list of #LdmUser that should be presented to the user.
830 ldm_greeter_get_users (LdmGreeter *greeter)
832 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
833 update_users (greeter);
834 return GET_PRIVATE (greeter)->users;
838 * ldm_greeter_get_user_by_name:
839 * @greeter: A #LdmGreeter
840 * @username: Name of user to get.
842 * Get infomation about a given user or NULL if this user doesn't exist.
844 * Return value: (transfer none): A #LdmUser entry for the given user.
847 ldm_greeter_get_user_by_name (LdmGreeter *greeter, const gchar *username)
849 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
850 g_return_val_if_fail (username != NULL, NULL);
852 update_users (greeter);
854 return get_user_by_name (greeter, username);
858 update_languages (LdmGreeter *greeter)
860 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
861 gchar *stdout_text = NULL, *stderr_text = NULL;
864 GError *error = NULL;
866 if (priv->have_languages)
869 result = g_spawn_command_line_sync ("locale -a", &stdout_text, &stderr_text, &exit_status, &error);
870 if (!result || exit_status != 0)
871 g_warning ("Failed to get languages, locale -a returned %d: %s", exit_status, error->message);
877 tokens = g_strsplit_set (stdout_text, "\n\r", -1);
878 for (i = 0; tokens[i]; i++)
880 LdmLanguage *language;
883 code = g_strchug (tokens[i]);
887 /* Ignore the non-interesting languages */
888 if (strcmp (code, "C") == 0 || strcmp (code, "POSIX") == 0)
891 language = ldm_language_new (code);
892 priv->languages = g_list_append (priv->languages, language);
898 g_clear_error (&error);
899 g_free (stdout_text);
900 g_free (stderr_text);
902 priv->have_languages = TRUE;
906 * ldm_greeter_get_default_language:
907 * @greeter: A #LdmGreeter
909 * Get the default language.
911 * Return value: The default language.
914 ldm_greeter_get_default_language (LdmGreeter *greeter)
917 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
918 lang = getenv ("LANG");
926 * ldm_greeter_get_languages:
927 * @greeter: A #LdmGreeter
929 * Get a list of languages to present to the user.
931 * Return value: (element-type LdmLanguage) (transfer none): A list of #LdmLanguage that should be presented to the user.
934 ldm_greeter_get_languages (LdmGreeter *greeter)
936 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
937 update_languages (greeter);
938 return GET_PRIVATE (greeter)->languages;
942 layout_cb (XklConfigRegistry *config,
943 const XklConfigItem *item,
946 LdmGreeter *greeter = data;
947 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
950 layout = ldm_layout_new (item->name, item->short_description, item->description);
951 priv->layouts = g_list_append (priv->layouts, layout);
955 setup_display (LdmGreeter *greeter)
957 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
959 priv->display = XOpenDisplay (NULL);
963 setup_xkl (LdmGreeter *greeter)
965 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
967 setup_display (greeter);
969 priv->xkl_engine = xkl_engine_get_instance (priv->display);
970 priv->xkl_config = xkl_config_rec_new ();
971 if (!xkl_config_rec_get_from_server (priv->xkl_config, priv->xkl_engine))
972 g_warning ("Failed to get Xkl configuration from server");
973 priv->layout = g_strdup (priv->xkl_config->layouts[0]);
977 * ldm_greeter_get_layouts:
978 * @greeter: A #LdmGreeter
980 * Get a list of keyboard layouts to present to the user.
982 * Return value: (element-type LdmLayout) (transfer none): A list of #LdmLayout that should be presented to the user.
985 ldm_greeter_get_layouts (LdmGreeter *greeter)
987 LdmGreeterPrivate *priv;
988 XklConfigRegistry *registry;
990 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
992 priv = GET_PRIVATE (greeter);
994 if (priv->have_layouts)
995 return priv->layouts;
999 registry = xkl_config_registry_get_instance (priv->xkl_engine);
1000 xkl_config_registry_load (registry, FALSE);
1001 xkl_config_registry_foreach_layout (registry, layout_cb, greeter);
1002 g_object_unref (registry);
1003 priv->have_layouts = TRUE;
1005 return priv->layouts;
1009 * ldm_greeter_set_layout:
1010 * @greeter: A #LdmGreeter
1011 * @layout: The layout to use
1013 * Set the layout for this session.
1016 ldm_greeter_set_layout (LdmGreeter *greeter, const gchar *layout)
1018 LdmGreeterPrivate *priv;
1019 XklConfigRec *config;
1021 g_return_if_fail (LDM_IS_GREETER (greeter));
1022 g_return_if_fail (layout != NULL);
1024 priv = GET_PRIVATE (greeter);
1026 g_debug ("Setting keyboard layout to %s", layout);
1028 setup_xkl (greeter);
1030 config = xkl_config_rec_new ();
1031 config->layouts = g_malloc (sizeof (gchar *) * 2);
1032 config->model = g_strdup (priv->xkl_config->model);
1033 config->layouts[0] = g_strdup (layout);
1034 config->layouts[1] = NULL;
1035 if (!xkl_config_rec_activate (config, priv->xkl_engine))
1036 g_warning ("Failed to activate XKL config");
1038 priv->layout = g_strdup (layout);
1039 g_object_unref (config);
1043 * ldm_greeter_get_layout:
1044 * @greeter: A #LdmGreeter
1046 * Get the current keyboard layout.
1048 * Return value: The currently active layout for this user.
1051 ldm_greeter_get_layout (LdmGreeter *greeter)
1053 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1054 setup_xkl (greeter);
1055 return GET_PRIVATE (greeter)->layout;
1059 update_sessions (LdmGreeter *greeter)
1061 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
1063 GError *error = NULL;
1065 if (priv->have_sessions)
1068 directory = g_dir_open (XSESSIONS_DIR, 0, &error);
1070 g_warning ("Failed to open sessions directory: %s", error->message);
1071 g_clear_error (&error);
1077 const gchar *filename;
1082 filename = g_dir_read_name (directory);
1083 if (filename == NULL)
1086 if (!g_str_has_suffix (filename, ".desktop"))
1089 key = g_strndup (filename, strlen (filename) - strlen (".desktop"));
1090 path = g_build_filename (XSESSIONS_DIR, filename, NULL);
1091 g_debug ("Loading session %s", path);
1093 key_file = g_key_file_new ();
1094 result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
1096 g_warning ("Failed to load session file %s: %s:", path, error->message);
1097 g_clear_error (&error);
1099 if (result && !g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, NULL))
1101 gchar *domain, *name, *comment;
1103 #ifdef G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN
1104 domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN, NULL);
1106 domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL);
1108 name = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, domain, NULL);
1109 comment = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, domain, NULL);
1111 comment = g_strdup ("");
1114 g_debug ("Loaded session %s (%s, %s)", key, name, comment);
1115 priv->sessions = g_list_append (priv->sessions, ldm_session_new (key, name, comment));
1118 g_warning ("Invalid session %s: %s", path, error->message);
1126 g_key_file_free (key_file);
1129 g_dir_close (directory);
1131 priv->have_sessions = TRUE;
1135 * ldm_greeter_get_sessions:
1136 * @greeter: A #LdmGreeter
1138 * Get the available sessions.
1140 * Return value: (element-type LdmSession) (transfer none): A list of #LdmSession
1143 ldm_greeter_get_sessions (LdmGreeter *greeter)
1145 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1146 update_sessions (greeter);
1147 return GET_PRIVATE (greeter)->sessions;
1151 * ldm_greeter_get_hint:
1152 * @greeter: A #LdmGreeter
1153 * @name: The hint name to query.
1157 * Return value: The value for this hint or NULL if not set.
1160 ldm_greeter_get_hint (LdmGreeter *greeter, const gchar *name)
1162 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1163 return g_hash_table_lookup (GET_PRIVATE (greeter)->hints, name);
1167 * ldm_greeter_get_default_session_hint:
1168 * @greeter: A #LdmGreeter
1170 * Get the default session to use.
1172 * Return value: The session name
1175 ldm_greeter_get_default_session_hint (LdmGreeter *greeter)
1177 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1178 return ldm_greeter_get_hint (greeter, "default-session");
1182 * ldm_greeter_get_hide_users_hint:
1183 * @greeter: A #LdmGreeter
1185 * Check if user accounts should be shown.
1187 * Return value: TRUE if the available users should not be shown.
1190 ldm_greeter_get_hide_users_hint (LdmGreeter *greeter)
1194 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1195 value = ldm_greeter_get_hint (greeter, "hide-users");
1197 return g_strcmp0 (value, "true") == 0;
1201 * ldm_greeter_get_has_guest_account_hint:
1202 * @greeter: A #LdmGreeter
1204 * Check if guest sessions are supported.
1206 * Return value: TRUE if guest sessions are supported.
1209 ldm_greeter_get_has_guest_account_hint (LdmGreeter *greeter)
1213 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1214 value = ldm_greeter_get_hint (greeter, "has-guest-account");
1216 return g_strcmp0 (value, "true") == 0;
1220 * ldm_greeter_get_select_user_hint:
1221 * @greeter: A #LdmGreeter
1223 * Get the user to select by default.
1225 * Return value: A username
1228 ldm_greeter_get_select_user_hint (LdmGreeter *greeter)
1230 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1231 return ldm_greeter_get_hint (greeter, "select-user");
1235 * ldm_greeter_get_select_guest_hint:
1236 * @greeter: A #LdmGreeter
1238 * Check if the guest account should be selected by default.
1240 * Return value: TRUE if the guest account should be selected by default.
1243 ldm_greeter_get_select_guest_hint (LdmGreeter *greeter)
1247 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1248 value = ldm_greeter_get_hint (greeter, "select-guest");
1250 return g_strcmp0 (value, "true") == 0;
1254 * ldm_greeter_get_autologin_user_hint:
1255 * @greeter: A #LdmGreeter
1257 * Get the user account to automatically logg into when the timer expires.
1259 * Return value: The user account to automatically log into.
1262 ldm_greeter_get_autologin_user_hint (LdmGreeter *greeter)
1264 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1265 return ldm_greeter_get_hint (greeter, "autologin-user");
1269 * ldm_greeter_get_autologin_guest_hint:
1270 * @greeter: A #LdmGreeter
1272 * Check if the guest account should be automatically logged into when the timer expires.
1274 * Return value: TRUE if the guest account should be automatically logged into.
1277 ldm_greeter_get_autologin_guest_hint (LdmGreeter *greeter)
1281 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1282 value = ldm_greeter_get_hint (greeter, "autologin-guest");
1284 return g_strcmp0 (value, "true") == 0;
1288 * ldm_greeter_get_autologin_timeout_hint:
1289 * @greeter: A #LdmGreeter
1291 * Get the number of seconds to wait before automaitcally logging in.
1293 * Return value: The number of seconds to wait before automatically logging in or 0 for no timeout.
1296 ldm_greeter_get_autologin_timeout_hint (LdmGreeter *greeter)
1301 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1302 value = ldm_greeter_get_hint (greeter, "autologin-timeout");
1304 timeout = atoi (value);
1312 * ldm_greeter_cancel_timed_login:
1313 * @greeter: A #LdmGreeter
1315 * Cancel the login as the default user.
1318 ldm_greeter_cancel_timed_login (LdmGreeter *greeter)
1320 LdmGreeterPrivate *priv;
1322 g_return_if_fail (LDM_IS_GREETER (greeter));
1324 priv = GET_PRIVATE (greeter);
1326 if (priv->login_timeout)
1327 g_source_remove (priv->login_timeout);
1328 priv->login_timeout = 0;
1332 * ldm_greeter_login:
1333 * @greeter: A #LdmGreeter
1334 * @username: (allow-none): A username or NULL to prompt for a username.
1336 * Starts the authentication procedure for a user.
1339 ldm_greeter_login (LdmGreeter *greeter, const char *username)
1341 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
1342 guint8 message[MAX_MESSAGE_LENGTH];
1345 g_return_if_fail (LDM_IS_GREETER (greeter));
1350 priv->cancelling_authentication = FALSE;
1351 priv->authenticate_sequence_number++;
1352 priv->in_authentication = TRUE;
1353 priv->is_authenticated = FALSE;
1354 g_free (priv->authentication_user);
1355 priv->authentication_user = g_strdup (username);
1357 g_debug ("Starting authentication for user %s...", username);
1358 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_LOGIN, int_length () + string_length (username), &offset);
1359 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1360 write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
1361 write_message (greeter, message, offset);
1365 * ldm_greeter_login_with_user_prompt:
1366 * @greeter: A #LdmGreeter
1368 * Starts the authentication procedure, prompting the greeter for a username.
1371 ldm_greeter_login_with_user_prompt (LdmGreeter *greeter)
1373 ldm_greeter_login (greeter, NULL);
1377 * ldm_greeter_login_as_guest:
1378 * @greeter: A #LdmGreeter
1380 * Starts the authentication procedure for the guest user.
1383 ldm_greeter_login_as_guest (LdmGreeter *greeter)
1385 LdmGreeterPrivate *priv;
1386 guint8 message[MAX_MESSAGE_LENGTH];
1389 g_return_if_fail (LDM_IS_GREETER (greeter));
1391 priv = GET_PRIVATE (greeter);
1393 priv->cancelling_authentication = FALSE;
1394 priv->authenticate_sequence_number++;
1395 priv->in_authentication = TRUE;
1396 priv->is_authenticated = FALSE;
1397 g_free (priv->authentication_user);
1398 priv->authentication_user = NULL;
1400 g_debug ("Starting authentication for guest account...");
1401 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_LOGIN_AS_GUEST, int_length (), &offset);
1402 write_int (message, MAX_MESSAGE_LENGTH, priv->authenticate_sequence_number, &offset);
1403 write_message (greeter, message, offset);
1407 * ldm_greeter_respond:
1408 * @greeter: A #LdmGreeter
1409 * @response: Response to a prompt
1411 * Provide response to a prompt.
1414 ldm_greeter_respond (LdmGreeter *greeter, const gchar *response)
1416 guint8 message[MAX_MESSAGE_LENGTH];
1419 g_return_if_fail (LDM_IS_GREETER (greeter));
1420 g_return_if_fail (response != NULL);
1422 g_debug ("Providing response to display manager");
1423 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, int_length () + string_length (response), &offset);
1424 // FIXME: Could be multiple responses required
1425 write_int (message, MAX_MESSAGE_LENGTH, 1, &offset);
1426 write_string (message, MAX_MESSAGE_LENGTH, response, &offset);
1427 write_message (greeter, message, offset);
1431 * ldm_greeter_cancel_authentication:
1432 * @greeter: A #LdmGreeter
1434 * Cancel the current user authentication.
1437 ldm_greeter_cancel_authentication (LdmGreeter *greeter)
1439 LdmGreeterPrivate *priv;
1440 guint8 message[MAX_MESSAGE_LENGTH];
1443 g_return_if_fail (LDM_IS_GREETER (greeter));
1445 priv = GET_PRIVATE (greeter);
1447 priv->cancelling_authentication = TRUE;
1448 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CANCEL_AUTHENTICATION, 0, &offset);
1449 write_message (greeter, message, offset);
1453 * ldm_greeter_get_in_authentication:
1454 * @greeter: A #LdmGreeter
1456 * Checks if the greeter is in the process of authenticating.
1458 * Return value: TRUE if the greeter is authenticating a user.
1461 ldm_greeter_get_in_authentication (LdmGreeter *greeter)
1463 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1464 return GET_PRIVATE (greeter)->in_authentication;
1468 * ldm_greeter_get_is_authenticated:
1469 * @greeter: A #LdmGreeter
1471 * Checks if the greeter has successfully authenticated.
1473 * Return value: TRUE if the greeter is authenticated for login.
1476 ldm_greeter_get_is_authenticated (LdmGreeter *greeter)
1478 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1479 return GET_PRIVATE (greeter)->is_authenticated;
1483 * ldm_greeter_get_authentication_user:
1484 * @greeter: A #LdmGreeter
1486 * Get the user that is being authenticated.
1488 * Return value: The username of the authentication user being authenticated or NULL if no authentication in progress.
1491 ldm_greeter_get_authentication_user (LdmGreeter *greeter)
1493 g_return_val_if_fail (LDM_IS_GREETER (greeter), NULL);
1494 return GET_PRIVATE (greeter)->authentication_user;
1498 * ldm_greeter_start_session:
1499 * @greeter: A #LdmGreeter
1500 * @session: (allow-none): The session to log into or NULL to use the default
1502 * Start a session for the logged in user.
1505 ldm_greeter_start_session (LdmGreeter *greeter, const gchar *session)
1507 guint8 message[MAX_MESSAGE_LENGTH];
1510 g_return_if_fail (LDM_IS_GREETER (greeter));
1515 g_debug ("Starting session %s", session);
1516 write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset);
1517 write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
1518 write_message (greeter, message, offset);
1522 * ldm_greeter_start_session_with_defaults:
1523 * @greeter: A #LdmGreeter
1525 * Login a user to a session using default settings for that user.
1528 ldm_greeter_start_default_session (LdmGreeter *greeter)
1530 ldm_greeter_start_session (greeter, NULL);
1534 upower_call_function (LdmGreeter *greeter, const gchar *function, gboolean has_result)
1536 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
1539 GError *error = NULL;
1540 gboolean function_result = FALSE;
1542 if (!priv->system_bus)
1545 proxy = g_dbus_proxy_new_sync (priv->system_bus,
1546 G_DBUS_PROXY_FLAGS_NONE,
1548 "org.freedesktop.UPower",
1549 "/org/freedesktop/UPower",
1550 "org.freedesktop.UPower",
1552 result = g_dbus_proxy_call_sync (proxy,
1555 G_DBUS_CALL_FLAGS_NONE,
1559 g_object_unref (proxy);
1562 g_warning ("Error calling UPower function %s: %s", function, error->message);
1563 g_clear_error (&error);
1567 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(b)")))
1568 g_variant_get (result, "(b)", &function_result);
1570 g_variant_unref (result);
1571 return function_result;
1575 * ldm_greeter_get_can_suspend:
1576 * @greeter: A #LdmGreeter
1578 * Checks if the greeter is authorized to do a system suspend.
1580 * Return value: TRUE if the greeter can suspend the system
1583 ldm_greeter_get_can_suspend (LdmGreeter *greeter)
1585 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1586 return upower_call_function (greeter, "SuspendAllowed", TRUE);
1590 * ldm_greeter_suspend:
1591 * @greeter: A #LdmGreeter
1593 * Triggers a system suspend.
1596 ldm_greeter_suspend (LdmGreeter *greeter)
1598 g_return_if_fail (LDM_IS_GREETER (greeter));
1599 upower_call_function (greeter, "Suspend", FALSE);
1603 * ldm_greeter_get_can_hibernate:
1604 * @greeter: A #LdmGreeter
1606 * Checks if the greeter is authorized to do a system hibernate.
1608 * Return value: TRUE if the greeter can hibernate the system
1611 ldm_greeter_get_can_hibernate (LdmGreeter *greeter)
1613 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1614 return upower_call_function (greeter, "HibernateAllowed", TRUE);
1618 * ldm_greeter_hibernate:
1619 * @greeter: A #LdmGreeter
1621 * Triggers a system hibernate.
1624 ldm_greeter_hibernate (LdmGreeter *greeter)
1626 g_return_if_fail (LDM_IS_GREETER (greeter));
1627 upower_call_function (greeter, "Hibernate", FALSE);
1631 ck_call_function (LdmGreeter *greeter, const gchar *function, gboolean has_result)
1633 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
1636 GError *error = NULL;
1637 gboolean function_result = FALSE;
1639 if (!priv->system_bus)
1642 proxy = g_dbus_proxy_new_sync (priv->system_bus,
1643 G_DBUS_PROXY_FLAGS_NONE,
1645 "org.freedesktop.ConsoleKit",
1646 "/org/freedesktop/ConsoleKit/Manager",
1647 "org.freedesktop.ConsoleKit.Manager",
1649 result = g_dbus_proxy_call_sync (proxy,
1652 G_DBUS_CALL_FLAGS_NONE,
1656 g_object_unref (proxy);
1659 g_warning ("Error calling ConsoleKit function %s: %s", function, error->message);
1660 g_clear_error (&error);
1664 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(b)")))
1665 g_variant_get (result, "(b)", &function_result);
1667 g_variant_unref (result);
1668 return function_result;
1672 * ldm_greeter_get_can_restart:
1673 * @greeter: A #LdmGreeter
1675 * Checks if the greeter is authorized to do a system restart.
1677 * Return value: TRUE if the greeter can restart the system
1680 ldm_greeter_get_can_restart (LdmGreeter *greeter)
1682 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1683 return ck_call_function (greeter, "CanRestart", TRUE);
1687 * ldm_greeter_restart:
1688 * @greeter: A #LdmGreeter
1690 * Triggers a system restart.
1693 ldm_greeter_restart (LdmGreeter *greeter)
1695 g_return_if_fail (LDM_IS_GREETER (greeter));
1696 ck_call_function (greeter, "Restart", FALSE);
1700 * ldm_greeter_get_can_shutdown:
1701 * @greeter: A #LdmGreeter
1703 * Checks if the greeter is authorized to do a system shutdown.
1705 * Return value: TRUE if the greeter can shutdown the system
1708 ldm_greeter_get_can_shutdown (LdmGreeter *greeter)
1710 g_return_val_if_fail (LDM_IS_GREETER (greeter), FALSE);
1711 return ck_call_function (greeter, "CanStop", TRUE);
1715 * ldm_greeter_shutdown:
1716 * @greeter: A #LdmGreeter
1718 * Triggers a system shutdown.
1721 ldm_greeter_shutdown (LdmGreeter *greeter)
1723 g_return_if_fail (LDM_IS_GREETER (greeter));
1724 ck_call_function (greeter, "Stop", FALSE);
1728 ldm_greeter_init (LdmGreeter *greeter)
1730 LdmGreeterPrivate *priv = GET_PRIVATE (greeter);
1732 priv->read_buffer = g_malloc (HEADER_SIZE);
1733 priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1735 g_debug ("default-language=%s", ldm_greeter_get_default_language (greeter));
1739 ldm_greeter_set_property (GObject *object,
1741 const GValue *value,
1746 self = LDM_GREETER (object);
1750 ldm_greeter_set_layout(self, g_value_get_string (value));
1753 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1759 ldm_greeter_get_property (GObject *object,
1766 self = LDM_GREETER (object);
1770 g_value_set_string (value, ldm_greeter_get_hostname (self));
1772 case PROP_NUM_USERS:
1773 g_value_set_int (value, ldm_greeter_get_num_users (self));
1777 case PROP_DEFAULT_LANGUAGE:
1778 g_value_set_string (value, ldm_greeter_get_default_language (self));
1783 g_value_set_string (value, ldm_greeter_get_layout (self));
1787 case PROP_DEFAULT_SESSION_HINT:
1788 g_value_set_string (value, ldm_greeter_get_default_session_hint (self));
1790 case PROP_HIDE_USERS_HINT:
1791 g_value_set_boolean (value, ldm_greeter_get_hide_users_hint (self));
1793 case PROP_HAS_GUEST_ACCOUNT_HINT:
1794 g_value_set_boolean (value, ldm_greeter_get_has_guest_account_hint (self));
1796 case PROP_SELECT_USER_HINT:
1797 g_value_set_string (value, ldm_greeter_get_select_user_hint (self));
1799 case PROP_SELECT_GUEST_HINT:
1800 g_value_set_boolean (value, ldm_greeter_get_select_guest_hint (self));
1802 case PROP_AUTOLOGIN_USER_HINT:
1803 g_value_set_string (value, ldm_greeter_get_autologin_user_hint (self));
1805 case PROP_AUTOLOGIN_GUEST_HINT:
1806 g_value_set_boolean (value, ldm_greeter_get_autologin_guest_hint (self));
1808 case PROP_AUTOLOGIN_TIMEOUT_HINT:
1809 g_value_set_int (value, ldm_greeter_get_autologin_timeout_hint (self));
1811 case PROP_AUTHENTICATION_USER:
1812 g_value_set_string (value, ldm_greeter_get_authentication_user (self));
1814 case PROP_IN_AUTHENTICATION:
1815 g_value_set_boolean (value, ldm_greeter_get_in_authentication (self));
1817 case PROP_IS_AUTHENTICATED:
1818 g_value_set_boolean (value, ldm_greeter_get_is_authenticated (self));
1820 case PROP_CAN_SUSPEND:
1821 g_value_set_boolean (value, ldm_greeter_get_can_suspend (self));
1823 case PROP_CAN_HIBERNATE:
1824 g_value_set_boolean (value, ldm_greeter_get_can_hibernate (self));
1826 case PROP_CAN_RESTART:
1827 g_value_set_boolean (value, ldm_greeter_get_can_restart (self));
1829 case PROP_CAN_SHUTDOWN:
1830 g_value_set_boolean (value, ldm_greeter_get_can_shutdown (self));
1833 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1839 marshal_VOID__STRING_INT (GClosure *closure,
1840 GValue *return_value G_GNUC_UNUSED,
1841 guint n_param_values,
1842 const GValue *param_values,
1843 gpointer invocation_hint G_GNUC_UNUSED,
1844 gpointer marshal_data)
1846 typedef void (*GMarshalFunc_VOID__STRING_INT) (gpointer data1,
1850 register GMarshalFunc_VOID__STRING_INT callback;
1851 register GCClosure *cc = (GCClosure*) closure;
1852 register gpointer data1, data2;
1854 g_return_if_fail (n_param_values == 3);
1856 if (G_CCLOSURE_SWAP_DATA (closure))
1858 data1 = closure->data;
1859 data2 = g_value_peek_pointer (param_values + 0);
1863 data1 = g_value_peek_pointer (param_values + 0);
1864 data2 = closure->data;
1866 callback = (GMarshalFunc_VOID__STRING_INT) (marshal_data ? marshal_data : cc->callback);
1869 (param_values + 1)->data[0].v_pointer,
1870 (param_values + 2)->data[0].v_int,
1875 ldm_greeter_finalize (GObject *object)
1877 LdmGreeter *self = LDM_GREETER (object);
1878 LdmGreeterPrivate *priv = GET_PRIVATE (self);
1880 g_hash_table_unref (priv->hints);
1882 G_OBJECT_CLASS (ldm_greeter_parent_class)->finalize (object);
1886 ldm_greeter_class_init (LdmGreeterClass *klass)
1888 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1890 g_type_class_add_private (klass, sizeof (LdmGreeterPrivate));
1892 object_class->set_property = ldm_greeter_set_property;
1893 object_class->get_property = ldm_greeter_get_property;
1894 object_class->finalize = ldm_greeter_finalize;
1896 g_object_class_install_property (object_class,
1898 g_param_spec_string ("hostname",
1900 "Hostname displaying greeter for",
1903 g_object_class_install_property (object_class,
1905 g_param_spec_int ("num-users",
1907 "Number of login users",
1910 /*g_object_class_install_property (object_class,
1912 g_param_spec_list ("users",
1914 "Users that can login"));
1915 g_object_class_install_property (object_class,
1916 PROP_DEFAULT_LANGUAGE,
1917 g_param_spec_string ("default-language",
1921 G_PARAM_READWRITE));
1922 g_object_class_install_property (object_class,
1924 g_param_spec_list ("layouts",
1926 "Available keyboard layouts"));*/
1927 g_object_class_install_property (object_class,
1929 g_param_spec_string ("layout",
1931 "Current keyboard layout",
1933 G_PARAM_READWRITE));
1934 /*g_object_class_install_property (object_class,
1936 g_param_spec_list ("sessions",
1938 "Available sessions"));*/
1939 g_object_class_install_property (object_class,
1940 PROP_DEFAULT_SESSION_HINT,
1941 g_param_spec_string ("default-session-hint",
1942 "default-session-hint",
1943 "Default session hint",
1945 G_PARAM_READWRITE));
1947 g_object_class_install_property (object_class,
1948 PROP_HIDE_USERS_HINT,
1949 g_param_spec_boolean ("hide-users-hint",
1955 g_object_class_install_property (object_class,
1956 PROP_HAS_GUEST_ACCOUNT_HINT,
1957 g_param_spec_boolean ("has-guest-account-hint",
1958 "has-guest-account-hint",
1959 "Has guest account hint",
1963 g_object_class_install_property (object_class,
1964 PROP_SELECT_USER_HINT,
1965 g_param_spec_string ("select-user-hint",
1971 g_object_class_install_property (object_class,
1972 PROP_SELECT_GUEST_HINT,
1973 g_param_spec_boolean ("select-guest-hint",
1974 "select-guest-hint",
1975 "Select guest account hint",
1979 g_object_class_install_property (object_class,
1980 PROP_AUTOLOGIN_USER_HINT,
1981 g_param_spec_string ("autologin-user-hint",
1982 "autologin-user-hint",
1983 "Autologin user hint",
1987 g_object_class_install_property (object_class,
1988 PROP_AUTOLOGIN_GUEST_HINT,
1989 g_param_spec_boolean ("autologin-guest-hint",
1990 "autologin-guest-hint",
1991 "Autologin guest account hint",
1995 g_object_class_install_property (object_class,
1996 PROP_AUTOLOGIN_TIMEOUT_HINT,
1997 g_param_spec_int ("autologin-timeout-hint",
1998 "autologin-timeout-hint",
1999 "Autologin timeout hint",
2003 g_object_class_install_property (object_class,
2004 PROP_AUTHENTICATION_USER,
2005 g_param_spec_string ("authentication-user",
2006 "authentication-user",
2007 "The user being authenticated",
2010 g_object_class_install_property (object_class,
2011 PROP_IN_AUTHENTICATION,
2012 g_param_spec_boolean ("in-authentication",
2013 "in-authentication",
2014 "TRUE if a user is being authenticated",
2017 g_object_class_install_property (object_class,
2018 PROP_IS_AUTHENTICATED,
2019 g_param_spec_boolean ("is-authenticated",
2021 "TRUE if the selected user is authenticated",
2024 g_object_class_install_property (object_class,
2026 g_param_spec_boolean ("can-suspend",
2028 "TRUE if allowed to suspend the system",
2031 g_object_class_install_property (object_class,
2033 g_param_spec_boolean ("can-hibernate",
2035 "TRUE if allowed to hibernate the system",
2038 g_object_class_install_property (object_class,
2040 g_param_spec_boolean ("can-restart",
2042 "TRUE if allowed to restart the system",
2045 g_object_class_install_property (object_class,
2047 g_param_spec_boolean ("can-shutdown",
2049 "TRUE if allowed to shutdown the system",
2054 * LdmGreeter::connected:
2055 * @greeter: A #LdmGreeter
2057 * The ::connected signal gets emitted when the greeter connects to the
2060 signals[CONNECTED] =
2061 g_signal_new ("connected",
2062 G_TYPE_FROM_CLASS (klass),
2064 G_STRUCT_OFFSET (LdmGreeterClass, connected),
2066 g_cclosure_marshal_VOID__VOID,
2070 * LdmGreeter::show-prompt:
2071 * @greeter: A #LdmGreeter
2072 * @text: Prompt text
2073 * @type: Prompt type
2075 * The ::show-prompt signal gets emitted when the greeter should show a
2076 * prompt to the user. The given text should be displayed and an input
2077 * field for the user to provide a response.
2079 * Call ldm_greeter_respond() with the resultant input or
2080 * ldm_greeter_cancel_authentication() to abort the authentication.
2082 signals[SHOW_PROMPT] =
2083 g_signal_new ("show-prompt",
2084 G_TYPE_FROM_CLASS (klass),
2086 G_STRUCT_OFFSET (LdmGreeterClass, show_prompt),
2088 marshal_VOID__STRING_INT,
2089 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
2092 * LdmGreeter::show-message:
2093 * @greeter: A #LdmGreeter
2094 * @text: Message text
2095 * @type: Message type
2097 * The ::show-message signal gets emitted when the greeter
2098 * should show a message to the user.
2100 signals[SHOW_MESSAGE] =
2101 g_signal_new ("show-message",
2102 G_TYPE_FROM_CLASS (klass),
2104 G_STRUCT_OFFSET (LdmGreeterClass, show_message),
2106 marshal_VOID__STRING_INT,
2107 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
2110 * LdmGreeter::authentication-complete:
2111 * @greeter: A #LdmGreeter
2113 * The ::authentication-complete signal gets emitted when the greeter
2114 * has completed authentication.
2116 * Call ldm_greeter_get_is_authenticated() to check if the authentication
2119 signals[AUTHENTICATION_COMPLETE] =
2120 g_signal_new ("authentication-complete",
2121 G_TYPE_FROM_CLASS (klass),
2123 G_STRUCT_OFFSET (LdmGreeterClass, authentication_complete),
2125 g_cclosure_marshal_VOID__VOID,
2129 * LdmGreeter::session-failed:
2130 * @greeter: A #LdmGreeter
2132 * The ::session-failed signal gets emitted when the deamon has failed
2133 * to start the requested session.
2135 signals[SESSION_FAILED] =
2136 g_signal_new ("session-failed",
2137 G_TYPE_FROM_CLASS (klass),
2139 G_STRUCT_OFFSET (LdmGreeterClass, session_failed),
2141 g_cclosure_marshal_VOID__VOID,
2145 * LdmGreeter::autologin-timer-expired:
2146 * @greeter: A #LdmGreeter
2147 * @username: A username
2149 * The ::timed-login signal gets emitted when the automatic login timer has expired.
2150 * The application should then call ldm_greeter_login().
2152 signals[AUTOLOGIN_TIMER_EXPIRED] =
2153 g_signal_new ("autologin-timer-expired",
2154 G_TYPE_FROM_CLASS (klass),
2156 G_STRUCT_OFFSET (LdmGreeterClass, autologin_timer_expired),
2158 g_cclosure_marshal_VOID__VOID,
2162 * LdmGreeter::user-added:
2163 * @greeter: A #LdmGreeter
2165 * The ::user-added signal gets emitted when a user account is created.
2167 signals[USER_ADDED] =
2168 g_signal_new ("user-added",
2169 G_TYPE_FROM_CLASS (klass),
2171 G_STRUCT_OFFSET (LdmGreeterClass, user_added),
2173 g_cclosure_marshal_VOID__OBJECT,
2174 G_TYPE_NONE, 1, LDM_TYPE_USER);
2177 * LdmGreeter::user-changed:
2178 * @greeter: A #LdmGreeter
2180 * The ::user-changed signal gets emitted when a user account is modified.
2182 signals[USER_CHANGED] =
2183 g_signal_new ("user-changed",
2184 G_TYPE_FROM_CLASS (klass),
2186 G_STRUCT_OFFSET (LdmGreeterClass, user_changed),
2188 g_cclosure_marshal_VOID__OBJECT,
2189 G_TYPE_NONE, 1, LDM_TYPE_USER);
2192 * LdmGreeter::user-removed:
2193 * @greeter: A #LdmGreeter
2195 * The ::user-removed signal gets emitted when a user account is removed.
2197 signals[USER_REMOVED] =
2198 g_signal_new ("user-removed",
2199 G_TYPE_FROM_CLASS (klass),
2201 G_STRUCT_OFFSET (LdmGreeterClass, user_removed),
2203 g_cclosure_marshal_VOID__OBJECT,
2204 G_TYPE_NONE, 1, LDM_TYPE_USER);
2208 * @greeter: A #LdmGreeter
2210 * The ::quit signal gets emitted when the greeter should exit.
2213 g_signal_new ("quit",
2214 G_TYPE_FROM_CLASS (klass),
2216 G_STRUCT_OFFSET (LdmGreeterClass, quit),
2218 g_cclosure_marshal_VOID__VOID,