[comp.sources.misc] v06i086: Gone version 2.0: vt[12]?? terminal locking program

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (04/09/89)

Posting-number: Volume 6, Issue 86
Submitted-by: lavallee@samsung.com (Warren Lavallee)
Archive-name: gone-2.0

	This is gone v2.0.  An earlier version was posted previously about
a year or so ago.  This is basically a lock for vt[12]xx terminals that
looks nicer than lock.  This will probally be of no use to you at all
unless you have a true vt[12]xx compatible terminal.

	A few new features have been added since the last release:

	o ~/.passwd file.  On some systems, passwd's are not kept in
		/etc/passwd.  On these systems, gone can create and use
		it's own crypted passwd found in this file.  See man page
		for option.

	o timeout.  Gone now timesout.  This is configurable in conf.h

	o Support for Pyramid computers has been added.

	o Added error checking.

	This has successfully compiled under Ultrix 2.x, BSD 4.3, DGUX 3.00, 
	Dynix 2.1, Dynix 3.0, Sun OS 4.0, and DualPort OS 4.4b

#! /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:  Makefile README conf.h gone.1l gone.c
# Wrapped by lavallee@ginosko on Fri Apr  7 14:19:57 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(761 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# This  software  is provided with absolutely no warranty, to the extent
X# permitted  by  applicable  state law.  In no event, unless required by
X# applicable law, will the author(s) of this this software be liable for
X# any damages caused by this software.
X#
all: gone gone.man
X
gone: gone.c conf.h
X	cc -O -o gone gone.c
X
gone.man: gone.1l
X	nroff -man gone.1l > gone.man
X
clean:
X	/bin/rm -f *.o gone *~ foo bar baz Gone?? gone.man
X
shar: Gone01
X
Gone01: conf.h Makefile gone.c gone.1l README
X	makekit -nGone Makefile README conf.h gone.c gone.1l 
X
install: gone gone.1l
X	cp gone /usr/local/bin/gone
X	chgrp kmem /usr/local/bin/gone
X	chmod 2755 /usr/local/bin/gone
X	cp gone.1l /usr/man/manl
X
gone.c: conf.h Makefile
Gone01: conf.h Makefile gone.c gone.1l README
END_OF_FILE
if test 761 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1040 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
X	This is gone v2.0.  An earlier version was posted previously about
a year or so ago.  This is basically a lock for vt[12]xx terminals that
looks nicer than lock.  This will probally be of no use to you at all
unless you have a true vt[12]xx compatible terminal.
X
X	A few new features have been added since the last release:
X
X	o ~/.passwd file.  On some systems, passwd's are not kept in
X		/etc/passwd.  On these systems, gone can create and use
X		it's own crypted passwd found in this file.  See man page
X		for option.
X
X	o timeout.  Gone now timesout.  This is configurable in conf.h
X
X	o Support for Pyramid computers has been added.
X
X	o Added error checking.
X
X	This has successfully compiled under Ultrix 2.x, BSD 4.3, DGUX 3.00, 
X	Dynix 2.1, Dynix 3.0, Sun OS 4.0, and DualPort OS 4.4b
X
X----------------------------------------------------------------------------
INTERNET:  lavallee@samsung.com
UUCP:      {decvax!{gsg,cg-atla},uunet,ulowell}!ginosko!lavallee
US MAIL:   Samsung Software America. One Corporate Dr.  Andover, Ma.  01810
END_OF_FILE
if test 1040 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'conf.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'conf.h'\"
else
echo shar: Extracting \"'conf.h'\" \(1051 characters\)
sed "s/^X//" >'conf.h' <<'END_OF_FILE'
X/* This  software  is provided with absolutely no warranty, to the extent
X * permitted  by  applicable  state law.  In no event, unless required by
X * applicable law, will the author(s) of this this software be liable for
X * any damages caused by this software.
X */
X
X#ifndef __CONF__
X#define VERSION "2.0"
X
X/** undefine TIMEOUT if you want no timeout **/
X
X#define TIMEOUT 60		/** default timeout          **/
X#define MAXTIMEOUT 180		/** Maximum timeout allowed. **/
X#undef HOSTNAME			/** define this to you hostname if
X				 **  you don't have gethostname(2)
X				 **/
X
X/**         You may undefine this if you don't want it                 **/
X
X#define WIZGROUP "wheel"    /** Magic group:
X                              * If you type in the password of someone
X			      * in this group, you will get out.
X			      *
X			      * I think this is better than having a
X			      * global password like "hasta la vista"
X			      * like some locks have.
X			     **/
X
X/** #define FCRYPT **/	     /** define if you are useing fcrypt **/
X
X#define __CONF__
X#endif
END_OF_FILE
if test 1051 -ne `wc -c <'conf.h'`; then
    echo shar: \"'conf.h'\" unpacked with wrong size!
