[comp.windows.x] X window locking program

radzy@unet.UUCP.UUCP (04/04/87)

#!/bin/sh
#
# Well, I finally got things put together and shar'ed up.
# If anyone has any comments about this, please let me know.
# The rest is pretty much self-explanatory.
# 
# -----------cut here------------------------------
#
# This is a shar archive.  To unpack it, run it through
# sh,  e.g. sh FILENAME
#
echo "Making directory xexec"
mkdir xexec
echo extracting xexec/README
sed -e 's/^X //' << SHAR_EOF > xexec/README
X 		first xexec distribution
X 	Copyright (C) 1987, Tim Radzykewycz
X 
X This software is available for non-profit use and distribution,
X provided that this and any other copyright notices are included
X in each copy.
X 
X ------------------------------------------------------------
X 
X This is the first release of xexec, a program intended to provide
X a screen locking mechanism for the X window package.  This has
X been tested on X version 4, running on a SUN-3 running SUNOS 3.0
X and higher.
X 
X Included in this package is a lock program, which I feel is better
X than any of the lock programs I've seen on UNIX to date.  It comes
X with a man page.
X 
X Files included in this release include:
X 	README		-- this file.
X 	Makefile	-- a makefile, which will install xexec for you
X 	util.c		-- a few minor subroutine stubs, for use with
X 				early versions of X
X 	xexec.c		-- the source to xexec
X 	xexec.man	-- a man page for xexec
X 	xlock.icon	-- a bitmap for the icon used by xexec
X 	xlock_mask.icon	-- the mask for xlock.icon
X 	lock.c		-- a new version of lock(1).  Some vendors
X 				don't provide one with their systems.
X 				This is also somewhat improved over
X 				the one provided with 4.2 bsd.
X 	lock.man	-- a man page for lock.c
X 
X ------------------------------------------------------------
X 
X INSTALLATION:
X 
X Unfortunately, you can't just say "make install", though there isn't
X much more than that.
X 
X There are several definitions in the beginning of the Makefile,
X which should be configured for your system.  They are explained
X in the Makefile, so I won't duplicate things by putting them
X here also.  Just edit the Makefile, changing whatever is appropriate,
X and then type "make install".
X 
X Default locations to put things are:
X 	/usr/local/bin
X 	/usr/man/manl
X The default action with regard to the lock program is to ignore
X it.  If you don't like any of these, just edit the Makefile,
X and read the comments as you go along.
X 
X I don't promise to "support" this, however if you have any bug
X reports and/or fixes, please send them to me and I might try
X to incorporate them into the package.
X 
X I also welcome comments on what you find useful with this package.
X If I get enough responses, I'll create a file explaining what people
X are doing with xexec, and include it in any future (potential)
X releases.
X 
X 		Tim "radzy" Radzykewycz
X 		The Incredible Radical Cabbage
X 		radzy@unet.uucp
X 
X     oliveb!  -
X                \
X     ames!    ---\
X                  \
X sun!sunncal! ------- unet!radzy
X                  /
X     ptsfa!   ---/
X                /
X     tymix!   -
SHAR_EOF
echo extracting xexec/Makefile
sed -e 's/^X //' << SHAR_EOF > xexec/Makefile
X #################################################################
X #
X #	Copyright (C) 1987 by Tim Radzykewycz
X #
X #	This software is available for non-profit use and
X #	distribution, provided that this any other copyright
X #	notices are included in each copy.
X #
X #################################################################
X 
X COPYRIGHT = "Copyright (C) 1987 by Tim Radzykewycz"
X 
X #
X #  The final destination directory for installation.  For
X #  final installation, this should be unset
X DESTDIR = 
X #
X #  Where binaries will be kept
X BINDIR	= /usr/local/bin
X #
X #  Where libraries go (this is un-used, and I don't know why I
X #  leave it here.)
X LIBDIR	= /usr/local/lib
X #
X #  Where man pages go.  Should normally be /usr/man/man1 or
X #  /usr/man/manl.
X MANDIR	= /usr/man/manl
X 
X #
X # The MAN_SECTION define will be the extension to the file name
X # when the man pages are installed, so it should agree with what
X # you specify in MANDIR, or man might not be able to find the
X # page.
X MAN_SECTION=l
X 
X #
X #  Define -DDEBUG here, if you want to have debugging code
X #  compiled into the software.  Otherwise, leave it empty
X DEBUG	=
X 
X #
X #  The version and release number of the X package you are
X #  running.  This is used for several configuration options,
X #  and to provide stub routines where necessary for old releases.
X VERSION	= -DV10
X RELEASE	= -DREL4
X 
X #
X #  The location of the library with X subroutines in it.
X #  Most of the time, this should just be -lX
X XLIB	= -lX
X 
X #
X #  This release comes with a lock program.  If you have (and
X #  like) your own lock program, then don't define this.  Otherwise,
X #  define it to install_lock
X INSTALL_LOCK=
X #INSTALL_LOCK	= install_lock
X 
X 
X #################################################################
X #
X #  This makefile will need work if this stuff is to be installed
X #  on an Apollo workstation.  This assumes that the UNIX
X #  interpretation of multiple slashes in filenames is held -- e.g.
X #  that multiple slashes are ignored.
X #
X #  To fix it for the Apollo, you need to insure that BINDIR, and
X #  MANDIR do NOT BEGIN with a slash, and that DESTDIR does NOT
X #  END with a slash.  Alternately, you could remove the slashes
X #  from the lines below, and insure that the appropriate defines
X #  above DO have slashes.
X #
X #################################################################
X 
X 
X #################################################################
X #            end of site-specific options                       #
X #################################################################
X 
X INCLUDES = 
X SRCS	= xexec.c\
X 	  util.c
X 
X OBJS	= xexec.o\
X 	  util.o
X 
X CFLAGS	= -O $(INCLUDES) $(DEBUG) $(VERSION) $(RELEASE)
X PROG	= xexec
X 
X make: $(PROG)
X 
X install: install_man install_prog $(INSTALL_LOCK)
X 
X install_man:	xexec.man
X 	@rm -f $(DESTDIR)/$(MANDIR)/xexec.$(MAN_SECTION)
X 	install -c -m 644 xexec.man $(DESTDIR)/$(MANDIR)/xexec.$(MAN_SECTION)
X 
X install_prog:	all
X 	@rm -f $(DESTDIR)/$(BINDIR)/$(PROG)
X 	install -c -m 755 $(PROG) $(DESTDIR)/$(BINDIR)
X 	@rm -f $(DESTDIR)/$(BINDIR)/xlock
X 	ln $(DESTDIR)/$(BINDIR)/$(PROG) $(DESTDIR)/$(BINDIR)/xlock
X 
X install_lock:	lock lock.man
X 	@rm -f $(DESTDIR)/$(BINDIR)/lock
X 	install -c -m 755 lock $(DESTDIR)/$(BINDIR)
X 	@rm -f $(DESTDIR)/$(MANDIR)/lock.$(MAN_SECTION)
X 	install -c -m 644 lock.man $(DESTDIR)/$(MANDIR)/lock.$(MAN_SECTION)
X 
X clean:
X 	rm -f *.o $(PROG) *~ \#* lock xlock
X 
X xexec:	xexec.o util.o
X 	$(CC) $(CFLAGS) -o xexec xexec.o util.o $(XLIB)
X 
X xexec.o: xexec.c xlock.icon xlock_mask.icon
X 	$(CC) -c $(CFLAGS) xexec.c
X 
X util.o: util.c
X 	$(CC) -c $(CFLAGS) util.c
X 
X xlock: xexec
X 	@rm -f xlock
X 	ln xexec xlock
X 
X lock:	lock.o
X 	cc $(CFLAGS) -o lock lock.o
X 
X all:	xlock lock
SHAR_EOF
echo extracting xexec/xexec.man
sed -e 's/^X //' << SHAR_EOF > xexec/xexec.man
X .TH XEXEC 1 "3 March 1987"
X .SH NAME
X xexec \- run command and cover entire X screen
X .SH SYNOPSIS
X .B xexec
X [
X .B \-D\ display
X ]
X [
X .B \-c\ |\ \-h
X ]
X [
X .B \-e program
X ]
X [
X .B \-C command
X ]
X .br
X .B xlock
X [
X .B \-D\ display
X ]
X [
X .B \-c\ |\ \-h
X ]
X [
X .B \-e program
X ]
X [
X .B \-C command
X ]
X .SH DESCRIPTION
X .I xexec
X creates a window which covers the entire X window system, then creates
X a sub-window, in which it runs some program.  This is useful for locking
X the screen or for making a custom screen-saver.
X .PP
X .I xexec
X by default, will run the command
X .br
X .I xterm\ =15x4+200+300\ \-fn\ 9x15\ \-e\ lock
X .br
X to lock the screen.
X .PP
X .I xexec
X can be placed in the user's
X .I \.uwmrc
X file, to provide a menu-based screen locking mechanism.
X .SH OPTIONS
X .IP \-D
X set the display, overriding the display specified
X in the environment.
X .IP \-c
X create a clear window over the screen, rather than an
X opaque one.
X .IP \-h
X The opposite of
X .I \-c.
X This will cause the screen contents to be hidden.
X .IP \-e
X exec the specified command in an xterm window.  This is the
X same as
X .I \-C\ \"xterm\ -fn\ 9x15\ \-e\"
X .IP \-C
X specifies the complete command to run.
X .SH EXAMPLES
X The following examples may be placed in a user's
X .I \.uwmrc
X file, to give a menu-based method of locking the screen.
X .sp
X xexec\ -c\ -C\ \'xterm\ -r\ =15x8-0-100\ -fn\ 9x15\ -bw\ 5\ -e\ lock\'
X .sp
X to leave the screen contents intact while the screen is locked,
X or
X .sp
X xexec\ -C\ \'xterm\ -r\ =15x8-0+0\ -fn\ 9x15\ -bw\ 5\ -e\ lock\\'
X .sp
X to cover the screen while it is locked.  These are the commands that
X are in the author's configuration.
X .SH AUTHOR
X Tim Radzykewycz
X .br
X .SH SEE ALSO
X X(1), xterm(1)
X .SH BUGS
X .PP
X If this is run under V10 R3, signals are not handled correctly,
X causing the lock (if that is what was run) to be interruptible.
X .PP
X The idea of a clear window cover has been removed from the spec
X for V11.  At that time, some other method of blocking out other
X windows will have to be found.
SHAR_EOF
echo extracting xexec/xexec.c
sed -e 's/^X //' << SHAR_EOF > xexec/xexec.c
X /*
X  * Copyright (C) 1987, Tim Radzykewycz
X  *
X  *	This software is available for non-profit use and distribution
X  *	provided that this any any other copyright notice are included
X  *	in all copies.
X */
X 
X #include <X/Xlib.h>
X #include <stdio.h>
X 
X #include <sys/types.h>
X #include <sys/stat.h>
X #include <signal.h>
X #include <sgtty.h>
X 
X #include "xlock.icon"
X #include "xlock_mask.icon"
X 
X #ifdef DEBUG
X int debug = 0;
X int parsequit = 0;
X int nocover = 0;
X #endif DEBUG
X 
X int	DisplayWidth(), DisplayHeight();
X 
X static char *Copyright = "\tCopyright (C) 1987 by Tim Radzykewycz\n";
X 
X Window w;
X char command[1024] = "xterm =15x4+200+300 -fn 9x15 -e lock";
X 
X char *progname;
X #ifdef V10
X char *usage = "usage: %s [-D display] [-c|h] [-e exec] [-C command]\n";
X #else V10
X char *usage = "usage: %s [-D display] [-e exec] [-C command]\n";
X #endif V10
X 
X away()
X {
X 	XMapWindow(w);			/* put it up on the screen 	*/
X 	XDestroyWindow(w);		/* throw it away		*/
X 	XFlush();			/* and make sure the server sees it*/
X }
X 
X main(argc, argv)
X int argc;
X char **argv;
X {
X 	int manager;
X 	int i;
X 	int xsiz, ysiz;
X 	FontInfo *font;
X 	OpaqueFrame frame;
X 	char *display = "\0";
X 	XEvent event;
X 	Cursor cursor;
X 	long mask;
X #ifdef V10
X 	int hidden = 1;
X #endif V10
X 
X 	progname = &argv[0][0];
X 
X 	manager = getppid();
X 
X 	while (argv[1] && argv[1][0] == '-') {
X 		switch (argv[1][1]) {
X 		case 'D':	/* display */
X #ifdef DEBUG
X 			if (debug)
X 				fprintf(stderr,"Setting display\n");
X #endif DEBUG
X 			/* this probably shouldn't be here, but what the heck */
X 			if (argv[1][2] != '\0')
X 				display = &argv[1][2];
X 			else {
X 				display = &argv[2][0];
X 				argv++;
X 				argc--;
X 			}
X 			break;
X 
X #ifdef V10
X 		case 'c':	/* clear cover window */
X #ifdef DEBUG
X 			if (debug)
X 				fprintf(stderr,"clear window specified\n");
X #endif DEBUG
X 			hidden = 0;
X 			break;
X 
X 		case 'h':	/* hide screen -- default */
X #ifdef DEBUG
X 			if (debug)
X 				fprintf(stderr,"opaque window specified\n");
X #endif DEBUG
X 			hidden++;
X 			break;
X #endif V10
X 
X 		case 'C':	/* command */
X #ifdef DEBUG
X 			if (debug)
X 				fprintf(stderr,"command specified\n");
X #endif DEBUG
X 			if (argv[1][2] != '\0')
X 				strcpy(command,&argv[1][2]);
X 			else {
X 				strcpy(command,&argv[2][0]);
X 				argv++;
X 				argc--;
X 			}
X 			break;
X 
X 		case 'e':	/* exec */
X #ifdef DEBUG
X 			if (debug)
X 				fprintf(stderr,"exec specified\n");
X #endif DEBUG
X 			if (argv[1][2] != '\0')
X 				sprintf(command,"xterm -fn 9x15 -e %s",&argv[1][2]);
X 			else {
X 				sprintf(command,"xterm -fn 9x15 -e %s",&argv[2][0]);
X 				argv++;
X 				argc--;
X 			}
X 			break;
X 
X #ifdef DEBUG
X 		case 'P':	/* parent */
X 			if (debug)
X 				fprintf(stderr,"window manager specified\n");
X 			if (argv[1][2] != '\0')
X 				manager = atoi(&argv[1][2]);
X 			else {
X 				manager = atoi(&argv[2][0]);
X 				argv++;
X 				argc--;
X 			}
X 			if (manager <= 1) {
X 				fprintf(stderr, "Illegal manager PID: %d\n", manager);
X 				exit(3);
X 			}
X 			break;
X 
X 		case 'x':	/* debug */
X 			if (debug)
X 				fprintf(stderr,"turn debugging on (again)\n");
X 			debug++;
X 			break;
X 
X 		case 'q':	/* quit after parse */
X 			if (debug)
X 				fprintf(stderr,"quit after argument parsing\n");
X 			parsequit++;
X 			break;
X 		
X 		case 'W':	/* no window cover */
X 			if (debug)
X 				fprintf(stderr,"turn off cover window\n");
X 			nocover++;
X 			break;
X #endif DEBUG
X 
X 		default:	
X 			Usage("Unknown flag '%s'\n",argv[1]);
X 			exit(2);
X 		}
X 		argv++;
X 		argc--;
X 	}
X 
X #ifdef DEBUG
X 	if (debug) {
X 		fprintf(stderr,"Finished parsing args\n");
X 		fprintf(stderr,"\tdisplay: %s\n",display);
X 		fprintf(stderr,"\tcommand: %s\n",command);
X 		fprintf(stderr,"\tmanager PID: %d\n",manager);
X #ifdef V10
X 		fprintf(stderr,"\tclear window: %s\n",hidden?"off":"on");
X #endif V10
X 		fflush(stderr);
X 	}
X 	if (parsequit)
X 		exit(0);
X #endif DEBUG
X 
X 	for (i=0;i<33;i++)
X 		signal(i,away);
X 
X 	if (XOpenDisplay(display) == NULL) {
X 		fprintf (stderr, "Could not open Display!\n");
X 		exit(1);
X 	}
X 
X #ifdef DEBUG
X 	if (!nocover)
X #endif DEBUG
X 			{
X 
X #ifdef V10
X 		if (hidden)
X #endif V10
X 			w = XCreateWindow(RootWindow, 0, 0, 
X 				DisplayWidth(), DisplayHeight(),
X 				0, (Pixmap) 0, (Pixmap) 0);
X #ifdef V10
X 		    else
X 			w = XCreateTransparency(RootWindow, 0, 0, DisplayWidth(),
X 				DisplayHeight());
X #endif V10
X 
X 		mask = ButtonPressed | ButtonReleased | ExposeWindow |
X 			ExposeRegion | ExposeCopy | RightDownMotion |
X 			MiddleDownMotion | LeftDownMotion | FocusChange;
X 		XSelectInput(w, mask);
X 	}
X 
X 	XQueryCursorShape(xlock_width, xlock_height, &xsiz, &ysiz);
X 	if (xlock_width > xsiz || xlock_height > ysiz) {
X 		fprintf (stderr, "Can't create icon of correct size\n");
X 		exit(1);
X 	}
X 
X 	cursor = XCreateCursor(
X 		xlock_width, xlock_height,
X 		xlock_bits, xlock_mask_bits,
X 		0, 0,
X 		BlackPixel, WhitePixel,
X 		GXcopy /* 3 */);
X 
X 	if (cursor == NULL) {
X 		fprintf (stderr, "Can't create icon\n");
X 		exit(1);
X 	}
X 
X #ifdef DEBUG
X 	if (!nocover)
X #endif DEBUG
X 			{
X 		XDefineCursor (w, cursor);	/* use the lock icon as cursor */
X 		XGrabMouse(w, cursor, mask);	/* grab all mouse events */
X 
X 		XMapWindow(w);			/* put the window on the screen */
X 	}
X 
X 	XFlush();			/* and make sure the server sees it*/
X 
X 	lock();
X 
X 	/* flush mouse moved events */
X 	while (XPending() != 0) {
X 		XNextEvent(&event);
X 	}
X 
X 	XUngrabMouse();
X #ifdef DEBUG
X 	if (!nocover)
X #endif DEBUG
X 			{
X 		XDestroyWindow(w);		/* throw it away		*/
X 	}
X 	XFlush();			/* and make sure the server sees it*/
X }
X 
X lock()
X {
X 	/* what a kludge! */
X 	system (command);
X }
X 
X Usage(format,arg)
X {
X 	fprintf(stderr,usage,progname);
X 	fprintf(stderr,format,arg);
X }
SHAR_EOF
echo extracting xexec/util.c
sed -e 's/^X //' << SHAR_EOF > xexec/util.c
X #ifdef V10
X #ifdef REL3
X 
X DisplayHeight()
X {
X return(2000);
X }
X 
X DisplayWidth()
X {
X return(2000);
X }
X 
X #endif REL3
X #endif V10
SHAR_EOF
echo extracting xexec/xlock.icon
sed -e 's/^X //' << SHAR_EOF > xexec/xlock.icon
X #define xlock_width 16
X #define xlock_height 16
X static short xlock_bits[] = {
X    0xf01f, 0xe00f, 0xe7cf, 0xe7cf,
X    0xe7cf, 0xe7cf, 0xe7cf, 0x0001,
X    0x0001, 0x0101, 0x0101, 0x0101,
X    0x0381, 0x0381, 0x0001, 0x0001};
SHAR_EOF
echo extracting xexec/xlock_mask.icon
sed -e 's/^X //' << SHAR_EOF > xexec/xlock_mask.icon
X #define xlock_mask_width 16
X #define xlock_mask_height 16
X static short xlock_mask_bits[] = {
X    0x0fe0, 0x1ff0, 0x1830, 0x1830,
X    0x1830, 0x1830, 0x1830, 0xfffe,
X    0xfffe, 0xfffe, 0xfffe, 0xfffe,
X    0xfffe, 0xfffe, 0xfffe, 0xfffe};
SHAR_EOF
echo extracting xexec/lock.man
sed -e 's/^X //' << SHAR_EOF > xexec/lock.man
X .TH LOCK 1 "3 March 1987"
X .SH NAME
X lock \- lock the screen until a knowledgable joe returns
X .SH SYNOPSIS
X .B lock
X [
X .B \-l
X ]
X [
X .B \-p
X ]
X [
X .B \-g
X ]
X .SH DESCRIPTION
X .IX "lock command"  ""  "\fLlock\fP \(em lock arguments"
X .I Lock
X will lock the user's screen, waiting for a password from the
X user.  It will be unlocked if the password the user selected,
X or the system's root password, is typed.
X .br
X .SH OPTIONS
X .IP \fB\-l\fP
X Causes
X .I lock
X to use the login password of the user who invoked lock.  This
X is the default.
X .IP \fB\-p\fP
X Causes
X .I lock
X to use the password supplied on the command line.  As a service
X to those who don't normally set echo off, this will try to clear
X the screen first, by calling the 'clear' command.
X .IP \fB\-g\fP
X Causes
X .I lock
X to ask for a password from the users terminal.
X .I Lock
X will read a string from the terminal, then ask the user
X to repeat it for verification, and then use the password.
X .SH AUTHOR
X Tim Radzykewycz
X .br
X .SH NOTES
X This code was written from scratch.  It does not contain any
X UCB or AT&T code.
SHAR_EOF
echo extracting xexec/lock.c
sed -e 's/^X //' << SHAR_EOF > xexec/lock.c
X /*
X  *  Copyright (C) 1987 by Tim Radzykewycz
X  *
X  *  This software is available for non-profit use and distribution,
X  *  provided this and any other copyright notice is included with
X  *  each copy.
X */
X #include <stdio.h>
X #include <sys/types.h>
X #include <sys/stat.h>
X #include <signal.h>
X #include <pwd.h>
X 
X char *Usage = "lock: Usage lock [-p password] [-g] [-l]\n";
X 
X char *Copyright = "\tCopyright (C) 1987 by Tim Radzykewycz\n";
X 
X extern char *crypt();
X extern char *getpass();
X 
X char	orig[BUFSIZ];	/* original key typed at terminal */
X char	check[BUFSIZ];	/* verify that the user didn't mis-type */
X char	cpw[BUFSIZ];	/* encrypted password */
X char	rpw[BUFSIZ];	/* root's (encrypted) password */
X 
X char *
X get_crypt_pw(uid)
X 	int uid;
X {
X 	struct passwd *pw;
X 
X 	pw = getpwuid(uid);
X 	return(pw->pw_passwd);
X }
X 
X main(argc, argv)
X 	char **argv;
X {
X 	register int t;
X 	struct stat statb;
X 	int ac;
X 	char *cp;
X 
X 	/* dis-allow all signals */
X 	for (t = 0 ; t < 32  ; t++)
X 		signal(t,SIG_IGN);
X 
X 	/* find the superuser's password, and save it away for later */
X 	strcpy(rpw,get_crypt_pw(0));
X 
X 	for (ac = 1 ; ac < argc ; ac++) {
X 		if (argv[ac][0] != '-') {
X 			argv[0] = 0;
X 			break;
X 		} else switch(argv[ac][1]) {
X 		case 'p':	/* use the next argument as the key */
X 			argv[ac] = NULL;
X 			ac++;
X 			cp = &argv[ac][0];
X 			if (argv[ac] != NULL && argv[ac][0] != '\0') {
X 				/* first, clear the screen -- or at least try to */
X 				system("clear");
X 				fprintf(stderr,"getting password\n");
X 				strcpy(cpw,crypt(cp));
X 				/* zero out key, so it can't be found with ps */
X 				fprintf(stderr,"zero out key\n");
X 				for (cp = &argv[ac][0]; *cp ; cp++)
X 					*cp = '\0';
X 				fprintf(stderr,"calling check_pw()\n");
X 				check_pw();
X 			    } else {
X 				fprintf(stderr,Usage);
X 			}
X 			exit(0);
X 		case 'g':	/* get the key from the terminal */
X 			tty_pw();
X 			exit(0);
X 		case 'l':	/* use the login password as the key */
X 			strcpy(cpw,get_crypt_pw(getuid()));
X 			check_pw();
X 			exit(0);
X 		default:	/* huh? */
X 			fprintf(stderr,Usage);
X 			exit(1);
X 		}
X 	}
X 	/* default behavior -- get lock from passwd file */
X 	if (argc > 0)
X 		argv[0] = 0;
X 	strcpy(cpw,get_crypt_pw(getuid()));
X 	check_pw();
X }
X 
X tty_pw()
X {
X 	strcpy(orig,getpass("key: "));
X 	strcpy(check,getpass("again:"));
X 	if (strcmp(check,orig) != 0) {
X 		fprintf(stderr,"Mismatch\n");
X 		exit(1);
X 	}
X 	orig[0] = 0;
X 	strcpy(cpw,crypt(orig));
X 	check_pw();
X }
X 
X check_pw()
X {
X 	char *upw;		/* un-encrypted password */
X 	char *npw;		/* new copy of encrypted password */
X 
X 	for (;;) {
X 		upw = getpass(": ");
X 		npw = crypt(upw,cpw);
X 		if (strcmp(npw,cpw) == 0)
X 			return(0);
X 		npw = crypt(upw,rpw);
X 		if (strcmp(npw,rpw) == 0)
X 			return(0);
X 	}
X }
SHAR_EOF
echo ""
echo "finished with extraction"
echo ""
exit 0