[comp.windows.x] How to lock a sun under X

avr@mtgzz.UUCP (XMRP50000[jcm]-a.v.reed) (03/22/88)

Our company policy on protecting proprietary information requires that all
workstations and terminals be locked when left unattended, however briefly.
Under suntools, this is readily accomplished with the "Lock Screen" selection in
the top-level menu, which calls /usr/bin/lockscreen. Since there is as yet no
comparable program under the X Window System, the easiest way to be able to lock
the screen under X is to run X 11 (made with -DSUN_WINDOWS) over suntools.
I do this automatically by placing

    alias -x  x='XRUN=XRUN;export XRUN;/usr/bin/suntools -s $HOME/.xst;clear'

and the clause

    if [ `tty` = /dev/ttyp0 -a "$WINDOW_PARENT" -a "$XRUN" ]
	then
	sleep 16
	trap "" 1 15
	. $HOME/.xrun 2>/dev/null
	kill `ps -g|/bin/grep suntools|cut -c1-5`
	trap 1 15
	fi

in my ksh $ENV file. When I invoke "x" from the login shell, the alias
fires up suntools with the startup script $HOME/.xst, which contains
the one line

cmdtool    -Wp    0   0 -Ws 590  55 -WP    0   0 -Wl "<< CONSOLE >>" -WL console -C 

The ksh that automatically fires up in cmdtool runs into the "if" clause above,
and executes $HOME/.xrun, which contains my X startup (I don't use xinit; and I
won't post my opinion of xinit where it might be read by minors :-) :

    # PATH=:/usr/mtgzfs1/avr/x11r2.core/usr/bin/X11$PATH
    TTY=`tty`
    DISPLAY=adam:0;export DISPLAY
    (sleep 2 ; xterm -fn 6x10 -b 2 -bw 3 =80x24+0-450 -C) 2>/dev/null &
    (sleep 3 ; xterm -fn 6x10 -b 2 -bw 3 =81x44-0-0) 2>/dev/null &
    (sleep 4 ; xterm -fn 6x10 -b 2 -bw 3 =81x44-0+0) 2>/dev/null &
    (sleep 5 ; xterm -fn 6x10 -b 2 -bw 3 =81x44+0-0) 2>/dev/null &
    (sleep 6 ; xterm -fn 6x10 -b 2 -bw 3 =81x89+573+0) 2>/dev/null &
    (sleep 7 ; xterm -fn 6x10 -b 2 -bw 3 =81x89-573+0) 2>/dev/null &
    (sleep 8 ; xclock -analog =83x83+0+0 -update 1) 2>xclock.out &
    (sleep 9 ; xsetroot -gray) 2>/dev/null &
    (sleep 12 ; uwm) 2>uwm.out &
    (sleep 14 ; xset -r m 4 2 s 600 ) 2>/dev/null &
    Xsun -mono -fp /usr/mtgzfs1/avr/x11r2.core/fonts/snf -a 4 -t 2 \
	    -co /usr/mtgzfs1/avr/x11r2.core/util/rgb/rgb -r \
	    >/$HOME/xsun.out 2>&1
    case $TTY in
	    /dev/ttyp* )
		    kbd_mode -e
		    ;;
	    * )
		    kbd_mode -a
		    setkeys reset
		    ;;
	esac
    clear

Once in x, I can lock the screen with the alias "xlock", also in my $ENV:

    alias -x xlock='xset s off;/usr/bin/lockscreen;xrefresh;xset s;kbd_mode -u'

And to quit, I just type "xkill":

    alias -x xkill='kill `ps -g|/bin/grep Xsun|cut -c1-5`'

					Adam Reed (mtgzz!avr)

milliken@heron.bbn.com (Walter Milliken) (03/24/88)

In article <3757@mtgzz.UUCP> avr@mtgzz.UUCP (XMRP50000[jcm]-a.v.reed) writes:
>Our company policy on protecting proprietary information requires that all
>workstations and terminals be locked when left unattended, however briefly.
>Under suntools, this is readily accomplished with the "Lock Screen" selection in
>the top-level menu, which calls /usr/bin/lockscreen. Since there is as yet no
>comparable program under the X Window System, the easiest way to be able to lock
>the screen under X is to run X 11 (made with -DSUN_WINDOWS) over suntools.

