#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 3)."
# Contents:  password.c savescreen.c xsaver.man.s
# Wrapped by jik@pit-manager on Mon Jan 27 17:01:56 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'password.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'password.c'\"
else
echo shar: Extracting \"'password.c'\" \(11103 characters\)
sed "s/^X//" >'password.c' <<'END_OF_FILE'
X/*
X * $Source: /afs/sipb.mit.edu/project/sipbsrc/src/xscreensaver/RCS/password.c,v $
X * $Author: jik $
X *
X * This file is part of xscreensaver.  It contains the code for
X * password manipulation.
X *
X * Author: Jonathan Kamens, MIT Project Athena and
X *                          MIT Student Information Processing Board
X *
X * Copyright (c) 1989 by Jonathan Kamens.  This code may be
X * distributed freely as long as this notice is kept intact in its
X * entirety and every effort is made to send all corrections and
X * improvements to the code back to the author.  Also, don't try to
X * make any money off of it or pretend that you wrote it.
X */
X
X#if !defined(lint) && !defined(SABER)
X     static char rcsid_password_c[] = "$Header: /afs/sipb.mit.edu/project/sipbsrc/src/xscreensaver/RCS/password.c,v 1.26 91/11/03 23:20:44 jik Exp $";
X#endif
X
X#include "xsaver.h"
X#include <X11/Xaw/Form.h>
X#include <X11/Xaw/Label.h>
X#include <X11/Shell.h>
X#ifdef PASSWORD_PORT
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <fcntl.h>
X#include <errno.h>
X#if defined(mips) || defined(sparc) || defined (_IBMR2)
Xextern int sys_nerr;
Xextern char *sys_errlist[];
X#endif
X#if defined(ibm) && defined(SYSV) && defined(i386)
Xextern int sys_nerr, errno;
Xextern char *sys_errlist[];
X#endif
X#endif
X#include <pwd.h>
X#include "globals.h"
X#include "PromptBox.h"
X
Xchar *get_passwd();
XWidget PasswordWindow();
X
Xextern char *time_string(), *timeleft_string(), *timeout_string(),
X     *user_string(), *get_user(), *malloc(), *crypt(), *my_malloc();
Xextern long random();
Xextern void RemoveRoot();
X
X#ifdef PASSWORD_PORT
Xstatic int password_port = -1;
X#endif
X
X
X
XWidget PasswordWindow(which)
Xint which;
X{
X     PromptLine prompt_lines[MAXPROMPT];
X     int i = 0;
X     Widget prompt;
X     
X     switch (which) {
X	case GETTING_FIRST_INITIAL_PASSWORD:
X	case GETTING_SECOND_INITIAL_PASSWORD:
X	case GETTING_LOCKED_PASSWORD:
X	  prompt_lines[i] = default_line;
X	  prompt_lines[i].str = user_string(USER_FORMAT); i++;
X	  prompt_lines[i] = default_line;
X	  prompt_lines[i].name = "time";
X	  prompt_lines[i].str = time_string(TIME_FORMAT, Force); i++;
X	  if (defs.timeout && lock_flag) {
X	       prompt_lines[i] = default_line;
X	       if (which < 3) {
X		    prompt_lines[i].str = timeout_string(TIMEOUT_FORMAT, Force);
X		    i++;
X	       }
X	       else {
X		    prompt_lines[i].str = timeleft_string(TIMELEFT_FORMAT, Force);
X		    i++;
X	       }
X	  }
X	  prompt_lines[i] = default_line;
X	  prompt_lines[i].str = "";
X	  prompt_lines[i].center = False; i++;
X	  prompt_lines[i] = default_line;
X	  if (which != GETTING_SECOND_INITIAL_PASSWORD)
X	       prompt_lines[i].str = PASS_PROMPT1;
X	  else
X	       prompt_lines[i].str = PASS_PROMPT2;
X	  prompt_lines[i].center = False; i++;
X	  prompt_lines[i].spread = 10;
X	  break;
X
X	case SHOWING_CAPSLOCK_WARNING:
X	  prompt_lines[i] = default_line;
X	  prompt_lines[i].str = "";
X	  prompt_lines[i].center = False; i++;
X	  prompt_lines[i] = default_line;
X	  prompt_lines[i].str = "";
X	  prompt_lines[i].center = False; i++;
X	  prompt_lines[i] = default_line;
X	  prompt_lines[i].str = CAPS_LOCK_PROMPT;
X	  prompt_lines[i].center = True; i++;
X	  prompt_lines[i] = default_line;
X	  prompt_lines[i].str = "";
X	  prompt_lines[i].center = False; i++;
X	  prompt_lines[i] = default_line;
X	  prompt_lines[i].str = "";
X	  prompt_lines[i].center = False; i++;
X	  break;
X     }
X	  
X     prompt = CenteredPromptBox(root_widget, "prompt", prompt_lines, i,
X			(Widget *) NULL);
X
X     XtMapWidget(prompt);
X
X     return(prompt);
X}
X
X
X
X
X     
X     
Xchar *get_passwd()
X{
X     struct passwd *pwent;
X     char *user;
X     char *passwd;
X     
X     user = get_user();
X
X     if (! *user)
X	  return((char *) NULL);
X     
X     pwent = getpwnam(user);
X
X     if (pwent) if (strlen(pwent->pw_passwd) == PASSWDLENGTH)
X	  return(pwent->pw_passwd);
X     
X     passwd = malloc(1);
X     *passwd = '\0';
X     return(passwd);
X}
X
X
XBoolean correct_password(passwd)
Xchar *passwd;
X{
X     char seed[3];
X
X     if (*defs.ekey) {
X	  strncpy(seed, defs.ekey, 2);
X	  return(! strcmp(crypt(passwd, seed), defs.ekey));
X     }
X     else if (*defs.key) {
X	  if (! strcmp(passwd, defs.key))
X	       return(True);
X	  else
X	       return(False);
X     }
X     else
X	  return(False);
X}
X
X
X/*
X * Takes the password from defs.key, encrypts it, places its value
X * into defs.ekey, and then zeros out defs.key.  This is basically for
X * security reasons -- if someone gcore's the file or manages to read
X * memory and the key is stored in plaintext, they can read it and do
X * nasty things.
X *
X * There's no sanity checking here -- if there's nothing in defs.key,
X * things will lose.
X * 
X * This is relatively useless when the unencrypted key is given on the
X * command line or put in the user's resources, since the toolkit
X * keeps several copies of the key floating around.  Even if we bzero
X * the copy we have, there are still several others in memory.  It
X * becomes useful when the key is typed in the first time the screen
X * is locked, and since we're assuming that that's what will be
X * happening most of the time, this is a useful procedure.
X */
Xinstall_password()
X{
X     char seed[3];
X     
X     /* Calculate the seed for the password */
X     *seed = *(seed + 1) = *(seed + 2) = 0;
X     do {
X	  *seed = (char) (random() % 0172);
X     } while (! (((*seed >= 056) && (*seed <= 071)) || /* /, ., 0-9 */
X		 ((*seed >= 0101) && (*seed <= 0132)) || /* A-Z */
X		 ((*seed >= 0141) && (*seed <= 0172)))); /* a-z */
X     do {
X	  seed[1] = (char) (random() % 0172);
X     } while (! (((seed[1] >= 056) && (seed[1] <= 071)) || /* /, ., 0-9 */
X		 ((seed[1] >= 0101) && (seed[1] <= 0132)) || /* A-Z */
X		 ((seed[1] >= 0141) && (seed[1] <= 0172)))); /* a-z */
X
X     defs.ekey = my_malloc(PASSWDLENGTH + 1, "install_password");
X     strcpy(defs.ekey, crypt(defs.key, seed));
X
X     bzero(defs.key, strlen(defs.key));
X}
X
X	  
X
X#ifdef PASSWORD_PORT
Xinitialize_password_port()
X{
X     struct sockaddr_in name;
X
X     /* Only do this if the port is positive. */
X     if (defs.password_port <= 0)
X	  return(-1);
X     
X     /* First, get a file descriptor to work with */
X     
X     password_port = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
X     if (password_port < 0) {
X	  /* Forget it, we can't open the socket, so punt trying. */
X	  fprintf(stderr, "%s: couldn't create password socket", whoami);
X	  if (errno < sys_nerr)
X	       fprintf(stderr, ": %s\n", sys_errlist[errno]);
X	  else
X	       fprintf(stderr, "\n");
X	  if (defs.require_port)
X	       exit(1);
X	  password_port = -1;
X	  return(password_port);
X     }
X
X     /* set non-blocking IO on the socket */
X     fcntl(password_port, F_SETFL, FNDELAY);
X     
X     /* Now, bind it to a port. */
X
X     name.sin_family = AF_INET;
X     name.sin_port =  htons((u_short) defs.password_port);
X     name.sin_addr.s_addr = INADDR_ANY;
X
X     if (bind(password_port, (struct sockaddr *) &name, sizeof(name)) < 0) {
X	  fprintf(stderr, "%s: couldn't bind to port %d", whoami,
X		  defs.password_port);
X	  if (errno < sys_nerr)
X	       fprintf(stderr, ": %s\n", sys_errlist[errno]);
X	  else
X	       fprintf(stderr, "\n");
X	  if (errno == EADDRINUSE) {
X	       fprintf(stderr, "%s: Are you running another %s?\n",
X		       whoami, whoami);
X	  }
X	  if (defs.require_port)
X	       exit(1);
X	  password_port = -1;
X	  return(password_port);
X     }
X     
X     listen(password_port, 5);
X
X     /* All done, we've got a socket now */
X     return(password_port);
X}
X
X
X
Xvoid close_password_port()
X{
X     /*
X      * N.B.: I'm not also doing an XtRemoveInput to remove it from
X      * the list of inputs the X toolkit is expecting input from.  I
X      * don't think this'll be a problem, but I'm noting it here, just
X      * in case...
X      */
X     (void) close(password_port);
X}
X
X
X
X /* Note that two connections made at once will produde garbled */
X /* password. 							*/
X/*ARGSUSED*/
Xstatic void get_password_data(client_data, source, id)
Xcaddr_t client_data;
Xint *source;
XXtInputId *id;
X{
X     static int reading = 0;
X     static int tries = 0;
X     static int num_read;
X     static char password[MAXPASSWORD];
X     static char readbuf[1];
X
X     if (! is_locked) {
X	  if (debug_file)
X	       fprintf(debug_file,
X		       "Got port data when screen isn't locked, closing.\n");
X	  close(*source);
X	  XtRemoveInput(*id);
X	  return;
X     }
X     
X     if (reading == 0) {
X	  if (debug_file)
X	       fprintf(debug_file,
X		       "Starting to read password from port.\n");
X	  reading = 1;
X	  num_read = 0;
X	  *password = '\0';
X     }
X     
X     /* I know it's heinous to read one character at a time, but it's */
X     /* easier to program, and this is, after all, only a hack,       */
X     /* anyway. 						      */
X
X     while (read(*source, readbuf, 1) > 0) {
X	  password[num_read] = *readbuf;
X	  if (*readbuf == '\n') {
X	       password[num_read] = '\0';
X	       if (correct_password(password)) {
X		    if (debug_file)
X			 fprintf(debug_file,
X				 "Correct password from port, unlocking and closing.\n");
X		    write(*source, "Password correct, unlocking screen.\n",
X			  36);
X		    RemoveRoot((Widget) NULL, (XEvent *) NULL,
X			       (String *) NULL, (Cardinal *) NULL);
X		    close(*source);
X		    XtRemoveInput(*id);
X		    bzero(password, strlen(password));
X		    return;
X	       }
X	       else {
X		    if (debug_file)
X			 fprintf(debug_file,
X				 "Incorrect password from port.\n");
X		    write(*source, "Password incorrect.\n", 20);
X		    tries++;
X		    if (tries == 6) {
X			 /* Maximum number of tries (6) exceeded */
X			 write(*source, "Maximum number of tries exceeded.\n",
X			       34);
X			 if (debug_file)
X			      fprintf(debug_file,
X				      "Maximum tries on port exceeded.\n");
X			 close(*source);
X			 XtRemoveInput(*id);
X			 tries = 0;
X		    }
X		    reading = 0;
X		    return;
X	       }
X	  }
X	  if ((num_read < MAXPASSWORD - 1) && (*readbuf != '\r'))
X	       num_read += 1;
X     }
X
X     if (errno != EWOULDBLOCK) {
X	  if (debug_file)
X	       fprintf(debug_file,
X		       "Error reading from port, closing.\n");
X	  close(*source);
X	  XtRemoveInput(*id);
X	  reading = 0;
X     }
X
X     return;
X}
X
X     
X
X/*ARGSUSED*/
Xvoid check_password_port(client_data, source, id)
Xcaddr_t client_data;
Xint *source;
XXtInputId *id;
X{
X     int ns;
X     struct sockaddr_in name;
X     int size;
X
X     size = sizeof(struct sockaddr_in);
X     ns = accept(*source, (struct sockaddr *) &name, &size);
X
X     if (ns < 0)
X	  return;
X
X     if (debug_file)
X	  fprintf(debug_file,
X		  "New port connection.\n");
X     
X     /* If we aren't locked, then punt this connection. */
X     if (! is_locked) {
X	  if (debug_file)
X	       fprintf(debug_file, "Screen's not locked, so punting.\n");
X	  close(ns);
X	  return;
X     }
X
X     /* Tell the user what to do. */
X     write(ns, "Type password to unlock screen:\n", 32);
X	   
X     /* Tell the toolkit to read data off of this socket */
X     if (debug_file)
X	  fprintf(debug_file, "Adding new port to X toolkit inputs.\n");
X     XtAppAddInput(app_context, ns,
X		   (XtPointer) (XtInputReadMask | XtInputExceptMask),
X		   get_password_data, (caddr_t) NULL);
X     
X     return;
X}
X#endif /* PASSWORD_PORT */
END_OF_FILE
if test 11103 -ne `wc -c <'password.c'`; then
    echo shar: \"'password.c'\" unpacked with wrong size!
