/* * Copyright (C) 2010 Robert Ancell. * Author: Robert Ancell * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) any * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the * license. */ #include #include #include "lightdm/session.h" enum { PROP_0, PROP_KEY, PROP_NAME, PROP_COMMENT }; typedef struct { gchar *key; gchar *name; gchar *comment; } LightDMSessionPrivate; G_DEFINE_TYPE (LightDMSession, lightdm_session, G_TYPE_OBJECT); #define GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_SESSION, LightDMSessionPrivate) static gboolean have_sessions = FALSE; static GList *sessions = NULL; static gint compare_session (gconstpointer a, gconstpointer b) { LightDMSessionPrivate *priv_a = GET_PRIVATE (a); LightDMSessionPrivate *priv_b = GET_PRIVATE (b); return strcmp (priv_a->name, priv_b->name); } static LightDMSession * load_session (GKeyFile *key_file, const gchar *key) { gchar *domain, *name; LightDMSession *session; LightDMSessionPrivate *priv; gchar *try_exec; if (g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY, NULL) || g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_HIDDEN, NULL)) return NULL; #ifdef G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_GETTEXT_DOMAIN, NULL); #else domain = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL); #endif name = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_NAME, domain, NULL); if (!name) { g_warning ("Ignoring session without name"); g_free (domain); return NULL; } try_exec = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_TRY_EXEC, domain, NULL); if (try_exec) { gchar *full_path; full_path = g_find_program_in_path (try_exec); g_free (try_exec); if (!full_path) { g_free (name); g_free (domain); return NULL; } g_free (full_path); } session = g_object_new (LIGHTDM_TYPE_SESSION, NULL); priv = GET_PRIVATE (session); g_free (priv->key); priv->key = g_strdup (key); g_free (priv->name); priv->name = name; g_free (priv->comment); priv->comment = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_COMMENT, domain, NULL); if (!priv->comment) priv->comment = g_strdup (""); sessions = g_list_insert_sorted (sessions, session, compare_session); g_free (domain); return session; } static void update_sessions (void) { GDir *directory; gboolean result; GError *error = NULL; GKeyFile *config_key_file = NULL; gchar *config_path = NULL; gchar *xsessions_dir = g_strdup (XSESSIONS_DIR); if (have_sessions) return; config_path = g_build_filename (CONFIG_DIR, "lightdm.conf", NULL); config_key_file = g_key_file_new (); result = g_key_file_load_from_file (config_key_file, config_path, G_KEY_FILE_NONE, &error); if (error) g_warning ("Failed to open configuration file: %s", error->message); g_clear_error (&error); if (result) { gchar *xd_value = g_key_file_get_string (config_key_file, "LightDM", "xsessions-directory", NULL); if (xd_value) { g_free (xsessions_dir); xsessions_dir = xd_value; } } g_key_file_free (config_key_file); g_free (config_path); directory = g_dir_open (xsessions_dir, 0, &error); if (error) g_warning ("Failed to open sessions directory: %s", error->message); g_clear_error (&error); if (!directory) { g_free (xsessions_dir); return; } while (TRUE) { const gchar *filename; gchar *path; GKeyFile *key_file; gboolean result; filename = g_dir_read_name (directory); if (filename == NULL) break; if (!g_str_has_suffix (filename, ".desktop")) continue; path = g_build_filename (xsessions_dir, filename, NULL); key_file = g_key_file_new (); result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error); if (error) g_warning ("Failed to load session file %s: %s:", path, error->message); g_clear_error (&error); if (result) { gchar *key; LightDMSession *session; key = g_strndup (filename, strlen (filename) - strlen (".desktop")); session = load_session (key_file, key); if (session) g_debug ("Loaded session %s (%s, %s)", path, GET_PRIVATE (session)->name, GET_PRIVATE (session)->comment); else g_debug ("Ignoring session %s", path); g_free (key); } g_free (path); g_key_file_free (key_file); } g_dir_close (directory); g_free (xsessions_dir); have_sessions = TRUE; } /** * lightdm_get_sessions: * * Get the available sessions. * * Return value: (element-type LightDMSession) (transfer none): A list of #LightDMSession **/ GList * lightdm_get_sessions (void) { update_sessions (); return sessions; } /** * lightdm_session_get_key: * @session: A #LightDMSession * * Get the key for a session * * Return value: The session key **/ const gchar * lightdm_session_get_key (LightDMSession *session) { g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL); return GET_PRIVATE (session)->key; } /** * lightdm_session_get_name: * @session: A #LightDMSession * * Get the name for a session * * Return value: The session name **/ const gchar * lightdm_session_get_name (LightDMSession *session) { g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL); return GET_PRIVATE (session)->name; } /** * lightdm_session_get_comment: * @session: A #LightDMSession * * Get the comment for a session * * Return value: The session comment **/ const gchar * lightdm_session_get_comment (LightDMSession *session) { g_return_val_if_fail (LIGHTDM_IS_SESSION (session), NULL); return GET_PRIVATE (session)->comment; } static void lightdm_session_init (LightDMSession *session) { } static void lightdm_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } static void lightdm_session_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { LightDMSession *self; self = LIGHTDM_SESSION (object); switch (prop_id) { case PROP_KEY: g_value_set_string (value, lightdm_session_get_key (self)); break; case PROP_NAME: g_value_set_string (value, lightdm_session_get_name (self)); break; case PROP_COMMENT: g_value_set_string (value, lightdm_session_get_comment (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void lightdm_session_finalize (GObject *object) { LightDMSession *self = LIGHTDM_SESSION (object); LightDMSessionPrivate *priv = GET_PRIVATE (self); g_free (priv->key); g_free (priv->name); g_free (priv->comment); } static void lightdm_session_class_init (LightDMSessionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (LightDMSessionPrivate)); object_class->set_property = lightdm_session_set_property; object_class->get_property = lightdm_session_get_property; object_class->finalize = lightdm_session_finalize; g_object_class_install_property (object_class, PROP_KEY, g_param_spec_string ("key", "key", "Session key", NULL, G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_NAME, g_param_spec_string ("name", "name", "Session name", NULL, G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_COMMENT, g_param_spec_string ("comment", "comment", "Session comment", NULL, G_PARAM_READABLE)); }