diff options
author | William Jon McCann <mccann@jhu.edu> | 2007-10-03 04:16:41 +0000 |
---|---|---|
committer | William Jon McCann <mccann@src.gnome.org> | 2007-10-03 04:16:41 +0000 |
commit | 7b2080c213c2fdea9269e76da72766aa077dd5b7 (patch) | |
tree | b5f48824ae132199eb212b419bffb4472573975c | |
parent | 33c755a0078df7031ec342487203dbe3bf6c9f3f (diff) | |
download | gdm-7b2080c213c2fdea9269e76da72766aa077dd5b7.tar.gz |
Add basic user monitoring. Hook up to user-list.
2007-10-03 William Jon McCann <mccann@jhu.edu>
* configure.ac:
* gui/simple-greeter/Makefile.am:
* gui/simple-greeter/gdm-user-chooser-widget.c: (populate_model),
(on_user_added), (on_user_removed), (gdm_user_chooser_widget_init):
* gui/simple-greeter/gdm-user-manager.c:
(gdm_user_manager_error_quark), (gdm_user_manager_get_user),
(listify_hash_values_hfunc), (gdm_user_manager_list_users),
(reload_passwd), (reload_shells), (shells_monitor_cb),
(passwd_monitor_cb), (gdm_user_manager_class_init),
(reload_passwd_timeout), (queue_reload_passwd),
(gdm_user_manager_init), (gdm_user_manager_finalize),
(gdm_user_manager_ref_default):
* gui/simple-greeter/gdm-user-manager.h:
* gui/simple-greeter/gdm-user.c: (gdm_user_class_init),
(gdm_user_init), (gdm_user_set_property), (gdm_user_get_property),
(gdm_user_finalize), (_gdm_user_update), (_gdm_user_add_session),
(_gdm_user_remove_session), (_gdm_user_icon_changed),
(gdm_user_get_uid), (gdm_user_get_real_name),
(gdm_user_get_user_name), (gdm_user_get_home_directory),
(gdm_user_get_shell), (gdm_user_get_sessions),
(gdm_user_get_n_sessions), (gdm_user_collate):
* gui/simple-greeter/gdm-user.h:
* gui/simple-greeter/test-user-chooser.c: (main):
* gui/simple-greeter/test-user-manager.c: (on_user_added),
(on_user_removed), (main):
Add basic user monitoring. Hook up to user-list.
svn path=/branches/mccann-gobject/; revision=5331
-rw-r--r-- | ChangeLog | 29 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | gui/simple-greeter/Makefile.am | 21 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-user-chooser-widget.c | 122 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-user-manager.c | 482 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-user-manager.h | 73 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-user.c | 587 | ||||
-rw-r--r-- | gui/simple-greeter/gdm-user.h | 59 | ||||
-rw-r--r-- | gui/simple-greeter/test-user-chooser.c | 2 | ||||
-rw-r--r-- | gui/simple-greeter/test-user-manager.c | 82 |
10 files changed, 1399 insertions, 63 deletions
@@ -1,3 +1,32 @@ +2007-10-03 William Jon McCann <mccann@jhu.edu> + + * configure.ac: + * gui/simple-greeter/Makefile.am: + * gui/simple-greeter/gdm-user-chooser-widget.c: (populate_model), + (on_user_added), (on_user_removed), (gdm_user_chooser_widget_init): + * gui/simple-greeter/gdm-user-manager.c: + (gdm_user_manager_error_quark), (gdm_user_manager_get_user), + (listify_hash_values_hfunc), (gdm_user_manager_list_users), + (reload_passwd), (reload_shells), (shells_monitor_cb), + (passwd_monitor_cb), (gdm_user_manager_class_init), + (reload_passwd_timeout), (queue_reload_passwd), + (gdm_user_manager_init), (gdm_user_manager_finalize), + (gdm_user_manager_ref_default): + * gui/simple-greeter/gdm-user-manager.h: + * gui/simple-greeter/gdm-user.c: (gdm_user_class_init), + (gdm_user_init), (gdm_user_set_property), (gdm_user_get_property), + (gdm_user_finalize), (_gdm_user_update), (_gdm_user_add_session), + (_gdm_user_remove_session), (_gdm_user_icon_changed), + (gdm_user_get_uid), (gdm_user_get_real_name), + (gdm_user_get_user_name), (gdm_user_get_home_directory), + (gdm_user_get_shell), (gdm_user_get_sessions), + (gdm_user_get_n_sessions), (gdm_user_collate): + * gui/simple-greeter/gdm-user.h: + * gui/simple-greeter/test-user-chooser.c: (main): + * gui/simple-greeter/test-user-manager.c: (on_user_added), + (on_user_removed), (main): + Add basic user monitoring. Hook up to user-list. + 2007-10-02 William Jon McCann <mccann@jhu.edu> * daemon/gdm-factory-slave.c: (on_session_relay_info), diff --git a/configure.ac b/configure.ac index 7c3305e3..8c884053 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,8 @@ GNOME_DOC_INIT DBUS_GLIB_REQUIRED=0.74 GLIB_REQUIRED=2.13.0 -GTK_REQUIRED=2.6.0 +GTK_REQUIRED=2.10.0 +GNOME_VFS_REQUIRED=2.18.0 PANGO_REQUIRED=1.3.0 LIBGLADE_REQUIRED=1.99.2 SCROLLKEEPER_REQUIRED=0.1.4 @@ -169,7 +170,7 @@ PKG_CHECK_MODULES(DAEMON, gtk+-2.0 >= $GTK_REQUIRED) AC_SUBST(DAEMON_CFLAGS) AC_SUBST(DAEMON_LIBS) -PKG_CHECK_MODULES(GUI, gtk+-2.0 >= $GTK_REQUIRED libglade-2.0 >= $LIBGLADE_REQUIRED) +PKG_CHECK_MODULES(GUI, gtk+-2.0 >= $GTK_REQUIRED libglade-2.0 >= $LIBGLADE_REQUIRED gnome-vfs-2.0 >= $GNOME_VFS_REQUIRED) AC_SUBST(GUI_CFLAGS) AC_SUBST(GUI_LIBS) diff --git a/gui/simple-greeter/Makefile.am b/gui/simple-greeter/Makefile.am index a6afa7cf..9d1828a6 100644 --- a/gui/simple-greeter/Makefile.am +++ b/gui/simple-greeter/Makefile.am @@ -28,6 +28,7 @@ noinst_PROGRAMS = \ test-language-chooser \ test-session-chooser \ test-user-chooser \ + test-user-manager \ $(NULL) test_greeter_background_SOURCES = \ @@ -83,12 +84,28 @@ test_user_chooser_SOURCES = \ gdm-user-chooser-widget.c \ gdm-user-chooser-dialog.h \ gdm-user-chooser-dialog.c \ + gdm-user-manager.h \ + gdm-user-manager.c \ + gdm-user.h \ + gdm-user.c \ $(NULL) test_user_chooser_LDADD = \ $(GUI_LIBS) \ $(NULL) +test_user_manager_SOURCES = \ + test-user-manager.c \ + gdm-user-manager.h \ + gdm-user-manager.c \ + gdm-user.h \ + gdm-user.c \ + $(NULL) + +test_user_manager_LDADD = \ + $(GUI_LIBS) \ + $(NULL) + libexec_PROGRAMS = \ gdm-simple-greeter @@ -102,6 +119,10 @@ gdm_simple_greeter_SOURCES = \ gdm-greeter-background.c \ gdm-user-chooser-widget.h \ gdm-user-chooser-widget.c \ + gdm-user-manager.h \ + gdm-user-manager.c \ + gdm-user.h \ + gdm-user.c \ $(NULL) gdm_simple_greeter_LDADD = \ diff --git a/gui/simple-greeter/gdm-user-chooser-widget.c b/gui/simple-greeter/gdm-user-chooser-widget.c index 782763ef..525edc18 100644 --- a/gui/simple-greeter/gdm-user-chooser-widget.c +++ b/gui/simple-greeter/gdm-user-chooser-widget.c @@ -33,6 +33,7 @@ #include <glib/gstdio.h> #include <gtk/gtk.h> +#include "gdm-user-manager.h" #include "gdm-user-chooser-widget.h" enum { @@ -53,6 +54,7 @@ struct GdmUserChooserWidgetPrivate { GtkWidget *iconview; + GdmUserManager *manager; GHashTable *available_users; char *current_user; }; @@ -372,66 +374,6 @@ static void populate_model (GdmUserChooserWidget *widget, GtkTreeModel *model) { - GtkTreeIter iter; - GdkPixbuf *pixbuf; - char *caption; - char *tooltip; - - /* Add some fake entries */ - - caption = g_strdup_printf ("<span size=\"x-large\">%s</span>\n<i>%s</i>", - _("Guest User"), - _("Already logged in")); - tooltip = g_strdup_printf ("%s: %s", - _("Short Name"), - "guest"); - pixbuf = get_pixbuf_for_user (widget, "guest"); - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - CHOOSER_LIST_PIXBUF_COLUMN, pixbuf, - CHOOSER_LIST_CAPTION_COLUMN, caption, - CHOOSER_LIST_TOOLTIP_COLUMN, tooltip, - CHOOSER_LIST_ID_COLUMN, "guest", - -1); - g_free (caption); - g_free (tooltip); - - caption = g_strdup_printf ("<span size=\"x-large\">%s</span>\n<i>%s</i>", - _("GNOME Test"), - _("Already logged in")); - tooltip = g_strdup_printf ("%s: %s", - _("Short Name"), - "gtest"); - pixbuf = get_pixbuf_for_user (widget, "gtest"); - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - CHOOSER_LIST_PIXBUF_COLUMN, pixbuf, - CHOOSER_LIST_CAPTION_COLUMN, caption, - CHOOSER_LIST_TOOLTIP_COLUMN, tooltip, - CHOOSER_LIST_ID_COLUMN, "gtest", - -1); - g_free (caption); - g_free (tooltip); - - caption = g_strdup_printf ("<span size=\"x-large\">%s</span>", - _("Administrator")); - tooltip = g_strdup_printf ("%s: %s", - _("Short Name"), - "administrator"); - - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - CHOOSER_LIST_PIXBUF_COLUMN, pixbuf, - CHOOSER_LIST_CAPTION_COLUMN, caption, - CHOOSER_LIST_TOOLTIP_COLUMN, tooltip, - CHOOSER_LIST_ID_COLUMN, "administrator", - -1); - g_free (caption); - g_free (tooltip); - - if (pixbuf != NULL) { - g_object_unref (pixbuf); - } g_hash_table_foreach (widget->priv->available_users, (GHFunc)add_user_to_model, @@ -521,6 +463,53 @@ compare_user (GtkTreeModel *model, } static void +on_user_added (GdmUserManager *manager, + GdmUser *user, + GdmUserChooserWidget *widget) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GdkPixbuf *pixbuf; + char *caption; + char *tooltip; + + g_debug ("User added: %s", gdm_user_get_user_name (user)); + + pixbuf = get_pixbuf_for_user (widget, gdm_user_get_user_name (user)); + + caption = g_strdup_printf ("<span size=\"x-large\">%s</span>", + gdm_user_get_real_name (user)); + tooltip = g_strdup_printf ("%s: %s", + _("Short Name"), + gdm_user_get_user_name (user)); + + model = gtk_icon_view_get_model (GTK_ICON_VIEW (widget->priv->iconview)); + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + CHOOSER_LIST_PIXBUF_COLUMN, pixbuf, + CHOOSER_LIST_CAPTION_COLUMN, caption, + CHOOSER_LIST_TOOLTIP_COLUMN, tooltip, + CHOOSER_LIST_ID_COLUMN, gdm_user_get_user_name (user), + -1); + g_free (caption); + g_free (tooltip); + + if (pixbuf != NULL) { + g_object_unref (pixbuf); + } +} + +static void +on_user_removed (GdmUserManager *manager, + GdmUser *user, + GdmUserChooserWidget *widget) +{ + g_debug ("User removed: %s", gdm_user_get_user_name (user)); + + /* FIXME: */ +} + +static void gdm_user_chooser_widget_init (GdmUserChooserWidget *widget) { GtkTreeModel *model; @@ -528,13 +517,24 @@ gdm_user_chooser_widget_init (GdmUserChooserWidget *widget) widget->priv = GDM_USER_CHOOSER_WIDGET_GET_PRIVATE (widget); + widget->priv->manager = gdm_user_manager_ref_default (); + g_signal_connect (widget->priv->manager, + "user-added", + G_CALLBACK (on_user_added), + widget); + g_signal_connect (widget->priv->manager, + "user-removed", + G_CALLBACK (on_user_removed), + widget); + widget->priv->available_users = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)chooser_user_free); scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (widget), scrolled, TRUE, TRUE, 0); widget->priv->iconview = gtk_icon_view_new (); diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c new file mode 100644 index 00000000..1755d7d2 --- /dev/null +++ b/gui/simple-greeter/gdm-user-manager.c @@ -0,0 +1,482 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <glib.h> +#include <glib/gi18n.h> +#include <glib/gstdio.h> +#include <glib-object.h> + +#include <libgnomevfs/gnome-vfs-ops.h> + +#include "gdm-user-manager.h" +#include "gdm-user-private.h" + +#define GDM_USER_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_USER_MANAGER, GdmUserManagerPrivate)) + +/* Prefs Defaults */ +#define DEFAULT_ALLOW_ROOT TRUE +#define DEFAULT_MAX_ICON_SIZE 128 +#define DEFAULT_USER_MAX_FILE 65536 +#define DEFAULT_MINIMAL_UID 500 +#define DEFAULT_GLOBAL_FACE_DIR DATADIR "/faces" +#define DEFAULT_USER_ICON "stock_person" +#define DEFAULT_EXCLUDE { "bin", \ + "daemon", \ + "adm", \ + "lp", \ + "sync", \ + "shutdown", \ + "halt", \ + "mail", \ + "news", \ + "uucp", \ + "operator", \ + "nobody", \ + "gdm", \ + "postgres", \ + "pvm", \ + "rpm", \ + "nfsnobody", \ + "pcap", \ + NULL } + +struct GdmUserManagerPrivate +{ + GHashTable *users; + GHashTable *shells; + GHashTable *exclusions; + GnomeVFSMonitorHandle *passwd_monitor; + GnomeVFSMonitorHandle *shells_monitor; + + guint reload_id; + uid_t minimal_uid; + + guint8 users_dirty : 1; +}; + +enum { + USER_ADDED, + USER_REMOVED, + LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL] = { 0, }; + +static void gdm_user_manager_class_init (GdmUserManagerClass *klass); +static void gdm_user_manager_init (GdmUserManager *user_manager); +static void gdm_user_manager_finalize (GObject *object); + +static gpointer user_manager_object = NULL; + +G_DEFINE_TYPE (GdmUserManager, gdm_user_manager, G_TYPE_OBJECT) + +GQuark +gdm_user_manager_error_quark (void) +{ + static GQuark ret = 0; + if (ret == 0) { + ret = g_quark_from_static_string ("gdm_user_manager_error"); + } + + return ret; +} + +/** + * gdm_manager_get_user: + * @manager: the manager to query. + * @username: the login name of the user to get. + * + * Retrieves a pointer to the #GdmUser object for the login named @username + * from @manager. This pointer is not a reference, and should not be released. + * + * Returns: a pointer to a #GdmUser object. + **/ +GdmUser * +gdm_user_manager_get_user (GdmUserManager *manager, + const char *username) +{ + GdmUser *user; + + g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), NULL); + g_return_val_if_fail (username != NULL && username[0] != '\0', NULL); + + user = g_hash_table_lookup (manager->priv->users, username); + + if (user == NULL) { + struct passwd *pwent; + + pwent = getpwnam (username); + + if (pwent != NULL) { + user = g_object_new (GDM_TYPE_USER, "manager", manager, NULL); + _gdm_user_update (user, pwent); + g_hash_table_insert (manager->priv->users, + g_strdup (pwent->pw_name), + user); + g_signal_emit (manager, signals[USER_ADDED], 0, user); + } + } + + return user; +} + +static void +listify_hash_values_hfunc (gpointer key, + gpointer value, + gpointer user_data) +{ + GSList **list = user_data; + + *list = g_slist_prepend (*list, value); +} + +GSList * +gdm_user_manager_list_users (GdmUserManager *manager) +{ + GSList *retval; + + g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), NULL); + + retval = NULL; + g_hash_table_foreach (manager->priv->users, listify_hash_values_hfunc, &retval); + + return g_slist_sort (retval, (GCompareFunc) gdm_user_collate); +} + +static void +reload_passwd (GdmUserManager *manager) +{ + struct passwd *pwent; + GSList *old_users; + GSList *new_users; + GSList *list; + + old_users = NULL; + new_users = NULL; + + g_hash_table_foreach (manager->priv->users, listify_hash_values_hfunc, &old_users); + g_slist_foreach (old_users, (GFunc) g_object_ref, NULL); + + /* Make sure we keep users who are logged in no matter what. */ + for (list = old_users; list; list = list->next) { + if (gdm_user_get_n_sessions (list->data)) { + g_object_freeze_notify (G_OBJECT (list->data)); + new_users = g_slist_prepend (new_users, g_object_ref (list->data)); + } + } + + setpwent (); + + for (pwent = getpwent (); pwent; pwent = getpwent ()) { + GdmUser *user; + + user = NULL; + + /* Skip users below MinimalUID... */ + if (pwent->pw_uid < manager->priv->minimal_uid) { + continue; + } + + /* ...And users w/ invalid shells... */ + if (!pwent->pw_shell || + !g_hash_table_lookup (manager->priv->shells, pwent->pw_shell)) { + continue; + } + + /* ...And explicitly excluded users */ + if (g_hash_table_lookup (manager->priv->exclusions, pwent->pw_name)) { + continue; + } + + user = g_hash_table_lookup (manager->priv->users, pwent->pw_name); + + /* Update users already in the *new* list */ + if (g_slist_find (new_users, user)) { + _gdm_user_update (user, pwent); + continue; + } + + if (user == NULL) { + user = g_object_new (GDM_TYPE_USER, + "manager", manager, + NULL); + } else { + g_object_ref (user); + } + + /* Freeze & update users not already in the new list */ + g_object_freeze_notify (G_OBJECT (user)); + _gdm_user_update (user, pwent); + + new_users = g_slist_prepend (new_users, user); + } + + endpwent (); + + /* Go through and handle added users */ + for (list = new_users; list; list = list->next) { + if (! g_slist_find (old_users, list->data)) { + g_hash_table_insert (manager->priv->users, + g_strdup (gdm_user_get_user_name (list->data)), + g_object_ref (list->data)); + g_signal_emit (manager, signals[USER_ADDED], 0, list->data); + } + } + + /* Go through and handle removed users */ + for (list = old_users; list; list = list->next) { + if (! g_slist_find (new_users, list->data)) { + g_signal_emit (manager, signals[USER_REMOVED], 0, list->data); + g_hash_table_remove (manager->priv->users, + gdm_user_get_user_name (list->data)); + } + } + + /* Cleanup */ + g_slist_foreach (new_users, (GFunc) g_object_thaw_notify, NULL); + g_slist_foreach (new_users, (GFunc) g_object_unref, NULL); + g_slist_free (new_users); + + g_slist_foreach (old_users, (GFunc) g_object_unref, NULL); + g_slist_free (old_users); +} + +static void +reload_shells (GdmUserManager *manager) +{ + char *shell; + + setusershell (); + + g_hash_table_remove_all (manager->priv->shells); + for (shell = getusershell (); shell; shell = getusershell ()) { + g_hash_table_insert (manager->priv->shells, + g_strdup (shell), + GUINT_TO_POINTER (TRUE)); + } + + endusershell (); +} + +static void +shells_monitor_cb (GnomeVFSMonitorHandle *handle, + const gchar *text_uri, + const gchar *info_uri, + GnomeVFSMonitorEventType event_type, + GdmUserManager *manager) +{ + if (event_type != GNOME_VFS_MONITOR_EVENT_CHANGED && + event_type != GNOME_VFS_MONITOR_EVENT_CREATED) + return; + + reload_shells (manager); + reload_passwd (manager); +} + +static void +passwd_monitor_cb (GnomeVFSMonitorHandle *handle, + const gchar *text_uri, + const gchar *info_uri, + GnomeVFSMonitorEventType event_type, + GdmUserManager *manager) +{ + if (event_type != GNOME_VFS_MONITOR_EVENT_CHANGED && + event_type != GNOME_VFS_MONITOR_EVENT_CREATED) + return; + + reload_passwd (manager); +} + +static void +gdm_user_manager_class_init (GdmUserManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gdm_user_manager_finalize; + + signals [USER_ADDED] = + g_signal_new ("user-added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GdmUserManagerClass, user_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, GDM_TYPE_USER); + signals [USER_REMOVED] = + g_signal_new ("user-removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GdmUserManagerClass, user_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, GDM_TYPE_USER); + + g_type_class_add_private (klass, sizeof (GdmUserManagerPrivate)); +} + +static gboolean +reload_passwd_timeout (GdmUserManager *manager) +{ + reload_passwd (manager); + manager->priv->reload_id = 0; + return FALSE; +} + +static void +queue_reload_passwd (GdmUserManager *manager) +{ + if (manager->priv->reload_id > 0) { + return; + } + + manager->priv->reload_id = g_idle_add ((GSourceFunc)reload_passwd_timeout, manager); +} + +static void +gdm_user_manager_init (GdmUserManager *manager) +{ + GError *error; + char *uri; + GnomeVFSResult result; + int i; + const char *exclude_default[] = DEFAULT_EXCLUDE; + + manager->priv = GDM_USER_MANAGER_GET_PRIVATE (manager); + + manager->priv->minimal_uid = DEFAULT_MINIMAL_UID; + + /* exclusions */ + manager->priv->exclusions = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); + for (i = 0; exclude_default[i] != NULL; i++) { + g_hash_table_insert (manager->priv->exclusions, + g_strdup (exclude_default [i]), + GUINT_TO_POINTER (TRUE)); + } + + /* /etc/shells */ + manager->priv->shells = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); + reload_shells (manager); + error = NULL; + uri = g_filename_to_uri ("/etc/shells", NULL, &error); + if (uri == NULL) { + g_critical ("Could not create URI for shells file `/etc/shells': %s", + error->message); + g_error_free (error); + } else { + result = gnome_vfs_monitor_add (&(manager->priv->shells_monitor), + uri, + GNOME_VFS_MONITOR_FILE, + (GnomeVFSMonitorCallback)shells_monitor_cb, + manager); + g_free (uri); + + if (result != GNOME_VFS_OK) + g_critical ("Could not install monitor for shells file `/etc/shells': %s", + gnome_vfs_result_to_string (result)); + } + + /* /etc/passwd */ + manager->priv->users = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_object_run_dispose); + error = NULL; + uri = g_filename_to_uri ("/etc/passwd", NULL, &error); + if (uri == NULL) { + g_critical ("Could not create URI for password file `/etc/passwd': %s", + error->message); + g_error_free (error); + } else { + result = gnome_vfs_monitor_add (&(manager->priv->passwd_monitor), + uri, + GNOME_VFS_MONITOR_FILE, + (GnomeVFSMonitorCallback)passwd_monitor_cb, + manager); + g_free (uri); + + if (result != GNOME_VFS_OK) + g_critical ("Could not install monitor for password file `/etc/passwd: %s", + gnome_vfs_result_to_string (result)); + } + + /* FIXME: add ConsoleKit seat monitoring */ + + queue_reload_passwd (manager); + + manager->priv->users_dirty = FALSE; + +} + +static void +gdm_user_manager_finalize (GObject *object) +{ + GdmUserManager *manager; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_USER_MANAGER (object)); + + manager = GDM_USER_MANAGER (object); + + g_return_if_fail (manager->priv != NULL); + + if (manager->priv->reload_id > 0) { + g_source_remove (manager->priv->reload_id); + manager->priv->reload_id = 0; + } + + gnome_vfs_monitor_cancel (manager->priv->shells_monitor); + g_hash_table_destroy (manager->priv->shells); + + gnome_vfs_monitor_cancel (manager->priv->passwd_monitor); + g_hash_table_destroy (manager->priv->users); + + G_OBJECT_CLASS (gdm_user_manager_parent_class)->finalize (object); +} + +GdmUserManager * +gdm_user_manager_ref_default (void) +{ + if (user_manager_object != NULL) { + g_object_ref (user_manager_object); + } else { + user_manager_object = g_object_new (GDM_TYPE_USER_MANAGER, NULL); + g_object_add_weak_pointer (user_manager_object, + (gpointer *) &user_manager_object); + } + + return GDM_USER_MANAGER (user_manager_object); +} diff --git a/gui/simple-greeter/gdm-user-manager.h b/gui/simple-greeter/gdm-user-manager.h new file mode 100644 index 00000000..590ab1da --- /dev/null +++ b/gui/simple-greeter/gdm-user-manager.h @@ -0,0 +1,73 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __GDM_USER_MANAGER_H +#define __GDM_USER_MANAGER_H + +#include <glib-object.h> + +#include "gdm-user.h" + +G_BEGIN_DECLS + +#define GDM_TYPE_USER_MANAGER (gdm_user_manager_get_type ()) +#define GDM_USER_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_USER_MANAGER, GdmUserManager)) +#define GDM_USER_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_USER_MANAGER, GdmUserManagerClass)) +#define GDM_IS_USER_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_USER_MANAGER)) +#define GDM_IS_USER_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_USER_MANAGER)) +#define GDM_USER_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_USER_MANAGER, GdmUserManagerClass)) + +typedef struct GdmUserManagerPrivate GdmUserManagerPrivate; + +typedef struct +{ + GObject parent; + GdmUserManagerPrivate *priv; +} GdmUserManager; + +typedef struct +{ + GObjectClass parent_class; + + void (* user_added) (GdmUserManager *user_manager, + GdmUser *user); + void (* user_removed) (GdmUserManager *user_manager, + GdmUser *user); +} GdmUserManagerClass; + +typedef enum +{ + GDM_USER_MANAGER_ERROR_GENERAL, + GDM_USER_MANAGER_ERROR_KEY_NOT_FOUND +} GdmUserManagerError; + +#define GDM_USER_MANAGER_ERROR gdm_user_manager_error_quark () + +GQuark gdm_user_manager_error_quark (void); +GType gdm_user_manager_get_type (void); + +GdmUserManager * gdm_user_manager_ref_default (void); + +GSList * gdm_user_manager_list_users (GdmUserManager *manager); +GdmUser * gdm_user_manager_get_user (GdmUserManager *manager, + const char *user_name); +G_END_DECLS + +#endif /* __GDM_USER_MANAGER_H */ diff --git a/gui/simple-greeter/gdm-user.c b/gui/simple-greeter/gdm-user.c new file mode 100644 index 00000000..a7d1e9ed --- /dev/null +++ b/gui/simple-greeter/gdm-user.c @@ -0,0 +1,587 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>. + * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <config.h> + +#include <string.h> +#include <glib/gi18n.h> +#include <gtk/gtkicontheme.h> + +#include "gdm-user-manager.h" +#include "gdm-user-private.h" + +#define GDM_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_USER, GdmUserClass)) +#define GDM_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_USER)) +#define GDM_USER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), GDM_TYPE_USER, GdmUserClass)) + +enum { + PROP_0, + PROP_MANAGER, + PROP_REAL_NAME, + PROP_USER_NAME, + PROP_UID, + PROP_HOME_DIR, + PROP_SHELL, + PROP_SESSIONS +}; + +enum { + ICON_CHANGED, + SESSIONS_CHANGED, + LAST_SIGNAL +}; + +struct _GdmUser { + GObject parent; + + GdmUserManager *manager; + + uid_t uid; + gchar *user_name; + gchar *real_name; + gchar *home_dir; + gchar *shell; + GSList *sessions; +}; + +typedef struct _GdmUserClass +{ + GObjectClass parent_class; + + void (* icon_changed) (GdmUser *user); + void (* sessions_changed) (GdmUser *user); +} GdmUserClass; + +/* GObject Functions */ +static void gdm_user_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); +static void gdm_user_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static void gdm_user_finalize (GObject *object); + + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (GdmUser, gdm_user, G_TYPE_OBJECT); + +static void +gdm_user_class_init (GdmUserClass *class) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (class); + + gobject_class->set_property = gdm_user_set_property; + gobject_class->get_property = gdm_user_get_property; + gobject_class->finalize = gdm_user_finalize; + + g_object_class_install_property (gobject_class, + PROP_MANAGER, + g_param_spec_object ("manager", + _("Manager"), + _("The user manager object this user is controlled by."), + GDM_TYPE_USER_MANAGER, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY))); + + g_object_class_install_property (gobject_class, + PROP_REAL_NAME, + g_param_spec_string ("real-name", + "Real Name", + "The real name to display for this user.", + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_UID, + g_param_spec_ulong ("uid", + "User ID", + "The UID for this user.", + 0, G_MAXULONG, 0, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, + PROP_USER_NAME, + g_param_spec_string ("user-name", + "User Name", + "The login name for this user.", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, + PROP_HOME_DIR, + g_param_spec_string ("home-directory", + "Home Directory", + "The home directory for this user.", + NULL, + G_PARAM_READABLE)); + g_object_class_install_property (gobject_class, + PROP_SHELL, + g_param_spec_string ("shell", + "Shell", + "The shell for this user.", + NULL, + G_PARAM_READABLE)); + + signals [ICON_CHANGED] = + g_signal_new ("icon-changed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GdmUserClass, icon_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals [SESSIONS_CHANGED] = + g_signal_new ("sessions-changed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GdmUserClass, sessions_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +gdm_user_init (GdmUser *user) +{ + user->manager = NULL; + user->user_name = NULL; + user->real_name = NULL; + user->sessions = NULL; +} + +static void +gdm_user_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + GdmUser *user; + + user = GDM_USER (object); + + switch (param_id) { + case PROP_MANAGER: + user->manager = g_value_get_object (value); + g_assert (user->manager); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +gdm_user_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + GdmUser *user; + + user = GDM_USER (object); + + switch (param_id) { + case PROP_MANAGER: + g_value_set_object (value, user->manager); + break; + case PROP_USER_NAME: + g_value_set_string (value, user->user_name); + break; + case PROP_REAL_NAME: + g_value_set_string (value, user->real_name); + break; + case PROP_HOME_DIR: + g_value_set_string (value, user->home_dir); + break; + case PROP_UID: + g_value_set_ulong (value, user->uid); + break; + case PROP_SHELL: + g_value_set_string (value, user->shell); + break; + case PROP_SESSIONS: + if (user->sessions) { + GValueArray *ar; + GSList *list; + GValue tmp = { 0 }; + + ar = g_value_array_new (g_slist_length (user->sessions)); + g_value_init (&tmp, GDM_TYPE_USER); + for (list = user->sessions; list; list = list->next) { + g_value_set_object (&tmp, list->data); + g_value_array_append (ar, &tmp); + g_value_reset (&tmp); + } + + g_value_take_boxed (value, ar); + } else { + g_value_set_boxed (value, NULL); + } + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +gdm_user_finalize (GObject *object) +{ + GdmUser *user; + + user = GDM_USER (object); + + g_free (user->user_name); + g_free (user->real_name); + + if (G_OBJECT_CLASS (gdm_user_parent_class)->finalize) + (*G_OBJECT_CLASS (gdm_user_parent_class)->finalize) (object); +} + +/** + * _gdm_user_update: + * @user: the user object to update. + * @pwent: the user data to use. + * + * Updates the properties of @user using the data in @pwent. + * + * Since: 1.0 + **/ +void +_gdm_user_update (GdmUser *user, + const struct passwd *pwent) +{ + gchar *real_name; + + g_return_if_fail (GDM_IS_USER (user)); + g_return_if_fail (pwent != NULL); + + g_object_freeze_notify (G_OBJECT (user)); + + /* Display Name */ + if (pwent->pw_gecos && pwent->pw_gecos[0] != '\0') { + gchar *first_comma; + + first_comma = strchr (pwent->pw_gecos, ','); + if (first_comma) { + real_name = g_strndup (pwent->pw_gecos, + (first_comma - pwent->pw_gecos)); + } else { + real_name = g_strdup (pwent->pw_gecos); + } + + if (real_name[0] == '\0') { + g_free (real_name); + real_name = NULL; + } + } else { + real_name = NULL; + } + + if ((real_name && !user->real_name) || + (!real_name && user->real_name) || + (real_name && + user->real_name && + strcmp (real_name, user->real_name) != 0)) { + g_free (user->real_name); + user->real_name = real_name; + g_object_notify (G_OBJECT (user), "real-name"); + } else { + g_free (real_name); + } + + /* UID */ + if (pwent->pw_uid != user->uid) { + user->uid = pwent->pw_uid; + g_object_notify (G_OBJECT (user), "uid"); + } + + /* Username */ + if ((pwent->pw_name && !user->user_name) || + (!pwent->pw_name && user->user_name) || + (pwent->pw_name && + user->user_name && + strcmp (user->user_name, pwent->pw_name) != 0)) { + g_free (user->user_name); + user->user_name = g_strdup (pwent->pw_name); + g_object_notify (G_OBJECT (user), "user-name"); + } + + /* Home Directory */ + if ((pwent->pw_dir && !user->home_dir) || + (!pwent->pw_dir && user->home_dir) || + strcmp (user->home_dir, pwent->pw_dir) != 0) { + g_free (user->home_dir); + user->home_dir = g_strdup (pwent->pw_dir); + g_object_notify (G_OBJECT (user), "home-directory"); + g_signal_emit (user, signals[ICON_CHANGED], 0); + } + + /* Shell */ + if ((pwent->pw_shell && !user->shell) || + (!pwent->pw_shell && user->shell) || + (pwent->pw_shell && + user->shell && + strcmp (user->shell, pwent->pw_shell) != 0)) { + g_free (user->shell); + user->shell = g_strdup (pwent->pw_shell); + g_object_notify (G_OBJECT (user), "shell"); + } + + g_object_thaw_notify (G_OBJECT (user)); +} + +void +_gdm_user_add_session (GdmUser *user, + const char *ssid) +{ + g_return_if_fail (GDM_IS_USER (user)); + g_return_if_fail (ssid != NULL); + + if (! g_slist_find (user->sessions, ssid)) { + user->sessions = g_slist_append (user->sessions, g_strdup (ssid)); + g_signal_emit (user, signals[SESSIONS_CHANGED], 0); + } +} + +/** + * _gdm_user_remove_session: + * @user: the user to modify. + * @ssid: the session id to remove + * + * Removes @ssid from the list of sessions @user is using, and emits the + * "sessions-changed" signal, if necessary. + * + * Since: 1.0 + **/ +void +_gdm_user_remove_session (GdmUser *user, + const char *ssid) +{ + GSList *li; + + g_return_if_fail (GDM_IS_USER (user)); + g_return_if_fail (ssid != NULL); + + li = g_slist_find (user->sessions, ssid); + if (li != NULL) { + g_free (li->data); + user->sessions = g_slist_delete_link (user->sessions, li); + g_signal_emit (user, signals[SESSIONS_CHANGED], 0); + } +} + +/** + * _gdm_user_icon_changed: + * @user: the user to emit the signal for. + * + * Emits the "icon-changed" signal for @user. + * + * Since: 1.0 + **/ +void +_gdm_user_icon_changed (GdmUser *user) +{ + g_return_if_fail (GDM_IS_USER (user)); + + g_signal_emit (user, signals[ICON_CHANGED], 0); +} + +/** + * gdm_user_get_uid: + * @user: the user object to examine. + * + * Retrieves the ID of @user. + * + * Returns: a pointer to an array of characters which must not be modified or + * freed, or %NULL. + * + * Since: 1.0 + **/ + +uid_t +gdm_user_get_uid (GdmUser *user) +{ + g_return_val_if_fail (GDM_IS_USER (user), -1); + + return user->uid; +} + +/** + * gdm_user_get_real_name: + * @user: the user object to examine. + * + * Retrieves the display name of @user. + * + * Returns: a pointer to an array of characters which must not be modified or + * freed, or %NULL. + * + * Since: 1.0 + **/ +G_CONST_RETURN gchar * +gdm_user_get_real_name (GdmUser *user) +{ + g_return_val_if_fail (GDM_IS_USER (user), NULL); + + return (user->real_name ? user->real_name : user->user_name); +} + +/** + * gdm_user_get_user_name: + * @user: the user object to examine. + * + * Retrieves the login name of @user. + * + * Returns: a pointer to an array of characters which must not be modified or + * freed, or %NULL. + * + * Since: 1.0 + **/ + +G_CONST_RETURN gchar * +gdm_user_get_user_name (GdmUser *user) +{ + g_return_val_if_fail (GDM_IS_USER (user), NULL); + + return user->user_name; +} + +/** + * gdm_user_get_home_directory: + * @user: the user object to examine. + * + * Retrieves the home directory of @user. + * + * Returns: a pointer to an array of characters which must not be modified or + * freed, or %NULL. + * + * Since: 1.0 + **/ + +G_CONST_RETURN gchar * +gdm_user_get_home_directory (GdmUser *user) +{ + g_return_val_if_fail (GDM_IS_USER (user), NULL); + + return user->home_dir; +} + +/** + * gdm_user_get_shell: + * @user: the user object to examine. + * + * Retrieves the login shell of @user. + * + * Returns: a pointer to an array of characters which must not be modified or + * freed, or %NULL. + * + * Since: 1.0 + **/ + +G_CONST_RETURN gchar * +gdm_user_get_shell (GdmUser *user) +{ + g_return_val_if_fail (GDM_IS_USER (user), NULL); + + return user->shell; +} + +/** + * gdm_user_get_displays: + * @user: the user object to examine. + * + * Retrieves a new list of the displays that @user is logged in on. The list + * itself must be freed with g_slist_free() when no longer needed. + * + * Returns: a list of #GdmDisplay objects which must be freed with + * g_slist_free(). + * + * Since: 1.0 + **/ +GSList * +gdm_user_get_sessions (GdmUser *user) +{ + g_return_val_if_fail (GDM_IS_USER (user), NULL); + + return g_slist_copy (user->sessions); +} + +/** + * gdm_user_get_n_sessions: + * @user: the user object to examine. + * + * Retrieves the number of sessions that @user is logged into. + * + * Returns: an unsigned integer. + * + * Since: 1.0 + **/ +guint +gdm_user_get_n_sessions (GdmUser *user) +{ + g_return_val_if_fail (GDM_IS_USER (user), FALSE); + + return g_slist_length (user->sessions); +} + +gint +gdm_user_collate (GdmUser *user1, + GdmUser *user2) +{ + const gchar *str1, *str2; + + g_return_val_if_fail (user1 == NULL || GDM_IS_USER (user1), 0); + g_return_val_if_fail (user2 == NULL || GDM_IS_USER (user2), 0); + + if (!user1 && user2) + return -1; + + if (user1 && !user2) + return 1; + + if (!user1 && !user2) + return 0; + + if (user1->real_name) + str1 = user1->real_name; + else + str1 = user1->user_name; + + if (user2->real_name) + str2 = user2->real_name; + else + str2 = user2->user_name; + + if (!str1 && str2) + return -1; + + if (str1 && !str2) + return 1; + + if (!str1 && !str2) + return 0; + + return g_utf8_collate (str1, str2); +} diff --git a/gui/simple-greeter/gdm-user.h b/gui/simple-greeter/gdm-user.h new file mode 100644 index 00000000..fb091534 --- /dev/null +++ b/gui/simple-greeter/gdm-user.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Facade object for user data, owned by GdmUserManager + */ + +#ifndef __GDM_USER__ +#define __GDM_USER__ 1 + +#include <sys/types.h> +#include <gtk/gtkwidget.h> +#include <gdk-pixbuf/gdk-pixbuf.h> + +G_BEGIN_DECLS + +#define GDM_TYPE_USER (gdm_user_get_type ()) +#define GDM_USER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDM_TYPE_USER, GdmUser)) +#define GDM_IS_USER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDM_TYPE_USER)) + +typedef struct _GdmUser GdmUser; + +GType gdm_user_get_type (void) G_GNUC_CONST; + +uid_t gdm_user_get_uid (GdmUser *user); +G_CONST_RETURN gchar *gdm_user_get_user_name (GdmUser *user); +G_CONST_RETURN gchar *gdm_user_get_real_name (GdmUser *user); +G_CONST_RETURN gchar *gdm_user_get_home_directory (GdmUser *user); +G_CONST_RETURN gchar *gdm_user_get_shell (GdmUser *user); + +GSList *gdm_user_get_sessions (GdmUser *user); +guint gdm_user_get_n_sessions (GdmUser *user); + +GdkPixbuf *gdm_user_render_icon (GdmUser *user, + GtkWidget *widget, + gint icon_size); + +gint gdm_user_collate (GdmUser *user1, + GdmUser *user2); + +G_END_DECLS + +#endif diff --git a/gui/simple-greeter/test-user-chooser.c b/gui/simple-greeter/test-user-chooser.c index d3c9fec2..7efd8c33 100644 --- a/gui/simple-greeter/test-user-chooser.c +++ b/gui/simple-greeter/test-user-chooser.c @@ -29,6 +29,7 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> +#include <libgnomevfs/gnome-vfs-init.h> #include "gdm-user-chooser-dialog.h" @@ -44,6 +45,7 @@ main (int argc, char *argv[]) setlocale (LC_ALL, ""); gtk_init (&argc, &argv); + gnome_vfs_init (); dialog = gdm_user_chooser_dialog_new (); /*gtk_widget_set_size_request (dialog, 480, 128);*/ diff --git a/gui/simple-greeter/test-user-manager.c b/gui/simple-greeter/test-user-manager.c new file mode 100644 index 00000000..436dce18 --- /dev/null +++ b/gui/simple-greeter/test-user-manager.c @@ -0,0 +1,82 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include <stdlib.h> +#include <libintl.h> +#include <locale.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> +#include <errno.h> + +#include <glib/gi18n.h> +#include <gtk/gtk.h> + +#include <libgnomevfs/gnome-vfs-init.h> + +#include "gdm-user-manager.h" + +static GdmUserManager *manager = NULL; + +static void +on_user_added (GdmUserManager *manager, + GdmUser *user, + gpointer data) +{ + g_debug ("User added: %s", gdm_user_get_user_name (user)); +} + +static void +on_user_removed (GdmUserManager *manager, + GdmUser *user, + gpointer data) +{ + g_debug ("User removed: %s", gdm_user_get_user_name (user)); +} + +int +main (int argc, char *argv[]) +{ + GtkWidget *dialog; + + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + setlocale (LC_ALL, ""); + + gtk_init (&argc, &argv); + gnome_vfs_init (); + + manager = gdm_user_manager_ref_default (); + g_signal_connect (manager, + "user-added", + G_CALLBACK (on_user_added), + NULL); + g_signal_connect (manager, + "user-removed", + G_CALLBACK (on_user_removed), + NULL); + + gtk_main (); + + return 0; +} |