I posted such a program for X10 to the xpert list a while back.
Here's the X11 version (apologies for posting source here, but it's
relatively short).

The program locks the workstation and also performs as a screensaver.
To unlock the terminal, type your password, followed by a return.  No
line editing is provided, but you can abort password entry by typing
return and starting over.

For the incredibly paranoid, you can supply an optional key string on
the command line, which will become the unlocking key instead of your
password.

--------- cut here -------
/* program to secure SUN console under X11 */

#include <stdio.h>
#include <pwd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#define FALSE 0
#define TRUE 1

char * crypt();


#define lckcurs_width 32
#define lckcurs_height 32
#define lckcurs_x_hot 16
#define lckcurs_y_hot 20
static char lckcurs_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf8, 0x1f, 0x00,
   0x00, 0xfc, 0x3f, 0x00, 0x00, 0x3e, 0x7c, 0x00, 0x00, 0x0f, 0xf0, 0x00,
   0x00, 0x07, 0xe0, 0x00, 0x80, 0x03, 0xc0, 0x01, 0x80, 0x03, 0xc0, 0x01,
   0x80, 0x03, 0xc0, 0x01, 0xc0, 0x01, 0x80, 0x03, 0xc0, 0x01, 0x80, 0x03,
   0xc0, 0x01, 0x80, 0x03, 0xc0, 0x01, 0x80, 0x03, 0x08, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00,
   0x00, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00,
   0x00, 0xf0, 0x0f, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x03, 0x00,
   0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00,
   0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00};

#define lckmask_width 32
#define lckmask_height 32
#define lckmask_x_hot 16
#define lckmask_y_hot 20
static char lckmask_bits[] = {
   0x00, 0xe0, 0x07, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xfc, 0x3f, 0x00,
   0x00, 0xfe, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x80, 0x3f, 0xfc, 0x01,
   0x80, 0x0f, 0xf0, 0x01, 0xc0, 0x07, 0xe0, 0x03, 0xc0, 0x07, 0xe0, 0x03,
   0xc0, 0x07, 0xe0, 0x03, 0xe0, 0x03, 0xc0, 0x07, 0xe0, 0x03, 0xc0, 0x07,
   0xe0, 0x03, 0xc0, 0x07, 0xf0, 0x03, 0xc0, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
   0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
   0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
   0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
   0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
   0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
   0xf0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00};

#endif


struct passwd * pw;

Display * dsp;			/* current display */
Window w;			/* window used to cover screen */
int width;			/* width of screen */
int height;			/* height of screen */

Cursor mycursor;		/* "lock" cursor */

Window rootw;			/* root window */
int scrn;			/* current screen */
Colormap cmap;			/* colormap of current screen */

unsigned long black_pixel;	/* pixel value for black */
unsigned long white_pixel;	/* pixel value for white */
XColor black_color;		/* color value for black */
XColor white_color;		/* color value for white */


ReadXString(s, slen)
char * s;
int slen;
{
    int bp;
    char c;
    int n;
    XEvent evt;
    XKeyEvent * kpevt = (XKeyEvent *) &evt;
    char keystr[20];



    bp = 0;
    c = 'x';
    while (c != '\r') {
	if (XPending(dsp) == 0) {
	    XWarpPointer(dsp, None, w, 0, 0, 0, 0,
			 (random() % (width-64))+32,
			 (random() % (height-64))+32);
	    sleep(2);
	    }
	else {
	    XNextEvent(dsp, &evt);
	    if (evt.type == KeyPress) {
		n = XLookupString(kpevt, keystr, 20, NULL, NULL);
		if (n>0) {
		    c = keystr[0];
		    if (c == '\r') s[bp] = '\0';
		    else s[bp] = c;
		    if (bp < slen-1) bp++;
		    }
		}
	    else ; /* do nothing */
	    }
	}
}


