[mod.sources.games] v01i006: gr - games regulator

games-request@tekred.TEK.COM (04/22/87)

Submitted by: Michael A. Cooper <mcooper@oberon.USC.EDU>
Mod.sources.games: Volume 1, Issue 6
Archive-name: gr

	[This is an update of a program originally posted to mod.sources
	 volume 1 issue 113 (May 1896).  While this isn't a game, it is
	 for game administrators, so I think it's appropriate for this
	 newsgroup.  I haven't used this [we just turn off r-x permission
	 on /usr/games with cron], but Mike welcomes comments (see README).
		-br]

#! /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 MANIFEST Makefile dolink.sh gr.8 gr.c gr.conf
#   gr.conf.5 gr.h logfile.c parse.c
# Wrapped by billr@tekred on Wed Apr 22 09:43:33 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(3571 characters\)
sed "s/^X//" >README <<'END_OF_README'
X
X		G R  -  A   G A M E   R E G U L A T O R
X
X			   for Berkeley UNIX
X
X			      Release 2.0
X			     January, 1987
X
X
XGR is used to regulate game playing.  It checks various system facts
Xto determine if game playing is allowed.  GR can be set up to not
Xallow game playing:
X
X	1) during certain hours (i.e. prime time work hours), 
X	2) when the load average exceeds a set maximum, 
X	3) the number of users exceeds a set maximum, 
X	4) if there are not enough free "special" tty lines 
X	   (i.e. dialup lines), and 
X	5) if a master no-game-playing file is present.  
X
XAll configuration parameters can be specified in a central control
Xfile that is read on the fly.  Please read the manual pages (gr.8 and
Xgr.conf.5) for specific details.
X	
XGR is based on "gsh" written at Reed College by a person who wishes to
Xremain anonymous.  Little of the original code remains, however.
X
XWe have been running GR on VAX 11/750's (under both 4.2 and 4.3 BSD)
Xfor almost a year now without any major problems.  It is very useful
Xfor keeping people from abusing the system with games during heavy
Xusage times when ``real'' work is being done.
X
XSince its last release via mod.sources in May of 1986, there have been
Xseveral key bug fixes.  The most important of which, was a problem
Xwith setuid games not being nuked off as advertised.  I have also
Xmoved almost all configuration parameters to the master control file.
XYou should no longer need to edit gr.h.  See the code for details on
Xthe changes that have been made.
X
XThroughout the code you may notice #ifdef FINDTTY's.  This is there
Xfor finding a user's real tty by looking at there process tree.  It
Xwas written for 4.2BSD, but is not needed for 4.3BSD since the
Xttyname() call now handles things properly.  You should not really
Xneed the code if you are still running 4.2BSD.  Indeed, the version of
XGR posted in mod.sources did not have the code and things seemed to
Xwork okay without it.  If you *really* want to use it, please contact
Xme and I will send you an additional C file containing the findtty()
Xfunction itself.
X
X
X
X			How To Install GR
X
X
XTo install GR: 
X	1) First read the manual pages, gr.conf.5 and gr.8.  They
X	   contain specific information on how GR works and how it 
X	   should be configured.
X	2) Edit Makefile to reflect how you wish to install GR.
X	   You will need to decide what user id GR will run as.
X	   I *strongly* suggest using "daemon" since all of the
X	   setuid games distributed with 4.[23]BSD run as "daemon".
X	   Unless GR is run as "daemon", it will not be able to kill
X	   off these setuid games.  The only other alternative is 
X	   making it setuid "root", but I strongly advise against this.
X	   If /dev/kmem is not readable by the world, but is readable
X	   by a particular group (4.3BSD uses group "kmem"), then set
X	   the group GR will run as to this group.
X	3) Edit the provided "gr.conf" file to customize for your site.
X	4) Type "make gr" to compile GR.
X	5) Type "make create" to create the appropriate directory and
X	   files.  Do this only *once*!
X	6) Run "make dolink" to have the games listed in Makefile
X	   put under control of the GR.
X
X
X
X
X
XIf you encounter any problems, please let me know.  I'm interested in
Xhearing about your successes and failures with GR.  If you find a bug
Xand fix it, please send a context diff along with a note explaining
Xthe problem and your fix.
X
X
XMichael A. Cooper, University Computing Services, U of Southern California
X  UUCP: {sdcrdcf, uscvax}!oberon!mcooper  BITNET: mcooper@uscvaxq
X  ARPA: mcooper@oberon.USC.EDU            PHONE: (213) 743-3462
END_OF_README
if test 3571 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MANIFEST -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MANIFEST\"
else
echo shar: Extracting \"MANIFEST\" \(444 characters\)
sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                  1	This shipping list
X Makefile                  1	
X README                    1	
X dolink.sh                 1	
X gr.8                      1	
X gr.c                      1	
X gr.conf                   1	
X gr.conf.5                 1	
X gr.h                      1	
X logfile.c                 1	
X parse.c                   1	
END_OF_MANIFEST
if test 444 -ne `wc -c <MANIFEST`; then
    echo shar: \"MANIFEST\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(2256 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X# $Header: Makefile,v 1.10 86/12/17 19:36:12 mcooper Exp $
X#
X# Makefile for Game Regulator.
X#
X
X#
X# GAMEDIR - This is where the symbolic links are to be placed.
X#	    Should be /usr/games.
X#
XGAMEDIR = /usr/games
X
X#
X# HIDEDIR - Name of directory to hide the actual executables
X#
XHIDEDIR = $(GAMEDIR)/.hide
X
X#
X# MAN5 - Manual directory for gr.conf.5
X# MAN8 - Manual directory for gr.8
X#
XMAN5 = /usr/usc/man/man5
XMAN5 = /usr/usc/man/man8
X
X# 
X# OWNER - This is the user who owns HIDEDIR.
X# GROUP - This group has read/execute permissions on HIDEDIR and owns
X#	  the Game Regulator which is set[ug]id to OWNER/GROUP.
X#	  Either the owner or the group must have read access to
X#	  /dev/kmem.
X#
XOWNER = daemon
XGROUP = kmem
X
X#
X# NAME - Name of Game Regulator in GAMEDIR.  I have it set to ".gr"
X# 	 so it doesn't show up with ls(1) by default.
X#
XNAME = .gr
X
X#
X# GAMES - The games in the original GAMEDIR to be put under regulation.
X#	  Currently set to the games distributed with 4.3BSD.
X#
XGAMES = aardvark adventure arithmetic backgammon battlestar bcd\
X	bogdict boggle btlgammon canfield chess ching cribbage\
X	doctor factor fish hangman hunt mille rain robots rogue\
X	sail snake teachgammon trek worm worms wump zork
X
XCFLAGS = -O
X
XOBJS = gr.o logfile.o parse.o
XSRCS = gr.c gr.h logfile.c parse.c
X
Xgr: $(OBJS)
X	cc $(OBJS) -o gr
X
X#
X# Set "CFLAGS=-DDEBUG" if you want gr compiled with debug info.
X#
Xdebug: $(OBJS)
X	cc -g $(OBJS) -o gr
X	rm -f gr
X	ln -s gr debug
X
X.c.o:
X	cc $(CFLAGS) -c $*.c
X
X$(OBJS): gr.h
X
Xinstall: gr gr.conf.5 gr.8
X	install -m 6751 -o $(OWNER) -g $(GROUP) gr $(GAMEDIR)/$(NAME)
X	install -c gr.conf.5 $(MAN5)
X	install -c gr.8 $(MAN8)
X
Xcreate:
X	-mkdir $(HIDEDIR)
X	chown $(OWNER) $(HIDEDIR)
X	chgrp $(GROUP) $(HIDEDIR)
X	chmod 770 $(HIDEDIR)
X	cp gr.conf $(GAMEDIR)/lib
X	touch $(GAMEDIR)/lib/gr.log
X	chown $(OWNER) $(GAMEDIR)/lib/gr.conf $(GAMEDIR)/lib/gr.log
X	chgrp $(GROUP) $(GAMEDIR)/lib/gr.conf $(GAMEDIR)/lib/gr.log
X	chmod 664 $(GAMEDIR)/lib/gr.conf $(GAMEDIR)/lib/gr.log
X
Xdolink: dolink.sh
X	sed -e s#HIDEDIR#$(HIDEDIR)# -e s#GAMEDIR#$(GAMEDIR)# \
X		-e s#NAME#$(NAME)# dolink.sh > dolink
X	chmod +x dolink
X	dolink $(GAMES)
X
Xclean:
X	rm -f *.o log dolink gr.shar debug
X
Xshar:
X	shar README gr.8 gr.conf.5 Makefile gr.conf $(SRCS) dolink.sh > gr.shar
END_OF_Makefile
if test 2256 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f dolink.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dolink.sh\"
else
echo shar: Extracting \"dolink.sh\" \(203 characters\)
sed "s/^X//" >dolink.sh <<'END_OF_dolink.sh'
X#!/bin/csh -f
X#
X# dolink - Move and link files for GR.
X#
X# **** Do NOT edit this file - it is automatically generated ****
X#
Xcd GAMEDIR
Xforeach i ($*)
X	echo Doing $i...
X	mv $i HIDEDIR
X	ln -s NAME $i
Xend
END_OF_dolink.sh
if test 203 -ne `wc -c <dolink.sh`; then
    echo shar: \"dolink.sh\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gr.8 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gr.8\"