fi
# end of 'password.c'
fi
if test -f 'savescreen.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'savescreen.c'\"
else
echo shar: Extracting \"'savescreen.c'\" \(17688 characters\)
sed "s/^X//" >'savescreen.c' <<'END_OF_FILE'
X/*
X * $Source: /afs/sipb.mit.edu/project/sipbsrc/src/xscreensaver/RCS/savescreen.c,v $
X * $Author: jik $
X *
X * This file is part of xscreensaver.  It contains the code for the
X * actual locking/blanking of the screen, with the floating icon and
X * the handling of passwords.
X *
X * Author: Jonathan Kamens, MIT Project Athena and
X *                          MIT Student Information Processing Board
X *
X * Coyright (c) 1989 by Jonathan Kamens.  This code may be distributed
X * freely as long as this notice is kept intact in its entirety and
X * every effort is made to send all corrections and improvements to
X * the code back to the author.  Also, don't try to make any money off
X * of it or pretend that you wrote it.
X */
X
X#ifndef lint
X     static char rcsid_savescreen_c[] = "$Header: /afs/sipb.mit.edu/project/sipbsrc/src/xscreensaver/RCS/savescreen.c,v 1.45 91/11/03 23:20:52 jik Exp $";
X#endif
X
X#include "xsaver.h"
X#include <signal.h>
X#include <ctype.h>
X#include <X11/Xaw/Command.h>
X#include <X11/Shell.h>
X#include "scaling.h"
X#include "globals.h"
X#include "float.h"
X
Xextern char *my_malloc();
Xextern Cursor blank_cursor();
Xextern Widget PasswordWindow();
Xextern Boolean correct_password();
Xextern void XtMoveWidget();
Xextern Dimension widget_width();
Xextern void exitCallback();
X#ifdef _IBMR2
Xextern void enable_hft_hotkey();
Xextern int disable_hft_hotkey();
X#endif
X
Xvoid build_root(), lock_command(), unlock_command(),
X     ActivateClock(), ReallyLockScreen(), SaveScreen(), PasswordTimeout(),
X     LockScreen();
Xvoid ActivateRoot(), RaiseRoot(), RemoveRoot(), GetPassword();
X
Xstatic int lock_command_pid = 0, did_lock_command = 0;
Xstatic String lockedTransString = 
X     "<Key>:			GetPassword(Locked)\n\
X      <BtnDown>,<BtnUp>:	GetPassword(Locked)\n\
X      <Visible>:		RaiseRoot()\n\
X      <Map>:			RaiseRoot()\n";
Xstatic XtTranslations lockedTrans = (XtTranslations) NULL;
Xstatic Widget root_shell = (Widget) NULL;
Xstatic XtIntervalId password_timeout;
Xstatic struct {
X     int timeout, interval, prefer_blanking, allow_exposures;
X} saver, saver2;
X
X
X#define PASSWORD_TIMEOUT 30	/* time, in seconds, before a password */
X				/* prompt will time out */
X#define WARNING_TIMEOUT 3	/* time, in seconds, to show the */
X				/* caps lock warning */
X
X#ifdef PASSWORD_PORT
Xextern void close_password_port();
X#endif
X
X
X
X
X
Xvoid build_root()
X{
X     Arg arglist[10];
X     int i = 0;
X     Cursor cursor;
X     char geometry[20];
X
X     (void) sprintf(geometry, "%dx%d+0+0", display_width, display_height);
X     if (! root_shell) {
X	  XtSetArg(arglist[i], XtNborderWidth, 0); 			i++;
X	  XtSetArg(arglist[i], XtNx, 0); 				i++;
X	  XtSetArg(arglist[i], XtNy, 0); 				i++;
X	  XtSetArg(arglist[i], XtNwidth, display_width);		i++;
X	  XtSetArg(arglist[i], XtNheight, display_height);		i++;
X	  XtSetArg(arglist[i], XtNgeometry, geometry);			i++;
X#ifndef _IBMR2
X	  /* This doesn't work on the RS/6000 X server... */
X	  if (defs.use_background) {
X	       XtSetArg(arglist[i], XtNbackgroundPixmap,
X			ParentRelative); 				i++;
X	  }
X#endif
X
X	  root_shell = XtCreatePopupShell("rootShell",
X					  overrideShellWidgetClass,
X					  top_widget, arglist, i);
X     
X	  root_widget = XtCreateManagedWidget("root", widgetClass,
X					      root_shell, arglist, i);	i = 0;
X
X	  XtRealizeWidget(root_shell);
X
X	  /* Here lies the direct Xlib trickery your mother warned you */
X	  /* about when she taught you tou use Xtk. */
X	  cursor = blank_cursor();
X	  XDefineCursor(dpy, XtWindow(root_shell), cursor);
X	  XDefineCursor(dpy, XtWindow(root_widget), cursor);
X	  /* Setting the coordinates to 0, 0 appears not to work in some */
X	  /* cases, in particular when people specify Geometry *class* in */
X	  /* the resources, so we are going to reposition the window after */
X	  /* we create it. */
X	  XtMoveWidget(root_shell, 0, 0);
X     }
X}
X
X
X
X
X
X
X/* ARGSUSED */
Xvoid ActivateRoot()
X{
X     int	ret;
X     char	buf[80];
X     XWMHints	*hints;
X
X     /* I'm using CurrentTime here where I shouldn't -- at some point */
X     /* in the future, the code should be fixed to move the map time  */
X     /* of the root window.					      */
X     
X     ActivateClock();
X
X     build_root();
X
X     NewFloat();
X     if (defs.disable_x_screensaver) {
X	  XGetScreenSaver(dpy, &saver.timeout, &saver.interval,
X			  &saver.prefer_blanking, &saver.allow_exposures);
X	  XSetScreenSaver(dpy, 0, saver.interval, saver.prefer_blanking,
X			  saver.allow_exposures);
X     }
X     XtMapWidget(root_shell);
X     XRaiseWindow(dpy, XtWindow(root_shell));
X     /* Window must be mapped for some of the following calls to work, */
X     /* so we flush the display to make sure it gets mapped before     */
X     /* these calls take place. 				       */
X     XSync(dpy, False);
X     if (ret = XGrabPointer(dpy, XtWindow(root_widget), True, ButtonPressMask,
X			    GrabModeAsync, GrabModeAsync,
X			    XtWindow(root_widget), blank_cursor(),
X			    CurrentTime) != GrabSuccess) {
X	  XGetErrorText(dpy, ret, buf, 80);
X	  fprintf(stderr, "%s: %s (%s)!  %s.\n",
X		  whoami, "Error grabbing pointer", buf,
X		  "Giving up on screensaver activation (try again)");
X	  if (debug_file) {
X	       fprintf(debug_file,
X		       "About to unmap root widget 0x%x (window id 0x%x) in ActivateRoot.\n",
X		       root_shell, XtWindow(root_shell));
X	  }
X	  XtUnmapWidget(root_shell);
X	  return;
X     }
X     if (ret = XGrabKeyboard(dpy, XtWindow(root_widget), False, GrabModeAsync,
X			     GrabModeAsync, CurrentTime) != GrabSuccess) {
X	  XGetErrorText(dpy, ret, buf, 80);
X	  fprintf(stderr, "%s: %s (%s)!  %s.\n",
X		  whoami, "Error grabbing keyboard", buf,
X		  "Giving up on screensaver activation (try again)");
X	  if (debug_file) {
X	       fprintf(debug_file,
X		       "About to unmap root widget 0x%x (window id 0x%x) in ActivateRoot.\n",
X		       root_shell, XtWindow(root_shell));
X	  }
X	  XtUnmapWidget(root_shell);
X	  XUngrabPointer(dpy, CurrentTime);
X
X	  return;
X     }
X     XtSetKeyboardFocus(root_shell, root_widget);
X     XSetInputFocus(dpy, XtWindow(root_widget), RevertToPointerRoot,
X		    CurrentTime);
X     /* We need to do this for the ICCCM */
X     hints = XGetWMHints(dpy, XtWindow(root_widget));
X     if (hints) {
X	  hints->input = False;
X	  XSetWMHints(dpy, XtWindow(root_widget), hints);
X	  XtFree((char *) hints);
X     }
X     
X     if (lock_flag) {
X	  is_locked = True;
X	  LockScreen();
X     }
X     else
X	  SaveScreen();
X}
X
X
X
Xstatic void LockScreen()
X{
X     if (! lockedTrans)
X	  lockedTrans = XtParseTranslationTable(lockedTransString);
X     if (! (*defs.ekey || *defs.key)) {
X	  String str = "Initial";
X	  Cardinal num = 1;
X	  GetPassword(root_widget, (XEvent *) NULL, &str, &num);
X     }
X     else
X	  ReallyLockScreen();
X}
X
X
X
Xstatic void ReallyLockScreen()
X{
X#ifdef _IBMR2
X     if (defs.disable_hotkey && disable_hft_hotkey()) {
X	  if (defs.require_hotkey) {
X	       fprintf(stderr, "%s: error disabling HFT hot key.\n%s: Giving up on screen locking.\n%s: To force screen locking, run %s again\n%s: with the \"-requireHotkey\" option.\n", whoami, whoami, whoami, whoami, whoami);
X	       RemoveRoot(0, 0, 0, 0);
X	       return;
X	  }
X	  else {
X	       fprintf(stderr, "%s: warning: error disabling HFT hot key.\n%s: Locking screen anyway.\n", whoami, whoami);
X	  }
X     }
X#endif
X     lock_command();
X     XtOverrideTranslations(root_widget, lockedTrans);
X     XtOverrideTranslations(root_shell, lockedTrans);
X     StartupFloat();
X}     
X
X
Xstatic void SaveScreen()
X{
X     static String rootTranslations =
X	  "<Key>:		RemoveRoot()\n\
X           <BtnDown>,<BtnUp>:	RemoveRoot()\n\
X           <Visible>:		RaiseRoot()\n\
X           <Map>:		RaiseRoot()\n";
X     XtTranslations trans = (XtTranslations) NULL;
X
X     if (! trans)
X	  trans = XtParseTranslationTable(rootTranslations);
X     XtOverrideTranslations(root_widget, trans);
X     XtOverrideTranslations(root_shell, trans);
X     StartupFloat();
X}
X
X
X
X
X
Xstatic void PasswordTimeout()
X{
X     char *str = "Timeout";
X     Cardinal num = 1;
X     GetPassword(root_shell, (XEvent *) NULL, &str, &num);
X}
X
X
X
X
X/* The state machine's states are defined in xsaver.h */
X
X
X
X/* ARGSUSED */
Xvoid GetPassword(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X     static char password[MAXPASSWORD];
X     static char *ptr;
X     static String gettingPasswordTranslations =
X	  "<Key>Return:		GetPassword(Done)\n\
X	   <Key>:		GetPassword(Reading)\n\
X           <Visible>:		RaiseRoot()\n\
X           <Map>:		RaiseRoot()\n";
X     static XtTranslations gettingPasswordTrans = (XtTranslations) NULL;
X     static Widget prompt;
X     static int state = DOING_NOTHING;
X     Arg arglist[2];
X     int i = 0;
X     
X     if (! gettingPasswordTrans)
X	  gettingPasswordTrans =
X	       XtParseTranslationTable(gettingPasswordTranslations);
X     if (**params == 'L') {
X	  DeactivateFloat();
X	  ptr = password;
X	  state = GETTING_LOCKED_PASSWORD;
X	  prompt = PasswordWindow(state);
X	  XtSetArg(arglist[i], XtNtranslations, gettingPasswordTrans);	i++;
X	  XtSetValues(root_shell, arglist, i);
X	  XtSetValues(root_widget, arglist, i);				i = 0;
X	  XtMapWidget(prompt);
X	  password_timeout = XtAppAddTimeOut(app_context,
X					     PASSWORD_TIMEOUT * 1000, 
X					     PasswordTimeout, NULL);
X     }
X     else if (**params == 'I') {
X	  ptr = password;
X	  state = GETTING_FIRST_INITIAL_PASSWORD;
X	  prompt = PasswordWindow(state);
X	  XtOverrideTranslations(root_widget, gettingPasswordTrans);
X	  XtOverrideTranslations(root_shell, gettingPasswordTrans);
X	  XtMapWidget(prompt);
X	  password_timeout = XtAppAddTimeOut(app_context,
X					     PASSWORD_TIMEOUT * 1000, 
X					     PasswordTimeout, NULL);
X     }
X     else if (**params == 'R' && state != SHOWING_CAPSLOCK_WARNING) {
X	  XtRemoveTimeOut(password_timeout);
X	  password_timeout = XtAppAddTimeOut(app_context,
X					     PASSWORD_TIMEOUT * 1000, 
X					     PasswordTimeout, NULL);
X	  if (ptr - password < MAXPASSWORD - 1) {
X	       char key_buf[5];
X	       int num_read;
X	       
X	       num_read = XLookupString(&event->xkey, key_buf, 5,
X					(KeySym *) NULL,
X					(XComposeStatus *) NULL);
X	       if (num_read == 1) {
X		    switch (*key_buf) {
X		    case '\025':
X			 /* Check for ctrl-u first -- ctrl-u clears the */
X			 /* entered password */
X			 ptr = password;
X			 *ptr = '\0';
X			 break;
X		    case '\010':
X		    case '\177':
X			 /* ctrl-h and ctrl-? delete a character */
X			 if (ptr - password > 0) {
X			      ptr--;
X			      *ptr = '\0';
X			 }
X			 break;
X		    default:
X			 *ptr = *key_buf;
X			 ptr++;
X		    }
X	       }
X	  }
X     }
X     else if (**params == 'D') {
X	  XtRemoveTimeOut(password_timeout);
X	  if (debug_file) {
X	       fprintf(debug_file,
X		       "About to unmap prompt widget 0x%x (window id 0x%x) in GetPassword.\n",
X		       prompt, XtWindow(prompt));
X	  }
X	  XtUnmapWidget(prompt);
X	  if (debug_file) {
X	       fprintf(debug_file,
X		       "About to destroy prompt widget 0x%x (window id 0x%x) in GetPassword.\n",
X		       prompt, XtWindow(prompt));
X	  }
X	  XtDestroyWidget(prompt);
X	  if (state == SHOWING_CAPSLOCK_WARNING) {
X	       ReallyLockScreen();
X	  }
X	  else {
X	       *ptr = '\0';
X	       if (state == GETTING_LOCKED_PASSWORD) {
X		    state = DOING_NOTHING;
X		    if (correct_password(password)) {
X			 RemoveRoot(root_shell, (XEvent *) NULL, (String *) NULL,
X				    (Cardinal *) NULL);
X			 bzero(password, strlen(password));
X		    }
X		    else {
X			 int any_uppers = 0, any_lowers = 0;
X			 char *c;
X			 
X			 /* There must be at least one upper */
X			 /* and no lowers! */
X			 c = password;
X			 while (*c) {
X			      any_uppers |= (isupper(*c));
X			      any_lowers |= (islower(*c));
X			      c++;
X			 }
X			 bzero(password, strlen(password));
X			 if (any_uppers && (!any_lowers)) {
X			      state = SHOWING_CAPSLOCK_WARNING;
X			      prompt = PasswordWindow(state);
X			      XtMapWidget(prompt);
X			      password_timeout = XtAppAddTimeOut(app_context,
X								 WARNING_TIMEOUT * 1000, 
X								 PasswordTimeout, NULL);
X			 } 
X			 else {
X			      XtOverrideTranslations(root_widget, lockedTrans);
X			      XtOverrideTranslations(root_shell, lockedTrans);
X			      ActivateFloat();
X			 }
X		    }
X	       }
X	       else if (state == GETTING_FIRST_INITIAL_PASSWORD) {
X		    ptr = password;
X		    if (*ptr) {
X			 state = GETTING_SECOND_INITIAL_PASSWORD;
X			 XtFree(defs.key);
X			 defs.key = my_malloc(strlen(password) + 1,
X					      "password");
X			 strcpy(defs.key, password);
X			 bzero(password, strlen(password));
X			 prompt = PasswordWindow(state);
X			 XtMapWidget(prompt);
X		    }
X		    else { /* User just hit return.  That's a no-no, so ask */
X			 /* for a password again */
X			 char *param = "Initial";
X			 Cardinal num = 1;
X			 
X			 XBell(dpy, 100);
X			 state = DOING_NOTHING;
X			 GetPassword(root_shell, (XEvent *) NULL, &param, &num);
X		    }
X	       }
X	       else if (state == GETTING_SECOND_INITIAL_PASSWORD) {
X		    if (! strcmp(password, defs.key)) {
X			 install_password();
X			 bzero(password, strlen(password));
X		    ReallyLockScreen();
X		    }
X		    else {
X			 char *param = "Initial";
X			 Cardinal num = 1;
X			 
X			 bzero(password, strlen(password));
X			 bzero(defs.key, strlen(defs.key));
X			 state = DOING_NOTHING;
X			 GetPassword(root_shell, (XEvent *) NULL, &param, &num);
X		    }
X	       }
X	  }
X     }
X     else if (**params == 'T') {
X	  if (debug_file) {
X	       fprintf(debug_file,
X		       "About to unmap prompt widget 0x%x (window id 0x%x) in GetPassword.\n",
X		       prompt, XtWindow(prompt));
X	  }
X	  XtUnmapWidget(prompt);
X	  if (debug_file) {
X	       fprintf(debug_file,
X		       "About to destroy prompt widget 0x%x (window id 0x%x) in GetPassword.\n",
X		       prompt, XtWindow(prompt));
X	  }
X	  XtDestroyWidget(prompt);
X	  bzero(password, ptr - password);
X	  if (state == GETTING_LOCKED_PASSWORD || state == SHOWING_CAPSLOCK_WARNING)
X	       ReallyLockScreen();
X	  else if (state == GETTING_FIRST_INITIAL_PASSWORD)
X	       RemoveRoot((Widget) NULL, (XEvent *) NULL, (String *) NULL,
X			  (Cardinal *) NULL);
X	  else if (state == GETTING_SECOND_INITIAL_PASSWORD)
X	       RemoveRoot((Widget) NULL, (XEvent *) NULL, (String *) NULL,
X			  (Cardinal *) NULL);
X     }
X}
X     
X            
X
X
Xstatic void ActivateClock()
X{
X     struct timeval tim;
X
X     gettimeofday(&tim, (struct timezone *) NULL);
X     times.start = tim.tv_sec;
X     times.current = times.start + 1; /* don't ask; if you can't figure */
X				      /* out why I'm adding 1 to this,  */
X				      /* you don't want to know :-)     */
X}     
X
X
X
X
X
Xvoid change_timeout(new_val)
Xchar *new_val;
X{
X     if (! new_val)
X	  return;
X     
X     if (*new_val)
X	  defs.timeout = atoi(new_val);
X     else
X	  defs.timeout = 0;
X#ifdef MAXTIMEOUT
X     if ((defs.timeout > MAXTIMEOUT) || (defs.timeout == 0)) {
X	  fprintf(stderr, "%s: Timeout cannot be greater than %d minutes.\n",
X		  whoami, MAXTIMEOUT);
X	  defs.timeout = MAXTIMEOUT;
X     }
X#endif
X}
X
X
X
X
Xvoid change_lock(new_val)
Xchar *new_val;
X{
X     char *buf;
X
X     if (! new_val)
X	  return;
X	  
X     buf = my_malloc(strlen(new_val) + 1, "lock command");
X     strcpy(buf, new_val);
X     XtFree(defs.lock_command);
X     defs.lock_command = buf;
X}
X
X
X
X
Xvoid change_unlock(new_val)
Xchar *new_val;
X{
X     char *buf;
X
X     if (! new_val)
X	  return;
X     
X     buf = my_malloc(strlen(new_val) + 1, "unlock command");
X     strcpy(buf, new_val);
X     XtFree(defs.unlock_command);
X     defs.unlock_command = buf;
X}
X
X
X
X/* ARGSUSED */
Xvoid RaiseRoot(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X     XRaiseWindow(dpy, XtWindow(root_shell));
X}
X
X
X
X/* ARGSUSED */
Xvoid RemoveRoot(w, event, params, num_params)
XWidget w;
XXEvent *event;
XString *params;
XCardinal *num_params;
X{
X     is_locked = False;
X#ifdef _IBMR2
X     if (defs.disable_hotkey)
X	  enable_hft_hotkey();
X#endif
X     unlock_command();
X     DeactivateFloat();
X     if (debug_file) {
X	  fprintf(debug_file,
X		  "About to unmap root widget 0x%x (window id 0x%x) in RemoveRoot.\n",
X		       root_shell, XtWindow(root_shell));
X     }
X     XtUnmapWidget(root_shell);
X     XUngrabPointer(dpy, CurrentTime);
X     XUngrabKeyboard(dpy, CurrentTime);
X     if (defs.disable_x_screensaver) {
X	  XGetScreenSaver(dpy, &saver2.timeout, &saver2.interval,
X			  &saver2.prefer_blanking, &saver2.allow_exposures);
X	  if ((saver2.timeout == 0) && (saver.interval == saver2.interval) &&
X	      (saver.prefer_blanking == saver2.prefer_blanking) &&
X	      (saver.allow_exposures == saver2.allow_exposures))
X	       /* The saver hasn't been changed underneath us */
X	       XSetScreenSaver(dpy, saver.timeout, saver.interval,
X			       saver.prefer_blanking, saver.allow_exposures);
X     }
X     if (! defs.display_icon)
X	  exitCallback(NULL, NULL, NULL);
X}
X
X
X
X
Xstatic void lock_command()
X{
X     did_lock_command = 1;
X     if ((! lock_command_pid) && (*defs.lock_command)) {
X	  if ((lock_command_pid = fork()) == -1) {
X	       fprintf(stderr, "%s: ", whoami);
X	       perror("executing lock command");
X	       lock_command_pid = 0;
X	  }
X	  else if (! lock_command_pid) {
X	       setpgrp(getpid(), getpid());
X	       XtCloseDisplay(dpy);
X#ifdef PASSWORD_PORT
X	       close_password_port();
X#endif
X	       system(defs.lock_command);
X	       exit(0);
X	  }
X     }
X}
X
X
X
X
X
Xvoid unlock_command()
X{
X     if (! did_lock_command)
X	  return;
X     did_lock_command = 0;
X     if (lock_command_pid) {
X	  killpg(lock_command_pid, SIGTERM);
X	  lock_command_pid = 0;
X     }
X     if (lock_flag && *defs.unlock_command) {
X	  int pid;
X
X	  if ((pid = fork()) == -1) {
X	       fprintf(stderr, "%s: ", whoami);
X	       perror("executing unlock command");
X	  }
X	  else if (! pid) {
X	       XtCloseDisplay(dpy);
X#ifdef PASSWORD_PORT
X	       close_password_port();
X#endif
X	       system(defs.unlock_command);
X	       exit(0);
X	  }
X     }
X}
X
X
X
END_OF_FILE
if test 17688 -ne `wc -c <'savescreen.c'`; then
    echo shar: \"'savescreen.c'\" unpacked with wrong size!
