/* -*- Mode: C; indent-tabs-mode:nil; tab-width:4 -*-
*
* Copyright (C) 2010 Robert Ancell.
* Author: Robert Ancell <robert.ancell@canonical.com>
*
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2 or version 3 of the License.
* See http://www.gnu.org/copyleft/lgpl.html the full text of the license.
*/
#include "config.h"
#include <errno.h>
#include <string.h>
#include <pwd.h>
enum
{
};
enum
{
};
enum
{
};
enum
{
};
typedef struct
{
/* Connection to AccountsService */
/* Connection to DisplayManager */
/* File monitor for password file */
/* TRUE if have scanned users */
/* List of users */
/* List of sessions */
typedef struct
{
typedef struct
{
typedef struct
{
} Session;
typedef struct
{
} SessionClass;
GType session_get_type (void);
#define GET_LIST_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER_LIST, LightDMUserListPrivate)
#define GET_USER_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), LIGHTDM_TYPE_USER, LightDMUserPrivate)
/**
* lightdm_user_list_get_instance:
*
* Get the user list.
*
* Return value: (transfer none): the #LightDMUserList
**/
{
if (!singleton)
return singleton;
}
static LightDMUser *
{
{
return user;
}
return NULL;
}
static gint
{
}
static gboolean
update_passwd_user (LightDMUser *user, const gchar *real_name, const gchar *home_directory, const gchar *image)
{
return FALSE;
return TRUE;
}
static void
{
}
static void
{
config = g_key_file_new ();
g_warning ("Failed to load configuration from %s: %s", USER_CONFIG_FILE, error->message); // FIXME: Don't make warning on no file, just info
g_clear_error (&error);
else
minimum_uid = 500;
if (!value)
if (!value)
setpwent ();
while (TRUE)
{
char **tokens;
int i;
errno = 0;
if (!entry)
break;
/* Ignore system users */
continue;
/* Ignore users disabled by shell */
{
if (hidden_shells[i])
continue;
}
/* Ignore certain users */
if (hidden_users[i])
continue;
else
g_strfreev (tokens);
{
{
}
}
/* Update existing users if have them */
{
{
if (update_passwd_user (info, lightdm_user_get_real_name (user), lightdm_user_get_home_directory (user), lightdm_user_get_image (user)))
break;
}
}
if (!link)
{
/* Only notify once we have loaded the user list */
if (priv->have_users)
}
}
if (errno != 0)
endpwent ();
/* Use new user list */
/* Notify of changes */
{
if (emit_add_signal)
}
{
}
{
/* See if this user is in the current list */
{
break;
}
if (!new_link)
{
}
}
}
static void
passwd_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, LightDMUserList *user_list)
{
{
}
}
static gboolean
{
"org.freedesktop.Accounts",
"org.freedesktop.DBus.Properties",
"GetAll",
G_VARIANT_TYPE ("(a{sv})"),
-1,
NULL,
&error);
if (error)
g_warning ("Error updating user %s: %s", g_dbus_proxy_get_object_path (object->proxy), error->message);
g_clear_error (&error);
if (!result)
return FALSE;
{
{
}
{
}
else if (strcmp (name, "HomeDirectory") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
{
}
{
else
}
else if (strcmp (name, "BackgroundFile") == 0 && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
{
else
}
}
return TRUE;
}
static void
user_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, UserAccountObject *object)
{
{
{
}
else
g_warning ("Got org.freedesktop.Accounts.User signal Changed with unknown parameters %s", g_variant_get_type_string (parameters));
}
}
static UserAccountObject *
{
NULL,
"org.freedesktop.Accounts",
path,
"org.freedesktop.Accounts.User",
NULL,
&error);
if (error)
g_clear_error (&error);
if (!proxy)
return NULL;
return object;
}
static void
{
if (!object)
return;
}
static UserAccountObject *
{
{
return object;
}
return NULL;
}
static void
user_accounts_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, LightDMUserList *user_list)
{
{
{
/* Ignore duplicate requests */
if (object)
return;
{
}
else
}
else
g_warning ("Got UserAccounts signal UserAdded with unknown parameters %s", g_variant_get_type_string (parameters));
}
{
{
if (!object)
return;
}
else
g_warning ("Got UserAccounts signal UserDeleted with unknown parameters %s", g_variant_get_type_string (parameters));
}
}
static Session *
{
"org.freedesktop.DisplayManager",
path,
"org.freedesktop.DBus.Properties",
"Get",
G_VARIANT_TYPE ("(v)"),
-1,
NULL,
&error);
if (error)
g_warning ("Error getting UserName from org.freedesktop.DisplayManager.Session: %s", error->message);
g_clear_error (&error);
if (!result)
return NULL;
{
}
return session;
}
static void
display_manager_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, LightDMUserList *user_list)
{
{
{
if (session)
if (user)
}
}
{
{
{
{
if (user)
break;
}
}
}
}
}
static void
{
if (priv->have_users)
return;
NULL,
"org.freedesktop.Accounts",
"/org/freedesktop/Accounts",
"org.freedesktop.Accounts",
NULL,
&error);
if (error)
g_clear_error (&error);
/* Check if the service exists */
if (priv->accounts_service_proxy)
{
if (!name)
{
g_debug ("org.freedesktop.Accounts does not exist, falling back to passwd file");
}
}
if (priv->accounts_service_proxy)
{
g_signal_connect (priv->accounts_service_proxy, "g-signal", G_CALLBACK (user_accounts_signal_cb), user_list);
"ListCachedUsers",
g_variant_new ("()"),
-1,
NULL,
&error);
if (error)
g_clear_error (&error);
if (!result)
return;
{
g_debug ("Loading users from org.freedesktop.Accounts");
{
{
}
else
}
}
else
}
else
{
/* Watch for changes to user list */
if (error)
else
g_clear_error (&error);
}
NULL,
"org.freedesktop.DisplayManager",
"org.freedesktop.DisplayManager",
NULL,
&error);
if (error)
g_clear_error (&error);
if (priv->display_manager_proxy)
{
g_signal_connect (priv->display_manager_proxy, "g-signal", G_CALLBACK (display_manager_signal_cb), user_list);
"org.freedesktop.DisplayManager",
"org.freedesktop.DBus.Properties",
"Get",
G_VARIANT_TYPE ("(v)"),
-1,
NULL,
&error);
if (error)
g_clear_error (&error);
if (!result)
return;
{
g_debug ("Loading sessions from org.freedesktop.DisplayManager");
}
else
g_warning ("Unexpected type from org.freedesktop.DisplayManager.Sessions: %s", g_variant_get_type_string (result));
}
}
/**
* lightdm_user_list_get_length:
* @user_list: a #LightDMUserList
*
* Return value: The number of users able to log in
**/
{
}
/**
* lightdm_user_list_get_users:
* @user_list: A #LightDMUserList
*
* Get a list of users to present to the user. This list may be a subset of the
* available users and may be empty depending on the server configuration.
*
* Return value: (element-type LightDMUser) (transfer none): A list of #LightDMUser that should be presented to the user.
**/
GList *
{
}
/**
* lightdm_user_list_get_user_by_name:
* @user_list: A #LightDMUserList
* @username: Name of user to get.
*
* Get infomation about a given user or #NULL if this user doesn't exist.
*
* Return value: (transfer none): A #LightDMUser entry for the given user.
**/
{
}
static void
{
}
static void
{
}
static void
{
switch (prop_id)
{
case LIST_PROP_NUM_USERS:
break;
default:
break;
}
}
static void
{
if (priv->accounts_service_proxy)
if (priv->passwd_monitor)
}
static void
{
g_param_spec_int ("num-users",
"num-users",
"Number of login users",
0, G_MAXINT, 0,
/**
* LightDMUserList::user-added:
* @user_list: A #LightDMUserList
* @user: The #LightDM user that has been added.
*
* The ::user-added signal gets emitted when a user account is created.
**/
g_signal_new ("user-added",
/**
* LightDMUserList::user-changed:
* @user_list: A #LightDMUserList
* @user: The #LightDM user that has been changed.
*
* The ::user-changed signal gets emitted when a user account is modified.
**/
g_signal_new ("user-changed",
/**
* LightDMUserList::user-removed:
* @user_list: A #LightDMUserList
* @user: The #LightDM user that has been removed.
*
* The ::user-removed signal gets emitted when a user account is removed.
**/
g_signal_new ("user-removed",
}
/**
* lightdm_user_get_name:
* @user: A #LightDMUser
*
* Get the name of a user.
*
* Return value: The name of the given user
**/
const gchar *
{
}
/**
* lightdm_user_get_real_name:
* @user: A #LightDMUser
*
* Get the real name of a user.
*
* Return value: The real name of the given user
**/
const gchar *
{
}
/**
* lightdm_user_get_display_name:
* @user: A #LightDMUser
*
* Get the display name of a user.
*
* Return value: The display name of the given user
**/
const gchar *
{
else
}
/**
* lightdm_user_get_home_directory:
* @user: A #LightDMUser
*
* Get the home directory for a user.
*
* Return value: The users home directory
*/
const gchar *
{
}
/**
* lightdm_user_get_image:
* @user: A #LightDMUser
*
* Get the image URI for a user.
*
* Return value: The image URI for the given user or #NULL if no URI
**/
const gchar *
{
}
/**
* lightdm_user_get_background:
* @user: A #LightDMUser
*
* Get the background file path for a user.
*
* Return value: The background file path for the given user or #NULL if no path
**/
const gchar *
{
}
static void
{
//gboolean have_dmrc;
/* Load from the user directory */
/* If no ~/.dmrc, then load from the cache */
// FIXME
// FIXME: Watch for changes
/* The Language field is actually a locale, strip the codeset off it to get the language */
{
if (codeset)
*codeset = '\0';
}
{
}
{
}
}
static GVariant *
{
if (!proxy)
return NULL;
if (!answer)
{
return NULL;
}
return answer;
}
static gboolean
{
{
g_warning ("Unexpected accounts property type for %s: %s",
return FALSE;
}
return rv;
}
static gchar *
{
{
g_warning ("Unexpected accounts property type for %s: %s",
return NULL;
}
{
}
return rv;
}
static gchar **
{
if (!proxy)
return NULL;
if (!answer)
{
return NULL;
}
{
g_warning ("Unexpected accounts property type for %s: %s",
return NULL;
}
return rv;
}
static gboolean
{
/* First, find AccountObject proxy */
{
{
account = a;
break;
}
}
if (!account)
return FALSE;
/* We have proxy, let's grab some properties */
if (value)
{
if (value[0])
{
}
else
g_strfreev (value);
}
return TRUE;
}
static void
{
/* Ensure a few guarantees */
{
}
}
/**
* lightdm_user_get_language:
* @user: A #LightDMUser
*
* Get the language for a user.
*
* Return value: The language for the given user or #NULL if using system defaults.
**/
const gchar *
{
}
/**
* lightdm_user_get_layout:
* @user: A #LightDMUser
*
* Get the keyboard layout for a user.
*
* Return value: The keyboard layout for the given user or #NULL if using system defaults. Copy the value if you want to use it long term.
**/
const gchar *
{
}
/**
* lightdm_user_get_layouts:
* @user: A #LightDMUser
*
* Get the configured keyboard layouts for a user.
*
* Return value: (transfer none): A NULL-terminated array of keyboard layouts for the given user. Copy the values if you want to use them long term.
**/
const gchar * const *
{
}
/**
* lightdm_user_get_session:
* @user: A #LightDMUser
*
* Get the session for a user.
*
* Return value: The session for the given user or #NULL if using system defaults.
**/
const gchar *
{
}
/**
* lightdm_user_get_logged_in:
* @user: A #LightDMUser
*
* Check if a user is logged in.
*
* Return value: #TRUE if the user is currently logged in.
**/
{
{
return TRUE;
}
return FALSE;
}
/**
* lightdm_user_get_has_messages:
* @user: A #LightDMUser
*
* Check if a user has waiting messages.
*
* Return value: #TRUE if the user has waiting messages.
**/
{
}
static void
{
}
static void
{
}
static void
{
switch (prop_id)
{
case USER_PROP_NAME:
break;
case USER_PROP_REAL_NAME:
break;
case USER_PROP_DISPLAY_NAME:
break;
case USER_PROP_HOME_DIRECTORY:
break;
case USER_PROP_IMAGE:
break;
case USER_PROP_BACKGROUND:
break;
case USER_PROP_LANGUAGE:
break;
case USER_PROP_LAYOUT:
break;
case USER_PROP_LAYOUTS:
break;
case USER_PROP_SESSION:
break;
case USER_PROP_LOGGED_IN:
break;
case USER_PROP_HAS_MESSAGES:
break;
default:
break;
}
}
static void
{
}
static void
{
g_param_spec_string ("name",
"name",
"Username",
NULL,
g_param_spec_string ("real-name",
"real-name",
"Users real name",
NULL,
g_param_spec_string ("display-name",
"display-name",
"Users display name",
NULL,
g_param_spec_string ("home-directory",
"home-directory",
"Home directory",
NULL,
g_param_spec_string ("image",
"image",
"Avatar image",
NULL,
g_param_spec_string ("background",
"background",
"User background",
NULL,
g_param_spec_string ("language",
"language",
"Language used by this user",
NULL,
g_param_spec_string ("layout",
"layout",
"Keyboard layout used by this user",
NULL,
g_param_spec_boxed ("layouts",
"layouts",
"Keyboard layouts used by this user",
g_param_spec_string ("session",
"session",
"Session used by this user",
NULL,
g_param_spec_boolean ("logged-in",
"logged-in",
"TRUE if the user is currently in a session",
g_param_spec_boolean ("has-messages",
"has-messages",
"TRUE if the user is has waiting messages",
/**
* LightDMUser::changed:
* @user: A #LightDMUser
*
* The ::changed signal gets emitted this user account is modified.
**/
g_signal_new ("changed",
G_TYPE_NONE, 0);
}
static void
{
}
static void
{
}
static void
{
}