else
echo shar: Extracting \"gr.8\" \(3107 characters\)
sed "s/^X//" >gr.8 <<'END_OF_gr.8'
X.\"
X.\" $Header: gr.8,v 1.1 86/12/17 19:31:25 mcooper Exp $
X.\"
X.TH GR 8 12/17/86
X.ds ]W USC Computing Services
X.SH NAME
Xgr \- Game Regulator
X.SH SYNOPSIS
Xln -s
X.B GR
X.I game	
X\- To install the
X.B GR
X.SH DESCRIPTION
X.I GR
Xis a program used to regulate game playing.
XWhen invoked, 
X.I GR
Xlooks at the name it was called by (argv[0]) and assumes that is the name
Xof the game that is to be played.
XThe actual binaries are located in a ``hidden'' directory (usually
X.B /usr/games/.hide).
XBefore an actual game is started, 
X.I GR
Xdetermines several system facts.
X.PP
XThe file
X.B /usr/games/lib/gr.conf
Xis the configuration and control file for
Xthe
X.I GR.
XIt
Xis checked to determine: 1) the maximum load average, 2) the maximum
Xnumber of users, for game playing to be allowed, and 3)
Xthe priority (see 
X.I setpriority(2))
Xthe game will run at.
XThere are also some configuration parameters that you may set.
XSee the manual on
X.I gr.conf(5)
Xfor details.
X.PP
XIf the initial system conditions are satisfactory, then the requested game
Xis forked (via 
X.I fork(2))
Xand  the
X.I GR
Xgoes into a loop where it sleeps for an interval and
Xthen wakes up 
Xand checks the current time, number of users, the load average and
Xif the 
X.I nogames
Xfile is present (see below).  If any of these conditions is unsatisfactory, an
Xappropriate message is printed and the user is warned to end their game.
XThe user is given a total of three warnings (with an appropriate interval 
Xin-between warnings to act) before the game is actually killed.
X.PP
XThe file
X.B /usr/games/nogames
Xcan be used to ``turn off'' game playing.  The first line of the file is
Xused as part of a message that is displayed to the user.
XUseful for turning off game playing for one reason or another.
X.SH AUTHOR
XMichael A. Cooper (mcooper@oberon.USC.EDU)
X.br
XUSC Computing Services
X.SH FILES
X.nf
X.ta \w'/usr/games/lib/gr.conf 'u
X/usr/games/lib/gr.conf	- Master configuration file
X/usr/games/lib/gr.log	- Log file 
X/usr/games/.hide	- Directory of ``real'' binaries
X/usr/games/nogames	- Turn off game playing
X.SH SEE ALSO
Xgr.conf(5), fork(2), kill(2), setpriority(2),
X.br
XSection 6 of the UNIX Programmer's Manual.
X.SH DIAGNOSTICS
X.IP "Game playing is not permitted on tty?? at any time."
XThe installer of the 
X.I GR
Xspecified tty ``??'' as a tty on which game playing is 
X.I never
Xpermitted.
X.IP "The system load is greater than \fIN\fR."
XThe load average exceeds the limit of ``\fIN\fR'' for the requested
Xgame.
X.IP "There are more than \fIN\fR users logged in."
XThe number of users exceeds the limit of ``\fIN\fR'' for the requested
Xgame.
X.IP "Game playing is not permitted between \fIM\fR and \fIN\fR hours on weekdays."
XThe installer of the
X.I GR
Xhas specified that game playing is not permitted between the hours of
X.I M
Xand 
X.I N
Xduring weekdays.
X.IP "There are not \fIN\fR \fIspecial\fR ttys available."
XThe installer of the
X.I GR
Xhas specified that there must be at least 
X.I N
Xspare 
X.I special
Xttys available for game playing to be permitted.
X.SH BUGS
XThere are several ways to play games on  
X.I special
Xttys no matter the number of
X.I special
Xttys in use.
END_OF_gr.8
if test 3107 -ne `wc -c <gr.8`; then
    echo shar: \"gr.8\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gr.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gr.c\"
