diff --git a/.gitignore b/.gitignore
index a102587..da569df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ gnome-screensaver-2.30.0.tar.bz2
/gnome-screensaver-2.91.3.tar.bz2
/gnome-screensaver-2.91.4.tar.bz2
/gnome-screensaver-2.91.90.tar.bz2
+/gnome-screensaver-2.91.91.tar.bz2
diff --git a/gnome-screensaver-2.20.0-blank-by-default.patch b/gnome-screensaver-2.20.0-blank-by-default.patch
deleted file mode 100644
index 618e693..0000000
--- a/gnome-screensaver-2.20.0-blank-by-default.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- gnome-screensaver-2.20.0/data/gnome-screensaver.schemas.in.orig 2007-10-29 15:02:52.000000000 -0400
-+++ gnome-screensaver-2.20.0/data/gnome-screensaver.schemas.in 2007-10-29 15:05:29.000000000 -0400
-@@ -55,7 +55,7 @@
- gnome-screensaver
- list
- string
-- [screensavers-system]
-+ [blank-only]
-
- Screensaver themes
-
diff --git a/gnome-screensaver-2.20.0-default-theme.patch b/gnome-screensaver-2.20.0-default-theme.patch
deleted file mode 100644
index 1496d71..0000000
--- a/gnome-screensaver-2.20.0-default-theme.patch
+++ /dev/null
@@ -1,20 +0,0 @@
---- gnome-screensaver-2.15.4/data/gnome-screensaver.schemas.in.use-floaters-by-default 2006-06-08 16:37:39.000000000 -0400
-+++ gnome-screensaver-2.15.4/data/gnome-screensaver.schemas.in 2006-07-11 10:15:54.000000000 -0400
-@@ -36,7 +36,7 @@
- /apps/gnome-screensaver/mode
- gnome-screensaver
- string
-- blank-only
-+ single
-
- Screensaver theme selection mode
-
-@@ -55,7 +55,7 @@
- gnome-screensaver
- list
- string
-- []
-+ [screensavers-system]
-
- Screensaver themes
-
diff --git a/gnome-screensaver-2.26.0-securitytoken.patch b/gnome-screensaver-2.26.0-securitytoken.patch
deleted file mode 100644
index 6a7c3c4..0000000
--- a/gnome-screensaver-2.26.0-securitytoken.patch
+++ /dev/null
@@ -1,2907 +0,0 @@
-diff -up gnome-screensaver-2.26.0/configure.ac.securitytoken gnome-screensaver-2.26.0/configure.ac
---- gnome-screensaver-2.26.0/configure.ac.securitytoken 2009-03-18 13:20:20.000000000 -0400
-+++ gnome-screensaver-2.26.0/configure.ac 2009-03-19 00:20:36.625194934 -0400
-@@ -45,6 +45,7 @@ GNOME_DESKTOP_REQUIRED_VERSION=2.23.2
-
- GLADE_REQUIRED_VERSION=2.5.0
- LIBGNOMEKBDUI_REQUIRED_VERSION=0.1
-+NSS_REQUIRED_VERSION=3.11.2
-
- AC_CHECK_HEADERS(unistd.h)
- AC_CHECK_HEADERS(crypt.h sys/select.h)
-@@ -59,7 +60,8 @@ PKG_CHECK_MODULES(GNOME_SCREENSAVER,
- dbus-glib-1 >= $DBUS_REQUIRED_VERSION
- gconf-2.0 >= $GCONF_REQUIRED_VERSION
- gnome-desktop-2.0 >= $GNOME_DESKTOP_REQUIRED_VERSION
-- libgnome-menu >= $LIBGNOME_MENU_REQUIRED_VERSION)
-+ libgnome-menu >= $LIBGNOME_MENU_REQUIRED_VERSION
-+ nss >= $NSS_REQUIRED_VERSION)
- AC_SUBST(GNOME_SCREENSAVER_CFLAGS)
- AC_SUBST(GNOME_SCREENSAVER_LIBS)
-
-@@ -96,8 +98,6 @@ AC_PATH_PROG(GCONFTOOL, gconftool-2)
-
- AM_GCONF_SOURCE_2
-
--GNOME_COMPILE_WARNINGS(yes)
--
- # Solaris requires libresolv for daemon()
- case "$host" in
- *-*-solaris*)
-@@ -171,6 +171,13 @@ PKG_CHECK_MODULES(LIB_GNOME_MENU,
- AC_SUBST(LIB_GNOME_MENU_CFLAGS)
- AC_SUBST(LIB_GNOME_MENU_LIBS)
-
-+# security token support
-+PKG_CHECK_MODULES(SECURITY_TOKEN,
-+ gobject-2.0 >= $GLIB_REQUIRED_VERSION
-+ nss >= $NSS_REQUIRED_VERSION)
-+AC_SUBST(SECURITY_TOKEN_CFLAGS)
-+AC_SUBST(SECURITY_TOKEN_LIBS)
-+
- dnl ---------------------------------------------------------------------------
- dnl - Where should we put documentation ?
- dnl ---------------------------------------------------------------------------
-diff -up gnome-screensaver-2.26.0/src/gs-auth-pam.c.securitytoken gnome-screensaver-2.26.0/src/gs-auth-pam.c
---- gnome-screensaver-2.26.0/src/gs-auth-pam.c.securitytoken 2009-03-18 11:39:58.000000000 -0400
-+++ gnome-screensaver-2.26.0/src/gs-auth-pam.c 2009-03-19 00:20:36.632207149 -0400
-@@ -354,6 +354,13 @@ close_pam_handle (int status)
- status2,
- (status2 == PAM_SUCCESS ? "Success" : "Failure"));
- }
-+
-+ /* iterate the glib event loop inbetween processing pam
-+ * messages so that the user interface can be updated
-+ * to reflect changes that are a result of the pam
-+ * messages
-+ */
-+ while (g_main_context_iteration (NULL, FALSE));
- }
-
- if (message_handled_condition != NULL) {
-diff -up gnome-screensaver-2.26.0/src/gs-monitor.c.securitytoken gnome-screensaver-2.26.0/src/gs-monitor.c
---- gnome-screensaver-2.26.0/src/gs-monitor.c.securitytoken 2009-03-18 11:39:58.000000000 -0400
-+++ gnome-screensaver-2.26.0/src/gs-monitor.c 2009-03-19 00:46:39.466197461 -0400
-@@ -41,10 +41,15 @@
- #include "gs-prefs.h"
- #include "gs-debug.h"
-
-+#include "securitytokenmonitor.h"
-+
- static void gs_monitor_class_init (GSMonitorClass *klass);
- static void gs_monitor_init (GSMonitor *monitor);
- static void gs_monitor_finalize (GObject *object);
-
-+static void gs_monitor_simulate_user_activity (GSMonitor *monitor);
-+static void gs_monitor_lock_screen (GSMonitor *monitor);
-+
- #define GS_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_MONITOR, GSMonitorPrivate))
-
- struct GSMonitorPrivate
-@@ -56,6 +61,7 @@ struct GSMonitorPrivate
- GSFade *fade;
- GSGrab *grab;
- guint release_grab_id;
-+ ScSecurityTokenMonitor *security_token_monitor;
- };
-
- #define FADE_TIMEOUT 10000
-@@ -85,6 +91,36 @@ manager_deactivated_cb (GSManager *manag
- gs_listener_set_active (monitor->priv->listener, FALSE);
- }
-
-+static void
-+security_token_inserted_cb (ScSecurityTokenMonitor *token_monitor,
-+ ScSecurityToken *token,
-+ GSMonitor *monitor)
-+{
-+ gs_monitor_simulate_user_activity (monitor);
-+}
-+
-+static gboolean
-+gs_monitor_should_lock_on_login_security_token_removal (void)
-+{
-+ /* FIXME: lame hack
-+ */
-+ return system ("pkcs11_setup rm_action | grep -q lock") == 0;
-+}
-+
-+static void
-+security_token_removed_cb (ScSecurityTokenMonitor *token_monitor,
-+ ScSecurityToken *token,
-+ GSMonitor *monitor)
-+{
-+ if (gs_monitor_should_lock_on_login_security_token_removal () &&
-+ sc_security_token_is_login_token (token))
-+ gs_monitor_lock_screen (monitor);
-+
-+ /* If we're already locked and the lock dialog is up, kill it.
-+ */
-+ gs_manager_cancel_unlock_request (monitor->priv->manager);
-+}
-+
- static gboolean
- watcher_idle_cb (GSWatcher *watcher,
- gboolean is_idle,
-@@ -165,35 +201,6 @@ watcher_idle_notice_cb (GSWatcher *watch
- }
-
- static void
--gs_monitor_lock_screen (GSMonitor *monitor)
--{
-- gboolean res;
-- gboolean locked;
--
-- /* set lock flag before trying to activate screensaver
-- in case something tries to react to the ActiveChanged signal */
--
-- gs_manager_get_lock_active (monitor->priv->manager, &locked);
-- gs_manager_set_lock_active (monitor->priv->manager, TRUE);
-- res = gs_listener_set_active (monitor->priv->listener, TRUE);
-- if (! res) {
-- /* If we've failed then restore lock status */
-- gs_manager_set_lock_active (monitor->priv->manager, locked);
-- gs_debug ("Unable to lock the screen");
-- }
--}
--
--static void
--gs_monitor_simulate_user_activity (GSMonitor *monitor)
--{
-- /* FIXME: reset the xsync timer? */
--
-- /* request that the manager unlock -
-- will pop up a dialog if necessary */
-- gs_manager_request_unlock (monitor->priv->manager);
--}
--
--static void
- listener_lock_cb (GSListener *listener,
- GSMonitor *monitor)
- {
-@@ -401,6 +408,27 @@ connect_manager_signals (GSMonitor *moni
- }
-
- static void
-+disconnect_security_token_monitor_signals (GSMonitor *monitor)
-+{
-+ g_signal_handlers_disconnect_by_func (monitor->priv->security_token_monitor,
-+ security_token_removed_cb, monitor);
-+
-+ g_signal_handlers_disconnect_by_func (monitor->priv->security_token_monitor,
-+ security_token_inserted_cb, monitor);
-+}
-+
-+static void
-+connect_security_token_monitor_signals (GSMonitor *monitor)
-+{
-+ g_signal_connect (monitor->priv->security_token_monitor,
-+ "security-token-removed",
-+ G_CALLBACK (security_token_removed_cb), monitor);
-+ g_signal_connect (monitor->priv->security_token_monitor,
-+ "security-token-inserted",
-+ G_CALLBACK (security_token_inserted_cb), monitor);
-+}
-+
-+static void
- disconnect_prefs_signals (GSMonitor *monitor)
- {
- g_signal_handlers_disconnect_by_func (monitor->priv->prefs, _gs_monitor_update_from_prefs, monitor);
-@@ -434,6 +462,26 @@ gs_monitor_init (GSMonitor *monitor)
- monitor->priv->manager = gs_manager_new ();
- connect_manager_signals (monitor);
-
-+ /* PKCS11_LOGIN_TOKEN_NAME is set if the user logged in with a
-+ * security token.
-+ */
-+ if (g_getenv ("PKCS11_LOGIN_TOKEN_NAME") != NULL) {
-+ monitor->priv->security_token_monitor = sc_security_token_monitor_new (NULL);
-+ sc_security_token_monitor_start (monitor->priv->security_token_monitor,
-+ NULL);
-+ connect_security_token_monitor_signals (monitor);
-+
-+ /* if the user logged in with a security token but it's
-+ * not currently inserted, then they must have yanked it
-+ * before we started. lock the screen immediately
-+ */
-+ if (gs_monitor_should_lock_on_login_security_token_removal () &&
-+ !sc_security_token_monitor_login_token_is_inserted (monitor->priv->security_token_monitor))
-+ gs_monitor_lock_screen (monitor);
-+ } else {
-+ monitor->priv->security_token_monitor = NULL;
-+ }
-+
- _gs_monitor_update_from_prefs (monitor, monitor->priv->prefs);
- }
-
-@@ -449,6 +497,12 @@ gs_monitor_finalize (GObject *object)
-
- g_return_if_fail (monitor->priv != NULL);
-
-+ if (monitor->priv->security_token_monitor != NULL) {
-+ sc_security_token_monitor_stop (monitor->priv->security_token_monitor);
-+ disconnect_security_token_monitor_signals (monitor);
-+ g_object_unref (monitor->priv->security_token_monitor);
-+ }
-+
- disconnect_watcher_signals (monitor);
- disconnect_listener_signals (monitor);
- disconnect_manager_signals (monitor);
-@@ -486,3 +540,30 @@ gs_monitor_start (GSMonitor *monitor,
-
- return TRUE;
- }
-+
-+static void
-+gs_monitor_simulate_user_activity (GSMonitor *monitor)
-+{
-+ /* request that the manager unlock -
-+ will pop up a dialog if necessary */
-+ gs_manager_request_unlock (monitor->priv->manager);
-+}
-+
-+static void
-+gs_monitor_lock_screen (GSMonitor *monitor)
-+{
-+ gboolean res;
-+ gboolean locked;
-+
-+ /* set lock flag before trying to activate screensaver
-+ in case something tries to react to the ActiveChanged signal */
-+
-+ gs_manager_get_lock_active (monitor->priv->manager, &locked);
-+ gs_manager_set_lock_active (monitor->priv->manager, TRUE);
-+ res = gs_listener_set_active (monitor->priv->listener, TRUE);
-+ if (! res) {
-+ /* If we've failed then restore lock status */
-+ gs_manager_set_lock_active (monitor->priv->manager, locked);
-+ gs_debug ("Unable to lock the screen");
-+ }
-+}
-diff -upr gnome-screensaver-2.27.0.orig/src/Makefile.am gnome-screensaver-2.27.0/src/Makefile.am
---- gnome-screensaver-2.27.0.orig/src/Makefile.am 2009-06-15 18:35:56.000000000 +0100
-+++ gnome-screensaver-2.27.0/src/Makefile.am 2009-06-26 16:25:29.000000000 +0100
-@@ -56,6 +56,18 @@ desktop_in_files = gnome-screensaver.des
- desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
- @INTLTOOL_DESKTOP_RULE@
-
-+noinst_LIBRARIES = libsecuritytoken.a
-+
-+libsecuritytoken_a_SOURCES = \
-+ securitytoken.h \
-+ securitytoken.c \
-+ securitytokenmonitor.h \
-+ securitytokenmonitor.c
-+
-+libsecuritytoken_a_CFLAGS = $(SECURITY_TOKEN_CFLAGS) \
-+ -DLIBDIR=\""$(libdir)"\" \
-+ -DSYSCONFDIR=\""$(sysconfdir)"\"
-+
- gnome_screensaver_command_SOURCES = \
- gnome-screensaver-command.c \
- $(NULL)
-@@ -213,6 +225,7 @@ gnome_screensaver_gl_helper_SOURCES = \
- gnome_screensaver_LDADD = \
- $(GNOME_SCREENSAVER_LIBS) \
- $(SAVER_LIBS) \
-+ $(top_builddir)/src/libsecuritytoken.a \
- $(NULL)
-
- gnome_screensaver_LDFLAGS = -export-dynamic
-diff -up /dev/null gnome-screensaver-2.26.0/src/securitytoken.c
---- /dev/null 2009-03-18 22:51:48.055015100 -0400
-+++ gnome-screensaver-2.26.0/src/securitytoken.c 2009-03-19 00:20:36.637204629 -0400
-@@ -0,0 +1,680 @@
-+/* securitytoken.c - security token
-+ *
-+ * Copyright (C) 2006 Ray Strode
-+ *
-+ * 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, 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.
-+ *
-+ * TODO: - doing this per project is a bad idea i think.
-+ * We should probably make this a system service
-+ * and use dbus.
-+ *
-+ * - We hardcode a driver right now. We should probably
-+ * look up the default list and go from there.
-+ */
-+#define SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
-+#include "securitytoken.h"
-+
-+#include
-+#include
-+#include
-+
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#if defined (SC_SECURITY_TOKEN_ENABLE_TEST) || defined (SC_SECURITY_TOKEN_MONITOR_ENABLE_TEST)
-+#define sc_debug(format, args...) g_printerr (format "\n", ##args)
-+#define sc_warning(format, args...) g_printerr (format "\n", ##args)
-+#else
-+#define sc_debug(format, args...)
-+#define sc_warning(format, args...)
-+#endif
-+
-+struct _ScSecurityTokenPrivate {
-+ SECMODModule *module;
-+ ScSecurityTokenState state;
-+
-+ CK_SLOT_ID slot_id;
-+ gint slot_series;
-+
-+ PK11SlotInfo *slot;
-+ gchar *name;
-+
-+ CERTCertificate *signing_certificate;
-+ CERTCertificate *encryption_certificate;
-+};
-+
-+static void sc_security_token_finalize (GObject *object);
-+static void sc_security_token_class_install_signals (ScSecurityTokenClass *token_class);
-+static void sc_security_token_class_install_properties (ScSecurityTokenClass *token_class);
-+static void sc_security_token_set_property (GObject *object,
-+ guint prop_id,
-+ const GValue *value,
-+ GParamSpec *pspec);
-+static void sc_security_token_get_property (GObject *object,
-+ guint prop_id,
-+ GValue *value,
-+ GParamSpec *pspec);
-+static void sc_security_token_set_name (ScSecurityToken *token, const gchar *name);
-+static void sc_security_token_set_slot_id (ScSecurityToken *token,
-+ gint slot_id);
-+static void sc_security_token_set_slot_series (ScSecurityToken *token,
-+ gint slot_series);
-+static void sc_security_token_set_module (ScSecurityToken *token,
-+ SECMODModule *module);
-+
-+static PK11SlotInfo *sc_security_token_find_slot_from_id (ScSecurityToken *token,
-+ gint slot_id);
-+
-+static PK11SlotInfo *sc_security_token_find_slot_from_token_name (ScSecurityToken *token,
-+ const gchar *token_name);
-+static gboolean sc_security_token_fetch_certificates (ScSecurityToken *token);
-+
-+
-+#ifndef SC_SECURITY_TOKEN_DEFAULT_SLOT_ID
-+#define SC_SECURITY_TOKEN_DEFAULT_SLOT_ID ((gulong) -1)
-+#endif
-+
-+#ifndef SC_SECURITY_TOKEN_DEFAULT_SLOT_SERIES
-+#define SC_SECURITY_TOKEN_DEFAULT_SLOT_SERIES -1
-+#endif
-+
-+enum {
-+ PROP_0 = 0,
-+ PROP_NAME,
-+ PROP_SLOT_ID,
-+ PROP_SLOT_SERIES,
-+ PROP_MODULE,
-+ NUMBER_OF_PROPERTIES
-+};
-+
-+enum {
-+ INSERTED,
-+ REMOVED,
-+ NUMBER_OF_SIGNALS
-+};
-+
-+static guint sc_security_token_signals[NUMBER_OF_SIGNALS];
-+
-+G_DEFINE_TYPE (ScSecurityToken, sc_security_token, G_TYPE_OBJECT);
-+
-+static void
-+sc_security_token_class_init (ScSecurityTokenClass *token_class)
-+{
-+ GObjectClass *gobject_class;
-+
-+ gobject_class = G_OBJECT_CLASS (token_class);
-+
-+ gobject_class->finalize = sc_security_token_finalize;
-+
-+ sc_security_token_class_install_signals (token_class);
-+ sc_security_token_class_install_properties (token_class);
-+
-+ g_type_class_add_private (token_class,
-+ sizeof (ScSecurityTokenPrivate));
-+}
-+
-+static void
-+sc_security_token_class_install_signals (ScSecurityTokenClass *token_class)
-+{
-+ GObjectClass *object_class;
-+
-+ object_class = G_OBJECT_CLASS (token_class);
-+
-+ sc_security_token_signals[INSERTED] =
-+ g_signal_new ("inserted",
-+ G_OBJECT_CLASS_TYPE (object_class),
-+ G_SIGNAL_RUN_LAST,
-+ G_STRUCT_OFFSET (ScSecurityTokenClass,
-+ inserted),
-+ NULL, NULL, g_cclosure_marshal_VOID__VOID,
-+ G_TYPE_NONE, 0);
-+ token_class->inserted = NULL;
-+
-+ sc_security_token_signals[REMOVED] =
-+ g_signal_new ("removed",
-+ G_OBJECT_CLASS_TYPE (object_class),
-+ G_SIGNAL_RUN_LAST,
-+ G_STRUCT_OFFSET (ScSecurityTokenClass,
-+ removed),
-+ NULL, NULL, g_cclosure_marshal_VOID__VOID,
-+ G_TYPE_NONE, 0);
-+ token_class->removed = NULL;
-+}
-+
-+static void
-+sc_security_token_class_install_properties (ScSecurityTokenClass *token_class)
-+{
-+ GObjectClass *object_class;
-+ GParamSpec *param_spec;
-+
-+ object_class = G_OBJECT_CLASS (token_class);
-+ object_class->set_property = sc_security_token_set_property;
-+ object_class->get_property = sc_security_token_get_property;
-+
-+ param_spec = g_param_spec_ulong ("slot-id", _("Slot ID"),
-+ _("The slot the token is in"),
-+ 1, G_MAXULONG,
-+ SC_SECURITY_TOKEN_DEFAULT_SLOT_ID,
-+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-+ g_object_class_install_property (object_class, PROP_SLOT_ID, param_spec);
-+
-+ param_spec = g_param_spec_int ("slot-series", _("Slot Series"),
-+ _("per-slot token identifier"),
-+ -1, G_MAXINT,
-+ SC_SECURITY_TOKEN_DEFAULT_SLOT_SERIES,
-+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-+ g_object_class_install_property (object_class, PROP_SLOT_SERIES, param_spec);
-+
-+ param_spec = g_param_spec_string ("name", _("name"),
-+ _("name"), NULL,
-+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-+ g_object_class_install_property (object_class, PROP_NAME, param_spec);
-+
-+ param_spec = g_param_spec_pointer ("module", _("Module"),
-+ _("security token driver"),
-+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
-+ g_object_class_install_property (object_class, PROP_MODULE, param_spec);
-+}
-+
-+static void
-+sc_security_token_set_property (GObject *object,
-+ guint prop_id,
-+ const GValue *value,
-+ GParamSpec *pspec)
-+{
-+ ScSecurityToken *token = SC_SECURITY_TOKEN (object);
-+
-+ switch (prop_id)
-+ {
-+ case PROP_NAME:
-+ sc_security_token_set_name (token, g_value_get_string (value));
-+ break;
-+
-+ case PROP_SLOT_ID:
-+ sc_security_token_set_slot_id (token,
-+ g_value_get_ulong (value));
-+ break;
-+
-+ case PROP_SLOT_SERIES:
-+ sc_security_token_set_slot_series (token,
-+ g_value_get_int (value));
-+ break;
-+
-+ case PROP_MODULE:
-+ sc_security_token_set_module (token,
-+ (SECMODModule *)
-+ g_value_get_pointer (value));
-+ break;
-+
-+ default:
-+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-+ }
-+}
-+
-+CK_SLOT_ID
-+sc_security_token_get_slot_id (ScSecurityToken *token)
-+{
-+ return token->priv->slot_id;
-+}
-+
-+ScSecurityTokenState
-+sc_security_token_get_state (ScSecurityToken *token)
-+{
-+ return token->priv->state;
-+}
-+
-+gchar *
-+sc_security_token_get_name (ScSecurityToken *token)
-+{
-+ return g_strdup (token->priv->name);
-+}
-+
-+gboolean
-+sc_security_token_is_login_token (ScSecurityToken *token)
-+{
-+ const gchar *login_token_name;
-+ login_token_name = g_getenv ("PKCS11_LOGIN_TOKEN_NAME");
-+
-+ if ((login_token_name == NULL) || (token->priv->name == NULL))
-+ return FALSE;
-+
-+ if (strcmp (token->priv->name, login_token_name) == 0)
-+ return TRUE;
-+
-+ return FALSE;
-+}
-+
-+static void
-+sc_security_token_get_property (GObject *object,
-+ guint prop_id,
-+ GValue *value,
-+ GParamSpec *pspec)
-+{
-+ ScSecurityToken *token = SC_SECURITY_TOKEN (object);
-+
-+ switch (prop_id)
-+ {
-+ case PROP_NAME:
-+ g_value_take_string (value,
-+ sc_security_token_get_name (token));
-+ break;
-+
-+ case PROP_SLOT_ID:
-+ g_value_set_ulong (value,
-+ (gulong) sc_security_token_get_slot_id (token));
-+ break;
-+
-+ case PROP_SLOT_SERIES:
-+ g_value_set_int (value,
-+ sc_security_token_get_slot_series (token));
-+ break;
-+
-+ default:
-+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-+ }
-+}
-+
-+static void
-+sc_security_token_set_name (ScSecurityToken *token,
-+ const gchar *name)
-+{
-+ if (name == NULL)
-+ return;
-+
-+ if ((token->priv->name == NULL) ||
-+ (strcmp (token->priv->name, name) != 0)) {
-+ g_free (token->priv->name);
-+ token->priv->name = g_strdup (name);
-+
-+ if (token->priv->slot == NULL) {
-+ token->priv->slot = sc_security_token_find_slot_from_token_name (token,
-+ token->priv->name);
-+
-+ if (token->priv->slot != NULL) {
-+ gint slot_id, slot_series;
-+
-+ slot_id = PK11_GetSlotID (token->priv->slot);
-+ if (slot_id != token->priv->slot_id)
-+ sc_security_token_set_slot_id (token, slot_id);
-+
-+ slot_series = PK11_GetSlotSeries (token->priv->slot);
-+ if (slot_series != token->priv->slot_series)
-+ sc_security_token_set_slot_series (token, slot_series);
-+
-+ _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_INSERTED);
-+ } else {
-+ _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_REMOVED);
-+ }
-+ }
-+
-+
-+ g_object_notify (G_OBJECT (token), "name");
-+ }
-+}
-+
-+static void
-+sc_security_token_set_slot_id (ScSecurityToken *token,
-+ gint slot_id)
-+{
-+ if (token->priv->slot_id != slot_id)
-+ {
-+ token->priv->slot_id = slot_id;
-+
-+ if (token->priv->slot == NULL) {
-+ token->priv->slot = sc_security_token_find_slot_from_id (token,
-+ token->priv->slot_id);
-+
-+ if (token->priv->slot != NULL) {
-+ const gchar *token_name;
-+
-+ token_name = PK11_GetTokenName (token->priv->slot);
-+ if ((token->priv->name == NULL) ||
-+ ((token_name != NULL) &&
-+ (strcmp (token_name, token->priv->name) != 0)))
-+ sc_security_token_set_name (token, token_name);
-+
-+ _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_INSERTED);
-+ } else {
-+ _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_REMOVED);
-+ }
-+ }
-+
-+ g_object_notify (G_OBJECT (token), "slot-id");
-+ }
-+}
-+
-+static void
-+sc_security_token_set_slot_series (ScSecurityToken *token,
-+ gint slot_series)
-+{
-+ if (token->priv->slot_series != slot_series)
-+ {
-+ token->priv->slot_series = slot_series;
-+ g_object_notify (G_OBJECT (token), "slot-series");
-+ }
-+}
-+
-+static void
-+sc_security_token_set_module (ScSecurityToken *token,
-+ SECMODModule *module)
-+{
-+ gboolean should_notify;
-+
-+ if (token->priv->module != module)
-+ should_notify = TRUE;
-+ else
-+ should_notify = FALSE;
-+
-+ if (token->priv->module != NULL) {
-+ SECMOD_DestroyModule (token->priv->module);
-+ token->priv->module = NULL;
-+ }
-+
-+ if (module != NULL)
-+ token->priv->module = SECMOD_ReferenceModule (module);
-+
-+ if (should_notify)
-+ g_object_notify (G_OBJECT (token), "module");
-+}
-+
-+gint
-+sc_security_token_get_slot_series (ScSecurityToken *token)
-+{
-+ return token->priv->slot_series;
-+}
-+
-+static void
-+sc_security_token_init (ScSecurityToken *token)
-+{
-+
-+ sc_debug ("initializing security token ");
-+
-+ token->priv = G_TYPE_INSTANCE_GET_PRIVATE (token,
-+ SC_TYPE_SECURITY_TOKEN,
-+ ScSecurityTokenPrivate);
-+
-+ if (token->priv->slot != NULL)
-+ token->priv->name = g_strdup (PK11_GetTokenName (token->priv->slot));
-+}
-+
-+static void sc_security_token_finalize (GObject *object)
-+{
-+ ScSecurityToken *token;
-+ GObjectClass *gobject_class;
-+
-+ token = SC_SECURITY_TOKEN (object);
-+
-+ g_free (token->priv->name);
-+
-+ sc_security_token_set_module (token, NULL);
-+
-+ gobject_class =
-+ G_OBJECT_CLASS (sc_security_token_parent_class);
-+
-+ gobject_class->finalize (object);
-+}
-+
-+GQuark sc_security_token_error_quark (void)
-+{
-+ static GQuark error_quark = 0;
-+
-+ if (error_quark == 0)
-+ error_quark = g_quark_from_static_string ("sc-security-token-error-quark");
-+
-+ return error_quark;
-+}
-+
-+ScSecurityToken *
-+_sc_security_token_new (SECMODModule *module,
-+ CK_SLOT_ID slot_id,
-+ gint slot_series)
-+{
-+ ScSecurityToken *token;
-+
-+ g_return_val_if_fail (module != NULL, NULL);
-+ g_return_val_if_fail (slot_id >= 1, NULL);
-+ g_return_val_if_fail (slot_series > 0, NULL);
-+ g_return_val_if_fail (sizeof (gulong) == sizeof (slot_id), NULL);
-+
-+ token = SC_SECURITY_TOKEN (g_object_new (SC_TYPE_SECURITY_TOKEN,
-+ "module", module,
-+ "slot-id", (gulong) slot_id,
-+ "slot-series", slot_series,
-+ NULL));
-+ return token;
-+}
-+
-+ScSecurityToken *
-+_sc_security_token_new_from_name (SECMODModule *module,
-+ const gchar *name)
-+{
-+ ScSecurityToken *token;
-+
-+ g_return_val_if_fail (module != NULL, NULL);
-+ g_return_val_if_fail (name != NULL, NULL);
-+
-+ token = SC_SECURITY_TOKEN (g_object_new (SC_TYPE_SECURITY_TOKEN,
-+ "module", module,
-+ "name", name,
-+ NULL));
-+ return token;
-+}
-+
-+void
-+_sc_security_token_set_state (ScSecurityToken *token,
-+ ScSecurityTokenState state)
-+{
-+ /* sc_security_token_fetch_certificates (token); */
-+ if (token->priv->state != state)
-+ {
-+ token->priv->state = state;
-+
-+ if (state == SC_SECURITY_TOKEN_STATE_INSERTED) {
-+ g_signal_emit (token, sc_security_token_signals[INSERTED], 0);
-+ } else if (state == SC_SECURITY_TOKEN_STATE_REMOVED)
-+ g_signal_emit (token, sc_security_token_signals[REMOVED], 0);
-+ else
-+ g_assert_not_reached ();
-+ }
-+}
-+
-+/* So we could conceivably make the closure data a pointer to the token
-+ * or something similiar and then emit signals when we want passwords,
-+ * but it's probably easier to just get the password up front and use
-+ * it. So we just take the passed in g_malloc'd (well probably, who knows)
-+ * and strdup it using NSPR's memory allocation routines.
-+ */
-+static char *
-+sc_security_token_password_handler (PK11SlotInfo *slot,
-+ PRBool is_retrying,
-+ const gchar *password)
-+{
-+ if (is_retrying)
-+ return NULL;
-+
-+ return password != NULL? PL_strdup (password): NULL;
-+}
-+
-+gboolean
-+sc_security_token_unlock (ScSecurityToken *token,
-+ const gchar *password)
-+{
-+ SECStatus status;
-+
-+ PK11_SetPasswordFunc ((PK11PasswordFunc) sc_security_token_password_handler);
-+
-+ /* we pass PR_TRUE to load certificates
-+ */
-+ status = PK11_Authenticate (token->priv->slot, PR_TRUE, (gpointer) password);
-+
-+ if (status != SECSuccess) {
-+ sc_debug ("could not unlock token - %d", status);
-+ return FALSE;
-+ }
-+ return TRUE;
-+}
-+
-+static PK11SlotInfo *
-+sc_security_token_find_slot_from_token_name (ScSecurityToken *token,
-+ const gchar *token_name)
-+{
-+ int i;
-+
-+ for (i = 0; i < token->priv->module->slotCount; i++) {
-+ const gchar *slot_token_name;
-+
-+ slot_token_name = PK11_GetTokenName (token->priv->module->slots[i]);
-+
-+ if ((slot_token_name != NULL) &&
-+ (strcmp (slot_token_name, token_name) == 0))
-+ return token->priv->module->slots[i];
-+ }
-+
-+ return NULL;
-+}
-+
-+static PK11SlotInfo *
-+sc_security_token_find_slot_from_id (ScSecurityToken *token,
-+ gint slot_id)
-+{
-+ int i;
-+
-+ for (i = 0; i < token->priv->module->slotCount; i++)
-+ if (PK11_GetSlotID (token->priv->module->slots[i]) == slot_id)
-+ return token->priv->module->slots[i];
-+
-+ return NULL;
-+}
-+
-+static gboolean
-+sc_security_token_fetch_certificates (ScSecurityToken *token)
-+{
-+ PK11SlotInfo *slot;
-+ CERTCertList *certificates;
-+ CERTCertListNode *node;
-+ SECStatus status;
-+ int i;
-+
-+ sc_security_token_unlock (token, "0000");
-+
-+ sc_debug ("fetching certificates for token in slot %lu",
-+ token->priv->slot_id);
-+
-+ slot = sc_security_token_find_slot_from_id (token,
-+ token->priv->slot_id);
-+
-+ g_assert (PK11_GetSlotID (slot) == token->priv->slot_id);
-+
-+ if (i == token->priv->module->slotCount) {
-+ sc_debug ("could not find slot %lu", token->priv->slot_id);
-+ return FALSE;
-+ }
-+
-+ certificates = PK11_ListCertsInSlot (slot);
-+
-+ sc_debug ("filtering out non-user certificates");
-+ if (CERT_FilterCertListForUserCerts (certificates) != SECSuccess) {
-+ CERT_DestroyCertList (certificates);
-+ sc_debug ("could not filter out non-user certificates");
-+ return FALSE;
-+ }
-+
-+ for (node = CERT_LIST_HEAD (certificates);
-+ !CERT_LIST_END (node, certificates);
-+ node = CERT_LIST_NEXT(node)) {
-+
-+ SECCertificateUsage cert_usages;
-+
-+ sc_debug ("verifying certificate for use");
-+ status = CERT_VerifyCertificateNow (NULL, node->cert, TRUE,
-+ 0, NULL, &cert_usages);
-+
-+ if (status != SECSuccess) {
-+ sc_debug ("could not be verified, skipping...");
-+ continue;
-+ }
-+
-+ sc_debug ("got cert with usages 0x%lx", (gulong) cert_usages);
-+
-+ if (token->priv->encryption_certificate == NULL) {
-+
-+ sc_debug ("checking if certificate can be used for data "
-+ "encryption");
-+ status = CERT_CheckCertUsage (node->cert,
-+ KU_DATA_ENCIPHERMENT);
-+
-+ if (status == SECSuccess) {
-+ token->priv->encryption_certificate =
-+ CERT_DupCertificate (node->cert);
-+ } else {
-+ sc_debug ("certificate can not be used for encryption");
-+ }
-+ }
-+
-+ if (token->priv->signing_certificate == NULL) {
-+
-+ sc_debug ("checking if certificate can be used for data "
-+ "signing");
-+ status = CERT_CheckCertUsage (node->cert,
-+ KU_DIGITAL_SIGNATURE);
-+
-+ if (status == SECSuccess) {
-+ token->priv->signing_certificate =
-+ CERT_DupCertificate (node->cert);
-+ } else {
-+ sc_debug ("certificate can not be used for signing things");
-+ }
-+ }
-+ }
-+ return TRUE;
-+}
-+
-+#ifdef SC_SECURITY_TOKEN_ENABLE_TEST
-+#include
-+
-+static GMainLoop *event_loop;
-+
-+int
-+main (int argc,
-+ char *argv[])
-+{
-+ ScSecurityToken *token;
-+ GError *error;
-+
-+ g_log_set_always_fatal (G_LOG_LEVEL_ERROR
-+ | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
-+
-+ g_type_init ();
-+
-+ g_message ("creating instance of 'security token' object...");
-+ token = _sc_security_token_new (NULL, 1, 1);
-+ g_message ("'security token' object created successfully");
-+
-+ g_message ("destroying previously created 'security token' object...");
-+ g_object_unref (token);
-+ token = NULL;
-+ g_message ("'security token' object destroyed successfully");
-+
-+ return 0;
-+}
-+#endif
-diff -up /dev/null gnome-screensaver-2.26.0/src/securitytoken.h
---- /dev/null 2009-03-18 22:51:48.055015100 -0400
-+++ gnome-screensaver-2.26.0/src/securitytoken.h 2009-03-19 00:20:36.638249327 -0400
-@@ -0,0 +1,94 @@
-+/* securitytoken.h - api for reading and writing data to a security token
-+ *
-+ * Copyright (C) 2006 Ray Strode
-+ *
-+ * 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, 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 SC_SECURITY_TOKEN_H
-+#define SC_SECURITY_TOKEN_H
-+
-+#include
-+#include
-+
-+#include
-+
-+G_BEGIN_DECLS
-+#define SC_TYPE_SECURITY_TOKEN (sc_security_token_get_type ())
-+#define SC_SECURITY_TOKEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_SECURITY_TOKEN, ScSecurityToken))
-+#define SC_SECURITY_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_SECURITY_TOKEN, ScSecurityTokenClass))
-+#define SC_IS_SECURITY_TOKEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SECURITY_TOKEN))
-+#define SC_IS_SECURITY_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SECURITY_TOKEN))
-+#define SC_SECURITY_TOKEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SC_TYPE_SECURITY_TOKEN, ScSecurityTokenClass))
-+#define SC_SECURITY_TOKEN_ERROR (sc_security_token_error_quark ())
-+typedef struct _ScSecurityTokenClass ScSecurityTokenClass;
-+typedef struct _ScSecurityToken ScSecurityToken;
-+typedef struct _ScSecurityTokenPrivate ScSecurityTokenPrivate;
-+typedef enum _ScSecurityTokenError ScSecurityTokenError;
-+typedef enum _ScSecurityTokenState ScSecurityTokenState;
-+
-+typedef struct _ScSecurityTokenRequest ScSecurityTokenRequest;
-+
-+struct _ScSecurityToken {
-+ GObject parent;
-+
-+ /*< private > */
-+ ScSecurityTokenPrivate *priv;
-+};
-+
-+struct _ScSecurityTokenClass {
-+ GObjectClass parent_class;
-+
-+ void (* inserted) (ScSecurityToken *token);
-+ void (* removed) (ScSecurityToken *token);
-+};
-+
-+enum _ScSecurityTokenError {
-+ SC_SECURITY_TOKEN_ERROR_GENERIC = 0,
-+};
-+
-+enum _ScSecurityTokenState {
-+ SC_SECURITY_TOKEN_STATE_INSERTED = 0,
-+ SC_SECURITY_TOKEN_STATE_REMOVED,
-+};
-+
-+GType sc_security_token_get_type (void) G_GNUC_CONST;
-+GQuark sc_security_token_error_quark (void) G_GNUC_CONST;
-+
-+CK_SLOT_ID sc_security_token_get_slot_id (ScSecurityToken *token);
-+gint sc_security_token_get_slot_series (ScSecurityToken *token);
-+ScSecurityTokenState sc_security_token_get_state (ScSecurityToken *token);
-+
-+gchar *sc_security_token_get_name (ScSecurityToken *token);
-+gboolean sc_security_token_is_login_token (ScSecurityToken *token);
-+
-+gboolean sc_security_token_unlock (ScSecurityToken *token,
-+ const gchar *password);
-+
-+/* don't under any circumstances call these functions */
-+#ifdef SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
-+
-+ScSecurityToken *_sc_security_token_new (SECMODModule *module,
-+ CK_SLOT_ID slot_id,
-+ gint slot_series);
-+ScSecurityToken *_sc_security_token_new_from_name (SECMODModule *module,
-+ const gchar *name);
-+
-+void _sc_security_token_set_state (ScSecurityToken *token,
-+ ScSecurityTokenState state);
-+#endif
-+
-+G_END_DECLS
-+#endif /* SC_SECURITY_TOKEN_H */
-diff -up /dev/null gnome-screensaver-2.26.0/src/securitytokenmonitor.c
---- /dev/null 2009-03-18 22:51:48.055015100 -0400
-+++ gnome-screensaver-2.26.0/src/securitytokenmonitor.c 2009-03-19 00:20:36.641220270 -0400
-@@ -0,0 +1,1743 @@
-+/* securitytokenmonitor.c - monitor for security token insertion and
-+ * removal events
-+ *
-+ * Copyright (C) 2006 Ray Strode
-+ *
-+ * 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, 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.
-+ *
-+ * TODO: - doing this per project is a bad idea i think.
-+ * We should probably make this a system service
-+ * and use dbus.
-+ */
-+#define _GNU_SOURCE
-+#include "securitytokenmonitor.h"
-+
-+#define SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
-+#include "securitytoken.h"
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include
-+#include
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER
-+#define SC_SECURITY_TOKEN_MONITOR_DRIVER LIBDIR"/pkcs11/libcoolkeypk11.so"
-+#endif
-+
-+#ifndef SC_SECURITY_TOKEN_MONITOR_NSS_DB
-+#define SC_SECURITY_TOKEN_MONITOR_NSS_DB SYSCONFDIR"/pki/nssdb"
-+#endif
-+
-+#ifndef SC_MAX_OPEN_FILE_DESCRIPTORS
-+#define SC_MAX_OPEN_FILE_DESCRIPTORS 1024
-+#endif
-+
-+#ifndef SC_OPEN_FILE_DESCRIPTORS_DIR
-+#define SC_OPEN_FILE_DESCRIPTORS_DIR "/proc/self/fd"
-+#endif
-+
-+#ifndef sc_debug
-+#if defined (SC_SECURITY_TOKEN_MONITOR_ENABLE_TEST)
-+#define sc_debug(fmt, args...) g_printerr("[%u] " fmt " \n", getpid(), ##args)
-+#else
-+#define sc_debug(fmt, args...)
-+#endif
-+#endif
-+
-+typedef enum _ScSecurityTokenMonitorState ScSecurityTokenMonitorState;
-+typedef struct _ScSecurityTokenMonitorWorker ScSecurityTokenMonitorWorker;
-+
-+enum _ScSecurityTokenMonitorState {
-+ SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED = 0,
-+ SC_SECURITY_TOKEN_MONITOR_STATE_STARTING,
-+ SC_SECURITY_TOKEN_MONITOR_STATE_STARTED,
-+ SC_SECURITY_TOKEN_MONITOR_STATE_STOPPING,
-+};
-+
-+struct _ScSecurityTokenMonitorPrivate {
-+ ScSecurityTokenMonitorState state;
-+ SECMODModule *module;
-+ gchar *module_path;
-+
-+ GSource *security_token_event_source;
-+ GPid security_token_event_watcher_pid;
-+ GHashTable *security_tokens;
-+
-+ guint poll_timeout_id;
-+
-+ guint32 is_unstoppable : 1;
-+ guint32 nss_is_loaded : 1;
-+
-+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
-+ GArray *fds_to_close_on_fork;
-+#endif
-+};
-+
-+struct _ScSecurityTokenMonitorWorker {
-+ SECMODModule *module;
-+ GHashTable *security_tokens;
-+ gint write_fd;
-+
-+ guint32 nss_is_loaded : 1;
-+};
-+
-+static void sc_security_token_monitor_finalize (GObject *object);
-+static void sc_security_token_monitor_class_install_signals (ScSecurityTokenMonitorClass *service_class);
-+static void sc_security_token_monitor_class_install_properties (ScSecurityTokenMonitorClass *service_class);
-+static void sc_security_token_monitor_set_property (GObject *object,
-+ guint prop_id,
-+ const GValue *value,
-+ GParamSpec *pspec);
-+static void sc_security_token_monitor_get_property (GObject *object,
-+ guint prop_id,
-+ GValue *value,
-+ GParamSpec *pspec);
-+static void sc_security_token_monitor_set_module_path (ScSecurityTokenMonitor *monitor,
-+ const gchar *module_path);
-+static void sc_security_token_monitor_token_removed_handler (ScSecurityTokenMonitor *monitor,
-+ ScSecurityToken *token);
-+static void sc_security_token_monitor_token_inserted_handler (ScSecurityTokenMonitor *monitor_class,
-+ ScSecurityToken *token);
-+static gboolean sc_security_token_monitor_stop_now (ScSecurityTokenMonitor *monitor);
-+static void sc_security_token_monitor_queue_stop (ScSecurityTokenMonitor *monitor);
-+
-+static gboolean sc_security_token_monitor_create_worker (ScSecurityTokenMonitor *monitor,
-+ gint *worker_fd, GPid *worker_pid);
-+
-+static ScSecurityTokenMonitorWorker * sc_security_token_monitor_worker_new (gint write_fd);
-+static void sc_security_token_monitor_worker_free (ScSecurityTokenMonitorWorker *worker);
-+static void sc_security_token_monitor_worker_die_with_parent (ScSecurityTokenMonitorWorker *worker);
-+static gboolean sc_open_pipe (gint *write_fd, gint *read_fd);
-+static gboolean sc_read_bytes (gint fd, gpointer bytes, gsize num_bytes);
-+static gboolean sc_write_bytes (gint fd, gconstpointer bytes, gsize num_bytes);
-+static ScSecurityToken *sc_read_security_token (gint fd, SECMODModule *module);
-+static gboolean sc_write_security_token (gint fd, ScSecurityToken *token);
-+
-+enum {
-+ PROP_0 = 0,
-+ PROP_MODULE_PATH,
-+ NUMBER_OF_PROPERTIES
-+};
-+
-+enum {
-+ SECURITY_TOKEN_INSERTED = 0,
-+ SECURITY_TOKEN_REMOVED,
-+ ERROR,
-+ NUMBER_OF_SIGNALS
-+};
-+
-+static guint sc_security_token_monitor_signals[NUMBER_OF_SIGNALS];
-+
-+G_DEFINE_TYPE (ScSecurityTokenMonitor,
-+ sc_security_token_monitor,
-+ G_TYPE_OBJECT);
-+
-+static void
-+sc_security_token_monitor_class_init (ScSecurityTokenMonitorClass *monitor_class)
-+{
-+ GObjectClass *gobject_class;
-+
-+ gobject_class = G_OBJECT_CLASS (monitor_class);
-+
-+ gobject_class->finalize = sc_security_token_monitor_finalize;
-+
-+ sc_security_token_monitor_class_install_signals (monitor_class);
-+ sc_security_token_monitor_class_install_properties (monitor_class);
-+
-+ g_type_class_add_private (monitor_class,
-+ sizeof (ScSecurityTokenMonitorPrivate));
-+}
-+
-+static void
-+sc_security_token_monitor_class_install_properties (ScSecurityTokenMonitorClass *token_class)
-+{
-+ GObjectClass *object_class;
-+ GParamSpec *param_spec;
-+
-+ object_class = G_OBJECT_CLASS (token_class);
-+ object_class->set_property = sc_security_token_monitor_set_property;
-+ object_class->get_property = sc_security_token_monitor_get_property;
-+
-+ param_spec = g_param_spec_string ("module-path", _("Module Path"),
-+ _("path to security token PKCS #11 driver"),
-+ NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-+ g_object_class_install_property (object_class, PROP_MODULE_PATH, param_spec);
-+}
-+
-+static void
-+sc_security_token_monitor_set_property (GObject *object,
-+ guint prop_id,
-+ const GValue *value,
-+ GParamSpec *pspec)
-+{
-+ ScSecurityTokenMonitor *monitor = SC_SECURITY_TOKEN_MONITOR (object);
-+
-+ switch (prop_id)
-+ {
-+ case PROP_MODULE_PATH:
-+ sc_security_token_monitor_set_module_path (monitor,
-+ g_value_get_string (value));
-+ break;
-+
-+ default:
-+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-+ break;
-+ }
-+}
-+
-+static void
-+sc_security_token_monitor_get_property (GObject *object,
-+ guint prop_id,
-+ GValue *value,
-+ GParamSpec *pspec)
-+{
-+ ScSecurityTokenMonitor *monitor = SC_SECURITY_TOKEN_MONITOR (object);
-+ gchar *module_path;
-+
-+ switch (prop_id)
-+ {
-+ case PROP_MODULE_PATH:
-+ module_path = sc_security_token_monitor_get_module_path (monitor);
-+ g_value_set_string (value, module_path);
-+ g_free (module_path);
-+ break;
-+
-+ default:
-+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-+ break;
-+ }
-+}
-+
-+gchar *
-+sc_security_token_monitor_get_module_path (ScSecurityTokenMonitor *monitor)
-+{
-+ return monitor->priv->module_path;
-+}
-+
-+static void
-+sc_security_token_monitor_set_module_path (ScSecurityTokenMonitor *monitor,
-+ const gchar *module_path)
-+{
-+ if ((monitor->priv->module_path == NULL) && (module_path == NULL))
-+ return;
-+
-+ if (((monitor->priv->module_path == NULL) ||
-+ (module_path == NULL) ||
-+ (strcmp (monitor->priv->module_path, module_path) != 0))) {
-+ g_free (monitor->priv->module_path);
-+ monitor->priv->module_path = g_strdup (module_path);
-+ g_object_notify (G_OBJECT (monitor), "module-path");
-+ }
-+}
-+
-+static void
-+sc_security_token_monitor_token_removed_handler (ScSecurityTokenMonitor *monitor,
-+ ScSecurityToken *token)
-+{
-+ sc_debug ("informing security token of its removal");
-+ _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_REMOVED);
-+ sc_debug ("done");
-+}
-+
-+static void
-+sc_security_token_monitor_token_inserted_handler (ScSecurityTokenMonitor *monitor,
-+ ScSecurityToken *token)
-+{
-+ sc_debug ("informing security token of its insertion");
-+
-+ _sc_security_token_set_state (token, SC_SECURITY_TOKEN_STATE_INSERTED);
-+ sc_debug ("done");
-+
-+}
-+
-+static void
-+sc_security_token_monitor_class_install_signals (ScSecurityTokenMonitorClass *monitor_class)
-+{
-+ GObjectClass *object_class;
-+
-+ object_class = G_OBJECT_CLASS (monitor_class);
-+
-+ sc_security_token_monitor_signals[SECURITY_TOKEN_INSERTED] =
-+ g_signal_new ("security-token-inserted",
-+ G_OBJECT_CLASS_TYPE (object_class),
-+ G_SIGNAL_RUN_FIRST,
-+ G_STRUCT_OFFSET (ScSecurityTokenMonitorClass,
-+ security_token_inserted),
-+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
-+ G_TYPE_NONE, 1, G_TYPE_POINTER);
-+ monitor_class->security_token_inserted = sc_security_token_monitor_token_inserted_handler;
-+
-+ sc_security_token_monitor_signals[SECURITY_TOKEN_REMOVED] =
-+ g_signal_new ("security-token-removed",
-+ G_OBJECT_CLASS_TYPE (object_class),
-+ G_SIGNAL_RUN_FIRST,
-+ G_STRUCT_OFFSET (ScSecurityTokenMonitorClass,
-+ security_token_removed),
-+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
-+ G_TYPE_NONE, 1, G_TYPE_POINTER);
-+ monitor_class->security_token_removed = sc_security_token_monitor_token_removed_handler;
-+
-+ sc_security_token_monitor_signals[ERROR] =
-+ g_signal_new ("error",
-+ G_OBJECT_CLASS_TYPE (object_class),
-+ G_SIGNAL_RUN_LAST,
-+ G_STRUCT_OFFSET (ScSecurityTokenMonitorClass, error),
-+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
-+ G_TYPE_NONE, 1, G_TYPE_POINTER);
-+ monitor_class->error = NULL;
-+}
-+
-+static gboolean
-+sc_slot_id_equal (CK_SLOT_ID *slot_id_1,
-+ CK_SLOT_ID *slot_id_2)
-+{
-+ g_assert (slot_id_1 != NULL);
-+ g_assert (slot_id_2 != NULL);
-+
-+ return *slot_id_1 == *slot_id_2;
-+}
-+
-+static gboolean
-+sc_slot_id_hash (CK_SLOT_ID *slot_id)
-+{
-+ guint32 upper_bits, lower_bits;
-+ gint temp;
-+
-+ if (sizeof (CK_SLOT_ID) == sizeof (gint))
-+ return g_int_hash (slot_id);
-+
-+ upper_bits = ((*slot_id) >> 31) - 1;
-+ lower_bits = (*slot_id) & 0xffffffff;
-+
-+ /* The upper bits are almost certainly always zero,
-+ * so let's degenerate to g_int_hash for the
-+ * (very) common case
-+ */
-+ temp = lower_bits + upper_bits;
-+ return upper_bits + g_int_hash (&temp);
-+}
-+
-+static void
-+sc_security_token_monitor_init (ScSecurityTokenMonitor *monitor)
-+{
-+ sc_debug ("initializing security token monitor");
-+
-+ monitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (monitor,
-+ SC_TYPE_SECURITY_TOKEN_MONITOR,
-+ ScSecurityTokenMonitorPrivate);
-+ monitor->priv->poll_timeout_id = 0;
-+ monitor->priv->is_unstoppable = FALSE;
-+ monitor->priv->module = NULL;
-+
-+ monitor->priv->security_tokens =
-+ g_hash_table_new_full (g_str_hash,
-+ g_str_equal,
-+ (GDestroyNotify) g_free,
-+ (GDestroyNotify) g_object_unref);
-+
-+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
-+ monitor->priv->fds_to_close_on_fork = g_array_new (FALSE, FALSE, sizeof (gint));
-+#endif
-+
-+}
-+
-+static void
-+sc_security_token_monitor_finalize (GObject *object)
-+{
-+ ScSecurityTokenMonitor *monitor;
-+ GObjectClass *gobject_class;
-+
-+ monitor = SC_SECURITY_TOKEN_MONITOR (object);
-+ gobject_class =
-+ G_OBJECT_CLASS (sc_security_token_monitor_parent_class);
-+
-+ sc_security_token_monitor_stop_now (monitor);
-+
-+ g_hash_table_destroy (monitor->priv->security_tokens);
-+ monitor->priv->security_tokens = NULL;
-+
-+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
-+ g_array_free (monitor->priv->fds_to_close_on_fork, TRUE);
-+#endif
-+
-+ gobject_class->finalize (object);
-+}
-+
-+GQuark
-+sc_security_token_monitor_error_quark (void)
-+{
-+ static GQuark error_quark = 0;
-+
-+ if (error_quark == 0)
-+ error_quark = g_quark_from_static_string ("sc-security-token-monitor-error-quark");
-+
-+ return error_quark;
-+}
-+
-+ScSecurityTokenMonitor *
-+sc_security_token_monitor_new (const gchar *module_path)
-+{
-+ ScSecurityTokenMonitor *instance;
-+
-+ instance = SC_SECURITY_TOKEN_MONITOR (g_object_new (SC_TYPE_SECURITY_TOKEN_MONITOR,
-+ "module-path", module_path,
-+ NULL));
-+
-+ return instance;
-+}
-+
-+static void
-+sc_security_token_monitor_emit_error (ScSecurityTokenMonitor *monitor,
-+ GError *error)
-+{
-+ monitor->priv->is_unstoppable = TRUE;
-+ g_signal_emit (monitor, sc_security_token_monitor_signals[ERROR], 0,
-+ error);
-+ monitor->priv->is_unstoppable = FALSE;
-+}
-+
-+static void
-+sc_security_token_monitor_emit_security_token_inserted (ScSecurityTokenMonitor *monitor,
-+ ScSecurityToken *token)
-+{
-+ monitor->priv->is_unstoppable = TRUE;
-+ g_signal_emit (monitor, sc_security_token_monitor_signals[SECURITY_TOKEN_INSERTED], 0,
-+ token);
-+ monitor->priv->is_unstoppable = FALSE;
-+}
-+
-+static void
-+sc_security_token_monitor_emit_security_token_removed (ScSecurityTokenMonitor *monitor,
-+ ScSecurityToken *token)
-+{
-+ ScSecurityTokenMonitorState old_state;
-+
-+ old_state = monitor->priv->state;
-+ monitor->priv->is_unstoppable = TRUE;
-+ g_signal_emit (monitor, sc_security_token_monitor_signals[SECURITY_TOKEN_REMOVED], 0,
-+ token);
-+ monitor->priv->is_unstoppable = FALSE;
-+}
-+
-+static gboolean
-+sc_security_token_monitor_check_for_and_process_events (GIOChannel *io_channel,
-+ GIOCondition condition,
-+ ScSecurityTokenMonitor *monitor)
-+{
-+ ScSecurityToken *token;
-+ gboolean should_stop;
-+ guchar event_type;
-+ gchar *token_name;
-+ gint fd;
-+
-+ token = NULL;
-+ should_stop = (condition & G_IO_HUP) || (condition & G_IO_ERR);
-+
-+ if (should_stop)
-+ sc_debug ("received %s on event socket, stopping "
-+ "monitor...",
-+ (condition & G_IO_HUP) && (condition & G_IO_ERR)?
-+ "error and hangup" :
-+ (condition & G_IO_HUP)?
-+ "hangup" : "error");
-+
-+ if (!(condition & G_IO_IN))
-+ goto out;
-+
-+ fd = g_io_channel_unix_get_fd (io_channel);
-+
-+ event_type = '\0';
-+ if (!sc_read_bytes (fd, &event_type, 1)) {
-+ should_stop = TRUE;
-+ goto out;
-+ }
-+
-+ token = sc_read_security_token (fd, monitor->priv->module);
-+
-+ if (token == NULL) {
-+ should_stop = TRUE;
-+ goto out;
-+ }
-+
-+ token_name = sc_security_token_get_name (token);
-+
-+ switch (event_type) {
-+ case 'I':
-+ g_hash_table_replace (monitor->priv->security_tokens,
-+ token_name, token);
-+ token_name = NULL;
-+
-+ sc_security_token_monitor_emit_security_token_inserted (monitor, token);
-+ token = NULL;
-+ break;
-+
-+ case 'R':
-+ sc_security_token_monitor_emit_security_token_removed (monitor, token);
-+ if (!g_hash_table_remove (monitor->priv->security_tokens, token_name))
-+ sc_debug ("got removal event of unknown token!");
-+ g_free (token_name);
-+ token_name = NULL;
-+ token = NULL;
-+ break;
-+
-+ default:
-+ g_free (token_name);
-+ token_name = NULL;
-+ g_object_unref (token);
-+
-+ should_stop = TRUE;
-+ break;
-+ }
-+
-+out:
-+ if (should_stop) {
-+ GError *error;
-+
-+ error = g_error_new (SC_SECURITY_TOKEN_MONITOR_ERROR,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_WATCHING_FOR_EVENTS,
-+ "%s", (condition & G_IO_IN) ? g_strerror (errno) : _("received error or hang up from event source"));
-+
-+ sc_security_token_monitor_emit_error (monitor, error);
-+ g_error_free (error);
-+ sc_security_token_monitor_stop_now (monitor);
-+ return FALSE;
-+ }
-+
-+ return TRUE;
-+}
-+
-+static void
-+sc_security_token_monitor_event_processing_stopped_handler (ScSecurityTokenMonitor *monitor)
-+{
-+ monitor->priv->security_token_event_source = NULL;
-+ sc_security_token_monitor_stop_now (monitor);
-+}
-+
-+/* sorta complex function that is nothing more than fork() without having
-+ * to worry about reaping the child later with waitpid
-+ */
-+static GPid
-+sc_fork_and_disown (void)
-+{
-+ pid_t child_pid;
-+ GPid grandchild_pid;
-+ gint write_fd, read_fd;
-+ gint saved_errno;
-+
-+ write_fd = -1;
-+ read_fd = -1;
-+ if (!sc_open_pipe (&write_fd, &read_fd))
-+ return (GPid) -1;
-+
-+ child_pid = fork ();
-+
-+ if (child_pid < 0) {
-+ close (write_fd);
-+ close (read_fd);
-+ return (GPid) child_pid;
-+ }
-+
-+ if (child_pid == 0) {
-+
-+ /* close the end of the pipe we're not going to use
-+ */
-+ close (read_fd);
-+
-+ /* fork again
-+ */
-+ child_pid = fork ();
-+
-+ /* in the event of error, write out negative errno
-+ */
-+ if (child_pid < 0) {
-+ child_pid = -1 * errno;
-+
-+ sc_write_bytes (write_fd, &child_pid, sizeof (child_pid));
-+ close (write_fd);
-+ _exit (1);
-+ }
-+
-+ /* otherwise write out the pid of the child and exit
-+ */
-+ if (child_pid != 0) {
-+
-+ signal (SIGPIPE, SIG_IGN);
-+
-+ if (!sc_write_bytes (write_fd, &child_pid, sizeof (child_pid))) {
-+ kill (SIGKILL, child_pid);
-+ _exit (2);
-+ }
-+ close (write_fd);
-+ _exit (0);
-+ }
-+ close (write_fd);
-+
-+ /* we're done, we've forked without having to worry about
-+ * reaping the child later
-+ */
-+ g_assert (child_pid == 0);
-+ return (GPid) 0;
-+ }
-+
-+ /* close the end of the pipe we're not going to use
-+ */
-+ close (write_fd);
-+
-+ grandchild_pid = -1;
-+ if (!sc_read_bytes (read_fd, &grandchild_pid, sizeof (grandchild_pid))) {
-+ grandchild_pid = -1;
-+ }
-+
-+ saved_errno = errno;
-+
-+ /* close the other end of the pipe since we're done with it
-+ */
-+ close (read_fd);
-+
-+ /* wait for child to die (and emancipate the grandchild)
-+ */
-+ waitpid (child_pid, NULL, 0);
-+
-+ errno = saved_errno;
-+ return (GPid) grandchild_pid;
-+}
-+
-+static gboolean
-+sc_open_pipe (gint *write_fd,
-+ gint *read_fd)
-+{
-+ gint pipe_fds[2] = { -1, -1 };
-+
-+ g_assert (write_fd != NULL);
-+ g_assert (read_fd != NULL);
-+
-+ if (pipe (pipe_fds) < 0)
-+ return FALSE;
-+
-+ if (fcntl (pipe_fds[0], F_SETFD, FD_CLOEXEC) < 0) {
-+ close (pipe_fds[0]);
-+ close (pipe_fds[1]);
-+ return FALSE;
-+ }
-+
-+ if (fcntl (pipe_fds[1], F_SETFD, FD_CLOEXEC) < 0) {
-+ close (pipe_fds[0]);
-+ close (pipe_fds[1]);
-+ return FALSE;
-+ }
-+
-+ *read_fd = pipe_fds[0];
-+ *write_fd = pipe_fds[1];
-+
-+ return TRUE;
-+}
-+
-+static void
-+sc_security_token_monitor_stop_watching_for_events (ScSecurityTokenMonitor *monitor)
-+{
-+ if (monitor->priv->security_token_event_source != NULL) {
-+ g_source_destroy (monitor->priv->security_token_event_source);
-+ monitor->priv->security_token_event_source = NULL;
-+ }
-+
-+ if (monitor->priv->security_token_event_watcher_pid > 0) {
-+ kill (monitor->priv->security_token_event_watcher_pid, SIGKILL);
-+ monitor->priv->security_token_event_watcher_pid = 0;
-+ }
-+}
-+
-+static gboolean
-+sc_load_nss (GError **error)
-+{
-+ SECStatus status = SECSuccess;
-+ static const guint32 flags =
-+ NSS_INIT_READONLY| NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB |
-+ NSS_INIT_FORCEOPEN | NSS_INIT_NOROOTINIT |
-+ NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD;
-+
-+ sc_debug ("attempting to load NSS database '%s'",
-+ SC_SECURITY_TOKEN_MONITOR_NSS_DB);
-+
-+ status = NSS_Initialize (SC_SECURITY_TOKEN_MONITOR_NSS_DB,
-+ "", "", SECMOD_DB, flags);
-+
-+ if (status != SECSuccess) {
-+ gsize error_message_size;
-+ gchar *error_message;
-+
-+ error_message_size = PR_GetErrorTextLength ();
-+
-+ if (error_message_size == 0) {
-+ sc_debug ("NSS security system could not be initialized");
-+ g_set_error (error,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
-+ _("NSS security system could not be initialized"));
-+ goto out;
-+ }
-+
-+ error_message = g_slice_alloc0 (error_message_size);
-+ PR_GetErrorText (error_message);
-+
-+ g_set_error (error,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
-+ "%s", error_message);
-+ sc_debug ("NSS security system could not be initialized - %s",
-+ error_message);
-+
-+ g_slice_free1 (error_message_size, error_message);
-+
-+ goto out;
-+ }
-+
-+ sc_debug ("NSS database sucessfully loaded");
-+ return TRUE;
-+
-+out:
-+ sc_debug ("NSS database couldn't be sucessfully loaded");
-+ return FALSE;
-+}
-+
-+static SECMODModule *
-+sc_load_driver (gchar *module_path,
-+ GError **error)
-+{
-+ SECMODModule *module;
-+ gchar *module_spec;
-+ gboolean module_explicitly_specified;
-+
-+ sc_debug ("attempting to load driver...");
-+
-+ module = NULL;
-+ module_explicitly_specified = module_path != NULL;
-+ if (module_explicitly_specified) {
-+ module_spec = g_strdup_printf ("library=\"%s\"", module_path);
-+ sc_debug ("loading security token driver using spec '%s'",
-+ module_spec);
-+
-+ module = SECMOD_LoadUserModule (module_spec,
-+ NULL /* parent */,
-+ FALSE /* recurse */);
-+ g_free (module_spec);
-+ module_spec = NULL;
-+
-+ } else {
-+ SECMODModuleList *modules, *tmp;
-+
-+ modules = SECMOD_GetDefaultModuleList ();
-+
-+ for (tmp = modules; tmp != NULL; tmp = tmp->next) {
-+ if (!SECMOD_HasRemovableSlots (tmp->module) ||
-+ !tmp->module->loaded)
-+ continue;
-+
-+ module = SECMOD_ReferenceModule (tmp->module);
-+ break;
-+ }
-+
-+ /* fallback to compiled in driver path
-+ */
-+ if (module == NULL) {
-+ if (g_file_test (SC_SECURITY_TOKEN_MONITOR_DRIVER,
-+ G_FILE_TEST_IS_REGULAR)) {
-+
-+ module_spec = g_strdup_printf ("library=\"%s\"", module_path);
-+ sc_debug ("loading security token driver using spec '%s'",
-+ module_spec);
-+
-+ module = SECMOD_LoadUserModule (module_spec,
-+ NULL /* parent */,
-+ FALSE /* recurse */);
-+ g_free (module_spec);
-+ module_spec = NULL;
-+
-+ }
-+ }
-+
-+ }
-+
-+ if (!module_explicitly_specified && module == NULL) {
-+ g_set_error (error,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
-+ _("no suitable security token driver could be found"));
-+ } else if (module == NULL || !module->loaded) {
-+
-+ gsize error_message_size;
-+ gchar *error_message;
-+
-+ if (module != NULL && !module->loaded) {
-+ sc_debug ("module found but not loaded?!");
-+ SECMOD_DestroyModule (module);
-+ module = NULL;
-+ }
-+
-+ error_message_size = PR_GetErrorTextLength ();
-+
-+ if (error_message_size == 0) {
-+ sc_debug ("security token driver '%s' could not be loaded",
-+ module_path);
-+ g_set_error (error,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
-+ _("security token driver '%s' could not be "
-+ "loaded"), module_path);
-+ goto out;
-+ }
-+
-+ error_message = g_slice_alloc0 (error_message_size);
-+ PR_GetErrorText (error_message);
-+
-+ g_set_error (error,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
-+ "%s", error_message);
-+
-+ sc_debug ("security token driver '%s' could not be loaded - %s",
-+ module_path, error_message);
-+ g_slice_free1 (error_message_size, error_message);
-+ }
-+
-+out:
-+ return module;
-+}
-+
-+static void
-+sc_security_token_monitor_get_all_tokens (ScSecurityTokenMonitor *monitor)
-+{
-+ int i;
-+
-+ for (i = 0; i < monitor->priv->module->slotCount; i++) {
-+ ScSecurityToken *token;
-+ CK_SLOT_ID slot_id;
-+ gint slot_series;
-+ gchar *token_name;
-+
-+ slot_id = PK11_GetSlotID (monitor->priv->module->slots[i]);
-+ slot_series = PK11_GetSlotSeries (monitor->priv->module->slots[i]);
-+
-+ token = _sc_security_token_new (monitor->priv->module,
-+ slot_id, slot_series);
-+
-+ token_name = sc_security_token_get_name (token);
-+
-+ g_hash_table_replace (monitor->priv->security_tokens,
-+ token_name, token);
-+ }
-+}
-+
-+gboolean
-+sc_security_token_monitor_start (ScSecurityTokenMonitor *monitor,
-+ GError **error)
-+{
-+ GError *watching_error;
-+ gint worker_fd;
-+ GPid worker_pid;
-+ GIOChannel *io_channel;
-+ GSource *source;
-+ GIOFlags channel_flags;
-+ GError *nss_error;
-+
-+ if (monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STARTED) {
-+ sc_debug ("security token monitor already started");
-+ return TRUE;
-+ }
-+
-+ monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STARTING;
-+
-+ worker_fd = -1;
-+ worker_pid = 0;
-+
-+ nss_error = NULL;
-+ if (!monitor->priv->nss_is_loaded && !sc_load_nss (&nss_error)) {
-+ g_propagate_error (error, nss_error);
-+ goto out;
-+ }
-+ monitor->priv->nss_is_loaded = TRUE;
-+
-+ if (monitor->priv->module == NULL)
-+ monitor->priv->module = sc_load_driver (monitor->priv->module_path, &nss_error);
-+
-+ if (monitor->priv->module == NULL) {
-+ g_propagate_error (error, nss_error);
-+ goto out;
-+ }
-+
-+ if (!sc_security_token_monitor_create_worker (monitor, &worker_fd, &worker_pid)) {
-+
-+ g_set_error (error,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_WATCHING_FOR_EVENTS,
-+ _("could not watch for incoming token events - %s"),
-+ g_strerror (errno));
-+
-+ goto out;
-+ }
-+
-+ monitor->priv->security_token_event_watcher_pid = worker_pid;
-+
-+ io_channel = g_io_channel_unix_new (worker_fd);
-+
-+ channel_flags = g_io_channel_get_flags (io_channel);
-+ watching_error = NULL;
-+
-+ source = g_io_create_watch (io_channel, G_IO_IN | G_IO_HUP);
-+ g_io_channel_unref (io_channel);
-+ io_channel = NULL;
-+
-+ monitor->priv->security_token_event_source = source;
-+
-+ g_source_set_callback (monitor->priv->security_token_event_source,
-+ (GSourceFunc) (GIOFunc)
-+ sc_security_token_monitor_check_for_and_process_events,
-+ monitor,
-+ (GDestroyNotify)
-+ sc_security_token_monitor_event_processing_stopped_handler);
-+ g_source_attach (monitor->priv->security_token_event_source, NULL);
-+ g_source_unref (monitor->priv->security_token_event_source);
-+
-+ /* populate the hash with tokens that are already inserted
-+ */
-+ sc_security_token_monitor_get_all_tokens (monitor);
-+
-+ monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STARTED;
-+
-+out:
-+ /* don't leave it in a half started state
-+ */
-+ if (monitor->priv->state != SC_SECURITY_TOKEN_MONITOR_STATE_STARTED) {
-+ sc_debug ("security token monitor could not be completely started");
-+ sc_security_token_monitor_stop (monitor);
-+ } else
-+ sc_debug ("security token monitor started");
-+
-+ return monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STARTED;
-+}
-+
-+static gboolean
-+sc_security_token_monitor_stop_now (ScSecurityTokenMonitor *monitor)
-+{
-+ if (monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED)
-+ return FALSE;
-+
-+ monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED;
-+ sc_security_token_monitor_stop_watching_for_events (monitor);
-+#ifdef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
-+ if (monitor->priv->module != NULL) {
-+ SECMOD_DestroyModule (monitor->priv->module);
-+ monitor->priv->module = NULL;
-+ }
-+
-+ if (monitor->priv->nss_is_loaded) {
-+ NSS_Shutdown ();
-+ monitor->priv->nss_is_loaded = FALSE;
-+ }
-+#endif
-+ sc_debug ("security token monitor stopped");
-+
-+ return FALSE;
-+}
-+
-+static void
-+sc_security_token_monitor_queue_stop (ScSecurityTokenMonitor *monitor)
-+{
-+
-+ monitor->priv->state = SC_SECURITY_TOKEN_MONITOR_STATE_STOPPING;
-+
-+ g_idle_add ((GSourceFunc) sc_security_token_monitor_stop_now, monitor);
-+}
-+
-+void
-+sc_security_token_monitor_stop (ScSecurityTokenMonitor *monitor)
-+{
-+ if (monitor->priv->state == SC_SECURITY_TOKEN_MONITOR_STATE_STOPPED)
-+ return;
-+
-+ if (monitor->priv->is_unstoppable) {
-+ sc_security_token_monitor_queue_stop (monitor);
-+ return;
-+ }
-+
-+ sc_security_token_monitor_stop_now (monitor);
-+}
-+
-+static void
-+sc_security_token_monitor_check_for_login_token (CK_SLOT_ID slot_id,
-+ ScSecurityToken *token,
-+ gboolean *is_inserted)
-+{
-+ g_assert (is_inserted != NULL);
-+
-+ if (sc_security_token_is_login_token (token))
-+ *is_inserted = TRUE;
-+
-+}
-+
-+gboolean
-+sc_security_token_monitor_login_token_is_inserted (ScSecurityTokenMonitor *monitor)
-+
-+{
-+ gboolean is_inserted;
-+
-+ is_inserted = FALSE;
-+ g_hash_table_foreach (monitor->priv->security_tokens,
-+ (GHFunc)
-+ sc_security_token_monitor_check_for_login_token,
-+ &is_inserted);
-+ return is_inserted;
-+}
-+
-+static gint
-+sc_get_max_open_fds (void)
-+{
-+ struct rlimit open_fd_limit;
-+ const gint fallback_limit = SC_MAX_OPEN_FILE_DESCRIPTORS;
-+
-+ if (getrlimit (RLIMIT_NOFILE, &open_fd_limit) < 0) {
-+ sc_debug ("could not get file descriptor limit: %s",
-+ g_strerror (errno));
-+ sc_debug ("returning fallback file descriptor limit of %d",
-+ fallback_limit);
-+ return fallback_limit;
-+ }
-+
-+ if (open_fd_limit.rlim_cur == RLIM_INFINITY) {
-+ sc_debug ("currently no file descriptor limit, returning fallback limit of %d",
-+ fallback_limit);
-+ return fallback_limit;
-+ }
-+
-+ return (gint) open_fd_limit.rlim_cur;
-+}
-+
-+static void
-+sc_close_all_fds (int *fds_to_keep_open)
-+{
-+ int max_open_fds, fd;
-+
-+ sc_debug ("closing all file descriptors");
-+ max_open_fds = sc_get_max_open_fds ();
-+
-+ for (fd = 0; fd < max_open_fds; fd++) {
-+ int i;
-+ gboolean should_close_fd;
-+
-+ should_close_fd = TRUE;
-+
-+ if (fds_to_keep_open != NULL) {
-+ for (i = 0; fds_to_keep_open[i] >= 0; i++) {
-+ if (fd == fds_to_keep_open[i]) {
-+ should_close_fd = FALSE;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (should_close_fd) {
-+ sc_debug ("closing file descriptor '%d'", fd);
-+ close (fd);
-+ }
-+ }
-+}
-+
-+static void
-+sc_close_open_fds (int *fds_to_keep_open)
-+{
-+ /* using DIR instead of GDir because we need access to dirfd so
-+ * that we can iterate through the fds and close them in one sweep.
-+ * (if we just closed all of them then we would close the one we're using
-+ * for reading the directory!)
-+ */
-+ DIR *dir;
-+ struct dirent *entry;
-+ gint fd, opendir_fd;
-+ gboolean should_use_fallback;
-+
-+ should_use_fallback = FALSE;
-+ opendir_fd = -1;
-+
-+ dir = opendir (SC_OPEN_FILE_DESCRIPTORS_DIR);
-+
-+ if (dir != NULL)
-+ opendir_fd = dirfd (dir);
-+
-+ if ((dir == NULL) || (opendir_fd < 0)) {
-+ sc_debug ("could not open "SC_OPEN_FILE_DESCRIPTORS_DIR": %s", g_strerror (errno));
-+ should_use_fallback = TRUE;
-+ } else {
-+ sc_debug ("reading files in '"SC_OPEN_FILE_DESCRIPTORS_DIR"'");
-+ while ((entry = readdir (dir)) != NULL) {
-+ gint i;
-+ glong filename_as_number;
-+ gchar *byte_after_number;
-+ gboolean should_close_fd;
-+
-+ errno = 0;
-+ if (entry->d_name[0] == '.')
-+ continue;
-+
-+ sc_debug ("scanning filename '%s' for file descriptor number",
-+ entry->d_name);
-+ fd = -1;
-+ filename_as_number = strtol (entry->d_name, &byte_after_number, 10);
-+
-+ g_assert (byte_after_number != NULL);
-+
-+ if ((*byte_after_number != '\0') ||
-+ (filename_as_number < 0) ||
-+ (filename_as_number >= G_MAXINT)) {
-+ sc_debug ("filename '%s' does not appear to represent a "
-+ "file descriptor: %s",
-+ entry->d_name, strerror (errno));
-+ should_use_fallback = TRUE;
-+ } else {
-+ fd = (gint) filename_as_number;
-+ sc_debug ("filename '%s' represents file descriptor '%d'",
-+ entry->d_name, fd);
-+ should_use_fallback = FALSE;
-+ }
-+
-+ if (fd == opendir_fd) {
-+ should_close_fd = FALSE;
-+ } else {
-+ should_close_fd = TRUE;
-+ if (fds_to_keep_open != NULL)
-+ for (i = 0; fds_to_keep_open[i] >= 0; i++) {
-+ if (fd == fds_to_keep_open[i]) {
-+ should_close_fd = FALSE;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (should_close_fd) {
-+ sc_debug ("closing file descriptor '%d'", fd);
-+ close (fd);
-+ } else {
-+ sc_debug ("will not close file descriptor '%d' because it "
-+ "is still needed", fd);
-+ }
-+ }
-+
-+ if (entry != NULL)
-+ should_use_fallback = TRUE;
-+
-+ sc_debug ("closing directory '"SC_OPEN_FILE_DESCRIPTORS_DIR"'");
-+ closedir (dir);
-+ }
-+
-+ /* if /proc isn't mounted or something else is screwy,
-+ * fall back to closing everything
-+ */
-+ if (should_use_fallback)
-+ sc_close_all_fds (fds_to_keep_open);
-+}
-+
-+static void
-+sc_close_fds (gint *fds,
-+ gint num_fds)
-+{
-+ gint i;
-+
-+ for (i = 0; i < num_fds; i++)
-+ close (fds[i]);
-+}
-+
-+static ScSecurityTokenMonitorWorker *
-+sc_security_token_monitor_worker_new (gint write_fd)
-+{
-+ ScSecurityTokenMonitorWorker *worker;
-+
-+ worker = g_slice_new0 (ScSecurityTokenMonitorWorker);
-+ worker->write_fd = write_fd;
-+ worker->module = NULL;
-+
-+ worker->security_tokens =
-+ g_hash_table_new_full ((GHashFunc) sc_slot_id_hash,
-+ (GEqualFunc) sc_slot_id_equal,
-+ (GDestroyNotify) g_free,
-+ (GDestroyNotify) g_object_unref);
-+
-+ return worker;
-+}
-+
-+static void
-+sc_security_token_monitor_worker_free (ScSecurityTokenMonitorWorker *worker)
-+{
-+ if (worker->security_tokens != NULL) {
-+ g_hash_table_destroy (worker->security_tokens);
-+ worker->security_tokens = NULL;
-+ }
-+
-+ g_slice_free (ScSecurityTokenMonitorWorker, worker);
-+}
-+
-+/* This function checks to see if the helper's connection to the
-+ * parent process has been closed. If it has, we assume the
-+ * parent has died (or is otherwise done with the connection)
-+ * and so we die, too. We do this from a signal handler (yuck!)
-+ * because there isn't a nice way to cancel the
-+ * SECMOD_WaitForAnyTokenEvent call, which just sits and blocks
-+ * indefinitely. There is a SECMOD_CancelWait wait function
-+ * that we could call if we would have gone multithreaded like
-+ * NSS really wants us to do, but that call isn't signal handler
-+ * safe, so we just _exit() instead (eww).
-+ */
-+static void
-+worker_io_signal_handler (int signal_number,
-+ siginfo_t *signal_info,
-+ void *data)
-+{
-+ int number_of_events;
-+ int old_errno;
-+ struct pollfd poll_fds[1] = { { 0 } };
-+ int parent_fd;
-+
-+ old_errno = errno;
-+
-+ /* pipe fd set up to talk to the parent */
-+ parent_fd = signal_info->si_fd;
-+
-+ /* We only care about disconnection events
-+ * (which get unmasked implicitly), so we just
-+ * pass 0 for the event mask
-+ */
-+ poll_fds[0].events = 0;
-+ poll_fds[0].fd = parent_fd;
-+
-+ do {
-+ number_of_events = poll (poll_fds, G_N_ELEMENTS (poll_fds), 0);
-+ } while ((number_of_events < 0) && (errno == EINTR));
-+
-+ g_assert (number_of_events <= G_N_ELEMENTS (poll_fds));
-+
-+ if (number_of_events < 0)
-+ _exit (errno);
-+
-+ /* pipe disconnected; parent died
-+ */
-+ if (number_of_events > 0) {
-+ g_assert (!(poll_fds[0].revents & POLLNVAL));
-+
-+ if ((poll_fds[0].revents & POLLHUP) ||
-+ (poll_fds[0].revents & POLLERR)) {
-+ _exit (poll_fds[0].revents);
-+ }
-+ }
-+
-+ errno = old_errno;
-+}
-+
-+static void
-+sc_security_token_monitor_worker_die_with_parent (ScSecurityTokenMonitorWorker *worker)
-+{
-+ struct sigaction action = { { 0 } };
-+ gint flags;
-+
-+ /* dirty hack to clean up worker if parent goes away
-+ */
-+ sigemptyset (&action.sa_mask);
-+ action.sa_sigaction = worker_io_signal_handler;
-+ action.sa_flags = SA_SIGINFO;
-+ sigaction (SIGIO, &action, NULL);
-+
-+ flags = fcntl (worker->write_fd, F_GETFL, 0);
-+
-+ fcntl (worker->write_fd, F_SETOWN, getpid ());
-+ fcntl (worker->write_fd, F_SETFL, flags | O_ASYNC);
-+ fcntl (worker->write_fd, F_SETSIG, SIGIO);
-+}
-+
-+static gboolean
-+sc_read_bytes (gint fd, gpointer bytes, gsize num_bytes)
-+{
-+ size_t bytes_left;
-+ size_t total_bytes_read;
-+ ssize_t bytes_read;
-+
-+ bytes_left = (size_t) num_bytes;
-+ total_bytes_read = 0;
-+
-+ do {
-+ bytes_read = read (fd, bytes + total_bytes_read, bytes_left);
-+ g_assert (bytes_read <= (ssize_t) bytes_left);
-+
-+ if (bytes_read <= 0) {
-+ if ((bytes_read < 0) && (errno == EINTR || errno == EAGAIN))
-+ continue;
-+
-+ bytes_left = 0;
-+ } else {
-+ bytes_left -= bytes_read;
-+ total_bytes_read += bytes_read;
-+ }
-+ } while (bytes_left > 0);
-+
-+ if (total_bytes_read < (size_t) num_bytes)
-+ return FALSE;
-+
-+ return TRUE;
-+}
-+
-+static gboolean
-+sc_write_bytes (gint fd, gconstpointer bytes, gsize num_bytes)
-+{
-+ size_t bytes_left;
-+ size_t total_bytes_written;
-+ ssize_t bytes_written;
-+
-+ bytes_left = (size_t) num_bytes;
-+ total_bytes_written = 0;
-+
-+ do {
-+ bytes_written = write (fd, bytes + total_bytes_written, bytes_left);
-+ g_assert (bytes_written <= (ssize_t) bytes_left);
-+
-+ if (bytes_written <= 0) {
-+ if ((bytes_written < 0) && (errno == EINTR || errno == EAGAIN))
-+ continue;
-+
-+ bytes_left = 0;
-+ } else {
-+ bytes_left -= bytes_written;
-+ total_bytes_written += bytes_written;
-+ }
-+ } while (bytes_left > 0);
-+
-+ if (total_bytes_written < (size_t) num_bytes)
-+ return FALSE;
-+
-+ return TRUE;
-+}
-+
-+static ScSecurityToken *
-+sc_read_security_token (gint fd, SECMODModule *module)
-+{
-+ ScSecurityToken *token;
-+ gchar *token_name;
-+ gsize token_name_size;
-+
-+ token_name_size = 0;
-+ if (!sc_read_bytes (fd, &token_name_size, sizeof (token_name_size)))
-+ return NULL;
-+
-+ token_name = g_slice_alloc0 (token_name_size);
-+ if (!sc_read_bytes (fd, token_name, token_name_size)) {
-+ g_slice_free1 (token_name_size, token_name);
-+ return NULL;
-+ }
-+ token = _sc_security_token_new_from_name (module, token_name);
-+ g_slice_free1 (token_name_size, token_name);
-+
-+ return token;
-+}
-+
-+static gboolean
-+sc_write_security_token (gint fd,
-+ ScSecurityToken *token)
-+{
-+ gsize token_name_size;
-+ gchar *token_name;
-+
-+ token_name = sc_security_token_get_name (token);
-+ token_name_size = strlen (token_name) + 1;
-+
-+ if (!sc_write_bytes (fd, &token_name_size, sizeof (token_name_size))) {
-+ g_free (token_name);
-+ return FALSE;
-+ }
-+
-+ if (!sc_write_bytes (fd, token_name, token_name_size)) {
-+ g_free (token_name);
-+ return FALSE;
-+ }
-+ g_free (token_name);
-+
-+ return TRUE;
-+}
-+
-+static gboolean
-+sc_security_token_monitor_worker_emit_security_token_removed (ScSecurityTokenMonitorWorker *worker,
-+ ScSecurityToken *token,
-+ GError **error)
-+{
-+ sc_debug ("token '%s' removed!", sc_security_token_get_name (token));
-+
-+ if (!sc_write_bytes (worker->write_fd, "R", 1))
-+ goto error_out;
-+
-+ if (!sc_write_security_token (worker->write_fd, token))
-+ goto error_out;
-+
-+ return TRUE;
-+
-+error_out:
-+ g_set_error (error, SC_SECURITY_TOKEN_MONITOR_ERROR,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_REPORTING_EVENTS,
-+ "%s", g_strerror (errno));
-+ return FALSE;
-+}
-+
-+static gboolean
-+sc_security_token_monitor_worker_emit_security_token_inserted (ScSecurityTokenMonitorWorker *worker,
-+ ScSecurityToken *token,
-+ GError **error)
-+{
-+ GError *write_error;
-+
-+ write_error = NULL;
-+ sc_debug ("token '%s' inserted!", sc_security_token_get_name (token));
-+ if (!sc_write_bytes (worker->write_fd, "I", 1))
-+ goto error_out;
-+
-+ if (!sc_write_security_token (worker->write_fd, token))
-+ goto error_out;
-+
-+ return TRUE;
-+
-+error_out:
-+ g_set_error (error, SC_SECURITY_TOKEN_MONITOR_ERROR,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_REPORTING_EVENTS,
-+ "%s", g_strerror (errno));
-+ return FALSE;
-+}
-+
-+static gboolean
-+sc_security_token_monitor_worker_watch_for_and_process_event (ScSecurityTokenMonitorWorker *worker,
-+ GError **error)
-+{
-+ PK11SlotInfo *slot;
-+ CK_SLOT_ID slot_id, *key;
-+ gint slot_series, token_slot_series;
-+ ScSecurityToken *token;
-+ GError *processing_error;
-+
-+ sc_debug ("waiting for token event");
-+
-+ /* FIXME: we return FALSE quite a bit in this function without cleaning up
-+ * resources. By returning FALSE we're going to ultimately exit anyway, but
-+ * we should still be tidier about things.
-+ */
-+
-+ slot = SECMOD_WaitForAnyTokenEvent (worker->module, 0, PR_SecondsToInterval (1));
-+ processing_error = NULL;
-+
-+ if (slot == NULL) {
-+ int error_code;
-+
-+ error_code = PORT_GetError ();
-+ if ((error_code == 0) || (error_code == SEC_ERROR_NO_EVENT)) {
-+ sc_debug ("spurrious event occurred");
-+ return TRUE;
-+ }
-+
-+ /* FIXME: is there a function to convert from a PORT error
-+ * code to a translated string?
-+ */
-+ g_set_error (error, SC_SECURITY_TOKEN_MONITOR_ERROR,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
-+ _("encountered unexpected error while "
-+ "waiting for security token events"));
-+ return FALSE;
-+ }
-+
-+ /* the slot id and series together uniquely identify a token.
-+ * You can never have two tokens with the same slot id at the
-+ * same time, however (I think), so we can key off of it.
-+ */
-+ slot_id = PK11_GetSlotID (slot);
-+ slot_series = PK11_GetSlotSeries (slot);
-+
-+ /* First check to see if there is a token that we're currently
-+ * tracking in the slot.
-+ */
-+ key = g_new (CK_SLOT_ID, 1);
-+ *key = slot_id;
-+ token = g_hash_table_lookup (worker->security_tokens, key);
-+
-+ if (token != NULL)
-+ token_slot_series = sc_security_token_get_slot_series (token);
-+
-+ if (PK11_IsPresent (slot)) {
-+ /* Now, check to see if their is a new token in the slot.
-+ * If there was a different token in the slot now than
-+ * there was before, then we need to emit a removed signal
-+ * for the old token (we don't want unpaired insertion events).
-+ */
-+ if ((token != NULL) &&
-+ token_slot_series != slot_series) {
-+ if (!sc_security_token_monitor_worker_emit_security_token_removed (worker, token, &processing_error)) {
-+ g_propagate_error (error, processing_error);
-+ return FALSE;
-+ }
-+ }
-+
-+ token = _sc_security_token_new (worker->module,
-+ slot_id, slot_series);
-+
-+ g_hash_table_replace (worker->security_tokens,
-+ key, token);
-+ key = NULL;
-+
-+ if (!sc_security_token_monitor_worker_emit_security_token_inserted (worker, token, &processing_error)) {
-+ g_propagate_error (error, processing_error);
-+ return FALSE;
-+ }
-+ } else {
-+ /* if we aren't tracking the token, just discard the event.
-+ * We don't want unpaired remove events. Note on startup
-+ * NSS will generate an "insertion" event if a token is
-+ * already inserted in the slot.
-+ */
-+ if ((token != NULL)) {
-+ /* FIXME: i'm not sure about this code. Maybe we
-+ * shouldn't do this at all, or maybe we should do it
-+ * n times (where n = slot_series - token_slot_series + 1)
-+ *
-+ * Right now, i'm just doing it once.
-+ */
-+ if ((slot_series - token_slot_series) > 1) {
-+
-+ if (!sc_security_token_monitor_worker_emit_security_token_removed (worker, token, &processing_error)) {
-+ g_propagate_error (error, processing_error);
-+ return FALSE;
-+ }
-+ g_hash_table_remove (worker->security_tokens, key);
-+
-+ token = _sc_security_token_new (worker->module,
-+ slot_id, slot_series);
-+ g_hash_table_replace (worker->security_tokens,
-+ key, token);
-+ key = NULL;
-+ if (!sc_security_token_monitor_worker_emit_security_token_inserted (worker, token, &processing_error)) {
-+ g_propagate_error (error, processing_error);
-+ return FALSE;
-+ }
-+ }
-+
-+ if (!sc_security_token_monitor_worker_emit_security_token_removed (worker, token, &processing_error)) {
-+ g_propagate_error (error, processing_error);
-+ return FALSE;
-+ }
-+
-+ g_hash_table_remove (worker->security_tokens, key);
-+ token = NULL;
-+ } else {
-+ sc_debug ("got spurious remove event");
-+ }
-+ }
-+
-+ g_free (key);
-+ PK11_FreeSlot (slot);
-+
-+ return TRUE;
-+}
-+
-+static gboolean
-+sc_security_token_monitor_create_worker (ScSecurityTokenMonitor *monitor,
-+ gint *worker_fd, GPid *worker_pid)
-+{
-+ GPid child_pid;
-+ gint write_fd, read_fd;
-+
-+ write_fd = -1;
-+ read_fd = -1;
-+ if (!sc_open_pipe (&write_fd, &read_fd))
-+ return FALSE;
-+
-+ child_pid = sc_fork_and_disown ();
-+
-+ if (child_pid < 0)
-+ return FALSE;
-+
-+ if (child_pid == 0) {
-+ GError *error;
-+ ScSecurityTokenMonitorWorker *worker;
-+
-+/* FIXME: Gotta figure out why this isn't working
-+*/
-+#ifdef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
-+ gint fds_to_keep_open[] = { -1, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, -1 };
-+
-+ SECMOD_DestroyModule (monitor->priv->module);
-+ monitor->priv->module = NULL;
-+
-+ NSS_Shutdown ();
-+
-+ fds_to_keep_open[0] = write_fd;
-+ sc_close_open_fds (fds_to_keep_open);
-+ read_fd = -1;
-+
-+ if (!sc_load_nss (&error)) {
-+ sc_debug ("could not load nss - %s", error->message);
-+ g_error_free (error);
-+ _exit (1);
-+ }
-+#else
-+ g_array_append_val (monitor->priv->fds_to_close_on_fork, read_fd);
-+ /* Junky workaround to keep from leaking fds
-+ */
-+ sc_close_fds ((gint *) monitor->priv->fds_to_close_on_fork->data,
-+ monitor->priv->fds_to_close_on_fork->len);
-+#endif
-+ error = NULL;
-+
-+ worker = sc_security_token_monitor_worker_new (write_fd);
-+
-+ sc_security_token_monitor_worker_die_with_parent (worker);
-+
-+ worker->module = sc_load_driver (monitor->priv->module_path, &error);
-+
-+ if (worker->module == NULL) {
-+ sc_debug ("could not load nss driver - %s", error->message);
-+ g_error_free (error);
-+ _exit (2);
-+ }
-+
-+ while (sc_security_token_monitor_worker_watch_for_and_process_event (worker, &error));
-+
-+ sc_debug ("could not process token event - %s", error->message);
-+ sc_security_token_monitor_worker_free (worker);
-+
-+ _exit (0);
-+ }
-+
-+ close (write_fd);
-+
-+#ifndef SC_SECURITY_TOKEN_MONITOR_DRIVER_CAN_BE_RELOADED_AFTER_BEING_DESTROYED
-+ g_array_append_val (monitor->priv->fds_to_close_on_fork, read_fd);
-+#endif
-+
-+ if (worker_pid)
-+ *worker_pid = child_pid;
-+
-+ if (worker_fd)
-+ *worker_fd = read_fd;
-+
-+ return TRUE;
-+}
-+
-+#ifdef SC_SECURITY_TOKEN_MONITOR_ENABLE_TEST
-+#include
-+
-+static GMainLoop *event_loop;
-+static gboolean should_exit_on_next_remove = FALSE;
-+
-+static gboolean
-+on_timeout (ScSecurityTokenMonitor *monitor)
-+{
-+ GError *error;
-+ g_print ("Re-enabling monitor.\n");
-+
-+ if (!sc_security_token_monitor_start (monitor, &error)) {
-+ g_warning ("could not start security token monitor - %s",
-+ error->message);
-+ g_error_free (error);
-+ return 1;
-+ }
-+ g_print ("Please re-insert security token\n");
-+
-+ should_exit_on_next_remove = TRUE;
-+
-+ return FALSE;
-+}
-+
-+static void
-+on_device_inserted (ScSecurityTokenMonitor * monitor,
-+ ScSecurityToken *token)
-+{
-+ g_print ("security token inserted!\n");
-+ g_print ("Please remove it.\n");
-+}
-+
-+static void
-+on_device_removed (ScSecurityTokenMonitor * monitor,
-+ ScSecurityToken *token)
-+{
-+ g_print ("security token removed!\n");
-+
-+ if (should_exit_on_next_remove)
-+ g_main_loop_quit (event_loop);
-+ else {
-+ g_print ("disabling monitor for 2 seconds\n");
-+ sc_security_token_monitor_stop (monitor);
-+ g_timeout_add (2000, (GSourceFunc) on_timeout, monitor);
-+ }
-+}
-+
-+int
-+main (int argc,
-+ char *argv[])
-+{
-+ ScSecurityTokenMonitor *monitor;
-+ GError *error;
-+
-+ g_log_set_always_fatal (G_LOG_LEVEL_ERROR
-+ | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
-+
-+ g_type_init ();
-+
-+ g_message ("creating instance of 'security token monitor' object...");
-+ monitor = sc_security_token_monitor_new (NULL);
-+ g_message ("'security token monitor' object created successfully");
-+
-+ g_signal_connect (monitor, "security-token-inserted",
-+ G_CALLBACK (on_device_inserted), NULL);
-+
-+ g_signal_connect (monitor, "security-token-removed",
-+ G_CALLBACK (on_device_removed), NULL);
-+
-+ g_message ("starting listener...");
-+
-+ error = NULL;
-+ if (!sc_security_token_monitor_start (monitor, &error)) {
-+ g_warning ("could not start security token monitor - %s",
-+ error->message);
-+ g_error_free (error);
-+ return 1;
-+ }
-+
-+ event_loop = g_main_loop_new (NULL, FALSE);
-+ g_main_loop_run (event_loop);
-+ g_main_loop_unref (event_loop);
-+ event_loop = NULL;
-+
-+ g_message ("destroying previously created 'security token monitor' object...");
-+ g_object_unref (monitor);
-+ monitor = NULL;
-+ g_message ("'security token monitor' object destroyed successfully");
-+
-+ return 0;
-+}
-+#endif
-diff -up /dev/null gnome-screensaver-2.26.0/src/securitytokenmonitor.h
---- /dev/null 2009-03-18 22:51:48.055015100 -0400
-+++ gnome-screensaver-2.26.0/src/securitytokenmonitor.h 2009-03-19 00:20:36.643204483 -0400
-@@ -0,0 +1,84 @@
-+/* securitytokenmonitor.h - monitor for security token insertion and
-+ * removal events
-+ *
-+ * Copyright (C) 2006 Ray Strode
-+ *
-+ * 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, 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 SC_SECURITY_TOKEN_MONITOR_H
-+#define SC_SECURITY_TOKEN_MONITOR_H
-+
-+#define SC_SECURITY_TOKEN_ENABLE_INTERNAL_API
-+#include "securitytoken.h"
-+
-+#include
-+#include
-+
-+G_BEGIN_DECLS
-+#define SC_TYPE_SECURITY_TOKEN_MONITOR (sc_security_token_monitor_get_type ())
-+#define SC_SECURITY_TOKEN_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_SECURITY_TOKEN_MONITOR, ScSecurityTokenMonitor))
-+#define SC_SECURITY_TOKEN_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_SECURITY_TOKEN_MONITOR, ScSecurityTokenMonitorClass))
-+#define SC_IS_SECURITY_TOKEN_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_SECURITY_TOKEN_MONITOR))
-+#define SC_IS_SECURITY_TOKEN_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SC_TYPE_SECURITY_TOKEN_MONITOR))
-+#define SC_SECURITY_TOKEN_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SC_TYPE_SECURITY_TOKEN_MONITOR, ScSecurityTokenMonitorClass))
-+#define SC_SECURITY_TOKEN_MONITOR_ERROR (sc_security_token_monitor_error_quark ())
-+typedef struct _ScSecurityTokenMonitor ScSecurityTokenMonitor;
-+typedef struct _ScSecurityTokenMonitorClass ScSecurityTokenMonitorClass;
-+typedef struct _ScSecurityTokenMonitorPrivate ScSecurityTokenMonitorPrivate;
-+typedef enum _ScSecurityTokenMonitorError ScSecurityTokenMonitorError;
-+
-+struct _ScSecurityTokenMonitor {
-+ GObject parent;
-+
-+ /*< private > */
-+ ScSecurityTokenMonitorPrivate *priv;
-+};
-+
-+struct _ScSecurityTokenMonitorClass {
-+ GObjectClass parent_class;
-+
-+ /* Signals */
-+ void (*security_token_inserted) (ScSecurityTokenMonitor *monitor,
-+ ScSecurityToken *token);
-+ void (*security_token_removed) (ScSecurityTokenMonitor *monitor,
-+ ScSecurityToken *token);
-+ void (*error) (ScSecurityTokenMonitor *monitor,
-+ GError *error);
-+};
-+
-+enum _ScSecurityTokenMonitorError {
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_GENERIC = 0,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_WITH_NSS,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_LOADING_DRIVER,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_WATCHING_FOR_EVENTS,
-+ SC_SECURITY_TOKEN_MONITOR_ERROR_REPORTING_EVENTS
-+};
-+
-+GType sc_security_token_monitor_get_type (void) G_GNUC_CONST;
-+GQuark sc_security_token_monitor_error_quark (void) G_GNUC_CONST;
-+
-+ScSecurityTokenMonitor *sc_security_token_monitor_new (const gchar *module);
-+
-+gboolean sc_security_token_monitor_start (ScSecurityTokenMonitor *monitor,
-+ GError **error);
-+
-+void sc_security_token_monitor_stop (ScSecurityTokenMonitor *monitor);
-+
-+gchar *sc_security_token_monitor_get_module_path (ScSecurityTokenMonitor *monitor);
-+gboolean sc_security_token_monitor_login_token_is_inserted (ScSecurityTokenMonitor *monitor);
-+
-+G_END_DECLS
-+#endif /* SC_SECURITY_TOKEN_MONITOR_H */
diff --git a/gnome-screensaver-2.29.90-linker-fixes.patch b/gnome-screensaver-2.29.90-linker-fixes.patch
deleted file mode 100644
index b1fa9f2..0000000
--- a/gnome-screensaver-2.29.90-linker-fixes.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-diff -up gnome-screensaver-2.29.90/configure.ac.linker-fixes gnome-screensaver-2.29.90/configure.ac
---- gnome-screensaver-2.29.90/configure.ac.linker-fixes 2010-02-08 10:50:19.000000000 -0500
-+++ gnome-screensaver-2.29.90/configure.ac 2010-02-09 09:48:39.880808232 -0500
-@@ -42,6 +42,7 @@ GLIB_REQUIRED_VERSION=2.15.0
- GCONF_REQUIRED_VERSION=2.6.1
- GDK_REQUIRED_VERSION=2.14.0
- GTK_REQUIRED_VERSION=2.11.5
-+X11_REQUIRED_VERSION=1.3
- LIBGNOME_MENU_REQUIRED_VERSION=2.11.1
- GNOME_DESKTOP_REQUIRED_VERSION=2.29.0
-
-@@ -56,6 +57,7 @@ AC_TYPE_UID_T
-
- AC_CHECK_FUNCS([setresuid setenv unsetenv clearenv])
- PKG_CHECK_MODULES(GNOME_SCREENSAVER,
-+ x11 >= $X11_REQUIRED_VERSION
- gtk+-2.0 >= $GTK_REQUIRED_VERSION
- dbus-glib-1 >= $DBUS_REQUIRED_VERSION
- gconf-2.0 >= $GCONF_REQUIRED_VERSION
-diff -up gnome-screensaver-2.29.90/savers/Makefile.am.linker-fixes gnome-screensaver-2.29.90/savers/Makefile.am
---- gnome-screensaver-2.29.90/savers/Makefile.am.linker-fixes 2010-02-09 10:14:46.863797660 -0500
-+++ gnome-screensaver-2.29.90/savers/Makefile.am 2010-02-09 10:17:25.877811125 -0500
-@@ -87,6 +87,7 @@ floaters_SOURCES = \
- floaters_LDADD = \
- libgs-theme-engine.a \
- $(GNOME_SCREENSAVER_SAVER_LIBS) \
-+ -lm \
- $(NULL)
-
- popsquares_SOURCES = \
diff --git a/gnome-screensaver-2.91.1-size-request.patch b/gnome-screensaver-2.91.1-size-request.patch
deleted file mode 100644
index 8125afb..0000000
--- a/gnome-screensaver-2.91.1-size-request.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-From a3388633c5f55b08df4f3af48b0dc2f0ef06d143 Mon Sep 17 00:00:00 2001
-From: Richard Hughes
-Date: Thu, 02 Dec 2010 11:57:03 +0000
-Subject: Remove and correct usages of size_request to fix compile
-
----
-diff --git a/src/gs-lock-plug.c b/src/gs-lock-plug.c
-index 70f324e..20a0eda 100644
---- a/src/gs-lock-plug.c
-+++ b/src/gs-lock-plug.c
-@@ -870,28 +870,6 @@ forward_key_events (GSLockPlug *plug)
- }
-
- static void
--gs_lock_plug_size_request (GtkWidget *widget,
-- GtkRequisition *requisition)
--{
-- int mod_width;
-- int mod_height;
--
-- if (GTK_WIDGET_CLASS (gs_lock_plug_parent_class)->size_request) {
-- GTK_WIDGET_CLASS (gs_lock_plug_parent_class)->size_request (widget, requisition);
-- }
--
-- mod_width = requisition->height * 1.3;
-- mod_height = requisition->width / 1.6;
-- if (requisition->width < mod_width) {
-- /* if the dialog is tall fill out the width */
-- requisition->width = mod_width;
-- } else if (requisition->height < mod_height) {
-- /* if the dialog is wide fill out the height */
-- requisition->height = mod_height;
-- }
--}
--
--static void
- gs_lock_plug_set_logout_enabled (GSLockPlug *plug,
- gboolean logout_enabled)
- {
-@@ -1082,7 +1060,6 @@ gs_lock_plug_class_init (GSLockPlugClass *klass)
- widget_class->style_set = gs_lock_plug_style_set;
- widget_class->show = gs_lock_plug_show;
- widget_class->hide = gs_lock_plug_hide;
-- widget_class->size_request = gs_lock_plug_size_request;
-
- klass->close = gs_lock_plug_close;
-
-diff --git a/src/gs-window-x11.c b/src/gs-window-x11.c
-index 0c1e729..eaaba36 100644
---- a/src/gs-window-x11.c
-+++ b/src/gs-window-x11.c
-@@ -2104,6 +2104,30 @@ gs_window_real_visibility_notify_event (GtkWidget *widget,
- }
-
- static void
-+gs_window_real_get_preferred_width (GtkWidget *widget,
-+ gint *minimal_width,
-+ gint *natural_width)
-+{
-+ GtkRequisition requisition;
-+
-+ gs_window_real_size_request (widget, &requisition);
-+
-+ *minimal_width = *natural_width = requisition.width;
-+}
-+
-+static void
-+gs_window_real_get_preferred_height (GtkWidget *widget,
-+ gint *minimal_height,
-+ gint *natural_height)
-+{
-+ GtkRequisition requisition;
-+
-+ gs_window_real_size_request (widget, &requisition);
-+
-+ *minimal_height = *natural_height = requisition.height;
-+}
-+
-+static void
- gs_window_class_init (GSWindowClass *klass)
- {
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-@@ -2121,7 +2145,8 @@ gs_window_class_init (GSWindowClass *klass)
- widget_class->motion_notify_event = gs_window_real_motion_notify_event;
- widget_class->button_press_event = gs_window_real_button_press_event;
- widget_class->scroll_event = gs_window_real_scroll_event;
-- widget_class->size_request = gs_window_real_size_request;
-+ widget_class->get_preferred_width = gs_window_real_get_preferred_width;
-+ widget_class->get_preferred_height = gs_window_real_get_preferred_height;
- widget_class->grab_broken_event = gs_window_real_grab_broken;
- widget_class->visibility_notify_event = gs_window_real_visibility_notify_event;
-
---
-cgit v0.8.3.1
diff --git a/gnome-screensaver.spec b/gnome-screensaver.spec
index 9cf619c..f9399bd 100644
--- a/gnome-screensaver.spec
+++ b/gnome-screensaver.spec
@@ -1,19 +1,19 @@
-%define gtk3_version 2.99
+%define gtk3_version 2.99.3
%define libgnomeui_version 2.6.0
%define libglade2_version 2.5.0
%define dbus_version 0.90
-%define dbus_glib_version 0.70
+%define dbus_glib_version 0.74
%define libxml2_version 2.6.0
%define gconf2_version 2.6.1
%define redhat_menus_version 5.0.1
%define gnome_menus_version 2.11.1
%define gnome_desktop3_version 2.91.5
%define libexif_version 0.6.12
-%define libgnomekbd_version 2.21
+%define libgnomekbd_version 2.91.1
Summary: GNOME Screensaver
Name: gnome-screensaver
-Version: 2.91.90
+Version: 2.91.91
Release: 1%{?dist}
License: GPLv2+
Group: Amusements/Graphics
@@ -21,7 +21,6 @@ Group: Amusements/Graphics
Source0: http://download.gnome.org/sources/gnome-screensaver/2.91/%{name}-%{version}.tar.bz2
Source1: gnome-screensaver-hide-xscreensaver.menu
-Patch2: gnome-screensaver-2.26.0-securitytoken.patch
Patch8: gnome-screensaver-2.20.0-selinux-permit.patch
URL: http://www.gnome.org
@@ -63,7 +62,6 @@ simple, sane, secure defaults and be well integrated with the desktop.
%prep
%setup -q
-#%patch2 -p1 -b .securitytoken
%patch8 -p1 -b .selinux-permit
autoreconf -f -i
@@ -103,6 +101,9 @@ install -D -m644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/xdg/menus/preferences-
%doc %{_mandir}/man1/*.1.gz
%changelog
+* Tue Mar 8 2011 Christopher Aillon - 2.91.91-1
+- Update to 2.91.91
+
* Tue Feb 22 2011 Matthias Clasen
- Update to 2.91.90
diff --git a/sources b/sources
index 1d79cc0..24af069 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-5e3ade436e244c864f83cd5dec15cc2d gnome-screensaver-2.91.90.tar.bz2
+eda4ec43761b6d29d922828716b3e064 gnome-screensaver-2.91.91.tar.bz2