1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: char copyright[] =
   9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)machdep.c	5.2 (Berkeley) 1/9/86";
  15: #endif not lint
  16: 
  17: /*
  18:  * Various installation dependent routines
  19:  *
  20:  * $Revision: 1.7 $, $Date: 85/04/05 11:33:30 $
  21:  */
  22: 
  23: /*
  24:  * The various tuneable defines are:
  25:  *
  26:  *	SCOREFILE	Where/if the score file should live.
  27:  *	ALLSCORES	Score file is top ten scores, not top ten
  28:  *			players.  This is only useful when only a few
  29:  *			people will be playing; otherwise the score file
  30:  *			gets hogged by just a few people.
  31:  *	NUMSCORES	Number of scores in the score file (default 10).
  32:  *	NUMNAME		String version of NUMSCORES (first character
  33:  *			should be capitalized) (default "Ten").
  34:  *	MAXLOAD		What (if any) the maximum load average should be
  35:  *			when people are playing.
  36:  *		LOADAV		Should it use it's own routine to get
  37:  *				the load average?
  38:  *		NAMELIST	If so, where does the system namelist
  39:  *				hide?
  40:  *	MAXUSERS	What (if any) the maximum user count should be
  41:  *			when people are playing.  If defined, then
  42:  *		UCOUNT		Should it use it's own routine to count
  43:  *				users?
  44:  *		UTMP		If so, where does the user list hide?
  45:  *	CHECKTIME	How often/if it should check during the game
  46:  *			for high load average.
  47:  *	WARNTIME	How much time between warnings when load gets
  48:  *			too high (if not defined, it is the same as
  49:  *			CHECKTIME).
  50:  */
  51: 
  52: # include   <curses.h>
  53: # include   "machdep.h"
  54: # include   <signal.h>
  55: # include   <sys/types.h>
  56: # include   <sys/stat.h>
  57: # include   <sys/file.h>
  58: 
  59: # ifdef SCOREFILE
  60: 
  61: static char *Lockfile = "/tmp/.fredlock";
  62: 
  63: # ifndef    NUMSCORES
  64: # 	define   NUMSCORES   10
  65: # 	define   NUMNAME     "Ten"
  66: # endif		NUMSCORES
  67: 
  68: unsigned int    Numscores = NUMSCORES;
  69: 
  70: char        *Numname = NUMNAME;
  71: 
  72: # ifdef ALLSCORES
  73: bool    Allscore = TRUE;
  74: # else  ALLSCORES
  75: bool    Allscore = FALSE;
  76: # endif ALLSCORES
  77: 
  78: # endif	SCOREFILE
  79: 
  80: # ifdef CHECKTIME
  81: static int  Num_checks; /* times we've gone over in checkout() */
  82: 
  83: # ifndef WARNTIME
  84: # define    WARNTIME    CHECKTIME
  85: # endif
  86: # endif	CHECKTIME
  87: 
  88: /*
  89:  * init_check:
  90:  *	Check out too see if it is proper to play the game now
  91:  */
  92: init_check()
  93: {
  94: # if    defined(MAXLOAD) || defined(MAXUSERS)
  95:     if (too_much()) {
  96:         printf("Sorry, %s, but the system is too loaded now.\n",
  97:                Whoami);
  98:         printf("Try again later.  Meanwhile, why not enjoy a%s %s?\n",
  99:                vowelstr(Fruit), Fruit);
 100:         if (author())
 101:             printf("However, since you're a good guy, it's up to you\n");
 102:         else
 103:             exit(1);
 104:     }
 105: # endif	defined(MAXLOAD) || defined(MAXUSERS)
 106: }
 107: 
 108: /*
 109:  * open_score:
 110:  *	Open up the score file for future use, and then
 111:  *	setuid(getuid()) in case we are running setuid.
 112:  */
 113: open_score()
 114: {
 115: # ifdef SCOREFILE
 116:     Fd = open(SCOREFILE, 2);
 117: # else  SCOREFILE
 118:     Fd = -1;
 119: # endif	SCOREFILE
 120:     setuid(getuid());
 121:     setgid(getgid());
 122: }
 123: 
 124: /*
 125:  * setup:
 126:  *	Get starting setup for all games
 127:  */
 128: setup()
 129: {
 130:     extern int  auto_save(), quit(), endit(), tstp();
 131: # ifdef CHECKTIME
 132:     extern int  heckout();
 133: # endif	CHECKTIME
 134: 
 135:     signal(SIGHUP, auto_save);
 136: # ifndef DUMP
 137:     signal(SIGILL, auto_save);
 138:     signal(SIGTRAP, auto_save);
 139:     signal(SIGIOT, auto_save);
 140:     signal(SIGEMT, auto_save);
 141:     signal(SIGFPE, auto_save);
 142:     signal(SIGBUS, auto_save);
 143:     signal(SIGSEGV, auto_save);
 144:     signal(SIGSYS, auto_save);
 145:     signal(SIGTERM, auto_save);
 146: # endif	DUMP
 147: 
 148:     signal(SIGINT, quit);
 149: # ifndef DUMP
 150:     signal(SIGQUIT, endit);
 151: # endif	DUMP
 152: # ifdef CHECKTIME
 153:     signal(SIGALRM, checkout);
 154:     alarm(CHECKTIME * 60);
 155:     Num_checks = 0;
 156: # endif	CHECKTIME
 157:     crmode();               /* Cbreak mode */
 158:     noecho();               /* Echo off */
 159:     nonl();
 160: # ifdef TIOCGLTC
 161:     getltchars();           /* get the local tty chars */
 162: # endif	TIOCGLTC
 163: }
 164: 
 165: /*
 166:  * getltchars:
 167:  *	Get the local tty chars for later use
 168:  */
 169: getltchars()
 170: {
 171: # ifdef TIOCGLTC
 172:     ioctl(1, TIOCGLTC, &Ltc);
 173:     Got_ltc = TRUE;
 174:     Orig_dsusp = Ltc.t_dsuspc;
 175:     if (Orig_dsusp == CTRL(Y)) {
 176:         Ltc.t_dsuspc = Ltc.t_suspc;
 177:         ioctl(1, TIOCSLTC, &Ltc);
 178:     }
 179: # endif	TIOCGLTC
 180: }
 181: 
 182: /*
 183:  * start_score:
 184:  *	Start the scoring sequence
 185:  */
 186: start_score()
 187: {
 188: # ifdef CHECKTIME
 189:     signal(SIGALRM, SIG_IGN);   /* NOSTRICT */
 190: # endif	CHECKTIME
 191: }
 192: 
 193: /*
 194:  * symlink:
 195:  *	See if the file has a symbolic link
 196:  */
 197: symlink(sp)
 198: char    *sp;
 199: {
 200: # ifdef S_IFLNK
 201:     struct stat sbuf2;
 202: 
 203:     if (lstat(sp, &sbuf2) < 0)
 204:         return FALSE;
 205:     else
 206:         return ((sbuf2.st_mode & S_IFMT) != S_IFREG);
 207: # else  S_IFLNK
 208:     return FALSE;
 209: # endif	S_IFLNK
 210: }
 211: 
 212: # if    defined(MAXLOAD) || defined(MAXUSERS)
 213: /*
 214:  * too_much:
 215:  *	See if the system is being used too much for this game
 216:  */
 217: too_much()
 218: {
 219: # ifdef MAXLOAD
 220:     double      avec[3];
 221: # endif	MAXLOAD
 222: # ifdef MAXUSERS
 223:     register int    cnt;
 224: # endif	MAXUSERS
 225: 
 226: # ifdef MAXLOAD
 227:     loadav(avec);
 228:     if (avec[1] > MAXLOAD)
 229:         return TRUE;
 230: # endif	MAXLOAD
 231: # ifdef MAXUSERS
 232:     if (ucount() > MAXUSERS)
 233:         return TRUE;
 234: # endif	MAXUSERS
 235:     return FALSE;
 236: }
 237: 
 238: /*
 239:  * author:
 240:  *	See if a user is an author of the program
 241:  */
 242: author()
 243: {
 244: # ifdef MASTER
 245:     if (Wizard)
 246:         return TRUE;
 247: # endif	MASTER
 248:     switch (getuid())
 249:     {
 250:       case -1:
 251:         return TRUE;
 252:       default:
 253:         return FALSE;
 254:     }
 255: }
 256: # endif	defined(MAXLOAD) || defined(MAXUSERS)
 257: 
 258: # ifdef CHECKTIME
 259: /*
 260:  * checkout:
 261:  *	Check each CHECKTIME seconds to see if the load is too high
 262:  */
 263: checkout()
 264: {
 265:     int     checktime;
 266:     static char *msgs[] = {
 267:         "The load is too high to be playing.  Please leave in %.2f minutes",
 268:         "Please save your game.  You have %.2f minutes",
 269:         "Last warning.  You have %.2f minutes to leave",
 270:     };
 271: 
 272:     signal(SIGALRM, checkout);
 273:     if (too_much()) {
 274:         if (author()) {
 275:             Num_checks = 1;
 276:             chmsg("The load is rather high, O exaulted one");
 277:         }
 278:         else if (Num_checks++ == 3)
 279:             fatal("Sorry.  You took too long.  You are dead\n");
 280:         checktime = (WARNTIME * 60) / Num_checks;
 281:         alarm(checktime);
 282:         chmsg(msgs[Num_checks - 1], ((double) checktime / 60.0));
 283:     }
 284:     else {
 285:         if (Num_checks) {
 286:             Num_checks = 0;
 287:             chmsg("The load has dropped back down.  You have a reprieve");
 288:         }
 289:         alarm(CHECKTIME * 60);
 290:     }
 291: }
 292: 
 293: /*
 294:  * chmsg:
 295:  *	checkout()'s version of msg.  If we are in the middle of a
 296:  *	shell, do a printf instead of a msg to avoid the refresh.
 297:  */
 298: /* VARARGS1 */
 299: chmsg(fmt, arg)
 300: char    *fmt;
 301: int arg;
 302: {
 303:     if (!In_shell)
 304:         msg(fmt, arg);
 305:     else {
 306:         printf(fmt, arg);
 307:         putchar('\n');
 308:         fflush(stdout);
 309:     }
 310: }
 311: # endif	defined(MAXLOAD) || defined(MAXUSERS)
 312: 
 313: # ifdef LOADAV
 314: /*
 315:  * loadav:
 316:  *	Looking up load average in core (for system where the loadav()
 317:  *	system call isn't defined
 318:  */
 319: 
 320: # include   <nlist.h>
 321: 
 322: struct nlist    avenrun = {
 323:         "_avenrun"
 324: };
 325: 
 326: # ifndef    NAMELIST
 327: # define    NAMELIST    "/vmunix"
 328: # endif
 329: 
 330: loadav(avg)
 331: register double *avg;
 332: {
 333:     register int    kmem;
 334: 
 335:     if ((kmem = open("/dev/kmem", 0)) < 0)
 336:         goto bad;
 337:     nlist(NAMELIST, &avenrun);
 338:     if (avenrun.n_type == 0) {
 339:         close(kmem);
 340:         bad:
 341:         avg[0] = 0.0;
 342:         avg[1] = 0.0;
 343:         avg[2] = 0.0;
 344:         return;
 345:     }
 346: 
 347:     lseek(kmem, (long) avenrun.n_value, 0);
 348:     read(kmem, (char *) avg, 3 * sizeof (double));
 349:     close(kmem);
 350: }
 351: # endif	LOADAV
 352: 
 353: # ifdef UCOUNT
 354: /*
 355:  * ucount:
 356:  *	Count number of users on the system
 357:  */
 358: # include   <utmp.h>
 359: 
 360: struct utmp buf;
 361: 
 362: ucount()
 363: {
 364:     register struct utmp    *up;
 365:     register FILE       *utmp;
 366:     register int        count;
 367: 
 368:     if ((utmp = fopen(UTMP, "r")) == NULL)
 369:         return 0;
 370: 
 371:     up = &buf;
 372:     count = 0;
 373: 
 374:     while (fread(up, 1, sizeof (*up), utmp) > 0)
 375:         if (buf.ut_name[0] != '\0')
 376:             count++;
 377:     fclose(utmp);
 378:     return count;
 379: }
 380: # endif	UCOUNT
 381: 
 382: /*
 383:  * lock_sc:
 384:  *	lock the score file.  If it takes too long, ask the user if
 385:  *	they care to wait.  Return TRUE if the lock is successful.
 386:  */
 387: lock_sc()
 388: {
 389: # ifdef SCOREFILE
 390: # ifdef LOCK_EX
 391:     return (flock(Fd, LOCK_EX) >= 0);
 392: # else  LOCK_EX
 393:     register int        cnt;
 394:     static struct stat  sbuf;
 395: 
 396: over:
 397:     close(8);   /* just in case there are no files left */
 398:     if (creat(Lockfile, 0000) >= 0)
 399:         return TRUE;
 400:     for (cnt = 0; cnt < 5; cnt++) {
 401:         sleep(1);
 402:         if (creat(Lockfile, 0000) >= 0)
 403:             return TRUE;
 404:     }
 405:     if (stat(Lockfile, &sbuf) < 0) {
 406:         creat(Lockfile, 0000);
 407:         return TRUE;
 408:     }
 409:     if (time(NULL) - sbuf.st_mtime > 10) {
 410:         if (unlink(Lockfile) < 0)
 411:             return FALSE;
 412:         goto over;
 413:     }
 414:     else {
 415:         printf("The score file is very busy.  Do you want to wait longer\n");
 416:         printf("for it to become free so your score can get posted?\n");
 417:         printf("If so, type \"y\"\n");
 418:         fgets(Prbuf, MAXSTR, stdin);
 419:         if (Prbuf[0] == 'y')
 420:             for (;;) {
 421:                 if (creat(Lockfile, 0000) >= 0)
 422:                     return TRUE;
 423:                 if (stat(Lockfile, &sbuf) < 0) {
 424:                     creat(Lockfile, 0000);
 425:                     return TRUE;
 426:                 }
 427:                 if (time(NULL) - sbuf.st_mtime > 10)
 428:                     if (unlink(Lockfile) < 0)
 429:                         return FALSE;
 430:                 sleep(1);
 431:             }
 432:         else
 433:             return FALSE;
 434:     }
 435: # endif	LOCK_EX
 436: # endif	SCOREFILE
 437: }
 438: 
 439: /*
 440:  * unlock_sc:
 441:  *	Unlock the score file
 442:  */
 443: unlock_sc()
 444: {
 445: # ifdef SCOREFILE
 446: # ifdef LOCK_EX
 447:     flock(Fd, LOCK_UN);
 448: #else
 449:     unlink(Lockfile);
 450: # endif
 451: # endif
 452: }

Defined functions

author defined in line 242; used 2 times
checkout defined in line 263; used 3 times
chmsg defined in line 299; used 3 times
getltchars defined in line 169; used 1 times
init_check defined in line 92; never used
loadav defined in line 330; used 1 times
lock_sc defined in line 387; never used
open_score defined in line 113; never used
setup defined in line 128; never used
start_score defined in line 186; never used
symlink defined in line 197; never used
too_much defined in line 217; used 2 times
ucount defined in line 362; used 1 times
unlock_sc defined in line 443; never used

Defined variables

Lockfile defined in line 61; used 10 times
Num_checks defined in line 81; used 7 times
Numname defined in line 70; never used
Numscores defined in line 68; never used
avenrun defined in line 322; used 3 times
buf defined in line 360; used 2 times
copyright defined in line 8; never used
sccsid defined in line 14; never used

Defined macros

NAMELIST defined in line 327; used 2 times
NUMNAME defined in line 65; used 1 times
  • in line 70
NUMSCORES defined in line 64; used 2 times
WARNTIME defined in line 84; used 2 times
Last modified: 1986-01-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1592
Valid CSS Valid XHTML 1.0 Strict