else
echo shar: Extracting \"gr.c\" \(16592 characters\)
sed "s/^X//" >gr.c <<'END_OF_gr.c'
X/*
X *                  GR - A  G A M E   R E G U L A T O R
X *                          for Berkeley UNIX
X *
X */
X
X#ifndef lint
Xstatic char *RCSid = "$Header: gr.c,v 1.32 86/12/02 20:26:57 mcooper Locked $";
X#endif
X
X/*
X *------------------------------------------------------------------
X *
X * $Source: /big/src/usc/bin/gr/RCS/gr.c,v $
X * $Revision: 1.32 $
X * $Date: 86/12/02 20:26:57 $
X * $State: Exp $
X * $Author: mcooper $
X * $Locker: mcooper $
X *
X *------------------------------------------------------------------
X *
X * Michael A. Cooper (mcooper@oberon.USC.EDU)
X * University Computing Services,
X * University of Southern California
X *
X *------------------------------------------------------------------
X * $Log:	gr.c,v $
X * Revision 1.32  86/12/02  20:26:57  mcooper
X * #ifdef'd all dprintf's.
X * 
X * Revision 1.31  86/08/06  20:07:55  mcooper
X * Yet another attempt at fixing the setuid
X * problem.  Think I got it this time!
X * 
X * Revision 1.30  86/08/05  12:54:22  mcooper
X * Fixed setuid() problem (again).
X * 
X * Revision 1.29  86/07/30  12:22:30  mcooper
X * If DEBUG is defined, use a SLEEPTIME of 5
X * to speed things up.
X * 
X * Revision 1.28  86/07/17  16:13:04  mcooper
X * All fatal errors now use fatal().
X * 
X * Revision 1.27  86/07/17  14:49:21  mcooper
X * - Fixed bug in freettys() that caused
X *   was_freettys to be TRUE when there
X *   where exactly cf->cf_nofreettys free.
X * - Tweaked was_freettys user message a bit.
X * 
X * Revision 1.26  86/07/15  14:53:36  mcooper
X * Determine user name in setup() instead of
X * everytime logfile() is called.
X * 
X * Revision 1.25  86/07/14  19:03:45  mcooper
X * Log more info to a log file.
X * 
X * Revision 1.24  86/07/14  15:53:53  mcooper
X * Moved most of the compile time configuration
X * options to the control file.
X * 
X * Revision 1.23  86/07/03  15:54:41  mcooper
X * Now checks for NOGAMING file along with the
X * other tests in case game playing is turn off
X * while we're playing.
X * 
X * Revision 1.22  86/07/03  14:25:07  mcooper
X * - Major work on "special" ttys.  
X *   - Bug fix in deltty().
X *   - Changed are #define macros.
X *   - Added findtty() (in findtty.c) to try and
X *     determine the users real tty.  (4.2bsd)
X * - Added debug mode.
X * - Misc. - Can't remember them all.
X * 
X * Revision 1.21  86/06/18  13:46:47  mcooper
X * Implemented BAD_TTYS - Check to see if
X * the user is on a BAD_TTYS.  If so, game
X * playing is not permited at all.  Also
X * cleaned up #ifdef TOD stuff.
X * 
X * Revision 1.20  86/06/04  12:21:23  mcooper
X * Use SP_NAME for name of special ttys when
X * printing messages to the user.
X * 
X * Revision 1.19  86/06/02  13:31:53  mcooper
X * More cleanup on SP_TTYS.
X * 
X * Revision 1.18  86/05/30  21:33:10  mcooper
X * Added support for "special" ttys.  i.e. only a limited
X * number of SP_TTYS.
X * 
X * Revision 1.17  86/05/14  16:08:44  mcooper
X * Cleaned up and somewhat de-linted.
X * 
X *------------------------------------------------------------------
X */
X
X#include <stdio.h>
X#include <pwd.h>
X#include <signal.h>
X#include <sys/wait.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X#include <sys/file.h>
X#include <utmp.h>
X#include <nlist.h>
X
X#include <sys/vm.h>
X#include <machine/pte.h>
X
X#include "gr.h"
X
X#ifdef DEBUG
Xint sleeptime = 5;
X#else
Xint sleeptime = SLEEPTIME;
X#endif
X
Xint hastried = 0;
X
Xint Fswap;
Xint Fpmem;
Xint Fkmem;
Xint Futmp;
X
Xchar *mytty;
Xchar *user;
Xchar *prog = "GR";
X
Xstatic char *badtty;
X#ifdef FINDTTY
Xstruct pte *usrptmap, *usrpt;	/* Hold values of _Usrptmap & _usrpt */
Xint i_proc, i_nproc;			/* Hold values of _proc & _nproc */
X#endif
X
Xint was_freettys;
Xint was_badttys;
Xint was_tod;
Xint was_load;
Xint was_nogames;
Xint was_users;
X
Xstatic double avenrun[3];
Xstatic char *game;
Xchar mbuf[BUFSIZ];
X
X
Xchar *warnmesg1 = "to save your game.  If you do not leave\r\nthe game ";
Xchar *warnmesg2 = "within this period, your game will be terminated.";
X
Xchar *warntime[3] = {
X	"4 minutes ",
X	"2 minutes ",
X	"1 minute "
X};
X
X
Xstatic struct utmp buf;
Xstatic struct nlist nl[] = {
X#define N_AVENRUN	0
X	{ "_avenrun" },
X#ifdef FINDTTY
X#define N_PROC		1				/* Address of process table */
X	{ "_proc" },
X#define N_NPROC		2				/* Length of process table */
X	{ "_nproc" },
X#define N_USRPTMAP 	3
X	{ "_Usrptmap" },
X#define N_USRPT 	4
X	{ "_usrpt" },
X#endif
X	{ "" },
X};
X
Xchar *rindex();
Xchar *deltty();
Xchar *gettyname();
Xchar *getaline();
Xlong time();
X
Xint debug = 0;
Xstruct cfinfo *cf, *parse();
X
X/*VARARGS*/
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	game = rindex(argv[0], '/');
X	if (game == 0)
X		game = argv[0];
X	else
X		game++;	/* Skip the '/' */
X
X	if (strcmp(game, "debug") == 0)
X		debug = 1;
X
X	if (debug) {
X		setbuf(stdout, 0);
X#ifdef DEBUG
X		dprintf("debug is ON\n");
X#endif DEBUG
X		sleeptime = 5;
X	}
X
X	setup(game);
X
X	if (checkfor(cf->cf_nogames) || tod() || badttys() || freettys() || 
X	  users() || load()) {
X		fprintf(stderr, "Sorry, no games now.\n");
X		if (was_nogames)
X			fprintf(stderr, getaline(cf->cf_nogames));
X		if (was_freettys)
X			fprintf(stderr, "There %s not %d %s tty%c available.\n",
X				(cf->cf_nofreettys > 1) ? "are" : "is", cf->cf_nofreettys,
X				cf->cf_spname, (cf->cf_nofreettys > 1) ? 's' : 0);
X		if (was_badttys)
X			fprintf(stderr, 
X			"Game playing is not permitted on tty%s at any time.\n",
X				badtty);
X		if (was_load)
X			fprintf(stderr, 
X				"The system load is greater than %.2lf.\n",
X				cf->cf_load);
X		if (was_users)
X			fprintf(stderr, 
X				"There are more than %d users logged in.\n",
X				cf->cf_users);
X		if (was_tod)
X			fprintf(stderr, 
X"Game playing is not permitted between %d00 and %d00 hours on weekdays.\n", 
X				cf->cf_todmorn, cf->cf_todeven);
X		exit(1);
X	}
X	if (cf->cf_logfile[0]) {
X		sprintf(mbuf, "startup of %s (%d)", game, getpid());
X		logfile(mbuf, cf->cf_logfile);
X	}
X	play(game, argv);
X}
X
Xplay(game, args)
Xchar *game;
Xchar **args;
X{
X	int pid;
X	char tmp[BUFSIZ];
X
X	switch (pid = fork()) {
X		case -1:
X			fprintf(stderr, "Cannot fork.\n");
X			exit(1);
X		case 0:
X			(void) strcpy(tmp, cf->cf_hidedir);
X			(void) strcat(tmp, "/");
X			(void) strcat(tmp, game);
X			(void) signal(SIGINT, SIG_DFL);
X			(void) signal(SIGQUIT, SIG_DFL);
X			(void) signal(SIGTSTP, SIG_DFL);
X#ifdef DEBUG
X			dprintf("before: getuid = %d\n", getuid());
X			dprintf("before: geteuid = %d\n", geteuid());
X#endif DEBUG
X			(void) setuid(getuid());
X#ifdef DEBUG
X			dprintf("after: getuid = %d\n", getuid());
X			dprintf("after: geteuid = %d\n", geteuid());
X#endif DEBUG
X			if(setpriority(PRIO_PROCESS, 0, cf->cf_priority) < 0) {
X				fatal("setpriority", TRUE);
X				/*NOTREACHED*/
X			}
X			execv(tmp, args);
X			fatal(tmp, TRUE);
X			/*NOTREACHED*/
X	}
X	for (;;) {
X		sleep(sleeptime);
X		if (load() || checkfor(cf->cf_nogames) || tod() || freettys() || 
X		  users()) {
X			warn(0);
X			sleep(sleeptime);
X			if (reprieve())
X				continue;
X			sleep(sleeptime);
X			if (reprieve())
X				continue;
X			warn(1);
X			sleep(sleeptime);
X			if (reprieve())
X				continue;
X			warn(2);
X			sleep(sleeptime);
X			if (reprieve())
X				continue;
X			blast(pid);
X		}
X	}
X}
X
Xreprieve()
X{
X	static char mess[] = "\r\nYou have a reprieve.  Continue playing.\r\n";
X
X	if (checkfor(cf->cf_nogames) || load() || tod() || freettys() || users())
X		return (0);
X	(void) write(2, mess, sizeof(mess));
X	return (1);
X}
X
X/*
X * warn - Warn the user how close his game is to ending.
X */
Xwarn(which)
Xint which;
X{
X	char buf1[BUFSIZ];
X	char buf2[BUFSIZ];
X	char *space = "                                                        ";
X	extern errno;
X
X#ifdef DEBUG
X	dprintf("warn(): which = %d\n", which);
X#endif DEBUG
X
X	if (was_nogames)
X		(void) sprintf(buf2, getaline(cf->cf_nogames));
X	if (was_load)
X		(void) sprintf(buf2, 
X			"The system load is greater than %.2lf.",
X			cf->cf_load);
X	if (was_users)
X		(void) sprintf(buf2, 
X			"There are more than %d users logged in.",
X				cf->cf_users);
X	if (was_freettys)
X		(void) sprintf(buf2, "There %s not %d %s tty%s available.",
X			(cf->cf_nofreettys > 1) ? "are" : "is", cf->cf_nofreettys,
X			cf->cf_spname, (cf->cf_nofreettys > 1) ? "s" : "");
X	if (was_tod)
X		(void) sprintf(buf2, "Game time is over.");
X
X	(void) sprintf(buf1, 
X			"\r\n\007\007\007%s\r\n%s\r\nYou have %s%s%s\r\n%s\r\n",
X			space, buf2, warntime[which], warnmesg1, warnmesg2, space);
X	(void) write(2, buf1, strlen(buf1));
X}
X
X/*
X * blast - Kill the game.
X */
Xblast(pid)
Xint pid;
X{
X	static char mess[] = "\rYour game is forfeit.\r\n";
X
X#ifdef DEBUG
X	dprintf("blast(): pid = %d myuid = %d(%d)\n", pid, getuid(), geteuid());
X#endif DEBUG
X
X	if(!hastried)
X		(void) write(2, mess, sizeof(mess));
X
X	if (cf->cf_logfile[0]) {
X		(void) sprintf(mbuf, "blast(%d) %s", pid, game);
X		(void) logfile(mbuf, cf->cf_logfile);
X	}
X
X	if(kill(pid, SIGHUP) < 0) {
X		(void) sprintf(mbuf, "kill(%d, SIGHUP) failed: %d", pid, errno);
X		(void) logfile(mbuf, cf->cf_logfile);
X#ifdef DEBUG
X		dprintf("%s: ", mbuf);
X		if(debug)perror();
X#endif DEBUG
X	}
X	sleep(30);
X	if(kill(pid, SIGKILL) < 0) {
X		(void) sprintf(mbuf, "kill(%d, SIGKILL) failed: %d", pid, errno);
X		(void) logfile(mbuf, cf->cf_logfile);
X#ifdef DEBUG
X		dprintf("%s: ", mbuf);
X		if(debug)perror();
X#endif DEBUG
X	}
X	if(!hastried) {
X#ifdef DEBUG
X		dprintf("_before: getuid = %d\n", getuid());
X		dprintf("_before: geteuid = %d\n", geteuid());
X#endif DEBUG
X		(void) setuid(getuid());
X#ifdef DEBUG
X		dprintf("_after: getuid = %d\n", getuid());
X		dprintf("_after: geteuid = %d\n", geteuid());
X#endif DEBUG
X		hastried = 1;
X		blast(pid);
X		return;
X	} else
X		hastried = 0;
X}
X
X/*
X * death - More on killing.
X */
Xdeath()
X{
X	union wait status;
X
X	if (wait3(&status, WNOHANG | WUNTRACED, (char *)0) == 0) {
X		return;
X	}
X	if (status.w_stopval == WSTOPPED) {
X		(void) signal(SIGTSTP, SIG_DFL);
X		(void) kill(getpid(), SIGTSTP);
X		(void) signal(SIGTSTP, SIG_IGN);
X		return;
X	} else {
X#ifdef DEBUG
X		dprintf("\nClosing with exit(0)...\n");
X#endif DEBUG
X		if(cf->cf_logfile[0]) {
X			(void) sprintf(mbuf, "end of %s (%d)", game, getpid());
X			(void) logfile(mbuf, cf->cf_logfile);
X		}
X		(void) close(Fkmem);
X		(void) close(Fpmem);
X		(void) close(Fswap);
X		(void) close(Futmp);
X		exit(0);
X	}
X}
X
X/*
X * setup - Setup constants.
X */
Xsetup(game)
Xchar *game;
X{
X	FILE *list;
X	char *getlogin();
X	struct passwd *pw, *getpwuid();
X
X	Fswap = Fpmem = Fkmem = Futmp = 0;
X
X	if ((Futmp = open("/etc/utmp", 0)) < 0) {
X		fatal("/etc/utmp", TRUE);
X		/*NOTREACHED*/
X	}
X	if ((Fkmem = open("/dev/kmem", 0)) < 0) {
X		fatal("/dev/kmem", TRUE);
X		/*NOTREACHED*/
X	}
X	if ((Fpmem = open("/dev/mem", 0)) < 0) {
X		fatal("/dev/mem", TRUE);
X		/*NOTREACHED*/
X	}
X	if ((Fswap = open("/dev/drum", 0)) < 0) {
X		fatal("/dev/drum", TRUE);
X		/*NOTREACHED*/
X	}
X
X	nlist("/vmunix", nl);
X	if (nl[0].n_type == 0) {
X		fatal("/vmunix", TRUE);
X		/*NOTREACHED*/
X	}
X
X#ifdef FINDTTY
X	usrptmap = (struct pte *) nl[N_USRPTMAP].n_value;
X	usrpt = (struct pte *) nl[N_USRPT].n_value;
X
X#ifdef DEBUG
X	dprintf("seeking _nproc...\n");
X#endif DEBUG
X	memseek(Fkmem, (long) nl[N_NPROC].n_value);
X	if (read(Fkmem, (char *) &i_nproc, sizeof i_nproc) != sizeof i_nproc) {
X		fatal("Could not get value of nproc.", FALSE);
X		/*NOTREACHED*/
X	}
X#ifdef DEBUG
X	dprintf("seeking _proc...\n");
X#endif DEBUG
X	memseek(Fkmem, (long) nl[N_PROC].n_value);
X	if (read(Fkmem, (char *) &i_proc, sizeof i_proc) != sizeof i_proc) {
X		fatal("Could not get value of proc.", FALSE);
X		/*NOTREACHED*/
X	}
X#endif
X	mytty = gettyname();
X#ifdef DEBUG
X	dprintf("mytty = '%s'\n", mytty);
X#endif DEBUG
X	
X	if ((list = fopen(CONTROL, "r")) == NULL) {
X		fatal(CONTROL, TRUE);
X		/*NOTREACHED*/
X	}
X
X	if ((user = getlogin()) == NULL) {
X		if ((pw = getpwuid(getuid())) != NULL)
X			user = pw->pw_name;
X		else
X			user = "(unknown)";
X#ifdef DEBUG
X		dprintf("getlogin() failed. user = '%s'\n", user);
X#endif DEBUG
X	}
X#ifdef DEBUG
X		else dprintf("getlogin() succeeded. user = '%s'\n", user);
X#endif DEBUG
X
X	cf = parse(list, game);
X
X#ifdef DEBUG
X	dprintf("game = '%s'\tmax load = '%.2f'\tmax users = '%d'\tpriority = %d\n",
X			cf->cf_game, cf->cf_load, cf->cf_users, cf->cf_priority);
X	dprintf("badttys = '%s'\tfreettys = '%s'\nnofree = %d\tsp_name = '%s'\n", 
X		cf->cf_badttys, cf->cf_freettys, cf->cf_nofreettys, cf->cf_spname);
X	dprintf("tod morn = %d \t even = %d\n", cf->cf_todmorn, cf->cf_todeven);
X#endif DEBUG
X		
X	(void) fclose(list);
X	(void) signal(SIGCHLD, death);
X	(void) signal(SIGINT, SIG_IGN);
X	(void) signal(SIGQUIT, SIG_IGN);
X	(void) signal(SIGTSTP, SIG_IGN);
X}
X
X/*
X * load - Return the 5 minute load average
X */
Xload()
X{
X	(void) lseek(Fkmem, (long)nl[N_AVENRUN].n_value, 0);
X	(void) read(Fkmem, avenrun, sizeof(avenrun));
X	return (was_load = (avenrun[1] >= cf->cf_load));
X}
X
X/*
X * users - Count the number of users logged in.
X */
Xusers()
X{
X	int count = 0;
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	return (was_users = (count > cf->cf_users));
X}
X
X/*
X * tod - Find out if it is okay to play right now.
X */
Xtod()
X{
X	long now;
X	struct tm *localtime();
X	struct tm *ntime;
X
X	if (cf->cf_todmorn == 0 && cf->cf_todeven == 0) {
X#ifdef DEBUG
X		dprintf("tod(): tod not set.\n");
X#endif DEBUG
X		return(was_tod = FALSE);
X	}
X
X	time(&now);
X	ntime = localtime(&now);
X	if(ntime->tm_wday == 0 || ntime->tm_wday == 6)
X		return(was_tod = FALSE);/* OK on Sat & Sun */
X	if(ntime->tm_hour < cf->cf_todmorn || ntime->tm_hour >= cf->cf_todeven)
X		return(was_tod = FALSE);/* OK during non working hours */
X	
X	return(was_tod = TRUE);
X}
X
Xcheckfor(file)
Xchar *file;
X{
X#ifdef DEBUG
X	dprintf("checkfor(%s) called\n", file);
X#endif DEBUG
X
X	was_nogames = access(file, R_OK) == 0;
X#ifdef DEBUG
X	dprintf("checkfor(): access = %d\n", was_nogames);
X#endif DEBUG
X	return(was_nogames);
X}
X
X/*
X * getaline - Returns the first line from file.
X */
Xchar *
Xgetaline(file)
Xchar *file;
X{
X	char buf[BUFSIZ];
X	FILE *fd, *fopen();
X
X	if((fd = fopen(file, "r")) != NULL) {
X		fgets(buf, sizeof(buf), fd);
X		(void) fclose(fd);
X		return(buf);
X	}
X	return(NULL);
X}
X
X/*
X * freettys - Find out if there are enough free ttys.
X *		The user invoking a game (under GR) must be on
X *		one of the ttys listed in cf->cf_freettys for this check.
X */
Xfreettys()
X{
X	int left = 0;
X	char *remttys;
X
X	remttys = cf->cf_freettys;
X	if(strlen(remttys) < 2)
X		return;
X
X#ifdef DEBUG
X	dprintf("freeyttys started. ttys = '%s'\n", remttys);
X#endif DEBUG
X
X	/*
X	 * If you're not on a "special" tty, we don't
X	 * worry about you.
X	 */
X	if(!sgrep(mytty, remttys)) {
X#ifdef DEBUG
X		dprintf("You're NOT on a special tty.\n");
X#endif DEBUG
X		return(0);
X	}
X
X#ifdef DEBUG
X	dprintf("You're on a special tty.\n");
X#endif DEBUG
X
X	(void) lseek(Futmp, (long)0, 0);
X	while (read(Futmp, &buf, sizeof(buf)) > 0) {
X		if (buf.ut_name[0] != '\0') {
X			if(strncmp(buf.ut_line, "tty", 3) == 0)
X				remttys = deltty(buf.ut_line+3, remttys);
X		}
X	}
X
X	left = strlen(remttys) / 2;
X#ifdef DEBUG
X	dprintf("remaining ttys = '%s' # left = %d\n", remttys, left);
X#endif DEBUG
X	return(was_freettys = (left < cf->cf_nofreettys));
X}
X
X/*
X * deltty - delete a tty "name" from the remaining ttys
X */
Xchar *
Xdeltty(name, list)
Xchar *name;
Xchar *list;
X{
X	char tmp[BUFSIZ];
X	register int i;
X
X	i = 0;
X	while(*list) {
X		if (*list == *name) {
X			if(*++list == *++name) {
X				*++list;
X			} else {
X				*--list;
X			}
X			*--name;
X		} 
X		tmp[i++] = *list++;
X	}
X	tmp[i] = NULL;
X	return(tmp);
X}
X
X/*
X * sgrep(x, str) -- check for x in str.  Return 1 (TRUE) if exists.
X *			Otherwise 0 (FALSE).
X */
X
Xsgrep(x, str)
Xchar 	*x;
Xchar 	*str;
X{
X	if (!str)
X		return(FALSE);
X	while(*str) {
X		if(*str == *x){
X			if(*++str == *++x) {
X				return(TRUE);
X			} else {
X				*--x;
X			}
X		}
X		*++str;
X	}
X	return(FALSE);
X}
X
X/*
X * badttys - Are we allowed to play games on this tty?
X */
Xbadttys()
X{
X	if(sgrep(mytty, cf->cf_badttys)) {
X		badtty = mytty;
X		return(was_badttys = TRUE);
X	}
X	return(was_badttys = FALSE);
X}
X
X/*
X * gettyname - Determine which tty we're on.
X *             Returns 2 char string.
X */
Xchar *
Xgettyname()
X{
X	char *ttyname();
X#ifdef FINDTTY
X	char *findtty();
X	char *t, *t2;
X
X#ifdef DEBUG
X	dprintf("gettyname(): calling findtty()...\n");
X#endif DEBUG
X	t = findtty(getpid());
X	if (strcmp(t, "co") == 0) {	/* We're probably  using rlogin or telnet */
X		t2 = ttyname(2)+8;
X#ifdef DEBUG
X		dprintf("t2 = '%s'\n", t2);
X#endif DEBUG
X		if (strcmp(t, t2)) { 	/* there's a difference: so believe ttyname() */
X#ifdef DEBUG
X			dprintf("gettyname: difference.  using t2\n");
X#endif DEBUG
X			t = t2;
X		}
X	}
X	return(t);
X#else
X#ifdef DEBUG
X	dprintf("gettyname(): using ttyname()...\n");
X#endif DEBUG
X	return(ttyname(2)+8);
X#endif
X}
X
Xfatal(msg, pflag)
Xchar *msg;
Xint pflag;
X{
X	fprintf(stderr, "%s: ", prog);
X	if (pflag)
X		perror(msg);
X	else
X		fprintf(stderr, "Fatal Error: %s\n", msg);
X	exit(1);
X}
END_OF_gr.c
if test 16592 -ne `wc -c <gr.c`; then
    echo shar: \"gr.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gr.conf -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gr.conf\"