main(argc, argv)
int argc;
char * argv[];
{
    char geometry[40];
    char buf[200];
    char * pass;
    char cryptpass[20];
    char * s;
    int n;
    int i;
    int done;
    Pixmap lckcurs;		/* temp pixmaps for cursor creation */
    Pixmap lckmask;
    XSetWindowAttributes attrs;	/* used to set background, kill redirects */


    pw = getpwuid(getuid());
    if (argc == 1) pass = pw->pw_passwd;
    else if (argc == 2) {
	pass = crypt(argv[1], pw->pw_passwd);
	strcpy(cryptpass, pass);
	pass = cryptpass;
	}
    else {
	fprintf(stderr, "usage: %s [<lock password>]\n", argv[0]);
	exit(1);
	}

    dsp = XOpenDisplay(NULL);
    rootw = DefaultRootWindow(dsp);
    scrn = DefaultScreen(dsp);
    width = DisplayWidth(dsp, scrn);
    height = DisplayHeight(dsp, scrn);
    cmap = DefaultColormap(dsp, scrn);

    black_pixel = BlackPixel(dsp, scrn);
    black_color.pixel = black_pixel;
    XQueryColor(dsp, cmap, &black_color);

    white_pixel = WhitePixel(dsp, scrn);
    white_color.pixel = white_pixel;
    XQueryColor(dsp, cmap, &white_color);


    attrs.background_pixel = black_pixel;
    attrs.override_redirect = True;
    w = XCreateWindow(dsp, rootw, 0, 0, width, height, 0, 0, InputOutput,
		      CopyFromParent, CWOverrideRedirect|CWBackPixel, &attrs);
    lckcurs = XCreateBitmapFromData(dsp, w, lckcurs_bits,
				    lckcurs_width, lckcurs_height);
    lckmask = XCreateBitmapFromData(dsp, w, lckmask_bits,
				    lckmask_width, lckmask_height);
    mycursor = XCreatePixmapCursor(dsp, lckcurs, lckmask,
				   &black_color, &white_color,
				   lckcurs_x_hot, lckcurs_y_hot);
    XFreePixmap(dsp, lckcurs);
    XFreePixmap(dsp, lckmask);

    XSelectInput(dsp, w, KeyPressMask);
    XMapWindow(dsp, w);

    XGrabKeyboard(dsp, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
    XGrabPointer(dsp, w, False, -1, GrabModeAsync, GrabModeAsync, None,
		 mycursor, CurrentTime);

    do {
	ReadXString(buf, 200);
	s = crypt(buf, pw->pw_passwd);
	} while (! (strcmp(s, pass) == 0));

    XUngrabPointer(dsp, CurrentTime);
    XUngrabKeyboard(dsp, CurrentTime);
    XDestroyWindow(dsp, w);
    XFlush(dsp);
}

randy@sun1.nlm.nih.gov (Rand Huntzinger) (03/25/88)

In article <22533@bbn.COM> milliken@bbn.com (Walter Milliken) writes:
>I posted such a program for X10 to the xpert list a while back.
>Here's the X11 version (apologies for posting source here, but it's
>relatively short).
>
>The program locks the workstation and also performs as a screensaver.
>To unlock the terminal, type your password, followed by a return.  No
>line editing is provided, but you can abort password entry by typing
>return and starting over.

There is a bit of a security problem with this program as given if you
have pranksters around.  I can sit on another host, set my DISPLAY
environment variable to point to your machine, and if xhosts on your
server lets me, I can lockup your screen remotely.  If you don't know
my password, you're sorta stuck.  Of course, you can probably figure
out I did it, unless I ran the program from Fred's terminal when he
was in the bathroom.

If you want to use it, you could make the following patch to require the
program to be run from your workstation.  That would help if you're the
only guy with an account on your system.

in main.c - replace the line:

    dsp = XOpenDisplay(NULL);

with:

    dsp = XOpenDisplay("unix:0");
    if(dsp == (Display *) NULL) {
        fprintf(stderr, "Can't connect to X server!\n");
        exit(1);
    }

That way only trusted friends can betray you.

avr@mtgzz.UUCP (XMRP50000[jcm]-a.v.reed) (03/25/88)

In article <22533@bbn.COM>, milliken@heron.bbn.com (Walter Milliken) writes:
> In article <3757@mtgzz.UUCP> avr@mtgzz.UUCP (XMRP50000[jcm]-a.v.reed) writes:
<> >Our company policy on protecting proprietary information requires that all
<> >workstations and terminals be locked when left unattended, however briefly.
> I posted such a program for X10 to the xpert list a while back.
> Here's the X11 version (apologies for posting source here, but it's
> relatively short).

I compiled Walter Milliken's program, and it does just what we need.
Now I can delete the suntools/lockscreen kludge described in my
earlier posting. Thanks!
			Adam Reed (mtgzz!avr)

