v03i050: one more lockscreen program, Part01/01

Mike Wexler mikew at wyse.wyse.com
Sat Mar 11 06:41:25 AEST 1989


Submitted-by: raj at tertius.ics.uci.edu (Richard Johnson)
Posting-number: Volume 3, Issue 50
Archive-name: xgone/part01

#! /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 1 (of 1)."
# Contents:  README AUTHOR Imakefile Makefile patchlevel.h xgone.c
#   xgone.man
# Wrapped by mikew at wyse on Fri Mar 10 12:39:37 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(291 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X     Xgone locks the screen until the current user's password  is
X     entered.  While waiting, it displays a message telling where
X     the person went and when they started the program and  moves
X     this  text  around  the screen to avoid burning them in at a
X     particular location.
X
END_OF_FILE
if test 291 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'AUTHOR' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'AUTHOR'\"
else
echo shar: Extracting \"'AUTHOR'\" \(843 characters\)
sed "s/^X//" >'AUTHOR' <<'END_OF_FILE'
X(Message inbox:1234)
XReturn-Path: news at PARIS.ICS.UCI.EDU
XReceived:  by wyse.wyse.com (5.58/Wyse master/5-13-88)
X	id AA14084; Fri, 10 Mar 89 09:53:24 PST
XReceived: from ucsd.edu by uunet.UU.NET (5.61/1.14) with SMTP 
X	id AA05007; Fri, 10 Mar 89 00:25:46 -0500
XReceived: from paris.ics.uci.edu by ucsd.edu; id AA17980
X	sendmail 5.60/UCSD-1.0
X	Thu, 9 Mar 89 19:57:29 PST
XTo: comp-sources-x%ucsd.edu at PARIS.ICS.UCI.EDU
XPath: uci-ics!tertius.ics.uci.edu!raj
XFrom: raj%tertius.ics.uci.edu at PARIS.ICS.UCI.EDU
XNewsgroups: comp.sources.x
XSubject: The "gone" program for X11
XMessage-Id: <8916 at paris.ics.uci.edu>
XDate: 10 Mar 89 03:52:07 GMT
XSender: news at PARIS.ICS.UCI.EDU
XReply-To: <raj%tertius.ics.uci.edu at PARIS.ICS.UCI.EDU>
XOrganization: University of California, Irvine - Dept of ICS
XLines: 890
XSource-Info:  From (or Sender) name not authenticated.
X
X
END_OF_FILE
if test 843 -ne `wc -c <'AUTHOR'`; then
    echo shar: \"'AUTHOR'\" unpacked with wrong size!
fi
# end of 'AUTHOR'
fi
if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Imakefile'\"
else
echo shar: Extracting \"'Imakefile'\" \(107 characters\)
sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
X           SRCS = xgone.c
X           OBJS = xgone.o
XLOCAL_LIBRARIES = $(XLIB)
X
XComplexProgramTarget(xgone)
END_OF_FILE
if test 107 -ne `wc -c <'Imakefile'`; then
    echo shar: \"'Imakefile'\" unpacked with wrong size!