else
echo shar: Extracting \"gr.conf\" \(1455 characters\)
sed "s/^X//" >gr.conf <<'END_OF_gr.conf'
X#
X# $Header: gr.conf,v 1.1 86/12/04 13:23:47 mcooper Exp $
X#
X# GENERIC Game Regulator Control and Configuration File
X#
X# 	Name 		- Name of game in /usr/games. 	(string)
X#	Load 		- Maximum load average.  	(floating point)
X#	Users 		- Maximum number of users.  	(integer)
X#	Priority	- Priority game will run at.
X#			  See setpriority(2).		(integer)
X#
X# A default for all other games may be set by naming the last 
X# entry "default".
X#
X#		 Maximum
X# Name	       Load    Users   Priority
X#--------------------------------------
Xrogue		3.5	14	0
Xarogue		3.5	14	0
Xurogue		3.5	14	0
Xhack		3.5	14	5
Xsail		3.5	14	0
Xempire		3.5	14	5
Xdebug		4.2 	20 	3
Xtest		5.0	20	3
Xdefault		4.0	14	0
X
X
XCONFIGURATION
X#
X#		==================================
X# 			Configuration Section
X#		==================================
X#
X#   Word	  Usage				  Default
X#-----------------------------------------------------------------------
X# "hidedir"	hidedir dir			/usr/games/.hide
X# "freettys"	freettys tty_names number	[no default]
X# "spname"	spname name			[no default]
X# "badttys"	badttys tty_names		[no default]
X# "tod"		tod morning evening		[no default]
X# "logfile"	logfile file			/usr/games/lib/gr.log
X# "nogames"	nogames file			/usr/games/nogames
X#-----------------------------------------------------------------------
X#
X
Xfreettys	h2h3h4h5h6h7h8h9hahbhchdhehf 	1
Xspname		Micom
X
Xbadttys		h0h1
Xtod		8	19
X
Xhidedir		/usr/games/.hide
Xlogfile		/usr/games/lib/gr.log
Xnogames		/usr/games/nogames
END_OF_gr.conf
if test 1455 -ne `wc -c <gr.conf`; then
    echo shar: \"gr.conf\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gr.conf.5 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gr.conf.5\"