naughton@sun.soe.clarkson.edu (Patrick Naughton) (03/25/88)

> In article <22533@bbn.COM>, milliken@heron.bbn.com (Walter Milliken) writes:
> I posted such a program for X10 to the xpert list a while back.
> Here's the X11 version (apologies for posting source here, but it's
> relatively short).


 I have taken the code posted by Walter Milliken to lock an X11 terminal
and modified it to increase both the security of its use and the
aesthetics of its display.  I (and others) noticed that it should only
be allowed to run on "unix:0", and I also removed the option for a
command line password, since anyone could lock your terminal with any
random password using this option.  As an added measure, I have it set
up so you need to enter your password in order to lock the terminal as
well as unlock it.  (This is an arguable point and may be removed given
enough opposition.)  I also wrote a "standard" X11 man page for it.

  The most noticeable enhancement is in the display.  I coded the
"HOPALONG" routine from the September 1986 issue of Scientific American. 
These "real plane fractals" are quite nice to watch.  There is a command
line option to support color and it will change patterns after 10-20K
iterations or when Return is pressed.  Control-H and Control-U are
supported for line editing as in login.

 If anyone has any comments or additions, I will be happy to make the
changes and make the full sources available via anonymous ftp from
sun.soe.clarkson.edu (128.153.12.3) along with the X distribution and
lots of other X related software.  (in ~ftp/pub/X.V11R2/local)

-Patrick
		 ___________________________________________
		|                                           |
		|  Internet: naughton@sun.soe.clarkson.edu  |
		|  BITNET:   naughton@CLUTX.BITNET          |
		|  uucp:     {rpics, gould}!clutx!naughton  |
		|___________________________________________|

-----------------------------cut here------------------------------------
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	xlock.c
#	xlock.man
#	Imakefile
# This archive created: Thu Mar 24 23:06:55 1988
export PATH; PATH=/bin:$PATH
if test -f 'xlock.c'
then
	echo shar: over-writing existing file "'xlock.c'"
fi
cat << \SHAR_EOF > 'xlock.c'
/*
 *                             XLOCK V1.1
 *
 *                      A Terminal Locker for X11
 *
 *              Copyright (c) 1988 by Patrick J. Naughton
 *
 *                         All Rights Reserved
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * Original version posted to comp.windows.x by:
 * Walter Milliken
 * (milliken@heron.bbn.com)
 * BBN Advanced Computers, Inc., Cambridge, MA
 *
 * Comments and additions may be sent the author at:
 *
 * naughton@sun.soe.clarkson.edu
 *
 * or by Snail Mail:
 * Patrick J. Naughton
 * 23 Pleasant Street, #3
 * Potsdam, NY  13676
 *         or
 * (315) 265-2853 (voice)
 *
 *
 * Revision History:
 * 24-Mar-88: Added color support. [-color]
 *            wrote the man page.
 * 23-Mar-88: Added HOPALONG routines from Scientific American Sept. 86 p. 14.
 *            added password requirement for invokation
 *            removed option for command line password
 *            added requirement for display to be "unix:0".
 *            changed the icon.
 * 22-Mar-88: Recieved Walter Milliken's comp.windows.x posting.
 *
 */

#include <stdio.h>
#include <pwd.h>
#include <math.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

char *crypt();
struct passwd *pw;

Display *dsp = NULL;		/* current display (must be inited) */
Window w;			/* window used to cover screen */
GContext gc;

int width;			/* width of screen */
int height;			/* height of screen */

Window rootw;			/* root window */
int screen;			/* current screen */
Colormap cmap;			/* colormap of current screen */
Cursor mycursor;		/* "locked" cursor */

unsigned long black_pixel;	/* pixel value for black */
unsigned long white_pixel;	/* pixel value for white */
XColor black_color;		/* color value for black */
XColor white_color;		/* color value for white */

