gdm r6040 - in trunk: . gui/simple-greeter
- From: mccann svn gnome org
- To: svn-commits-list gnome org
- Subject: gdm r6040 - in trunk: . gui/simple-greeter
- Date: Tue, 18 Mar 2008 19:54:00 +0000 (GMT)
Author: mccann
Date: Tue Mar 18 19:54:00 2008
New Revision: 6040
URL: http://svn.gnome.org/viewvc/gdm?rev=6040&view=rev
Log:
2008-03-18 William Jon McCann <jmccann redhat com>
* gui/simple-greeter/gdm-user-manager.c: (get_seat_id_for_session),
(get_x11_display_for_session), (reload_ck_history),
(reload_passwd), (reload_users), (reload_shells),
(on_shells_monitor_changed), (on_passwd_monitor_changed),
(gdm_user_manager_init), (gdm_user_manager_finalize):
Load local users and monitor passwd for changes.
Modified:
trunk/ChangeLog
trunk/gui/simple-greeter/gdm-user-manager.c
Modified: trunk/gui/simple-greeter/gdm-user-manager.c
==============================================================================
--- trunk/gui/simple-greeter/gdm-user-manager.c (original)
+++ trunk/gui/simple-greeter/gdm-user-manager.c Tue Mar 18 19:54:00 2008
@@ -30,6 +30,10 @@
#include <sys/stat.h>
#include <sys/types.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif /* HAVE_PATHS_H */
+
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
@@ -58,6 +62,17 @@
#define DEFAULT_MAX_ICON_SIZE 128
#define DEFAULT_USER_MAX_FILE 65536
+#ifdef __sun
+#define DEFAULT_MINIMAL_UID 100
+#else
+#define DEFAULT_MINIMAL_UID 500
+#endif
+
+#ifndef _PATH_SHELLS
+#define _PATH_SHELLS "/etc/shells"
+#endif
+#define PATH_PASSWD "/etc/passwd"
+
#define DEFAULT_GLOBAL_FACE_DIR DATADIR "/faces"
#define DEFAULT_USER_ICON "stock_person"
#define DEFAULT_EXCLUDE { "bin", \
@@ -86,10 +101,14 @@
GHashTable *users;
GHashTable *sessions;
GHashTable *exclusions;
+ GHashTable *shells;
DBusGConnection *connection;
DBusGProxy *seat_proxy;
char *seat_id;
+ GFileMonitor *passwd_monitor;
+ GFileMonitor *shells_monitor;
+
guint reload_id;
guint ck_history_id;
@@ -484,7 +503,7 @@
session_id,
CK_SESSION_INTERFACE);
if (proxy == NULL) {
- g_warning ("Failed to connect to the ConsoleKit seat object");
+ g_warning ("Failed to connect to the ConsoleKit session object");
goto out;
}
@@ -524,7 +543,7 @@
session_id,
CK_SESSION_INTERFACE);
if (proxy == NULL) {
- g_warning ("Failed to connect to the ConsoleKit seat object");
+ g_warning ("Failed to connect to the ConsoleKit session object");
goto out;
}
@@ -1174,7 +1193,7 @@
}
static void
-reload_users (GdmUserManager *manager)
+reload_ck_history (GdmUserManager *manager)
{
char *command;
const char *seat_id;
@@ -1240,6 +1259,114 @@
g_free (command);
}
+static void
+reload_passwd (GdmUserManager *manager)
+{
+ struct passwd *pwent;
+ GSList *old_users;
+ GSList *new_users;
+ GSList *list;
+ FILE *fp;
+
+ old_users = NULL;
+ new_users = NULL;
+
+ errno = 0;
+ fp = fopen (PATH_PASSWD, "r");
+ if (fp == NULL) {
+ g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno));
+ goto out;
+ }
+
+ 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_num_sessions (list->data) > 0) {
+ g_object_freeze_notify (G_OBJECT (list->data));
+ new_users = g_slist_prepend (new_users, g_object_ref (list->data));
+ }
+ }
+
+ for (pwent = fgetpwent (fp); pwent != NULL; pwent = fgetpwent (fp)) {
+ GdmUser *user;
+
+ user = NULL;
+
+ /* Skip users below MinimalUID... */
+ if (pwent->pw_uid < DEFAULT_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 = create_user (manager);
+ } 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);
+ }
+
+ /* Go through and handle added users */
+ for (list = new_users; list; list = list->next) {
+ if (! g_slist_find (old_users, list->data)) {
+ add_user (manager, 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));
+ }
+ }
+
+ out:
+ /* Cleanup */
+
+ fclose (fp);
+
+ 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_users (GdmUserManager *manager)
+{
+ reload_ck_history (manager);
+ reload_passwd (manager);
+}
+
static gboolean
reload_users_timeout (GdmUserManager *manager)
{
@@ -1259,6 +1386,54 @@
}
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
+on_shells_monitor_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ GdmUserManager *manager)
+{
+ if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
+ event_type != G_FILE_MONITOR_EVENT_CREATED) {
+ return;
+ }
+
+ reload_shells (manager);
+ reload_passwd (manager);
+}
+
+static void
+on_passwd_monitor_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ GdmUserManager *manager)
+{
+ if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
+ event_type != G_FILE_MONITOR_EVENT_CREATED) {
+ return;
+ }
+
+ reload_passwd (manager);
+}
+
+static void
gdm_user_manager_class_init (GdmUserManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -1305,6 +1480,8 @@
gdm_user_manager_init (GdmUserManager *manager)
{
int i;
+ GFile *file;
+ GError *error;
const char *exclude_default[] = DEFAULT_EXCLUDE;
manager->priv = GDM_USER_MANAGER_GET_PRIVATE (manager);
@@ -1326,10 +1503,50 @@
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);
+ file = g_file_new_for_path (_PATH_SHELLS);
+ error = NULL;
+ manager->priv->shells_monitor = g_file_monitor_file (file,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ &error);
+ if (manager->priv->shells_monitor != NULL) {
+ g_signal_connect (manager->priv->shells_monitor,
+ "changed",
+ G_CALLBACK (on_shells_monitor_changed),
+ manager);
+ } else {
+ g_warning ("Unable to monitor %s: %s", _PATH_SHELLS, error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+
+ /* /etc/passwd */
manager->priv->users = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify) g_object_run_dispose);
+ file = g_file_new_for_path (PATH_PASSWD);
+ manager->priv->passwd_monitor = g_file_monitor_file (file,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ &error);
+ if (manager->priv->shells_monitor != NULL) {
+ g_signal_connect (manager->priv->passwd_monitor,
+ "changed",
+ G_CALLBACK (on_passwd_monitor_changed),
+ manager);
+ } else {
+ g_warning ("Unable to monitor %s: %s", PATH_PASSWD, error->message);
+ g_error_free (error);
+ }
+ g_object_unref (file);
+
get_seat_proxy (manager);
@@ -1366,8 +1583,12 @@
g_hash_table_destroy (manager->priv->sessions);
+ g_file_monitor_cancel (manager->priv->passwd_monitor);
g_hash_table_destroy (manager->priv->users);
+ g_file_monitor_cancel (manager->priv->shells_monitor);
+ g_hash_table_destroy (manager->priv->shells);
+
g_free (manager->priv->seat_id);
G_OBJECT_CLASS (gdm_user_manager_parent_class)->finalize (object);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]