else
echo shar: Extracting \"gr.conf.5\" \(4005 characters\)
sed "s/^X//" >gr.conf.5 <<'END_OF_gr.conf.5'
X.\"
X.\" $Header: gr.conf.5,v 1.1 86/12/17 19:29:15 mcooper Exp $
X.\"
X.TH GR.CONF 5 12/17/86
X.ds ]W USC Computing Services
X.SH NAME
Xgr.conf \- Game Regulator control and configuration file
X.SH DESCRIPTION
X.I Gr.conf
Xis 
Xthe configuration and control file for
X.I GR.
XIt is split into two major parts.
XThe first part contains information on the system conditions on a
Xper game basis with a provision for a default.
XThese parameters may need tuning from time to time as system loading
Xand resources change over a long period of time.
XThe second part contains configuration
Xinformation for enabling/disabling certain features of
X.I GR.
XThis part should rarely need updating.
XThe two parts of the control file are seperated by the word
X.I CONFIGURE
Xappearing on a line by itself.
X.PP
XThe syntax of the first section is as follows:
Xthe first field is a
Xgame name (string), 
Xthe second field is the
Xmaximum load average (floating point), 
Xthe third field is the
Xmaximum users (integer), and
Xthe fourth and final field is the
Xpriority (integer) the game should run at (see 
X.I setpriority(2)).
XEach field should be seperated
Xby white space (spaces and/or tabs).  Lines beginning with ``#'' are 
Xignored.
XIf the game name (first field) is called 
X.I default,
Xthen the other three fields are taken as the default parameters for any
Xgame not specifically listed.
XThe
X.I default
Xshould be the last game listed.
XThus, you may specify specific values for a
Xfew games, with a default for all others.
X.PP
XThe second part of the control and configuration file can be used
Xto set 
X.I GR
Xoptions.
XEach 
X.I GR
Xoption is enabled/set with a keyword followed by a set of parameters:
X.IP "hidedir \fIdirectory\fR"
X.I directory
Xis the name of the directory containing the real (hiden) game binaries.
XThe default is
X.I /usr/games/.hide
X.IP "freettys \fIttynames N\fR"
X.I ttynames
Xis a list of ttys (last 2 characters only) that there are to be at least
X.I N
Xavialable for game playing to be allowed.
XUseful if you have a limited number of dialup modem ports or such
Xthat you don't
Xwant monopolized by game players.
X.IP "spname \fIname\fR"
XUse 
X.I name
Xto describe what
X.I freettys
Xare when printing a message to a user.
Xi.e. ``Dialup'', ``Micom'', ``Special'', etc.
X.IP "badttys \fIttynames\fR"
X.I ttynames
Xis a list of ttys (last 2 characters only) on which game playing is
X.B never
Xpermitted.
X.IP "tod \fIN M\fR"
XGame playing is 
X.B never
Xpermitted between the hours of
X.I N
Xand
X.I M
X(24 hour clock format).
X.IP "logfile \fIfile\fR"
XLog information concerning game playing to
X.I file.
XThe default is
X.I /usr/games/lib/gr.log.
X.IP "nogames \fIfile\fR"
XIf
X.I file
Xis present, game playing is not permitted.  The first line of
Xthe file is used to print a message to the user.
XUsed to turn game playing on and off.
XThe default is
X.I /usr/games/nogames.
X.PP
XBelow is a sample file:
X.nf
X.sp 1
X.KS
X    #
X    # Game Regulator Control File
X    #
X    #
X    # Control Section
X    #                   Maximum
X    # Name            Load    Users      Priority
X    #\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
X    rogue             4.0      8            0
X    hack              4.0      8            5
X    sail              4.0      8            0
X    empire            4.0      8            0
X    default           5.0      8            0
X    
X    CONFIGURE
X    #
X    # Configuration section
X    #
X    
X    # should always be at least 1 of ttyd[0125] avialable
X    freettys        d0d1d2d5        1
X    spname          Dialup
X    
X    # no games ever on ttyh[01]
X    badttys	        h0h1
X    
X    # no games from 800 hours to 1900 hours
X    tod             8       19
X    
X    hidedir	        /usr/games/.hide
X    logfile	        /usr/games/lib/gr.log
X    nogames	        /usr/games/nogames
X.KE
X.fi
X.SH AUTHOR
XMichael A. Cooper (mcooper@oberon.USC.EDU)
X.br
XUSC Computing Services
X.SH FILES
X/usr/games/lib/gr.conf
X.SH SEE ALSO
Xgr(8), setpriority(2),
X.br
XSection 6 of the UNIX Programmer's Manual.
END_OF_gr.conf.5
if test 4005 -ne `wc -c <gr.conf.5`; then
    echo shar: \"gr.conf.5\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gr.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gr.h\"