fi
# end of 'savescreen.c'
fi
if test -f 'xsaver.man.s' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xsaver.man.s'\"
else
echo shar: Extracting \"'xsaver.man.s'\" \(11400 characters\)
sed "s/^X//" >'xsaver.man.s' <<'END_OF_FILE'
X.\"
X.\" $Source: /afs/sipb.mit.edu/project/sipbsrc/src/xscreensaver/RCS/xsaver.man.s,v $
X.\" $Author: jik $
X.\" $Header: /afs/sipb.mit.edu/project/sipbsrc/src/xscreensaver/RCS/xsaver.man.s,v 1.17 91/11/03 23:21:05 jik Exp $
X.\"
X.\" This file is part of xscreensaver.  It's the man page
X.\" (obviously).
X.\"
X.\" Author: Jonathan Kamens, MIT Project Athena and
X.\"                          MIT Student Information Processing Board
X.\"
X.\" Copyright (c) 1989 by Jonathan Kamens.  This code may be
X.\" distributed freely as long as this notice is kept intact in its
X.\" entirety and every effort is made to send all corrections and
X.\" improvements to the code back to the author.  Also, don't try to
X.\" make any money off of it or pretend that you wrote it. 
X.\"
X.TH $TARGET SIPB "22 January  1989" "X Version 11"
X.SH NAME
X$TARGET \- blanks and/or locks display
X.SH SYNOPSIS
X.B $TARGET
X[
X.B X toolkit options
X] [
X.B $TARGET options 
X]
X.SH DESCRIPTION
X.I $TARGET
Xis a client application running under the X Window System that blanks
Xand/or locks the display when activated.
XThe display is restored by pressing a key or a mouse button, and then 
Xentering the appropriate password if the screen is locked.
X.PP
XWhen executed,
X.I $TARGET
Xsplits off a child process to run in the background.  Two default
X.IR bitmap (1)
Xfiles are loaded, one to serve as the
X.I $TARGET
Xcommand icon (and icon pixmap) and one to bounce
Xaround the display with other useful information when the screen saver 
Xis activated.  Also, the X server screensaver is deactivated when
X.I $TARGET
Xis either blanking or locking the screen.
X.PP
XWhen
X.I $TARGET
Xis not activated, it manifests itself as a small icon (whose position
Xdefaults to the upper left corner of the screen).  Clicking the left
Xor right mouse button on the icon will cause the screen to lock or
Xblank, depending on whether the auto-lock option has been selected.
XClicking and holding the middle mouse button will bring up a menu for
Xeight items: change auto-lock state, blank screen, lock screen, change
Xtimeout, change lock command, change unlock command, change lock
Xmessage, and exit.  Drag the mouse cursor to the proper selection and
Xrelease the mouse button to select.  To get rid of the menu without
Xselecting anything, move the mouse out of the menu and release the
Xmouse button, or type `q' with the mouse cursor in the menu.
X.PP
XWhen entering new timeout, lock command, unlock command, or lock
Xmessage values, entering a blank value will cancel the existing value.
XTyping Return (or Ctrl-Return for the lock message) will accept the
Xcurrently typed value, while
XCtrl-Delete (or Ctrl-Backspace, depending on your keyboard
Xconfiguration) will cancel your changes.
X.PP
XWhen
X.I $TARGET
Xlocks, it attempts to use the user's password in the
X.I /etc/passwd
Xfile as the password to unlock the display.  If that password is 
Xunuseable for some reason and the user has not specified an alternate
Xkey on the command line or in the X resource database (see below),
X.I $TARGET
Xwill prompt for a password when the screen is first locked, and will not allow
Xthe screen to be locked unless the same password is typed twice at
Xthe prompt.
X.PP
XOn some systems,
X.I $TARGET
Xwill listen on a network port (SIPB default port 32253) when the
Xscreen is locked.  If a connection is received on that port, an
Xattempt to read the user's password from it is made; if the correct
Xpassword is read, the screen is unlocked.
X.PP
XWhen
X.I $TARGET
Xstarts up, it attempts to write its process ID number into the file
X.I /tmp/$APPCLASS.$DISPLAY.pid, where $DISPLAY is the name of the X
Xdisplay on which it is running.
X.\" Sending a USR1 signal (see \fIsigvec\fR(2)) to the
X.\" .I $TARGET
X.\" process will cause the screen to immediately lock.
X.PP
XMany of the program defaults are defined in the file
X.I $APPDIR/$APPTARGET.
XTo find out the specific resource strings which may be used to set
Xdefault fonts and other defaults, users should refer to that file.
X.SH OPTIONS
X.I $TARGET
Xwill accept all X toolkit command-line options and resource database 
Xspecifications, using the instance
X.I $TARGET
Xor the class
X.I $APPCLASS;
Xfor more information, see
X.IR X (1).
XIn addition,
X.I $TARGET
Xwill accept the following command-line options (or resource database 
Xspecifications):
X.TP
X.B -b (icon.bitmap, float.bitmap)
XThe
X.B -b
Xoption allows the user to specify the bitmap that will be used both for the
X.I $TARGET
Xcommand icon and for the bouncing icon.  The X resource
X.B icon.bitmap
Xspecifies the command icon bitmap, while
X.B float.bitmap
Xspecifies the bouncing icon bitmap.
X.TP
X.B -B (useBackground = true)
XCauses the root window's pattern or color to be used as the background of the screen when
X.I $TARGET
Xis blanked or locked.  This option is ineffective on IBM RS/6000
Xworkstations, since it doesn't work properly due to a bug in the X
Xserver.
X.TP
X.B -v (velocity)
XSpecifies the velocity of the bouncing icon, supposedly in centimeters
Xper second.  The default is 40.  Must be greater than 0.
X.TP
X.B -l (autoLock = true)
XSets the auto-lock function of the screen saver.  When auto-lock is set, 
Xclicking the left or middle mouse button on the
X.I $TARGET
Xicon will cause the screen to lock.  Otherwise, doing so will only cause
Xthe screen to blank.
X.TP
X.B -dtime (displayTime = true)
X.br
X.ns
X.HP 5
X.B +dtime (displayTime = false)
X.br
XWhen dtime is set to true, the current time will be displayed in the
Xbouncing icon.  When it is set to false, the current time will not be
Xdisplayed.
X.TP
X.B -delapsed (displayElapsed = true)
X.br
X.ns
X.HP 5
X.B +delapsed (displayElapsed = false)
X.br
XControls the display of the elapsed time in the bouncing icon.
X.TP
X.B -dtimeout (displayTimeout = true)
X.br
X.ns
X.HP 5
X.B +dtimeout (displayTimeout = false)
X.br
XControls the display of the time left before
X.I $TARGET
Xtimes out in the bouncing icon.
X.TP
X.B -dtimes (DisplayTimes = true) 
X.br
X.ns
X.HP 5
X.B +dtimes (DisplayTimes = false)
X.br
XA class toggle option which controls dtime, delapsed and dtimeout.
X.TP
X.B -xsaver (disableXScreenSaver = false)
XTells
X.I $TARGET
Xnot to disable the X server's screen saver when blanking or locking
Xthe screen.
X.TP
X.B -t (timeout)
XThe timeout, specified in minutes, tells
X.I $TARGET
Xhow long to leave the screen locked before automatically unlocking it and
Xexiting (and logging the user out, if 
X.I $TARGET
Xhas been configured to do this by the installer).  Some sites may have
Xa default timeout hard-coded into the program,
Xand some sites may have a maximum timeout.  To specify no timeout, specify
Xa timeout of 0 minutes.
X.TP
X.B -key (key)
XSpecify a plaintext password to use for locking the screen.
X.TP
X.B -ekey (encryptedKey)
XSpecify an encrypted password, in standard Unix
X.IR crypt (3)
Xformat, for locking the screen.
X.TP
X.B -port (passwordPort)
XOn systems for which unlocking of the screen by port is enabled,
Xspecify the port to which
X.I $TARGET
Xshould listen when the screen is locked.
X.TP
X.B +port (passwordPort = 0)
XOn systems for which unlocking of the screen by port is enabled,
Xdisables this feature so that the screen cannot be unlocked by
Xconnecting to a port.
X.TP
X.B -requirePort (requirePort = false)
XOn systems for which unlocking of the screen by port is enabled, tells
X.I $TARGET
Xto start up even if attempts to bind to the port fail.
X.TP
X.B +requirePort (requirePort = true)
XRequire the password port to be bound successfully or exit if it
Xcannot be bound.
X.TP
X.B -npw (usePasswd = false)
XWhen this command-line option or X resource is specified,
X.I $TARGET
Xwill ignore the entry in the
X.IR /etc/passwd
Xfile and prompt for a password instead.  Note that it is not necessary
Xto specify this option if the
X.B -key
Xor
X.B -ekey
Xoption is specified.
X.TP
X.B -lc, +lc (lockCommand)
XThe
X.BR -lc
Xoption allows the user to specify a command line to be executed by the 
X.IR system (3)
Xsystem call each time the screen is locked.  When the screen is unlocked, the
Xprocess executing the command will be killed (with the TERM signal --
Xsee
X.IR sigvec(2))
Xif it has not already exited.  The
X.BR +lc
Xoption disables any lock commands specified in X resources, and is
Xuseful as an override when the user wants to temporarily turn off the
Xlock command.
X.TP
X.B -uc, +uc (unlockCommand)
XThe
X.BR -uc
Xoption allows the user to specify a command line to be executed each time
Xthe screen is unlocked.  The process executing the command will
X.B not
Xbe killed by
X.I $TARGET
Xso the user should be sure that any command specified using this option
Xwill exit on its own.  The
X.BR +uc
Xoption disables any resource unlock commands.
X.TP
X.B -nofork (noFork)
XPrevents
X.I $TARGET
Xfrom forking into the background when it starts up.
X.TP
X.B -mb (menuButton)
XThis option allows the user to specify which of the three mouse
Xbuttons (1, 2, or 3), when pressed on the
X.I $TARGET
Xicon, should cause the menu to pop up.  The default is
X.BR -mb 2.
X.TP
X.B -cl (leaveClose = true)
XWhen this option is specified, the
X.I $TARGET
Xmenu automatically goes up when the mouse cursor leaves it, without
Xwaiting for the button to be released outside of the window.
X.TP
X.B -L (startLocked = true)
XWhen this flag is specified,
X.I $TARGET
Xwill start up in locked mode.
X.TP
X.B -m (lockMessage)
XThis option allows the user to specify a short message to be displayed
Xin the floating icon when the screen is blanked or locked.  The
Xmessage text 
Xshould be one command-line option following the flag, so if it is
Xspecified on the command line and is more
Xthan one word, it should be placed in quotes or spaces should be quoted.
X.TP
X.B +icon (displayIcon = false)
XWhen this option is specified,
X.I $TARGET
Xwill refrain from displaying the button icon, and will
Xinstead immediately blank the screen or lock it (if \fBautoLock\fR or
X\fBstartLocked\fR are true).  When the screen is unblanked or
Xunblocked,
X.I $TARGET
Xexits.
X.TP
X.B -icon (displayIcon = true)
XThis option forces the button icon to displayed.  It is the default.
X.TP
X.B -/+disableHotkey (disableHotkey = false, true)
XOn the IBM RS/6000 workstation, determines whether
X.I $TARGET
Xshould attempt to disable the ability to switch between HFTs when the
Xscreen is locked.  Defaults to true.
X.TP
X.B -/+requireHotkey (requireHotkey = false, true)
XOn the IBM RS/6000 workstation, determines whether
X.I $TARGET
Xshould require that HFT switching be disabled before locking the
Xscreen.  If this is false,
X.B disableHotkey
Xis true and
X.I $TARGET
Xis unable to disable HFT switching when it is
Xasked to lock the screen, it will print an error and refuse to lock.
XOtherwise, a failure to disable HFT switching will cause a warning to
Xbe printed, but the screen will be locked anyway.
X.SH FILES
X.TP \w'$APPDIR/$APPTARGET'u+4n
X$BITMAPDIR/$ICONBITMAP
XDefault icon bitmap.
X.TP
X$BITMAPDIR/$FLOATBITMAP
XDefault bouncing icon bitmap.
X.TP
X$BITMAPDIR/$ICONPIXMAP
XDefault window-manager icon bitmap.
X.TP
X$APPDIR/$APPTARGET
X.I $TARGET
Xprogram defaults.
X.TP
X~/.Xresources
XUser X resource database file.
X.TP
X/tmp/$APPCLASS.$DISPLAY.pid
XProcess ID of the program.
X.TP
X/dev/hft
XOn the IBM RS/6000, the device that is accessed in order to obtain a
Xnew HFT when disabling HFT switching.
X.SH SEE ALSO
XX(1), bitmap(1), lock(1), xfree(1)
X.SH AUTHOR
XWritten by Jonathan Kamens, MIT Project Athena and MIT Student Information
XProcessing Board, for X Version 11 and the X toolkit
X.PP
XOriginal idea by Edward Moy, Academic Computing Services, University of
XCalifornia at Berkeley, for X Version 10
END_OF_FILE
if test 11400 -ne `wc -c <'xsaver.man.s'`; then
    echo shar: \"'xsaver.man.s'\" unpacked with wrong size!
fi
# end of 'xsaver.man.s'
fi
echo shar: End of archive 3 \(of 3\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