fi
# end of 'conf.h'
fi
if test -f 'gone.1l' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'gone.1l'\"
else
echo shar: Extracting \"'gone.1l'\" \(1545 characters\)
sed "s/^X//" >'gone.1l' <<'END_OF_FILE'
X.TH GONE "1 local" "AJR/WJL"
X.SH NAME
gone [\-t number] [\-c] [\-p] \- reserve a terminal
X.SH SYNOPSIS
X.B gone 
X.SH DESCRIPTION
X.IR Gone
clears the screen and prints a cute picture on the display.  It
then asks you for a Magic Word.  The Magic Word is the password
you use to log on to the system.  You must type this in to exit
gone.  Gone will display the load average and the number of users
that are on the system near the bottom of the screen.  This info
will be updated every minute.
X.SH OPTIONS
X.PP
The
X.IR \-t
flag allows you to change the timeout interval.  The default interval is
X20 minutes.  The maximum interval is defined at compile time and defaults
to 45 minutes.
X.PP
The 
X.IR \-c
flag allows you to initialize/change a password in ~/.passwd.  Some
versions of UNIX don't keep encrypted passwords in /etc/passwd anymore.
On these systems, you can keep and encrypted password in ~/.passwd for
gone.
X.PP
The
X.IR \-p
flag is present to let you defeat idle daemons and things like that.  It
touches the terminal every five minutes.  This feature is only supported
on a smart terminal due to implementation details.
X.SH INSPIRATION
X.IR Gone
was written because using lock was too time consuming.  With
X.IR gone
all you have to do is type in gone and you are done. 
The escape sequences were snagged from a
X.IR VMS 
COM file and converted to 
X.IR UNIX
gone.
X.SH AUTHORS
Warren Lavallee (converted it to C), 
Andy Rosen  (provided DG/UX code so it would work on DG/UX systems)
X.SH ADDRESS
X	lavallee@samsung.com
X	arosen@hawk.ulowell.edu
END_OF_FILE
if test 1545 -ne `wc -c <'gone.1l'`; then
    echo shar: \"'gone.1l'\" unpacked with wrong size!