#define lock_width 48
#define lock_height 16
#define lock_x_hot 24
#define lock_y_hot 8
static char lock_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x3c, 0x3c, 0x66, 0x7e, 0x3e,
   0x06, 0x66, 0x66, 0x66, 0x7e, 0x76, 0x06, 0x66, 0x46, 0x66, 0x06, 0x66,
   0x06, 0x66, 0x06, 0x36, 0x06, 0x66, 0x06, 0x66, 0x06, 0x36, 0x06, 0x66,
   0x06, 0x66, 0x06, 0x36, 0x06, 0x66, 0x06, 0x66, 0x06, 0x1e, 0x3e, 0x66,
   0x06, 0x66, 0x06, 0x1e, 0x3e, 0x66, 0x06, 0x66, 0x06, 0x36, 0x06, 0x66,
   0x06, 0x66, 0x06, 0x36, 0x06, 0x66, 0x06, 0x66, 0x06, 0x36, 0x06, 0x66,
   0x06, 0x66, 0x46, 0x66, 0x06, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x7e, 0x76,
   0x7e, 0x3c, 0x3c, 0x66, 0x7e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static char lock_mask[] = {
   0x0f, 0x7e, 0x7e, 0xff, 0xff, 0x7f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
   0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
   0x0f, 0xff, 0xef, 0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0x7f, 0x0f, 0xff,
   0x0f, 0xff, 0x0f, 0x7f, 0x7f, 0xff, 0x0f, 0xff, 0x0f, 0x7f, 0x7f, 0xff,
   0x0f, 0xff, 0x0f, 0x7f, 0x7f, 0xff, 0x0f, 0xff, 0x0f, 0x7f, 0x7f, 0xff,
   0x0f, 0xff, 0x0f, 0x7f, 0x0f, 0xff, 0x0f, 0xff, 0xef, 0xff, 0x0f, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x7e, 0xff, 0xff, 0x7f};


int centerx, centery, iter, maxiter, range, color;
double a, b, c, i, j;


ReadXString(s, slen)
char *s;
int slen;
{
    int bp;
    char c;
    XEvent evt;
    XKeyEvent *kpevt = (XKeyEvent *) &evt;
    char keystr[20];

    bp = 0;
    while (1) {
	if (XPending(dsp)) {
	    XNextEvent(dsp, &evt);
	    if (evt.type == KeyPress) {
		if (XLookupString(kpevt, keystr, 20, NULL, NULL) > 0) {
		    c = keystr[0];
		    switch (c) {
			case 8:			/* ^H */
			    if (bp > 0) bp--;
			    break;
			case 13:		/* ^M */
			    s[bp] = '\0';
			    return;
			case 21:		/* ^U */
			    bp = 0;
			    break;
			default:
			    s[bp] = c;
			    if (bp < slen-1) bp++;
		    }
		}
	    }
	}
	else iterate();
    }
}