fi
# end of 'Imakefile'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(6418 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Makefile generated by imake - do not edit!
X# $XConsortium: imake.c,v 1.37 88/10/08 20:08:30 jim Exp $
X#
X# The cpp used on this machine replaces all newlines and multiple tabs and
X# spaces in a macro expansion with a single space.  Imake tries to compensate
X# for this, but is not always successful.
X#
X
X###########################################################################
X# X Window System Makefile generated from template file Imake.tmpl
X# $XConsortium: Imake.tmpl,v 1.91 88/10/23 22:37:10 jim Exp $
X#
X# Do not change the body of the imake template file.  Server-specific
X# parameters may be set in the appropriate .macros file; site-specific
X# parameters (but shared by all servers) may be set in site.def.  If you
X# make any changes, you'll need to rebuild the makefiles using
X# "make World" (at best) or "make Makefile; make Makefiles" (at least) in
X# the top level directory.
X#
X# If your C preprocessor doesn't define any unique symbols, you'll need
X# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
X# "make Makefile", "make Makefiles", or "make World").
X#
X# If you absolutely can't get imake to work, you'll need to set the
X# variables at the top of each Makefile as well as the dependencies at the
X# bottom (makedepend will do this automatically).
X#
X
X###########################################################################
X# platform-specific configuration parameters - edit Sun.macros to change
X
X# platform:  $XConsortium: Sun.macros,v 1.52 88/10/23 11:00:55 jim Exp $
X# operating system:   SunOS 3.4
X
XBOOTSTRAPCFLAGS =
X             AS = as
X             CC = cc
X            CPP = /lib/cpp
X             LD = ld
X           LINT = lint
X        INSTALL = install
X           TAGS = ctags
X             RM = rm -f
X             MV = mv
X             LN = ln -s
X         RANLIB = ranlib
XRANLIBINSTFLAGS = -t
X             AR = ar clq
X             LS = ls
X       LINTOPTS = -xz
X    LINTLIBFLAG = -C
X           MAKE = make
XSTD_CPP_DEFINES =
X    STD_DEFINES =
X
X###########################################################################
X# site-specific configuration parameters - edit site.def to change
X
X# site:  $XConsortium: site.def,v 1.16 88/10/12 10:30:24 jim Exp $
X
X###########################################################################
X# definitions common to all Makefiles - do not edit
X
X          SHELL =  /bin/sh
X
X        DESTDIR = /global
X      USRLIBDIR = $(DESTDIR)/lib
X         BINDIR = $(DESTDIR)/bin/X11
X         INCDIR = $(DESTDIR)/include
X         ADMDIR = $(DESTDIR)/usr/adm
X         LIBDIR = $(USRLIBDIR)/X11
X     LINTLIBDIR = $(USRLIBDIR)/lint
X        FONTDIR = $(LIBDIR)/fonts
X       XINITDIR = $(LIBDIR)/xinit
X         XDMDIR = $(LIBDIR)/xdm
X         UWMDIR = $(LIBDIR)/uwm
X         AWMDIR = $(LIBDIR)/awm
X         TWMDIR = $(LIBDIR)/twm
X          DTDIR = $(LIBDIR)/dt
X        MANPATH = /usr/man
X  MANSOURCEPATH = $(MANPATH)/man
X         MANDIR = $(MANSOURCEPATH)n
X      LIBMANDIR = $(MANSOURCEPATH)n3
X    XAPPLOADDIR = $(LIBDIR)/app-defaults
X
X   INSTBINFLAGS = -m 0755
X   INSTUIDFLAGS = -m 4755
X   INSTLIBFLAGS = -m 0664
X   INSTINCFLAGS = -m 0444
X   INSTMANFLAGS = -m 0444
X   INSTAPPFLAGS = -m 0444
X  INSTKMEMFLAGS = -m 4755
X        FCFLAGS = -t
X    CDEBUGFLAGS = -O
X
X        PATHSEP = /
X         DEPEND = $(BINDIR)/makedepend
X          IMAKE = $(BINDIR)/imake
X            RGB = $(LIBDIR)/rgb
X             FC = $(BINDIR)/bdftosnf
X      MKFONTDIR = $(BINDIR)/mkfontdir
X      MKDIRHIER = $(BINDIR)/mkdirhier.sh
X
X         CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(STD_DEFINES) $(DEFINES)
X      LINTFLAGS = $(LINTOPTS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) -DLINT
X        LDFLAGS = $(CDEBUGFLAGS) -L$(USRLIBDIR) $(SYS_LIBRARIES) $(SYSAUX_LIBRARIES)
X
X       IRULESRC = $(LIBDIR)/imake.includes
X
X   EXTENSIONLIB = $(USRLIBDIR)/libext.a
X           XLIB = $(USRLIBDIR)/libX11.a
X         XMULIB = $(USRLIBDIR)/libXmu.a
X        OLDXLIB = $(USRLIBDIR)/liboldX.a
X       XTOOLLIB = $(USRLIBDIR)/libXt.a
X         XAWLIB = $(USRLIBDIR)/libXaw.a
X       LINTXLIB = $(USRLIBDIR)/lint/llib-lX11.ln
X        LINTXMU = $(USRLIBDIR)/lint/llib-lXmu.ln
X      LINTXTOOL = $(USRLIBDIR)/lint/llib-lXt.ln
X        LINTXAW = $(USRLIBDIR)/lint/llib-lXaw.ln
X       INCLUDES = -I$(INCDIR)
X      MACROFILE = Sun.macros
X   ICONFIGFILES = $(IRULESRC)/Imake.tmpl \
X			$(IRULESRC)/$(MACROFILE) $(IRULESRC)/site.def
X  IMAKE_DEFINES =
X      IMAKE_CMD = $(NEWTOP)$(IMAKE) -TImake.tmpl -I$(NEWTOP)$(IRULESRC) \
X			-s Makefile $(IMAKE_DEFINES)
X         RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a \
X			.emacs_* tags TAGS make.log MakeOut
X
X###########################################################################
X# rules:  $XConsortium: Imake.rules,v 1.71 88/10/23 22:46:34 jim Exp $
X
X###########################################################################
X# start of Imakefile
X
X           SRCS = xgone.c
X           OBJS = xgone.o
XLOCAL_LIBRARIES = $(XLIB)
X
X PROGRAM = xgone
X
Xall:: xgone
X
Xxgone: $(OBJS) $(LOCAL_LIBRARIES)
X	$(RM) $@
X	$(CC) -o $@ $(OBJS) $(LOCAL_LIBRARIES) $(LDFLAGS) $(SYSLAST_LIBRARIES)
X
Xrelink::
X	$(RM) $(PROGRAM)
X	$(MAKE) $(MFLAGS) $(PROGRAM)
X
Xinstall:: xgone
X	$(INSTALL) -c $(INSTALLFLAGS) xgone $(BINDIR)
X
Xinstall.man:: xgone.man
X	$(INSTALL) -c $(INSTMANFLAGS) xgone.man $(MANDIR)/xgone.n
X
Xdepend:: $(DEPEND)
X
Xdepend::
X	$(DEPEND) -s "# DO NOT DELETE" -- $(CFLAGS) -- $(SRCS)
X
X$(DEPEND):
X	@echo "making $@"; \
X	cd $(DEPENDSRC); $(MAKE)
X
Xclean::
X	$(RM) $(PROGRAM)
X
X###########################################################################
X# Imake.tmpl common rules for all Makefiles - do not edit
X
Xemptyrule::
X
Xclean::
X	$(RM_CMD) \#*
X
XMakefile:: $(IMAKE)
X
XMakefile:: Imakefile \
X	$(IRULESRC)/Imake.tmpl \
X	$(IRULESRC)/Imake.rules \
X	$(IRULESRC)/site.def \
X	$(IRULESRC)/$(MACROFILE)
X	- at if [ -f Makefile ]; then \
X	echo "$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
X	$(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
X	else exit 0; fi
X	$(IMAKE_CMD) -DTOPDIR=$(TOP)
X
X$(IMAKE):
X	@echo "making $@"; \
X	cd $(IMAKESRC); $(MAKE) BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS)
X
Xtags::
X	$(TAGS) -w *.[ch]
X	$(TAGS) -xw *.[ch] > TAGS
X
X###########################################################################
X# empty rules for directories that do not have SUBDIRS - do not edit
X
Xinstall::
X	@echo "install done"
X
Xinstall.man::
X	@echo "install.man done"
X
XMakefiles::
X
X###########################################################################
X# dependencies generated by makedepend
X
END_OF_FILE
if test 6418 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(21 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X#define PATCHLEVEL 0
END_OF_FILE
if test 21 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
if test -f 'xgone.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xgone.c'\"
else
echo shar: Extracting \"'xgone.c'\" \(14177 characters\)
sed "s/^X//" >'xgone.c' <<'END_OF_FILE'
X/*
X * Lockscreen for X windows
X * Tim Morgan 2/25/87
X * 
X * Modified for X11 by Richard Johnson
X * Modified/Rewritten extensively afterwards.
X */
X
X#include <X11/Xlib.h>
X#include <stdio.h>
X#include <pwd.h>
X#include <signal.h>
X#include <X11/Xos.h>
X
X#define	SLEEP_TIME	2		/* Seconds, of course */
X#define FONT		"fixed"		/* BORING! (but always there) */
X#define SEPARATION	2		/* ... between lines */
X#define DISPLAYNAME	""
X#define DELAYTIME	2		/* delay time for "-delay" option */
X#define FALSE		0
X#define TRUE		1
X#define UTMP		"/etc/utmp"	/* the utmp file */
X#define control(a)	((a) - ('@'))	/* control characters */
X
Xchar	DspMsg[1024]="X Gone";	/* Default message to display */
Xchar	*Dsptime="Started: ";		/* Time command was started */
Xint	fontheight;			/* height of one line of text */
XPixmap	textpixmap;			/* pixmap to hold text */
Xint	textwidth, textheight;		/* sizes of whole text area */
Xint	Sleeptime=SLEEP_TIME;		/* sleep time between updates */
Xint	Delay=FALSE;			/* Delay startup (for twm) */
Xint	lastx=0, lasty=0;		/* last coord's of text */
Xfd_set	select_mask, sel_mask;		/* for select stuff */
Xint	select_bits;			/* width of select_mask */
Xstruct timeval	sleeptime;		/* for selects */
Xchar	*index();			/* from C lib. */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X    Display			*dpy;
X    XSetWindowAttributes	xswa;
X    Visual			visual;
X    Window			w;
X    GC				gc;
X    XGCValues			gcvalues;
X    XEvent			in;
X    XFontStruct			*font;
X    XColor			blackcolor;
X    XColor			whitecolor;
X    Pixmap			pixmap;
X    Cursor			cursor;
X    char			buffer[100], inputbuf[80], *string, *user_name
X				,*getenv(), *ctime(), *rindex(), response[100];
X    char			*crypt(), *pw, root_pw[20], *user_passwd;
X    int				len, password_bad = 1, response_i, nbytes, i;
X    struct passwd		*u;
X    char			*myname, *dspptr;
X    short			*bits;
X    int				width, lenwidth;
X    int				timeout, interval,
X				preference, allowexp;
X    static char			fontname[80]={FONT};
X
X    if((myname = rindex(argv[0], '/')) == NULL)
X	myname = argv[0];
X    else
X	myname++;
X
X    if (! verify(getuid(), getenv("DISPLAY"))) {
X	fprintf(stderr, "I can't open that display  -  sorry...\n");
X	exit(1);
X    } 
X    
X    if ((dpy = XOpenDisplay(DISPLAYNAME)) == NULL) {
X	fprintf(stderr, "%s: Can't open display '%s'\n",
X		myname, XDisplayName(DISPLAYNAME));
X	exit(1);
X    }
X/*
X * Get the defaults
X */
X    if((string = XGetDefault(dpy, myname, "Font")) != NULL)
X	strcpy(fontname, string);
X    if((string = XGetDefault(dpy, myname, "Text")) != NULL)
X	strcpy(DspMsg, string);
X    if((string = XGetDefault(dpy, myname, "Sleep")) != NULL)
X	Sleeptime = atoi(string);
X    if((string = XGetDefault(dpy, myname, "Update")) != NULL)
X	Sleeptime = atoi(string);
X    if((string = XGetDefault(dpy, myname, "Delay")) != NULL)
X	if(strcmp(string, "off") == 0 || strcmp(string, "0") == 0
X	   || strcmp(string, "no") == 0)
X	    Delay = FALSE;
X	else
X	    Delay = TRUE;
X	    
X/*
X * Parse arguments
X */
X    for(--argc , ++argv ; *argv && **argv == '-' ; argv++ , argc--) {
X	++*argv;
X	if(strcmp(*argv, "fn") == 0 || strncmp(*argv, "font", 1) == 0)
X	    strcpy(fontname, *++argv);	/* save font name */
X	else if(strncmp(*argv, "sleep", 1) == 0
X	   || strncmp(*argv, "update", 1) == 0)
X	    Sleeptime = atoi(*++argv);
X	else if(strncmp(*argv, "delay", 1) == 0)
X	    Delay = TRUE;
X    }
X
X/*
X * If we should delay startup, then fork and exit the parent right now.
X * (This way, "twm" changes the cursor back to the original one and lets
X *  go of the mouse so that we can grab it.)
X */
X    if(Delay)
X	switch(fork()) {
X	case 0:	/* child  -  continue with program */
X	    sleep(DELAYTIME);
X	    break;
X
X	case -1:	/* error during fork  -  exit */
X	    fprintf(stderr, "Can't fork - ");
X	    perror("");
X	    exit(1);
X
X	default:	/* parent  -  exit */
X	    exit(0);
X	}
X
X/*
X * Get the message
X */
X    dspptr = DspMsg;
X    if( *argv ) strcpy(dspptr, "\0");
X    while( *argv ) {
X	strcat(dspptr, *argv++);
X	strcat(dspptr, " ");
X    }
X
X/*
X * Set random number generator
X */
X    srandom(time(0));
X
X/*
X * Make a big window to cover the screen
X */
X    xswa.background_pixel = BlackPixel(dpy, DefaultScreen(dpy));
X    xswa.override_redirect = True;
X    visual.visualid = CopyFromParent;
X    w = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, 9999, 9999,
X		      0, DefaultDepth(dpy, DefaultScreen(dpy)), InputOutput,
X		&visual, CWBackPixel | CWOverrideRedirect, &xswa);
X
X/*
X * Get their chosen font information
X */
X    font = XLoadQueryFont(dpy, fontname);
X    fontheight = font->max_bounds.ascent
X	+ font->max_bounds.descent + SEPARATION;
X
X/*
X * Make sure we get the events we want
X */
X    i = ButtonPressMask | ExposureMask | KeyPressMask | VisibilityChangeMask;
X    XSelectInput(dpy, w, i);
X
X/*
X * The infamous GC!  (Oh no!!  Not the *GC*!!!  ARRRGGHHH!! :-)   )
X */
X    gcvalues.font = font->fid;
X    gcvalues.fill_style = FillOpaqueStippled;
X    gcvalues.foreground = WhitePixel(dpy, DefaultScreen(dpy));
X    gcvalues.background = BlackPixel(dpy, DefaultScreen(dpy));
X    gc = XCreateGC(dpy, w, GCFont|GCFillStyle|GCForeground|GCBackground
X		   , &gcvalues);
X
X    XMapWindow(dpy, w);		/* put it up on the screen 	 */
X
X/*
X * Get rid of the cursor
X */
X    pixmap = XCreatePixmap(dpy, w, 1, 1
X		, DefaultDepth(dpy, DefaultScreen(dpy)));
X    XSetForeground(dpy, gc, BlackPixel(dpy, DefaultScreen(dpy)));
X    XFillRectangle(dpy, pixmap, gc, 0, 0, 1, 1);
X    XSetForeground(dpy, gc, WhitePixel(dpy, DefaultScreen(dpy)));
X    blackcolor.pixel = BlackPixel(dpy, DefaultScreen(dpy));
X    whitecolor.pixel = WhitePixel(dpy, DefaultScreen(dpy));
X    cursor = XCreatePixmapCursor(dpy, pixmap, None,
X	&blackcolor, &whitecolor, 0, 0);
X    XDefineCursor(dpy, w, cursor);
X
X/*
X * Grab mouse and keyboard at same time
X */
X    if((i = XGrabPointer(dpy, w, False, ButtonPressMask, GrabModeAsync,
X	GrabModeAsync,
X	w, cursor, CurrentTime)) != GrabSuccess) {
X	fprintf(stderr, "Can't grab mouse\n");
X	XDestroyWindow(dpy, w);
X	exit(1);
X    }
X
X/*
X * Turn off the screen saver control to make sure they see our window
X * (But make sure you can turn it back on again in the right way!)
X */
X    XGetScreenSaver(dpy, &timeout, &interval, &preference, &allowexp);
X    XSetScreenSaver(dpy, 0, interval, preference, allowexp);
X
X    u = getpwuid(0);
X    if (u)
X	strcpy(root_pw, u->pw_passwd);
X    else
X	root_pw[0] = '\0';
X
X    u = getpwuid(getuid());
X    if (u == NULL) {
X	fprintf(stderr, "Who are you?\n");
X	exit(1);
X    }
X    user_name = u->pw_name;
X    user_passwd = u->pw_passwd;
X
X    sprintf(buffer, "Enter password for user %s:", user_name);
X    len = strlen(buffer);
X    lenwidth = XTextWidth(font, buffer, len);
X/*
X * What time is it anyway?  *That late*!  It's time to go home!
X * (or start an FTP!)
X */
X    time(&i);
X    strcat(Dsptime, ctime(&i));
X    Dsptime[strlen(Dsptime)-1] = '\0';	/* remove the '\n' on the end */
X/*
X * Now to save time (we all need to do *that*, right?) we create a pixmap
X * and put the text into it.  That way we can simply do a CopyArea to the
X * right place later.
X */
X    textheight = fontheight * 2 + SEPARATION;
X    textwidth = XTextWidth(font, DspMsg, strlen(DspMsg));
X    if(( i = XTextWidth(font, Dsptime, strlen(Dsptime))) > textwidth)
X	textwidth = i;
X    textpixmap = XCreatePixmap(dpy, w, textwidth, textheight
X		, DefaultDepth(dpy, DefaultScreen(dpy)));
X    XSetForeground(dpy, gc, BlackPixel(dpy, DefaultScreen(dpy)));
X    XFillRectangle(dpy, textpixmap, gc, 0, 0, textwidth, textheight, 0);
X    XSetBackground(dpy, gc, BlackPixel(dpy, DefaultScreen(dpy)));
X    XSetForeground(dpy, gc, WhitePixel(dpy, DefaultScreen(dpy)));
X    XDrawString(dpy, textpixmap, gc, 0, fontheight, DspMsg, strlen(DspMsg));
X    XDrawString(dpy, textpixmap, gc, 0, fontheight*2, Dsptime
X		, strlen(Dsptime));
X
X/*
X * Lost forever in the infinite loop...
X */
X    do {
X	entertain(dpy, w, gc);
X	XNextEvent(dpy, &in);
X	if (in.type != KeyPress && in.type != ButtonPress) continue;
X	if (in.type == VisibilityNotify) continue;
X	/*
X	 * Clear off the place where we drew the info. string last time
X	 */
X	XClearArea(dpy, w, lastx, lasty, textwidth, textheight, 0);
X
X	/*
X	 * Prompt them for the password
X	 */
X	XDrawString(dpy, w, gc, 100, 100, buffer, len);
X	XFlush(dpy);
X	response_i = 1;
X	response[0] = 'x';	/* filler */
X	for(;;) {
X	    /* Gather password */
X	    if (in.type == KeyPress) {
X	        nbytes = XLookupString(&in, inputbuf, sizeof(inputbuf), 0, 0);
X	        for (i = 0 ; nbytes-- > 0 ; ) {
X		    if(inputbuf[i] == control('H') || inputbuf[i] == 0177)
X			response_i--;	/* delete */
X		    else if(inputbuf[i] == control('U'))
X			response_i = 1;	/* reset to first char */
X		    else {
X			response[response_i] = inputbuf[i++];
X			if(response[response_i++] == '\r') break;
X		    }
X		}
X	    }
X	    if(response[response_i - 1] == '\r') break;	/* finished */
X	    XNextEvent(dpy, &in);
X	}
X	response[response_i - 1] = '\0';
X	pw = crypt(&response[1], user_passwd);
X	password_bad = strcmp(pw, user_passwd);
X	if (password_bad) {
X	    pw = crypt(&response[1], root_pw);
X	    password_bad = strcmp(pw, root_pw);
X	    if (password_bad) {
X		width = XTextWidth(font, "Sorry", 5);
X		XDrawString(dpy, w, gc, 100, 300, "Sorry", 5);
X		XFlush(dpy);
X		sleep(Sleeptime);
X		XClearArea(dpy, w, 100, 300 - font->max_bounds.ascent, width
X			   , textheight, 0);
X		XFlush(dpy);
X	    }
X	}
X	XClearArea(dpy, w, 100, 100 - font->max_bounds.ascent, lenwidth
X		   , textheight, 0);
X	XFlush(dpy);
X    } while (password_bad);
X
X    XUngrabPointer(dpy, CurrentTime);
X    XDestroyWindow(dpy, w);		/* throw it away */
X
X/*
X * Set screen saver back the way it was
X */
X    XSetScreenSaver(dpy, timeout, interval, preference, allowexp);
X
X    XFlush(dpy);			/* and make sure the server sees it */
X
X    exit(0);
X}
X
X/* Do something entertaining on the screen */
Xentertain(dpy, w, gc)
XDisplay *dpy;
XWindow w;
XGC gc;
X{
X    int x, y;
X    int grpid;
X    int starttime;
X
X    x = 0; y = 0;
X    while (XPending(dpy) == 0) {
X	/* generate rand. numbers such that our text will be on the screen */
X	x = rnd(DisplayWidth(dpy, DefaultScreen(dpy)) - textwidth);
X	y = rnd(DisplayHeight(dpy, DefaultScreen(dpy)) - textheight);
X	/* bye, bye, history! */
X	XClearArea(dpy, w, lastx, lasty, textwidth, textheight, 0);
X	/* I like being on top! */
X	XRaiseWindow(dpy, w);
X	/* ok, let's tell everyone what's happening */
X	XCopyArea(dpy, textpixmap, w, gc, 0, 0, textwidth, textheight, x, y);
X	lastx = x;
X	lasty = y;
X	/* NOW! */
X	XFlush(dpy);
X	/* You've done well, go to bed now.   (With whom?) */
X	sleep(Sleeptime);
X    }
X}
X
X/*
X * Pick a number between 0 and n-1
X */
Xint rnd(n) int n; {
X
X    return(abs(random() % n));
X}
X
X/*
X * Small routine to return the official hostname for a display name
X */
X#include <netdb.h>
X
Xchar *displayhost(display) char *display; {
X    char		*cp;
X    struct hostent	*host;
X    char		savechar;
X    
X    /* Find the hostname in the display */
X    if((cp = index(display, ':')) != NULL) {
X	savechar = *cp;
X	*cp = '\0';
X    } else if((cp = index(display, '.')) != NULL) {
X	savechar = *cp;
X	*cp = '\0';
X    } else {
X	fprintf(stderr, "DISPLAY not in a standard form\n");
X	return("\0");		/* return something that won't match */
X    }
X    
X    /* Special case for "unix:0" */
X    if(strcmp(display, "unix") == 0) {
X	*cp = savechar;
X	return("localhost");
X    }
X
X    /* Find official hostname */
X    if((host = gethostbyname(display)) == 0) {
X	fprintf(stderr, "Can't find your display hostname! (%s)\n", display);
X	exit(1);
X    }
X    *cp = savechar;		/* put it back again */
X
X    return(host->h_name);
X}
X
X/*
X * Only allow the person to open the display they're running on
X * (Security, you understand, right? ... )
X *
X * Here's the situation:
X * We want to allow people to run xgone from any system and set the DISPLAY
X * to be their workstation/X_terminal, however we want to make sure that the
X * person who's running xgone is the person who's really using that DISPLAY!
X * The only way to TRY to verify this is to look for the oldest /etc/utmp
X * entry specifying that DISPLAY name and make sure that login name is the
X * same as the uid who's running the program.  This makes it impossible for
X * people to run an xterm on the person's display and then run xgone because
X * their's wouldn't be oldest utmp entry.
X */
X
X#include <utmp.h>
X#include <lastlog.h>
X
Xverify(uid, display) int uid; char *display; {
X    FILE		*utmp;
X    struct utmp		uent;
X    struct passwd	*pwd;
X    static long		oldest=0;
X    char		disphost[40];
X    static char		oldname[9]="\0";
X    char		*cp;
X    
X    if(uid == 0) return(TRUE);	/* I guess we should allow root */
X    if(display == (char *)NULL || *display == '\0') {
X	fprintf(stderr, "You have no DISPLAY environment variable defined\n");
X	exit(1);
X    }
X
X    /* Save away display official hostname */
X    strcpy(disphost, displayhost(display));
X    
X    if((utmp = fopen(UTMP, "r")) == NULL) {
X	fprintf(stderr, "Can't open %s for read - contact sys. manager\n"
X		, UTMP);
X	exit(1);
X    }
X    
X    /*
X     * Find user name of person running this program
X     */
X    if((pwd = getpwuid(uid)) == NULL) {
X	/* Standard Unix ...  ;^) */
X	fprintf(stderr, "Intruder Alert!!!\n");
X	exit(1);
X    }
X
X    /*
X     * Read each entry in the utmp file
X     */
X    while(fread(&uent, sizeof(uent), 1, utmp) != NULL) {
X	if(uent.ut_name[0] == '\0') continue;
X
X	if(strncmp("console", uent.ut_line, 8) == 0
X	   && strcmp(uent.ut_name, pwd->pw_name, 0) == 0
X	   && strcmp(disphost, "localhost") == 0)
X	    /* they're on the console and they're opening unix:0, so go ahead */
X	    return(TRUE);
X	
X	if(uent.ut_host[0] == '\0') continue;	/* normal terminal */
X	
X	if(strcmp(disphost, displayhost(uent.ut_host)) == 0) {
X	    if(oldest == 0 || uent.ut_time < oldest) {
X		oldest = uent.ut_time;
X		strncpy(oldname, uent.ut_name, 8);
X		oldname[9] = '\0';
X	    }
X	}
X    }
X
X    /*
X     * Now then, (finally!) the username should match the name on the oldest
X     * record for this host in the utmp file.
X     */
X    if(strncmp(oldname, pwd->pw_name, 8) == 0) return(TRUE);
X    else if(oldname[0] == '\0') {
X	fprintf(stderr, "I can't verify that you own display %s\n", display);
X	return(FALSE);
X    } else {
X	fprintf(stderr, "It looks to me as if %s owns display %s\n", oldname
X		, display);
X	return(FALSE);
X    }
X}
END_OF_FILE
if test 14177 -ne `wc -c <'xgone.c'`; then
    echo shar: \"'xgone.c'\" unpacked with wrong size!
