|
|
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.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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.