fi
# end of 'gone.1l'
fi
if test -f 'gone.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'gone.c'\"
else
echo shar: Extracting \"'gone.c'\" \(24387 characters\)
sed "s/^X//" >'gone.c' <<'END_OF_FILE'
static char *credits="@(#) GONE Version 2.0--(c)1989 Warren Lavallee/Andrew Rosen\n";
X
static char *authors = "@(#)Warren Lavallee, Andy Rosen";
X
X/*
X * All rights reserved with the following exceptions
X * 
X * This software is supplied free of charge.  This software, or any part
X * of it, may  not  be  redistributed or otherwise made available to, or
X * used  by, any  other  person  without the inclusion of this copyright
X * notice.  This software may not be used to make a profit in any way.
X * 
X * This  software  is provided with absolutely no warranty, to the extent
X * permitted  by  applicable  state law.  In no event, unless required by
X * applicable law, will the author(s) of this this software be liable for
X * any damages caused by this software.
X * 
X * This will compile under Ultrix 2.x, BSD 4.3, DGUX 3.00, 
X *   Dynix 2.1, Dynix 3.0, Sun OS 4.0, DualPort OS 4.4b
X */
X
X/**
X *  C program by Warren Lavallee
X *  DGUX code by Andy Rosen
X **/
X
X#include <stdio.h>
X#include <syslog.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <signal.h>
X#include <pwd.h>
X#include <sys/file.h>
X#include <utmp.h>
X#include <nlist.h>
X#include <time.h>
X#include <sgtty.h>
X#include <grp.h>
X#include <assert.h>
X
X#include "conf.h"
X
X#ifdef FCRYPT
X#define CRYPT fcrypt		/** Use the fast crypt (not incl)**/
char *fcrypt ();
X#else
char *crypt ();
X#define CRYPT crypt		/** Use library crypt  **/
X#endif
X
X#ifdef UENT
X#include <uent.h>
X#endif
X
X#ifdef dgux
X#include <fcntl.h>
X#endif
X
typedef enum {false, true} bool;
X
char *getenv(), *getpass(), *ttyname(), *strcpy();
char savehost[28];
double load();
long startup_time;		/** Time we started up                   **/
X#ifdef TIMEOUT
long timeouttime = TIMEOUT;
X#endif
X
int die(),			/** Exits	                         **/
X    pflag = 0, 			/** Touch the terminal evey 5 minutes    **/
X    dflag = 0, 			/** Want to use dumb format anyways?     **/
X    pid, 			/** Used with fork		         **/
X    invalid = 0,		/** Number of invalid logins	         **/
X    foo,                        /** Generic tmp variable                 **/
X    dumb;			/** Am I dumb?			         **/
X
bool virgin = true; 		/** Am I a virgin?		         **/
X
struct passwd *pwd;		/** Used to find next variable (myname)  **/
char myname[9];			/** Who am i?			         **/
char hostname[28];		/** Where am i?			         **/
char *validate();		/** Is this password valid?	         **/
X
struct unode {                  /** In here goes the encrypted passwords **/
X  char name[81];                /**  of all the people in WIZGROUP.      **/
X  char passwd[20];              /** Faster this way, instead of scanning **/
X  struct unode *next;           /**  the whole password file each time   **/
X} *wizusers = NULL;             /**  a password is typed in.             **/
X
X#ifdef UENT			/** Local: We store names and ss#'s for  **/
struct uent muent;		/**   each person.			 **/
X#endif
X
X#ifdef TIMEOUT
int timeout ();			/** Jump to here if we get a SIGALRM     **/
X#endif
X
char *mcrypt();                 /** My crypt.  Decides whether to use    **
X                                 **  the fast crypt, or the library      **
X				 **  crypt				 **
X				 **                                      **/
X
struct passwd *getpwuid();	/** Just in case pwd.h didn't declare it
X				 **/
main(argc, argv)
X     int argc;
X     char *argv[];
X{
X  register i = 1;
X  int intprint();
X  char *obuf = (char *) malloc (80L*25L);/** stdout buffer/one full screen**/
X  char *term = getenv("TERM");		 /** Terminal type                **/
X  char *liberator = NULL;		 /** Who liberated this terminal? **/
X
X  for (i = SIGHUP; i <= SIGUSR2; i++)
X    signal(i, intprint);
X
X  (void) signal(SIGINT, SIG_IGN);
X  (void) signal(SIGQUIT, SIG_IGN);
X#ifdef SIGTSTP	/** Some sysVers don't have job control. **/
X  (void) signal(SIGTSTP, SIG_IGN);
X#endif
X#ifdef SIGTTOU  /** Bug in kernel with pgrps can send this signal. **/
X  (void) signal(SIGTTOU, SIG_IGN);
X#endif
X  (void) signal(SIGTERM, die);
X  (void) signal(SIGCHLD, SIG_DFL);
X#ifdef TIMEOUT
X  (void) signal(SIGALRM, timeout);
X#endif
X  
X  if (!isatty(0)) {  			 /** pipes?  ICK                   **/
X     fprintf(stderr, 
X       "%s: Without a terminal?  What\'s the point\?\n", argv[0]);
X     exit(-1);
X  } else if (!strcmp(term, "emacs")) { 	/** In emacs window 		   **/
X     fprintf(stderr,			/** I guess we get all types       **/
X       "%s: In an emacs window?  Ha\!\n", argv[0]);
X     exit(-1);
X  } else if (!strncmp(term, "xterm", 5)) { /** an X window?  Gaud, get real **/
X     fprintf(stderr, "In an X-window?  Be real.\n");
X     fprintf(stderr, "Try xlock instead l\buser.\n");
X     exit(-1);
X  } else {                  /** In script, or a window, come on, be real!  **/
X#ifdef unix
X     char *name = (char *) getlogin ();
X#else
X     char *name = (char *) cuserid(NULL);
X#endif
X
X     if (strlen(name) < 2) { 		/** Not logged in on terminal      **/
X        fprintf(stderr,			/** Must be in script or something **/
X          "%s: You must be at the lowest level to run gone.\n", argv[0]);
X	fprintf(stderr,
X	  "%s:  i.e.. on your login terminal, and in your login shell.\n",
X		argv[0]);
X        exit(-1);
X     }
X  }
X
X  setbuf (stdout, obuf);
X#ifdef FCRYPT
X  init_des ();
X#endif
X
X#ifdef dgux
X  assert(1);				/** Just checking                **/
X#endif
X
X#ifdef UENT
X  muent = getuent(getuid());
X#endif
X
X  while ((i <= argc-1) && (argv[i++][0] == '-')) {
X    switch (argv[i-1][1]) {
X    case 'p': 
X      ++pflag;
X      break;
X#ifdef TIMEOUT
X    case 't':
X      timeouttime = atoi(argv[i++]);
X      break;
X#endif
X    case 'd': 
X      ++dflag;
X      break;
X    case 'c': { /** Change the password in the ~/.passwd file or create one **/
X      struct passwd *pwd;
X      FILE *pwdfile;
X      char path[80], *chpasswd();
X      char oldpw[12], newpw[12];
X      
X      if ((pwd = getpwuid(getuid())) == NULL) {
X	printf("Intruder alert!?\n");
X	printf("Your account appears to be GONE.\n");
X	exit(1);
X      }
X      sprintf(path, "%s/.passwd", pwd->pw_dir);
X      if ((pwdfile = fopen(path, "r")) == NULL) {
X	strcpy(oldpw, "");
X      } else {
X	fscanf(pwdfile, "%s", oldpw);
X	fclose(pwdfile);
X      }
X
X      strcpy(newpw, chpasswd(oldpw));
X      sprintf(path, "%s/.passwd", pwd->pw_dir);
X      if ((pwdfile = fopen(path, "w+")) == NULL) {
X	fprintf(stderr, 
X		"cannot change passwd, open of .passwd file failed.\n");
X	perror(path);
X	exit(1);
X      }
X      fprintf(pwdfile, "%s\n", newpw);
X      fclose(pwdfile);
X      exit(1);
X      }
X    default: 
X      fprintf(stderr, "%s:  Can\'t grok a %c\n", argv[0], argv[i-1][1]);
X      sleep (1);
X      break;
X    }
X  }
X#ifdef TIMEOUT
X  if (!wizuser())
X    if (timeouttime > MAXTIMEOUT) {
X      timeouttime = MAXTIMEOUT;
X      fprintf(stderr, "Maximum time out is %d.\n", MAXTIMEOUT);
X      fprintf(stderr, "You request has been degraded to that amount.\n");
X    } else 
X      if (timeouttime < 1) {
X	timeouttime = TIMEOUT;
X	fprintf(stderr, "Timeout times must be greater and not equal to 0 minutes.\n");
X      }
X#endif
X  if (pflag && dflag) 
X    fprintf(stderr, "%s: p option can not be specified with d.\n", argv[0]);
X  {
X    char buf[80];
X
X    sprintf(buf, 
X	    "fired up by %s, timeout time is %d", getlogin(), timeouttime);
X    syslog(LOG_INFO, buf);
X  }
X
X  dumb = 0;
X#ifndef HOSTNAME
X  gethostname(hostname, 28);
X#else
X  strcpy(hostname, HOSTNAME);
X#endif
X  
X  /** These are the terminals that this is compatible with.  If
X   *  the invoker isn't on one of these, we define dumb, and
X   *  skip all the frills.
X   **/
X  
X  if (!dflag) {
X    if (strncmp(term, "vt100", 5) && strncmp(term, "vt200", 5)
X	&& strncmp(term, "vt220", 5)  && strncmp(term, "vt240", 5) 
X	&& strncmp(term, "vt300", 5)  && strncmp(term, "hds220", 5)) dumb++;
X  } else ++dumb;
X
X#ifdef TIMEOUT
X  alarm(timeouttime*60);
X  if (timeouttime)
X    fprintf(stderr, "Timeout in %d minutes.\n", timeouttime);
X  else
X    fprintf(stderr, "The timeout has been disabled.\n", timeouttime);
X  sleep(3);
X#endif
X  
X  if ((pwd = getpwuid(getuid())) == NULL) 
X    {     /** Not in passwd file.  Hmmm.  Funky.        **/
X      assert(pwd == NULL);
X      printf("Who the hell are you, and how did you manage that?\n");
X      printf("[You don\'t appear to be in the passwd file.]\n");
X      printf("Either your account has been deleted or your uid as been ");
X      printf("munged.  [neat trick]\n");
X      printf("You may want to contact your sysmgr.\n");
X      exit(-1);
X    }
X  else 
X    strcpy(myname, pwd->pw_name);
X  
X#ifndef dgux
X  tag_utmp();
X#endif
X
X  do_screen() ;
X  
X  if (!dumb)
X    do {
X      assert(!dumb);
X      pid = fork ();
X      switch (pid) {
X      case -1: 
X	assert(pid == -1);	/** This section hasn't been tested. **/
X	fprintf(stderr, "\033[20;25HCan't fork... retrying...");
X	pid = fork ();
X	if (pid == 0)
X	  dodate (); /** Success **/
X	break;
X      case 0:  
X	dodate ();      /** success **/
X	/** NOT REACHED **/
X	break;
X      default:
X	break;
X      }
X    } while (pid == -1);
X  
X  init_pwd ();
X
X  /** Loop until we get either the users password, or roots password **/
X  for (;;) {   /**   Main body of program.  Loop until valid password **/
X    char *passwd;
X  kludge:
X    if (!dumb)
X      passwd = getpass ("\033[20;19H      Magic Word:\033[K ");
X    else
X      passwd = getpass ("Enter the magic word: ");
X
X    if (!strcmp(passwd, "credits")) {
X      printcredits();
X      goto kludge;
X    } else
X      if ((liberator = validate(passwd, &foo)) != NULL)
X	break;
X
X    putchar(07);
X    if (!dumb)
X      printf("\033[20;19H            Nope.\033[K");
X    else
X      printf("Nope\n");
X    fflush(stdout);
X    sleep(2);
X  }
X  if (!dumb) {
X    printf("\033[20;12HWelcome, %s, to this account%s.\033[J", liberator,
X	   foo ? ", Oh Mighty Wizard" : "");
X    if (invalid)
X      printf(
X        "\033[21;6HThere were %d invalid attemps before this sucessful one.\n",
X	invalid);
X    printf("\n");
X  } else {
X    printf("\nWelcome, %s, to this account%s.\n", liberator,
X	   foo ? ", Oh Mighty Wizard" : "");
X    if (invalid)
X      printf("There were %d invalid before this sucessful one.\n", invalid);
X}
X
X#ifndef dgux
X  restore_utmp();
X#endif
X  
X  if (!dumb)
X    kill (pid,SIGTERM);  /** Kill our baby doing the time and date and load **/
X
X  fflush (stdout);
X}
X
dodate () 
X{
X#ifdef TIMEOUT
X  long foo[2];
X#endif
X#ifdef dgux
X  char *obuf = (char *) malloc(80*5);
X#endif
X  char *tty = ttyname(0);
X  int count = 0, update();
X
X  signal(SIGHUP, update);
X  signal(SIGTERM, SIG_DFL);
X  signal(SIGCONT, SIG_DFL);
X
X#ifndef dgux
X  startup_time = time(0);
X#else
X  startup_time = time((long *)0);  /* wierd */
X#endif
X
X#ifdef dgux
X  setbuf(stdout, obuf);
X#endif
X
X  if (timeouttime)
X    --timeouttime;
X
X  nice(10);
X  signal (SIGTERM, die);
X  for (;;) {
X    if (pflag) {                  /* Touch the terminal every soo often */
X      foo[0] = foo[1] = time(0);
X      utime(tty, foo);
X    }
X    if (++count > 5) {
X      count = 0;
X      do_screen();
X    }
X    
X    if (timeouttime)
X      printf("\033[17;25HTimeout in \033[1m%d\033[0m minutes.", timeouttime);
X
X	/** Have to put all this in one printf for DG/UX **/
X    printf ("\033[22;24Hload: %.2f, and %d users.\033[K\033[23;18HStarted up at %26s\033[20;37H", load(), users(), ctime(&startup_time));
X
X    fflush (stdout);      /** Moves cursor to Password: prompt **/
X    sleep (60);
X    if (timeouttime)
X      --timeouttime;
X  }
X}
die () {
X  exit (1);
X}
update () {
X    if (timeouttime)
X      printf("\033[17;25HTimeout in \033[1m%d\033[0m minutes.", timeouttime);
X
X    printf ("\033[22;24Hload: %.2f, and %d users.\033[K\033[23;18HStarted up at %26s\033[20;37H", load(), users(), ctime(&startup_time));
X
X    fflush (stdout);      /** Moves cursor to Password: prompt **/
X    signal(SIGHUP, update);
X}
int Fkmem;
int Futmp;
static double avenrun[3];
X
static struct utmp buf;
X
static struct nlist nl[] = {
X#define N_AVENRUN	0
X#ifndef dgux
X  { "_avenrun" },
X#else
X  { "avenrun" },
X#endif
X  { "" },
X};
X
X/*
X * load - Return the 5 minute load average
X */
double load()
X{
X  register i;
X#ifdef dgux
X  double lavg[3];
X#endif
X  
X#if ns32000
X  nlist("/dynix", nl);
X#endif
X#if dgux
X  nlist("/dgux", nl);
X#endif
X#if defined(vax) || defined(pyr) || defined(sun)
X  nlist("/vmunix", nl);
X#endif
X  
X  if (nl[0].n_type == 0) return (-1);
X  
X  if ((Fkmem = open("/dev/kmem", 0)) < 0) return (-1);
X  
X  lseek(Fkmem, (long)nl[N_AVENRUN].n_value, 0);
X#if ns32000
X  {   long l_avenrun[3]; 
X      read(Fkmem, l_avenrun, sizeof(l_avenrun));
X      for (i=0; i < (sizeof(avenrun)/sizeof(avenrun[0])); i++) {
X	avenrun[i] = ((double)l_avenrun[i])/1000.0;
X      }
X    }
X#endif
X#ifdef dgux
X  lseek(Fkmem, (long)nl->n_value, 0);
X  read(Fkmem, (char *)lavg, sizeof(lavg));
X  avenrun[0] = lavg[0];
X#endif
X#if defined(vax) || defined(pyr) || defined(sun)
X  read(Fkmem, avenrun, sizeof(avenrun));
X#endif
X  close(Fkmem);
X  return (avenrun[0]);
X}
X
X/*
X * users - Count the number of users logged in.
X */
users()
X{
X#ifdef dgux
X  struct utmp *ut;
X#endif
X  int count = 0;
X  
X  
X  /* Get number of users */
X#ifdef dgux
X  setutent();
X  while (ut = getutent()) if (ut->ut_type == USER_PROCESS) count++;
X  endutent();
X#else
X  if ((Futmp = open("/etc/utmp", 0)) < 0) return (-1);
X  
X  (void) lseek(Futmp, (long)0, 0);
X  while (read(Futmp, &buf, sizeof(buf)) > 0) {
X    if (buf.ut_name[0] != '\0') {
X      count++;
X    }
X  }
X  close(Futmp);
X#endif
X  return (count);
X}
do_screen () {
X  
X  if (!dumb) {
X    printf ("\033[H\033[2J\033(0\0331");    /** Clear screen, Graphics mode **/
X    printf ("\
X   lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk\n\
X   x                                                                       x\n\
X   x   ////////    //      //        ///     ///    ////////    /////////  x\n\
X   x  aaaaaaaa/   aa/     aa/       aaa/    aaa/   aaaaaaaa/   aaaaaaaaa/  x\n\
X   x     aa/      aaa/    aa/       aaa/    aaa/   aa/         aa/         x\n");
X    printf("\
X   x     aa/      aa/a/   aa/  ///  aaa/    aaa/   aa///////   aa//////    x\n\
X   x     aa/      aa/ a/  aa/ aaa/  aaa/    aaa/   aaaaaaaa/   aaaaaaa/    x\n\
X   x     aa/      aa/  a/ aa/       aaa/    aaa/         aa/   aa/         x\n\
X   x   //aa////   aa/   a/aa/       aaa/////aaa/    /////aa/   aa////////  x\n");
X    printf("\
X   x  aaaaaaaa/   aa/    aaa/        aaaaaaaaa/    aaaaaaaa/   aaaaaaaaa/  x\n\
X   x                                                                       x\n\
X   mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj\n");
X    
X    printf ("\033(B\0332");
X    printf ("\n\033[0m\033#3  This terminal is IN USE by \033[1m%s\033[0m\n", myname);
X    printf ("\033[0m\033#4  This terminal is IN USE by \033[1m%s\033[0m\n", myname);
X    printf ("\033#5");
X    printf ("\n\n    Version %s for %s (%s)... Enter '\033[1mcredits\033[0m' for info on copyright\n", VERSION, 
X#ifdef unix
X	    "Unix",
X#else
X	    "VMS",		/** ICK!!!!! **/
X#endif
X	    hostname);
X    /**  	 Skip the @(#) junk in the banner 			**/
X    printf ("\033[16;0H         %s", (char *) (credits+4));
X#ifdef UENT
X    printf ("\033[24;0H                This terminal is in use by %s", muent.fullname);
X#endif
X    if (virgin == true) {
X       assert(virgin == true);
X       printf("\033[20;25HInitializing....");
X       virgin = false;
X    } else
X       printf("\033[20;25HMagic Word:\033[K");     
X  fflush(stdout);
X  }
X  else {     /* Less verbose... For terminals that can't do neat graphics.*/
X#ifdef UENT
X    printf("This terminal has been locked by %s\n", muent.fullname);
X#endif
X    printf("Terminal is LOCKED, RESERVED!\n");
X    printf("NO TRESSPASSING.  BEWARE OF DOG.  NOBODY HOME.\n");
X    printf("OUT TO LUNCH.  TRESSPASSERS WILL BE PROSECUTED.\n");
X  }
X  fflush(stdout);
X}
X/** Do the crypt.
X **/
char *mcrypt(arg1, arg2)
char *arg1, *arg2;
X{
char *output;
X
X	output = CRYPT(arg1, arg2);
X	return(output);
X}
X/** Is the a valid password?  Should I exit?  returns NULL if invalid attempt,
X ** else returns a pointer to the name of the person who liberated the 
X ** terminal.
X **/
char *validate(passwd, wiz) 
register char *passwd; 
register int *wiz;
X{
X  register struct unode *foo;
X
X  foo = wizusers;
X
X  *wiz = 1;
X
X  while (foo != NULL) {
X    if (!strcmp(foo->passwd, mcrypt(passwd, foo->passwd))) {
X      if (foo->next == NULL)
X	*wiz = 0;
X      return (foo->name);
X    }
X    foo = foo->next;
X  }
X  ++invalid;
X  return(NULL);
X}
X/** Load crypted passwords into memory. 
X **
X ** If a ~user/.passwd file exists and is readable, we use that as
X ** the encrypted password instead.
X **/
init_pwd () {
X  struct passwd *hisent = NULL;
X#ifdef WIZGROUP
X  register g = 0;
X  struct group *grp = NULL;
X  struct unode *newone;
X  char myname[9];
X#endif
X#ifdef UENT
X  struct uent fooent;
X#endif
X
X  assert(wizusers == NULL);  /** this has been initialized during
X			       ** setup.  This must be false by definition 
X			       **/
X
X  if ((hisent = getpwuid(getuid())) == NULL) 
X    {
X      printf("Who the hell are you?\n");
X      exit(-1);
X    }
X  else {
X    if ((wizusers = (struct unode *) malloc (sizeof(struct unode))) == NULL) {
X      assert(wizusers = NULL);
X      perror("malloc failed");
X      kill(pid, SIGTERM);
X      exit (-1);
X    }
X    strcpy(myname, hisent->pw_name);
X#ifdef UENT
X    fooent = getuent(hisent->pw_uid);
X    strcpy(wizusers->name, fooent.fullname);
X#else
X    strcpy(wizusers->name, hisent->pw_name);
X#endif
X    wizusers->next = NULL;
X
X    { FILE *altpwf;
X      char pwf[40];
X
X      sprintf(pwf, "%s/.passwd", hisent->pw_dir);
X      if ((altpwf = fopen(pwf, "r")) == NULL)
X	strcpy(wizusers->passwd, hisent->pw_passwd);
X      else {
X	fscanf(altpwf, "%s", wizusers->passwd);
X	fclose(altpwf);
X      }
X    }
X  }
X
X#ifdef WIZGROUP
X  if ((grp = getgrnam(WIZGROUP)) != NULL) 
X    while (grp->gr_mem[g] != NULL) {
X      if (strcmp(grp->gr_mem[g], myname)) { /** Don't add me twice **/
X	setpwent ();
X	if ((hisent = getpwnam(grp->gr_mem[g++])) != NULL) {
X	  if ((newone=(struct unode *)malloc(sizeof(struct unode)))==NULL) {
X	    assert(newone == NULL);
X	    perror("malloc failed");
X	    kill(pid, SIGTERM);
X	    exit (-1);
X	  }
X#ifdef UENT
X	  fooent = getuent(hisent->pw_uid);
X	  strcpy(newone->name, fooent.fullname);
X#else
X	  strcpy(newone->name, hisent->pw_name);
X#endif
X	  { FILE *altpwf;
X	    char pwf[40];
X	  
X	    sprintf(pwf, "%s/.passwd", hisent->pw_dir);
X	    if ((altpwf = fopen(pwf, "r")) == NULL)
X	      strcpy(newone->passwd, hisent->pw_passwd);
X	    else 
X	      {
X		fscanf(altpwf, "%s", newone->passwd);
X		fclose(altpwf);
X	      }
X	  }
X	  newone->next = wizusers;
X	  wizusers = newone;
X	  assert(wizusers != NULL);
X	  endpwent();
X	}
X      } else 
X	g++;
X    }	
X#endif
X}
X#ifdef TIMEOUT
X     
X/**
X ** This is called when the timeout time has been reached.
X ** We log out the user by killing out Parent.... Lets hope
X ** that that is the shell!
X **/
X
timeout() 
X{
X  signal(SIGALRM, SIG_IGN);	/** Ignore anymore alarms... **/
X  signal(SIGINT, SIG_IGN);	/** Just in case             **/
X  signal(SIGQUIT, SIG_IGN);	/** Just in case             **/
X
X  kill(pid, SIGTERM);		/** Kill the baby doing the 
X				 **  time and date.
X				 **/
X  if (!dumb)
X    printf("\033[20;12HTimeout after %d minutes.\033[J\n\n", timeouttime);
X  else
X     printf("\nTimeout after %d minutes.\n", TIMEOUT);
X
X  fprintf(stderr, 
X	  "You have been idle for too long.  You are being TERMINATED....\n");
X
X  fflush(stdout);
X  sleep(3);
X  fprintf(stderr, ">>>>> ZAP <<<<<<,  You've been disintegrated.\n");
X  ioctl(0, TIOCCDTR, 0);         /** Drop DTR                 **/
X  kill(getppid(), SIGKILL); 	/** Log me out 		     **/
X  exit(-1);
X}
X#endif
int wizuser() 
X{
X#ifdef WIZGROUP
X  register i;			         /* index                      */
X  char *group = WIZGROUP;		 /* The name of the group      */
X  struct group *gr;		         /* group file entry           */
X  char *logname = (char *) getlogin ();  /* login name of caller       */
X  gr = getgrnam(group);                  /* get id of authorized group */
X
X  if (gr == NULL) return(0);             /* groups does not exist      */
X
X  for (i = 0; gr->gr_mem[i] != NULL; i++)/* loop through each member   */
X    if (!strcmp(gr->gr_mem[i], logname)) /* is he a valid member?      */
X      return(1);                         /* user looks okay to me      */
X#endif
X  /** Or if we are the author, then we are a wiz user **/
X  if (!strcmp(logname, "lavallee")) 
X    return(1);
X
X  return(0);                             /* Not found                  */
X}
X
X/** Change the guys passwd from the ~/.passwd file...  We return the new
X ** crypted password if successful... NULL elsewise...  old is the
X ** old crypted password.
X **/
X
char *chpasswd(old)
char *old;
X{
X	char saltc[2];
X	long salt;
X	int i;
X	int c, pwlen;
X	static char pwbuf[10];
X	long time();
X	char *mcrypt();
X
X	if (strlen(old) > 3) {
X	  strcpy(pwbuf, getpass("Old password:"));
X	  if (strcmp(old, mcrypt(pwbuf, old))) {
X	    printf("Sorry\n");
X	    exit(-1);
X	  }
X	}
X
X	(void) strcpy(pwbuf, getpass("New password:"));
X	pwlen = strlen(pwbuf);
X	if (pwlen == 0) {
X		printf("Password unchanged.\n");
X		exit(-1);
X	}
X	/*
X	 * Insure password is of reasonable length and
X	 * composition.  If we really wanted to make things
X	 * sticky, we could check the dictionary for common
X	 * words, but then things would really be slow.
X	 */
X	if (strcmp(pwbuf, getpass("Retype new password:")) != 0) {
X		printf("Mismatch - password unchanged.\n");
X		exit(-1);
X	}
X	(void) time(&salt);
X	salt = 9 * getpid();
X	saltc[0] = salt & 077;
X	saltc[1] = (salt>>6) & 077;
X	for (i = 0; i < 2; i++) {
X		c = saltc[i] + '.';
X		if (c > '9')
X			c += 7;
X		if (c > 'Z')
X			c += 6;
X		saltc[i] = c;
X	}
X	return(mcrypt(pwbuf, saltc));
X}
printcredits() 
X{
X  struct sgttyb buf, obuf;
X
X  gtty(0, &buf);
X  obuf = buf;
X  buf.sg_flags |= CBREAK;  /** Turn on cbreak **/
X  buf.sg_flags &= ~ECHO;   /** Turn off echo  **/
X  stty(0, &buf);
X
X  if (!dumb) 
X    kill(pid, SIGSTOP);  /** Don't want those stupid things on the screen **/
X  
X  fprintf(stderr, "\033[H\033[J");
X  fprintf(stderr, "Gone version %s. (c)1989 by %s\n",
X	  VERSION, (authors+4));
X  fprintf(stderr, "\nIf you port this to any machines, context diffs would be greatly appreciated.\n");
X  fprintf(stderr, "The authors can be reached at 'lavallee@samsung.com, arosen@hawk.ulowell.edu'\n\n");
X  fprintf(stderr, "All rights reserved with the following \033[1mexceptions\033[0m:\n");
X  fprintf(stderr, "\n");
X  fprintf(stderr, "This software is supplied free of charge.  This software, or any part\n");
X  fprintf(stderr, "of it, may  not  be  redistributed or otherwise made available to, or\n");
X  fprintf(stderr, "used  by, any  other  person  without the inclusion of this copyright\n");
X  fprintf(stderr, "notice.  This software may not be used to make a profit in any way.\n");
X  fprintf(stderr, "\n");
X  fprintf(stderr, "This  software  is provided with absolutely no warranty, to the extent\n");
X  fprintf(stderr, "permitted  by  applicable  state law.  In no event, unless required by\n");
X  fprintf(stderr, "applicable law, will the author(s) of this this software be liable for\n");
X  fprintf(stderr, "any damages caused by this software.\n");
X  fprintf(stderr, "\n\n\n\n");
X  sleep(10);
X  do_screen();
X  if (!dumb) {
X    kill(pid, SIGCONT);
X    kill(pid, SIGHUP);
X  }
X  stty(0, &obuf);
X}
X
tag_utmp()
X{
X  struct utmp ut;
X  int slot = ttyslot();
X  int fd;
X
X  fd = open("/etc/utmp", O_RDWR);
X  if (fd == -1) {
X    return;
X  }
X  
X  if (lseek(fd, slot*(sizeof(ut)), L_SET) == -1) {
X    perror("utmp: lseek");
X    sleep(3);
X    return;
X  }
X  if (read(fd, &ut, sizeof(ut)) != sizeof(ut)) {
X    perror("utmp: read");
X    sleep(3);
X    return;
X  }
X  strcpy(savehost, ut.ut_host);
X  strcpy(ut.ut_host, "in gone");
X  if (lseek(fd, slot*(sizeof(ut)), L_SET) == -1) {
X    perror("utmp: lseek");
X    sleep(3);
X    return;
X  }
X  write(fd, &ut, sizeof(ut));
X  close(fd);
X}
X
restore_utmp()
X{
X  struct utmp ut;
X  int slot = ttyslot();
X  int fd;
X
X  fd = open("/etc/utmp", O_RDWR);
X  if (fd == -1) {
X    return;
X  }
X
X  assert(fd != -1);
X
X  if (lseek(fd, slot*(sizeof(ut)), L_SET) == -1) {
X    perror("utmp: lseek");
X    sleep(3);
X    return;
X  }
X  if (read(fd, &ut, sizeof(ut)) != sizeof(ut)) {
X    perror("utmp: read");
X    sleep(3);
X    return;
X  }
X  strcpy(ut.ut_host, savehost);
X  if (lseek(fd, slot*(sizeof(ut)), L_SET) == -1) {
X    perror("utmp: lseek");
X    sleep(3);
X    return;
X  }
X  write(fd, &ut, sizeof(ut));
X  close(fd);
X}
intprint(sig)
int sig;
X{
X  printf("\033[24;12HReceived a %d signal.", sig);
X  signal(signal, intprint);
X}
END_OF_FILE
if test 24387 -ne `wc -c <'gone.c'`; then
    echo shar: \"'gone.c'\" unpacked with wrong size!
fi
# end of 'gone.c'
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
-- 
INTERNET:  lavallee@samsung.com
UUCP:      {decvax!{gsg,cg-atla},uunet,ulowell}!ginosko!lavallee
US MAIL:   Samsung Software America. One Corporate Dr.  Andover, Ma.  01810