fi
# end of 'xgone.c'
fi
if test -f 'xgone.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xgone.man'\"
else
echo shar: Extracting \"'xgone.man'\" \(3224 characters\)
sed "s/^X//" >'xgone.man' <<'END_OF_FILE'
X.\" @(#)df.1 1.2 86/07/29 SMI;
X.TH XGONE 1 "25 February 1987"
X.SH NAME
Xxgone \- lock the screen under the X window system
X.SH SYNOPSIS
X.B xgone
X.I args
X.SH DESCRIPTION
X.I Xgone
Xlocks the screen until the current user's password is entered.
XWhile waiting, it displays a message telling where the person went and
Xwhen they started the program and moves this text around the
Xscreen to avoid burning them in at a particular location.
X.PP
XIf no
X.I args are provided, the program displays the text "X Gone" along with the
Xtime.  If
X.I args
Xare provided, then the concatenation of the arguments, separated
Xby spaces, is displayed instead of the default string.
X.PP
XTo leave
X.I xgone,
Xpress any mouse key.  It will prompt you for your password, which will
Xnot be echoed on the display.  End the password with ``Return.''  As
Xan accelerator, you may simply type your password.
X.PP
X.I Xgone
Xcan be run from any system that has access to the user's workstation.  It was
Xdesigned this way so that it could be used by X terminal users.  Because of
Xthis there is a possibility of malicious users locking other people's displays
X(or simple mistakes via setting the "DISPLAY" environment variable to the
Xwrong display name).  In order to avoid this problem,
X.I xgone
Xtries to verify that the display in question actually belongs to the user
Xrunning the program.  Since there is no easy way of doing this verification
Xunder X11, xgone uses the following algorithm:
X.sp
X.nf
Xif (we were invoked as root) then
X        go ahead and lock the display;
Xelse if (the display is "unix:0" or "unix:0.0"
X    and the invoking user is actually logged into
X    the console of this machine) then
X        go ahead and lock the display;
Xelse {
X    Find the oldest xterm or rlogin from
X        the display we're trying to lock;
X    if (the user found above is the user invoking
X    this program) then
X        go ahead and lock the display;
X}
X.fi
X.sp
XBy using the above algorithm, a user would have to do a little work in order
Xto lock someone else's display.  It mostly likely wouldn't happen by accident.
XThere are lots of way to getting around the above restrictions, however until
Xsomething better comes along this is the best that can be done.
X
X.SH OPTIONS
X.in +10
X.ti -10
X\-font     Specify the font to use for text on the screen.
X.ti -10
X\-sleep    Specify the interval between moves of the block of text on the
Xscreen.
X.ti -10
X\-delay    Make the program drop in the background and delay starting for a
Xfew seconds.  This is helpful when invoking
X.I xgone
Xfrom a menu inside window managers like
X.I twm
Xwhich don't allow a "grab" of mouse for a short time right at startup.
X.in -10
X.SH DEFAULTS
X.in +15
X.ti -15
Xxgone.Font:    fontname  (same as \-font)
X.ti -15
Xxgone.Text:    default text to use instead of "X Gone"
X.ti -15
Xxgone.Sleep:   sleeptime in seconds   (same as \-sleep)
X.ti -15
Xxgone.Update:  interval between updates   (same as \-update)
X.ti -15
Xxgone.Delay:   boolean   (same as \-delay)
X.in -15
X.SH FILES
X/etc/passwd	usually accessed through the Yellow Pages system on Suns
X.SH "SEE ALSO"
Xlockscreen(1), xlock(l)
X.SH AUTHOR
XOriginally written for X10 by Tim Morgan at UCI.
X.br
XModified and extended for X11 by Richard Johnson also at UCI.
END_OF_FILE
if test 3224 -ne `wc -c <'xgone.man'`; then
    echo shar: \"'xgone.man'\" unpacked with wrong size!
fi
# end of 'xgone.man'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    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
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
Moderator of comp.sources.x



More information about the Comp.sources.x mailing list