main(argc, argv)
int argc;
char *argv[];
{
    char buf[10];
    char *pass;
    XSetWindowAttributes attrs;
    XGCValues xgcv;
    Pixmap lockc, lockm;
    char *getpass();

    color = 0;
    if (argc > 1) {
	if (!strcmp("-color", argv[1])) color++;
	else {
	    fprintf (stderr, "usage: %s [-color]\n", argv[0]);
	    exit(1);
	}
    }

    pw = getpwuid(getuid());
    pass = crypt(getpass("Password:"), pw->pw_passwd);
    if (strcmp(pw->pw_passwd, pass)) {
	fprintf(stderr, "Sorry\n");
	exit(1);
    }

    if (!(dsp = XOpenDisplay("unix:0"))) {
	fprintf (stderr, "%s:  unable to open display.\n", argv[0]);
	exit(1);
    }
    rootw = DefaultRootWindow(dsp);
    screen = DefaultScreen(dsp);
    width = DisplayWidth(dsp, screen);
    height = DisplayHeight(dsp, screen);
    centerx = width / 2;
    centery = height / 2;
    range = (int) sqrt((double)centerx*centerx+(double)centery*centery);
    cmap = DefaultColormap(dsp, screen);

    black_pixel = BlackPixel(dsp, screen);
    black_color.pixel = black_pixel;
    XQueryColor(dsp, cmap, &black_color);

    white_pixel = WhitePixel(dsp, screen);
    white_color.pixel = white_pixel;
    XQueryColor(dsp, cmap, &white_color);

    attrs.background_pixel = black_pixel;
    attrs.override_redirect = True;
    attrs.event_mask = KeyPressMask;
    w = XCreateWindow(dsp, rootw, 0, 0, width, height, 0,
		CopyFromParent, InputOutput, CopyFromParent,
		CWOverrideRedirect | CWBackPixel | CWEventMask, &attrs);

    lockc = XCreateBitmapFromData(dsp, w, lock_bits,
				    lock_width, lock_height);

    lockm = XCreateBitmapFromData(dsp, w, lock_mask,
				    lock_width, lock_height);

    mycursor = XCreatePixmapCursor(dsp, lockc, lockm,
				   &black_color, &white_color,
				   lock_x_hot, lock_y_hot);
    XFreePixmap(dsp, lockc);
    XFreePixmap(dsp, lockm);


    XMapWindow(dsp, w);

    xgcv.foreground = white_pixel;
    xgcv.background = black_pixel;
    gc = (GContext) XCreateGC(dsp, w, GCForeground | GCBackground, &xgcv);

    XGrabKeyboard(dsp, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
    XGrabPointer(dsp, w, False, -1, GrabModeAsync, GrabModeAsync, None,
		 mycursor, CurrentTime);

    srandom(time(NULL));
    do {
	inithop();
	ReadXString(buf, 10);
    } while (strcmp(crypt(buf, pw->pw_passwd), pw->pw_passwd));

    XUngrabPointer(dsp, CurrentTime);
    XUngrabKeyboard(dsp, CurrentTime);
    XDestroyWindow(dsp, w);
    XFlush(dsp);
}


iterate()
{
double oldj;
register int k;

    for (k=0;k<500;k++) {
	if (color) XSetForeground(dsp, gc, (iter % 25) * 10 + 5);
	XDrawPoint(dsp, w, gc, (int)i+centerx,centery-(int)j);
	oldj=j;
	j=a-i;
	i = oldj + (i<0?sqrt(fabs(b*i - c)):-sqrt(fabs(b*i - c))); 
	iter++;
    }
    if (iter > maxiter) inithop();
}
     
inithop()
{
	a = random() % (range * 100) * (random()%2?-1.0:1.0) / 100.0;
	b = random() % (range * 100) * (random()%2?-1.0:1.0) / 100.0;
	c = random() % (range * 100) * (random()%2?-1.0:1.0) / 100.0;

	if (!(random()%3)) a /= 10.0;
	if (!(random()%2)) b /= 100.0;

	maxiter = (color?10000+random()%20000:20000+random()%50000);
	iter = 0;
	i = j = 0.0;
	XClearWindow(dsp, w);
}

SHAR_EOF
if test -f 'xlock.man'
then
	echo shar: over-writing existing file "'xlock.man'"
fi
cat << \SHAR_EOF > 'xlock.man'
.TH XLOCK 1 "24 Mar 1988" "X Version 11"
.SH NAME
xlock \- Locks the X terminal till a password is entered.

.SH SYNOPSIS
.B xlock [\fI-color\fP]

.SH DESCRIPTION
.I xlock
prompts the user for their password then locks the screen such that no
mouse or keyboard actions are recognized till the user re-enters their
password at the keyboard.  The screen is blanked and the mouse cursor
changes to the word \fILOCKED\fP.  Then the "real plane" iterative
fractals from the September 1986 issue of Scientific American are put on
the screen.  The pattern changes after 10-20K iterations or when the
Return key is pressed.  The password is not echoed to the screen and ^U
and ^H are active as clear and rubout repectively.  The [\fI-color\fP]
option allows users of color frame buffers to get color output of the
fractals. 

.SH BUGS
There are no known bugs.

.SH ENVIRONMENT
DISPLAY is ignored! "unix:0" is used as the display for security reasons.

.SH SEE ALSO
X(1), Xlib Documentation.

.SH AUTHOR
   
 Copyright (c) 1988 by Patrick Naughton
 (naughton@sun.soe.clarkson.edu)
 Clarkson University, Potsdam, NY

 Original version posted to comp.windows.x by:
 Walter Milliken
 (milliken@heron.bbn.com)
 BBN Advanced Computers, Inc., Cambridge, MA

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation. 
SHAR_EOF
if test -f 'Imakefile'
then
	echo shar: over-writing existing file "'Imakefile'"
fi
cat << \SHAR_EOF > 'Imakefile'
LOCAL_LIBRARIES = $(XLIB)
  SYS_LIBRARIES = -lm
         CFLAGS = -O -fswitch
           SRCS = xlock.c
           OBJS = xlock.o

ComplexProgramTarget(xlock)
SHAR_EOF
#	End of shell archive
exit 0