118589Sarnold /* 221461Smckusick * Copyright (c) 1980 Regents of the University of California. 321461Smckusick * All rights reserved. The Berkeley software License Agreement 421461Smckusick * specifies the terms and conditions for redistribution. 521461Smckusick */ 621461Smckusick 721461Smckusick #ifndef lint 821461Smckusick char copyright[] = 921461Smckusick "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1021461Smckusick All rights reserved.\n"; 1121461Smckusick #endif not lint 1221461Smckusick 1321461Smckusick #ifndef lint 14*25786Smckusick static char sccsid[] = "@(#)machdep.c 5.2 (Berkeley) 01/09/86"; 1521461Smckusick #endif not lint 1621461Smckusick 1721461Smckusick /* 1818589Sarnold * Various installation dependent routines 1918589Sarnold * 2018589Sarnold * $Revision: 1.7 $, $Date: 85/04/05 11:33:30 $ 2118589Sarnold */ 2218589Sarnold 2318589Sarnold /* 2418589Sarnold * The various tuneable defines are: 2518589Sarnold * 2618589Sarnold * SCOREFILE Where/if the score file should live. 2718589Sarnold * ALLSCORES Score file is top ten scores, not top ten 2818589Sarnold * players. This is only useful when only a few 2918589Sarnold * people will be playing; otherwise the score file 3018589Sarnold * gets hogged by just a few people. 3118589Sarnold * NUMSCORES Number of scores in the score file (default 10). 3218589Sarnold * NUMNAME String version of NUMSCORES (first character 3318589Sarnold * should be capitalized) (default "Ten"). 3418589Sarnold * MAXLOAD What (if any) the maximum load average should be 3518589Sarnold * when people are playing. 3618589Sarnold * LOADAV Should it use it's own routine to get 3718589Sarnold * the load average? 3818589Sarnold * NAMELIST If so, where does the system namelist 3918589Sarnold * hide? 4018589Sarnold * MAXUSERS What (if any) the maximum user count should be 4118589Sarnold * when people are playing. If defined, then 4218589Sarnold * UCOUNT Should it use it's own routine to count 4318589Sarnold * users? 4418589Sarnold * UTMP If so, where does the user list hide? 4518589Sarnold * CHECKTIME How often/if it should check during the game 4618589Sarnold * for high load average. 4718589Sarnold * WARNTIME How much time between warnings when load gets 4818589Sarnold * too high (if not defined, it is the same as 4918589Sarnold * CHECKTIME). 5018589Sarnold */ 5118589Sarnold 5218589Sarnold # include <curses.h> 53*25786Smckusick # include "machdep.h" 5418589Sarnold # include <signal.h> 5518589Sarnold # include <sys/types.h> 5618589Sarnold # include <sys/stat.h> 5718589Sarnold # include <sys/file.h> 5818589Sarnold 5918589Sarnold # ifdef SCOREFILE 6018589Sarnold 6118589Sarnold static char *Lockfile = "/tmp/.fredlock"; 6218589Sarnold 6318589Sarnold # ifndef NUMSCORES 6418589Sarnold # define NUMSCORES 10 6518589Sarnold # define NUMNAME "Ten" 6618589Sarnold # endif NUMSCORES 6718589Sarnold 6818589Sarnold unsigned int Numscores = NUMSCORES; 6918589Sarnold 7018589Sarnold char *Numname = NUMNAME; 7118589Sarnold 7218589Sarnold # ifdef ALLSCORES 7318589Sarnold bool Allscore = TRUE; 7418589Sarnold # else ALLSCORES 7518589Sarnold bool Allscore = FALSE; 7618589Sarnold # endif ALLSCORES 7718589Sarnold 7818589Sarnold # endif SCOREFILE 7918589Sarnold 8018589Sarnold # ifdef CHECKTIME 8118589Sarnold static int Num_checks; /* times we've gone over in checkout() */ 8218589Sarnold 8318589Sarnold # ifndef WARNTIME 8418589Sarnold # define WARNTIME CHECKTIME 8518589Sarnold # endif 8618589Sarnold # endif CHECKTIME 8718589Sarnold 8818589Sarnold /* 8918589Sarnold * init_check: 9018589Sarnold * Check out too see if it is proper to play the game now 9118589Sarnold */ 9218589Sarnold init_check() 9318589Sarnold { 9418589Sarnold # if defined(MAXLOAD) || defined(MAXUSERS) 9518589Sarnold if (too_much()) { 9618589Sarnold printf("Sorry, %s, but the system is too loaded now.\n", 9718589Sarnold Whoami); 9818589Sarnold printf("Try again later. Meanwhile, why not enjoy a%s %s?\n", 9918589Sarnold vowelstr(Fruit), Fruit); 10018589Sarnold if (author()) 10118589Sarnold printf("However, since you're a good guy, it's up to you\n"); 10218589Sarnold else 10318589Sarnold exit(1); 10418589Sarnold } 10518589Sarnold # endif defined(MAXLOAD) || defined(MAXUSERS) 10618589Sarnold } 10718589Sarnold 10818589Sarnold /* 10918589Sarnold * open_score: 11018589Sarnold * Open up the score file for future use, and then 11118589Sarnold * setuid(getuid()) in case we are running setuid. 11218589Sarnold */ 11318589Sarnold open_score() 11418589Sarnold { 11518589Sarnold # ifdef SCOREFILE 11618589Sarnold Fd = open(SCOREFILE, 2); 11718589Sarnold # else SCOREFILE 11818589Sarnold Fd = -1; 11918589Sarnold # endif SCOREFILE 12018589Sarnold setuid(getuid()); 12118589Sarnold setgid(getgid()); 12218589Sarnold } 12318589Sarnold 12418589Sarnold /* 12518589Sarnold * setup: 12618589Sarnold * Get starting setup for all games 12718589Sarnold */ 12818589Sarnold setup() 12918589Sarnold { 13018589Sarnold extern int auto_save(), quit(), endit(), tstp(); 13118589Sarnold # ifdef CHECKTIME 13218589Sarnold extern int heckout(); 13318589Sarnold # endif CHECKTIME 13418589Sarnold 13518589Sarnold signal(SIGHUP, auto_save); 13618589Sarnold # ifndef DUMP 13718589Sarnold signal(SIGILL, auto_save); 13818589Sarnold signal(SIGTRAP, auto_save); 13918589Sarnold signal(SIGIOT, auto_save); 14018589Sarnold signal(SIGEMT, auto_save); 14118589Sarnold signal(SIGFPE, auto_save); 14218589Sarnold signal(SIGBUS, auto_save); 14318589Sarnold signal(SIGSEGV, auto_save); 14418589Sarnold signal(SIGSYS, auto_save); 14518589Sarnold signal(SIGTERM, auto_save); 14618589Sarnold # endif DUMP 14718589Sarnold 14818589Sarnold signal(SIGINT, quit); 14918589Sarnold # ifndef DUMP 15018589Sarnold signal(SIGQUIT, endit); 15118589Sarnold # endif DUMP 15218589Sarnold # ifdef CHECKTIME 15318589Sarnold signal(SIGALRM, checkout); 15418589Sarnold alarm(CHECKTIME * 60); 15518589Sarnold Num_checks = 0; 15618589Sarnold # endif CHECKTIME 15718589Sarnold crmode(); /* Cbreak mode */ 15818589Sarnold noecho(); /* Echo off */ 15918589Sarnold nonl(); 16018589Sarnold # ifdef TIOCGLTC 16118589Sarnold getltchars(); /* get the local tty chars */ 16218589Sarnold # endif TIOCGLTC 16318589Sarnold } 16418589Sarnold 16518589Sarnold /* 16618589Sarnold * getltchars: 16718589Sarnold * Get the local tty chars for later use 16818589Sarnold */ 16918589Sarnold getltchars() 17018589Sarnold { 17118589Sarnold # ifdef TIOCGLTC 17218589Sarnold ioctl(1, TIOCGLTC, &Ltc); 17318589Sarnold Got_ltc = TRUE; 17418589Sarnold Orig_dsusp = Ltc.t_dsuspc; 175*25786Smckusick if (Orig_dsusp == CTRL(Y)) { 176*25786Smckusick Ltc.t_dsuspc = Ltc.t_suspc; 177*25786Smckusick ioctl(1, TIOCSLTC, &Ltc); 178*25786Smckusick } 17918589Sarnold # endif TIOCGLTC 18018589Sarnold } 18118589Sarnold 18218589Sarnold /* 18318589Sarnold * start_score: 18418589Sarnold * Start the scoring sequence 18518589Sarnold */ 18618589Sarnold start_score() 18718589Sarnold { 18818589Sarnold # ifdef CHECKTIME 18918589Sarnold signal(SIGALRM, SIG_IGN); /* NOSTRICT */ 19018589Sarnold # endif CHECKTIME 19118589Sarnold } 19218589Sarnold 19318589Sarnold /* 19418589Sarnold * symlink: 19518589Sarnold * See if the file has a symbolic link 19618589Sarnold */ 19718589Sarnold symlink(sp) 19818589Sarnold char *sp; 19918589Sarnold { 20018589Sarnold # ifdef S_IFLNK 20118589Sarnold struct stat sbuf2; 20218589Sarnold 20318589Sarnold if (lstat(sp, &sbuf2) < 0) 20418589Sarnold return FALSE; 20518589Sarnold else 20618589Sarnold return ((sbuf2.st_mode & S_IFMT) != S_IFREG); 20718589Sarnold # else S_IFLNK 20818589Sarnold return FALSE; 20918589Sarnold # endif S_IFLNK 21018589Sarnold } 21118589Sarnold 21218589Sarnold # if defined(MAXLOAD) || defined(MAXUSERS) 21318589Sarnold /* 21418589Sarnold * too_much: 21518589Sarnold * See if the system is being used too much for this game 21618589Sarnold */ 21718589Sarnold too_much() 21818589Sarnold { 21918589Sarnold # ifdef MAXLOAD 22018589Sarnold double avec[3]; 22118589Sarnold # endif MAXLOAD 22218589Sarnold # ifdef MAXUSERS 22318589Sarnold register int cnt; 22418589Sarnold # endif MAXUSERS 22518589Sarnold 22618589Sarnold # ifdef MAXLOAD 22718589Sarnold loadav(avec); 22818589Sarnold if (avec[1] > MAXLOAD) 22918589Sarnold return TRUE; 23018589Sarnold # endif MAXLOAD 23118589Sarnold # ifdef MAXUSERS 23218589Sarnold if (ucount() > MAXUSERS) 23318589Sarnold return TRUE; 23418589Sarnold # endif MAXUSERS 23518589Sarnold return FALSE; 23618589Sarnold } 23718589Sarnold 23818589Sarnold /* 23918589Sarnold * author: 24018589Sarnold * See if a user is an author of the program 24118589Sarnold */ 24218589Sarnold author() 24318589Sarnold { 24418589Sarnold # ifdef MASTER 24518589Sarnold if (Wizard) 24618589Sarnold return TRUE; 24718589Sarnold # endif MASTER 24818589Sarnold switch (getuid()) 24918589Sarnold { 25018589Sarnold case -1: 25118589Sarnold return TRUE; 25218589Sarnold default: 25318589Sarnold return FALSE; 25418589Sarnold } 25518589Sarnold } 25618589Sarnold # endif defined(MAXLOAD) || defined(MAXUSERS) 25718589Sarnold 25818589Sarnold # ifdef CHECKTIME 25918589Sarnold /* 26018589Sarnold * checkout: 26118589Sarnold * Check each CHECKTIME seconds to see if the load is too high 26218589Sarnold */ 26318589Sarnold checkout() 26418589Sarnold { 26518589Sarnold int checktime; 26618589Sarnold static char *msgs[] = { 26718589Sarnold "The load is too high to be playing. Please leave in %.2f minutes", 26818589Sarnold "Please save your game. You have %.2f minutes", 26918589Sarnold "Last warning. You have %.2f minutes to leave", 27018589Sarnold }; 27118589Sarnold 27218589Sarnold signal(SIGALRM, checkout); 27318589Sarnold if (too_much()) { 27418589Sarnold if (author()) { 27518589Sarnold Num_checks = 1; 27618589Sarnold chmsg("The load is rather high, O exaulted one"); 27718589Sarnold } 27818589Sarnold else if (Num_checks++ == 3) 27918589Sarnold fatal("Sorry. You took too long. You are dead\n"); 28018589Sarnold checktime = (WARNTIME * 60) / Num_checks; 28118589Sarnold alarm(checktime); 28218589Sarnold chmsg(msgs[Num_checks - 1], ((double) checktime / 60.0)); 28318589Sarnold } 28418589Sarnold else { 28518589Sarnold if (Num_checks) { 28618589Sarnold Num_checks = 0; 28718589Sarnold chmsg("The load has dropped back down. You have a reprieve"); 28818589Sarnold } 28918589Sarnold alarm(CHECKTIME * 60); 29018589Sarnold } 29118589Sarnold } 29218589Sarnold 29318589Sarnold /* 29418589Sarnold * chmsg: 29518589Sarnold * checkout()'s version of msg. If we are in the middle of a 29618589Sarnold * shell, do a printf instead of a msg to avoid the refresh. 29718589Sarnold */ 29818589Sarnold /* VARARGS1 */ 29918589Sarnold chmsg(fmt, arg) 30018589Sarnold char *fmt; 30118589Sarnold int arg; 30218589Sarnold { 30318589Sarnold if (!In_shell) 30418589Sarnold msg(fmt, arg); 30518589Sarnold else { 30618589Sarnold printf(fmt, arg); 30718589Sarnold putchar('\n'); 30818589Sarnold fflush(stdout); 30918589Sarnold } 31018589Sarnold } 31118589Sarnold # endif defined(MAXLOAD) || defined(MAXUSERS) 31218589Sarnold 31318589Sarnold # ifdef LOADAV 31418589Sarnold /* 31518589Sarnold * loadav: 31618589Sarnold * Looking up load average in core (for system where the loadav() 31718589Sarnold * system call isn't defined 31818589Sarnold */ 31918589Sarnold 32018589Sarnold # include <nlist.h> 32118589Sarnold 32218589Sarnold struct nlist avenrun = { 32318589Sarnold "_avenrun" 32418589Sarnold }; 32518589Sarnold 32618589Sarnold # ifndef NAMELIST 32718589Sarnold # define NAMELIST "/vmunix" 32818589Sarnold # endif 32918589Sarnold 33018589Sarnold loadav(avg) 33118589Sarnold register double *avg; 33218589Sarnold { 33318589Sarnold register int kmem; 33418589Sarnold 33518589Sarnold if ((kmem = open("/dev/kmem", 0)) < 0) 33618589Sarnold goto bad; 33718589Sarnold nlist(NAMELIST, &avenrun); 33818589Sarnold if (avenrun.n_type == 0) { 33918589Sarnold close(kmem); 34018589Sarnold bad: 34118589Sarnold avg[0] = 0.0; 34218589Sarnold avg[1] = 0.0; 34318589Sarnold avg[2] = 0.0; 34418589Sarnold return; 34518589Sarnold } 34618589Sarnold 34718589Sarnold lseek(kmem, (long) avenrun.n_value, 0); 34818589Sarnold read(kmem, (char *) avg, 3 * sizeof (double)); 34918589Sarnold close(kmem); 35018589Sarnold } 35118589Sarnold # endif LOADAV 35218589Sarnold 35318589Sarnold # ifdef UCOUNT 35418589Sarnold /* 35518589Sarnold * ucount: 35618589Sarnold * Count number of users on the system 35718589Sarnold */ 35818589Sarnold # include <utmp.h> 35918589Sarnold 36018589Sarnold struct utmp buf; 36118589Sarnold 36218589Sarnold ucount() 36318589Sarnold { 36418589Sarnold register struct utmp *up; 36518589Sarnold register FILE *utmp; 36618589Sarnold register int count; 36718589Sarnold 36818589Sarnold if ((utmp = fopen(UTMP, "r")) == NULL) 36918589Sarnold return 0; 37018589Sarnold 37118589Sarnold up = &buf; 37218589Sarnold count = 0; 37318589Sarnold 37418589Sarnold while (fread(up, 1, sizeof (*up), utmp) > 0) 37518589Sarnold if (buf.ut_name[0] != '\0') 37618589Sarnold count++; 37718589Sarnold fclose(utmp); 37818589Sarnold return count; 37918589Sarnold } 38018589Sarnold # endif UCOUNT 38118589Sarnold 38218589Sarnold /* 38318589Sarnold * lock_sc: 38418589Sarnold * lock the score file. If it takes too long, ask the user if 38518589Sarnold * they care to wait. Return TRUE if the lock is successful. 38618589Sarnold */ 38718589Sarnold lock_sc() 38818589Sarnold { 38918589Sarnold # ifdef SCOREFILE 39018589Sarnold # ifdef LOCK_EX 39118589Sarnold return (flock(Fd, LOCK_EX) >= 0); 39218589Sarnold # else LOCK_EX 39318589Sarnold register int cnt; 39418589Sarnold static struct stat sbuf; 39518589Sarnold 39618589Sarnold over: 39718589Sarnold close(8); /* just in case there are no files left */ 39818589Sarnold if (creat(Lockfile, 0000) >= 0) 39918589Sarnold return TRUE; 40018589Sarnold for (cnt = 0; cnt < 5; cnt++) { 40118589Sarnold sleep(1); 40218589Sarnold if (creat(Lockfile, 0000) >= 0) 40318589Sarnold return TRUE; 40418589Sarnold } 40518589Sarnold if (stat(Lockfile, &sbuf) < 0) { 40618589Sarnold creat(Lockfile, 0000); 40718589Sarnold return TRUE; 40818589Sarnold } 40918589Sarnold if (time(NULL) - sbuf.st_mtime > 10) { 41018589Sarnold if (unlink(Lockfile) < 0) 41118589Sarnold return FALSE; 41218589Sarnold goto over; 41318589Sarnold } 41418589Sarnold else { 41518589Sarnold printf("The score file is very busy. Do you want to wait longer\n"); 41618589Sarnold printf("for it to become free so your score can get posted?\n"); 41718589Sarnold printf("If so, type \"y\"\n"); 41818589Sarnold fgets(Prbuf, MAXSTR, stdin); 41918589Sarnold if (Prbuf[0] == 'y') 42018589Sarnold for (;;) { 42118589Sarnold if (creat(Lockfile, 0000) >= 0) 42218589Sarnold return TRUE; 42318589Sarnold if (stat(Lockfile, &sbuf) < 0) { 42418589Sarnold creat(Lockfile, 0000); 42518589Sarnold return TRUE; 42618589Sarnold } 42718589Sarnold if (time(NULL) - sbuf.st_mtime > 10) 42818589Sarnold if (unlink(Lockfile) < 0) 42918589Sarnold return FALSE; 43018589Sarnold sleep(1); 43118589Sarnold } 43218589Sarnold else 43318589Sarnold return FALSE; 43418589Sarnold } 43518589Sarnold # endif LOCK_EX 43618589Sarnold # endif SCOREFILE 43718589Sarnold } 43818589Sarnold 43918589Sarnold /* 44018589Sarnold * unlock_sc: 44118589Sarnold * Unlock the score file 44218589Sarnold */ 44318589Sarnold unlock_sc() 44418589Sarnold { 44518589Sarnold # ifdef SCOREFILE 44618589Sarnold # ifdef LOCK_EX 44718589Sarnold flock(Fd, LOCK_UN); 44818589Sarnold #else 44918589Sarnold unlink(Lockfile); 45018589Sarnold # endif 45118589Sarnold # endif 45218589Sarnold } 453