From 8c50007e132d474a772ac456786342c0fe7fe189 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Sat, 2 Jan 2016 20:36:57 -0800
Subject: [PATCH] gtk-lock
Solaris uses the gtk unlock dialog program originally written by
Ximian & Wipro, in order to provide a dialog box that works with
the GNOME accessibility framework. This was done as a fork of
the original xscreensaver because the maintainer would not allow
use of a toolkit in the lock dialog - he has since softened his
stance a bit, but this has not been presented to him to see if it
meets his requirements as spelled out at:
This patch also contains fixes for:
15134570 SUNBT4782515 user is prompted to enter PIN or password when screen
is locked
15134983 SUNBT4783832 No date on xscreensaver-lock and warning on screen
15179562 SUNBT4931584 xscreensaver-demo cores with GTK_MODULES=gail:atk-bridge
15209082 SUNBT5039876 "User:" should not look like an input field
15209083 SUNBT5039878 "Password:" field should be focused / have flashing caret
15214348 SUNBT5059445 pam service name, screen kb and screen reader support
15220008 SUNBT5077989 Bug 147580: password input dialogue obscures GOK
15220010 SUNBT5077993 Bug 147639: Gok cant automatically UI grab screensaver
preferences
15220705 SUNBT5079870 147587: password field should set ATK_ROLE_PASSWORD_TEXT
15221761 SUNBT5083155 Unable to unlock screen when running dual head
magnification
15231258 SUNBT6176524 passwdTimeoutEnable for disabled user (xscreensaver-lock)
15231818 SUNBT6178584 Xscreensaver needs to use ROLE_PASSWORD_TEXT
15233078 SUNBT6182506 Screensaver dialog isn't magnified properly
15239418 SUNBT6203951 xscreensaver lockscreen translation errors for fr_FR
15252945 SUNBT6237901 Ldap and Gnome xscreensaver authentication failure
15265442 SUNBT6269444 snv_14 xscreensaver prints out gratuitous debug messages
after authentication
15280862 SUNBT6308859 xscreensaver: password lock dialog is not localized
15295912 SUNBT6346056 xscreensaver should not enable input method
15317555 SUNBT6395649 at-spi-registryd starts when screen is locked even when
accessible device support is off
15326852 SUNBT6417168 xscreensaver loops while trying to unlock a session for
a user whose password was expired
15346556 SUNBT6461887 GNOME screen lock does not prevent access to other
applications via 'alt-tab'
15352585 SUNBT6475285 xscreensaver core dumps in kill_job() after unlocking
the screen
15354012 SUNBT6478362 When the AT support is enabled, the input focus is
located at password label
15356879 SUNBT6484604 X should stop linking against -lcmd
15387793 SUNBT6541240 Screen saver will lock user out of the system if they
have no password set
15405753 SUNBT6573182 after applying patch 120094-11(or later), xscreensaver
core dump
15427168 SUNBT6611183 xscreensaver needs to put Sun logos in files loaded at
runtime
15461985 SUNBT6670025 xscreensaver passwd dialog image missing in nv_85
15462355 SUNBT6670659 password dialog window remains on the screen even after
screen is unlocked
15463666 SUNBT6673036 prepare for Indiana unlock logos
15500787 SUNBT6736157 Security problem when desktop a11y support is turned on
15521700 SUNBT6769901 popup windows appearing through xscreensaver
15553552 SUNBT6825374 xscreensaver issues under Xorg
15561643 SUNBT6839026 Regression in screensaver may cause Performance
Degradation and make locked screensaver unresponsive
15565807 SUNBT6845751 xscreensaver-lock chews CPU when daemon dies while unlock
dialog is up
15568147 SUNBT6849124 xscreensaver leaves a dialog that cannot be moved/closed
after password change warning
15573881 SUNBT6857559 Nevada build was broken because of 6849124
15652522 SUNBT6964562 xscreensaver dumps core whenever it unlocks in svn-142
15700093 SUNBT7023648 xscreensaver does not allow user to enter password
and login w/ sv_SE.ISO8859-01/-15
22706313 xscreensaver calls to pam_setcred with the wrong flag
---
config.h.in | 3 +
configure.in | 22 +-
driver/Makefile.in | 59 ++-
driver/auth.h | 4 +
driver/demo-Gtk.c | 18 +
driver/dialog-data.h | 131 ++++++
driver/lock-Gtk.c | 738 +++++++++++++++++++++++++++++++++
driver/lock.c | 1083 ++++++++++++++++++++++++++++++++++++++++++++-----
driver/passwd-pam.c | 228 +++++++++--
driver/passwd.c | 1 +
driver/setuid.c | 5 +-
driver/subprocs.c | 35 +-
driver/timers.c | 110 ++++-
driver/types.h | 18 +
driver/windows.c | 21 +-
driver/xscreensaver.c | 130 +++++-
driver/xscreensaver.h | 6 +
17 files changed, 2451 insertions(+), 161 deletions(-)
create mode 100644 driver/dialog-data.h
create mode 100644 driver/lock-Gtk.c
diff --git a/config.h.in b/config.h.in
index 3524ec4..6b6d077 100644
--- a/config.h.in
+++ b/config.h.in
@@ -360,6 +360,9 @@
make use of this if it is available. */
#undef HAVE_XPM
+/* Define this to build the external lock dialog */
+#undef HAVE_XSCREENSAVER_LOCK
+
/* Define this if you have the X Shared Memory Extension. */
#undef HAVE_XSHM_EXTENSION
diff --git a/configure.in b/configure.in
index 4c4dee5..eb753a3 100644
--- a/configure.in
+++ b/configure.in
@@ -2666,6 +2666,7 @@ if test "$with_gtk" = yes; then
pkg_check_version libglade-2.0 1.99.0
pkg_check_version gdk-pixbuf-2.0 2.0.0
pkg_check_version gdk-pixbuf-xlib-2.0 2.0.0
+ pkg_check_version gconf-2.0 2.6.1
have_gtk="$ok"
if test "$have_gtk" = no; then
@@ -2681,6 +2682,9 @@ if test "$with_gtk" = yes; then
fi
if test "$have_gtk" = yes; then
+#--- Begin SUNW addition
+ AC_DEFINE(HAVE_XSCREENSAVER_LOCK,[],[Define this to build the external lock dialog])
+#--- End SUNW addition
AC_CACHE_CHECK([for Gtk includes], ac_cv_gtk_config_cflags,
[ac_cv_gtk_config_cflags=`$pkg_config --cflags $pkgs`])
AC_CACHE_CHECK([for Gtk libs], ac_cv_gtk_config_libs,
@@ -3933,6 +3937,16 @@ if test "$have_gtk" = yes; then
ALL_DEMO_PROGRAMS="$PREFERRED_DEMO_PROGRAM $ALL_DEMO_PROGRAMS"
fi
+#--- Begin SUNW addition
+PREFERRED_LOCK_PROGRAM=
+ALL_LOCK_PROGRAMS=
+LOCK_PROGRAM=
+if test "$have_gtk" = yes; then
+ PREFERRED_LOCK_PROGRAM=xscreensaver-lock-Gtk
+ ALL_LOCK_PROGRAMS="$PREFERRED_LOCK_PROGRAM $ALL_LOCK_PROGRAMS"
+ LOCK_PROGRAM=xscreensaver-lock
+fi
+#--- End SUNW addition
if test "$have_kerberos" = yes; then
PASSWD_SRCS="$PASSWD_SRCS \$(KERBEROS_SRCS)"
@@ -4077,6 +4091,11 @@ AC_SUBST(INCLUDES)
AC_SUBST(PREFERRED_DEMO_PROGRAM)
AC_SUBST(ALL_DEMO_PROGRAMS)
+#--- Begin SUNW addition
+AC_SUBST(PREFERRED_LOCK_PROGRAM)
+AC_SUBST(ALL_LOCK_PROGRAMS)
+AC_SUBST(LOCK_PROGRAM)
+#--- End SUNW addition
AC_SUBST(SAVER_LIBS)
AC_SUBST(MOTIF_LIBS)
AC_SUBST(GTK_LIBS)
@@ -4598,7 +4617,8 @@ HACK_CONF_DIR=`echo "${HACK_CONF_DIR}" | sed 's@/$@@;s@//*@/@g'`
# Sanity check the hackdir
-for bad_choice in xscreensaver xscreensaver-demo xscreensaver-command ; do
+# SUNW addition: added xscreensaver-lock to list on next line
+for bad_choice in xscreensaver xscreensaver-demo xscreensaver-command xscreensaver-lock ; do
if test "${HACKDIR}" = "${bindir}/${bad_choice}" ; then
echo ""
AC_MSG_ERROR([\"--with-hackdir=${bindir}/${bad_choice}\" won't work.
diff --git a/driver/Makefile.in b/driver/Makefile.in
index 90ef1d2..a44e312 100644
@@ -29,6 +29,7 @@ GTK_APPDIR = $(GTK_DATADIR)/applications
GTK_ICONDIR = $(GTK_DATADIR)/pixmaps
GTK_GLADEDIR = $(prefix)/lib/xscreensaver/config
HACK_CONF_DIR = @HACK_CONF_DIR@
+LOCK_DIR = $(libexecdir)
CC = @CC@
OBJCC = @OBJCC@
@@ -42,6 +43,7 @@ SUBP_DEFS = $(DEFS) -DHACK_PATH='"@HACKDIR@"' \
GTK_DEFS = $(DEFS) -DDEFAULT_ICONDIR='"$(GTK_GLADEDIR)"' \
-DBINDIR='"$(bindir)"'
CONF_DEFS = -DHACK_CONFIGURATION_PATH='"$(HACK_CONF_DIR)"'
+LOCK_DEFS = $(DEFS) -DLOCKDIR=\"$(LOCK_DIR)\"
LIBS = @LIBS@
INTL_LIBS = @INTLLIBS@
@@ -98,6 +100,8 @@ MOTIF_OBJS = demo-Xm.o demo-Xm-widgets.o
GTK_SRCS = demo-Gtk.c demo-Gtk-conf.c
GTK_OBJS = demo-Gtk.o demo-Gtk-conf.o @GTK_EXTRA_OBJS@
PWENT_SRCS = passwd-pwent.c
PWENT_OBJS = passwd-pwent.o
@@ -217,8 +221,8 @@ GETIMG_LIBS = $(LIBS) $(X_LIBS) $(XPM_LIBS) $(JPEG_LIBS) \
$(X_PRE_LIBS) -lXt -lX11 $(XMU_LIBS) -lXext $(X_EXTRA_LIBS)
EXES = xscreensaver xscreensaver-command xscreensaver-demo \
- xscreensaver-getimage @EXES_OSX@
-EXES2 = @ALL_DEMO_PROGRAMS@
+ xscreensaver-getimage @EXES_OSX@ @LOCK_PROGRAM@
+EXES2 = @ALL_DEMO_PROGRAMS@ @ALL_LOCK_PROGRAMS@
EXES_OSX = pdf2jpeg
SCRIPTS_1 = xscreensaver-getimage-file xscreensaver-getimage-video \
-TARFILES = $(EXTRAS) $(VMSFILES) $(SAVER_SRCS_1) \
+TARFILES = $(EXTRAS) $(VMSFILES) $(SAVER_SRCS_1) $(GTK_LOCK_SRCS) \
$(MOTIF_SRCS) $(GTK_SRCS) $(PWENT_SRCS) $(PWHELPER_SRCS) \
$(KERBEROS_SRCS) $(PAM_SRCS) $(LOCK_SRCS_1) $(DEMO_SRCS_1) \
$(CMD_SRCS) $(GETIMG_SRCS_1) $(PDF2JPEG_SRCS) $(HDRS) \
@@ -260,7 +264,7 @@ all: $(EXES) $(EXES2)
tests: $(TEST_EXES)
install: install-program install-ad install-scripts \
- install-gnome install-man install-xml install-pam
+ install-gnome install-man install-xml
uninstall: uninstall-program uninstall-ad \
uninstall-gnome uninstall-man uninstall-xml
@@ -272,6 +276,9 @@ install-program: $(EXES)
@if [ ! -d $(install_prefix)$(bindir) ]; then \
$(INSTALL_DIRS) $(install_prefix)$(bindir) ; \
fi
+ @if [ -n "@LOCK_PROGRAM@" -a ! -d $(install_prefix)$(LOCK_DIR) ]; then \
+ $(INSTALL_DIRS) $(install_prefix)$(LOCK_DIR) ; \
+ fi
@inst="$(INSTALL_PROGRAM)" ; \
if [ @NEED_SETUID@ = yes ]; then \
me=`PATH="$$PATH:/usr/ucb" whoami` ; \
@@ -300,6 +307,12 @@ install-program: $(EXES)
echo $(INSTALL_PROGRAM) $$exe $(install_prefix)$(bindir)/$$exe ; \
$(INSTALL_PROGRAM) $$exe $(install_prefix)$(bindir)/$$exe ; \
done
+ @if [ -n "@LOCK_PROGRAM@" ]; then \
+ echo $(INSTALL_PROGRAM) xscreensaver-lock \
+ $(install_prefix)$(LOCK_DIR)/xscreensaver-lock ; \
+ $(INSTALL_PROGRAM) xscreensaver-lock \
+ $(install_prefix)$(LOCK_DIR)/xscreensaver-lock ; \
+ fi
install-ad: XScreenSaver.ad
@if [ ! -d $(install_prefix)$(AD_DIR) ]; then \
@@ -736,7 +749,7 @@ $(SAVER_UTIL_OBJS):
# How we build object files in this directory.
.c.o:
- $(CC) -c $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS) $<
+ $(CC) -c $(INCLUDES) $(DEFS) $(CPPFLAGS) $(INTL_DEFS) $(CFLAGS) $(X_CFLAGS) $<
.m.o:
$(OBJCC) -c $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS) $<
@@ -762,6 +775,16 @@ demo-Gtk-conf.o: demo-Gtk-conf.c
$(CC) -c $(INCLUDES) $(CONF_DEFS) $(GTK_DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS) \
$(srcdir)/demo-Gtk-conf.c
+# lock takes an extra -D option.
+lock.o:
+ $(CC) -c $(INCLUDES) $(LOCK_DEFS) $(CFLAGS) $(X_CFLAGS) \
+ $(srcdir)/lock.c
+
+# lock-Gtk takes extra -D and -I options.
+ $(CC) -c $(INCLUDES) -I$(ICON_SRC) $(GTK_DEFS) \
+ $(CFLAGS) $(X_CFLAGS) $(INTL_DEFS) \
+ $(srcdir)/lock-Gtk.c
# How we build the default app-defaults file into the program.
#
@@ -776,7 +799,8 @@ XScreenSaver_Xm_ad.h: XScreenSaver-Xm.ad
# The executables linked in this directory.
#
xscreensaver: $(SAVER_OBJS)
- $(CC) $(LDFLAGS) -o $@ $(SAVER_OBJS) $(SAVER_LIBS) $(INTL_LIBS)
+ $(CC) $(LDFLAGS) -o $@ $(SAVER_OBJS) $(SAVER_LIBS) $(INTL_LIBS) \
+ -lgconf-2 -lgobject-2.0 -lglib-2.0
xscreensaver-command: $(CMD_OBJS)
$(CC) $(LDFLAGS) -o $@ $(CMD_OBJS) $(CMD_LIBS)
@@ -792,6 +816,15 @@ xscreensaver-demo: @PREFERRED_DEMO_PROGRAM@
cp -p @PREFERRED_DEMO_PROGRAM@@EXEEXT@ $@@EXEEXT@ ; \
fi
+xscreensaver-lock: @PREFERRED_LOCK_PROGRAM@
+ $(INSTALL_PROGRAM) @PREFERRED_LOCK_PROGRAM@ $@
+
+xscreensaver-lock-Gtk: $(GTK_LOCK_OBJS)
+ $(CC) $(LDFLAGS) -o $@ $(GTK_LOCK_OBJS) $(LIBS) $(X_LIBS) \
+ $(GTK_LIBS) $(XML_LIBS) $(X_PRE_LIBS) -lXt -lX11 \
+ $(XDPMS_LIBS) -lXext \
+ $(X_EXTRA_LIBS)
+
xscreensaver-demo-Xm: $(DEMO_OBJS) $(MOTIF_OBJS)
$(CC) $(LDFLAGS) -o $@ $(DEMO_OBJS) $(MOTIF_OBJS) $(LIBS) $(X_LIBS) \
$(MOTIF_LIBS) $(INTL_LIBS) $(X_PRE_LIBS) -lXt -lX11 \
@@ -815,7 +848,7 @@ pdf2jpeg: $(PDF2JPEG_OBJS)
TEST_PASSWD_OBJS = test-passwd.o $(LOCK_OBJS_1) $(PASSWD_OBJS) \
$(SAVER_UTIL_OBJS)
dpms.o: $(srcdir)/xscreensaver.h
+lock-Gtk.o: $(srcdir)/atoms.h
+lock-Gtk.o: ../config.h
+lock-Gtk.o: $(srcdir)/remote.h
+lock-Gtk.o: $(UTILS_SRC)/xscreensaver-intl.h
+lock.o: $(srcdir)/dialog-data.h
lock.o: $(srcdir)/mlstring.h
@@ -907,6 +946,8 @@ lock.o: $(srcdir)/xscreensaver.h
mlstring.o: $(srcdir)/mlstring.h
+passwd.o: $(srcdir)/dialog-data.h
+passwd.o: $(srcdir)/mlstring.h
passwd.o: $(srcdir)/xscreensaver.h
test-xdpms.o: ../config.h
+timers.o: $(srcdir)/dialog-data.h
+timers.o: $(srcdir)/mlstring.h
timers.o: $(srcdir)/xscreensaver.h
@@ -1002,6 +1045,8 @@ xscreensaver-getimage.o: $(UTILS_SRC)/yarandom.h
xscreensaver.o: $(srcdir)/auth.h
+xscreensaver.o: $(srcdir)/dialog-data.h
+xscreensaver.o: $(srcdir)/mlstring.h
xscreensaver.o: $(srcdir)/prefs.h
xscreensaver.o: $(srcdir)/types.h
xscreensaver.o: $(UTILS_SRC)/resources.h
diff --git a/driver/auth.h b/driver/auth.h
index 65e00f3..4fcbb34 100644
--- a/driver/auth.h
+++ b/driver/auth.h
@@ -51,4 +51,8 @@ xss_authenticate(saver_info *si, Bool verbose_p);
void
auth_finished_cb (saver_info *si);
+#ifdef HAVE_XSCREENSAVER_LOCK
+extern int write_to_child (saver_info* si, const char* cmd, const char *msg);
+#endif
+
#endif
diff --git a/driver/demo-Gtk.c b/driver/demo-Gtk.c
index 3fa27c3..ece3c44 100644
@@ -98,6 +98,8 @@
# define G_MODULE_EXPORT /**/
#endif /* !HAVE_GTK2 */
+#include <gconf/gconf-client.h>
+
#if defined(DEFAULT_ICONDIR) && !defined(GLADE_DIR)
# define GLADE_DIR DEFAULT_ICONDIR
#endif
@@ -5042,6 +5044,22 @@ main (int argc, char **argv)
load_init_file (dpy, p);
initialize_sort_map (s);
+ /* Bug 147639: Gok cant automatically UI grab screensaver preferences */
+ {
+ GConfClient *client = gconf_client_get_default ();
+
+#define KEY "/desktop/gnome/interface/accessibility"
+
+ /* check if accessibilty mode is enabled */
+ if (gconf_client_get_bool (client, KEY, NULL))
+ {
+ /* GTK Accessibility Module initialized */
+ const char *modulesptr = g_getenv ("GTK_MODULES");
+ if (!modulesptr || (modulesptr [0] == '\0'))
+ putenv ("GTK_MODULES=gail:atk-bridge");
+ }
+ }
+
/* Now that Xt has been initialized, and the resources have been read,
we can set our `progname' variable to something more in line with
reality.
diff --git a/driver/dialog-data.h b/driver/dialog-data.h
new file mode 100644
index 0000000..1a6a965
--- /dev/null
@@ -0,0 +1,131 @@
+/* xscreensaver, Copyright (c) 1993-2008 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#ifndef __DIALOG_DATA_H__
+#define __DIALOG_DATA_H__
+
+#include <stdio.h>
+#include "types.h"
+#include "mlstring.h"
+
+#define MAX_BYTES_PER_CHAR 8 /* UTF-8 uses no more than 3, I think */
+#define MAX_PASSWD_CHARS 128 /* Longest possible passphrase */
+
+struct passwd_dialog_data {
+
+ saver_screen_info *prompt_screen;
+ int previous_mouse_x, previous_mouse_y;
+
+ /* "Characters" in the password may be a variable number of bytes long.
+ typed_passwd contains the raw bytes.
+ typed_passwd_char_size indicates the size in bytes of each character,
+ so that we can make backspace work.
+ */
+ char typed_passwd [MAX_PASSWD_CHARS * MAX_BYTES_PER_CHAR];
+ char typed_passwd_char_size [MAX_PASSWD_CHARS];
+
+ XtIntervalId timer;
+ int i_beam;
+
+ float ratio;
+ Position x, y;
+ Dimension width;
+ Dimension height;
+ Dimension border_width;
+
+ Bool echo_input;
+ Bool show_stars_p; /* "I regret that I have but one asterisk for my country."
+ -- Nathan Hale, 1776. */
+
+ char *heading_label;
+ char *body_label;
+ char *user_label;
+ mlstring *info_label;
+ /* The entry field shall only be displayed if prompt_label is not NULL */
+ mlstring *prompt_label;
+ char *date_label;
+ char *passwd_string;
+ Bool passwd_changed_p; /* Whether the user entry field needs redrawing */
+ Bool caps_p; /* Whether we saw a keypress with caps-lock on */
+ char *unlock_label;
+ char *login_label;
+ char *uname_label;
+
+ Bool show_uname_p;
+
+#ifndef HAVE_XSCREENSAVER_LOCK
+ XFontStruct *heading_font;
+ XFontStruct *body_font;
+ XFontStruct *label_font;
+ XFontStruct *passwd_font;
+ XFontStruct *date_font;
+ XFontStruct *button_font;
+ XFontStruct *uname_font;
+
+ Pixel foreground;
+ Pixel background;
+ Pixel border;
+ Pixel passwd_foreground;
+ Pixel passwd_background;
+ Pixel thermo_foreground;
+ Pixel thermo_background;
+ Pixel shadow_top;
+ Pixel shadow_bottom;
+ Pixel button_foreground;
+ Pixel button_background;
+
+ Dimension preferred_logo_width, logo_width;
+ Dimension preferred_logo_height, logo_height;
+ Dimension thermo_width;
+ Dimension internal_border;
+ Dimension shadow_width;
+
+ Dimension passwd_field_x, passwd_field_y;
+ Dimension passwd_field_width, passwd_field_height;
+
+ Dimension unlock_button_x, unlock_button_y;
+ Dimension unlock_button_width, unlock_button_height;
+
+ Dimension login_button_x, login_button_y;
+ Dimension login_button_width, login_button_height;
+
+ Dimension thermo_field_x, thermo_field_y;
+ Dimension thermo_field_height;
+
+ Pixmap logo_pixmap;
+ Pixmap logo_clipmask;
+ int logo_npixels;
+ unsigned long *logo_pixels;
+#endif /* ! HAVE_XSCREENSAVER_LOCK */
+
+ Cursor passwd_cursor;
+ Bool unlock_button_down_p;
+ Bool login_button_down_p;
+ Bool login_button_p;
+ Bool login_button_enabled_p;
+ Bool button_state_changed_p; /* Refers to both buttons */
+
+ Pixmap save_under;
+ Pixmap user_entry_pixmap;
+
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* extern passwd dialog stuff */
+ XtInputId stdout_input_id;
+ int stdin_fd; /* child's stdin - parent writes to this */
+ int stdout_fd; /* child's stdout - parent reads from this */
+ FILE *stdin_file; /* child's stdin - parent writes to this */
+ FILE *stdout_file; /* child's stdout - parent reads from this */
+ Bool got_windowid;
+ Bool got_passwd;
+#endif
+};
+
+#endif /* __DIALOG_DATA_H__ */
diff --git a/driver/lock-Gtk.c b/driver/lock-Gtk.c
new file mode 100644
index 0000000..93ef574
--- /dev/null
@@ -0,0 +1,738 @@
+/* lock-Gtk.c -- a GTK+ password dialog for xscreensaver
+ * xscreensaver, Copyright (c) 1993-1998 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* GTK+ locking code written by Jacob Berkman <jacob@ximian.com> for
+ * Sun Microsystems.
+ *
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_GTK2 /* whole file */
+
+#include <xscreensaver-intl.h>
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+/* AT-enabled */
+#include <stdio.h>
+#include <ctype.h>
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/WinUtil.h>
+
+#include <gconf/gconf-client.h>
+#include <atk/atkobject.h>
+
+#include "remote.h"
+#include "atoms.h"
+
+#if GTK_CHECK_VERSION(2,14,0)
+# define GET_WINDOW(w) gtk_widget_get_window (w)
+#else
+# define GET_WINDOW(w) ((w)->window)
+#endif
+
+static Atom XA_UNLOCK_RATIO;
+
+typedef struct {
+ GtkWidget *dialog;
+ GtkWidget *user_prompt_label;
+ GtkWidget *user_input_entry;
+ GtkWidget *progress;
+ GtkWidget *button;
+ GtkWidget *msg_label;
+ GtkWidget *pam_message_label;
+} PasswdDialog;
+
+/*Global info */
+#define MAXRAISEDWINS 2
+
+char *progname = 0;
+FILE *parent_file = NULL; /* child writes to parent on this */
+
+#define FD_TO_PARENT 9
+
+/* Send a command to the xscreensaver parent daemon
+ Arguments:
+ - msg - type of message - "input", "raise_wid", etc.
+ - data - data for message
+ - flush - whether to flush now or allow stdio to buffer
+ Message format sent to parent:
+ "msg\n" if no data, otherwise "msg=data\n"
+
+ Can be used to flush previously buffered messages by calling
+ with NULL msg & data, and TRUE for flush.
+ */
+static int
+write_to_parent (const char* msg, const char *data, gboolean flush)
+{
+ int len = 0;
+
+ /*
+ fprintf (stderr, "-->Child write_to_parent() string to send is: %s=%s\n",
+ msg, data ? data : "(null)");
+ fflush (stderr);
+ */
+
+ if (msg)
+ {
+ if (data)
+ len = fprintf (parent_file, "%s=%s\n", msg, data);
+ else
+ len = fprintf (parent_file, "%s\n", msg);
+ }
+
+ if (flush)
+ fflush (parent_file);
+
+ return len;
+}
+
+/* Send parent a message with a window id as the data */
+static void
+write_windowid (const char* msg, Window w)
+{
+ char s[16]; /* more than long enough to hold a 32-bit integer + '\0' */
+
+ snprintf(s, sizeof(s), "0x%lx", w);
+ write_to_parent(msg, s, FALSE);
+}
+
+static GtkWidget *
+load_unlock_logo_image (void)
+{
+ const char *logofile;
+ struct stat statbuf;
+
+ logofile = DEFAULT_ICONDIR "/unlock-logo.png";
+
+ if (stat (logofile, &statbuf) != 0)
+ {
+ logofile = DEFAULT_ICONDIR "/logo-180.gif"; /* fallback */
+ }
+
+ return gtk_image_new_from_file (logofile);
+}
+
+/* Create unlock dialog */
+static PasswdDialog *
+make_dialog (gboolean center_pos)
+{
+ GtkWidget *dialog;
+ AtkObject *atk_dialog;
+ GtkWidget *frame1, *frame2;
+ GtkWidget *vbox;
+ GtkWidget *hbox1, *hbox2;
+ GtkWidget *bbox;
+ GtkWidget *vbox2;
+ GtkWidget *entry;
+ AtkObject *atk_entry;
+ GtkWidget *title_label, *msg_label, *prompt_label,
+ *user_label, *date_label, *pam_msg_label;
+ AtkObject *atk_title_label, *atk_prompt_label;
+ GtkWidget *button;
+ GtkWidget *image;
+ GtkWidget *progress;
+ char *version;
+ char *user;
+ char *host;
+ char *s;
+ gchar *format_string_locale, *format_string_utf8;
+ PasswdDialog *pwd;
+
+ /* taken from lock.c */
+ char buf[256];
+ gchar *utf8_format;
+ time_t now = time (NULL);
+ struct tm* tm;
+
+ server_xscreensaver_version (GDK_DISPLAY (), &version, &user, &host);
+
+ if (!version)
+ {
+ fprintf (stderr, "%s: no xscreensaver running on display %s, exiting.\n",
+ progname, gdk_get_display ());
+ exit (1);
+ }
+
+ /* PUSH */
+ gtk_widget_push_colormap (gdk_rgb_get_cmap ());
+
+ pwd = g_new0 (PasswdDialog, 1);
+
+ dialog = gtk_window_new (GTK_WINDOW_POPUP);
+ pwd->dialog = dialog;
+
+ /*
+ ** bugid: 5077989(P2)Bug 147580: password input dialogue obscures GOK
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+ bugid: 5002244: scr unlock dialog incompatible with MAG technique
+ ** 6182506: scr dialog is obscured by MAG window
+ */
+ if (center_pos)
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS);
+ else
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); /*mali99 irritating*/
+
+ /* AT-enabled dialog role = frame */
+ atk_dialog = gtk_widget_get_accessible (dialog);
+ atk_object_set_description (atk_dialog, _("screen unlock dialog"));
+
+ /* frame */
+ frame1 = g_object_new (GTK_TYPE_FRAME,
+ "shadow-type", GTK_SHADOW_OUT,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (dialog), frame1);
+ /* AT role = panel */
+
+ /* vbox */
+ vbox = gtk_vbox_new (FALSE, 10);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
+ gtk_container_add (GTK_CONTAINER (frame1), vbox);
+ /* AT role= filler(default) */
+
+ /* hbox */
+ hbox1 = gtk_hbox_new (FALSE, 5);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox1,
+ TRUE, TRUE, 0);
+
+ /* image frame */
+ frame2 = g_object_new (GTK_TYPE_FRAME,
+ "shadow-type", GTK_SHADOW_ETCHED_IN,
+ NULL);
+ gtk_box_pack_start (GTK_BOX (hbox1), frame2,
+ TRUE, TRUE, 0);
+ /* AT role= filler(default) */
+
+ /* image */
+ image = load_unlock_logo_image ();
+ /* AT role = icon */
+ gtk_container_add (GTK_CONTAINER (frame2), image);
+
+ /* progress thingie */
+ progress = g_object_new (GTK_TYPE_PROGRESS_BAR,
+ "orientation", GTK_PROGRESS_BOTTOM_TO_TOP,
+ "fraction", 1.0,
+ NULL);
+ gtk_box_pack_start (GTK_BOX (hbox1), progress,
+ FALSE, FALSE, 0);
+ pwd->progress = progress;
+ atk_object_set_description (gtk_widget_get_accessible (progress),
+ _("Percent of time you have left to unlock the screen."));
+
+ /* text fields */
+ vbox2 = gtk_vbox_new (FALSE, 20);
+ gtk_box_pack_start (GTK_BOX (hbox1), vbox2,
+ TRUE, TRUE, 0);
+ /* AT role =filler */
+
+ s = g_markup_printf_escaped ("<span size=\"xx-large\"><b>%s </b></span>",
+ _("Screensaver"));
+ /* XScreenSaver foo label */
+ title_label = g_object_new (GTK_TYPE_LABEL,
+ "use-markup", TRUE,
+ "label", s,
+ NULL);
+ g_free (s);
+ gtk_box_pack_start (GTK_BOX (vbox2), title_label,
+ FALSE, FALSE, 0);
+ /* AT role = label prog name */
+ atk_title_label = gtk_widget_get_accessible (title_label);
+ atk_object_add_relationship (atk_title_label, ATK_RELATION_LABEL_FOR,
+ atk_dialog);
+ atk_object_add_relationship (atk_dialog, ATK_RELATION_LABELLED_BY,
+ atk_title_label);
+
+ /* This display is locked. */
+ msg_label = g_object_new (GTK_TYPE_LABEL,
+ "use-markup", TRUE,
+ "label", _("<b>This display is locked.</b>"),
+ NULL);
+ pwd->msg_label = msg_label;
+ gtk_box_pack_start (GTK_BOX (vbox2), msg_label,
+ FALSE, FALSE, 0);
+
+ /* User information */
+ s = g_strdup_printf (_("User: %s"), user ? user : "");
+ user_label = g_object_new (GTK_TYPE_LABEL,
+ "label", s,
+ "use_underline", TRUE,
+ NULL);
+ g_free(s);
+ gtk_label_set_width_chars (GTK_LABEL (user_label), 35);
+ gtk_box_pack_start (GTK_BOX (vbox2), user_label, FALSE, FALSE, 0);
+
+ /* User input */
+ hbox2 = gtk_widget_new (GTK_TYPE_HBOX,
+ "border_width", 5,
+ "visible", TRUE,
+ "homogeneous", FALSE,
+ "spacing", 1,
+ NULL);
+
+ /* PAM prompt */
+ prompt_label = g_object_new (GTK_TYPE_LABEL,
+ /* blank space for prompt */
+ "label", _(" "),
+ "use_underline", TRUE,
+ "use_markup", FALSE,
+ "justify", GTK_JUSTIFY_CENTER,
+ "wrap", FALSE,
+ "selectable", FALSE,
+ "xalign", 1.0,
+ "xpad", 0,
+ "ypad", 0,
+ "visible", FALSE,
+ NULL);
+ pwd->user_prompt_label = prompt_label;
+
+ entry = g_object_new (GTK_TYPE_ENTRY,
+ "activates-default", TRUE,
+ "visible", TRUE,
+ "editable", TRUE,
+ "visibility", FALSE,
+ "can_focus", TRUE,
+ NULL);
+ pwd->user_input_entry = entry;
+ /* gtk_widget_grab_focus (entry); */
+ atk_entry = gtk_widget_get_accessible (entry);
+ atk_object_set_role (atk_entry, ATK_ROLE_PASSWORD_TEXT);
+
+ /* AT role = label for input widget */
+ atk_prompt_label = gtk_widget_get_accessible (prompt_label);
+ atk_object_add_relationship (atk_prompt_label, ATK_RELATION_LABEL_FOR,
+ atk_entry);
+ atk_object_add_relationship (atk_entry, ATK_RELATION_LABELLED_BY,
+ atk_prompt_label);
+
+ gtk_box_pack_start (GTK_BOX (hbox2), prompt_label, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (hbox2), entry, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox2), hbox2, FALSE, FALSE, 0);
+
+ pam_msg_label = g_object_new (GTK_TYPE_LABEL,
+ NULL);
+ pwd->pam_message_label = pam_msg_label;
+
+ gtk_box_pack_start (GTK_BOX (vbox2), pam_msg_label, FALSE, FALSE, 0);
+
+ /* date string */
+ tm = localtime (&now);
+ memset (buf, 0, sizeof (buf));
+ format_string_utf8 = _("%d-%b-%y (%a); %I:%M %p");
+ format_string_locale = g_locale_from_utf8 (format_string_utf8, -1,
+ NULL, NULL, NULL);
+ strftime (buf, sizeof (buf) - 1, format_string_locale, tm);
+ g_free (format_string_locale);
+
+ utf8_format = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL);
+ s = g_markup_printf_escaped ("<small>%s</small>", utf8_format);
+ g_free (utf8_format);
+
+ date_label = g_object_new (GTK_TYPE_LABEL,
+ "use-markup", TRUE,
+ "label", s,
+ NULL);
+ g_free (s);
+ gtk_box_pack_start (GTK_BOX (vbox2), date_label,
+ FALSE, FALSE, 0);
+
+ /* button box */
+ bbox = g_object_new (GTK_TYPE_HBUTTON_BOX,
+ "layout-style", GTK_BUTTONBOX_END,
+ "spacing", 10,
+ NULL);
+
+ /* Ok button */
+ button = gtk_button_new_from_stock (GTK_STOCK_OK);
+ pwd->button = button;
+
+ gtk_box_pack_end (GTK_BOX (bbox), button,
+ FALSE, TRUE, 0);
+
+ free (user);
+ free (version);
+ free (host);
+
+ /* POP */
+ gtk_widget_pop_colormap ();
+
+ return pwd;
+}
+
+/* Callback for when user has finished entering input, even though
+ we don't display an "OK" button for them to click on */
+static void
+ok_clicked_cb (GtkWidget *button, PasswdDialog *pwd)
+{
+ const char *s;
+
+ g_object_set (pwd->msg_label, "label", _("<b>Checking...</b>"), NULL);
+
+ s = gtk_entry_get_text (GTK_ENTRY (pwd->user_input_entry));
+ write_to_parent ("input", s, TRUE);
+
+ /* Reset password field to blank, else passwd field shows old passwd *'s,
+ visible when passwd is expired, and pam is walking the user to change
+ old passwd.
+ */
+ gtk_editable_delete_text (GTK_EDITABLE (pwd->user_input_entry), 0, -1);
+ gtk_widget_hide (pwd->user_input_entry);
+ gtk_widget_hide (pwd->user_prompt_label);
+}
+
+static void
+connect_signals (PasswdDialog *pwd)
+{
+ g_signal_connect (pwd->button, "clicked",
+ G_CALLBACK (ok_clicked_cb),
+ pwd);
+
+ g_signal_connect (pwd->user_input_entry, "activate",
+ G_CALLBACK (ok_clicked_cb),
+ pwd);
+
+ g_signal_connect (pwd->dialog, "delete-event",
+ G_CALLBACK (gtk_main_quit),
+ NULL);
+}
+
+static GdkFilterReturn
+dialog_filter_func (GdkXEvent *xevent, GdkEvent *gevent, gpointer data)
+{
+ PasswdDialog *pwd = data;
+ XEvent *event = xevent;
+ gdouble ratio;
+
+ if ((event->xany.type != ClientMessage ||
+ event->xclient.message_type != XA_UNLOCK_RATIO))
+ return GDK_FILTER_CONTINUE;
+
+ ratio = event->xclient.data.l[0] / (gdouble)100.0;
+
+ /* CR 6176524 passwdTimeoutEnable for disabled user */
+ if (event->xclient.data.l[1] == 0)
+ g_object_set (pwd->progress, "fraction", ratio, NULL);
+
+ return GDK_FILTER_REMOVE;
+}
+
+static gboolean
+handle_input (GIOChannel *source, GIOCondition cond, gpointer data)
+{
+ PasswdDialog *pwd = data;
+ GIOStatus status;
+ char *str;
+ char *label;
+ char *hmsg = NULL; /* This is the heading of lock dialog..shows status */
+
+ if (cond & G_IO_HUP) /* daemon crashed/exited/was killed */
+ gtk_main_quit ();
+
+ do
+ {
+ status = g_io_channel_read_line (source, &str, NULL, NULL, NULL);
+ }
+ while (status == G_IO_STATUS_AGAIN);
+
+/* debug only
+ if (status == G_IO_STATUS_ERROR)
+ g_message ("handle input() status_error %s\n",str);
+ if (status == G_IO_STATUS_EOF)
+ g_message ("handle input() status_eof %s\n",str);
+ if (status == G_IO_STATUS_NORMAL)
+ g_message ("handle input() status_normal %s\n",str);
+ Most likely, the returned error msg of g_io_channel_read_line(),
+ i.e str will not be translated into other locales ...
+*/
+
+ if (str)
+ {
+ /* strip trailing newline */
+ char *nl = strrchr(str, '\n');
+ if (nl)
+ *nl = 0;
+
+ /*
+ fprintf (stderr,">>>>>Child..in handle_input..string is:%s\n",str);
+ fflush (stderr);
+ */
+
+ /* Handle commands from parent daemon */
+
+ if (((strncmp (str, "ul_", 3)) == 0))
+ {
+ /* search for =, and if found, split into two strings there */
+ char *msgstr = strchr(str, '='); /* Data sent with command */
+ if (msgstr)
+ *msgstr++ = 0;
+
+ if ((strcmp (str, "ul_ok") == 0))
+ {
+ hmsg = _("Authentication Successful!");
+ }
+ else if ((strcmp (str, "ul_acct_ok") == 0))
+ {
+ hmsg = _("PAM Account Management Also Successful!");
+ }
+ else if ((strcmp (str, "ul_setcred_fail") == 0))
+ {
+ hmsg = _("Just a Warning PAM Set Credential Failed!");
+ }
+ else if ((strcmp (str, "ul_setcred_ok") == 0))
+ {
+ hmsg = _("PAM Set Credential Also Successful!");
+ }
+ else if ((strcmp (str, "ul_acct_fail") == 0))
+ {
+ hmsg = _("Your Password has expired.");
+ }
+ else if ((strcmp (str, "ul_fail") == 0))
+ {
+ hmsg = _("Sorry!");
+ }
+ else if ((strcmp (str, "ul_read") == 0))
+ {
+ hmsg = _("Waiting for user input!");
+ }
+ else if ((strcmp (str, "ul_time") == 0))
+ {
+ hmsg = _("Timed Out!");
+ }
+ else if ((strcmp (str, "ul_null") == 0))
+ {
+ hmsg = _("Still Checking!");
+ }
+ else if ((strcmp (str, "ul_cancel") == 0))
+ {
+ hmsg = _("Authentication Cancelled!");
+ }
+ else if ((strcmp (str, "ul_pamprompt") == 0))
+ {
+ gtk_label_set_text (GTK_LABEL (pwd->user_prompt_label), msgstr);
+ gtk_widget_show (pwd->user_prompt_label);
+ msgstr = NULL; /* clear message so we don't show it twice */
+ }
+ else if ((strcmp (str, "ul_prompt_echo") == 0))
+ {
+ if ((strcmp (msgstr, "true") == 0))
+ {
+ gtk_entry_set_visibility
+ (GTK_ENTRY (pwd->user_input_entry), TRUE);
+ }
+ else
+ {
+ if ((strcmp (msgstr, "stars") == 0))
+ /* reset to default display of "*" or bullet */
+ gtk_entry_unset_invisible_char
+ (GTK_ENTRY (pwd->user_input_entry));
+ else
+ /* set to no display */
+ gtk_entry_set_invisible_char
+ (GTK_ENTRY (pwd->user_input_entry), 0);
+
+ gtk_entry_set_visibility
+ (GTK_ENTRY (pwd->user_input_entry), FALSE);
+ }
+ msgstr = NULL; /* clear message so we don't show it to user */
+ /* Show the entry field */
+ gtk_widget_show (pwd->user_input_entry);
+ gtk_widget_grab_focus (pwd->user_input_entry);
+ gdk_display_sync
+ (gtk_widget_get_display (pwd->user_input_entry));
+ }
+ else if ((strcmp (str, "ul_message") == 0))
+ {
+ hmsg = NULL; /* only show msg */
+ }
+ else
+ {
+ /* Should not be others, but if so just show it */
+ hmsg = str;
+ }
+
+ if (hmsg)
+ {
+ label = g_markup_printf_escaped ("<b>%s</b>", hmsg);
+ g_object_set (pwd->msg_label, "label", label, NULL);
+ g_free (label);
+ }
+
+ if (msgstr)
+ {
+ gtk_label_set_text (GTK_LABEL (pwd->pam_message_label), msgstr);
+ }
+ }
+ else if ((strcmp (str, "cmd_exit") == 0))
+ {
+ gtk_main_quit ();
+ }
+ else /* something came through that didn't start with ul_ */
+ {
+ gtk_label_set_text (GTK_LABEL (pwd->pam_message_label), str);
+ }
+
+ g_free (str);
+ }
+
+ return (status != G_IO_STATUS_EOF);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GIOChannel *ioc;
+ PasswdDialog *pwd;
+ char *s;
+ char *real_progname = argv[0];
+ GConfClient *client;
+ const char *modulesptr = NULL;
+ int i;
+ const char *locale = NULL;
+
+ gboolean at_enable = FALSE; /* accessibility mode enabled ? */
+ gboolean center_position = TRUE; /* center dialog on screen? */
+
+#ifdef ENABLE_NLS
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ textdomain (GETTEXT_PACKAGE);
+
+#ifdef HAVE_GTK2
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#else /* ! HAVE_GTK2 */
+ if (!setlocale (LC_ALL, ""))
+ fprintf (stderr, "%s: locale not supported by C library\n", real_progname);
+#endif /* ! HAVE_GTK2 */
+#endif /* ENABLE_NLS */
+
+ s = strrchr (real_progname, '/');
+ if (s) real_progname = s+1;
+ progname = real_progname;
+
+ parent_file = fdopen(FD_TO_PARENT, "w");
+ if (!parent_file)
+ {
+ fprintf (stderr, "%s: can't communicate with parent, exiting.\n",
+ progname);
+ exit (1);
+ }
+
+ gtk_init (&argc, &argv);
+
+ /* Intern the atoms that xscreensaver_command() needs.
+ */
+ {
+ Display *dpy = gdk_x11_get_default_xdisplay();
+
+ const struct atom_request unlock_atoms[] =
+ {
+ { &XA_UNLOCK_RATIO, "UNLOCK_RATIO" },
+ { NULL, NULL } /* Must be last to terminate list */
+ };
+
+ const struct atom_request *atom_lists[3] = { NULL, NULL, NULL };
+ atom_lists[0] = remote_control_atoms;
+ atom_lists[1] = unlock_atoms;
+ request_atoms (dpy, atom_lists);
+ }
+
+ /* bugid 6346056(P1):
+ ATOK pallet sometimes appears in screensave/lock-screen mode
+ */
+ putenv ("GTK_IM_MODULE=gtk-im-context-simple");
+
+
+ /* accessibility mode enabled ? */
+ client = gconf_client_get_default ();
+ at_enable = gconf_client_get_bool (client,
+ NULL);
+ if (at_enable)
+ {
+
+ /* GTK Accessibility Module initialized */
+ modulesptr = g_getenv ("GTK_MODULES");
+ if (!modulesptr || modulesptr [0] == '\0')
+ putenv ("GTK_MODULES=gail:atk-bridge");
+
+ /*
+ * 6182506: unlock dialog can be obscured by the magnifier window
+ * if it's always centered, so don't force that if any accessibility
+ * helpers are present
+ */
+ center_position = FALSE;
+ } /* accessibility enabled */
+
+ pwd = make_dialog (center_position);
+ connect_signals (pwd);
+
+ gtk_widget_show_all (pwd->dialog);
+ gtk_window_present (GTK_WINDOW (pwd->dialog));
+ gtk_widget_map (pwd->dialog);
+
+ gdk_display_sync (gtk_widget_get_display (pwd->dialog));
+
+ gdk_window_add_filter (GET_WINDOW (pwd->dialog), dialog_filter_func, pwd);
+ write_windowid ("dialog_win", GDK_WINDOW_XID (GET_WINDOW (pwd->dialog)));
+
+ /* Flush dialog window ids & any messages about login helpers to parent */
+ write_to_parent(NULL, NULL, TRUE);
+
+ gtk_widget_grab_focus (pwd->user_input_entry);
+
+ ioc = g_io_channel_unix_new (0);
+ g_get_charset (&locale);
+ g_io_channel_set_encoding(ioc, locale, NULL);
+ g_io_add_watch (ioc, G_IO_IN | G_IO_HUP, handle_input, pwd);
+
+ gtk_main ();
+
+ return 0;
+}
+#endif /* HAVE_GTK2 */
diff --git a/driver/lock.c b/driver/lock.c
index 7c92be6..a4114e2 100644
--- a/driver/lock.c
+++ b/driver/lock.c
@@ -21,8 +21,13 @@
#include <X11/Intrinsic.h>
#include <X11/cursorfont.h>
#include <X11/Xos.h> /* for time() */
+#include <X11/Xatom.h>
#include <time.h>
#include <sys/time.h>
+#include <errno.h>
+#include <gconf/gconf-client.h>
+#include "exec.h"
+#include "dialog-data.h"
#include "xscreensaver.h"
#include "resources.h"
#include "mlstring.h"
@@ -83,126 +88,631 @@ vms_passwd_valid_p(char *pw, Bool verbose_p)
typedef struct info_dialog_data info_dialog_data;
+/* struct passwd_dialog_data moved to dialog-data.h */
-#define MAX_BYTES_PER_CHAR 8 /* UTF-8 uses no more than 3, I think */
-#define MAX_PASSWD_CHARS 128 /* Longest possible passphrase */
-
-struct passwd_dialog_data {
-
- saver_screen_info *prompt_screen;
- int previous_mouse_x, previous_mouse_y;
-
- /* "Characters" in the password may be a variable number of bytes long.
- typed_passwd contains the raw bytes.
- typed_passwd_char_size indicates the size in bytes of each character,
- so that we can make backspace work.
- */
- char typed_passwd [MAX_PASSWD_CHARS * MAX_BYTES_PER_CHAR];
- char typed_passwd_char_size [MAX_PASSWD_CHARS];
-
- XtIntervalId timer;
- int i_beam;
-
- float ratio;
- Position x, y;
- Dimension width;
- Dimension height;
- Dimension border_width;
-
- Bool echo_input;
- Bool show_stars_p; /* "I regret that I have but one asterisk for my country."
- -- Nathan Hale, 1776. */
-
- char *heading_label;
- char *body_label;
- char *user_label;
- mlstring *info_label;
- /* The entry field shall only be displayed if prompt_label is not NULL */
- mlstring *prompt_label;
- char *date_label;
- char *passwd_string;
- Bool passwd_changed_p; /* Whether the user entry field needs redrawing */
- Bool caps_p; /* Whether we saw a keypress with caps-lock on */
- char *unlock_label;
- char *login_label;
- char *uname_label;
-
- Bool show_uname_p;
-
- XFontStruct *heading_font;
- XFontStruct *body_font;
- XFontStruct *label_font;
- XFontStruct *passwd_font;
- XFontStruct *date_font;
- XFontStruct *button_font;
- XFontStruct *uname_font;
-
- Pixel foreground;
- Pixel background;
- Pixel border;
- Pixel passwd_foreground;
- Pixel passwd_background;
- Pixel thermo_foreground;
- Pixel thermo_background;
- Pixel shadow_top;
- Pixel shadow_bottom;
- Pixel button_foreground;
- Pixel button_background;
-
- Dimension preferred_logo_width, logo_width;
- Dimension preferred_logo_height, logo_height;
- Dimension thermo_width;
- Dimension internal_border;
- Dimension shadow_width;
-
- Dimension passwd_field_x, passwd_field_y;
- Dimension passwd_field_width, passwd_field_height;
-
- Dimension unlock_button_x, unlock_button_y;
- Dimension unlock_button_width, unlock_button_height;
-
- Dimension login_button_x, login_button_y;
- Dimension login_button_width, login_button_height;
-
- Dimension thermo_field_x, thermo_field_y;
- Dimension thermo_field_height;
-
- Pixmap logo_pixmap;
- Pixmap logo_clipmask;
- int logo_npixels;
- unsigned long *logo_pixels;
-
- Cursor passwd_cursor;
- Bool unlock_button_down_p;
- Bool login_button_down_p;
- Bool login_button_p;
- Bool login_button_enabled_p;
- Bool button_state_changed_p; /* Refers to both buttons */
-
- Pixmap save_under;
- Pixmap user_entry_pixmap;
-};
-
+#ifndef HAVE_XSCREENSAVER_LOCK
static void draw_passwd_window (saver_info *si);
+#endif
static void update_passwd_window (saver_info *si, const char *printed_passwd,
float ratio);
static void destroy_passwd_window (saver_info *si);
+static int ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error);
static void undo_vp_motion (saver_info *si);
+#ifndef HAVE_XSCREENSAVER_LOCK
static void finished_typing_passwd (saver_info *si, passwd_dialog_data *pw);
+#endif
static void cleanup_passwd_window (saver_info *si);
static void restore_background (saver_info *si);
extern void xss_authenticate(saver_info *si, Bool verbose_p);
+#ifdef HAVE_XSCREENSAVER_LOCK
+
+#define WIN_ALLOC_INCREMENT 8 /* allocate entries in the window lists in
+ increments of 8 at a time for fewer
+ reallocs and less chance of malloc error
+ at the wrong time */
+#define EXTRA_RAISE_WIN_SLOTS 4 /* Need to leave four extra slots free in
+ raise_wins to allow calling XRestackWindows
+ when a window pops up without having to
+ realloc or copy to a new list.
+ These slots would be used by:
+ - passwd_dialog
+ - stderr_overlay_window
+ - xscreensaver virtual root
+ - an interloper popup we need to hide
+ */
+
+extern Atom XA_UNLOCK_RATIO;
+
+Bool g_passwd_dialog_created = 0;
+
+GConfClient *client = NULL;
+
+static const char *switch_windows_gconf_key
+static char *global_switch_key = NULL;
+
+static const char *main_menu_gconf_key
+static char *global_menu_key = NULL;
+
+extern Bool safe_XDestroyWindow (Display *dpy, Window window);
+static Bool safe_XRestackWindows(Display *dpy, Window windows[], int nwindows);
+static Bool safe_XSendEvent(Display *dpy, Window w, Bool propagate,
+ long event_mask, XEvent *event_send);
+static void passwd_animate_timer (XtPointer closure, XtIntervalId *id);
+extern void swallow_unlock_typeahead_events (saver_info *si, XEvent *e);
+
+
+static saver_screen_info *
+find_screen_for_window (saver_info *si, Window wid)
+{
+ saver_screen_info *ssi;
+ Screen *screen;
+ Window root, root_ret, parent_ret, *children = NULL;
+ unsigned int nchildren = 0;
+ int screen_no, status;
+
+ status = XQueryTree (si->dpy, wid, &root_ret, &parent_ret,
+ &children, &nchildren);
+
+ if (status == 0) /* failed */
+ return NULL;
+
+ XFree(children);
+ children = NULL;
+
+ for (screen_no = 0; screen_no < si->nscreens; screen_no++)
+ {
+ ssi = &si->screens[screen_no];
+ screen = ssi->screen;
+ root = RootWindowOfScreen (screen);
+
+ if (root == root_ret)
+ return ssi;
+ }
+
+ return NULL; /* Didn't match the root on any screen we know of - PUNT! */
+}
+
+/*
+ 5083155 Unable to unlock screen when running dual-head MAG
+ adding dual or multiple heads for magnifier support
+
+ screen 0: loginhelp can pass the raisedWid of GOK or MAG or both
+ found: return its parent Wid (child of root)
+ not found: 0
+
+ other screen: MAG only if the target screen no > 0 is selected
+ found: restack on that screen
+ return 0
+ not-found : return 0
+
+ */
+
+static Window
+check_raisedWid (saver_info *si, Window wid)
+{
+ saver_screen_info *ssi;
+ Screen *screen;
+ Window root, root_ret, parent_ret, *children = NULL;
+ unsigned int nchildren = 0;
+ int screen_no, status;
+
+ status = XQueryTree (si->dpy, wid, &root_ret, &parent_ret,
+ &children, &nchildren);
+
+ if (status == 0) /* failed */
+ return 0;
+
+ XFree(children);
+ children = NULL;
+
+ for (screen_no = 0; screen_no < si->nscreens; screen_no++)
+ {
+ ssi = &si->screens[screen_no];
+ screen = ssi->screen;
+ root = RootWindowOfScreen (screen);
+
+ if (root == root_ret)
+ break;
+ }
+
+ if ( screen_no >= si->nscreens ) /* Didn't match the root on any screen */
+ return 0; /* we know of - PUNT! */
+
+ /* Climb the tree until we find an ancestor that's a child of root */
+ while ( root_ret != parent_ret )
+ {
+ wid = parent_ret;
+
+ status = XQueryTree (si->dpy, wid, &root_ret, &parent_ret,
+ &children, &nchildren);
+
+ if (status == 0) /* failed */
+ return 0;
+
+ XFree(children);
+ children = NULL;
+ }
+
+ if ( ssi != si->pw_data->prompt_screen )
+ {
+ /* found in other screen (not the one with the unlock dialog),
+ implies MAG target screen, invoke XRestackWindow() there
+ */
+ Window screen_win[2] = { wid, ssi->screensaver_window };
+ safe_XRestackWindows(si->dpy, screen_win, 2);
+ return 0; /* no need to do the restack on prompt screen */
+ }
+
+ return wid;
+}
+
+/* Enforce window stacking order when a new window arrives.
+ Only allow raising windows the unlock dialog has told us to raise
+ (including itself).
+ */
+static void
+restack_my_windows (saver_info* si, saver_screen_info *ssi, Window newWin)
+{
+ int n = 0;
+ Window short_stack[EXTRA_RAISE_WIN_SLOTS];
+ Window *restack_list;
+ Bool allowed = False;
+
+ /* If window is on another screen than the unlock dialog,
+ or we have list of no windows to raise */
+ if ((si->raise_wins == NULL) || (ssi != si->pw_data->prompt_screen))
+ {
+ restack_list = short_stack;
+ }
+ else
+ {
+ restack_list = si->raise_wins;
+ for (n = 0; n < si->num_raise_wins; n++)
+ {
+ if (si->raise_wins[n] == newWin)
+ allowed = True;
+ }
+ }
+
+ if (si->passwd_dialog && (ssi == si->pw_data->prompt_screen))
+ {
+ restack_list[n++] = si->passwd_dialog;
+ if (si->passwd_dialog == newWin)
+ allowed = True;
+ }
+
+ if (ssi->stderr_overlay_window)
+ {
+ restack_list[n++] = ssi->stderr_overlay_window;
+ if (ssi->stderr_overlay_window == newWin)
+ allowed = True;
+ }
+
+ if (ssi->screensaver_window)
+ {
+ restack_list[n++] = ssi->screensaver_window;
+ if (ssi->screensaver_window == newWin)
+ allowed = True;
+ }
+
+ /* If it's not in the allowed list, it goes behind
+ the screensaver_window. */
+ if (newWin && !allowed)
+ restack_list[n++] = newWin;
+
+ if (n > 1)
+ safe_XRestackWindows (si->dpy, restack_list, n);
+}
+
+/* Send a command to the xscreensaver-lock child process
+ Arguments:
+ - msg - message to send, such as ul_ok
+ - data - additional data, such as string to display for this message,
+ if any, otherwise NULL
+ Message format sent to child:
+ "msg\n" if no data, otherwise "msg=data\n"
+ */
+int
+write_to_child (saver_info* si, const char* msg, const char *data)
+{
+ if (msg == NULL)
+ {
+ fprintf (stderr, "Invalid null message written to child\n");
+ return -1;
+ }
+
+ if (si->external_passwd && g_passwd_dialog_created &&
+ si->pw_data->stdin_fd != -1)
+ {
+ int len;
+
+ if (si->prefs.verbose_p)
+ {
+ fprintf (stderr,
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+ "HAVE_SCRSVR_LOCK writing to fd:%d message is:\n%s=%s\n"
+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n",
+ si->pw_data->stdin_fd, msg, data ? data : "(null)");
+ }
+
+ if (data)
+ len = fprintf (si->pw_data->stdin_file, "%s=%s\n", msg, data);
+ else
+ len = fprintf (si->pw_data->stdin_file, "%s\n", msg);
+
+ fflush (si->pw_data->stdin_file);
+ return len;
+ }
+
+ return (0); /* if we didn't write anything return 0 */
+}
+
+static int
+sane_dup2 (int fd1, int fd2)
+{
+ int ret;
+
+ do
+ {
+ ret = dup2 (fd1, fd2);
+ }
+ while (ret < 0 && errno == EINTR);
+
+ return ret;
+}
+
+static int
+close_and_invalidate (int *fd)
+{
+ int ret;
+
+ ret = close (*fd);
+ *fd = -1;
+
+ return ret;
+}
+
+void
+handle_passwd_input (XtPointer xtdata, int *fd, XtInputId *id)
+{
+ saver_info *si = (saver_info *)xtdata;
+ saver_preferences *p = &si->prefs;
+ char buffer[1024];
+ char *msg, *data;
+ passwd_dialog_data *pw = si->pw_data;
+
+ if (p->verbose_p)
+ fprintf (stderr, "passwd input handler() fd=%d\n", *fd);
+
+ msg = fgets (buffer, sizeof (buffer), pw->stdout_file);
+ if (!msg) /* child closed pipe */
+ {
+ if (p->verbose_p)
+ {
+ fprintf (stderr, "done reading...\n");
+ fprintf (stderr, "removing input handler...\n");
+ }
+ XtRemoveInput (*id);
+ pw->stdout_input_id = 0;
+
+ if (p->verbose_p)
+ fprintf (stderr, "passwd input handler() returning...done reading\n");
+
+ return;
+ }
+
+ if (p->verbose_p)
+ fprintf (stderr, "Child sent message: %s\n", msg);
+
+ /* search for =, and if found, split msg & data into two strings there */
+ data = strchr(msg, '=');
+ if (data)
+ {
+ char *nl;
+
+ *data++ = 0;
+
+ /* strip trailing newline */
+ nl = strchr (data, '\n');
+ if (nl)
+ *nl = '\0';
+ }
+ else
+ {
+ /* All the messages we currently expect require data! */
+ if (p->verbose_p)
+ fprintf (stderr, "*** Invalid message: no data found, discarding\n");
+
+ return;
+ }
+
+ if ((strcmp(msg, "input") == 0)) /* User input */
+ {
+ si->unlock_state = ul_finished;
+ pw->got_passwd = TRUE;
+ pw->passwd_string = strdup (data);
+ memset (data, 0, strlen(data));
+ }
+ else if ((strcmp(msg, "ungrab_keyboard") == 0))
+ {
+ /* An accessibility helper needs to access the keyboard, so we have
+ to release our grab - unfortunately this risks other apps acting
+ on keys they shouldn't, so first we disable metacity keys that
+ could allow getting back to the locked session windows, and hope
+ we don't crash or die before restoring them later.
+
+ Other window managers are likely to be risky to use in this case.
+ */
+
+ if (client == NULL)
+ client = gconf_client_get_default();
+
+ if (global_switch_key == NULL)
+ {
+ global_switch_key =
+ gconf_client_get_string (client, switch_windows_gconf_key, NULL);
+
+ if (global_switch_key && strncmp (global_switch_key, "dis", 3))
+ gconf_client_set_string (client, switch_windows_gconf_key,
+ "disabled", NULL);
+ }
+
+ if (global_menu_key == NULL)
+ {
+ global_menu_key =
+ gconf_client_get_string (client, main_menu_gconf_key, NULL);
+
+ if (global_menu_key && strncmp(global_menu_key, "dis", 3))
+ gconf_client_set_string (client, main_menu_gconf_key,
+ "disabled", NULL);
+ }
+
+ XUngrabKeyboard (si->dpy, CurrentTime);
+ XFlush (si->dpy);
+ }
+ else if ((strcmp(msg, "ungrab_pointer") == 0))
+ {
+ /* An accessibility helper needs to access the mouse, so we have
+ to release our grab - this is simpler, since we don't worry about
+ mouse gestures that may get through, though maybe we should...
+ */
+
+ XUngrabPointer (si->dpy, CurrentTime);
+ XFlush (si->dpy);
+ }
+ else /* Get a window id of an interesting window from the child */
+ {
+ Window window = strtoul (data, NULL, 0);
+ int status;
+
+ if ((strcmp (msg, "dialog_win") == 0))
+ {
+ /* The unlock dialog itself */
+ si->passwd_dialog = window;
+ pw->got_windowid = True;
+
+ move_mouse_grab (si, si->passwd_dialog, pw->passwd_cursor,
+ pw->prompt_screen->number);
+ undo_vp_motion (si);
+ passwd_animate_timer ((XtPointer) si, 0);
+
+ /* Flush queue of captured typeahead events */
+ if (si->typeahead_events && si->num_typeahead_events)
+ {
+ int i;
+
+ for (i = 0; i < si->num_typeahead_events; i++)
+ {
+ si->typeahead_events[i].window = window;
+ safe_XSendEvent (si->dpy, window, False, KeyPressMask,
+ (XEvent *) &si->typeahead_events[i]);
+ }
+ si->num_typeahead_events = 0;
+ }
+ XGrabKeyboard (si->dpy, window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XGrabPointer (si->dpy, window, True, 0, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+ XFlush (si->dpy);
+ XSetInputFocus (si->dpy, window, RevertToPointerRoot, CurrentTime);
+ XSync (si->dpy, False);
+ }
+ else if ((strcmp (msg, "raise_win") == 0))
+ {
+ /* Accessibility helpers that need to be raised above the
+ full-screen blanking window hiding the user's desktop */
+ Window *newlist;
+ Window overwin;
+
+ if ( (si->num_raise_wins + EXTRA_RAISE_WIN_SLOTS)
+ >= si->max_raise_wins)
+ {
+ int raise_alloc = si->max_raise_wins + WIN_ALLOC_INCREMENT;
+
+ newlist = realloc(si->raise_wins, raise_alloc * sizeof(Window));
+ if (newlist == NULL)
+ return;
+
+ si->raise_wins = newlist;
+ si->max_raise_wins = raise_alloc;
+ }
+
+ overwin = check_raisedWid (si, window);
+ if (overwin)
+ {
+ XWindowAttributes attrs;
+ status = XGetWindowAttributes (si->dpy, overwin, &attrs);
+
+ if ( status && !attrs.override_redirect )
+ {
+ unsigned long valuemask = CWOverrideRedirect;
+ XSetWindowAttributes setwinattr;
+ setwinattr.override_redirect = True;
+
+ XChangeWindowAttributes (si->dpy, overwin,
+ valuemask, &setwinattr);
+
+ if (si->num_override_wins >= si->max_override_wins)
+ {
+ int over_alloc
+ = si->max_override_wins + WIN_ALLOC_INCREMENT;
+
+ newlist = realloc(si->override_wins,
+ over_alloc * sizeof(Window));
+ if (newlist == NULL)
+ return;
+
+ si->override_wins = newlist;
+ si->max_override_wins = over_alloc;
+ }
+
+ si->override_wins[si->num_override_wins++] = overwin;
+ }
+ XMapSubwindows(si->dpy, overwin);
+ si->raise_wins[si->num_raise_wins++] = overwin;
+ }
+ else
+ si->raise_wins[si->num_raise_wins++] = window;
+ } /* "raise_win" */
+
+ restack_my_windows(si, si->pw_data->prompt_screen, 0);
+ }
+}
+
+/* returns successful fork/exec */
+Bool
+spawn_external_passwd_process (saver_info *si, passwd_dialog_data *pw)
+{
+ saver_preferences *p = &si->prefs;
+ pid_t forked;
+ const char *command = LOCKDIR "/xscreensaver-lock";
+ int stdin_pipe[2] = { -1, -1 };
+ int stdout_pipe[2] = { -1, -1 };
+
+ si->passwd_pid = 0;
+ pw->stdin_fd = pw->stdout_fd = -1;
+ pw->got_windowid = False;
+
+ if (si->prefs.verbose_p)
+ fprintf(stderr, "-->spawn_external_passwd()\n");
+
+ if (si->passwd_pid > 0)
+ {
+ if (si->prefs.verbose_p)
+ fprintf (stderr,"pid %ld still exists. Killing it with SIGKILL\n",
+ si->passwd_pid);
+ kill_job (si, si->passwd_pid, SIGKILL);
+ }
+ si->passwd_pid = 0;
+
+ if (pipe (stdin_pipe) < 0)
+ {
+ perror ("pipe(stdin_pipe) failed!");
+ return False;
+ }
+
+ if (pipe (stdout_pipe) < 0)
+ {
+ perror ("pipe(stdout_pipe) failed!");
+ close_and_invalidate (&stdin_pipe[0]);
+ close_and_invalidate (&stdin_pipe[1]);
+ return False;
+ }
+ switch ((int) (forked = fork ()))
+ {
+ case -1:
+ fprintf (stderr, "%s: ", blurb ());
+ perror ("couldn't fork");
+
+ close_and_invalidate (&stdin_pipe[0]);
+ close_and_invalidate (&stdin_pipe[1]);
+ close_and_invalidate (&stdout_pipe[0]);
+ close_and_invalidate (&stdout_pipe[1]);
+
+ return False;
+
+ case 0:
+ close (ConnectionNumber (si->dpy)); /* close display fd */
+ /* limit_subproc_memory (p->inferior_memory_limit, p->verbose_p); */
+ /* hack_subproc_environment (ssi); */ /* FIX $DISPLAY */
+
+ /* Inside Child Process */
+ if (p->verbose_p)
+ fprintf (stderr, "%s: spawning \"%s\" in pid %lu.\n",
+ blurb(), command, (unsigned long) getpid ());
+
+ close_and_invalidate (&stdin_pipe[1]);
+ close_and_invalidate (&stdout_pipe[0]);
+
+ sane_dup2 (stdin_pipe[0], 0); /* Listen to Parent from here */
+ sane_dup2 (stdout_pipe[1], 9); /* Talk to Parent from here */
+
+ /* Make sure we have relinquished setuid privs or lock dialog gtk
+ * program will not run as libgtk is not setuid safe.
+ */
+ hack_uid (si);
+
+ exec_command (p->shell, command, 0);
+ /* print_path_error (command); */
+ fprintf (stderr, "%s: couldn't exec: %s\n",
+ blurb (), command);
+ abort ();
+
+ default:
+ /* In Parent */
+ make_job(forked, 0, command);
+ close_and_invalidate (&stdin_pipe[0]);
+ close_and_invalidate (&stdout_pipe[1]);
+
+ sane_dup2 (stdin_pipe[0], 0); /* Listen to Child from here */
+ sane_dup2 (stdout_pipe[1], 13); /* Talk to Child from here */
+
+ pw->stdin_fd = stdin_pipe[1]; /* Talk to child from here */
+ pw->stdout_fd = stdout_pipe[0]; /* Listen to Child from here */
+ si->passwd_pid = forked;
+
+ /* Messages to child dialog are sent through this pipe/fd */
+ pw->stdin_file = fdopen (pw->stdin_fd, "w");
+ write_to_child (si, "Hello", NULL); /* Send a test message to Child */
+
+ /* Password from child dialog comes through this pipe/fd */
+ pw->stdout_file = fdopen (pw->stdout_fd, "r");
+
+ pw->stdout_input_id = XtAppAddInput (si->app, pw->stdout_fd,
+ (XtPointer) XtInputReadMask,
+ handle_passwd_input, si);
+
+ /* Set global flag to indicate that lock dialog is visible */
+ g_passwd_dialog_created = True;
+ return True;
+ }
+
+ /* shouldn't reach */
+ abort ();
+ return False;
+}
+#endif /* HAVE_XSCREENSAVER_LOCK */
+
static int
new_passwd_window (saver_info *si)
{
passwd_dialog_data *pw;
+#ifndef HAVE_XSCREENSAVER_LOCK
Screen *screen;
Colormap cmap;
char *f;
+#endif
saver_screen_info *ssi = &si->screens [mouse_screen (si)];
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* si->pw_data is globally allocated and never freed when HAVE_XSS_LOCK */
+ pw = si->pw_data;
+ if (!spawn_external_passwd_process (si, pw))
+ return -1;
+ si->external_passwd = True;
+#else
pw = (passwd_dialog_data *) calloc (1, sizeof(*pw));
if (!pw)
return -1;
@@ -211,17 +721,21 @@ new_passwd_window (saver_info *si)
*/
pw->login_button_p = (si->prefs.new_login_command &&
*si->prefs.new_login_command);
+#endif
pw->passwd_cursor = XCreateFontCursor (si->dpy, XC_top_left_arrow);
pw->prompt_screen = ssi;
+#ifndef HAVE_XSCREENSAVER_LOCK
screen = pw->prompt_screen->screen;
cmap = DefaultColormapOfScreen (screen);
+#endif
pw->show_stars_p = get_boolean_resource(si->dpy, "passwd.asterisks",
"Boolean");
+#ifndef HAVE_XSCREENSAVER_LOCK
pw->heading_label = get_string_resource (si->dpy, "passwd.heading.label",
pw->body_label = get_string_resource (si->dpy, "passwd.body.label",
@@ -376,6 +890,7 @@ new_passwd_window (saver_info *si)
if (pw->shadow_width == 0) pw->shadow_width = 4;
if (pw->thermo_width == 0) pw->thermo_width = pw->shadow_width;
+#endif /* ! HAVE_XSCREENSAVER_LOCK */
/* We need to remember the mouse position and restore it afterward, or
sometimes (perhaps only with Xinerama?) the mouse gets warped to
@@ -442,12 +957,16 @@ make_passwd_window (saver_info *si,
const char *prompt,
Bool echo)
{
+#ifndef HAVE_XSCREENSAVER_LOCK
XSetWindowAttributes attrs;
unsigned long attrmask = 0;
+#endif
passwd_dialog_data *pw;
+#ifndef HAVE_XSCREENSAVER_LOCK
Screen *screen;
Colormap cmap;
Dimension max_string_width_px;
+#endif
saver_screen_info *ssi = &si->screens [mouse_screen (si)];
cleanup_passwd_window (si);
@@ -455,7 +974,12 @@ make_passwd_window (saver_info *si,
if (! ssi) /* WTF? Trying to prompt while no screens connected? */
return -1;
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* si->pw_data is globally allocated and never freed when HAVE_XSS_LOCK */
+ if (!si->pw_data->got_windowid)
+#else
if (!si->pw_data)
+#endif
if (new_passwd_window (si) < 0)
return -1;
@@ -470,6 +994,29 @@ make_passwd_window (saver_info *si,
blurb(), pw->prompt_screen->number,
info_msg ? info_msg : "");
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* Wipe the old password, so we get prompted to enter new password. */
+ if (pw->passwd_string)
+ {
+ memset(pw->passwd_string, 0, strlen (pw->passwd_string));
+ free (pw->passwd_string);
+ pw->passwd_string = NULL;
+ }
+
+ if (info_msg)
+ write_to_child (si, "ul_message", info_msg);
+ if (prompt)
+ {
+ write_to_child (si, "ul_pamprompt", prompt);
+
+ if (echo)
+ write_to_child (si, "ul_prompt_echo", "true");
+ else if (pw->show_stars_p)
+ write_to_child (si, "ul_prompt_echo", "stars");
+ else
+ write_to_child (si, "ul_prompt_echo", "false");
+ }
+#else
screen = pw->prompt_screen->screen;
cmap = DefaultColormapOfScreen (screen);
@@ -721,11 +1268,13 @@ make_passwd_window (saver_info *si,
if (cmap)
XInstallColormap (si->dpy, cmap);
draw_passwd_window (si);
+#endif /* ! HAVE_XSCREENSAVER_LOCK */
return 0;
}
+#ifndef HAVE_XSCREENSAVER_LOCK
static void
draw_passwd_window (saver_info *si)
{
@@ -1071,17 +1620,48 @@ draw_button(Display *dpy,
draw_shaded_rectangle(dpy, dialog, x, y, width, height,
shadow_width, shadow_light, shadow_dark);
}
+#endif /* !HAVE_XSCREENSAVER_LOCK */
static void
update_passwd_window (saver_info *si, const char *printed_passwd, float ratio)
{
passwd_dialog_data *pw = si->pw_data;
+#ifndef HAVE_XSCREENSAVER_LOCK
XGCValues gcv;
GC gc1, gc2;
int x, y;
XRectangle rects[1];
+#endif
pw->ratio = ratio;
+
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* Send countdown timer ratio to child lock dialog */
+ if (si->passwd_dialog)
+ {
+ XEvent event;
+
+ event.xany.type = ClientMessage;
+ event.xclient.display = si->dpy;
+ event.xclient.window = si->passwd_dialog;
+ event.xclient.message_type = XA_UNLOCK_RATIO;
+ event.xclient.format = 32;
+ memset (&event.xclient.data, 0, sizeof (event.xclient.data));
+ event.xclient.data.l[0] = (long)(pw->ratio * 100);
+ event.xclient.data.l[1] = 0;
+ event.xclient.data.l[2] = 0;
+
+ if (!safe_XSendEvent (si->dpy, si->passwd_dialog, False, 0L, &event))
+ fprintf (stderr, "%s: error sending ratio to lock dialog\n", blurb ());
+ }
+ else
+ {
+ if (si->prefs.verbose_p)
+ fprintf (stderr,
+ "-->update_passwd_window() lockdialog not created, returning!!\n");
+ return;
+ }
+#else
gcv.foreground = pw->passwd_foreground;
gcv.font = pw->passwd_font->fid;
gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground|GCFont, &gcv);
@@ -1226,6 +1806,7 @@ update_passwd_window (saver_info *si, const char *printed_passwd, float ratio)
XFreeGC (si->dpy, gc1);
XFreeGC (si->dpy, gc2);
XSync (si->dpy, False);
+#endif /* !HAVE_XSCREENSAVER_LOCK */
}
@@ -1257,6 +1838,9 @@ cleanup_passwd_window (saver_info *si)
{
passwd_dialog_data *pw;
+ if (si->prefs.verbose_p)
+ fprintf (stderr, "cleanup_passwd_window\n");
+
if (!(pw = si->pw_data))
return;
@@ -1274,7 +1858,13 @@ cleanup_passwd_window (saver_info *si)
memset (pw->typed_passwd, 0, sizeof(pw->typed_passwd));
memset (pw->typed_passwd_char_size, 0, sizeof(pw->typed_passwd_char_size));
- memset (pw->passwd_string, 0, strlen(pw->passwd_string));
+ if (pw->passwd_string)
+ {
+ memset (pw->passwd_string, 0, strlen(pw->passwd_string));
+ free (pw->passwd_string);
+ pw->passwd_string = NULL;
+ }
+
if (pw->timer)
{
@@ -1297,8 +1887,10 @@ destroy_passwd_window (saver_info *si)
passwd_dialog_data *pw = si->pw_data;
saver_screen_info *ssi = pw->prompt_screen;
Colormap cmap = DefaultColormapOfScreen (ssi->screen);
+#ifndef HAVE_XSCREENSAVER_LOCK
Pixel black = BlackPixelOfScreen (ssi->screen);
Pixel white = WhitePixelOfScreen (ssi->screen);
+#endif
XEvent event;
cleanup_passwd_window (si);
@@ -1314,6 +1906,81 @@ destroy_passwd_window (saver_info *si)
si->cached_passwd = NULL;
}
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* reset global flag to indicate passwd dialog is no longer there */
+ g_passwd_dialog_created = False;
+
+ if (si->external_passwd)
+ {
+ /* kill the child etc. */
+ write_to_child (si, "cmd_exit", NULL);
+
+ if (pw->stdin_file)
+ fclose (pw->stdin_file);
+ if (pw->stdin_fd != -1)
+ close_and_invalidate (&pw->stdin_fd);
+ if (pw->stdout_input_id)
+ XtRemoveInput (pw->stdout_input_id);
+ if (pw->stdout_file)
+ fclose (pw->stdout_file);
+ else if (pw->stdout_fd != -1)
+ close_and_invalidate (&pw->stdout_fd);
+
+ if (si->passwd_pid)
+ {
+ kill_job (si, si->passwd_pid, SIGTERM);
+ si->passwd_pid = 0;
+ }
+
+ free (si->raise_wins);
+ si->raise_wins = NULL;
+ si->num_raise_wins = 0;
+ si->max_raise_wins = 0;
+
+ if (si->override_wins)
+ {
+ int n;
+
+ unsigned long valuemask = CWOverrideRedirect;
+ XSetWindowAttributes setwinattr;
+ setwinattr.override_redirect = False;
+
+ for (n = 0; n < si->num_override_wins; n++)
+ {
+ XChangeWindowAttributes (si->dpy, si->override_wins[n],
+ valuemask, &setwinattr);
+ }
+ free(si->override_wins);
+ si->override_wins = NULL;
+ }
+ si->num_override_wins = 0;
+ si->max_override_wins = 0;
+
+ si->pw_data->got_windowid = False;
+ si->external_passwd = False;
+
+ /* restore any metacity keys we temporarily disabled */
+ if (client)
+ {
+ if (global_switch_key)
+ {
+ gconf_client_set_string (client, switch_windows_gconf_key,
+ global_switch_key, NULL);
+ g_free(global_switch_key);
+ global_switch_key = NULL;
+ }
+
+ if (global_menu_key)
+ {
+ gconf_client_set_string (client, main_menu_gconf_key,
+ global_menu_key, NULL);
+ g_free(global_menu_key);
+ global_menu_key = NULL;
+ }
+ }
+ }
+#endif /* HAVE_XSCREENSAVER_LOCK */
+
move_mouse_grab (si, RootWindowOfScreen (ssi->screen),
ssi->cursor, ssi->number);
@@ -1348,7 +2015,14 @@ destroy_passwd_window (saver_info *si)
fprintf (stderr, "%s: %d: destroying password dialog.\n",
blurb(), pw->prompt_screen->number);
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* Ignore X error if window was already closed by the child,
+ and make sure any VisibilityNotify events are removed
+ from the event queue before we forget the window id. */
+ safe_XDestroyWindow (si->dpy, si->passwd_dialog);
+#else
XDestroyWindow (si->dpy, si->passwd_dialog);
+#endif
si->passwd_dialog = 0;
}
@@ -1359,6 +2033,7 @@ destroy_passwd_window (saver_info *si)
pw->save_under = 0;
}
+#ifndef HAVE_XSCREENSAVER_LOCK
if (pw->heading_label) free (pw->heading_label);
if (pw->body_label) free (pw->body_label);
if (pw->user_label) free (pw->user_label);
@@ -1409,6 +2084,7 @@ destroy_passwd_window (saver_info *si)
pw->logo_pixels = 0;
pw->logo_npixels = 0;
}
+#endif /* ! HAVE_XSCREENSAVER_LOCK */
if (pw->save_under)
XFreePixmap (si->dpy, pw->save_under);
@@ -1416,9 +2092,12 @@ destroy_passwd_window (saver_info *si)
if (cmap)
XInstallColormap (si->dpy, cmap);
+#ifndef HAVE_XSCREENSAVER_LOCK
+ /* si->pw_data is globally allocated and never freed when HAVE_XSS_LOCK */
memset (pw, 0, sizeof(*pw));
free (pw);
si->pw_data = 0;
+#endif
}
@@ -1435,6 +2114,49 @@ ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
#endif /* HAVE_XF86MISCSETGRABKEYSSTATE || HAVE_XF86VMODE */
+#ifdef HAVE_XSCREENSAVER_LOCK
+/* Catch errors from XRestackWindows, since there's an inherent race
+ condition in which other clients can destroy windows between when
+ we get the notification event and when we send the RestackWindows
+ response to it. */
+static Bool
+safe_XRestackWindows(Display *dpy, Window windows[], int nwindows)
+{
+ XErrorHandler old_handler;
+ XSync (dpy, False);
+ error_handler_hit_p = False;
+ old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+
+ XRestackWindows (dpy, windows, nwindows);
+
+ XSync (dpy, False);
+ XSetErrorHandler (old_handler);
+ XSync (dpy, False);
+
+ return (!error_handler_hit_p);
+}
+
+static Bool
+safe_XSendEvent(Display *dpy, Window w, Bool propagate,
+ long event_mask, XEvent *event_send)
+{
+ Status status;
+ XErrorHandler old_handler;
+ XSync (dpy, False);
+ error_handler_hit_p = False;
+ old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+
+ status = XSendEvent (dpy, w, propagate, event_mask, event_send);
+
+ XSync (dpy, False);
+ XSetErrorHandler (old_handler);
+ XSync (dpy, False);
+
+ return (!error_handler_hit_p && status);
+}
+
+#endif
+
#ifdef HAVE_XHPDISABLERESET
/* This function enables and disables the C-Sh-Reset hot-key, which
@@ -1636,6 +2358,17 @@ passwd_animate_timer (XtPointer closure, XtIntervalId *id)
if (!pw) return;
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* We want to make sure dialog is up before we update countdown timer */
+ if (!si->passwd_dialog)
+ {
+ if (si->prefs.verbose_p)
+ fprintf (stderr,
+ "-->passwd_animate_timer() returning..no dialog yet\n");
+ return;
+ }
+#endif
+
pw->ratio -= (1.0 / ((double) si->prefs.passwd_timeout / (double) tick));
if (pw->ratio < 0)
{
@@ -1655,6 +2388,7 @@ passwd_animate_timer (XtPointer closure, XtIntervalId *id)
idle_timer ((XtPointer) si, 0);
}
+#ifndef HAVE_XSCREENSAVER_LOCK
static XComposeStatus *compose_status;
@@ -1732,6 +2466,7 @@ finished_typing_passwd (saver_info *si, passwd_dialog_data *pw)
update_passwd_window (si, "", pw->ratio);
}
}
+#endif /* !HAVE_XSCREENSAVER_LOCK */
static void
handle_passwd_key (saver_info *si, XKeyEvent *event)
@@ -1740,6 +2475,7 @@ handle_passwd_key (saver_info *si, XKeyEvent *event)
unsigned char decoded [MAX_BYTES_PER_CHAR * 10]; /* leave some slack */
KeySym keysym = 0;
+#ifndef HAVE_XSCREENSAVER_LOCK
/* XLookupString may return more than one character via XRebindKeysym;
and on some systems it returns multi-byte UTF-8 characters (contrary
to its documentation, which says it returns only Latin1.)
@@ -1773,11 +2509,40 @@ handle_passwd_key (saver_info *si, XKeyEvent *event)
decoded[decoded_size] = 0;
pw->passwd_changed_p = True;
+#endif /* !HAVE_XSCREENSAVER_LOCK */
/* Add 10% to the time remaining every time a key is pressed. */
pw->ratio += 0.1;
if (pw->ratio > 1) pw->ratio = 1;
+#ifdef HAVE_XSCREENSAVER_LOCK
+ if (si->pw_data->got_windowid)
+ {
+ Bool status;
+
+ if (si->prefs.verbose_p)
+ fprintf (stderr, "event loop..gotwindowid..and keypress event...\n");
+
+ event->window = si->passwd_dialog;
+
+ status = safe_XSendEvent (si->dpy, si->passwd_dialog,
+ False, KeyPressMask, (XEvent *) event);
+
+ if (si->prefs.verbose_p)
+ {
+ if (status)
+ fprintf (stderr, "sent key...\n");
+ else
+ fprintf (stderr, "error %d sending key...\n", status);
+ }
+ update_passwd_window (si, NULL, pw->ratio);
+ }
+ else
+ {
+ swallow_unlock_typeahead_events (si, (XEvent *) event);
+ }
+
+#else /* !HAVE_XSCREENSAVER_LOCK */
if (decoded_size == 1) /* Handle single-char commands */
{
switch (*decoded)
@@ -1867,6 +2632,7 @@ handle_passwd_key (saver_info *si, XKeyEvent *event)
{
update_passwd_window (si, "", pw->ratio);
}
+#endif /* !HAVE_XSCREENSAVER_LOCK */
}
@@ -1890,7 +2656,9 @@ passwd_event_loop (saver_info *si)
passwd_animate_timer ((XtPointer) si, 0);
reset_watchdog_timer (si, False); /* Disable watchdog while dialog up */
- while (si->unlock_state == ul_read)
+ si->pw_data->got_passwd = FALSE;
+
+ while (si->unlock_state == ul_read && si->pw_data->got_passwd == FALSE)
{
XtAppNextEvent (si->app, &event.x_event);
@@ -1931,12 +2699,17 @@ passwd_event_loop (saver_info *si)
if (event.x_event.xany.window == si->passwd_dialog &&
event.x_event.xany.type == Expose)
+#ifdef HAVE_XSCREENSAVER_LOCK
+ XtDispatchEvent (&event.x_event);
+#else
draw_passwd_window (si);
+#endif /* !HAVE_XSCREENSAVER_LOCK */
else if (event.x_event.xany.type == KeyPress)
{
handle_passwd_key (si, &event.x_event.xkey);
si->pw_data->caps_p = (event.x_event.xkey.state & LockMask);
}
+#ifndef HAVE_XSCREENSAVER_LOCK
else if (event.x_event.xany.type == ButtonPress ||
event.x_event.xany.type == ButtonRelease)
{
@@ -1945,6 +2718,82 @@ passwd_event_loop (saver_info *si)
if (si->pw_data->login_button_p)
handle_login_button (si, &event.x_event);
}
+#endif /* !HAVE_XSCREENSAVER_LOCK */
+
+ /*
+ 5077974 P1 "Bug 147583: Screen Lock unlocks because of GOK dwell movement in
+ core pointer mode"
+
+ ScreenLock did not unlock the screen, but WM's XRestackWindow() did.
+ Once WM/metacity fixes the problem, the code can be removed.
+ The problem:
+ repositioning the Wids in the wrong positions when
+ 1. the window type is changed from NORMAL to DOCK or vice versa
+ 2. the Wid is managed
+ within the X window stack with or without screen-lock in a mixed Wids
+ there are two temp. get-around solutions:
+ 1. non-managed GOK or MAG Wid
+ or
+ 2. screensaver picks up the WM's restacking task and fixes the prevous
+ restacking problem.
+ the cons: there is a flashing screen when corepointer is touching
+ GOK or MAG and mouse is moved in a fast way
+ when GOK or MAG window type is DOCK only.
+ and it is not a good temp. get-around solution.
+ This is the only choice if WM did not want to fix the problem now
+ and AT group did not want to use non-managed Wids.
+ Now, GOK only supports 2nd USB/mouse/Dwell, corepointer is supposed
+ not to be used, and GOK cannot disable it
+ */
+/*
+ bugid 6769901,6839026: popup windows appearing through xscreensaver
+*/
+ else if (((event.x_event.xany.type == UnmapNotify)
+ || (event.x_event.xany.type == MapNotify)
+ || (event.x_event.xany.type == VisibilityNotify)
+ || (event.x_event.xany.type == ConfigureNotify)
+ || (event.x_event.xany.type == PropertyNotify)
+ || (event.x_event.xany.type == CreateNotify)
+ || (event.x_event.xany.type == ReparentNotify))
+ && (si->passwd_dialog))
+ {
+ /* Find the handle of popup window
+ * Note: we can not get handle of popup window with
+ * event.xany.window, thats why we have switch cases.
+ */
+ Window wPopWin = 0;
+
+ switch(event.x_event.xany.type)
+ {
+ case ConfigureNotify:
+ wPopWin = event.x_event.xconfigure.window;
+ break;
+ case CreateNotify:
+ wPopWin = event.x_event.xcreatewindow.window;
+ break;
+ case VisibilityNotify:
+ wPopWin = event.x_event.xvisibility.window;
+ break;
+ default:
+ break;
+ }
+
+ if (wPopWin)
+ {
+ saver_screen_info *ssi = find_screen_for_window (si, wPopWin);
+
+ /* This if case is for safety, it prevent screensaver stuck in
+ * loop of ConfigureNotify
+ */
+ if ((wPopWin != si->passwd_dialog) && (ssi != NULL) &&
+ (wPopWin != ssi->screensaver_window) &&
+ (wPopWin != ssi->stderr_overlay_window))
+ {
+ restack_my_windows(si, ssi, wPopWin);
+ }
+ }
+ }
+ /* the above new code for restacking under the condition */
else
XtDispatchEvent (&event.x_event);
}
@@ -1970,8 +2819,13 @@ passwd_event_loop (saver_info *si)
if (msg)
{
+#ifdef HAVE_XSCREENSAVER_LOCK
+ write_to_child (si, "ul_message", msg);
+ usleep (250000); /* 1/4 second */
+#else
si->pw_data->i_beam = 0;
update_passwd_window (si, msg, 0.0);
+#endif
XSync (si->dpy, False);
/* Swallow all pending KeyPress/KeyRelease events. */
@@ -1989,6 +2843,10 @@ passwd_event_loop (saver_info *si)
static void
handle_typeahead (saver_info *si)
{
+/* HAVE_XSCREENSAVER_LOCK: typeahead events are flushed to the external
+ dialog program in handle_passwd_input when we get the dialog_win notice
+ that it has created the window */
+#ifndef HAVE_XSCREENSAVER_LOCK
passwd_dialog_data *pw = si->pw_data;
int i;
if (!si->unlock_typeahead)
@@ -2016,6 +2874,7 @@ handle_typeahead (saver_info *si)
free (si->unlock_typeahead);
si->unlock_typeahead = 0;
+#endif
}
@@ -2121,9 +2980,11 @@ gui_auth_conv(int num_msg,
free(prompt_trimmed);
}
+#ifndef HAVE_XSCREENSAVER_LOCK
compose_status = calloc (1, sizeof (*compose_status));
if (!compose_status)
goto fail;
+#endif
si->unlock_state = ul_read;
@@ -2133,7 +2994,14 @@ gui_auth_conv(int num_msg,
if (si->unlock_state == ul_cancel)
goto fail;
+#ifdef HAVE_XSCREENSAVER_LOCK
+ if ((si->unlock_state != ul_time) && si->pw_data->passwd_string)
+ responses[i].response = strdup (si->pw_data->passwd_string);
+ else
+ goto fail;
+#else
responses[i].response = strdup(si->pw_data->typed_passwd);
+#endif
/* Cache the first response to a PROMPT_NOECHO to save prompting for
* each auth mechanism. */
@@ -2141,8 +3009,10 @@ gui_auth_conv(int num_msg,
auth_msgs[i].type == AUTH_MSGTYPE_PROMPT_NOECHO)
si->cached_passwd = strdup(responses[i].response);
+#ifndef HAVE_XSCREENSAVER_LOCK
free (compose_status);
compose_status = 0;
+#endif
}
*resp = responses;
@@ -2150,9 +3020,11 @@ gui_auth_conv(int num_msg,
return (si->unlock_state == ul_finished) ? 0 : -1;
fail:
+#ifndef HAVE_XSCREENSAVER_LOCK
if (compose_status)
free (compose_status);
compose_status = 0;
+#endif
if (responses)
{
@@ -2213,11 +3085,14 @@ auth_finished_cb (saver_info *si)
if (XPending (si->dpy))
{
XNextEvent (si->dpy, &event);
+#ifndef HAVE_XSCREENSAVER_LOCK
if (event.xany.window == si->passwd_dialog &&
event.xany.type == Expose)
draw_passwd_window (si);
- else if (event.xany.type == ButtonPress ||
- event.xany.type == KeyPress)
+ else
+#endif
+ if (event.xany.type == ButtonPress ||
+ event.xany.type == KeyPress)
break;
XSync (si->dpy, False);
}
@@ -2226,7 +3101,7 @@ auth_finished_cb (saver_info *si)
}
END:
- if (si->pw_data)
+ if (si->pw_data && si->pw_data->prompt_screen)
destroy_passwd_window (si);
}
diff --git a/driver/passwd-pam.c b/driver/passwd-pam.c
index 0c60d50..93c73f1 100644
@@ -39,10 +39,16 @@
#ifndef NO_LOCKING /* whole file */
#include <stdlib.h>
+#include <xscreensaver-intl.h>
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
+#ifdef __sun
+# include <deflt.h>
+#endif
+
extern char *blurb(void);
@@ -58,6 +64,7 @@ extern char *blurb(void);
#include <sys/stat.h>
+#include "dialog-data.h"
#include "auth.h"
extern sigset_t block_sigchld (void);
@@ -82,7 +89,10 @@ extern void unblock_sigchld (void);
#endif
static int pam_conversation (int nmsgs,
- const struct pam_message **msg,
+#ifndef __sun
+ const
+#endif
+ struct pam_message **msg,
struct pam_response **resp,
void *closure);
@@ -183,6 +193,11 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
struct pam_conv pc;
sigset_t set;
struct timespec timeout;
+ int pam_auth_status = 0; /* Specific for pam_authenticate() status*/
+ int acct_rc, setcred_rc, chauth_rc;
+ int pam_flags = 0;
+
+ uid_t euid = geteuid();
pc.conv = &pam_conversation;
pc.appdata_ptr = (void *) si;
@@ -191,6 +206,23 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
`closure' argument to pc.conv always comes in as random garbage. */
suns_pam_implementation_blows = (void *) si;
+#ifdef __sun
+ if (verbose_p)
+ fprintf (stderr, "Before uid=%d euid=%d \n\n", getuid(), geteuid());
+
+ if (seteuid (0) != 0)
+ {
+ if (verbose_p)
+ perror("Could not change euid to root, pam may not work!\n");
+ }
+
+ if (verbose_p)
+ {
+ fprintf (stderr, "After seteuid(0) uid=%d euid=%d \n\n",
+ getuid(), geteuid());
+ fprintf (stderr, "PAM is using SERVICE_NAME=\"%s\"\n\n", service);
+ }
+#endif
/* Initialize PAM.
*/
@@ -201,11 +233,35 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
status, PAM_STRERROR (pamh, status));
if (status != PAM_SUCCESS) goto DONE;
+#ifdef __sun
+ /* Check /etc/default/login to see if we should add
+ PAM_DISALLOW_NULL_AUTHTOK to pam_flags */
+ if (defopen("/etc/default/login") == 0) {
+ char *ptr;
+ int flags = defcntl(DC_GETFLAGS, 0);
+
+ TURNOFF(flags, DC_CASE);
+ (void) defcntl(DC_SETFLAGS, flags);
+ if ((ptr = defread("PASSREQ=")) != NULL &&
+ strcasecmp("YES", ptr) == 0)
+ {
+ pam_flags |= PAM_DISALLOW_NULL_AUTHTOK;
+ }
+
+ (void) defopen((char *)NULL); /* close current file */
+ }
+#endif
+
/* #### We should set PAM_TTY to the display we're using, but we
don't have that handy from here. So set it to :0.0, which is a
good guess (and has the bonus of counting as a "secure tty" as
far as PAM is concerned...)
*/
+
+/* From the pam trace and log file, it is found out that the
+ Sun pam modules can drive itself.
+*/
+#ifndef __sun
{
char *tty = strdup (":0.0");
status = pam_set_item (pamh, PAM_TTY, tty);
@@ -214,6 +270,7 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
blurb(), tty, status, PAM_STRERROR(pamh, status));
free (tty);
}
+#endif
/* Try to authenticate as the current user.
We must turn off our SIGCHLD handler for the duration of the call to
@@ -243,56 +300,102 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
timeout.tv_sec = 0;
timeout.tv_nsec = 1;
set = block_sigchld();
- status = pam_authenticate (pamh, 0);
+ pam_auth_status = pam_authenticate (pamh, pam_flags);
# ifdef HAVE_SIGTIMEDWAIT
sigtimedwait (&set, NULL, &timeout);
/* #### What is the portable thing to do if we don't have it? */
# endif /* HAVE_SIGTIMEDWAIT */
unblock_sigchld();
- if (verbose_p)
- fprintf (stderr, "%s: pam_authenticate (...) ==> %d (%s)\n",
- blurb(), status, PAM_STRERROR(pamh, status));
-
- if (status == PAM_SUCCESS) /* Win! */
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* Send status message to unlock dialog */
+ if (pam_auth_status == PAM_SUCCESS)
{
- int status2;
-
- /* On most systems, it doesn't matter whether the account modules
- are run, or whether they fail or succeed.
+ if (verbose_p)
+ write_to_child (si, "ul_ok", PAM_STRERROR (pamh, pam_auth_status));
+ }
+ else if (si->unlock_state != ul_cancel && si->unlock_state != ul_time)
+ {
+ write_to_child (si, "ul_fail", PAM_STRERROR (pamh, pam_auth_status));
+ }
+ if (verbose_p)
+ sleep (1);
+#endif
- On some systems, the account modules fail, because they were
- never configured properly, but it's necessary to run them anyway
- because certain PAM modules depend on side effects of the account
- modules having been run.
+ if (verbose_p)
+ fprintf (stderr, "after calling pam_authenticate state is: %s\n",
+ si->unlock_state == ul_success ? "ul_success" : "ul_fail");
- And on still other systems, the account modules are actually
- used, and failures in them should be considered to be true!
+ if (verbose_p)
+ fprintf (stderr, "%s: pam_authenticate (...) ==> %d (%s)\n",
+ blurb(), pam_auth_status, PAM_STRERROR(pamh, pam_auth_status));
- So:
- - We run the account modules on all systems.
- - Whether we ignore them is a configure option.
+ if (pam_auth_status == PAM_SUCCESS) /* Win! */
+ {
+ /* perform PAM account validation procedures for login user only */
+ acct_rc = pam_acct_mgmt(pamh, pam_flags);
- It's all kind of a mess.
- */
- status2 = pam_acct_mgmt (pamh, 0);
+ /******************************************************************
+ ignore other cases for the time being
+ PAM_USER_UNKNOWN, PAM_AUTH_ERR, PAM_ACCT_EXPIRED
+ (password mgn service module)
+ same as pam_setcred(), focus on auth. service module only
+ *****************************************************************/
if (verbose_p)
fprintf (stderr, "%s: pam_acct_mgmt (...) ==> %d (%s)\n",
- blurb(), status2, PAM_STRERROR(pamh, status2));
+ blurb(), acct_rc, PAM_STRERROR(pamh, acct_rc));
+
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* Send status message to unlock dialog ***/
+ if (acct_rc == PAM_SUCCESS)
+ {
+ if (verbose_p)
+ write_to_child (si, "ul_acct_ok", PAM_STRERROR(pamh, acct_rc));
+ }
+ else
+ write_to_child (si, "ul_acct_fail", PAM_STRERROR(pamh, acct_rc));
+ if (verbose_p)
+ sleep (1);
+#endif
/* HPUX for some reason likes to make PAM defines different from
* everyone else's. */
#ifdef PAM_AUTHTOKEN_REQD
- if (status2 == PAM_AUTHTOKEN_REQD)
+ if (acct_rc == PAM_AUTHTOKEN_REQD)
#else
- if (status2 == PAM_NEW_AUTHTOK_REQD)
+ if (acct_rc == PAM_NEW_AUTHTOK_REQD)
#endif
{
- status2 = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+ int i;
+ for (i = 0; i < 3; i++)
+ {
+ chauth_rc = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+ if (chauth_rc == PAM_AUTHTOK_ERR ||
+ chauth_rc == PAM_TRY_AGAIN )
+ {
+ i = 0;
+ si->unlock_state = ul_read;
+ }
+ else break; /* get out of the loop */
+ }
+
if (verbose_p)
fprintf (stderr, "%s: pam_chauthtok (...) ==> %d (%s)\n",
- blurb(), status2, PAM_STRERROR(pamh, status2));
+ blurb(), chauth_rc, PAM_STRERROR(pamh, chauth_rc));
+
+ if (chauth_rc != PAM_SUCCESS)
+ {
+ pam_auth_status = chauth_rc;
+ goto DONE;
+ }
+ }
+ else if (acct_rc != PAM_SUCCESS)
+ {
+ pam_auth_status = acct_rc;
+ write_to_child (si, "pw_acct_fail", PAM_STRERROR(pamh, acct_rc));
+ sleep (3);
+ goto DONE;
}
/* If 'configure' requested that we believe the results of PAM
@@ -306,30 +409,68 @@ pam_try_unlock(saver_info *si, Bool verbose_p,
/* Each time we successfully authenticate, refresh credentials,
for Kerberos/AFS/DCE/etc. If this fails, just ignore that
failure and blunder along; it shouldn't matter.
-
+ */
+#ifdef __linux__
+ /*
Note: this used to be PAM_REFRESH_CRED instead of
PAM_REINITIALIZE_CRED, but Jason Heiss <jheiss@ee.washington.edu>
says that the Linux PAM library ignores that one, and only refreshes
credentials when using PAM_REINITIALIZE_CRED.
*/
- status2 = pam_setcred (pamh, PAM_REINITIALIZE_CRED);
+ setcred_rc = pam_setcred (pamh, PAM_REINITIALIZE_CRED);
+#else
+ setcred_rc = pam_setcred (pamh, PAM_REFRESH_CRED);
+#endif
if (verbose_p)
fprintf (stderr, "%s: pam_setcred (...) ==> %d (%s)\n",
- blurb(), status2, PAM_STRERROR(pamh, status2));
+ blurb(), setcred_rc, PAM_STRERROR(pamh, setcred_rc));
+
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* Send status message to unlock dialog ***/
+ if (setcred_rc == PAM_SUCCESS)
+ {
+ if (verbose_p)
+ write_to_child (si, "ul_setcred_ok", PAM_STRERROR(pamh, setcred_rc));
+ }
+ else
+ write_to_child (si, "ul_setcred_fail", PAM_STRERROR(pamh, setcred_rc));
+ if (verbose_p)
+ sleep (1);
+#endif
}
DONE:
if (pamh)
{
- int status2 = pam_end (pamh, status);
- pamh = 0;
+ int status2 = pam_end (pamh, pam_auth_status);
+ pamh = NULL;
if (verbose_p)
fprintf (stderr, "%s: pam_end (...) ==> %d (%s)\n",
blurb(), status2,
(status2 == PAM_SUCCESS ? "Success" : "Failure"));
}
- if (status == PAM_SUCCESS)
+ if (seteuid (euid) != 0)
+ {
+ if (verbose_p)
+ perror("Error pam could not revert euid to user running as euid root,"
+ " locking may not work now\n");
+ }
+
+ if (verbose_p)
+ fprintf (stderr,
+ "<--end of pam_authenticate() returning ok_to_unblank = %d\n",
+ (int) ((pam_auth_status == PAM_SUCCESS) ? True : False));
+
+ if (si->pw_data->passwd_string)
+ {
+ memset(si->pw_data->passwd_string, 0,
+ strlen(si->pw_data->passwd_string));
+ free (si->pw_data->passwd_string);
+ si->pw_data->passwd_string = NULL;
+ }
+
+ if (pam_auth_status == PAM_SUCCESS)
si->unlock_state = ul_success; /* yay */
else if (si->unlock_state == ul_cancel ||
si->unlock_state == ul_time)
@@ -355,6 +496,13 @@ pam_priv_init (int argc, char **argv, Bool verbose_p)
const char file2[] = "/etc/pam.conf";
struct stat st;
+#ifdef __sun
+ if (! verbose_p) /* SUN addition: only print warnings in verbose mode */
+ { /* since they are rarely useful and mostly just */
+ return True; /* cause confusion when users see them. */
+ }
+#endif
+
# ifndef S_ISDIR
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
# endif
@@ -381,6 +529,8 @@ pam_priv_init (int argc, char **argv, Bool verbose_p)
break;
}
fclose (f);
+
+#ifndef __sun /* disable the misleading message */
if (!ok)
{
fprintf (stderr,
@@ -388,9 +538,11 @@ pam_priv_init (int argc, char **argv, Bool verbose_p)
"%s: password authentication via PAM is unlikely to work.\n",
blurb(), file2, PAM_SERVICE_NAME, blurb());
}
+#endif
}
/* else warn about file2 existing but being unreadable? */
}
+#ifndef __sun /* disable the misleading message */
else
{
fprintf (stderr,
@@ -398,15 +550,19 @@ pam_priv_init (int argc, char **argv, Bool verbose_p)
"%s: password authentication via PAM is unlikely to work.\n",
blurb(), file2, file, blurb());
}
+#endif
/* Return true anyway, just in case. */
return True;
}
-static int
+int
pam_conversation (int nmsgs,
- const struct pam_message **msg,
+#ifndef __sun
+ const
+#endif
+ struct pam_message **msg,
struct pam_response **resp,
void *vsaver_info)
{
diff --git a/driver/passwd.c b/driver/passwd.c
index ac5a3f0..0618642 100644
@@ -37,6 +37,7 @@
#include <X11/Intrinsic.h>
+#include "dialog-data.h"
#include "xscreensaver.h"
#include "auth.h"
diff --git a/driver/setuid.c b/driver/setuid.c
index 3ac78e4..a17194a 100644
@@ -145,7 +145,10 @@ set_ids_by_number (uid_t uid, gid_t gid, char **message_ret)
gid_errno = errno ? errno : -1;
errno = 0;
- if (setuid (uid) != 0)
+/*mali if (setuid (uid) != 0)**we need root privs back at pam_authenticate
+ this is causing to loose root priv for good, not good **/
+
+ if (seteuid (uid) != 0)
uid_errno = errno ? errno : -1;
if (uid_errno == 0 && gid_errno == 0 && sgs_errno == 0)
diff --git a/driver/subprocs.c b/driver/subprocs.c
index 9414df1..a244f36 100644
@@ -243,7 +243,11 @@ show_job_list (void)
static void clean_job_list (void);
+#ifdef HAVE_XSCREENSAVER_LOCK
+struct screenhack_job *
+#else
static struct screenhack_job *
+#endif
make_job (pid_t pid, int screen, const char *cmd)
{
struct screenhack_job *job = (struct screenhack_job *) malloc (sizeof(*job));
@@ -413,7 +417,11 @@ unblock_sigchld (void)
block_sigchld_handler--;
}
+#ifdef HAVE_XSCREENSAVER_LOCK
+int
+#else
static int
+#endif
kill_job (saver_info *si, pid_t pid, int signal)
{
saver_preferences *p = &si->prefs;
@@ -598,9 +606,14 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status)
mention them) if we've just killed the subprocess. But mention them
if they happen on their own.
*/
- if (!job ||
- (exit_status != 0 &&
- (p->verbose_p || job->status != job_killed)))
+
+ if ((!job
+#ifdef HAVE_XSCREENSAVER_LOCK
+ && kid != si->passwd_pid
+#endif /* HAVE_XSCREENSAVER_LOCK */
+ ) ||
+ (exit_status != 0 &&
+ (p->verbose_p || (job && job->status != job_killed))))
{
/* Don't call fprintf() from signal handlers, as it might malloc.
fprintf (stderr,
@@ -640,8 +653,12 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status)
else if (WIFSIGNALED (wait_status))
{
if (p->verbose_p ||
- !job ||
- job->status != job_killed ||
+ (!job
+#ifdef HAVE_XSCREENSAVER_LOCK
+ && kid != si->passwd_pid
+#endif /* HAVE_XSCREENSAVER_LOCK */
+ ) ||
+ (job && job->status != job_killed) ||
WTERMSIG (wait_status) != SIGTERM)
{
/* Don't call fprintf() from signal handlers, as it might malloc.
@@ -709,12 +726,20 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status)
/* Clear out the pid so that screenhack_running_p() knows it's dead.
*/
if (!job || job->status == job_dead)
+ {
for (i = 0; i < si->nscreens; i++)
{
saver_screen_info *ssi = &si->screens[i];
if (kid == ssi->pid)
ssi->pid = 0;
}
+#ifdef HAVE_XSCREENSAVER_LOCK
+ if (kid == si->passwd_pid)
+ {
+ si->passwd_pid = 0;
+ }
+#endif
+ }
}
#else /* VMS */
diff --git a/driver/timers.c b/driver/timers.c
index 81c8adb..9afc752 100644
@@ -47,6 +47,8 @@
#endif /* HAVE_RANDR */
#include "xscreensaver.h"
+#include "types.h"
+#include "dialog-data.h"
#undef ABS
#define ABS(x)((x)<0?-(x):(x))
@@ -60,6 +62,11 @@ static Bool proc_interrupts_activity_p (saver_info *si);
#endif /* HAVE_PROC_INTERRUPTS */
static void check_for_clock_skew (saver_info *si);
+#ifdef HAVE_XSCREENSAVER_LOCK
+static void watchdog_timer (XtPointer closure, XtIntervalId *id);
+extern Bool g_passwd_dialog_created;
+extern Bool ok_to_unblank;
+#endif
void
@@ -257,7 +264,11 @@ cycle_timer (XtPointer closure, XtIntervalId *id)
crash. So, restart the thing once an hour. */
how_long = 1000 * 60 * 60;
+#ifdef HAVE_XSCREENSAVER_LOCK
+ if (si->external_passwd)
+#else
if (si->dbox_up_p)
+#endif
{
if (p->verbose_p)
fprintf (stderr, "%s: dialog box up; delaying hack change.\n",
@@ -310,7 +321,28 @@ activate_lock_timer (XtPointer closure, XtIntervalId *id)
if (p->verbose_p)
fprintf (stderr, "%s: timed out; activating lock.\n", blurb());
- set_locked_p (si, True);
+
+ if (si->locked_p)
+ {
+ if (p->verbose_p)
+ fprintf (stderr,
+ "-->activate_lock_timer returning because screen already locked\n");
+ return;
+ }
+
+ /* Make sure screen is blanked before posting dialog box */
+ if (si->screen_blanked_p)
+ {
+ set_locked_p (si, True);
+ ok_to_unblank = unlock_p (si);
+ if (ok_to_unblank == True)
+ {
+ set_locked_p(si,False);
+ unblank_screen(si);
+ }
+ }
+ else /* blanking of screen failed reset lock flag */
+ set_locked_p (si, False);
}
@@ -616,14 +648,30 @@ dispatch_event (saver_info *si, XEvent *event)
}
+#ifdef HAVE_XSCREENSAVER_LOCK
+void /* called from lock.c */
+#else
static void
+#endif
swallow_unlock_typeahead_events (saver_info *si, XEvent *e)
{
XEvent event;
char buf [100];
int i = 0;
+#ifdef HAVE_XSCREENSAVER_LOCK
+ if (!si->typeahead_events)
+ {
+ /* Allocate enough space for 10 keys to be queued - if we get more
+ than that before the dialog is ready, it's most likely the user
+ left something sitting on the keyboard, and won't want them. */
+ si->typeahead_events = calloc(10, sizeof(XKeyEvent));
+ if (si->typeahead_events == NULL)
+ return;
+ }
+#else
memset (buf, 0, sizeof(buf));
+#endif
event = *e;
@@ -636,10 +684,12 @@ swallow_unlock_typeahead_events (saver_info *si, XEvent *e)
if (size != 1) continue;
switch (*s)
{
+#ifndef HAVE_XSCREENSAVER_LOCK /* Let these be queued with the rest */
case '\010': case '\177': /* Backspace */
if (i > 0) i--;
break;
case '\025': case '\030': /* Erase line */
+#endif
case '\012': case '\015': /* Enter */
case '\033': /* ESC */
i = 0;
@@ -649,7 +699,17 @@ swallow_unlock_typeahead_events (saver_info *si, XEvent *e)
break; /* ignore space at beginning of line */
/* else, fall through */
default:
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* Queue events to replay once dialog is ready */
+ if (si->num_typeahead_events < 10)
+ memcpy (&si->typeahead_events[si->num_typeahead_events++],
+ &event, sizeof(XKeyEvent));
+ else
+ XBell (si->dpy, 0);
+ i = 1; /* so that spaces are accepted after the beginning */
+#else
buf [i++] = *s;
+#endif
break;
}
}
@@ -657,6 +717,7 @@ swallow_unlock_typeahead_events (saver_info *si, XEvent *e)
} while (i < sizeof(buf)-1 &&
XCheckMaskEvent (si->dpy, KeyPressMask, &event));
+#ifndef HAVE_XSCREENSAVER_LOCK
buf[i] = 0;
if (si->unlock_typeahead)
@@ -671,6 +732,7 @@ swallow_unlock_typeahead_events (saver_info *si, XEvent *e)
si->unlock_typeahead = 0;
memset (buf, 0, sizeof(buf));
+#endif /* HAVE_XSCREENSAVER_LOCK */
}
@@ -854,6 +916,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
if (handle_clientmessage (si, &event.x_event, until_idle_p))
{
why = "ClientMessage";
+ si->emergency_lock_p = True;
goto DONE;
}
break;
@@ -868,6 +931,47 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
}
break;
+ case VisibilityNotify:
+ {
+ int k;
+
+ if (p->debug_p)
+ {
+ fprintf (stderr,
+ "************************************\n"
+ "-->sleep_until_idle() event:VisibilityNotify\n"
+ "\t Window of VisibilityNotify:%x\n"
+ "\t until_idle_p=%d g_passwd_dialog_created=%d\n",
+ until_idle_p, g_passwd_dialog_created);
+ fflush(stderr);
+ }
+
+ /* Don't raise root window when passwd dialog wants to come up */
+ if (g_passwd_dialog_created == 0 && !until_idle_p)
+ {
+ if (event.x_event.xvisibility.state != VisibilityUnobscured)
+ {
+ for (k = 0; k < si->nscreens; k++)
+ {
+ saver_screen_info *ssi = &si->screens[k];
+ XClearWindow (si->dpy, ssi->screensaver_window);
+ clear_stderr (ssi);
+ XMapRaised (si->dpy, ssi->screensaver_window);
+ }
+ if (p->debug_p)
+ {
+ fprintf (stderr,
+ "A window is trying to popup.\n"
+ "Raising saver root Window.\n"
+ "************************************\n");
+ fflush(stderr);
+ }
+ }
+ }
+ break;
+ }
+
case KeyPress:
case ButtonPress:
/* Ignore release events so that hitting ESC at the password dialog
@@ -1565,7 +1669,11 @@ watchdog_timer (XtPointer closure, XtIntervalId *id)
{
Bool running_p = screenhack_running_p (si);
+#ifdef HAVE_XSCREENSAVER_LOCK
+ if (si->external_passwd)
+#else
if (si->dbox_up_p)
+#endif
{
if (si->prefs.debug_p)
fprintf (stderr, "%s: dialog box is up: not raising screen.\n",
diff --git a/driver/types.h b/driver/types.h
index f1630b0..c77ee3f 100644
--- a/driver/types.h
+++ b/driver/types.h
@@ -275,12 +275,30 @@ struct saver_info {
int unlock_failures; /* Counts failed login attempts while the
screen is locked. */
time_t unlock_failure_time; /* Time of first failed login attempt. */
+#ifdef HAVE_XSCREENSAVER_LOCK
+ Window *raise_wins; /* List of windows to raise above the */
+ int num_raise_wins; /* virtual root/hack display, such as */
+ int max_raise_wins; /* accessibility helpers */
+
+ Window *override_wins; /* Windows we had to unset the */
+ int num_override_wins; /* override_redirect attribute on and */
+ int max_override_wins; /* need to restore it on after unlock. */
+
+
+ pid_t passwd_pid; /* The pid of the password dialog child if we
+ are running an external process for it. */
+ Bool external_passwd;
+
+ XKeyEvent *typeahead_events; /* Like unlock_typeahead, but as raw events */
+ int num_typeahead_events;
+#else
char *unlock_typeahead; /* If the screen is locked, and the user types
a character, we assume that it is the first
character of the password. It's stored here
for the password dialog to use to populate
itself. */
+#endif /* HAVE_XSCREENSAVER_LOCK */
char *user; /* The user whose session is locked. */
char *cached_passwd; /* Cached password, used to avoid multiple
diff --git a/driver/windows.c b/driver/windows.c
index 6acaddb..51e4c6a 100644
@@ -1082,8 +1082,12 @@ safe_XConfigureWindow (Display *dpy, Window window,
return (!error_handler_hit_p);
}
+#ifdef HAVE_XSCREENSAVER_LOCK
+Bool
+#else
/* This might not be necessary, but just in case. */
static Bool
+#endif
safe_XDestroyWindow (Display *dpy, Window window)
{
XErrorHandler old_handler;
@@ -1097,6 +1101,14 @@ safe_XDestroyWindow (Display *dpy, Window window)
XSetErrorHandler (old_handler);
XSync (dpy, False);
+ /* clear any queued VisibilityNotify events so we don't cause XErrors
+ later when we try to process them and find the windowid is invalid */
+ XEvent event;
+ while (XCheckWindowEvent(dpy, window, VisibilityChangeMask, &event))
+ {
+ /* discard event */ ;
+ }
+
return (!error_handler_hit_p);
}
@@ -1211,6 +1223,7 @@ initialize_screensaver_window_1 (saver_screen_info *ssi)
*/
attrs.event_mask = (KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
+ VisibilityChangeMask |
PointerMotionMask);
attrs.backing_store = NotUseful;
@@ -1482,6 +1495,9 @@ raise_window (saver_info *si,
saver_preferences *p = &si->prefs;
int i;
+ if (p->verbose_p)
+ fprintf(stderr,"-->raise_window()\n");
+
if (si->demoing_p)
inhibit_fade = True;
@@ -1696,6 +1712,9 @@ unblank_screen (saver_info *si)
Bool unfade_p = (si->fading_possible_p && p->unfade_p);
int i;
+ if (p->verbose_p)
+ fprintf(stderr,"-->unblank_screen()\n");
+
monitor_power_on (si, True);
reset_watchdog_timer (si, False);
@@ -1984,7 +2003,7 @@ select_visual (saver_screen_info *ssi, const char *visual_name)
maybe_transfer_grabs (ssi, old_w, ssi->screensaver_window, ssi->number);
/* Now we can destroy the old window without horking our grabs. */
- XDestroyWindow (si->dpy, old_w);
+ safe_XDestroyWindow (si->dpy, old_w);
if (p->verbose_p)
fprintf (stderr, "%s: %d: destroyed old saver window 0x%lx.\n",
diff --git a/driver/xscreensaver.c b/driver/xscreensaver.c
index 06f5c13..33d357a 100644
@@ -164,6 +164,8 @@
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xos.h>
+#include <gconf/gconf-client.h>
+#include <glib.h>
#include <time.h>
#include <sys/time.h>
#include <netdb.h> /* for gethostbyname() */
@@ -225,6 +227,7 @@
#endif /* HAVE_RANDR */
+#include "dialog-data.h"
#include "xscreensaver.h"
#include "version.h"
#include "yarandom.h"
@@ -236,11 +239,28 @@
saver_info *global_si_kludge = 0; /* I hate C so much... */
+/* Globals */
+Bool ok_to_unblank = False;
+
+#ifdef HAVE_XSCREENSAVER_LOCK
+/* Global storage for gtk passwd lock dialog
+ * we assign this to si->pw_data and this is needed
+ * to set user/passwd labels on gtk lock dialog by
+ * pam conv function.
+ */
+passwd_dialog_data mygtkpwd;
+passwd_dialog_data *ptr_mygtkpwd = &mygtkpwd;
+#endif
+
char *progname = 0;
char *progclass = 0;
XrmDatabase db = 0;
+#ifdef HAVE_XSCREENSAVER_LOCK
+Atom XA_UNLOCK_RATIO;
+#endif
+
static XrmOptionDescRec options [] = {
@@ -670,6 +690,9 @@ connect_to_server (saver_info *si, int *argc, char **argv)
{ &XA_ESETROOT_PMAP_ID, "ESETROOT_PMAP_ID" },
{ &XA_XROOTPMAP_ID, "_XROOTPMAP_ID" },
{ &XA_NET_WM_USER_TIME, "_NET_WM_USER_TIME" },
+#ifdef HAVE_XSCREENSAVER_LOCK
+ { &XA_UNLOCK_RATIO, "UNLOCK_RATIO" },
+#endif
{ NULL, NULL } /* Must be last to terminate list */
};
const struct atom_request *atom_lists[3] = { NULL, NULL, NULL };
@@ -1164,8 +1187,36 @@ static void
main_loop (saver_info *si)
{
saver_preferences *p = &si->prefs;
- Bool ok_to_unblank;
+ /* Bool ok_to_unblank; made this a global flag, gets set in timers.c */
int i;
+ const char *modulesptr = NULL;
+
+/*
+** CR4784055(P1)locked-screen dialog is inaccessible to Gnopernicus
+** voice for each type-in char in the password field of
+** pop-up dialog
+*/
+
+ /* BUG #6573182
+ ** g_type_init should be done before calling gconf_client routines
+ ** so that xscreensaver does not dump core if gconf daemon is not running.
+ */
+ g_type_init ();
+
+ /*
+ ** 6395649 at-spi-registryd starts when screen is locked even
+ ** when accessible device support is off(SR)
+ ** per AT core gp suggestion
+ ** GTK_MODULES is set only if at support is enabled
+ */
+
+ if (gconf_client_get_bool(gconf_client_get_default(),
+ "/desktop/gnome/interface/accessibility", NULL))
+ {
+ modulesptr = getenv ("GTK_MODULES");
+ if (!modulesptr || modulesptr [0] == '\0')
+ putenv ("GTK_MODULES=gail:atk-bridge");
+ }
while (1)
{
@@ -1196,6 +1247,17 @@ main_loop (saver_info *si)
fprintf (stderr, "%s: idle with blanking disabled at %s.\n",
blurb(), timestring());
+ /* 6221109 Changing mode from disable to anything else,
+ doesn't lock screen.
+
+ This is Disable Screen Saver mode, in this mode we dont lock
+ screen, but si->locked_p is already set to True, since someone
+ tried to lock screen, reset it to False, else when we change
+ mode from disable and try to lock screen, xscreensaver thinks
+ screen is already locked and doesnt lock screen anymore.
+ */
+ set_locked_p (si, False);
+
/* Go around the loop and wait for the next bout of idleness,
or for the init file to change, or for a remote command to
come in, or something.
@@ -1267,6 +1329,7 @@ main_loop (saver_info *si)
set_locked_p (si, False);
schedule_wakeup_event (si, retry, p->debug_p);
+ set_locked_p(si, False);
continue;
}
}
@@ -1329,7 +1392,17 @@ main_loop (saver_info *si)
p->lock_p && /* and locking is enabled */
!si->locking_disabled_p && /* and locking is possible */
lock_timeout == 0) /* and locking is not timer-deferred */
- set_locked_p (si, True); /* then lock right now. */
+ {
+ if (p->debug_p)
+ fprintf(stderr, "going to lock screen B\n");
+ set_locked_p (si, True); /* then lock right now. */
+ ok_to_unblank = unlock_p(si);
+ if (ok_to_unblank == True)
+ {
+ set_locked_p (si, False);
+ goto DONE;
+ }
+ }
/* locked_p might be true already because of the above, or because of
the LOCK ClientMessage. But if not, and if we're supposed to lock
@@ -1344,10 +1417,7 @@ main_loop (saver_info *si)
}
#endif /* !NO_LOCKING */
-
- ok_to_unblank = True;
do {
-
check_for_leaks ("blanked A");
sleep_until_idle (si, False); /* until not idle */
check_for_leaks ("blanked B");
@@ -1357,6 +1427,13 @@ main_loop (saver_info *si)
#ifndef NO_LOCKING
/* Maybe unlock the screen.
*/
+ if (si->demoing_p) goto DONE; /* in demoing mode and user wants out
+ unblank screen */
+
+ /* This is when blank timeout has happened but lock timeout hasnt
+ and user gets active. Simply get him out of the blank screen. */
+ if (si->screen_blanked_p && !si->locked_p) goto DONE;
+
if (si->locked_p)
{
saver_screen_info *ssi = si->default_screen;
@@ -1368,7 +1445,20 @@ main_loop (saver_info *si)
suspend_screenhack (&si->screens[i], True); /* suspend */
XUndefineCursor (si->dpy, ssi->screensaver_window);
+#ifdef HAVE_XSCREENSAVER_LOCK
+ /* Prevents lock dialog posting on non blanked screen */
+ if (!si->screen_blanked_p) /* locked_p is true, so blank now */
+ blank_screen (si);
+ if (si->screen_blanked_p) /* if blanking successful, call PAM */
+ {
+ set_locked_p (si, True);
+ ok_to_unblank = unlock_p(si);
+ }
+ else /* blanking failed, probably couldn't grab keyboard/mouse */
+ set_locked_p (si, False);
+#else
ok_to_unblank = unlock_p (si);
+#endif
si->dbox_up_p = False;
XDefineCursor (si->dpy, ssi->screensaver_window, ssi->cursor);
@@ -1393,6 +1483,7 @@ main_loop (saver_info *si)
} while (!ok_to_unblank);
+DONE:
if (p->verbose_p)
fprintf (stderr, "%s: unblanking screen at %s.\n",
@@ -1477,7 +1568,19 @@ main (int argc, char **argv)
textdomain (GETTEXT_PACKAGE);
#endif /* ENABLE_NLS */
+#if defined(ENABLE_NLS) && defined(HAVE_XSCREENSAVER_LOCK)
+ /* Gtk unlock dialog needs to be sent UTF-8 text to display */
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#endif
+
memset(si, 0, sizeof(*si));
+
+#ifdef HAVE_XSCREENSAVER_LOCK
+/* Initialize and point si to pw_data i.e. the lock dialog struct */
+ memset(ptr_mygtkpwd, 0, sizeof(*ptr_mygtkpwd));
+ si->pw_data = ptr_mygtkpwd;
+#endif
+
global_si_kludge = si; /* I hate C so much... */
fix_fds();
@@ -1487,7 +1590,9 @@ main (int argc, char **argv)
save_argv (argc, argv);
set_version_string (si, &argc, argv);
+#ifndef HAVE_XSCREENSAVER_LOCK /* moved below for external lock */
privileged_initialization (si, &argc, argv);
+#endif
hack_environment (si);
spasswd = getpwuid(getuid());
@@ -1510,6 +1615,10 @@ main (int argc, char **argv)
print_banner (si);
load_init_file(si->dpy, p); /* must be before initialize_per_screen_info() */
+#ifdef HAVE_XSCREENSAVER_LOCK
+ privileged_initialization (si, &argc, argv);
+#endif
+
blurb_timestamp_p = p->timestamp_p; /* kludge */
initialize_per_screen_info (si, shell); /* also sets si->fading_possible_p */
@@ -1762,8 +1871,12 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
Atom type = 0;
Window window = event->xclient.window;
+ if (p->verbose_p)
+ fprintf(stderr, "handle_clientmessage\n");
+
/* Preferences might affect our handling of client messages. */
maybe_reload_init_file (si);
+ XSync (si->dpy, False);
if (event->xclient.message_type != XA_SCREENSAVER ||
event->xclient.format != 32)
@@ -2055,10 +2168,14 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
sprintf (buf, "LOCK ClientMessage received; %s", response);
clientmessage_response (si, window, False, buf, response);
+ if (p->verbose_p)
+ fprintf(stderr, "going to lock screen A\n");
+
/* Note that this leaves things in a slightly inconsistent state:
we are blanked but not locked. And blanking might actually
fail if we can't get the grab. */
set_locked_p (si, True);
+ si->emergency_lock_p = True;
/* Have to set the time or xscreensaver-command doesn't
report the LOCK state change. */
@@ -2067,6 +2184,9 @@ handle_clientmessage (saver_info *si, XEvent *event, Bool until_idle_p)
si->selection_mode = 0;
si->demoing_p = False;
+ return True; /* dont set lock_id to 0,
+ causes to go in lock in main_loop above */
+
if (si->lock_id) /* we're doing it now, so lose the timeout */
{
XtRemoveTimeOut (si->lock_id);
diff --git a/driver/xscreensaver.h b/driver/xscreensaver.h
index 064e9c4..a52ba63 100644
@@ -164,6 +164,12 @@ extern Bool select_visual (saver_screen_info *ssi, const char *visual_name);
extern void store_saver_status (saver_info *si);
extern const char *signal_name (int signal);
+#ifdef HAVE_XSCREENSAVER_LOCK
+extern int kill_job (saver_info *si, pid_t pid, int signal);
+extern struct screenhack_job *make_job (pid_t pid, int screen,
+ const char *cmd);
+#endif
+
/* =======================================================================
subprocs diagnostics
======================================================================= */
--
2.7.4