Annotation of early-roguelike/rogue5/mach_dep.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * Various installation dependent routines
! 3: *
! 4: * @(#)mach_dep.c 4.37 (Berkeley) 05/23/83
! 5: *
! 6: * Rogue: Exploring the Dungeons of Doom
! 7: * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
! 8: * All rights reserved.
! 9: *
! 10: * See the file LICENSE.TXT for full copyright and licensing information.
! 11: */
! 12:
! 13: /*
! 14: * The various tuneable defines are:
! 15: *
! 16: * SCOREFILE Where/if the score file should live.
! 17: * ALLSCORES Score file is top ten scores, not top ten
! 18: * players. This is only useful when only a few
! 19: * people will be playing; otherwise the score file
! 20: * gets hogged by just a few people.
! 21: * NUMSCORES Number of scores in the score file (default 10).
! 22: * NUMNAME String version of NUMSCORES (first character
! 23: * should be capitalized) (default "Ten").
! 24: * MAXLOAD What (if any) the maximum load average should be
! 25: * when people are playing. Since it is divided
! 26: * by 10, to specify a load limit of 4.0, MAXLOAD
! 27: * should be "40". If defined, then
! 28: * LOADAV Should it use it's own routine to get
! 29: * the load average?
! 30: * NAMELIST If so, where does the system namelist
! 31: * hide?
! 32: * MAXUSERS What (if any) the maximum user count should be
! 33: * when people are playing. If defined, then
! 34: * UCOUNT Should it use it's own routine to count
! 35: * users?
! 36: * UTMP If so, where does the user list hide?
! 37: * CHECKTIME How often/if it should check during the game
! 38: * for high load average.
! 39: */
! 40:
! 41: #include <signal.h>
! 42: #include <sys/types.h>
! 43: #include <sys/stat.h>
! 44: #include <limits.h>
! 45: #include <string.h>
! 46: #include <fcntl.h>
! 47: #include <errno.h>
! 48: #include <time.h>
! 49: #include <curses.h>
! 50: #include "extern.h"
! 51:
! 52: #define NOOP(x) (x += 0)
! 53:
! 54: # ifndef NUMSCORES
! 55: # define NUMSCORES 10
! 56: # define NUMNAME "Ten"
! 57: # endif
! 58:
! 59: #ifdef CHECKTIME
! 60: static int num_checks = 0; /* times we've gone over in checkout() */
! 61: #endif /* CHECKTIME */
! 62:
! 63: /*
! 64: * init_check:
! 65: * Check out too see if it is proper to play the game now
! 66: */
! 67:
! 68: void
! 69: init_check(void)
! 70: {
! 71: #if defined(MAXLOAD) || defined(MAXUSERS)
! 72: if (too_much())
! 73: {
! 74: printf("Sorry, %s, but the system is too loaded now.\n", whoami);
! 75: printf("Try again later. Meanwhile, why not enjoy a%s %s?\n",
! 76: vowelstr(fruit), fruit);
! 77: if (author())
! 78: printf("However, since you're a good guy, it's up to you\n");
! 79: else
! 80: exit(1);
! 81: }
! 82: #endif
! 83: }
! 84:
! 85: /*
! 86: * open_score:
! 87: * Open up the score file for future use
! 88: */
! 89:
! 90: void
! 91: open_score(void)
! 92: {
! 93: #ifdef SCOREFILE
! 94: char *scorefile = SCOREFILE;
! 95:
! 96: numscores = NUMSCORES;
! 97: Numname = NUMNAME;
! 98:
! 99: #ifdef ALLSCORES
! 100: allscore = TRUE;
! 101: #else /* ALLSCORES */
! 102: allscore = FALSE;
! 103: #endif /* ALLSCORES */
! 104:
! 105: /*
! 106: * We drop setgid privileges after opening the score file, so subsequent
! 107: * open()'s will fail. Just reuse the earlier filehandle.
! 108: */
! 109:
! 110: if (scoreboard != NULL) {
! 111: rewind(scoreboard);
! 112: return;
! 113: }
! 114:
! 115: scoreboard = fopen(scorefile, "r+");
! 116:
! 117: if ((scoreboard == NULL) && (errno == ENOENT))
! 118: {
! 119: scoreboard = fopen(scorefile, "w+");
! 120: md_chmod(scorefile,0664);
! 121: }
! 122:
! 123: if (scoreboard == NULL) {
! 124: fprintf(stderr, "Could not open %s for writing: %s\n", scorefile, strerror(errno));
! 125: fflush(stderr);
! 126: }
! 127: #else
! 128: scoreboard = NULL;
! 129: #endif
! 130: }
! 131:
! 132: void
! 133: open_log(void)
! 134: {
! 135: #ifdef LOGFILE
! 136: logfi = fopen(LOGFILE, "a");
! 137: if (logfi == NULL)
! 138: {
! 139: fprintf(stderr, "Could not open %s for appending: %s\n", LOGFILE,
! 140: strerror(errno));
! 141: fflush(stderr);
! 142: }
! 143: #endif
! 144: return;
! 145: }
! 146:
! 147: /*
! 148: * getltchars:
! 149: * Get the local tty chars for later use
! 150: */
! 151:
! 152: void
! 153: getltchars(void)
! 154: {
! 155: got_ltc = TRUE;
! 156: orig_dsusp = md_dsuspchar();
! 157: md_setdsuspchar( md_suspchar() );
! 158: }
! 159:
! 160: /*
! 161: * setup:
! 162: * Get starting setup for all games
! 163: */
! 164:
! 165: void
! 166: setup(void)
! 167: {
! 168: #ifndef DUMP
! 169: md_onsignal_autosave();
! 170: #else
! 171: md_onsignal_default();
! 172: #endif
! 173:
! 174: #ifdef CHECKTIME
! 175: md_start_checkout_timer(CHECKTIME*60);
! 176: num_checks = 0;
! 177: #endif
! 178:
! 179: raw(); /* Raw mode */
! 180: noecho(); /* Echo off */
! 181: nonl();
! 182: keypad(stdscr,1);
! 183: getltchars(); /* get the local tty chars */
! 184: }
! 185:
! 186: /*
! 187: * resetltchars:
! 188: * Reset the local tty chars to original values.
! 189: */
! 190: void
! 191: resetltchars(void)
! 192: {
! 193: if (got_ltc) {
! 194: md_setdsuspchar(orig_dsusp);
! 195: }
! 196: }
! 197:
! 198: /*
! 199: * playltchars:
! 200: * Set local tty chars to the values we use when playing.
! 201: */
! 202: void
! 203: playltchars(void)
! 204: {
! 205: if (got_ltc) {
! 206: md_setdsuspchar( md_suspchar() );
! 207: }
! 208: }
! 209:
! 210: /*
! 211: * start_score:
! 212: * Start the scoring sequence
! 213: */
! 214:
! 215: void
! 216: start_score(void)
! 217: {
! 218: #ifdef CHECKTIME
! 219: md_stop_checkout_timer();
! 220: #endif
! 221: }
! 222:
! 223: /*
! 224: * is_symlink:
! 225: * See if the file has a symbolic link
! 226: */
! 227: int
! 228: is_symlink(char *sp)
! 229: {
! 230: #ifdef S_IFLNK
! 231: struct stat sbuf2;
! 232:
! 233: if (lstat(sp, &sbuf2) < 0)
! 234: return FALSE;
! 235: else
! 236: return ((sbuf2.st_mode & S_IFMT) != S_IFREG);
! 237: #else
! 238: NOOP(sp);
! 239: return FALSE;
! 240: #endif
! 241: }
! 242:
! 243: #if defined(MAXLOAD) || defined(MAXUSERS)
! 244: /*
! 245: * too_much:
! 246: * See if the system is being used too much for this game
! 247: */
! 248: int
! 249: too_much(void)
! 250: {
! 251: #ifdef MAXLOAD
! 252: double avec[3];
! 253: #else
! 254: int cnt;
! 255: #endif
! 256:
! 257: #ifdef MAXLOAD
! 258: md_loadav(avec);
! 259: if (avec[1] > (MAXLOAD / 10.0))
! 260: return TRUE;
! 261: #endif
! 262: #ifdef MAXUSERS
! 263: if (ucount() > MAXUSERS)
! 264: return TRUE;
! 265: #endif
! 266: return FALSE;
! 267: }
! 268:
! 269: /*
! 270: * author:
! 271: * See if a user is an author of the program
! 272: */
! 273: int
! 274: author(void)
! 275: {
! 276: #ifdef MASTER
! 277: if (wizard)
! 278: return TRUE;
! 279: #endif
! 280: switch (md_getuid())
! 281: {
! 282: case -1:
! 283: return TRUE;
! 284: default:
! 285: return FALSE;
! 286: }
! 287: }
! 288: #endif
! 289:
! 290: #ifdef CHECKTIME
! 291: /*
! 292: * checkout:
! 293: * Check each CHECKTIME seconds to see if the load is too high
! 294: */
! 295:
! 296: checkout(int sig)
! 297: {
! 298: char *msgs[] = {
! 299: "The load is too high to be playing. Please leave in %0.1f minutes",
! 300: "Please save your game. You have %0.1f minutes",
! 301: "Last warning. You have %0.1f minutes to leave",
! 302: };
! 303: int checktime;
! 304:
! 305: if (too_much())
! 306: {
! 307: if (author())
! 308: {
! 309: num_checks = 1;
! 310: chmsg("The load is rather high, O exaulted one");
! 311: }
! 312: else if (num_checks++ == 3)
! 313: fatal("Sorry. You took too long. You are dead\n");
! 314: checktime = (CHECKTIME * 60) / num_checks;
! 315: chmsg(msgs[num_checks - 1], ((double) checktime / 60.0));
! 316: }
! 317: else
! 318: {
! 319: if (num_checks)
! 320: {
! 321: num_checks = 0;
! 322: chmsg("The load has dropped back down. You have a reprieve");
! 323: }
! 324: checktime = (CHECKTIME * 60);
! 325: }
! 326:
! 327: md_start_checkout_timer(checktime);
! 328: }
! 329:
! 330: /*
! 331: * chmsg:
! 332: * checkout()'s version of msg. If we are in the middle of a
! 333: * shell, do a printf instead of a msg to a the refresh.
! 334: */
! 335: /* VARARGS1 */
! 336:
! 337: chmsg(char *fmt, int arg)
! 338: {
! 339: if (!in_shell)
! 340: msg(fmt, arg);
! 341: else
! 342: {
! 343: printf(fmt, arg);
! 344: putchar('\n');
! 345: fflush(stdout);
! 346: }
! 347: }
! 348: #endif
! 349:
! 350: #ifdef UCOUNT
! 351: /*
! 352: * ucount:
! 353: * count number of users on the system
! 354: */
! 355: #include <utmp.h>
! 356:
! 357: struct utmp buf;
! 358:
! 359: int
! 360: ucount(void)
! 361: {
! 362: struct utmp *up;
! 363: FILE *utmp;
! 364: int count;
! 365:
! 366: if ((utmp = fopen(UTMP, "r")) == NULL)
! 367: return 0;
! 368:
! 369: up = &buf;
! 370: count = 0;
! 371:
! 372: while (fread(up, 1, sizeof (*up), utmp) > 0)
! 373: if (buf.ut_name[0] != '\0')
! 374: count++;
! 375: fclose(utmp);
! 376: return count;
! 377: }
! 378: #endif
! 379:
! 380: /*
! 381: * lock_sc:
! 382: * lock the score file. If it takes too long, ask the user if
! 383: * they care to wait. Return TRUE if the lock is successful.
! 384: */
! 385: static FILE *lfd = NULL;
! 386: int
! 387: lock_sc(void)
! 388: {
! 389: #if defined(SCOREFILE) && defined(LOCKFILE)
! 390: int cnt;
! 391: struct stat sbuf;
! 392: char *lockfile = LOCKFILE;
! 393:
! 394: over:
! 395: if ((lfd=fopen(lockfile, "w+")) != NULL)
! 396: return TRUE;
! 397: for (cnt = 0; cnt < 5; cnt++)
! 398: {
! 399: md_sleep(1);
! 400: if ((lfd=fopen(lockfile, "w+")) != NULL)
! 401: return TRUE;
! 402: }
! 403: if (stat(lockfile, &sbuf) < 0)
! 404: {
! 405: lfd=fopen(lockfile, "w+");
! 406: return TRUE;
! 407: }
! 408: if (time(NULL) - sbuf.st_mtime > 10)
! 409: {
! 410: if (md_unlink(lockfile) < 0)
! 411: return FALSE;
! 412: goto over;
! 413: }
! 414: else
! 415: {
! 416: printf("The score file is very busy. Do you want to wait longer\n");
! 417: printf("for it to become free so your score can get posted?\n");
! 418: printf("If so, type \"y\"\n");
! 419: (void) fgets(prbuf, MAXSTR, stdin);
! 420: if (prbuf[0] == 'y')
! 421: for (;;)
! 422: {
! 423: if ((lfd=fopen(lockfile, "w+")) != 0)
! 424: return TRUE;
! 425: if (stat(lockfile, &sbuf) < 0)
! 426: {
! 427: lfd=fopen(lockfile, "w+");
! 428: return TRUE;
! 429: }
! 430: if (time(NULL) - sbuf.st_mtime > 10)
! 431: {
! 432: if (md_unlink(lockfile) < 0)
! 433: return FALSE;
! 434: }
! 435: md_sleep(1);
! 436: }
! 437: else
! 438: return FALSE;
! 439: }
! 440: #else
! 441: return TRUE;
! 442: #endif
! 443: }
! 444:
! 445: /*
! 446: * unlock_sc:
! 447: * Unlock the score file
! 448: */
! 449:
! 450: void
! 451: unlock_sc(void)
! 452: {
! 453: #if defined(SCOREFILE) && defined(LOCKFILE)
! 454: if (lfd != NULL)
! 455: fclose(lfd);
! 456: lfd = NULL;
! 457: md_unlink(LOCKFILE);
! 458: #endif
! 459: }
! 460:
! 461: /*
! 462: * flush_type:
! 463: * Flush typeahead for traps, etc.
! 464: */
! 465:
! 466: void
! 467: flush_type(void)
! 468: {
! 469: flushinp();
! 470: }
CVSweb