else
echo shar: Extracting \"gr.h\" \(3671 characters\)
sed "s/^X//" >gr.h <<'END_OF_gr.h'
X/*
X * $Header: gr.h,v 1.14 86/12/17 19:25:02 mcooper Exp $
X *------------------------------------------------------------------
X *
X * $Source: /big/src/usc/bin/gr/RCS/gr.h,v $
X * $Revision: 1.14 $
X * $Date: 86/12/17 19:25:02 $
X * $State: Exp $
X * $Author: mcooper $
X * $Locker:  $
X *
X *------------------------------------------------------------------
X *
X * Michael A. Cooper (mcooper@oberon.USC.EDU)
X * University Computing Services,
X * University of Southern California
X *
X *------------------------------------------------------------------
X * $Log:	gr.h,v $
X * Revision 1.14  86/12/17  19:25:02  mcooper
X * Config file is now called "gr.conf".
X * 
X * Revision 1.13  86/12/02  19:50:43  mcooper
X * Removed all references to FINDTTY
X * since findtty.c is not being distributed.
X * 
X * Revision 1.12  86/11/07  19:23:21  mcooper
X * If BSD42 is defined (from Makefile), then we
X * define FINDTTY.  This file should no longer need
X * tweaking by people installing gr.
X * 
X * Revision 1.11  86/07/17  15:22:39  mcooper
X * Bumped MAXTTYS to 120 for portability to
X * other UCS machines.
X * 
X * Revision 1.10  86/07/14  15:54:47  mcooper
X * Moved most of the compile time configuration
X * options to the control file.
X * 
X * Revision 1.9  86/07/03  14:27:44  mcooper
X * - Major work on "special" ttys.  
X *   - Bug fix in deltty().
X *   - Changed are #define macros.
X *   - Added findtty() (in findtty.c) to try and
X *     determine the users real tty.  (4.2bsd)
X * - Added debug mode.
X * - Misc. - Can't remember them all.
X * 
X * Revision 1.8  86/06/18  13:47:58  mcooper
X * Implemented BAD_TTYS - Check to see if
X * the user is on a BAD_TTYS.  If so, game
X * playing is not permited at all.  Also
X * cleaned up #ifdef TOD stuff.
X * 
X * Revision 1.7  86/06/04  12:21:55  mcooper
X * Use SP_NAME for name of special ttys when
X * printing messages to the user.
X * 
X * Revision 1.6  86/06/02  13:32:20  mcooper
X * More cleanup on SP_TTYS.
X * 
X * Revision 1.5  86/05/30  21:34:05  mcooper
X * Added support for "special" ttys.  i.e. only a limited
X * number of SP_TTYS.
X * 
X * Revision 1.4  86/05/14  16:09:17  mcooper
X * Cleaned up and somewhat de-linted.
X * 
X * Revision 1.3  86/03/25  15:50:31  mcooper
X * Moved CONTROL back to normal place in /usr/games/lib.
X * 
X * Revision 1.2  86/03/25  15:47:57  mcooper
X * Lines beginning with '#' are comment lines.
X * 
X * Revision 1.1  86/02/12  17:49:54  mcooper
X * Initial revision
X * 
X *------------------------------------------------------------------
X */
X
X/*
X * CONTROL - Master control file.
X */
X#ifndef DEBUG
X# define CONTROL		"/usr/games/lib/gr.conf"
X#else
X# define CONTROL		"gr.conf"
X#endif
X
X/* 
X * MAXTTYS - The maximum number of tty?? in /dev.
X *	      Only used with FINDTTY.
X */
X#define MAXTTYS	120
X
X
X/*
X * Misc. defines - Leave this alone!
X */
X#define TRUE		1
X#define FALSE		0
X#define COMMENT		'#'
X#define SLEEPTIME	60		/* sleep interval */
X#define dprintf		if (debug) printf
X
X#define CFBUF		256
X
Xstruct cfinfo {
X	char 	cf_game[CFBUF];		/* name of the game */
X	double 	cf_load;			/* max load average */
X	int 	cf_users;			/* max users */
X	int 	cf_priority;		/* game priority (setpriority(2)) */
X	char 	cf_badttys[CFBUF];	/* ttys game playing not permitted on */
X	char 	cf_freettys[CFBUF];	/* list of ttys to watch */
X	int 	cf_nofreettys;		/* number of freettys must be open */
X	char 	cf_spname[CFBUF];	/* name to use for freettys */
X	int 	cf_todmorn;			/* hour of morning for games off */
X	int 	cf_todeven;			/* hour of evening for games on */
X	char	cf_hidedir[CFBUF];	/* directory containing the real games */
X	char	cf_logfile[CFBUF];	/* file to log info to */
X	char	cf_nogames[CFBUF];	/* file that says no games */
X};
X
END_OF_gr.h
if test 3671 -ne `wc -c <gr.h`; then
    echo shar: \"gr.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f logfile.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"logfile.c\"
