*Background*
Patch 120094-22, may cause performance degradation of CPU and system
become unresposive when Trusted Extension or Accessibility is turned
on. Fixes of CR 6769901 are not appropriate should be corrected with CR
6839026, on all the x86 and SPARC machine .
When a machine is patched with 120094-22, Symptoms are as follows.
a) When screen is locked and Accessibility is turned on, popup window
might make x86/SPARC machine unresponsive.
b) When screen is locked and Trusted Extension is turned on, may cause
performance degradation of CPU. [tx] Xsun chews cpu and console appear
to be hung.
*Questions*
Q:why we have not fixed it at WindowManager?
Ans: We got some success in fixing this bug at metacity/WM, but with
lots of code changes. Login helper interface is required at metacity
Q: Is it fixed completly .What is remaining?
Ans: Yes this bug is fixed completely. But we should wait for final
test results, if any problem comes we will fix in CR6875930.
There are some special cases, where we need to do restacking of pop up
windows in timer.c . Also there are some existing bugs in a11y, we will
address them separately.
We are fixing this bug in incremental mode, all the remaining problem
will be fixed in CR6875930
*What we have fixied*
Xsun is consuming 100% cpu cycle with trusted path because of CR6769901
Also we found, with accessibility, cpu consumption goes to 100%
Popup window should not come through screensaver.
*Testing *
a) Pop-ups will not come through screensaver in case of dual head
display with and without xinerama . Same is the case when a11y is turned on.
b)Pop-ups will not come through screensaver with twinview display of
Xorg. Also there will be no performance degradation with my fixes
c) Pop-ups will not come through screensaver with trusted path
d) Pop-ups will not come through screensaver with all a11y cases
e) works fine with Xnewt,Xorg and Xsun
f) works fine with x86, x64, SPARC
g) The only pop-ups to get through are the ally pop-ups which are
allowed by design. GOK and MAG always on top of screensaver when we
lock the screen.
I am including svn diff of repository trunk/vermillion. For more detail
please see the attached source file.
Index: ChangeLog
===================================================================
--- ChangeLog (revision 19180)
+++ ChangeLog (working copy)
@@ -1,3 +1,8 @@
+2009-09-10 Arvind Umrao <arvind.umrao at sun.com>
+
+ * SUNWxscreensaver.spec, patches/xscreensaver-48-bug-6839026.diff:
+ * CR#6839026 Regression in screensaver may cause Performance
Degradation and make lock ed screensaver unresponsive.
+
2009-08-27 Abhijit Nath <abhijit.nath at sun.com>
* SUNWTiff.spec: add patch libtiff-05-CVE-2009-2285.diff
Index: patches/xscreensaver-48-bug-6839026.diff
===================================================================
--- patches/xscreensaver-48-bug-6839026.diff (revision 0)
+++ patches/xscreensaver-48-bug-6839026.diff (revision 0)
@@ -0,0 +1,150 @@
+--- xscreensaver-5.01/driver/lock.c_org 2009-08-27
16:40:31.474335000 +0530
++++ xscreensaver-5.01/driver/lock.c 2009-09-10 15:39:37.444268000 +0530
+@@ -109,8 +109,8 @@ extern Atom XA_UNLOCK_RATIO;
+
+
+ /* GOK bug */
+-Window at_win[4] = {0,0,0,0}; /* wIds for XRestackWindows() */
+- /* dialog, GOK, or MAG or screenSaver */
++Window at_win[5] = {0,0,0,0,0}; /* wIds for XRestackWindows() */
++ /* dialog, GOK, or MAG or screenSaver or
temporary popup wi ndow */
+
+ int no_atserv = 0; /* GOK or MAG or Both on def. screen 0 */
+
+@@ -2139,36 +2139,6 @@ passwd_event_loop (saver_info *si)
+ }
+ }
+
+- //bugid 6769901: popup windows appearing through xscreensaver
+- //code to stop popup windows while screen is locked
+- //Raise the screen saver window and then the password dialog
window
+- if (event.xany.type == VisibilityNotify || event.xany.type ==
ConfigureNotify || event.xany.type == CreateNotify)
+- {
+- int screen;
+- for (screen = 0; screen < si->nscreens; screen++)
+- {
+- if(si->passwd_dialog)for
+- {
+- saver_screen_info *ssi =
&si->screens[screen];
+- if(screen==0)
+- {
+- Window screen_win[2] = {
+- si->passwd_dialog,
+- ssi->screensaver_window
+- };
+- XRestackWindows(si->dpy,
screen_win, 2);
+-
XMapRaised(si->dpy,si->passwd_dialog);
+- XFlush(si->dpy);
+- }
+- else
+- {
+-
XMapRaised(si->dpy,ssi->screensaver_window);
+- XFlush(si->dpy);
+- }
+- }
+- }
+- }
+-
+ #else /* !HAVE_XSCREENSAVER_LOCK */
+ if (event.xany.window == si->passwd_dialog && event.xany.type ==
Expose)
+ draw_passwd_window (si);
+@@ -2219,24 +2189,87 @@ passwd_event_loop (saver_info *si)
+ Now, GOK only supports 2nd USB/mouse/Dwell, corepointer is supposed
+ not to be used, and GOK cannot disable it
+ */
+- else if (((event.type == UnmapNotify)
+- || (event.type == MapNotify )
+- || (event.type == ConfigureNotify)
+- || (event.type == PropertyNotify )
+- || (event.type == ReparentNotify ))*dfdf
*
+- && (si->passwd_dialog) && (no_atserv))
+- {
++/*
++ bugid 6769901,6839026: popup windows appearing through xscreensaver
++ Also this routine is to stop the popup window when a11y is on
also when a11y is not on.
++ Note: when a11y is on no_atserv > 0for
++*/
++
++else if (((event.type == UnmapNotify)
++ || (event.type == MapNotify )
++ || (event.type == VisibilityNotify)
++ || (event.type == ConfigureNotify)
++ || (event.type == PropertyNotify )
++ || (event.type == CreateNotify)
++ || (event.type == ReparentNotify ))
++ && (si->passwd_dialog) )
++ {
+ /* AT_LOCK_DEBUG
+ fprintf (stderr, "client window(0x%x) %s\n",
event.xclient.window,blurb());
+ fprintf (stderr, "dialog window 0x%x:\n", si->passwd_dialog);
+ fprintf(stderr, "** no_atserv: %d \n", no_atserv);
+ for (ii = 0; ii < 4; ii++)
+- fprintf(stderr, "** win : 0x%x \n", at_win[ii]);
++ fprintf(stderr, "** win : 0x%x \n", at_win[ii]);
+ */
+- at_win[no_atserv+1] = si->screens[0].screensaver_window;
+-/* 2 => screensaver and dialog Wids */
+- XRestackWindows(si->dpy, at_win, no_atserv+2);
+- XFlush(si->dpy);
++
++ /* this if case is for safety,it prevent screensaver stuck in
loop of ConfigureNot ify */
++ if(event.xany.window && (event.xany.window !=
si->screens[0].screensaver_window) & & (event.xany.window !=
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.type)
++ {
++ case ConfigureNotify:
++ wPopWin = event.xconfigure.window;
++ break;
++ case CreateNotify:
++ wPopWin = event.xcreatewindow.window;
Need to update about SUBCR of Nevada #6839026
My new fixes are very stable now. Barun and I have tested it very
thoroughly with a11y on. Today I will raise it for JDS-Review, if no
objection from Jeremy and Alan.
*Background*
Patch 120094-22, may cause performance degradation of CPU and system
become unresposive when Trusted Extension or Accessibility is turned
on. Fixes of CR 6769901 are not appropriate should be corrected with CR
6839026, on all the x86 and SPARC machine .
When a machine is patched with 120094-22, Symptoms are as follows.
a) When screen is locked and Accessibility is turned on, popup window
might make x86/SPARC machine unresponsive.
b) When screen is locked and Trusted Extension is turned on, may cause
performance degradation of CPU. [tx] Xsun chews cpu and console appear
to be hung.
*Questions*
Q:why we have not fixed it at WindowManager?
Ans: We got some success in fixing this bug at metacity/WM, but with
lots of code changes. Login helper interface is required at metacity
Q: Is it fixed completly .What is remaining?
Ans: Yes this bug is fixed completely. But we should wait for final
test results, if any problem comes we will fix in CR6875930.
There are some special cases, where we need to do restacking of pop up
windows in timer.c . Also there are some existing bugs in a11y, we will
address them separately.
We are fixing this bug in incremental mode, all the remaining problem
will be fixed in CR6875930
*What we have fixied*
Xsun is consuming 100% cpu cycle with trusted path because of CR6769901
Also we found, with accessibility, cpu consumption goes to 100%
Popup window should not come through screensaver.
*Testing *
a) Pop-ups will not come through screensaver in case of dual head
display with and without xinerama . Same is the case when a11y is turned on.
b)Pop-ups will not come through screensaver with twinview display of
Xorg. Also there will be no performance degradation with my fixes
c) Pop-ups will not come through screensaver with trusted path
d) Pop-ups will not come through screensaver with all a11y cases
e) works fine with Xnewt,Xorg and Xsun
f) works fine with x86, x64, SPARC
g) The only pop-ups to get through are the ally pop-ups which are
allowed by design. GOK and MAG always on top of screensaver when we
lock the screen.
I am including svn diff of repository trunk/vermillion. For more detail
please see the attached source file.
Index: ChangeLog
===================================================================
--- ChangeLog (revision 19180)
+++ ChangeLog (working copy)
@@ -1,3 +1,8 @@
+2009-09-10 Arvind Umrao <arvind.umrao at sun.com>
+
+ * SUNWxscreensaver.spec, patches/xscreensaver-48-bug-6839026.diff:
+ * CR#6839026 Regression in screensaver may cause Performance
Degradation and make lock ed screensaver unresponsive.
+
2009-08-27 Abhijit Nath <abhijit.nath at sun.com>
* SUNWTiff.spec: add patch libtiff-05-CVE-2009-2285.diff
Index: patches/xscreensaver-48-bug-6839026.diff
===================================================================
--- patches/xscreensaver-48-bug-6839026.diff (revision 0)
+++ patches/xscreensaver-48-bug-6839026.diff (revision 0)
@@ -0,0 +1,150 @@
+--- xscreensaver-5.01/driver/lock.c_org 2009-08-27
16:40:31.474335000 +0530
++++ xscreensaver-5.01/driver/lock.c 2009-09-10 15:39:37.444268000 +0530
+@@ -109,8 +109,8 @@ extern Atom XA_UNLOCK_RATIO;
+
+
+ /* GOK bug */
+-Window at_win[4] = {0,0,0,0}; /* wIds for XRestackWindows() */
+- /* dialog, GOK, or MAG or screenSaver */
++Window at_win[5] = {0,0,0,0,0}; /* wIds for XRestackWindows() */
++ /* dialog, GOK, or MAG or screenSaver or
temporary popup wi ndow */
+
+ int no_atserv = 0; /* GOK or MAG or Both on def. screen 0 */
+
+@@ -2139,36 +2139,6 @@ passwd_event_loop (saver_info *si)
+ }
+ }
+
+- //bugid 6769901: popup windows appearing through xscreensaver
+- //code to stop popup windows while screen is locked
+- //Raise the screen saver window and then the password dialog
window
+- if (event.xany.type == VisibilityNotify || event.xany.type ==
ConfigureNotify || event.xany.type == CreateNotify)
+- {
+- int screen;
+- for (screen = 0; screen < si->nscreens; screen++)
+- {
+- if(si->passwd_dialog)for
+- {
+- saver_screen_info *ssi =
&si->screens[screen];
+- if(screen==0)
+- {
+- Window screen_win[2] = {
+- si->passwd_dialog,
+- ssi->screensaver_window
+- };
+- XRestackWindows(si->dpy,
screen_win, 2);
+-
XMapRaised(si->dpy,si->passwd_dialog);
+- XFlush(si->dpy);
+- }
+- else
+- {
+-
XMapRaised(si->dpy,ssi->screensaver_window);
+- XFlush(si->dpy);
+- }
+- }
+- }
+- }
+-
+ #else /* !HAVE_XSCREENSAVER_LOCK */
+ if (event.xany.window == si->passwd_dialog && event.xany.type ==
Expose)
+ draw_passwd_window (si);
+@@ -2219,24 +2189,87 @@ passwd_event_loop (saver_info *si)
+ Now, GOK only supports 2nd USB/mouse/Dwell, corepointer is supposed
+ not to be used, and GOK cannot disable it
+ */
+- else if (((event.type == UnmapNotify)
+- || (event.type == MapNotify )
+- || (event.type == ConfigureNotify)
+- || (event.type == PropertyNotify )
+- || (event.type == ReparentNotify ))*dfdf
*
+- && (si->passwd_dialog) && (no_atserv))
+- {
++/*
++ bugid 6769901,6839026: popup windows appearing through xscreensaver
++ Also this routine is to stop the popup window when a11y is on
also when a11y is not on.
++ Note: when a11y is on no_atserv > 0for
++*/
++
++else if (((event.type == UnmapNotify)
++ || (event.type == MapNotify )
++ || (event.type == VisibilityNotify)
++ || (event.type == ConfigureNotify)
++ || (event.type == PropertyNotify )
++ || (event.type == CreateNotify)
++ || (event.type == ReparentNotify ))
++ && (si->passwd_dialog) )
++ {
+ /* AT_LOCK_DEBUG
+ fprintf (stderr, "client window(0x%x) %s\n",
event.xclient.window,blurb());
+ fprintf (stderr, "dialog window 0x%x:\n", si->passwd_dialog);
+ fprintf(stderr, "** no_atserv: %d \n", no_atserv);
+ for (ii = 0; ii < 4; ii++)
+- fprintf(stderr, "** win : 0x%x \n", at_win[ii]);
++ fprintf(stderr, "** win : 0x%x \n", at_win[ii]);
+ */
+- at_win[no_atserv+1] = si->screens[0].screensaver_window;
+-/* 2 => screensaver and dialog Wids */
+- XRestackWindows(si->dpy, at_win, no_atserv+2);
+- XFlush(si->dpy);
++
++ /* this if case is for safety,it prevent screensaver stuck in
loop of ConfigureNot ify */
++ if(event.xany.window && (event.xany.window !=
si->screens[0].screensaver_window) & & (event.xany.window !=
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.type)
++ {
++ case ConfigureNotify:
++ wPopWin = event.xconfigure.window;
++ break;
++ case CreateNotify:
++ wPopWin = event.xcreatewindow.window;
++ break;
++ case VisibilityNotify:
++ wPopWin = event.xvisibility.window;
++ break;
++ default:
++ break;
++ }
++
++
++ /* Array at_win stores password and screensaver window,
also MAG and/or GOK if a11y is on
++ /* if any window apart from password, MAG ,GOK or
screensaver comes over is considered as popup window. */
++ /* If it is not popup window but password, MAG, GOK, or
screensaver window t hen nWin < no_atserv+2 */
++ /* If it is popup window then nWin == no_atserv+2 */
++ int nWin =0;
++ if(wPopWin) // check if it is really a popup window
++ for(;nWin < no_atserv+2 ; ++nWin)
++ {
++ if(at_win[nWin]==wPopWin)
++ break;
++ }
++
++ /* Do restacking if it is popup window ie nWin ==
no_atserv+2 */
++ /* Also do restacking when a11y is on */
++ if( nWin== no_atserv+2 ||no_atserv )
++ {
++
++ /* at_win[0] -> passwordwindow */
++ /* at_win[1-2]-> if a11y on, may GOK or MAG */
++
++ at_win[no_atserv+1] = si->screens[0].screensaver_window;
++ if(nWin== no_atserv+2)
++ {
++ /* store popup window in array of at_win to restack
it */
++ at_win[no_atserv+2] = wPopWin;
++ XRestackWindows(si->dpy, at_win,no_atserv+3);
++ }
++ else
++ {
++ XRestackWindows(si->dpy, at_win,no_atserv+2);
++ }
++ XFlush(si->dpy);
++ }
++ }
++
+ }
+ /* the above new code for restacking under the conidtion
+ */
Index: SUNWxscreensaver.spec
===================================================================
--- SUNWxscreensaver.spec (revision 19180)
+++ SUNWxscreensaver.spec (working copy)
@@ -149,6 +149,8 @@
Patch46: xscreensaver-46-bug-6857559.diff
# date:2009-07-31 owner:bp230705 type:bug bugster:6859039
Patch47: xscreensaver-47-bug-6859039.diff
+# date:2009-09-10 owner:au230626 type:bug bugster:6839026
+Patch48: xscreensaver-48-bug-6839026.diff
# date:2008-03-07 owner:alanc type:branding
Patch101: rss-glx-101-matrixview.diff
@@ -327,6 +329,7 @@
%patch45 -p1
%patch46 -p1
%patch47 -p1
+%patch48 -p1
------------------------------------------------------------------------
/* lock.c --- handling the password dialog for locking-mode.
* xscreensaver, Copyright (c) 1993-2006 Jamie Zawinski <jwz at 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.
*/
/* Athena locking code contributed by Jon A. Christopher <jac8782 at tamu.edu>
*/
/* Copyright 1997, with the same permissions as above. */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <ctype.h>
#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 <signal.h>
#include "exec.h"
#include "xscreensaver.h"
#include "resources.h"
#include <gconf/gconf-client.h>
#ifndef NO_LOCKING /* (mostly) whole file */
#ifdef HAVE_SYSLOG
# include <syslog.h>
#endif /* HAVE_SYSLOG */
#ifdef HAVE_XHPDISABLERESET
# include <X11/XHPlib.h>
static void hp_lock_reset (saver_info *si, Bool lock_p);
#endif /* HAVE_XHPDISABLERESET */
#ifdef HAVE_XF86VMODE
# include <X11/extensions/xf86vmode.h>
static void xfree_lock_mode_switch (saver_info *si, Bool lock_p);
#endif /* HAVE_XF86VMODE */
#ifdef HAVE_XF86MISCSETGRABKEYSSTATE
# include <X11/extensions/xf86misc.h>
static void xfree_lock_grab_smasher (saver_info *si, Bool lock_p);
#endif /* HAVE_XF86MISCSETGRABKEYSSTATE */
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif /* HAVE_RANDR */
#ifdef _VROOT_H_
ERROR! You must not include vroot.h in this file.
#endif
#ifdef HAVE_UNAME
# include <sys/utsname.h> /* for hostname info */
#endif /* HAVE_UNAME */
#include <ctype.h>
#ifndef VMS
# include <pwd.h>
#else /* VMS */
extern char *getenv(const char *name);
extern int validate_user(char *name, char *password);
static Bool
vms_passwd_valid_p(char *pw, Bool verbose_p)
{
return (validate_user (getenv("USER"), typed_passwd) == 1);
}
# undef passwd_valid_p
# define passwd_valid_p vms_passwd_valid_p
#endif /* VMS */
/* 5059445(p3) screen kb and reader support */
extern int grab_mouse (saver_info *si, Window window, Cursor cursor, int
screen_no);
extern int grab_kbd (saver_info *si, Window window, int screen_no);
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);
void hack_uid (saver_info *si);
Bool g_passwd_dialog_created = 0;
#undef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
/* enum passwd_state & struct passwd_dialog_data moved to xscreensaver.h */
static void make_window (saver_info *si, enum window_type w_type);
static void draw_passwd_window (saver_info *si);
void update_passwd_window (saver_info *si, const char *printed_passwd,
float ratio);
void destroy_passwd_window (saver_info *si);
static void undo_vp_motion (saver_info *si);
static void handle_passwd_button (saver_info *si, XEvent *event);
extern Atom XA_UNLOCK_RATIO;
/* GOK bug */
Window at_win[5] = {0,0,0,0,0}; /* wIds for XRestackWindows() */
/* dialog, GOK, or MAG or screenSaver or
temporary popup window */
int no_atserv = 0; /* GOK or MAG or Both on def. screen 0 */
Bool at_enabled = False; /* Ass. Tech support? def. no */
/* for restoring the origin setting
override_redirect setting of MAG/GOK
*/
Bool winatt_reset[2] = {FALSE,FALSE};
char *globalkey_text = NULL;
char *globalmenu_key = NULL;
GConfClient *client = NULL;
/*
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 : rturn 0
*/
Atom atom_type[1], atom_window_type;
Window
check_raisedWid(saver_info *si,Window wid)
{
int screen_no,status;
Bool loop, found = FALSE;
Window root_ret, parent_ret, *children = NULL,root;
unsigned int nchildren = 0;
Screen *screen;
saver_screen_info *ssi;
Display *dpy;
Window screen_win[2] = {0,0};
for (screen_no = 0; screen_no < si->nscreens; screen_no++)
{
loop = TRUE;
ssi = &si->screens[screen_no];
screen = ssi->screen;
root = RootWindowOfScreen (screen);
if (screen_no == 0)
dpy = DisplayOfScreen(screen);
else
dpy = ssi->other_dpy;
if (dpy)
{
while (loop)
{
status =
XQueryTree (dpy, wid ,&root_ret,&parent_ret, &children, &nchildren);
/* AT_LOCK_DEBUG
fprintf(stderr, " ==>screen(%x) root(%x) wid(%x) root_ret(%x)
parent_ret(%x)\n", screen, root, wid, root_ret, parent_ret);
fprintf(stderr, " screen_no(%d) ==>dpy(%x)\n", screen_no,dpy);
*/
if (parent_ret == 0 || root != root_ret) /* not found */
loop = FALSE;
else if ( root_ret != parent_ret)
wid = parent_ret;
else
{
loop = FALSE;
found = TRUE;
/* AT_LOCK_DEBUG
fprintf(stderr,"==> found wid is 0x%x screen_no(%d)\n", wid, screen_no);
*/
if (screen_no)
{
/*
** found in other screen(not scn 0), implies MAG target scn,
** invoke XRestackWindow()
*/
screen_win[0] = wid;
screen_win[1] = ssi->screensaver_window;
XRestackWindows(dpy, screen_win, 2);
XSync (dpy, False);
wid = 0; /* no need to do the restack on screen 0 */
}
screen_no = si->nscreens;
}
} /* while loop */
} /*dpy check */
} /* for loop */
if (found)
return wid;
else
return 0;
}
static int ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error);
#ifdef HAVE_XSCREENSAVER_LOCK
int
write_to_child (saver_info* si, char* msg)
{
if (si->external_passwd && g_passwd_dialog_created &&
si->pw_data->stdin_fd != -1)
{
ssize_t len;
char *nlmsg;
nlmsg = (char *)malloc (strlen (msg) + 2);
sprintf (nlmsg, "%s\n", msg);
if (si->prefs.verbose_p)
{
fprintf (stderr,
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
fprintf (stderr, "HAVE_SCRSVR_LOCK message is:%s writing to
fd:%d\n",
msg, si->pw_data->stdin_fd);
fprintf (stderr,
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
write_msg:
len = write (si->pw_data->stdin_fd, nlmsg, strlen (nlmsg));
if (len < 0 && errno == EINTR)
goto write_msg;
free (nlmsg);
return (1);
}
return (0); /* if we didnt write anything return 0*/
}
static int
sane_dup2 (int fd1, int fd2)
{
int ret;
retry:
ret = dup2 (fd1, fd2);
if (ret < 0 && errno == EINTR)
goto retry;
return ret;
}
static int
close_and_invalidate (int *fd)
{
int ret;
ret = close (*fd);
*fd = -1;
return ret;
}
void
handle_passwd_input (XtPointer data, int *fd, XtInputId *id)
{
saver_info *si = (saver_info *)data;
saver_preferences *p = &si->prefs;
char buffer[1024];
char *s;
int status;
if (si->prefs.verbose_p)
fprintf (stderr, "passwd input handler() fd=%d\n",*fd);
s = fgets (buffer, sizeof (buffer), si->pw_data->input_file);
if (!s)
{
if (si->prefs.verbose_p)
{
fprintf (stderr, "done reading...\n");
fprintf (stderr, "removing input handler...\n");
}
XtRemoveInput (*id);
si->pw_data->stdout_input_id = 0;
if (si->pw_data->state == pw_read)
si->pw_data->state = pw_null;
if (si->prefs.verbose_p)
fprintf (stderr, "passwd input handler() returning...done reading\n");
return;
}
if (si->pw_data->got_windowid)
{
char *nl;
if (si->prefs.verbose_p)
fprintf (stderr, "got a password\n");
nl = strchr (s, '\n');
if (nl)
*nl = '\0';
si->pw_data->passwd_string = strdup (s);
if (si->prefs.verbose_p)
fprintf(stderr,"Dude got password and saving it in passwd_string:%s\n",
s);
/* We want to send null to lock dialog to say we are working on
authentication*/
si->pw_data->state = pw_null;
}
else /* Get the window id of lock dialog from Child ***/
{
Window window = strtoul (s, NULL, 0);
XSetWindowAttributes setwinattr;
unsigned long valuemask = CWOverrideRedirect;
XWindowChanges changes;
setwinattr.override_redirect = True;
XWindowAttributes window_attributes_return;
Window window1 = 0, passwd_win = 0,wintemp = 0; int j;
/*CR 5039878 2 3 "Password:" field should be focused / have flashing caret */
s = fgets (buffer, sizeof (buffer), si->pw_data->input_file);
passwd_win = strtoul (s, NULL, 0);
no_atserv = 0;
at_win[no_atserv] = window;
/* There is no need to reset the timer for Normal user
for each pop-up dialog
*/
at_enabled = False;
for (j= 0; j < 2; j++)
{
s = fgets (buffer, sizeof (buffer), si->pw_data->input_file);
window1 = strtoul (s, NULL, 0);
/* GOK, MAG, not running, Ass. Tech support is still selected
not enough interface info from loginhelper to cover all
possible conditions, ungrab kb/mouse now
*/
if (window1 == 0x1)
at_enabled = True;
else
if (window1 != 0x0 ) {
/*
5083155 Unable to unlock screen when running dual-head MAG
*adding dual or multiple heads for magnifier support
*/
at_enabled = True;
wintemp = check_raisedWid(si, window1);
if (wintemp) {
status =
XGetWindowAttributes(si->dpy,wintemp,&window_attributes_return);
if ((status) && (!window_attributes_return.override_redirect))
{
XFlush(si->dpy);
XChangeWindowAttributes(si->dpy,wintemp,valuemask,&setwinattr);
winatt_reset[j] = TRUE;
/* AT_LOCK_DEBUG
fprintf(stderr,"Debug: ==> winatt_reset[%d] override_redirect needs to be
reset\n",j);
*/
}
XMapSubwindows(si->dpy, wintemp);
no_atserv++;
at_win[no_atserv] = wintemp;
} /* wintemp != 0 */
}
}
/* common parent, i.e root win */
/* cases for running GOK , or MAG or GOK+MAG */
/* 6461887(P1) screen lock does not prevent access to other
** applications via 'alt-tab',
** see 6519433 mem leaks in libgconf-2.so's gconf_client_get_default()
*/
client = gconf_client_get_default();
if (no_atserv > 0) {
/* pop-up dialog in dock mode */
/* AT_LOCK_DEBUG
fprintf(stderr,"==> found dialog wid 0x%x\n", window);
*/
XRestackWindows(si->dpy, at_win, no_atserv+1);
XUngrabKeyboard(si->dpy, CurrentTime);
XUngrabPointer(si->dpy, CurrentTime);
si->at_external_passwd = True;
XFlush(si->dpy);
globalkey_text = gconf_client_get_string (client, \
"/apps/metacity/global_keybindings/switch_windows", NULL);
if (globalkey_text && strncmp(globalkey_text,"dis",3))
gconf_client_set_string (client, \
"/apps/metacity/global_keybindings/switch_windows", "disabled", NULL);
}
/* no MAG or GOK, only SPEECH is running
just Ass. Tech support is selected
*/
else if ((no_atserv == 0) && (at_enabled))
{
XUngrabKeyboard(si->dpy, CurrentTime);
XUngrabPointer(si->dpy, CurrentTime);
si->at_external_passwd = True;
XFlush(si->dpy);
globalkey_text = \
gconf_client_get_string(client, \
"/apps/metacity/global_keybindings/switch_windows", NULL);
if ( globalkey_text && strncmp(globalkey_text,"dis",3))
gconf_client_set_string ( client, \
"/apps/metacity/global_keybindings/switch_windows", "disabled", NULL);
/*
** 6736157 A11Y]Security problem when desktop a11y support is turned on
*/
globalmenu_key = \
gconf_client_get_string(client, \
"/apps/metacity/global_keybindings/panel_main_menu",NULL);
if ( globalmenu_key && strncmp(globalmenu_key,"dis",3))
gconf_client_set_string ( client, \
"/apps/metacity/global_keybindings/panel_main_menu","disabled",NULL);
}
/* AT_LOCK_DEBUG
fprintf(stderr,"debug no_atserv 0x%x\n", no_atserv);
fprintf(stderr,"debug passwd win 0x%x\n", passwd_win);
fprintf(stderr,"debug window 0x%x\n", window);
*/
XSelectInput(si->dpy, passwd_win,KeyPressMask);
XSetInputFocus (si->dpy, passwd_win,RevertToPointerRoot, CurrentTime);
XSync (si->dpy, False);
si->pw_data->got_windowid = True;
si->passwd_dialog = window;
/**g_passwd_dialog_created = True;**/ /*set global flag to check in
timers.c*/
if (si->prefs.verbose_p)
fprintf (stderr, "<---handle_passwd_input(): gotwindowid:0x%x\n",
passwd_win);
}
}
/* 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 };
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 %d still exists. Killing it with SIGKILL\n",
si->passwd_pid);
kill(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;
write_to_child (si, "Hello There"); /* Send a test message to Child */
/* Password from child dialog comes through this pipe/fd */
pw->input_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 */
void
make_passwd_window (saver_info *si)
{
make_window(si, w_dialog);
}
static void
make_window (saver_info *si, enum window_type w_type)
{
struct passwd *p = getpwuid (getuid ());
XSetWindowAttributes attrs;
unsigned long attrmask = 0;
passwd_dialog_data *pw = si->pw_data;
Screen *screen;
Colormap cmap;
char *f;
saver_screen_info *ssi = &si->screens [mouse_screen (si)];
if (si->prefs.verbose_p)
fprintf(stderr, "-->make_window()\n");
#ifdef HAVE_XSCREENSAVER_LOCK
if (spawn_external_passwd_process (si, si->pw_data))
{
/***************
if (si->prefs.verbose_p)
fprintf(stderr, "spawning external passwd process in
make_window()\n");
*******************/
/****************mali blank_fails remove this...
if(!blank_screen(si))
fprintf(stderr, "Failed to blank the screen\n");
*******************/
si->pw_data->ratio = 1.0;
si->pw_data->w_type = w_type;
/*si->pw_data = pw;*/
si->external_passwd = True;
return;
}
si->external_passwd = False;
si->at_external_passwd = False;
/* FIXME: don't abort() */
/*abort ();*/
#endif /* HAVE_XSCREENSAVER_LOCK */
/* Display the button only if the "newLoginCommand" pref is non-null.
*/
pw->login_button_p = (si->prefs.new_login_command &&
*si->prefs.new_login_command);
if (pw->login_button_p)
pw->passwd_cursor = XCreateFontCursor (si->dpy, XC_top_left_arrow);
else
pw->passwd_cursor = 0;
pw->prompt_screen = ssi;
if (si->prefs.verbose_p)
fprintf (stderr, "%s: %d: creating password dialog.\n",
blurb(), pw->prompt_screen->number);
screen = pw->prompt_screen->screen;
cmap = DefaultColormapOfScreen (screen);
pw->w_type = w_type;
pw->state = pw_read;
pw->ratio = 1.0;
pw->show_stars_p = get_boolean_resource(si->dpy, "passwd.asterisks",
"Boolean");
pw->heading_label = get_string_resource (si->dpy, "passwd.heading.label",
"Dialog.Label.Label");
pw->body_label = get_string_resource (si->dpy, "passwd.body.label",
"Dialog.Label.Label");
pw->user_label = get_string_resource (si->dpy, "passwd.user.label",
"Dialog.Label.Label");
pw->passwd_label = get_string_resource (si->dpy, "passwd.passwd.label",
"Dialog.Label.Label");
pw->login_label = get_string_resource (si->dpy, "passwd.login.label",
"Dialog.Button.Label");
pw->date_label = get_string_resource (si->dpy, "dateFormat", "DateFormat");
if (!pw->heading_label)
pw->heading_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
if (!pw->body_label)
pw->body_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
if (!pw->user_label) pw->user_label = strdup("ERROR");
if (!pw->passwd_label) pw->passwd_label = strdup("ERROR");
if (!pw->date_label) pw->date_label = strdup("ERROR");
if (!pw->login_label) pw->login_label = strdup ("ERROR (LOGIN)") ;
/* Put the version number in the label. */
{
char *s = (char *) malloc (strlen(pw->heading_label) + 20);
sprintf(s, pw->heading_label, si->version);
free (pw->heading_label);
pw->heading_label = s;
}
/* Get hostname info */
pw->uname_label = strdup(""); /* Initialy, write nothing */
# ifdef HAVE_UNAME
{
struct utsname uts;
if (uname (&uts) == 0)
{
#if 0 /* Get the full hostname */
{
char *s;
if ((s = strchr(uts.nodename, '.')))
*s = 0;
}
#endif
char *s = strdup (uts.nodename);
free (pw->uname_label);
pw->uname_label = s;
}
}
# endif
f = get_string_resource (si->dpy, "passwd.headingFont", "Dialog.Font");
pw->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->heading_font) pw->heading_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource (si->dpy, "passwd.buttonFont", "Dialog.Font");
pw->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->button_font) pw->button_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource(si->dpy, "passwd.bodyFont", "Dialog.Font");
pw->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->body_font) pw->body_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource(si->dpy, "passwd.labelFont", "Dialog.Font");
pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource(si->dpy, "passwd.passwdFont", "Dialog.Font");
pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource(si->dpy, "passwd.dateFont", "Dialog.Font");
pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource(si->dpy, "passwd.unameFont", "Dialog.Font");
pw->uname_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->uname_font) pw->uname_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
pw->show_uname_p = get_boolean_resource(si->dpy, "passwd.uname", "Boolean");
pw->foreground = get_pixel_resource (si->dpy, cmap,
"passwd.foreground",
"Dialog.Foreground" );
pw->background = get_pixel_resource (si->dpy, cmap,
"passwd.background",
"Dialog.Background" );
if (pw->foreground == pw->background)
{
/* Make sure the error messages show up. */
pw->foreground = BlackPixelOfScreen (screen);
pw->background = WhitePixelOfScreen (screen);
}
pw->passwd_foreground = get_pixel_resource (si->dpy, cmap,
"passwd.text.foreground",
"Dialog.Text.Foreground" );
pw->passwd_background = get_pixel_resource (si->dpy, cmap,
"passwd.text.background",
"Dialog.Text.Background" );
pw->button_foreground = get_pixel_resource (si->dpy, cmap,
"splash.Button.foreground",
"Dialog.Button.Foreground" );
pw->button_background = get_pixel_resource (si->dpy, cmap,
"splash.Button.background",
"Dialog.Button.Background" );
pw->thermo_foreground = get_pixel_resource (si->dpy, cmap,
"passwd.thermometer.foreground",
"Dialog.Thermometer.Foreground" );
pw->thermo_background = get_pixel_resource ( si->dpy, cmap,
"passwd.thermometer.background",
"Dialog.Thermometer.Background" );
pw->shadow_top = get_pixel_resource ( si->dpy, cmap,
"passwd.topShadowColor",
"Dialog.Foreground" );
pw->shadow_bottom = get_pixel_resource (si->dpy, cmap,
"passwd.bottomShadowColor",
"Dialog.Background" );
pw->logo_width = get_integer_resource (si->dpy, "passwd.logo.width",
"Dialog.Logo.Width");
pw->logo_height = get_integer_resource (si->dpy, "passwd.logo.height",
"Dialog.Logo.Height");
pw->thermo_width = get_integer_resource (si->dpy, "passwd.thermometer.width",
"Dialog.Thermometer.Width");
pw->internal_border = get_integer_resource (si->dpy,
"passwd.internalBorderWidth",
"Dialog.InternalBorderWidth");
pw->shadow_width = get_integer_resource (si->dpy, "passwd.shadowThickness",
"Dialog.ShadowThickness");
if (pw->logo_width == 0) pw->logo_width = 150;
if (pw->logo_height == 0) pw->logo_height = 150;
if (pw->internal_border == 0) pw->internal_border = 15;
if (pw->shadow_width == 0) pw->shadow_width = 4;
if (pw->thermo_width == 0) pw->thermo_width = pw->shadow_width;
{
int direction, ascent, descent;
XCharStruct overall;
pw->width = 0;
pw->height = 0;
/* Measure the heading_label. */
XTextExtents (pw->heading_font,
pw->heading_label, strlen(pw->heading_label),
&direction, &ascent, &descent, &overall);
if (overall.width > pw->width) pw->width = overall.width;
pw->height += ascent + descent;
/* Measure the uname_label. */
if ((strlen(pw->uname_label)) && pw->show_uname_p)
{
XTextExtents (pw->uname_font,
pw->uname_label, strlen(pw->uname_label),
&direction, &ascent, &descent, &overall);
if (overall.width > pw->width) pw->width = overall.width;
pw->height += ascent + descent;
}
pw->width += (pw->internal_border * 2);
pw->height += (pw->internal_border * 4);
pw->width += pw->thermo_width + (pw->shadow_width * 3);
if (pw->logo_height > pw->height)
pw->height = pw->logo_height;
else if (pw->height > pw->logo_height)
pw->logo_height = pw->height;
pw->logo_width = pw->logo_height;
pw->width += pw->logo_width;
}
attrmask |= CWOverrideRedirect; attrs.override_redirect = True;
attrmask |= CWEventMask;
attrs.event_mask = (ExposureMask | KeyPressMask |
ButtonPressMask | ButtonReleaseMask);
/* We need to remember the mouse position and restore it afterward, or
sometimes (perhaps only with Xinerama?) the mouse gets warped to
inside the bounds of the lock dialog window.
*/
{
Window pointer_root, pointer_child;
int root_x, root_y, win_x, win_y;
unsigned int mask;
pw->previous_mouse_x = 0;
pw->previous_mouse_y = 0;
if (XQueryPointer (si->dpy, RootWindowOfScreen (pw->prompt_screen->screen),
&pointer_root, &pointer_child,
&root_x, &root_y, &win_x, &win_y, &mask))
{
pw->previous_mouse_x = root_x;
pw->previous_mouse_y = root_y;
if (si->prefs.verbose_p)
fprintf (stderr, "%s: %d: mouse is at %d,%d.\n",
blurb(), pw->prompt_screen->number,
pw->previous_mouse_x, pw->previous_mouse_y);
}
else if (si->prefs.verbose_p)
fprintf (stderr, "%s: %d: unable to determine mouse position?\n",
blurb(), pw->prompt_screen->number);
}
/* Figure out where on the desktop to place the window so that it will
actually be visible; this takes into account virtual viewports as
well as Xinerama. */
{
int x, y, w, h;
get_screen_viewport (pw->prompt_screen, &x, &y, &w, &h,
pw->previous_mouse_x, pw->previous_mouse_y,
si->prefs.verbose_p);
if (si->prefs.debug_p) w /= 2;
pw->x = x + ((w + pw->width) / 2) - pw->width;
pw->y = y + ((h + pw->height) / 2) - pw->height;
if (pw->x < x) pw->x = x;
if (pw->y < y) pw->y = y;
}
pw->border_width = get_integer_resource (si->dpy, "passwd.borderWidth",
"Dialog.BorderWidth");
si->passwd_dialog =
XCreateWindow (si->dpy,
RootWindowOfScreen(screen),
pw->x, pw->y, pw->width, pw->height, pw->border_width,
DefaultDepthOfScreen (screen), InputOutput,
DefaultVisualOfScreen(screen),
attrmask, &attrs);
XSetWindowBackground (si->dpy, si->passwd_dialog, pw->background);
/* We use the default visual, not ssi->visual, so that the logo pixmap's
visual matches that of the si->passwd_dialog window. */
pw->logo_pixmap = xscreensaver_logo (ssi->screen,
/* ssi->current_visual, */
DefaultVisualOfScreen(screen),
si->passwd_dialog, cmap,
pw->background,
&pw->logo_pixels, &pw->logo_npixels,
&pw->logo_clipmask, True);
/* Before mapping the window, save the bits that are underneath the
rectangle the window will occlude. When we lower the window, we
restore these bits. This works, because the running screenhack
has already been sent SIGSTOP, so we know nothing else is drawing
right now! */
{
XGCValues gcv;
GC gc;
pw->save_under = XCreatePixmap (si->dpy,
pw->prompt_screen->screensaver_window,
pw->width + (pw->border_width*2) + 1,
pw->height + (pw->border_width*2) + 1,
pw->prompt_screen->current_depth);
gcv.function = GXcopy;
gc = XCreateGC (si->dpy, pw->save_under, GCFunction, &gcv);
XCopyArea (si->dpy, pw->prompt_screen->screensaver_window,
pw->save_under, gc,
pw->x - pw->border_width, pw->y - pw->border_width,
pw->width + (pw->border_width*2) + 1,
pw->height + (pw->border_width*2) + 1,
0, 0);
XFreeGC (si->dpy, gc);
}
XMapRaised (si->dpy, si->passwd_dialog);
XSync (si->dpy, False);
move_mouse_grab (si, si->passwd_dialog,
(pw->passwd_cursor
? pw->passwd_cursor
: pw->prompt_screen->cursor),
pw->prompt_screen->number);
undo_vp_motion (si);
/*mali si->pw_data = pw; */
if (cmap)
XInstallColormap (si->dpy, cmap);
draw_passwd_window (si);
XSync (si->dpy, False);
}
static void
draw_passwd_window (saver_info *si)
{
passwd_dialog_data *pw = si->pw_data;
XGCValues gcv;
GC gc1, gc2;
int spacing, height;
int x1, x2, x3, y1, y2;
int sw;
int tb_height;
if (si->prefs.verbose_p)
fprintf (stderr, "-->draw_passwd_window() case w_dialog!!\n");
height = (pw->heading_font->ascent + pw->heading_font->descent +
pw->body_font->ascent + pw->body_font->descent +
(2 * MAX ((pw->label_font->ascent + pw->label_font->descent),
(pw->passwd_font->ascent + pw->passwd_font->descent +
(pw->shadow_width * 4)))) +
pw->date_font->ascent + pw->date_font->descent);
if ((strlen(pw->uname_label)) && pw->show_uname_p)
height += (pw->uname_font->ascent + pw->uname_font->descent); /* for uname
*/
if (pw->login_button_p)
height += ((pw->button_font->ascent + pw->button_font->descent) * 2 +
2 * pw->shadow_width);
spacing = (((pw->height
- ((pw->login_button_p ? 4 : 2) * pw->shadow_width)
- pw->internal_border - height))
/ 8);
if (spacing < 0) spacing = 0;
gcv.foreground = pw->foreground;
gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
x1 = pw->logo_width + pw->thermo_width + (pw->shadow_width * 3);
x3 = pw->width - (pw->shadow_width * 2);
y1 = (pw->shadow_width * 2) + spacing + spacing;
/* top heading
*/
XSetFont (si->dpy, gc1, pw->heading_font->fid);
sw = string_width (pw->heading_font, pw->heading_label);
x2 = (x1 + ((x3 - x1 - sw) / 2));
y1 += spacing + pw->heading_font->ascent + pw->heading_font->descent;
XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
pw->heading_label, strlen(pw->heading_label));
/* uname below top heading
*/
if ((strlen(pw->uname_label)) && pw->show_uname_p)
{
XSetFont (si->dpy, gc1, pw->uname_font->fid);
y1 += spacing + pw->uname_font->ascent + pw->uname_font->descent;
sw = string_width (pw->uname_font, pw->uname_label);
x2 = (x1 + ((x3 - x1 - sw) / 2));
XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
pw->uname_label, strlen(pw->uname_label));
}
/* text below uname
*/
XSetFont (si->dpy, gc1, pw->body_font->fid);
y1 += spacing + pw->body_font->ascent + pw->body_font->descent;
sw = string_width (pw->body_font, pw->body_label);
x2 = (x1 + ((x3 - x1 - sw) / 2));
XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
pw->body_label, strlen(pw->body_label));
tb_height = (pw->passwd_font->ascent + pw->passwd_font->descent +
(pw->shadow_width * 4));
/* the "User:" prompt
*/
y1 += spacing;
y2 = y1;
XSetForeground (si->dpy, gc1, pw->foreground);
XSetFont (si->dpy, gc1, pw->label_font->fid);
y1 += (spacing + tb_height);
x2 = (x1 + pw->internal_border +
MAX(string_width (pw->label_font, pw->user_label),
string_width (pw->label_font, pw->passwd_label)));
XDrawString (si->dpy, si->passwd_dialog, gc1,
x2 - string_width (pw->label_font, pw->user_label),
y1 - pw->passwd_font->descent,
pw->user_label, strlen(pw->user_label));
/* the "Password:" prompt
*/
y1 += (spacing + tb_height);
XDrawString (si->dpy, si->passwd_dialog, gc1,
x2 - string_width (pw->label_font, pw->passwd_label),
y1 - pw->passwd_font->descent,
pw->passwd_label, strlen(pw->passwd_label));
XSetForeground (si->dpy, gc2, pw->passwd_background);
/* the "user name" text field
*/
y1 = y2;
XSetForeground (si->dpy, gc1, pw->passwd_foreground);
XSetFont (si->dpy, gc1, pw->passwd_font->fid);
y1 += (spacing + tb_height);
x2 += (pw->shadow_width * 4);
pw->passwd_field_width = x3 - x2 - pw->internal_border;
pw->passwd_field_height = (pw->passwd_font->ascent +
pw->passwd_font->descent +
pw->shadow_width);
XFillRectangle (si->dpy, si->passwd_dialog, gc2,
x2 - pw->shadow_width,
y1 - (pw->passwd_font->ascent + pw->passwd_font->descent),
pw->passwd_field_width, pw->passwd_field_height);
XDrawString (si->dpy, si->passwd_dialog, gc1,
x2,
y1 - pw->passwd_font->descent,
pw->user_string, strlen(pw->user_string));
/* the "password" text field
*/
y1 += (spacing + tb_height);
pw->passwd_field_x = x2 - pw->shadow_width;
pw->passwd_field_y = y1 - (pw->passwd_font->ascent +
pw->passwd_font->descent);
/* The shadow around the text fields
*/
y1 = y2;
y1 += (spacing + (pw->shadow_width * 3));
x1 = x2 - (pw->shadow_width * 2);
x2 = pw->passwd_field_width + (pw->shadow_width * 2);
y2 = pw->passwd_field_height + (pw->shadow_width * 2);
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
x1, y1, x2, y2,
pw->shadow_width,
pw->shadow_bottom, pw->shadow_top);
y1 += (spacing + pw->passwd_font->ascent + pw->passwd_font->descent +
(pw->shadow_width * 4));
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
x1, y1, x2, y2,
pw->shadow_width,
pw->shadow_bottom, pw->shadow_top);
/* The date, below the text fields
*/
{
char buf[100];
time_t now = time ((time_t *) 0);
struct tm *tm = localtime (&now);
memset (buf, 0, sizeof(buf));
strftime (buf, sizeof(buf)-1, pw->date_label, tm);
XSetFont (si->dpy, gc1, pw->date_font->fid);
y1 += pw->shadow_width;
y1 += (spacing + tb_height);
y1 += spacing/2;
sw = string_width (pw->date_font, buf);
x2 = x1 + x2 - sw;
XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1, buf, strlen(buf));
}
/* The "New Login" button
*/
if (pw->login_button_p)
{
XSetForeground (si->dpy, gc1, pw->button_foreground);
XSetForeground (si->dpy, gc2, pw->button_background);
XSetFont (si->dpy, gc1, pw->button_font->fid);
sw = string_width (pw->button_font, pw->login_label);
x2 = pw->width - pw->internal_border - (pw->shadow_width * 2);
/* right aligned button */
/* x1 = x2 - pw->login_button_width; */
/* centered button */
x1 = (pw->logo_width + pw->thermo_width + (pw->shadow_width * 3) +
pw->internal_border);
x1 = x1 + (x2 - x1 - pw->login_button_width) / 2;
y1 = (pw->height - pw->internal_border - pw->login_button_height +
spacing);
y2 = (y1 +
((pw->login_button_height -
(pw->button_font->ascent + pw->button_font->descent))
/ 2) +
pw->button_font->ascent);
pw->login_button_x = x1;
pw->login_button_y = y1;
}
/* The logo
*/
x1 = pw->shadow_width * 6;
y1 = pw->shadow_width * 6;
x2 = pw->logo_width - (pw->shadow_width * 12);
y2 = pw->logo_height - (pw->shadow_width * 12);
if (pw->logo_pixmap)
{
Window root;
int x, y;
unsigned int w, h, bw, d;
XGetGeometry (si->dpy, pw->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d);
XSetForeground (si->dpy, gc1, pw->foreground);
XSetBackground (si->dpy, gc1, pw->background);
XSetClipMask (si->dpy, gc1, pw->logo_clipmask);
XSetClipOrigin (si->dpy, gc1, x1 + ((x2 - (int)w) / 2), y1 + ((y2 -
(int)h) / 2));
if (d == 1)
XCopyPlane (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
0, 0, w, h,
x1 + ((x2 - (int)w) / 2),
y1 + ((y2 - (int)h) / 2),
1);
else
XCopyArea (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
0, 0, w, h,
x1 + ((x2 - (int)w) / 2),
y1 + ((y2 - (int)h) / 2));
}
/* The thermometer
*/
XSetForeground (si->dpy, gc1, pw->thermo_foreground);
XSetForeground (si->dpy, gc2, pw->thermo_background);
pw->thermo_field_x = pw->logo_width + pw->shadow_width;
pw->thermo_field_y = pw->shadow_width * 5;
pw->thermo_field_height = pw->height - (pw->shadow_width * 10);
#if 0
/* Solid border inside the logo box. */
XSetForeground (si->dpy, gc1, pw->foreground);
XDrawRectangle (si->dpy, si->passwd_dialog, gc1, x1, y1, x2-1, y2-1);
#endif
/* The shadow around the logo
*/
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
pw->shadow_width * 4,
pw->shadow_width * 4,
pw->logo_width - (pw->shadow_width * 8),
pw->logo_height - (pw->shadow_width * 8),
pw->shadow_width,
pw->shadow_bottom, pw->shadow_top);
/* The shadow around the thermometer
*/
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
pw->logo_width,
pw->shadow_width * 4,
pw->thermo_width + (pw->shadow_width * 2),
pw->height - (pw->shadow_width * 8),
pw->shadow_width,
pw->shadow_bottom, pw->shadow_top);
#if 1
/* Solid border inside the thermometer. */
XSetForeground (si->dpy, gc1, pw->foreground);
XDrawRectangle (si->dpy, si->passwd_dialog, gc1,
pw->thermo_field_x, pw->thermo_field_y,
pw->thermo_width - 1, pw->thermo_field_height - 1);
#endif
/* The shadow around the whole window
*/
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
0, 0, pw->width, pw->height, pw->shadow_width,
pw->shadow_top, pw->shadow_bottom);
XFreeGC (si->dpy, gc1);
XFreeGC (si->dpy, gc2);
update_passwd_window (si, pw->passwd_string, pw->ratio);
}
void
update_passwd_window (saver_info *si, const char *printed_passwd, float ratio)
{
passwd_dialog_data *pw = si->pw_data;
XGCValues gcv;
GC gc1, gc2;
int x, y;
XRectangle rects[1];
pw->ratio = ratio;
if (si->prefs.verbose_p)
fprintf (stderr, "-->update_passwd_window() w_dialog !!\n");
if (!si->pw_data->got_windowid )
{
if (si->prefs.verbose_p)
fprintf (stderr, "-->update_passwd_window() lockdialog not created
returning.. !!\n");
return;
}
gcv.foreground = pw->passwd_foreground;
if (pw->passwd_font)
gcv.font = pw->passwd_font->fid;
gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground|GCFont, &gcv);
gcv.foreground = pw->passwd_background;
gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
if (printed_passwd)
{
char *s = strdup (printed_passwd);
if (pw->passwd_string) free (pw->passwd_string);
pw->passwd_string = s;
}
/* the "password" text field
*/
rects[0].x = pw->passwd_field_x;
rects[0].y = pw->passwd_field_y;
rects[0].width = pw->passwd_field_width;
rects[0].height = pw->passwd_field_height;
XFillRectangle (si->dpy, si->passwd_dialog, gc2,
rects[0].x, rects[0].y, rects[0].width, rects[0].height);
XSetClipRectangles (si->dpy, gc1, 0, 0, rects, 1, Unsorted);
XDrawString (si->dpy, si->passwd_dialog, gc1,
rects[0].x + pw->shadow_width,
rects[0].y + pw->passwd_font->ascent,
pw->passwd_string, strlen(pw->passwd_string));
XSetClipMask (si->dpy, gc1, None);
/* The I-beam
*/
if (pw->i_beam != 0)
{
x = (rects[0].x + pw->shadow_width +
string_width (pw->passwd_font, pw->passwd_string));
y = rects[0].y + pw->shadow_width;
if (x > rects[0].x + rects[0].width - 1)
x = rects[0].x + rects[0].width - 1;
XDrawLine (si->dpy, si->passwd_dialog, gc1,
x, y,
x, y + pw->passwd_font->ascent + pw->passwd_font->descent-1);
}
pw->i_beam = (pw->i_beam + 1) % 4;
/* the thermometer
*/
y = (pw->thermo_field_height - 2) * (1.0 - pw->ratio);
if (y > 0)
{
XFillRectangle (si->dpy, si->passwd_dialog, gc2,
pw->thermo_field_x + 1,
pw->thermo_field_y + 1,
pw->thermo_width-2,
y);
XSetForeground (si->dpy, gc1, pw->thermo_foreground);
XFillRectangle (si->dpy, si->passwd_dialog, gc1,
pw->thermo_field_x + 1,
pw->thermo_field_y + 1 + y,
pw->thermo_width-2,
MAX (0, pw->thermo_field_height - y - 2));
}
/* The "New Login" button
*/
if (pw->login_button_p)
{
int x2, y2, sw;
XSetFont (si->dpy, gc1, pw->button_font->fid);
XSetForeground (si->dpy, gc1,
(pw->login_button_enabled_p
? pw->passwd_foreground
: pw->shadow_bottom));
XSetForeground (si->dpy, gc2, pw->button_background);
XFillRectangle (si->dpy, si->passwd_dialog, gc2,
pw->login_button_x, pw->login_button_y,
pw->login_button_width, pw->login_button_height);
sw = string_width (pw->button_font, pw->login_label);
x2 = pw->login_button_x + ((pw->login_button_width - sw) / 2);
y2 = (pw->login_button_y +
((pw->login_button_height -
(pw->button_font->ascent + pw->button_font->descent))
/ 2) +
pw->button_font->ascent);
XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y2,
pw->login_label, strlen(pw->login_label));
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
pw->login_button_x, pw->login_button_y,
pw->login_button_width, pw->login_button_height,
pw->shadow_width,
(pw->login_button_down_p
? pw->shadow_bottom
: pw->shadow_top),
(pw->login_button_down_p
? pw->shadow_top
: pw->shadow_bottom));
}
XFreeGC (si->dpy, gc1);
XFreeGC (si->dpy, gc2);
XSync (si->dpy, False);
}
void
destroy_passwd_window (saver_info *si)
{
saver_preferences *p = &si->prefs;
passwd_dialog_data *pw = si->pw_data;
saver_screen_info *ssi;
Colormap cmap;
Pixel black, white;
XEvent event;
/* CR5083155 [Cinn Solaris]Unable to unlock screen when running dual-head MAG
*/
int j;
XSetWindowAttributes setwinattr;
unsigned long valuemask = CWOverrideRedirect;
XWindowChanges changes;
setwinattr.override_redirect = FALSE;
if (si->prefs.verbose_p)
fprintf (stderr, "destroy_passwd_window\n");
/*reset global flag to indicate passwd dialog is no longer there*/
g_passwd_dialog_created = 0;
if (pw == NULL || si->external_passwd == 0)
return;
if (pw->timer)
XtRemoveTimeOut (pw->timer);
#ifdef HAVE_XSCREENSAVER_LOCK
if (si->external_passwd)
{
/* kill the child etc. */
if (si->passwd_dialog)
{
XErrorHandler old_handler;
XSync (si->dpy, False);
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
XDestroyWindow (si->dpy, si->passwd_dialog);
XSync (si->dpy, False);
XSetErrorHandler (old_handler);
si->passwd_dialog = 0;
}
if (pw->stdout_input_id)
XtRemoveInput (pw->stdout_input_id);
if (pw->stdin_fd != -1)
close_and_invalidate (&pw->stdin_fd);
if (pw->input_file)
fclose (pw->input_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;
}
si->external_passwd = False;
si->at_external_passwd = False;
}
else
#endif /* HAVE_XSCREENSAVER_LOCK */
{
if (p->verbose_p)
fprintf (stderr, "In destroy_passwd else case..i.e. si->external-passwd is
False already\n");
memset (pw->typed_passwd, 0, sizeof(pw->typed_passwd));
memset (pw->passwd_string, 0, strlen(pw->passwd_string));
ssi = pw->prompt_screen;
cmap = DefaultColormapOfScreen (ssi->screen);
black = BlackPixelOfScreen (ssi->screen);
white = WhitePixelOfScreen (ssi->screen);
move_mouse_grab (si, RootWindowOfScreen (ssi->screen),
ssi->cursor, ssi->number);
if (pw->passwd_cursor)
XFreeCursor (si->dpy, pw->passwd_cursor);
if (p->verbose_p)
fprintf (stderr, "%s: %d: moving mouse back to %d,%d.\n",
blurb(), ssi->number,
pw->previous_mouse_x, pw->previous_mouse_y);
XWarpPointer (si->dpy, None, RootWindowOfScreen (ssi->screen),
0, 0, 0, 0,
pw->previous_mouse_x, pw->previous_mouse_y);
XSync (si->dpy, False);
while (XCheckMaskEvent (si->dpy, PointerMotionMask, &event))
if (p->verbose_p)
fprintf (stderr, "%s: discarding MotionNotify event.\n", blurb());
if (si->passwd_dialog)
{
XDestroyWindow (si->dpy, si->passwd_dialog);
si->passwd_dialog = 0;
}
if (pw->save_under)
{
XGCValues gcv;
GC gc;
gcv.function = GXcopy;
gc = XCreateGC (si->dpy, ssi->screensaver_window, GCFunction, &gcv);
XCopyArea (si->dpy, pw->save_under,
ssi->screensaver_window, gc,
0, 0,
pw->width + (pw->border_width*2) + 1,
pw->height + (pw->border_width*2) + 1,
pw->x - pw->border_width, pw->y - pw->border_width);
XFreePixmap (si->dpy, pw->save_under);
pw->save_under = 0;
XFreeGC (si->dpy, gc);
}
if (pw->heading_label) free (pw->heading_label);
if (pw->body_label) free (pw->body_label);
if (pw->user_label) free (pw->user_label);
if (pw->passwd_label) free (pw->passwd_label);
if (pw->date_label) free (pw->date_label);
if (pw->login_label) free (pw->login_label);
if (pw->user_string) free (pw->user_string);
if (pw->passwd_string) free (pw->passwd_string);
if (pw->uname_label) free (pw->uname_label);
if (pw->heading_font) XFreeFont (si->dpy, pw->heading_font);
if (pw->body_font) XFreeFont (si->dpy, pw->body_font);
if (pw->label_font) XFreeFont (si->dpy, pw->label_font);
if (pw->passwd_font) XFreeFont (si->dpy, pw->passwd_font);
if (pw->date_font) XFreeFont (si->dpy, pw->date_font);
if (pw->button_font) XFreeFont (si->dpy, pw->button_font);
if (pw->uname_font) XFreeFont (si->dpy, pw->uname_font);
if (pw->foreground != black && pw->foreground != white)
XFreeColors (si->dpy, cmap, &pw->foreground, 1, 0L);
if (pw->background != black && pw->background != white)
XFreeColors (si->dpy, cmap, &pw->background, 1, 0L);
if (!(pw->button_foreground == black || pw->button_foreground == white))
XFreeColors (si->dpy, cmap, &pw->button_foreground, 1, 0L);
if (!(pw->button_background == black || pw->button_background == white))
XFreeColors (si->dpy, cmap, &pw->button_background, 1, 0L);
if (pw->passwd_foreground != black && pw->passwd_foreground != white)
XFreeColors (si->dpy, cmap, &pw->passwd_foreground, 1, 0L);
if (pw->passwd_background != black && pw->passwd_background != white)
XFreeColors (si->dpy, cmap, &pw->passwd_background, 1, 0L);
if (pw->thermo_foreground != black && pw->thermo_foreground != white)
XFreeColors (si->dpy, cmap, &pw->thermo_foreground, 1, 0L);
if (pw->thermo_background != black && pw->thermo_background != white)
XFreeColors (si->dpy, cmap, &pw->thermo_background, 1, 0L);
if (pw->shadow_top != black && pw->shadow_top != white)
XFreeColors (si->dpy, cmap, &pw->shadow_top, 1, 0L);
if (pw->shadow_bottom != black && pw->shadow_bottom != white)
XFreeColors (si->dpy, cmap, &pw->shadow_bottom, 1, 0L);
if (pw->logo_pixmap)
XFreePixmap (si->dpy, pw->logo_pixmap);
if (pw-> logo_clipmask)
XFreePixmap (si->dpy, pw->logo_clipmask);
if (pw->logo_pixels)
{
if (pw->logo_npixels)
XFreeColors (si->dpy, cmap, pw->logo_pixels, pw->logo_npixels, 0L);
free (pw->logo_pixels);
pw->logo_pixels = 0;
pw->logo_npixels = 0;
}
if (pw->save_under)
XFreePixmap (si->dpy, pw->save_under);
if (cmap)
XInstallColormap (si->dpy, cmap);
}
memset (pw, 0, sizeof(*pw));
/*** NO mali99 we only create a copy of pw in main and keep it
so dont free it.
free (pw);
si->pw_data = 0;
************/
for (j= 1; j < 3 ; j++)
{
if (winatt_reset[j-1] && at_win[j] )
{
XChangeWindowAttributes(si->dpy,at_win[j],valuemask,&setwinattr);
winatt_reset[j-1] = FALSE;
at_win[j] = 0;
/*fprintf(stderr, "DEBUG: at(%d) override_redirect set to FALSE\n", j);
*/
}
}
/*
** restore the prev one
** 6520014(P3) mem. leak in lock.c
*/
if ( client && globalkey_text)
gconf_client_set_string ( client, \
"/apps/metacity/global_keybindings/switch_windows", \
globalkey_text, NULL);
g_free(globalkey_text);
globalkey_text = NULL;
/*
** 6736157 A11Y]Security problem when desktop a11y support is turned on
*/
if ( client && globalmenu_key)
gconf_client_set_string ( client, \
"/apps/metacity/global_keybindings/panel_main_menu", \
globalmenu_key, NULL);
g_free(globalmenu_key);
globalmenu_key = NULL;
}
static Bool error_handler_hit_p = False;
static int
ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
{
error_handler_hit_p = True;
return 0;
}
#ifdef HAVE_XHPDISABLERESET
/* This function enables and disables the C-Sh-Reset hot-key, which
normally resets the X server (logging out the logged-in user.)
We don't want random people to be able to do that while the
screen is locked.
*/
static void
hp_lock_reset (saver_info *si, Bool lock_p)
{
static Bool hp_locked_p = False;
/* Calls to XHPDisableReset and XHPEnableReset must be balanced,
or BadAccess errors occur. (It's ok for this to be global,
since it affects the whole machine, not just the current screen.)
*/
if (hp_locked_p == lock_p)
return;
if (lock_p)
XHPDisableReset (si->dpy);
else
XHPEnableReset (si->dpy);
hp_locked_p = lock_p;
}
#endif /* HAVE_XHPDISABLERESET */
#ifdef HAVE_XF86MISCSETGRABKEYSSTATE
/* This function enables and disables the Ctrl-Alt-KP_star and
Ctrl-Alt-KP_slash hot-keys, which (in XFree86 4.2) break any
grabs and/or kill the grabbing client. That would effectively
unlock the screen, so we don't like that.
The Ctrl-Alt-KP_star and Ctrl-Alt-KP_slash hot-keys only exist
if AllowDeactivateGrabs and/or AllowClosedownGrabs are turned on
in XF86Config. I believe they are disabled by default.
This does not affect any other keys (specifically Ctrl-Alt-BS or
Ctrl-Alt-F1) but I wish it did. Maybe it will someday.
*/
static void
xfree_lock_grab_smasher (saver_info *si, Bool lock_p)
{
saver_preferences *p = &si->prefs;
int status;
int event, error;
if (!XF86MiscQueryExtension(si->dpy, &event, &error))
return;
XErrorHandler old_handler;
XSync (si->dpy, False);
error_handler_hit_p = False;
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
XSync (si->dpy, False);
status = XF86MiscSetGrabKeysState (si->dpy, !lock_p);
XSync (si->dpy, False);
if (error_handler_hit_p) status = 666;
if (!lock_p && status == MiscExtGrabStateAlready)
status = MiscExtGrabStateSuccess; /* shut up, consider this success */
if (p->verbose_p && status != MiscExtGrabStateSuccess)
fprintf (stderr, "%s: error: XF86MiscSetGrabKeysState(%d) returned %s\n",
blurb(), !lock_p,
(status == MiscExtGrabStateSuccess ? "MiscExtGrabStateSuccess" :
status == MiscExtGrabStateLocked ? "MiscExtGrabStateLocked" :
status == MiscExtGrabStateAlready ? "MiscExtGrabStateAlready" :
status == 666 ? "an X error" :
"unknown value"));
XSync (si->dpy, False);
XSetErrorHandler (old_handler);
XSync (si->dpy, False);
}
#endif /* HAVE_XF86MISCSETGRABKEYSSTATE */
/* This function enables and disables the C-Alt-Plus and C-Alt-Minus
hot-keys, which normally change the resolution of the X server.
We don't want people to be able to switch the server resolution
while the screen is locked, because if they switch to a higher
resolution, it could cause part of the underlying desktop to become
exposed.
*/
#ifdef HAVE_XF86VMODE
static void
xfree_lock_mode_switch (saver_info *si, Bool lock_p)
{
static Bool any_mode_locked_p = False;
saver_preferences *p = &si->prefs;
int screen;
int event, error;
Bool status;
XErrorHandler old_handler;
if (any_mode_locked_p == lock_p)
return;
if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
return;
for (screen = 0; screen < (si->xinerama_p ? 1 : si->nscreens); screen++)
{
XSync (si->dpy, False);
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
error_handler_hit_p = False;
status = XF86VidModeLockModeSwitch (si->dpy, screen, lock_p);
XSync (si->dpy, False);
XSetErrorHandler (old_handler);
if (error_handler_hit_p) status = False;
if (status)
any_mode_locked_p = lock_p;
if (!status && (p->verbose_p || !lock_p))
/* Only print this when verbose, or when we locked but can't unlock.
I tried printing this message whenever it comes up, but
mode-locking always fails if DontZoom is set in XF86Config. */
fprintf (stderr, "%s: %d: unable to %s mode switching!\n",
blurb(), screen, (lock_p ? "lock" : "unlock"));
else if (p->verbose_p)
fprintf (stderr, "%s: %d: %s mode switching.\n",
blurb(), screen, (lock_p ? "locked" : "unlocked"));
}
}
#endif /* HAVE_XF86VMODE */
/* If the viewport has been scrolled since the screen was blanked,
then scroll it back to where it belongs. This function only exists
to patch over a very brief race condition.
*/
static void
undo_vp_motion (saver_info *si)
{
#ifdef HAVE_XF86VMODE
saver_preferences *p = &si->prefs;
int screen;
int event, error;
if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
return;
for (screen = 0; screen < si->nscreens; screen++)
{
saver_screen_info *ssi = &si->screens[screen];
int x, y;
Bool status;
if (ssi->blank_vp_x == -1 && ssi->blank_vp_y == -1)
break;
if (!XF86VidModeGetViewPort (si->dpy, screen, &x, &y))
return;
if (ssi->blank_vp_x == x && ssi->blank_vp_y == y)
return;
/* We're going to move the viewport. The mouse has just been grabbed on
(and constrained to, thus warped to) the password window, so it is no
longer near the edge of the screen. However, wait a bit anyway, just
to make sure the server drains its last motion event, so that the
screen doesn't continue to scroll after we've reset the viewport.
*/
XSync (si->dpy, False);
usleep (250000); /* 1/4 second */
XSync (si->dpy, False);
status = XF86VidModeSetViewPort (si->dpy, screen,
ssi->blank_vp_x, ssi->blank_vp_y);
if (!status)
fprintf (stderr,
"%s: %d: unable to move vp from (%d,%d) back to (%d,%d)!\n",
blurb(), screen, x, y, ssi->blank_vp_x, ssi->blank_vp_y);
else if (p->verbose_p)
fprintf (stderr,
"%s: %d: vp moved to (%d,%d); moved it back to (%d,%d).\n",
blurb(), screen, x, y, ssi->blank_vp_x, ssi->blank_vp_y);
}
#endif /* HAVE_XF86VMODE */
}
/* Interactions
*/
static void
passwd_animate_timer (XtPointer closure, XtIntervalId *id)
{
saver_info *si = (saver_info *) closure;
int tick = 166;
passwd_dialog_data *pw = si->pw_data;
/* if (si->prefs.verbose_p)
fprintf (stderr,"-->passwd_animate_timer()\n");
**/
/*We want to make sure dialog isup before we try to animate**/
if (!si->external_passwd || !g_passwd_dialog_created)
{
if (si->prefs.verbose_p)
fprintf (stderr,"-->passwd_animate_timer() returning..no dialog yet\n");
return;
}
pw->ratio -= (1.0 / ((double) si->prefs.passwd_timeout / (double) tick));
if (pw->ratio < 0)
{
pw->ratio = 0;
if (pw->state == pw_read || pw->state == pw_null)
{
pw->state = pw_time;
}
}
/*** Communicating with the Child lock dialog...sending ratio back... mali99***/
#ifdef HAVE_XSCREENSAVER_LOCK
if (si->passwd_dialog)
{
XEvent event;
Bool status;
XErrorHandler old_handler;
/* fprintf (stderr,"-->passwd_animate_timer() sending ratio to child\n");
**/
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;
/* CR 6176524 passwdTimeoutEnable for disabled user */
if (!si->prefs.pwd_p)
event.xclient.data.l[1] = 1;
XSync (si->dpy, False);
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
status = XSendEvent (si->dpy, si->passwd_dialog, False, 0L, &event);
XSync (si->dpy, False);
XSetErrorHandler (old_handler);
if (!status)
fprintf (stderr, "%s: error sending ratio to lock dialog\n", blurb ());
}
#else /* !HAVE_XSCREENSAVER_LOCK */
update_passwd_window (si, 0, pw->ratio);
#endif /* !HAVE_XSCREENSAVER_LOCK */
if (pw->state == pw_read)
pw->timer = XtAppAddTimeOut (si->app, tick, passwd_animate_timer,
(XtPointer) si);
else
pw->timer = 0;
idle_timer ((XtPointer) si, 0);
}
static XComposeStatus *compose_status;
static void
handle_passwd_button (saver_info *si, XEvent *event)
{
saver_preferences *p = &si->prefs;
Bool mouse_in_box = False;
Bool hit_p = False;
passwd_dialog_data *pw = si->pw_data;
saver_screen_info *ssi = pw->prompt_screen;
if (! pw->login_button_enabled_p)
return;
mouse_in_box =
(event->xbutton.x >= pw->login_button_x &&
event->xbutton.x <= pw->login_button_x + pw->login_button_width &&
event->xbutton.y >= pw->login_button_y &&
event->xbutton.y <= pw->login_button_y + pw->login_button_height);
if (ButtonRelease == event->xany.type &&
pw->login_button_down_p &&
mouse_in_box)
{
/* Only allow them to press the button once: don't want to
accidentally launch a dozen gdm choosers if the machine
is being slow.
*/
hit_p = True;
pw->login_button_enabled_p = False;
}
pw->login_button_down_p = (mouse_in_box &&
ButtonRelease != event->xany.type);
update_passwd_window (si, 0, pw->ratio);
if (hit_p)
fork_and_exec (ssi, p->new_login_command);
}
static void
handle_passwd_key (saver_info *si, XKeyEvent *event)
{
saver_preferences *p = &si->prefs;
passwd_dialog_data *pw = si->pw_data;
int pw_size = sizeof (pw->typed_passwd) - 1;
char *typed_passwd = pw->typed_passwd;
char s[2];
char *stars = 0;
int i;
int size = XLookupString (event, s, 1, 0, compose_status);
if (size != 1) return;
s[1] = 0;
/* Add 10% to the time remaining every time a key is pressed. */
pw->ratio += 0.1;
if (pw->ratio > 1) pw->ratio = 1;
switch (*s)
{
case '\010': case '\177': /* Backspace */
if (!*typed_passwd)
XBell (si->dpy, 0);
else
typed_passwd [strlen(typed_passwd)-1] = 0;
break;
case '\025': case '\030': /* Erase line */
memset (typed_passwd, 0, pw_size);
break;
case '\012': case '\015': /* Enter */
if (pw->state != pw_read)
; /* already done? */
else if (typed_passwd[0] == 0)
pw->state = pw_null;
else
{
update_passwd_window (si, "Checking...", pw->ratio);
XSync (si->dpy, False);
/***************mali99************************************************
if (passwd_valid_p (typed_passwd, p->verbose_p, PAM_SERVICE))
pw->state = pw_ok;
else
pw->state = pw_fail;
update_passwd_window (si, "", pw->ratio);
****************************************************************************/
pw->state = pw_ok;
}
break;
default:
/* Though technically the only illegal characters in Unix passwords
are LF and NUL, most GUI programs (e.g., GDM) use regular text-entry
fields that only let you type printable characters. So, people
who use funky characters in their passwords are already broken.
We follow that precedent.
*/
if (isprint ((unsigned char) *s))
{
i = strlen (typed_passwd);
if (i >= pw_size-1)
XBell (si->dpy, 0);
else
{
typed_passwd [i] = *s;
typed_passwd [i+1] = 0;
}
}
else
XBell (si->dpy, 0);
break;
}
if (pw->show_stars_p)
{
i = strlen(typed_passwd);
stars = (char *) malloc(i+1);
memset (stars, '*', i);
stars[i] = 0;
update_passwd_window (si, stars, pw->ratio);
free (stars);
}
else
{
update_passwd_window (si, "", pw->ratio);
}
}
void XTSOLMakeTPWindow(Display *, Window);
void
passwd_event_loop (saver_info *si)
{
saver_preferences *p = &si->prefs;
char *msg = 0;
XEvent event;
unsigned int caps_p = 0;
passwd_dialog_data *pw = si->pw_data;
int ii;
Window w;
int mscreen;
int status = -2;
int counter = 0;
int retries = 2;
/*bugid 6580862 Unable to type in windows session with full screen mode when
hotdesked...
The issue is sunray connector grabs keyboard and focus is in connector
window. When xscreensaver
pastes the unlock dialog box the password typed by user goes into connector
window.
The following code attempts to set focus back in unlock dialog box. The
connector is looking
for focus out events to get a hint to let go of keyboard grab. Which is
exactly what we try to
do in the following code.
*/
write_to_child (si, "pw_read");
mscreen = mouse_screen (si);
w = RootWindowOfScreen(si->screens[mscreen].screen);
/* grab_kbd() uses GrabModeSync which is holding up pointer events and hence
unlcok
* dialog box does not show up when you move mouse, only when you hit a key.
* So, we locally call XGrabKeyboard() with GrabModeAsync instead of calling
grab_kbd().
* status = grab_kbd(si, w, mscreen);
**/
status = XGrabKeyboard (si->dpy, w, True,
GrabModeAsync, GrabModeAsync,
CurrentTime);
XSync (si->dpy, False);
while (status != GrabSuccess && counter++ <=retries)
{
status = XGrabKeyboard (si->dpy, w, True,
GrabModeAsync, GrabModeAsync,
CurrentTime);
write_to_child (si, "pw_read");
usleep (250000); /** 1/4 second */
XSync (si->dpy, False);
XTSOLMakeTPWindow(si->dpy,w);
if(p->verbose_p)
fprintf (stderr, "event loop..trying to grab keyboard######\n");
}
if (status == GrabSuccess)
{
si->keyboard_grab_window = w;
si->keyboard_grab_screen = mscreen;
}
/* bugid 6176524 passwdTimeout and reset timer for each key press */
passwd_animate_timer ((XtPointer) si, 0);
while (si->pw_data && si->pw_data->state == pw_read)
{
XtAppNextEvent (si->app, &event);
#ifdef HAVE_RANDR
/*
* 6757448 xscreensaver doesn't notice XRandR resize events.
*/
if (event.type == (si->randr_event_number + RRScreenChangeNotify))
{
/* The Resize and Rotate extension sends an event when the
size, rotation, or refresh rate of the screen has changed. */
XRRScreenChangeNotifyEvent *xrr_event =
(XRRScreenChangeNotifyEvent *) &event;
/* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */
int screen = XRRRootToScreen (si->dpy, xrr_event->window);
if (p->verbose_p)
{
if (si->screens[screen].width == xrr_event->width &&
si->screens[screen].height == xrr_event->height)
fprintf (stderr,
"%s: %d: no-op screen size change event (%dx%d)\n",
blurb(), screen,
xrr_event->width, xrr_event->height);
else
fprintf (stderr,
"%s: %d: screen size changed from %dx%d to %dx%d\n",
blurb(), screen,
si->screens[screen].width,
si->screens[screen].height,
xrr_event->width, xrr_event->height);
}
# ifdef RRScreenChangeNotifyMask
/* Inform Xlib that it's ok to update its data structures. */
XRRUpdateConfiguration (&event); /* Xrandr.h 1.9, 2002/09/29 */
# endif /* RRScreenChangeNotifyMask */
/* Resize the existing xscreensaver windows and cached ssi data. */
resize_screensaver_window (si);
}
#endif /* HAVE_RANDR */
#ifdef HAVE_XSCREENSAVER_LOCK
if (event.xany.type == KeyPress)
{
if (si->pw_data->got_windowid)
{
Bool status,pwd_status;
XErrorHandler old_handler;
if(p->verbose_p)
fprintf (stderr, "event loop..gotwindowid..and keypress
event...\n");
event.xany.window = si->passwd_dialog;
XSync (si->dpy, False);
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
status =
XSendEvent (si->dpy, si->passwd_dialog, False, KeyPressMask, &event);
XSync (si->dpy, False);
XSetErrorHandler (old_handler);
/* CR 6176524 passwdTimeoutEnable for disabled user
timer will be reset if 4 conditions art true (for each char of pwd)
(status) && (p->pwd_p) && (at_enabled) && (pw->timer)
However AT group wants to remove at_enabled
i.e reset the password timer for each key for all users
* 6240938 screensaver-lock's password timer needs to to be reset
for each key (all users) and enabling AT support
*/
if ((status) && (p->pwd_p) && (pw->timer)) {
XtRemoveTimeOut (pw->timer);
pw->ratio = 1.0;
pw->timer = XtAppAddTimeOut (si->app, 166, passwd_animate_timer,
(XtPointer) si);
}
if (p->verbose_p)
{
if (status)
fprintf (stderr, "sent key...\n");
else
fprintf (stderr, "error sending key...\n");
}
}
else
{
if (p->verbose_p)
fprintf (stderr, "got keypress but no window id yet :(\n");
XtDispatchEvent (&event);
}
}
#else /* !HAVE_XSCREENSAVER_LOCK */
if (event.xany.window == si->passwd_dialog && event.xany.type == Expose)
draw_passwd_window (si);
else if (event.xany.type == KeyPress)
{
handle_passwd_key (si, &event.xkey);
caps_p = (event.xkey.state & LockMask);
}
else if ((event.xany.type == ButtonPress ||
event.xany.type == ButtonRelease) &&
si->pw_data->login_button_p)
handle_passwd_button (si, &event);
#endif /* !HAVE_XSCREENSAVER_LOCK */
else if (event.xany.window == si->passwd_dialog && event.xany.type ==
Expose &&
si->pw_data->passwd_label != NULL)
{
if(p->verbose_p)
fprintf (stderr, "event loop...and expose event.should update lock
with new label...\n");
/***if (si->pw_data->passwd_label)**/
update_passwd_window (si, si->pw_data->passwd_label, pw->ratio);
free (si->pw_data->passwd_label);
si->pw_data->passwd_label = 0;
si->pw_data->state = pw_read;
}
/*
* 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
Also this routine is to stop the popup window when a11y is on also when
a11y is not on.
Note: when a11y is on no_atserv > 0
*/
else if (((event.type == UnmapNotify)
|| (event.type == MapNotify )
|| (event.type == VisibilityNotify)
|| (event.type == ConfigureNotify)
|| (event.type == PropertyNotify )
|| (event.type == CreateNotify)
|| (event.type == ReparentNotify ))
&& (si->passwd_dialog) )
{
/* AT_LOCK_DEBUG
fprintf (stderr, "client window(0x%x) %s\n", event.xclient.window,blurb());
fprintf (stderr, "dialog window 0x%x:\n", si->passwd_dialog);
fprintf(stderr, "** no_atserv: %d \n", no_atserv);
for (ii = 0; ii < 4; ii++)
fprintf(stderr, "** win : 0x%x \n", at_win[ii]);
*/
/* this if case is for safety,it prevent screensaver stuck in loop of
ConfigureNotify */
if(event.xany.window && (event.xany.window !=
si->screens[0].screensaver_window) && (event.xany.window != 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.type)
{
case ConfigureNotify:
wPopWin = event.xconfigure.window;
break;
case CreateNotify:
wPopWin = event.xcreatewindow.window;
break;
case VisibilityNotify:
wPopWin = event.xvisibility.window;
break;
default:
break;
}
/* Array at_win stores password and screensaver window, also MAG
and/or GOK if a11y is on
/* if any window apart from password, MAG ,GOK or screensaver
comes over is considered as popup window. */
/* If it is not popup window but password, MAG, GOK, or
screensaver window then nWin < no_atserv+2 */
/* If it is popup window then nWin == no_atserv+2 */
int nWin =0;
if(wPopWin) // check if it is really a popup window
for(;nWin < no_atserv+2 ; ++nWin)
{
if(at_win[nWin]==wPopWin)
break;
}
/* Do restacking if it is popup window ie nWin == no_atserv+2 */
/* Also do restacking when a11y is on */
if( nWin== no_atserv+2 ||no_atserv )
{
/* at_win[0] -> passwordwindow */
/* at_win[1-2]-> if a11y on, may GOK or MAG */
at_win[no_atserv+1] = si->screens[0].screensaver_window;
if(nWin== no_atserv+2)
{
/* store popup window in array of at_win to restack it */
at_win[no_atserv+2] = wPopWin;
XRestackWindows(si->dpy, at_win,no_atserv+3);
}
else
{
XRestackWindows(si->dpy, at_win,no_atserv+2);
}
XFlush(si->dpy);
}
}
}
/* the above new code for restacking under the conidtion
*/
else
{
/*
if ((si->passwd_dialog) && (no_atserv) && (event.type != 0))
fprintf(stderr, "** DEbug other event %d\n", event.type);
*/
XtDispatchEvent (&event);
}
}
switch (si->pw_data->state)
{
case pw_ok: msg = strdup("pw_ok"); break;
case pw_null: msg = strdup("pw_null"); break;
case pw_time: msg = strdup("pw_time"); break;
case pw_read: msg = strdup("pw_read"); break;
case pw_fail: msg = strdup("pw_fail"); break;
case pw_cancel: msg = strdup("pw_cancel"); break;
default: msg = 0;
fprintf(stderr, "si->pw_data->state is bad, serious error\n");
break;
}
if (si->pw_data->state == pw_fail)
si->unlock_failures++;
if (p->verbose_p)
switch (si->pw_data->state)
{
case pw_ok:
{
fprintf (stderr, "%s: password correct.\n", blurb());
fprintf (stderr, "%s: setting state to be null.\n", blurb());
si->pw_data->state = pw_null;
break;
}
case pw_fail:
fprintf (stderr, "%s: password incorrect!%s\n", blurb(),
(caps_p ? " (CapsLock)" : ""));
break;
case pw_null:
case pw_cancel:
fprintf (stderr, "%s: password entry cancelled.\n", blurb()); break;
case pw_time:
fprintf (stderr, "%s: password entry timed out.\n", blurb()); break;
default:
break;
}
#ifdef HAVE_SYSLOG
if (si->pw_data->state == pw_fail)
{
/* If they typed a password (as opposed to just hitting return) and
the password was invalid, log it.
*/
struct passwd *pw = getpwuid (getuid ());
char *d = DisplayString (si->dpy);
char *u = (pw->pw_name ? pw->pw_name : "???");
int opt = 0;
int fac = 0;
# ifdef LOG_PID
opt = LOG_PID;
# endif
# if defined(LOG_AUTHPRIV)
fac = LOG_AUTHPRIV;
# elif defined(LOG_AUTH)
fac = LOG_AUTH;
# else
fac = LOG_DAEMON;
# endif
if (!d) d = "";
openlog (progname, opt, fac);
syslog (LOG_NOTICE, "FAILED LOGIN %d ON DISPLAY \"%s\", FOR \"%s\"",
si->unlock_failures, d, u);
closelog ();
}
#endif /* HAVE_SYSLOG */
if (si->pw_data->state == pw_fail)
XBell (si->dpy, False);
if (si->pw_data->state == pw_ok && si->unlock_failures != 0)
{
if (si->unlock_failures == 1)
fprintf (real_stderr,
"%s: WARNING: 1 failed attempt to unlock the screen.\n",
blurb());
else
fprintf (real_stderr,
"%s: WARNING: %d failed attempts to unlock the screen.\n",
blurb(), si->unlock_failures);
si->unlock_failures = 0;
}
if (msg)
{
if (p->verbose_p)
{
fprintf (stderr, "..eventloop...msg is:%s\n",msg);
}
#ifdef HAVE_XSCREENSAVER_LOCK
/* DONT NEED TO SEND ANY INFO TO CHILD AT THIS STAGE */
/* if (write_to_child (si, msg));**/ /*if write is successful do nothing*/
free(msg);
/*********************************************************
if (si->external_passwd && si->pw_data->stdin_fd != -1)
{
ssize_t len;
char *nlmsg;
nlmsg = (char *)malloc (strlen (msg) + 2);
sprintf (nlmsg, "%s\n", msg);
if (p->verbose_p)
{
fprintf (stderr,
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
fprintf (stderr, "HAVE_SCRSVR_LOCK message is:%s writing to
fd:%d\n",
msg, si->pw_data->stdin_fd);
fprintf (stderr,
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
write_msg:
len = write (si->pw_data->stdin_fd, nlmsg, strlen (nlmsg));
if (len < 0 && errno == EINTR)
goto write_msg;
free (nlmsg);
}
else
******************************************************************************/
#endif /* HAVE_XSCREENSAVER_LOCK */
/************
{
si->pw_data->i_beam = 0;
update_passwd_window (si, msg, 0.0);
}
************/
XSync (si->dpy, False);
usleep (250000); /* 1/4 second */
/* Swallow all pending KeyPress/KeyRelease events. */
{
XEvent e;
while (XCheckMaskEvent (si->dpy, KeyPressMask|KeyReleaseMask, &e))
;
}
}
}
void
handle_typeahead (saver_info *si)
{
passwd_dialog_data *pw = si->pw_data;
int i;
if (!si->unlock_typeahead)
return;
i = strlen (si->unlock_typeahead);
if (i >= sizeof(pw->typed_passwd) - 1)
i = sizeof(pw->typed_passwd) - 1;
memcpy (pw->typed_passwd, si->unlock_typeahead, i);
pw->typed_passwd [i] = 0;
memset (si->unlock_typeahead, '*', strlen(si->unlock_typeahead));
si->unlock_typeahead[i] = 0;
#ifdef HAVE_XSCREENSAVER_LOCK
/* FIXME: bugzilla.gnome.org #77077 */
/* need to handle this in the external dialog case */
#else
update_passwd_window (si, si->unlock_typeahead, pw->ratio);
#endif /* !HAVE_XSCREENSAVER_LOCK */
free (si->unlock_typeahead);
si->unlock_typeahead = 0;
}
Bool
unlock_p (saver_info *si)
{
saver_preferences *p = &si->prefs;
Bool status;
raise_window (si, True, True, True);
if (p->verbose_p)
fprintf (stderr, "%s: -->unlock_p()\n", blurb());
Need to update about SUBCR of Nevada #6839026
My new fixes are very stable now. Barun and I have tested it very
thoroughly with a11y on. Today I will raise it for JDS-Review, if no
objection from Jeremy and Alan.
*Background*
Patch 120094-22, may cause performance degradation of CPU and system
become unresposive when Trusted Extension or Accessibility is turned
on. Fixes of CR 6769901 are not appropriate should be corrected with CR
6839026, on all the x86 and SPARC machine .
When a machine is patched with 120094-22, Symptoms are as follows.
a) When screen is locked and Accessibility is turned on, popup window
might make x86/SPARC machine unresponsive.
b) When screen is locked and Trusted Extension is turned on, may cause
performance degradation of CPU. [tx] Xsun chews cpu and console appear
to be hung.
*Questions*
Q:why we have not fixed it at WindowManager?
Ans: We got some success in fixing this bug at metacity/WM, but with
lots of code changes. Login helper interface is required at metacity
Q: Is it fixed completly .What is remaining?
Ans: Yes this bug is fixed completely. But we should wait for final
test results, if any problem comes we will fix in CR6875930.
There are some special cases, where we need to do restacking of pop up
windows in timer.c . Also there are some existing bugs in a11y, we will
address them separately.
We are fixing this bug in incremental mode, all the remaining problem
will be fixed in CR6875930
*What we have fixied*
Xsun is consuming 100% cpu cycle with trusted path because of CR6769901
Also we found, with accessibility, cpu consumption goes to 100%
Popup window should not come through screensaver.
*Testing *
Barun and Arvind have tested new fixes very thoroughly
a) Pop-ups will not come through screensaver in case of dual head
display with and without xinerama . Same is the case when a11y is turned on.
b)Pop-ups will not come through screensaver with twinview display of
Xorg. Also there will be no performance degradation with my fixes
c) Pop-ups will not come through screensaver with trusted path
d) Pop-ups will not come through screensaver with all a11y cases
e) works fine with Xnewt,Xorg and Xsun
f) works fine with x86, x64, SPARC
g) The only pop-ups to get through are the ally pop-ups which are
allowed by design. GOK and MAG always on top of screensaver when we
lock the screen.
I am including svn diff of repository trunk/vermillion. For more detail
please see the attached source file.
Index: ChangeLog
===================================================================
--- ChangeLog (revision 19180)
+++ ChangeLog (working copy)
@@ -1,3 +1,8 @@
+2009-09-10 Arvind Umrao <arvind.umrao at sun.com>
+
+ * SUNWxscreensaver.spec, patches/xscreensaver-48-bug-6839026.diff:
+ * CR#6839026 Regression in screensaver may cause Performance
Degradation and make lock ed screensaver unresponsive.
+
2009-08-27 Abhijit Nath <abhijit.nath at sun.com>
* SUNWTiff.spec: add patch libtiff-05-CVE-2009-2285.diff
Index: patches/xscreensaver-48-bug-6839026.diff
===================================================================
--- patches/xscreensaver-48-bug-6839026.diff (revision 0)
+++ patches/xscreensaver-48-bug-6839026.diff (revision 0)
@@ -0,0 +1,150 @@
+--- xscreensaver-5.01/driver/lock.c_org 2009-08-27
16:40:31.474335000 +0530
++++ xscreensaver-5.01/driver/lock.c 2009-09-10 15:39:37.444268000 +0530
+@@ -109,8 +109,8 @@ extern Atom XA_UNLOCK_RATIO;
+
+
+ /* GOK bug */
+-Window at_win[4] = {0,0,0,0}; /* wIds for XRestackWindows() */
+- /* dialog, GOK, or MAG or screenSaver */
++Window at_win[5] = {0,0,0,0,0}; /* wIds for XRestackWindows() */
++ /* dialog, GOK, or MAG or screenSaver or
temporary popup wi ndow */
+
+ int no_atserv = 0; /* GOK or MAG or Both on def. screen 0 */
+
+@@ -2139,36 +2139,6 @@ passwd_event_loop (saver_info *si)
+ }
+ }
+
+- //bugid 6769901: popup windows appearing through xscreensaver
+- //code to stop popup windows while screen is locked
+- //Raise the screen saver window and then the password dialog
window
+- if (event.xany.type == VisibilityNotify || event.xany.type ==
ConfigureNotify || event.xany.type == CreateNotify)
+- {
+- int screen;
+- for (screen = 0; screen < si->nscreens; screen++)
+- {
+- if(si->passwd_dialog)for
+- {
+- saver_screen_info *ssi =
&si->screens[screen];
+- if(screen==0)
+- {
+- Window screen_win[2] = {
+- si->passwd_dialog,
+- ssi->screensaver_window
+- };
+- XRestackWindows(si->dpy,
screen_win, 2);
+-
XMapRaised(si->dpy,si->passwd_dialog);
+- XFlush(si->dpy);
+- }
+- else
+- {
+-
XMapRaised(si->dpy,ssi->screensaver_window);
+- XFlush(si->dpy);
+- }
+- }
+- }
+- }
+-
+ #else /* !HAVE_XSCREENSAVER_LOCK */
+ if (event.xany.window == si->passwd_dialog && event.xany.type ==
Expose)
+ draw_passwd_window (si);
+@@ -2219,24 +2189,87 @@ passwd_event_loop (saver_info *si)
+ Now, GOK only supports 2nd USB/mouse/Dwell, corepointer is supposed
+ not to be used, and GOK cannot disable it
+ */
+- else if (((event.type == UnmapNotify)
+- || (event.type == MapNotify )
+- || (event.type == ConfigureNotify)
+- || (event.type == PropertyNotify )
+- || (event.type == ReparentNotify ))*dfdf
*
+- && (si->passwd_dialog) && (no_atserv))
+- {
++/*
++ bugid 6769901,6839026: popup windows appearing through xscreensaver
++ Also this routine is to stop the popup window when a11y is on
also when a11y is not on.
++ Note: when a11y is on no_atserv > 0for
++*/
++
++else if (((event.type == UnmapNotify)
++ || (event.type == MapNotify )
++ || (event.type == VisibilityNotify)
++ || (event.type == ConfigureNotify)
++ || (event.type == PropertyNotify )
++ || (event.type == CreateNotify)
++ || (event.type == ReparentNotify ))
++ && (si->passwd_dialog) )
++ {
+ /* AT_LOCK_DEBUG
+ fprintf (stderr, "client window(0x%x) %s\n",
event.xclient.window,blurb());
+ fprintf (stderr, "dialog window 0x%x:\n", si->passwd_dialog);
+ fprintf(stderr, "** no_atserv: %d \n", no_atserv);
+ for (ii = 0; ii < 4; ii++)
+- fprintf(stderr, "** win : 0x%x \n", at_win[ii]);
++ fprintf(stderr, "** win : 0x%x \n", at_win[ii]);
+ */
+- at_win[no_atserv+1] = si->screens[0].screensaver_window;
+-/* 2 => screensaver and dialog Wids */
+- XRestackWindows(si->dpy, at_win, no_atserv+2);
+- XFlush(si->dpy);
++
++ /* this if case is for safety,it prevent screensaver stuck in
loop of ConfigureNot ify */
++ if(event.xany.window && (event.xany.window !=
si->screens[0].screensaver_window) & & (event.xany.window !=
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.type)
++ {
++ case ConfigureNotify:
++ wPopWin = event.xconfigure.window;
++ break;
++ case CreateNotify:
++ wPopWin = event.xcreatewindow.window;
++ break;
++ case VisibilityNotify:
++ wPopWin = event.xvisibility.window;
++ break;
++ default:
++ break;
++ }
++
++
++ /* Array at_win stores password and screensaver window,
also MAG and/or GOK if a11y is on
++ /* if any window apart from password, MAG ,GOK or
screensaver comes over is considered as popup window. */
++ /* If it is not popup window but password, MAG, GOK, or
screensaver window t hen nWin < no_atserv+2 */
++ /* If it is popup window then nWin == no_atserv+2 */
++ int nWin =0;
++ if(wPopWin) // check if it is really a popup window
++ for(;nWin < no_atserv+2 ; ++nWin)
++ {
++ if(at_win[nWin]==wPopWin)
++ break;
++ }
++
++ /* Do restacking if it is popup window ie nWin ==
no_atserv+2 */
++ /* Also do restacking when a11y is on */
++ if( nWin== no_atserv+2 ||no_atserv )
++ {
++
++ /* at_win[0] -> passwordwindow */
++ /* at_win[1-2]-> if a11y on, may GOK or MAG */
++
++ at_win[no_atserv+1] = si->screens[0].screensaver_window;
++ if(nWin== no_atserv+2)
++ {
++ /* store popup window in array of at_win to restack
it */
++ at_win[no_atserv+2] = wPopWin;
++ XRestackWindows(si->dpy, at_win,no_atserv+3);
++ }
++ else
++ {
++ XRestackWindows(si->dpy, at_win,no_atserv+2);
++ }
++ XFlush(si->dpy);
++ }
++ }
++
+ }
+ /* the above new code for restacking under the conidtion
+ */
Index: SUNWxscreensaver.spec
===================================================================
--- SUNWxscreensaver.spec (revision 19180)
+++ SUNWxscreensaver.spec (working copy)
@@ -149,6 +149,8 @@
Patch46: xscreensaver-46-bug-6857559.diff
# date:2009-07-31 owner:bp230705 type:bug bugster:6859039
Patch47: xscreensaver-47-bug-6859039.diff
+# date:2009-09-10 owner:au230626 type:bug bugster:6839026
+Patch48: xscreensaver-48-bug-6839026.diff
# date:2008-03-07 owner:alanc type:branding
Patch101: rss-glx-101-matrixview.diff
@@ -327,6 +329,7 @@
%patch45 -p1
%patch46 -p1
%patch47 -p1
+%patch48 -p1
------------------------------------------------------------------------
/* lock.c --- handling the password dialog for locking-mode.
* xscreensaver, Copyright (c) 1993-2006 Jamie Zawinski <jwz at 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.
*/
/* Athena locking code contributed by Jon A. Christopher <jac8782 at tamu.edu>
*/
/* Copyright 1997, with the same permissions as above. */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <ctype.h>
#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 <signal.h>
#include "exec.h"
#include "xscreensaver.h"
#include "resources.h"
#include <gconf/gconf-client.h>
#ifndef NO_LOCKING /* (mostly) whole file */
#ifdef HAVE_SYSLOG
# include <syslog.h>
#endif /* HAVE_SYSLOG */
#ifdef HAVE_XHPDISABLERESET
# include <X11/XHPlib.h>
static void hp_lock_reset (saver_info *si, Bool lock_p);
#endif /* HAVE_XHPDISABLERESET */
#ifdef HAVE_XF86VMODE
# include <X11/extensions/xf86vmode.h>
static void xfree_lock_mode_switch (saver_info *si, Bool lock_p);
#endif /* HAVE_XF86VMODE */
#ifdef HAVE_XF86MISCSETGRABKEYSSTATE
# include <X11/extensions/xf86misc.h>
static void xfree_lock_grab_smasher (saver_info *si, Bool lock_p);
#endif /* HAVE_XF86MISCSETGRABKEYSSTATE */
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif /* HAVE_RANDR */
#ifdef _VROOT_H_
ERROR! You must not include vroot.h in this file.
#endif
#ifdef HAVE_UNAME
# include <sys/utsname.h> /* for hostname info */
#endif /* HAVE_UNAME */
#include <ctype.h>
#ifndef VMS
# include <pwd.h>
#else /* VMS */
extern char *getenv(const char *name);
extern int validate_user(char *name, char *password);
static Bool
vms_passwd_valid_p(char *pw, Bool verbose_p)
{
return (validate_user (getenv("USER"), typed_passwd) == 1);
}
# undef passwd_valid_p
# define passwd_valid_p vms_passwd_valid_p
#endif /* VMS */
/* 5059445(p3) screen kb and reader support */
extern int grab_mouse (saver_info *si, Window window, Cursor cursor, int
screen_no);
extern int grab_kbd (saver_info *si, Window window, int screen_no);
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);
void hack_uid (saver_info *si);
Bool g_passwd_dialog_created = 0;
#undef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
/* enum passwd_state & struct passwd_dialog_data moved to xscreensaver.h */
static void make_window (saver_info *si, enum window_type w_type);
static void draw_passwd_window (saver_info *si);
void update_passwd_window (saver_info *si, const char *printed_passwd,
float ratio);
void destroy_passwd_window (saver_info *si);
static void undo_vp_motion (saver_info *si);
static void handle_passwd_button (saver_info *si, XEvent *event);
extern Atom XA_UNLOCK_RATIO;
/* GOK bug */
Window at_win[5] = {0,0,0,0,0}; /* wIds for XRestackWindows() */
/* dialog, GOK, or MAG or screenSaver or
temporary popup window */
int no_atserv = 0; /* GOK or MAG or Both on def. screen 0 */
Bool at_enabled = False; /* Ass. Tech support? def. no */
/* for restoring the origin setting
override_redirect setting of MAG/GOK
*/
Bool winatt_reset[2] = {FALSE,FALSE};
char *globalkey_text = NULL;
char *globalmenu_key = NULL;
GConfClient *client = NULL;
/*
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 : rturn 0
*/
Atom atom_type[1], atom_window_type;
Window
check_raisedWid(saver_info *si,Window wid)
{
int screen_no,status;
Bool loop, found = FALSE;
Window root_ret, parent_ret, *children = NULL,root;
unsigned int nchildren = 0;
Screen *screen;
saver_screen_info *ssi;
Display *dpy;
Window screen_win[2] = {0,0};
for (screen_no = 0; screen_no < si->nscreens; screen_no++)
{
loop = TRUE;
ssi = &si->screens[screen_no];
screen = ssi->screen;
root = RootWindowOfScreen (screen);
if (screen_no == 0)
dpy = DisplayOfScreen(screen);
else
dpy = ssi->other_dpy;
if (dpy)
{
while (loop)
{
status =
XQueryTree (dpy, wid ,&root_ret,&parent_ret, &children, &nchildren);
/* AT_LOCK_DEBUG
fprintf(stderr, " ==>screen(%x) root(%x) wid(%x) root_ret(%x)
parent_ret(%x)\n", screen, root, wid, root_ret, parent_ret);
fprintf(stderr, " screen_no(%d) ==>dpy(%x)\n", screen_no,dpy);
*/
if (parent_ret == 0 || root != root_ret) /* not found */
loop = FALSE;
else if ( root_ret != parent_ret)
wid = parent_ret;
else
{
loop = FALSE;
found = TRUE;
/* AT_LOCK_DEBUG
fprintf(stderr,"==> found wid is 0x%x screen_no(%d)\n", wid, screen_no);
*/
if (screen_no)
{
/*
** found in other screen(not scn 0), implies MAG target scn,
** invoke XRestackWindow()
*/
screen_win[0] = wid;
screen_win[1] = ssi->screensaver_window;
XRestackWindows(dpy, screen_win, 2);
XSync (dpy, False);
wid = 0; /* no need to do the restack on screen 0 */
}
screen_no = si->nscreens;
}
} /* while loop */
} /*dpy check */
} /* for loop */
if (found)
return wid;
else
return 0;
}
static int ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error);
#ifdef HAVE_XSCREENSAVER_LOCK
int
write_to_child (saver_info* si, char* msg)
{
if (si->external_passwd && g_passwd_dialog_created &&
si->pw_data->stdin_fd != -1)
{
ssize_t len;
char *nlmsg;
nlmsg = (char *)malloc (strlen (msg) + 2);
sprintf (nlmsg, "%s\n", msg);
if (si->prefs.verbose_p)
{
fprintf (stderr,
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
fprintf (stderr, "HAVE_SCRSVR_LOCK message is:%s writing to
fd:%d\n",
msg, si->pw_data->stdin_fd);
fprintf (stderr,
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
write_msg:
len = write (si->pw_data->stdin_fd, nlmsg, strlen (nlmsg));
if (len < 0 && errno == EINTR)
goto write_msg;
free (nlmsg);
return (1);
}
return (0); /* if we didnt write anything return 0*/
}
static int
sane_dup2 (int fd1, int fd2)
{
int ret;
retry:
ret = dup2 (fd1, fd2);
if (ret < 0 && errno == EINTR)
goto retry;
return ret;
}
static int
close_and_invalidate (int *fd)
{
int ret;
ret = close (*fd);
*fd = -1;
return ret;
}
void
handle_passwd_input (XtPointer data, int *fd, XtInputId *id)
{
saver_info *si = (saver_info *)data;
saver_preferences *p = &si->prefs;
char buffer[1024];
char *s;
int status;
if (si->prefs.verbose_p)
fprintf (stderr, "passwd input handler() fd=%d\n",*fd);
s = fgets (buffer, sizeof (buffer), si->pw_data->input_file);
if (!s)
{
if (si->prefs.verbose_p)
{
fprintf (stderr, "done reading...\n");
fprintf (stderr, "removing input handler...\n");
}
XtRemoveInput (*id);
si->pw_data->stdout_input_id = 0;
if (si->pw_data->state == pw_read)
si->pw_data->state = pw_null;
if (si->prefs.verbose_p)
fprintf (stderr, "passwd input handler() returning...done reading\n");
return;
}
if (si->pw_data->got_windowid)
{
char *nl;
if (si->prefs.verbose_p)
fprintf (stderr, "got a password\n");
nl = strchr (s, '\n');
if (nl)
*nl = '\0';
si->pw_data->passwd_string = strdup (s);
if (si->prefs.verbose_p)
fprintf(stderr,"Dude got password and saving it in passwd_string:%s\n",
s);
/* We want to send null to lock dialog to say we are working on
authentication*/
si->pw_data->state = pw_null;
}
else /* Get the window id of lock dialog from Child ***/
{
Window window = strtoul (s, NULL, 0);
XSetWindowAttributes setwinattr;
unsigned long valuemask = CWOverrideRedirect;
XWindowChanges changes;
setwinattr.override_redirect = True;
XWindowAttributes window_attributes_return;
Window window1 = 0, passwd_win = 0,wintemp = 0; int j;
/*CR 5039878 2 3 "Password:" field should be focused / have flashing caret */
s = fgets (buffer, sizeof (buffer), si->pw_data->input_file);
passwd_win = strtoul (s, NULL, 0);
no_atserv = 0;
at_win[no_atserv] = window;
/* There is no need to reset the timer for Normal user
for each pop-up dialog
*/
at_enabled = False;
for (j= 0; j < 2; j++)
{
s = fgets (buffer, sizeof (buffer), si->pw_data->input_file);
window1 = strtoul (s, NULL, 0);
/* GOK, MAG, not running, Ass. Tech support is still selected
not enough interface info from loginhelper to cover all
possible conditions, ungrab kb/mouse now
*/
if (window1 == 0x1)
at_enabled = True;
else
if (window1 != 0x0 ) {
/*
5083155 Unable to unlock screen when running dual-head MAG
*adding dual or multiple heads for magnifier support
*/
at_enabled = True;
wintemp = check_raisedWid(si, window1);
if (wintemp) {
status =
XGetWindowAttributes(si->dpy,wintemp,&window_attributes_return);
if ((status) && (!window_attributes_return.override_redirect))
{
XFlush(si->dpy);
XChangeWindowAttributes(si->dpy,wintemp,valuemask,&setwinattr);
winatt_reset[j] = TRUE;
/* AT_LOCK_DEBUG
fprintf(stderr,"Debug: ==> winatt_reset[%d] override_redirect needs to be
reset\n",j);
*/
}
XMapSubwindows(si->dpy, wintemp);
no_atserv++;
at_win[no_atserv] = wintemp;
} /* wintemp != 0 */
}
}
/* common parent, i.e root win */
/* cases for running GOK , or MAG or GOK+MAG */
/* 6461887(P1) screen lock does not prevent access to other
** applications via 'alt-tab',
** see 6519433 mem leaks in libgconf-2.so's gconf_client_get_default()
*/
client = gconf_client_get_default();
if (no_atserv > 0) {
/* pop-up dialog in dock mode */
/* AT_LOCK_DEBUG
fprintf(stderr,"==> found dialog wid 0x%x\n", window);
*/
XRestackWindows(si->dpy, at_win, no_atserv+1);
XUngrabKeyboard(si->dpy, CurrentTime);
XUngrabPointer(si->dpy, CurrentTime);
si->at_external_passwd = True;
XFlush(si->dpy);
globalkey_text = gconf_client_get_string (client, \
"/apps/metacity/global_keybindings/switch_windows", NULL);
if (globalkey_text && strncmp(globalkey_text,"dis",3))
gconf_client_set_string (client, \
"/apps/metacity/global_keybindings/switch_windows", "disabled", NULL);
}
/* no MAG or GOK, only SPEECH is running
just Ass. Tech support is selected
*/
else if ((no_atserv == 0) && (at_enabled))
{
XUngrabKeyboard(si->dpy, CurrentTime);
XUngrabPointer(si->dpy, CurrentTime);
si->at_external_passwd = True;
XFlush(si->dpy);
globalkey_text = \
gconf_client_get_string(client, \
"/apps/metacity/global_keybindings/switch_windows", NULL);
if ( globalkey_text && strncmp(globalkey_text,"dis",3))
gconf_client_set_string ( client, \
"/apps/metacity/global_keybindings/switch_windows", "disabled", NULL);
/*
** 6736157 A11Y]Security problem when desktop a11y support is turned on
*/
globalmenu_key = \
gconf_client_get_string(client, \
"/apps/metacity/global_keybindings/panel_main_menu",NULL);
if ( globalmenu_key && strncmp(globalmenu_key,"dis",3))
gconf_client_set_string ( client, \
"/apps/metacity/global_keybindings/panel_main_menu","disabled",NULL);
}
/* AT_LOCK_DEBUG
fprintf(stderr,"debug no_atserv 0x%x\n", no_atserv);
fprintf(stderr,"debug passwd win 0x%x\n", passwd_win);
fprintf(stderr,"debug window 0x%x\n", window);
*/
XSelectInput(si->dpy, passwd_win,KeyPressMask);
XSetInputFocus (si->dpy, passwd_win,RevertToPointerRoot, CurrentTime);
XSync (si->dpy, False);
si->pw_data->got_windowid = True;
si->passwd_dialog = window;
/**g_passwd_dialog_created = True;**/ /*set global flag to check in
timers.c*/
if (si->prefs.verbose_p)
fprintf (stderr, "<---handle_passwd_input(): gotwindowid:0x%x\n",
passwd_win);
}
}
/* 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 };
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 %d still exists. Killing it with SIGKILL\n",
si->passwd_pid);
kill(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;
write_to_child (si, "Hello There"); /* Send a test message to Child */
/* Password from child dialog comes through this pipe/fd */
pw->input_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 */
void
make_passwd_window (saver_info *si)
{
make_window(si, w_dialog);
}
static void
make_window (saver_info *si, enum window_type w_type)
{
struct passwd *p = getpwuid (getuid ());
XSetWindowAttributes attrs;
unsigned long attrmask = 0;
passwd_dialog_data *pw = si->pw_data;
Screen *screen;
Colormap cmap;
char *f;
saver_screen_info *ssi = &si->screens [mouse_screen (si)];
if (si->prefs.verbose_p)
fprintf(stderr, "-->make_window()\n");
#ifdef HAVE_XSCREENSAVER_LOCK
if (spawn_external_passwd_process (si, si->pw_data))
{
/***************
if (si->prefs.verbose_p)
fprintf(stderr, "spawning external passwd process in
make_window()\n");
*******************/
/****************mali blank_fails remove this...
if(!blank_screen(si))
fprintf(stderr, "Failed to blank the screen\n");
*******************/
si->pw_data->ratio = 1.0;
si->pw_data->w_type = w_type;
/*si->pw_data = pw;*/
si->external_passwd = True;
return;
}
si->external_passwd = False;
si->at_external_passwd = False;
/* FIXME: don't abort() */
/*abort ();*/
#endif /* HAVE_XSCREENSAVER_LOCK */
/* Display the button only if the "newLoginCommand" pref is non-null.
*/
pw->login_button_p = (si->prefs.new_login_command &&
*si->prefs.new_login_command);
if (pw->login_button_p)
pw->passwd_cursor = XCreateFontCursor (si->dpy, XC_top_left_arrow);
else
pw->passwd_cursor = 0;
pw->prompt_screen = ssi;
if (si->prefs.verbose_p)
fprintf (stderr, "%s: %d: creating password dialog.\n",
blurb(), pw->prompt_screen->number);
screen = pw->prompt_screen->screen;
cmap = DefaultColormapOfScreen (screen);
pw->w_type = w_type;
pw->state = pw_read;
pw->ratio = 1.0;
pw->show_stars_p = get_boolean_resource(si->dpy, "passwd.asterisks",
"Boolean");
pw->heading_label = get_string_resource (si->dpy, "passwd.heading.label",
"Dialog.Label.Label");
pw->body_label = get_string_resource (si->dpy, "passwd.body.label",
"Dialog.Label.Label");
pw->user_label = get_string_resource (si->dpy, "passwd.user.label",
"Dialog.Label.Label");
pw->passwd_label = get_string_resource (si->dpy, "passwd.passwd.label",
"Dialog.Label.Label");
pw->login_label = get_string_resource (si->dpy, "passwd.login.label",
"Dialog.Button.Label");
pw->date_label = get_string_resource (si->dpy, "dateFormat", "DateFormat");
if (!pw->heading_label)
pw->heading_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
if (!pw->body_label)
pw->body_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
if (!pw->user_label) pw->user_label = strdup("ERROR");
if (!pw->passwd_label) pw->passwd_label = strdup("ERROR");
if (!pw->date_label) pw->date_label = strdup("ERROR");
if (!pw->login_label) pw->login_label = strdup ("ERROR (LOGIN)") ;
/* Put the version number in the label. */
{
char *s = (char *) malloc (strlen(pw->heading_label) + 20);
sprintf(s, pw->heading_label, si->version);
free (pw->heading_label);
pw->heading_label = s;
}
/* Get hostname info */
pw->uname_label = strdup(""); /* Initialy, write nothing */
# ifdef HAVE_UNAME
{
struct utsname uts;
if (uname (&uts) == 0)
{
#if 0 /* Get the full hostname */
{
char *s;
if ((s = strchr(uts.nodename, '.')))
*s = 0;
}
#endif
char *s = strdup (uts.nodename);
free (pw->uname_label);
pw->uname_label = s;
}
}
# endif
f = get_string_resource (si->dpy, "passwd.headingFont", "Dialog.Font");
pw->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->heading_font) pw->heading_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource (si->dpy, "passwd.buttonFont", "Dialog.Font");
pw->button_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->button_font) pw->button_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource(si->dpy, "passwd.bodyFont", "Dialog.Font");
pw->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->body_font) pw->body_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource(si->dpy, "passwd.labelFont", "Dialog.Font");
pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource(si->dpy, "passwd.passwdFont", "Dialog.Font");
pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource(si->dpy, "passwd.dateFont", "Dialog.Font");
pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
f = get_string_resource(si->dpy, "passwd.unameFont", "Dialog.Font");
pw->uname_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
if (!pw->uname_font) pw->uname_font = XLoadQueryFont (si->dpy, "fixed");
if (f) free (f);
pw->show_uname_p = get_boolean_resource(si->dpy, "passwd.uname", "Boolean");
pw->foreground = get_pixel_resource (si->dpy, cmap,
"passwd.foreground",
"Dialog.Foreground" );
pw->background = get_pixel_resource (si->dpy, cmap,
"passwd.background",
"Dialog.Background" );
if (pw->foreground == pw->background)
{
/* Make sure the error messages show up. */
pw->foreground = BlackPixelOfScreen (screen);
pw->background = WhitePixelOfScreen (screen);
}
pw->passwd_foreground = get_pixel_resource (si->dpy, cmap,
"passwd.text.foreground",
"Dialog.Text.Foreground" );
pw->passwd_background = get_pixel_resource (si->dpy, cmap,
"passwd.text.background",
"Dialog.Text.Background" );
pw->button_foreground = get_pixel_resource (si->dpy, cmap,
"splash.Button.foreground",
"Dialog.Button.Foreground" );
pw->button_background = get_pixel_resource (si->dpy, cmap,
"splash.Button.background",
"Dialog.Button.Background" );
pw->thermo_foreground = get_pixel_resource (si->dpy, cmap,
"passwd.thermometer.foreground",
"Dialog.Thermometer.Foreground" );
pw->thermo_background = get_pixel_resource ( si->dpy, cmap,
"passwd.thermometer.background",
"Dialog.Thermometer.Background" );
pw->shadow_top = get_pixel_resource ( si->dpy, cmap,
"passwd.topShadowColor",
"Dialog.Foreground" );
pw->shadow_bottom = get_pixel_resource (si->dpy, cmap,
"passwd.bottomShadowColor",
"Dialog.Background" );
pw->logo_width = get_integer_resource (si->dpy, "passwd.logo.width",
"Dialog.Logo.Width");
pw->logo_height = get_integer_resource (si->dpy, "passwd.logo.height",
"Dialog.Logo.Height");
pw->thermo_width = get_integer_resource (si->dpy, "passwd.thermometer.width",
"Dialog.Thermometer.Width");
pw->internal_border = get_integer_resource (si->dpy,
"passwd.internalBorderWidth",
"Dialog.InternalBorderWidth");
pw->shadow_width = get_integer_resource (si->dpy, "passwd.shadowThickness",
"Dialog.ShadowThickness");
if (pw->logo_width == 0) pw->logo_width = 150;
if (pw->logo_height == 0) pw->logo_height = 150;
if (pw->internal_border == 0) pw->internal_border = 15;
if (pw->shadow_width == 0) pw->shadow_width = 4;
if (pw->thermo_width == 0) pw->thermo_width = pw->shadow_width;
{
int direction, ascent, descent;
XCharStruct overall;
pw->width = 0;
pw->height = 0;
/* Measure the heading_label. */
XTextExtents (pw->heading_font,
pw->heading_label, strlen(pw->heading_label),
&direction, &ascent, &descent, &overall);
if (overall.width > pw->width) pw->width = overall.width;
pw->height += ascent + descent;
/* Measure the uname_label. */
if ((strlen(pw->uname_label)) && pw->show_uname_p)
{
XTextExtents (pw->uname_font,
pw->uname_label, strlen(pw->uname_label),
&direction, &ascent, &descent, &overall);
if (overall.width > pw->width) pw->width = overall.width;
pw->height += ascent + descent;
}
pw->width += (pw->internal_border * 2);
pw->height += (pw->internal_border * 4);
pw->width += pw->thermo_width + (pw->shadow_width * 3);
if (pw->logo_height > pw->height)
pw->height = pw->logo_height;
else if (pw->height > pw->logo_height)
pw->logo_height = pw->height;
pw->logo_width = pw->logo_height;
pw->width += pw->logo_width;
}
attrmask |= CWOverrideRedirect; attrs.override_redirect = True;
attrmask |= CWEventMask;
attrs.event_mask = (ExposureMask | KeyPressMask |
ButtonPressMask | ButtonReleaseMask);
/* We need to remember the mouse position and restore it afterward, or
sometimes (perhaps only with Xinerama?) the mouse gets warped to
inside the bounds of the lock dialog window.
*/
{
Window pointer_root, pointer_child;
int root_x, root_y, win_x, win_y;
unsigned int mask;
pw->previous_mouse_x = 0;
pw->previous_mouse_y = 0;
if (XQueryPointer (si->dpy, RootWindowOfScreen (pw->prompt_screen->screen),
&pointer_root, &pointer_child,
&root_x, &root_y, &win_x, &win_y, &mask))
{
pw->previous_mouse_x = root_x;
pw->previous_mouse_y = root_y;
if (si->prefs.verbose_p)
fprintf (stderr, "%s: %d: mouse is at %d,%d.\n",
blurb(), pw->prompt_screen->number,
pw->previous_mouse_x, pw->previous_mouse_y);
}
else if (si->prefs.verbose_p)
fprintf (stderr, "%s: %d: unable to determine mouse position?\n",
blurb(), pw->prompt_screen->number);
}
/* Figure out where on the desktop to place the window so that it will
actually be visible; this takes into account virtual viewports as
well as Xinerama. */
{
int x, y, w, h;
get_screen_viewport (pw->prompt_screen, &x, &y, &w, &h,
pw->previous_mouse_x, pw->previous_mouse_y,
si->prefs.verbose_p);
if (si->prefs.debug_p) w /= 2;
pw->x = x + ((w + pw->width) / 2) - pw->width;
pw->y = y + ((h + pw->height) / 2) - pw->height;
if (pw->x < x) pw->x = x;
if (pw->y < y) pw->y = y;
}
pw->border_width = get_integer_resource (si->dpy, "passwd.borderWidth",
"Dialog.BorderWidth");
si->passwd_dialog =
XCreateWindow (si->dpy,
RootWindowOfScreen(screen),
pw->x, pw->y, pw->width, pw->height, pw->border_width,
DefaultDepthOfScreen (screen), InputOutput,
DefaultVisualOfScreen(screen),
attrmask, &attrs);
XSetWindowBackground (si->dpy, si->passwd_dialog, pw->background);
/* We use the default visual, not ssi->visual, so that the logo pixmap's
visual matches that of the si->passwd_dialog window. */
pw->logo_pixmap = xscreensaver_logo (ssi->screen,
/* ssi->current_visual, */
DefaultVisualOfScreen(screen),
si->passwd_dialog, cmap,
pw->background,
&pw->logo_pixels, &pw->logo_npixels,
&pw->logo_clipmask, True);
/* Before mapping the window, save the bits that are underneath the
rectangle the window will occlude. When we lower the window, we
restore these bits. This works, because the running screenhack
has already been sent SIGSTOP, so we know nothing else is drawing
right now! */
{
XGCValues gcv;
GC gc;
pw->save_under = XCreatePixmap (si->dpy,
pw->prompt_screen->screensaver_window,
pw->width + (pw->border_width*2) + 1,
pw->height + (pw->border_width*2) + 1,
pw->prompt_screen->current_depth);
gcv.function = GXcopy;
gc = XCreateGC (si->dpy, pw->save_under, GCFunction, &gcv);
XCopyArea (si->dpy, pw->prompt_screen->screensaver_window,
pw->save_under, gc,
pw->x - pw->border_width, pw->y - pw->border_width,
pw->width + (pw->border_width*2) + 1,
pw->height + (pw->border_width*2) + 1,
0, 0);
XFreeGC (si->dpy, gc);
}
XMapRaised (si->dpy, si->passwd_dialog);
XSync (si->dpy, False);
move_mouse_grab (si, si->passwd_dialog,
(pw->passwd_cursor
? pw->passwd_cursor
: pw->prompt_screen->cursor),
pw->prompt_screen->number);
undo_vp_motion (si);
/*mali si->pw_data = pw; */
if (cmap)
XInstallColormap (si->dpy, cmap);
draw_passwd_window (si);
XSync (si->dpy, False);
}
static void
draw_passwd_window (saver_info *si)
{
passwd_dialog_data *pw = si->pw_data;
XGCValues gcv;
GC gc1, gc2;
int spacing, height;
int x1, x2, x3, y1, y2;
int sw;
int tb_height;
if (si->prefs.verbose_p)
fprintf (stderr, "-->draw_passwd_window() case w_dialog!!\n");
height = (pw->heading_font->ascent + pw->heading_font->descent +
pw->body_font->ascent + pw->body_font->descent +
(2 * MAX ((pw->label_font->ascent + pw->label_font->descent),
(pw->passwd_font->ascent + pw->passwd_font->descent +
(pw->shadow_width * 4)))) +
pw->date_font->ascent + pw->date_font->descent);
if ((strlen(pw->uname_label)) && pw->show_uname_p)
height += (pw->uname_font->ascent + pw->uname_font->descent); /* for uname
*/
if (pw->login_button_p)
height += ((pw->button_font->ascent + pw->button_font->descent) * 2 +
2 * pw->shadow_width);
spacing = (((pw->height
- ((pw->login_button_p ? 4 : 2) * pw->shadow_width)
- pw->internal_border - height))
/ 8);
if (spacing < 0) spacing = 0;
gcv.foreground = pw->foreground;
gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
x1 = pw->logo_width + pw->thermo_width + (pw->shadow_width * 3);
x3 = pw->width - (pw->shadow_width * 2);
y1 = (pw->shadow_width * 2) + spacing + spacing;
/* top heading
*/
XSetFont (si->dpy, gc1, pw->heading_font->fid);
sw = string_width (pw->heading_font, pw->heading_label);
x2 = (x1 + ((x3 - x1 - sw) / 2));
y1 += spacing + pw->heading_font->ascent + pw->heading_font->descent;
XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
pw->heading_label, strlen(pw->heading_label));
/* uname below top heading
*/
if ((strlen(pw->uname_label)) && pw->show_uname_p)
{
XSetFont (si->dpy, gc1, pw->uname_font->fid);
y1 += spacing + pw->uname_font->ascent + pw->uname_font->descent;
sw = string_width (pw->uname_font, pw->uname_label);
x2 = (x1 + ((x3 - x1 - sw) / 2));
XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
pw->uname_label, strlen(pw->uname_label));
}
/* text below uname
*/
XSetFont (si->dpy, gc1, pw->body_font->fid);
y1 += spacing + pw->body_font->ascent + pw->body_font->descent;
sw = string_width (pw->body_font, pw->body_label);
x2 = (x1 + ((x3 - x1 - sw) / 2));
XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
pw->body_label, strlen(pw->body_label));
tb_height = (pw->passwd_font->ascent + pw->passwd_font->descent +
(pw->shadow_width * 4));
/* the "User:" prompt
*/
y1 += spacing;
y2 = y1;
XSetForeground (si->dpy, gc1, pw->foreground);
XSetFont (si->dpy, gc1, pw->label_font->fid);
y1 += (spacing + tb_height);
x2 = (x1 + pw->internal_border +
MAX(string_width (pw->label_font, pw->user_label),
string_width (pw->label_font, pw->passwd_label)));
XDrawString (si->dpy, si->passwd_dialog, gc1,
x2 - string_width (pw->label_font, pw->user_label),
y1 - pw->passwd_font->descent,
pw->user_label, strlen(pw->user_label));
/* the "Password:" prompt
*/
y1 += (spacing + tb_height);
XDrawString (si->dpy, si->passwd_dialog, gc1,
x2 - string_width (pw->label_font, pw->passwd_label),
y1 - pw->passwd_font->descent,
pw->passwd_label, strlen(pw->passwd_label));
XSetForeground (si->dpy, gc2, pw->passwd_background);
/* the "user name" text field
*/
y1 = y2;
XSetForeground (si->dpy, gc1, pw->passwd_foreground);
XSetFont (si->dpy, gc1, pw->passwd_font->fid);
y1 += (spacing + tb_height);
x2 += (pw->shadow_width * 4);
pw->passwd_field_width = x3 - x2 - pw->internal_border;
pw->passwd_field_height = (pw->passwd_font->ascent +
pw->passwd_font->descent +
pw->shadow_width);
XFillRectangle (si->dpy, si->passwd_dialog, gc2,
x2 - pw->shadow_width,
y1 - (pw->passwd_font->ascent + pw->passwd_font->descent),
pw->passwd_field_width, pw->passwd_field_height);
XDrawString (si->dpy, si->passwd_dialog, gc1,
x2,
y1 - pw->passwd_font->descent,
pw->user_string, strlen(pw->user_string));
/* the "password" text field
*/
y1 += (spacing + tb_height);
pw->passwd_field_x = x2 - pw->shadow_width;
pw->passwd_field_y = y1 - (pw->passwd_font->ascent +
pw->passwd_font->descent);
/* The shadow around the text fields
*/
y1 = y2;
y1 += (spacing + (pw->shadow_width * 3));
x1 = x2 - (pw->shadow_width * 2);
x2 = pw->passwd_field_width + (pw->shadow_width * 2);
y2 = pw->passwd_field_height + (pw->shadow_width * 2);
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
x1, y1, x2, y2,
pw->shadow_width,
pw->shadow_bottom, pw->shadow_top);
y1 += (spacing + pw->passwd_font->ascent + pw->passwd_font->descent +
(pw->shadow_width * 4));
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
x1, y1, x2, y2,
pw->shadow_width,
pw->shadow_bottom, pw->shadow_top);
/* The date, below the text fields
*/
{
char buf[100];
time_t now = time ((time_t *) 0);
struct tm *tm = localtime (&now);
memset (buf, 0, sizeof(buf));
strftime (buf, sizeof(buf)-1, pw->date_label, tm);
XSetFont (si->dpy, gc1, pw->date_font->fid);
y1 += pw->shadow_width;
y1 += (spacing + tb_height);
y1 += spacing/2;
sw = string_width (pw->date_font, buf);
x2 = x1 + x2 - sw;
XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1, buf, strlen(buf));
}
/* The "New Login" button
*/
if (pw->login_button_p)
{
XSetForeground (si->dpy, gc1, pw->button_foreground);
XSetForeground (si->dpy, gc2, pw->button_background);
XSetFont (si->dpy, gc1, pw->button_font->fid);
sw = string_width (pw->button_font, pw->login_label);
x2 = pw->width - pw->internal_border - (pw->shadow_width * 2);
/* right aligned button */
/* x1 = x2 - pw->login_button_width; */
/* centered button */
x1 = (pw->logo_width + pw->thermo_width + (pw->shadow_width * 3) +
pw->internal_border);
x1 = x1 + (x2 - x1 - pw->login_button_width) / 2;
y1 = (pw->height - pw->internal_border - pw->login_button_height +
spacing);
y2 = (y1 +
((pw->login_button_height -
(pw->button_font->ascent + pw->button_font->descent))
/ 2) +
pw->button_font->ascent);
pw->login_button_x = x1;
pw->login_button_y = y1;
}
/* The logo
*/
x1 = pw->shadow_width * 6;
y1 = pw->shadow_width * 6;
x2 = pw->logo_width - (pw->shadow_width * 12);
y2 = pw->logo_height - (pw->shadow_width * 12);
if (pw->logo_pixmap)
{
Window root;
int x, y;
unsigned int w, h, bw, d;
XGetGeometry (si->dpy, pw->logo_pixmap, &root, &x, &y, &w, &h, &bw, &d);
XSetForeground (si->dpy, gc1, pw->foreground);
XSetBackground (si->dpy, gc1, pw->background);
XSetClipMask (si->dpy, gc1, pw->logo_clipmask);
XSetClipOrigin (si->dpy, gc1, x1 + ((x2 - (int)w) / 2), y1 + ((y2 -
(int)h) / 2));
if (d == 1)
XCopyPlane (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
0, 0, w, h,
x1 + ((x2 - (int)w) / 2),
y1 + ((y2 - (int)h) / 2),
1);
else
XCopyArea (si->dpy, pw->logo_pixmap, si->passwd_dialog, gc1,
0, 0, w, h,
x1 + ((x2 - (int)w) / 2),
y1 + ((y2 - (int)h) / 2));
}
/* The thermometer
*/
XSetForeground (si->dpy, gc1, pw->thermo_foreground);
XSetForeground (si->dpy, gc2, pw->thermo_background);
pw->thermo_field_x = pw->logo_width + pw->shadow_width;
pw->thermo_field_y = pw->shadow_width * 5;
pw->thermo_field_height = pw->height - (pw->shadow_width * 10);
#if 0
/* Solid border inside the logo box. */
XSetForeground (si->dpy, gc1, pw->foreground);
XDrawRectangle (si->dpy, si->passwd_dialog, gc1, x1, y1, x2-1, y2-1);
#endif
/* The shadow around the logo
*/
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
pw->shadow_width * 4,
pw->shadow_width * 4,
pw->logo_width - (pw->shadow_width * 8),
pw->logo_height - (pw->shadow_width * 8),
pw->shadow_width,
pw->shadow_bottom, pw->shadow_top);
/* The shadow around the thermometer
*/
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
pw->logo_width,
pw->shadow_width * 4,
pw->thermo_width + (pw->shadow_width * 2),
pw->height - (pw->shadow_width * 8),
pw->shadow_width,
pw->shadow_bottom, pw->shadow_top);
#if 1
/* Solid border inside the thermometer. */
XSetForeground (si->dpy, gc1, pw->foreground);
XDrawRectangle (si->dpy, si->passwd_dialog, gc1,
pw->thermo_field_x, pw->thermo_field_y,
pw->thermo_width - 1, pw->thermo_field_height - 1);
#endif
/* The shadow around the whole window
*/
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
0, 0, pw->width, pw->height, pw->shadow_width,
pw->shadow_top, pw->shadow_bottom);
XFreeGC (si->dpy, gc1);
XFreeGC (si->dpy, gc2);
update_passwd_window (si, pw->passwd_string, pw->ratio);
}
void
update_passwd_window (saver_info *si, const char *printed_passwd, float ratio)
{
passwd_dialog_data *pw = si->pw_data;
XGCValues gcv;
GC gc1, gc2;
int x, y;
XRectangle rects[1];
pw->ratio = ratio;
if (si->prefs.verbose_p)
fprintf (stderr, "-->update_passwd_window() w_dialog !!\n");
if (!si->pw_data->got_windowid )
{
if (si->prefs.verbose_p)
fprintf (stderr, "-->update_passwd_window() lockdialog not created
returning.. !!\n");
return;
}
gcv.foreground = pw->passwd_foreground;
if (pw->passwd_font)
gcv.font = pw->passwd_font->fid;
gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground|GCFont, &gcv);
gcv.foreground = pw->passwd_background;
gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
if (printed_passwd)
{
char *s = strdup (printed_passwd);
if (pw->passwd_string) free (pw->passwd_string);
pw->passwd_string = s;
}
/* the "password" text field
*/
rects[0].x = pw->passwd_field_x;
rects[0].y = pw->passwd_field_y;
rects[0].width = pw->passwd_field_width;
rects[0].height = pw->passwd_field_height;
XFillRectangle (si->dpy, si->passwd_dialog, gc2,
rects[0].x, rects[0].y, rects[0].width, rects[0].height);
XSetClipRectangles (si->dpy, gc1, 0, 0, rects, 1, Unsorted);
XDrawString (si->dpy, si->passwd_dialog, gc1,
rects[0].x + pw->shadow_width,
rects[0].y + pw->passwd_font->ascent,
pw->passwd_string, strlen(pw->passwd_string));
XSetClipMask (si->dpy, gc1, None);
/* The I-beam
*/
if (pw->i_beam != 0)
{
x = (rects[0].x + pw->shadow_width +
string_width (pw->passwd_font, pw->passwd_string));
y = rects[0].y + pw->shadow_width;
if (x > rects[0].x + rects[0].width - 1)
x = rects[0].x + rects[0].width - 1;
XDrawLine (si->dpy, si->passwd_dialog, gc1,
x, y,
x, y + pw->passwd_font->ascent + pw->passwd_font->descent-1);
}
pw->i_beam = (pw->i_beam + 1) % 4;
/* the thermometer
*/
y = (pw->thermo_field_height - 2) * (1.0 - pw->ratio);
if (y > 0)
{
XFillRectangle (si->dpy, si->passwd_dialog, gc2,
pw->thermo_field_x + 1,
pw->thermo_field_y + 1,
pw->thermo_width-2,
y);
XSetForeground (si->dpy, gc1, pw->thermo_foreground);
XFillRectangle (si->dpy, si->passwd_dialog, gc1,
pw->thermo_field_x + 1,
pw->thermo_field_y + 1 + y,
pw->thermo_width-2,
MAX (0, pw->thermo_field_height - y - 2));
}
/* The "New Login" button
*/
if (pw->login_button_p)
{
int x2, y2, sw;
XSetFont (si->dpy, gc1, pw->button_font->fid);
XSetForeground (si->dpy, gc1,
(pw->login_button_enabled_p
? pw->passwd_foreground
: pw->shadow_bottom));
XSetForeground (si->dpy, gc2, pw->button_background);
XFillRectangle (si->dpy, si->passwd_dialog, gc2,
pw->login_button_x, pw->login_button_y,
pw->login_button_width, pw->login_button_height);
sw = string_width (pw->button_font, pw->login_label);
x2 = pw->login_button_x + ((pw->login_button_width - sw) / 2);
y2 = (pw->login_button_y +
((pw->login_button_height -
(pw->button_font->ascent + pw->button_font->descent))
/ 2) +
pw->button_font->ascent);
XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y2,
pw->login_label, strlen(pw->login_label));
draw_shaded_rectangle (si->dpy, si->passwd_dialog,
pw->login_button_x, pw->login_button_y,
pw->login_button_width, pw->login_button_height,
pw->shadow_width,
(pw->login_button_down_p
? pw->shadow_bottom
: pw->shadow_top),
(pw->login_button_down_p
? pw->shadow_top
: pw->shadow_bottom));
}
XFreeGC (si->dpy, gc1);
XFreeGC (si->dpy, gc2);
XSync (si->dpy, False);
}
void
destroy_passwd_window (saver_info *si)
{
saver_preferences *p = &si->prefs;
passwd_dialog_data *pw = si->pw_data;
saver_screen_info *ssi;
Colormap cmap;
Pixel black, white;
XEvent event;
/* CR5083155 [Cinn Solaris]Unable to unlock screen when running dual-head MAG
*/
int j;
XSetWindowAttributes setwinattr;
unsigned long valuemask = CWOverrideRedirect;
XWindowChanges changes;
setwinattr.override_redirect = FALSE;
if (si->prefs.verbose_p)
fprintf (stderr, "destroy_passwd_window\n");
/*reset global flag to indicate passwd dialog is no longer there*/
g_passwd_dialog_created = 0;
if (pw == NULL || si->external_passwd == 0)
return;
if (pw->timer)
XtRemoveTimeOut (pw->timer);
#ifdef HAVE_XSCREENSAVER_LOCK
if (si->external_passwd)
{
/* kill the child etc. */
if (si->passwd_dialog)
{
XErrorHandler old_handler;
XSync (si->dpy, False);
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
XDestroyWindow (si->dpy, si->passwd_dialog);
XSync (si->dpy, False);
XSetErrorHandler (old_handler);
si->passwd_dialog = 0;
}
if (pw->stdout_input_id)
XtRemoveInput (pw->stdout_input_id);
if (pw->stdin_fd != -1)
close_and_invalidate (&pw->stdin_fd);
if (pw->input_file)
fclose (pw->input_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;
}
si->external_passwd = False;
si->at_external_passwd = False;
}
else
#endif /* HAVE_XSCREENSAVER_LOCK */
{
if (p->verbose_p)
fprintf (stderr, "In destroy_passwd else case..i.e. si->external-passwd is
False already\n");
memset (pw->typed_passwd, 0, sizeof(pw->typed_passwd));
memset (pw->passwd_string, 0, strlen(pw->passwd_string));
ssi = pw->prompt_screen;
cmap = DefaultColormapOfScreen (ssi->screen);
black = BlackPixelOfScreen (ssi->screen);
white = WhitePixelOfScreen (ssi->screen);
move_mouse_grab (si, RootWindowOfScreen (ssi->screen),
ssi->cursor, ssi->number);
if (pw->passwd_cursor)
XFreeCursor (si->dpy, pw->passwd_cursor);
if (p->verbose_p)
fprintf (stderr, "%s: %d: moving mouse back to %d,%d.\n",
blurb(), ssi->number,
pw->previous_mouse_x, pw->previous_mouse_y);
XWarpPointer (si->dpy, None, RootWindowOfScreen (ssi->screen),
0, 0, 0, 0,
pw->previous_mouse_x, pw->previous_mouse_y);
XSync (si->dpy, False);
while (XCheckMaskEvent (si->dpy, PointerMotionMask, &event))
if (p->verbose_p)
fprintf (stderr, "%s: discarding MotionNotify event.\n", blurb());
if (si->passwd_dialog)
{
XDestroyWindow (si->dpy, si->passwd_dialog);
si->passwd_dialog = 0;
}
if (pw->save_under)
{
XGCValues gcv;
GC gc;
gcv.function = GXcopy;
gc = XCreateGC (si->dpy, ssi->screensaver_window, GCFunction, &gcv);
XCopyArea (si->dpy, pw->save_under,
ssi->screensaver_window, gc,
0, 0,
pw->width + (pw->border_width*2) + 1,
pw->height + (pw->border_width*2) + 1,
pw->x - pw->border_width, pw->y - pw->border_width);
XFreePixmap (si->dpy, pw->save_under);
pw->save_under = 0;
XFreeGC (si->dpy, gc);
}
if (pw->heading_label) free (pw->heading_label);
if (pw->body_label) free (pw->body_label);
if (pw->user_label) free (pw->user_label);
if (pw->passwd_label) free (pw->passwd_label);
if (pw->date_label) free (pw->date_label);
if (pw->login_label) free (pw->login_label);
if (pw->user_string) free (pw->user_string);
if (pw->passwd_string) free (pw->passwd_string);
if (pw->uname_label) free (pw->uname_label);
if (pw->heading_font) XFreeFont (si->dpy, pw->heading_font);
if (pw->body_font) XFreeFont (si->dpy, pw->body_font);
if (pw->label_font) XFreeFont (si->dpy, pw->label_font);
if (pw->passwd_font) XFreeFont (si->dpy, pw->passwd_font);
if (pw->date_font) XFreeFont (si->dpy, pw->date_font);
if (pw->button_font) XFreeFont (si->dpy, pw->button_font);
if (pw->uname_font) XFreeFont (si->dpy, pw->uname_font);
if (pw->foreground != black && pw->foreground != white)
XFreeColors (si->dpy, cmap, &pw->foreground, 1, 0L);
if (pw->background != black && pw->background != white)
XFreeColors (si->dpy, cmap, &pw->background, 1, 0L);
if (!(pw->button_foreground == black || pw->button_foreground == white))
XFreeColors (si->dpy, cmap, &pw->button_foreground, 1, 0L);
if (!(pw->button_background == black || pw->button_background == white))
XFreeColors (si->dpy, cmap, &pw->button_background, 1, 0L);
if (pw->passwd_foreground != black && pw->passwd_foreground != white)
XFreeColors (si->dpy, cmap, &pw->passwd_foreground, 1, 0L);
if (pw->passwd_background != black && pw->passwd_background != white)
XFreeColors (si->dpy, cmap, &pw->passwd_background, 1, 0L);
if (pw->thermo_foreground != black && pw->thermo_foreground != white)
XFreeColors (si->dpy, cmap, &pw->thermo_foreground, 1, 0L);
if (pw->thermo_background != black && pw->thermo_background != white)
XFreeColors (si->dpy, cmap, &pw->thermo_background, 1, 0L);
if (pw->shadow_top != black && pw->shadow_top != white)
XFreeColors (si->dpy, cmap, &pw->shadow_top, 1, 0L);
if (pw->shadow_bottom != black && pw->shadow_bottom != white)
XFreeColors (si->dpy, cmap, &pw->shadow_bottom, 1, 0L);
if (pw->logo_pixmap)
XFreePixmap (si->dpy, pw->logo_pixmap);
if (pw-> logo_clipmask)
XFreePixmap (si->dpy, pw->logo_clipmask);
if (pw->logo_pixels)
{
if (pw->logo_npixels)
XFreeColors (si->dpy, cmap, pw->logo_pixels, pw->logo_npixels, 0L);
free (pw->logo_pixels);
pw->logo_pixels = 0;
pw->logo_npixels = 0;
}
if (pw->save_under)
XFreePixmap (si->dpy, pw->save_under);
if (cmap)
XInstallColormap (si->dpy, cmap);
}
memset (pw, 0, sizeof(*pw));
/*** NO mali99 we only create a copy of pw in main and keep it
so dont free it.
free (pw);
si->pw_data = 0;
************/
for (j= 1; j < 3 ; j++)
{
if (winatt_reset[j-1] && at_win[j] )
{
XChangeWindowAttributes(si->dpy,at_win[j],valuemask,&setwinattr);
winatt_reset[j-1] = FALSE;
at_win[j] = 0;
/*fprintf(stderr, "DEBUG: at(%d) override_redirect set to FALSE\n", j);
*/
}
}
/*
** restore the prev one
** 6520014(P3) mem. leak in lock.c
*/
if ( client && globalkey_text)
gconf_client_set_string ( client, \
"/apps/metacity/global_keybindings/switch_windows", \
globalkey_text, NULL);
g_free(globalkey_text);
globalkey_text = NULL;
/*
** 6736157 A11Y]Security problem when desktop a11y support is turned on
*/
if ( client && globalmenu_key)
gconf_client_set_string ( client, \
"/apps/metacity/global_keybindings/panel_main_menu", \
globalmenu_key, NULL);
g_free(globalmenu_key);
globalmenu_key = NULL;
}
static Bool error_handler_hit_p = False;
static int
ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
{
error_handler_hit_p = True;
return 0;
}
#ifdef HAVE_XHPDISABLERESET
/* This function enables and disables the C-Sh-Reset hot-key, which
normally resets the X server (logging out the logged-in user.)
We don't want random people to be able to do that while the
screen is locked.
*/
static void
hp_lock_reset (saver_info *si, Bool lock_p)
{
static Bool hp_locked_p = False;
/* Calls to XHPDisableReset and XHPEnableReset must be balanced,
or BadAccess errors occur. (It's ok for this to be global,
since it affects the whole machine, not just the current screen.)
*/
if (hp_locked_p == lock_p)
return;
if (lock_p)
XHPDisableReset (si->dpy);
else
XHPEnableReset (si->dpy);
hp_locked_p = lock_p;
}
#endif /* HAVE_XHPDISABLERESET */
#ifdef HAVE_XF86MISCSETGRABKEYSSTATE
/* This function enables and disables the Ctrl-Alt-KP_star and
Ctrl-Alt-KP_slash hot-keys, which (in XFree86 4.2) break any
grabs and/or kill the grabbing client. That would effectively
unlock the screen, so we don't like that.
The Ctrl-Alt-KP_star and Ctrl-Alt-KP_slash hot-keys only exist
if AllowDeactivateGrabs and/or AllowClosedownGrabs are turned on
in XF86Config. I believe they are disabled by default.
This does not affect any other keys (specifically Ctrl-Alt-BS or
Ctrl-Alt-F1) but I wish it did. Maybe it will someday.
*/
static void
xfree_lock_grab_smasher (saver_info *si, Bool lock_p)
{
saver_preferences *p = &si->prefs;
int status;
int event, error;
if (!XF86MiscQueryExtension(si->dpy, &event, &error))
return;
XErrorHandler old_handler;
XSync (si->dpy, False);
error_handler_hit_p = False;
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
XSync (si->dpy, False);
status = XF86MiscSetGrabKeysState (si->dpy, !lock_p);
XSync (si->dpy, False);
if (error_handler_hit_p) status = 666;
if (!lock_p && status == MiscExtGrabStateAlready)
status = MiscExtGrabStateSuccess; /* shut up, consider this success */
if (p->verbose_p && status != MiscExtGrabStateSuccess)
fprintf (stderr, "%s: error: XF86MiscSetGrabKeysState(%d) returned %s\n",
blurb(), !lock_p,
(status == MiscExtGrabStateSuccess ? "MiscExtGrabStateSuccess" :
status == MiscExtGrabStateLocked ? "MiscExtGrabStateLocked" :
status == MiscExtGrabStateAlready ? "MiscExtGrabStateAlready" :
status == 666 ? "an X error" :
"unknown value"));
XSync (si->dpy, False);
XSetErrorHandler (old_handler);
XSync (si->dpy, False);
}
#endif /* HAVE_XF86MISCSETGRABKEYSSTATE */
/* This function enables and disables the C-Alt-Plus and C-Alt-Minus
hot-keys, which normally change the resolution of the X server.
We don't want people to be able to switch the server resolution
while the screen is locked, because if they switch to a higher
resolution, it could cause part of the underlying desktop to become
exposed.
*/
#ifdef HAVE_XF86VMODE
static void
xfree_lock_mode_switch (saver_info *si, Bool lock_p)
{
static Bool any_mode_locked_p = False;
saver_preferences *p = &si->prefs;
int screen;
int event, error;
Bool status;
XErrorHandler old_handler;
if (any_mode_locked_p == lock_p)
return;
if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
return;
for (screen = 0; screen < (si->xinerama_p ? 1 : si->nscreens); screen++)
{
XSync (si->dpy, False);
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
error_handler_hit_p = False;
status = XF86VidModeLockModeSwitch (si->dpy, screen, lock_p);
XSync (si->dpy, False);
XSetErrorHandler (old_handler);
if (error_handler_hit_p) status = False;
if (status)
any_mode_locked_p = lock_p;
if (!status && (p->verbose_p || !lock_p))
/* Only print this when verbose, or when we locked but can't unlock.
I tried printing this message whenever it comes up, but
mode-locking always fails if DontZoom is set in XF86Config. */
fprintf (stderr, "%s: %d: unable to %s mode switching!\n",
blurb(), screen, (lock_p ? "lock" : "unlock"));
else if (p->verbose_p)
fprintf (stderr, "%s: %d: %s mode switching.\n",
blurb(), screen, (lock_p ? "locked" : "unlocked"));
}
}
#endif /* HAVE_XF86VMODE */
/* If the viewport has been scrolled since the screen was blanked,
then scroll it back to where it belongs. This function only exists
to patch over a very brief race condition.
*/
static void
undo_vp_motion (saver_info *si)
{
#ifdef HAVE_XF86VMODE
saver_preferences *p = &si->prefs;
int screen;
int event, error;
if (!XF86VidModeQueryExtension (si->dpy, &event, &error))
return;
for (screen = 0; screen < si->nscreens; screen++)
{
saver_screen_info *ssi = &si->screens[screen];
int x, y;
Bool status;
if (ssi->blank_vp_x == -1 && ssi->blank_vp_y == -1)
break;
if (!XF86VidModeGetViewPort (si->dpy, screen, &x, &y))
return;
if (ssi->blank_vp_x == x && ssi->blank_vp_y == y)
return;
/* We're going to move the viewport. The mouse has just been grabbed on
(and constrained to, thus warped to) the password window, so it is no
longer near the edge of the screen. However, wait a bit anyway, just
to make sure the server drains its last motion event, so that the
screen doesn't continue to scroll after we've reset the viewport.
*/
XSync (si->dpy, False);
usleep (250000); /* 1/4 second */
XSync (si->dpy, False);
status = XF86VidModeSetViewPort (si->dpy, screen,
ssi->blank_vp_x, ssi->blank_vp_y);
if (!status)
fprintf (stderr,
"%s: %d: unable to move vp from (%d,%d) back to (%d,%d)!\n",
blurb(), screen, x, y, ssi->blank_vp_x, ssi->blank_vp_y);
else if (p->verbose_p)
fprintf (stderr,
"%s: %d: vp moved to (%d,%d); moved it back to (%d,%d).\n",
blurb(), screen, x, y, ssi->blank_vp_x, ssi->blank_vp_y);
}
#endif /* HAVE_XF86VMODE */
}
/* Interactions
*/
static void
passwd_animate_timer (XtPointer closure, XtIntervalId *id)
{
saver_info *si = (saver_info *) closure;
int tick = 166;
passwd_dialog_data *pw = si->pw_data;
/* if (si->prefs.verbose_p)
fprintf (stderr,"-->passwd_animate_timer()\n");
**/
/*We want to make sure dialog isup before we try to animate**/
if (!si->external_passwd || !g_passwd_dialog_created)
{
if (si->prefs.verbose_p)
fprintf (stderr,"-->passwd_animate_timer() returning..no dialog yet\n");
return;
}
pw->ratio -= (1.0 / ((double) si->prefs.passwd_timeout / (double) tick));
if (pw->ratio < 0)
{
pw->ratio = 0;
if (pw->state == pw_read || pw->state == pw_null)
{
pw->state = pw_time;
}
}
/*** Communicating with the Child lock dialog...sending ratio back... mali99***/
#ifdef HAVE_XSCREENSAVER_LOCK
if (si->passwd_dialog)
{
XEvent event;
Bool status;
XErrorHandler old_handler;
/* fprintf (stderr,"-->passwd_animate_timer() sending ratio to child\n");
**/
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;
/* CR 6176524 passwdTimeoutEnable for disabled user */
if (!si->prefs.pwd_p)
event.xclient.data.l[1] = 1;
XSync (si->dpy, False);
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
status = XSendEvent (si->dpy, si->passwd_dialog, False, 0L, &event);
XSync (si->dpy, False);
XSetErrorHandler (old_handler);
if (!status)
fprintf (stderr, "%s: error sending ratio to lock dialog\n", blurb ());
}
#else /* !HAVE_XSCREENSAVER_LOCK */
update_passwd_window (si, 0, pw->ratio);
#endif /* !HAVE_XSCREENSAVER_LOCK */
if (pw->state == pw_read)
pw->timer = XtAppAddTimeOut (si->app, tick, passwd_animate_timer,
(XtPointer) si);
else
pw->timer = 0;
idle_timer ((XtPointer) si, 0);
}
static XComposeStatus *compose_status;
static void
handle_passwd_button (saver_info *si, XEvent *event)
{
saver_preferences *p = &si->prefs;
Bool mouse_in_box = False;
Bool hit_p = False;
passwd_dialog_data *pw = si->pw_data;
saver_screen_info *ssi = pw->prompt_screen;
if (! pw->login_button_enabled_p)
return;
mouse_in_box =
(event->xbutton.x >= pw->login_button_x &&
event->xbutton.x <= pw->login_button_x + pw->login_button_width &&
event->xbutton.y >= pw->login_button_y &&
event->xbutton.y <= pw->login_button_y + pw->login_button_height);
if (ButtonRelease == event->xany.type &&
pw->login_button_down_p &&
mouse_in_box)
{
/* Only allow them to press the button once: don't want to
accidentally launch a dozen gdm choosers if the machine
is being slow.
*/
hit_p = True;
pw->login_button_enabled_p = False;
}
pw->login_button_down_p = (mouse_in_box &&
ButtonRelease != event->xany.type);
update_passwd_window (si, 0, pw->ratio);
if (hit_p)
fork_and_exec (ssi, p->new_login_command);
}
static void
handle_passwd_key (saver_info *si, XKeyEvent *event)
{
saver_preferences *p = &si->prefs;
passwd_dialog_data *pw = si->pw_data;
int pw_size = sizeof (pw->typed_passwd) - 1;
char *typed_passwd = pw->typed_passwd;
char s[2];
char *stars = 0;
int i;
int size = XLookupString (event, s, 1, 0, compose_status);
if (size != 1) return;
s[1] = 0;
/* Add 10% to the time remaining every time a key is pressed. */
pw->ratio += 0.1;
if (pw->ratio > 1) pw->ratio = 1;
switch (*s)
{
case '\010': case '\177': /* Backspace */
if (!*typed_passwd)
XBell (si->dpy, 0);
else
typed_passwd [strlen(typed_passwd)-1] = 0;
break;
case '\025': case '\030': /* Erase line */
memset (typed_passwd, 0, pw_size);
break;
case '\012': case '\015': /* Enter */
if (pw->state != pw_read)
; /* already done? */
else if (typed_passwd[0] == 0)
pw->state = pw_null;
else
{
update_passwd_window (si, "Checking...", pw->ratio);
XSync (si->dpy, False);
/***************mali99************************************************
if (passwd_valid_p (typed_passwd, p->verbose_p, PAM_SERVICE))
pw->state = pw_ok;
else
pw->state = pw_fail;
update_passwd_window (si, "", pw->ratio);
****************************************************************************/
pw->state = pw_ok;
}
break;
default:
/* Though technically the only illegal characters in Unix passwords
are LF and NUL, most GUI programs (e.g., GDM) use regular text-entry
fields that only let you type printable characters. So, people
who use funky characters in their passwords are already broken.
We follow that precedent.
*/
if (isprint ((unsigned char) *s))
{
i = strlen (typed_passwd);
if (i >= pw_size-1)
XBell (si->dpy, 0);
else
{
typed_passwd [i] = *s;
typed_passwd [i+1] = 0;
}
}
else
XBell (si->dpy, 0);
break;
}
if (pw->show_stars_p)
{
i = strlen(typed_passwd);
stars = (char *) malloc(i+1);
memset (stars, '*', i);
stars[i] = 0;
update_passwd_window (si, stars, pw->ratio);
free (stars);
}
else
{
update_passwd_window (si, "", pw->ratio);
}
}
void XTSOLMakeTPWindow(Display *, Window);
void
passwd_event_loop (saver_info *si)
{
saver_preferences *p = &si->prefs;
char *msg = 0;
XEvent event;
unsigned int caps_p = 0;
passwd_dialog_data *pw = si->pw_data;
int ii;
Window w;
int mscreen;
int status = -2;
int counter = 0;
int retries = 2;
/*bugid 6580862 Unable to type in windows session with full screen mode when
hotdesked...
The issue is sunray connector grabs keyboard and focus is in connector
window. When xscreensaver
pastes the unlock dialog box the password typed by user goes into connector
window.
The following code attempts to set focus back in unlock dialog box. The
connector is looking
for focus out events to get a hint to let go of keyboard grab. Which is
exactly what we try to
do in the following code.
*/
write_to_child (si, "pw_read");
mscreen = mouse_screen (si);
w = RootWindowOfScreen(si->screens[mscreen].screen);
/* grab_kbd() uses GrabModeSync which is holding up pointer events and hence
unlcok
* dialog box does not show up when you move mouse, only when you hit a key.
* So, we locally call XGrabKeyboard() with GrabModeAsync instead of calling
grab_kbd().
* status = grab_kbd(si, w, mscreen);
**/
status = XGrabKeyboard (si->dpy, w, True,
GrabModeAsync, GrabModeAsync,
CurrentTime);
XSync (si->dpy, False);
while (status != GrabSuccess && counter++ <=retries)
{
status = XGrabKeyboard (si->dpy, w, True,
GrabModeAsync, GrabModeAsync,
CurrentTime);
write_to_child (si, "pw_read");
usleep (250000); /** 1/4 second */
XSync (si->dpy, False);
XTSOLMakeTPWindow(si->dpy,w);
if(p->verbose_p)
fprintf (stderr, "event loop..trying to grab keyboard######\n");
}
if (status == GrabSuccess)
{
si->keyboard_grab_window = w;
si->keyboard_grab_screen = mscreen;
}
/* bugid 6176524 passwdTimeout and reset timer for each key press */
passwd_animate_timer ((XtPointer) si, 0);
while (si->pw_data && si->pw_data->state == pw_read)
{
XtAppNextEvent (si->app, &event);
#ifdef HAVE_RANDR
/*
* 6757448 xscreensaver doesn't notice XRandR resize events.
*/
if (event.type == (si->randr_event_number + RRScreenChangeNotify))
{
/* The Resize and Rotate extension sends an event when the
size, rotation, or refresh rate of the screen has changed. */
XRRScreenChangeNotifyEvent *xrr_event =
(XRRScreenChangeNotifyEvent *) &event;
/* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */
int screen = XRRRootToScreen (si->dpy, xrr_event->window);
if (p->verbose_p)
{
if (si->screens[screen].width == xrr_event->width &&
si->screens[screen].height == xrr_event->height)
fprintf (stderr,
"%s: %d: no-op screen size change event (%dx%d)\n",
blurb(), screen,
xrr_event->width, xrr_event->height);
else
fprintf (stderr,
"%s: %d: screen size changed from %dx%d to %dx%d\n",
blurb(), screen,
si->screens[screen].width,
si->screens[screen].height,
xrr_event->width, xrr_event->height);
}
# ifdef RRScreenChangeNotifyMask
/* Inform Xlib that it's ok to update its data structures. */
XRRUpdateConfiguration (&event); /* Xrandr.h 1.9, 2002/09/29 */
# endif /* RRScreenChangeNotifyMask */
/* Resize the existing xscreensaver windows and cached ssi data. */
resize_screensaver_window (si);
}
#endif /* HAVE_RANDR */
#ifdef HAVE_XSCREENSAVER_LOCK
if (event.xany.type == KeyPress)
{
if (si->pw_data->got_windowid)
{
Bool status,pwd_status;
XErrorHandler old_handler;
if(p->verbose_p)
fprintf (stderr, "event loop..gotwindowid..and keypress
event...\n");
event.xany.window = si->passwd_dialog;
XSync (si->dpy, False);
old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
status =
XSendEvent (si->dpy, si->passwd_dialog, False, KeyPressMask, &event);
XSync (si->dpy, False);
XSetErrorHandler (old_handler);
/* CR 6176524 passwdTimeoutEnable for disabled user
timer will be reset if 4 conditions art true (for each char of pwd)
(status) && (p->pwd_p) && (at_enabled) && (pw->timer)
However AT group wants to remove at_enabled
i.e reset the password timer for each key for all users
* 6240938 screensaver-lock's password timer needs to to be reset
for each key (all users) and enabling AT support
*/
if ((status) && (p->pwd_p) && (pw->timer)) {
XtRemoveTimeOut (pw->timer);
pw->ratio = 1.0;
pw->timer = XtAppAddTimeOut (si->app, 166, passwd_animate_timer,
(XtPointer) si);
}
if (p->verbose_p)
{
if (status)
fprintf (stderr, "sent key...\n");
else
fprintf (stderr, "error sending key...\n");
}
}
else
{
if (p->verbose_p)
fprintf (stderr, "got keypress but no window id yet :(\n");
XtDispatchEvent (&event);
}
}
#else /* !HAVE_XSCREENSAVER_LOCK */
if (event.xany.window == si->passwd_dialog && event.xany.type == Expose)
draw_passwd_window (si);
else if (event.xany.type == KeyPress)
{
handle_passwd_key (si, &event.xkey);
caps_p = (event.xkey.state & LockMask);
}
else if ((event.xany.type == ButtonPress ||
event.xany.type == ButtonRelease) &&
si->pw_data->login_button_p)
handle_passwd_button (si, &event);
#endif /* !HAVE_XSCREENSAVER_LOCK */
else if (event.xany.window == si->passwd_dialog && event.xany.type ==
Expose &&
si->pw_data->passwd_label != NULL)
{
if(p->verbose_p)
fprintf (stderr, "event loop...and expose event.should update lock
with new label...\n");
/***if (si->pw_data->passwd_label)**/
update_passwd_window (si, si->pw_data->passwd_label, pw->ratio);
free (si->pw_data->passwd_label);
si->pw_data->passwd_label = 0;
si->pw_data->state = pw_read;
}
/*
* 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
Also this routine is to stop the popup window when a11y is on also when
a11y is not on.
Note: when a11y is on no_atserv > 0
*/
else if (((event.type == UnmapNotify)
|| (event.type == MapNotify )
|| (event.type == VisibilityNotify)
|| (event.type == ConfigureNotify)
|| (event.type == PropertyNotify )
|| (event.type == CreateNotify)
|| (event.type == ReparentNotify ))
&& (si->passwd_dialog) )
{
/* AT_LOCK_DEBUG
fprintf (stderr, "client window(0x%x) %s\n", event.xclient.window,blurb());
fprintf (stderr, "dialog window 0x%x:\n", si->passwd_dialog);
fprintf(stderr, "** no_atserv: %d \n", no_atserv);
for (ii = 0; ii < 4; ii++)
fprintf(stderr, "** win : 0x%x \n", at_win[ii]);
*/
/* this if case is for safety,it prevent screensaver stuck in loop of
ConfigureNotify */
if(event.xany.window && (event.xany.window !=
si->screens[0].screensaver_window) && (event.xany.window != 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.type)
{
case ConfigureNotify:
wPopWin = event.xconfigure.window;
break;
case CreateNotify:
wPopWin = event.xcreatewindow.window;
break;
case VisibilityNotify:
wPopWin = event.xvisibility.window;
break;
default:
break;
}
/* Array at_win stores password and screensaver window, also MAG
and/or GOK if a11y is on
/* if any window apart from password, MAG ,GOK or screensaver
comes over is considered as popup window. */
/* If it is not popup window but password, MAG, GOK, or
screensaver window then nWin < no_atserv+2 */
/* If it is popup window then nWin == no_atserv+2 */
int nWin =0;
if(wPopWin) // check if it is really a popup window
for(;nWin < no_atserv+2 ; ++nWin)
{
if(at_win[nWin]==wPopWin)
break;
}
/* Do restacking if it is popup window ie nWin == no_atserv+2 */
/* Also do restacking when a11y is on */
if( nWin== no_atserv+2 ||no_atserv )
{
/* at_win[0] -> passwordwindow */
/* at_win[1-2]-> if a11y on, may GOK or MAG */
at_win[no_atserv+1] = si->screens[0].screensaver_window;
if(nWin== no_atserv+2)
{
/* store popup window in array of at_win to restack it */
at_win[no_atserv+2] = wPopWin;
XRestackWindows(si->dpy, at_win,no_atserv+3);
}
else
{
XRestackWindows(si->dpy, at_win,no_atserv+2);
}
XFlush(si->dpy);
}
}
}
/* the above new code for restacking under the conidtion
*/
else
{
/*
if ((si->passwd_dialog) && (no_atserv) && (event.type != 0))
fprintf(stderr, "** DEbug other event %d\n", event.type);
*/
XtDispatchEvent (&event);
}
}
switch (si->pw_data->state)
{
case pw_ok: msg = strdup("pw_ok"); break;
case pw_null: msg = strdup("pw_null"); break;
case pw_time: msg = strdup("pw_time"); break;
case pw_read: msg = strdup("pw_read"); break;
case pw_fail: msg = strdup("pw_fail"); break;
case pw_cancel: msg = strdup("pw_cancel"); break;
default: msg = 0;
fprintf(stderr, "si->pw_data->state is bad, serious error\n");
break;
}
if (si->pw_data->state == pw_fail)
si->unlock_failures++;
if (p->verbose_p)
switch (si->pw_data->state)
{
case pw_ok:
{
fprintf (stderr, "%s: password correct.\n", blurb());
fprintf (stderr, "%s: setting state to be null.\n", blurb());
si->pw_data->state = pw_null;
break;
}
case pw_fail:
fprintf (stderr, "%s: password incorrect!%s\n", blurb(),
(caps_p ? " (CapsLock)" : ""));
break;
case pw_null:
case pw_cancel:
fprintf (stderr, "%s: password entry cancelled.\n", blurb()); break;
case pw_time:
fprintf (stderr, "%s: password entry timed out.\n", blurb()); break;
default:
break;
}
#ifdef HAVE_SYSLOG
if (si->pw_data->state == pw_fail)
{
/* If they typed a password (as opposed to just hitting return) and
the password was invalid, log it.
*/
struct passwd *pw = getpwuid (getuid ());
char *d = DisplayString (si->dpy);
char *u = (pw->pw_name ? pw->pw_name : "???");
int opt = 0;
int fac = 0;
# ifdef LOG_PID
opt = LOG_PID;
# endif
# if defined(LOG_AUTHPRIV)
fac = LOG_AUTHPRIV;
# elif defined(LOG_AUTH)
fac = LOG_AUTH;
# else
fac = LOG_DAEMON;
# endif
if (!d) d = "";
openlog (progname, opt, fac);
syslog (LOG_NOTICE, "FAILED LOGIN %d ON DISPLAY \"%s\", FOR \"%s\"",
si->unlock_failures, d, u);
closelog ();
}
#endif /* HAVE_SYSLOG */
if (si->pw_data->state == pw_fail)
XBell (si->dpy, False);
if (si->pw_data->state == pw_ok && si->unlock_failures != 0)
{
if (si->unlock_failures == 1)
fprintf (real_stderr,
"%s: WARNING: 1 failed attempt to unlock the screen.\n",
blurb());
else
fprintf (real_stderr,
"%s: WARNING: %d failed attempts to unlock the screen.\n",
blurb(), si->unlock_failures);
si->unlock_failures = 0;
}
if (msg)
{
if (p->verbose_p)
{
fprintf (stderr, "..eventloop...msg is:%s\n",msg);
}
#ifdef HAVE_XSCREENSAVER_LOCK
/* DONT NEED TO SEND ANY INFO TO CHILD AT THIS STAGE */
/* if (write_to_child (si, msg));**/ /*if write is successful do nothing*/
free(msg);
/*********************************************************
if (si->external_passwd && si->pw_data->stdin_fd != -1)
{
ssize_t len;
char *nlmsg;
nlmsg = (char *)malloc (strlen (msg) + 2);
sprintf (nlmsg, "%s\n", msg);
if (p->verbose_p)
{
fprintf (stderr,
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
fprintf (stderr, "HAVE_SCRSVR_LOCK message is:%s writing to
fd:%d\n",
msg, si->pw_data->stdin_fd);
fprintf (stderr,
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
write_msg:
len = write (si->pw_data->stdin_fd, nlmsg, strlen (nlmsg));
if (len < 0 && errno == EINTR)
goto write_msg;
free (nlmsg);
}
else
******************************************************************************/
#endif /* HAVE_XSCREENSAVER_LOCK */
/************
{
si->pw_data->i_beam = 0;
update_passwd_window (si, msg, 0.0);
}
************/
XSync (si->dpy, False);
usleep (250000); /* 1/4 second */
/* Swallow all pending KeyPress/KeyRelease events. */
{
XEvent e;
while (XCheckMaskEvent (si->dpy, KeyPressMask|KeyReleaseMask, &e))
;
}
}
}
void
handle_typeahead (saver_info *si)
{
passwd_dialog_data *pw = si->pw_data;
int i;
if (!si->unlock_typeahead)
return;
i = strlen (si->unlock_typeahead);
if (i >= sizeof(pw->typed_passwd) - 1)
i = sizeof(pw->typed_passwd) - 1;
memcpy (pw->typed_passwd, si->unlock_typeahead, i);
pw->typed_passwd [i] = 0;
memset (si->unlock_typeahead, '*', strlen(si->unlock_typeahead));
si->unlock_typeahead[i] = 0;
#ifdef HAVE_XSCREENSAVER_LOCK
/* FIXME: bugzilla.gnome.org #77077 */
/* need to handle this in the external dialog case */
#else
update_passwd_window (si, si->unlock_typeahead, pw->ratio);
#endif /* !HAVE_XSCREENSAVER_LOCK */
free (si->unlock_typeahead);
si->unlock_typeahead = 0;
}
Bool
unlock_p (saver_info *si)
{
saver_preferences *p = &si->prefs;
Bool status;
raise_window (si, True, True, True);
if (p->verbose_p)
fprintf (stderr, "%s: -->unlock_p()\n", blurb());
/*******mali99**/
if (si->pw_data || si->passwd_dialog)
destroy_passwd_window (si);
make_passwd_window (si);
/****mali99*********/
compose_status = calloc (1, sizeof (*compose_status));
handle_typeahead (si);
passwd_event_loop (si);
status = (si->pw_data->state == pw_ok);
destroy_passwd_window (si);
free (compose_status);
compose_status = 0;
return status;
}
void
set_locked_p (saver_info *si, Bool locked_p)
{
si->locked_p = locked_p;
#ifdef HAVE_XHPDISABLERESET
hp_lock_reset (si, locked_p); /* turn off/on C-Sh-Reset */
#endif
#ifdef HAVE_XF86VMODE
xfree_lock_mode_switch (si, locked_p); /* turn off/on C-Alt-Plus */
#endif
#ifdef HAVE_XF86MISCSETGRABKEYSSTATE
xfree_lock_grab_smasher (si, locked_p); /* turn off/on C-Alt-KP-*,/ */
#endif
store_saver_status (si); /* store locked-p */
}
#else /* NO_LOCKING -- whole file */
void
set_locked_p (saver_info *si, Bool locked_p)
{
if (locked_p) abort();
}
#endif /* !NO_LOCKING */
/*******mali99**/
if (si->pw_data || si->passwd_dialog)
destroy_passwd_window (si);
make_passwd_window (si);
/****mali99*********/
compose_status = calloc (1, sizeof (*compose_status));
handle_typeahead (si);
passwd_event_loop (si);
status = (si->pw_data->state == pw_ok);
destroy_passwd_window (si);
free (compose_status);
compose_status = 0;
return status;
}
void
set_locked_p (saver_info *si, Bool locked_p)
{
si->locked_p = locked_p;
#ifdef HAVE_XHPDISABLERESET
hp_lock_reset (si, locked_p); /* turn off/on C-Sh-Reset */
#endif
#ifdef HAVE_XF86VMODE
xfree_lock_mode_switch (si, locked_p); /* turn off/on C-Alt-Plus */
#endif
#ifdef HAVE_XF86MISCSETGRABKEYSSTATE
xfree_lock_grab_smasher (si, locked_p); /* turn off/on C-Alt-KP-*,/ */
#endif
store_saver_status (si); /* store locked-p */
}
#else /* NO_LOCKING -- whole file */
void
set_locked_p (saver_info *si, Bool locked_p)
{
if (locked_p) abort();
}
#endif /* !NO_LOCKING */
++ break;
++ case VisibilityNotify:
++ wPopWin = event.xvisibility.window;
++ break;
++ default:
++ break;
++ }
++
++
++ /* Array at_win stores password and screensaver window,
also MAG and/or GOK if a11y is on
++ /* if any window apart from password, MAG ,GOK or
screensaver comes over is considered as popup window. */
++ /* If it is not popup window but password, MAG, GOK, or
screensaver window t hen nWin < no_atserv+2 */
++ /* If it is popup window then nWin == no_atserv+2 */
++ int nWin =0;
++ if(wPopWin) // check if it is really a popup window
++ for(;nWin < no_atserv+2 ; ++nWin)
++ {
++ if(at_win[nWin]==wPopWin)
++ break;
++ }
++
++ /* Do restacking if it is popup window ie nWin ==
no_atserv+2 */
++ /* Also do restacking when a11y is on */
++ if( nWin== no_atserv+2 ||no_atserv )
++ {
++
++ /* at_win[0] -> passwordwindow */
++ /* at_win[1-2]-> if a11y on, may GOK or MAG */
++
++ at_win[no_atserv+1] = si->screens[0].screensaver_window;
++ if(nWin== no_atserv+2)
++ {
++ /* store popup window in array of at_win to restack
it */
++ at_win[no_atserv+2] = wPopWin;
++ XRestackWindows(si->dpy, at_win,no_atserv+3);
++ }
++ else
++ {
++ XRestackWindows(si->dpy, at_win,no_atserv+2);
++ }
++ XFlush(si->dpy);
++ }
++ }
++
+ }
+ /* the above new code for restacking under the conidtion
+ */
Index: SUNWxscreensaver.spec
===================================================================
--- SUNWxscreensaver.spec (revision 19180)
+++ SUNWxscreensaver.spec (working copy)
@@ -149,6 +149,8 @@
Patch46: xscreensaver-46-bug-6857559.diff
# date:2009-07-31 owner:bp230705 type:bug bugster:6859039
Patch47: xscreensaver-47-bug-6859039.diff
+# date:2009-09-10 owner:au230626 type:bug bugster:6839026
+Patch48: xscreensaver-48-bug-6839026.diff
# date:2008-03-07 owner:alanc type:branding
Patch101: rss-glx-101-matrixview.diff
@@ -327,6 +329,7 @@
%patch45 -p1
%patch46 -p1
%patch47 -p1
+%patch48 -p1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: lock.c
Type: text/x-csrc
Size: 79111 bytes
Desc: not available
URL:
<http://mail.opensolaris.org/pipermail/jds-review/attachments/20090911/8a5b4f65/attachment.bin>