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