else
echo shar: Extracting \"logfile.c\" \(1761 characters\)
sed "s/^X//" >logfile.c <<'END_OF_logfile.c'
X#ifndef lint
Xstatic char *RCSid = "$Header: logfile.c,v 1.7 86/12/02 20:27:42 mcooper Locked $";
X#endif
X
X/*
X *------------------------------------------------------------------
X *
X * $Source: /big/src/usc/bin/gr/RCS/logfile.c,v $
X * $Revision: 1.7 $
X * $Date: 86/12/02 20:27:42 $
X * $State: Exp $
X * $Author: mcooper $
X * $Locker: mcooper $
X *
X *------------------------------------------------------------------
X *
X * Michael Cooper (mcooper@oberon.USC.EDU)
X * University Computing Services,
X * University of Southern California,
X * Los Angeles, California,   90089-0251
X * (213) 743-3469
X *
X *------------------------------------------------------------------
X * $Log:	logfile.c,v $
X * Revision 1.7  86/12/02  20:27:42  mcooper
X * "#ifdef DEBUG"'s all dprintf's.
X * 
X * Revision 1.6  86/07/15  14:54:18  mcooper
X * Determine user name in setup() instead of
X * everytime logfile() is called.
X * 
X * Revision 1.5  86/07/14  15:54:42  mcooper
X * Moved most of the compile time configuration
X * options to the control file.
X * 
X * Revision 1.4  86/05/14  16:29:12  mcooper
X * Somewhat de-linted.
X * 
X * Revision 1.3  86/03/25  15:44:35  mcooper
X * more of same.
X * 
X * Revision 1.2  86/03/25  15:35:43  mcooper
X * New headers...
X * 
X *------------------------------------------------------------------
X */
X
X
X#include <stdio.h>
X#include "gr.h"
X
Xextern int debug;
Xextern char *user;
Xextern char *mytty;
X
Xlogfile(msg, file)
Xchar *msg;
Xchar *file;
X{
X	char *ctime();
X	double now;
X	FILE *fd, *fopen();
X
X	(void) time(&now);
X
X#ifdef DEBUG
X	dprintf("logfile(): user = '%s' tty = '%s'\n", user, mytty);
X#endif DEBUG
X
X	if((fd = fopen(file, "a")) != NULL){
X		(void) fprintf(fd, "%-9s tty%-3s %10.24s  [ %s ]\n", 
X				user, mytty, ctime(&now), msg);
X		(void) fclose(fd);
X	}
X}
END_OF_logfile.c
if test 1761 -ne `wc -c <logfile.c`; then
    echo shar: \"logfile.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f parse.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"parse.c\"
else
echo shar: Extracting \"parse.c\" \(3910 characters\)
sed "s/^X//" >parse.c <<'END_OF_parse.c'
X#ifndef lint
Xstatic char *RCSid = "$Header: parse.c,v 1.5 86/12/02 20:28:02 mcooper Locked $";
X#endif
X
X/*
X *------------------------------------------------------------------
X *
X * $Source: /big/src/usc/bin/gr/RCS/parse.c,v $
X * $Revision: 1.5 $
X * $Date: 86/12/02 20:28:02 $
X * $State: Exp $
X * $Author: mcooper $
X * $Locker: mcooper $
X *
X *------------------------------------------------------------------
X *
X * Michael A. Cooper
X * University Computing Services, 
X * University of Southern California
X * (mcooper@oberon.USC.EDU)
X *
X *------------------------------------------------------------------
X * $Log:	parse.c,v $
X * Revision 1.5  86/12/02  20:28:02  mcooper
X * "#ifdef DEBUG"'s all dprintf's.
X * 
X * Revision 1.4  86/07/17  16:15:45  mcooper
X * All fatal errors now use fatal().
X * 
X * Revision 1.3  86/07/14  16:00:40  mcooper
X * - Don't setup default logfile.
X * - Mostly de-linted.
X * 
X * Revision 1.2  86/07/14  15:55:30  mcooper
X * Added rcs headers.
X * 
X *------------------------------------------------------------------
X */
X
X#include <stdio.h>
X#include "gr.h"
X
Xextern int debug;
X
Xstruct cfinfo *
Xparse(fd, game)
XFILE *fd;
Xchar *game;
X{
X	char lbuf[BUFSIZ], tmp[3][BUFSIZ];
X	int config = FALSE;
X	int foundname = FALSE;
X	struct cfinfo cf;
X	
X	/*
X	 * setup some defaults
X	 */
X	cf.cf_nofreettys = 2;
X	cf.cf_load = 4.0;
X	cf.cf_users = 8;
X	(void) strcpy(cf.cf_spname, "Special");
X	(void) strcpy(cf.cf_hidedir, "/usr/games/.hide");
X	(void) strcpy(cf.cf_nogames, "/usr/games/nogames");
X
X	while (fgets(lbuf, sizeof(lbuf), fd)) {
X		if (lbuf[0] == COMMENT || lbuf[0] == '\n')
X			continue;
X
X		tmp[0][0] = NULL;
X		tmp[1][0] = NULL;
X		tmp[2][0] = NULL;
X
X		(void) sscanf(lbuf, "%s%s%s", tmp[0], tmp[1], tmp[2]);
X#ifdef DEBUG
X		dprintf("tmp[0] = '%s' tmp[1] = '%s' tmp[2] = '%s'\n", 
X			tmp[0], tmp[1], tmp[2]);
X#endif DEBUG
X
X		if (strncmp(tmp[0], "CONFIG", 6) == 0) {
X			config = TRUE;
X#ifdef DEBUG
X			dprintf("found config\n");
X#endif DEBUG
X			continue;
X		}
X
X		if (config) {
X			if (strncmp(tmp[0], "badttys", 7) == 0) {
X				(void) strcpy(cf.cf_badttys, tmp[1]);
X			}
X			else if (strncmp(tmp[0], "freettys", 8) == 0) {
X				(void) strcpy(cf.cf_freettys, tmp[1]);
X				cf.cf_nofreettys = atoi(tmp[2]);
X			}
X			else if (strncmp(tmp[0], "spname", 6) == 0) {
X				(void) strcpy(cf.cf_spname, tmp[1]);
X			}
X			else if (strncmp(tmp[0], "tod", 3) == 0) {
X				cf.cf_todmorn = atoi(tmp[1]);
X				cf.cf_todeven = atoi(tmp[2]);
X			}
X			else if (strncmp(tmp[0], "debug", 5) == 0) {
X				if (strcmp(tmp[1], "on") == 0) 
X					debug = TRUE;
X				else
X					debug = FALSE;
X			}
X			else if (strncmp(tmp[0], "hidedir", 7) == 0) {
X				if(tmp[1][0] == NULL) {
X					fatal("No hiden directory defined.");
X					/*NOTREACHED*/
X				}
X				(void) strcpy(cf.cf_hidedir, tmp[1]);
X			}
X			else if (strncmp(tmp[0], "nogames", 7) == 0) {
X				(void) strcpy(cf.cf_nogames, tmp[1]);
X			}
X			else if (strncmp(tmp[0], "logfile", 7) == 0) {
X				if(tmp[1][0] == NULL) {
X					fatal("Keyword \"logfile\" set, but not defined.");
X					/*NOTREACHED*/
X				}
X				(void) strcpy(cf.cf_logfile, tmp[1]);
X			}
X			continue;
X		} else if (!foundname) {
X			if ((strcmp(tmp[0], game) == 0)||(strcmp(tmp[0],"default") == 0)){
X#ifdef DEBUG
X				dprintf("parse: found game name\n");
X#endif DEBUG
X				foundname = TRUE;
X				(void) sscanf(lbuf, "%s%lf%d%d", 
X					cf.cf_game, &cf.cf_load, &cf.cf_users, &cf.cf_priority);
X			} 
X#ifdef DEBUG
X			else dprintf("word = '%s'\n");
X#endif DEBUG
X		}
X	}
X#ifdef DEBUG
X	dprintf("\nCF: game = '%s' load = %.2f users = %d prio = %d\n", 
X		cf.cf_game, cf.cf_load, cf.cf_users, cf.cf_priority);
X	dprintf("cf_badttys = '%s' cf_free = '%s' \ncf_nofree = %d\n\n",
X		cf.cf_badttys, cf.cf_freettys, cf.cf_nofreettys);
X	dprintf("cf_hidedir = '%s' cf_nogames = '%s'\ncf_logfile = '%s'\n",
X		cf.cf_hidedir, cf.cf_nogames, cf.cf_logfile);
X	dprintf("cf_spname = '%s'\n", cf.cf_spname);
X	dprintf("debug is %d\n", debug);
X#endif DEBUG
X	return(&cf);
X}
END_OF_parse.c
if test 3910 -ne `wc -c <parse.c`; then
    echo shar: \"parse.c\" unpacked with wrong size!
fi
# end of overwriting check
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 unpacked all 1 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="