Mercurial > hg > early-roguelike
diff rogue5/mach_dep.c @ 33:f502bf60e6e4
Import Rogue 5.4 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Mon, 24 May 2010 20:10:59 +0000 |
parents | |
children | 655c317b6237 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue5/mach_dep.c Mon May 24 20:10:59 2010 +0000 @@ -0,0 +1,454 @@ +/* + * Various installation dependent routines + * + * @(#)mach_dep.c 4.37 (Berkeley) 05/23/83 + * + * Rogue: Exploring the Dungeons of Doom + * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman + * All rights reserved. + * + * See the file LICENSE.TXT for full copyright and licensing information. + */ + +/* + * The various tuneable defines are: + * + * SCOREFILE Where/if the score file should live. + * ALLSCORES Score file is top ten scores, not top ten + * players. This is only useful when only a few + * people will be playing; otherwise the score file + * gets hogged by just a few people. + * NUMSCORES Number of scores in the score file (default 10). + * NUMNAME String version of NUMSCORES (first character + * should be capitalized) (default "Ten"). + * MAXLOAD What (if any) the maximum load average should be + * when people are playing. Since it is divided + * by 10, to specify a load limit of 4.0, MAXLOAD + * should be "40". If defined, then + * LOADAV Should it use it's own routine to get + * the load average? + * NAMELIST If so, where does the system namelist + * hide? + * MAXUSERS What (if any) the maximum user count should be + * when people are playing. If defined, then + * UCOUNT Should it use it's own routine to count + * users? + * UTMP If so, where does the user list hide? + * CHECKTIME How often/if it should check during the game + * for high load average. + */ + +#include <signal.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <limits.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <time.h> +#include <curses.h> +#include "extern.h" + +#define NOOP(x) (x += 0) + +# ifndef NUMSCORES +# define NUMSCORES 10 +# define NUMNAME "Ten" +# endif + +#ifdef CHECKTIME +static int num_checks = 0; /* times we've gone over in checkout() */ +#endif /* CHECKTIME */ + +/* + * init_check: + * Check out too see if it is proper to play the game now + */ + +void +init_check(void) +{ +#if defined(MAXLOAD) || defined(MAXUSERS) + if (too_much()) + { + printf("Sorry, %s, but the system is too loaded now.\n", whoami); + printf("Try again later. Meanwhile, why not enjoy a%s %s?\n", + vowelstr(fruit), fruit); + if (author()) + printf("However, since you're a good guy, it's up to you\n"); + else + exit(1); + } +#endif +} + +/* + * open_score: + * Open up the score file for future use + */ + +void +open_score(void) +{ +#ifdef SCOREFILE + char *scorefile = SCOREFILE; + + numscores = NUMSCORES; + Numname = NUMNAME; + +#ifdef ALLSCORES + allscore = TRUE; +#else /* ALLSCORES */ + allscore = FALSE; +#endif /* ALLSCORES */ + + /* + * We drop setgid privileges after opening the score file, so subsequent + * open()'s will fail. Just reuse the earlier filehandle. + */ + + if (scoreboard != NULL) { + rewind(scoreboard); + return; + } + + scoreboard = fopen(scorefile, "r+"); + + if ((scoreboard == NULL) && (errno == ENOENT)) + { + scoreboard = fopen(scorefile, "w+"); + md_chmod(scorefile,0664); + } + + if (scoreboard == NULL) { + fprintf(stderr, "Could not open %s for writing: %s\n", scorefile, strerror(errno)); + fflush(stderr); + } +#else + scoreboard = NULL; +#endif +} + +/* + * getltchars: + * Get the local tty chars for later use + */ + +void +getltchars(void) +{ + got_ltc = TRUE; + orig_dsusp = md_dsuspchar(); + md_setdsuspchar( md_suspchar() ); +} + +/* + * setup: + * Get starting setup for all games + */ + +void +setup(void) +{ +#ifdef DUMP + md_onsignal_autosave(); +#else + md_onsignal_default(); +#endif + +#ifdef CHECKTIME + md_start_checkout_timer(CHECKTIME*60); + num_checks = 0; +#endif + + raw(); /* Raw mode */ + noecho(); /* Echo off */ + keypad(stdscr,1); + getltchars(); /* get the local tty chars */ +} + +/* + * resetltchars: + * Reset the local tty chars to original values. + */ +void +resetltchars(void) +{ + if (got_ltc) { + md_setdsuspchar(orig_dsusp); + } +} + +/* + * playltchars: + * Set local tty chars to the values we use when playing. + */ +void +playltchars(void) +{ + if (got_ltc) { + md_setdsuspchar( md_suspchar() ); + } +} + +/* + * start_score: + * Start the scoring sequence + */ + +void +start_score(void) +{ +#ifdef CHECKTIME + md_stop_checkout_timer(); +#endif +} + +/* + * is_symlink: + * See if the file has a symbolic link + */ +int +is_symlink(char *sp) +{ +#ifdef S_IFLNK + struct stat sbuf2; + + if (lstat(sp, &sbuf2) < 0) + return FALSE; + else + return ((sbuf2.st_mode & S_IFMT) != S_IFREG); +#else + NOOP(sp); + return FALSE; +#endif +} + +#if defined(MAXLOAD) || defined(MAXUSERS) +/* + * too_much: + * See if the system is being used too much for this game + */ +int +too_much(void) +{ +#ifdef MAXLOAD + double avec[3]; +#else + int cnt; +#endif + +#ifdef MAXLOAD + md_loadav(avec); + if (avec[1] > (MAXLOAD / 10.0)) + return TRUE; +#endif +#ifdef MAXUSERS + if (ucount() > MAXUSERS) + return TRUE; +#endif + return FALSE; +} + +/* + * author: + * See if a user is an author of the program + */ +int +author(void) +{ +#ifdef MASTER + if (wizard) + return TRUE; +#endif + switch (md_getuid()) + { + case -1: + return TRUE; + default: + return FALSE; + } +} +#endif + +#ifdef CHECKTIME +/* + * checkout: + * Check each CHECKTIME seconds to see if the load is too high + */ + +checkout(int sig) +{ + char *msgs[] = { + "The load is too high to be playing. Please leave in %0.1f minutes", + "Please save your game. You have %0.1f minutes", + "Last warning. You have %0.1f minutes to leave", + }; + int checktime; + + if (too_much()) + { + if (author()) + { + num_checks = 1; + chmsg("The load is rather high, O exaulted one"); + } + else if (num_checks++ == 3) + fatal("Sorry. You took too long. You are dead\n"); + checktime = (CHECKTIME * 60) / num_checks; + chmsg(msgs[num_checks - 1], ((double) checktime / 60.0)); + } + else + { + if (num_checks) + { + num_checks = 0; + chmsg("The load has dropped back down. You have a reprieve"); + } + checktime = (CHECKTIME * 60); + } + + md_start_checkout_timer(checktime); +} + +/* + * chmsg: + * checkout()'s version of msg. If we are in the middle of a + * shell, do a printf instead of a msg to a the refresh. + */ +/* VARARGS1 */ + +chmsg(char *fmt, int arg) +{ + if (!in_shell) + msg(fmt, arg); + else + { + printf(fmt, arg); + putchar('\n'); + fflush(stdout); + } +} +#endif + +#ifdef UCOUNT +/* + * ucount: + * count number of users on the system + */ +#include <utmp.h> + +struct utmp buf; + +int +ucount(void) +{ + struct utmp *up; + FILE *utmp; + int count; + + if ((utmp = fopen(UTMP, "r")) == NULL) + return 0; + + up = &buf; + count = 0; + + while (fread(up, 1, sizeof (*up), utmp) > 0) + if (buf.ut_name[0] != '\0') + count++; + fclose(utmp); + return count; +} +#endif + +/* + * lock_sc: + * lock the score file. If it takes too long, ask the user if + * they care to wait. Return TRUE if the lock is successful. + */ +static FILE *lfd = NULL; +int +lock_sc(void) +{ +#if defined(SCOREFILE) && defined(LOCKFILE) + int cnt; + struct stat sbuf; + char *lockfile = LOCKFILE; + +over: + if ((lfd=fopen(lockfile, "w+")) != NULL) + return TRUE; + for (cnt = 0; cnt < 5; cnt++) + { + md_sleep(1); + if ((lfd=fopen(lockfile, "w+")) != NULL) + return TRUE; + } + if (stat(lockfile, &sbuf) < 0) + { + lfd=fopen(lockfile, "w+"); + return TRUE; + } + if (time(NULL) - sbuf.st_mtime > 10) + { + if (md_unlink(lockfile) < 0) + return FALSE; + goto over; + } + else + { + printf("The score file is very busy. Do you want to wait longer\n"); + printf("for it to become free so your score can get posted?\n"); + printf("If so, type \"y\"\n"); + (void) fgets(prbuf, MAXSTR, stdin); + if (prbuf[0] == 'y') + for (;;) + { + if ((lfd=fopen(lockfile, "w+")) != 0) + return TRUE; + if (stat(lockfile, &sbuf) < 0) + { + lfd=fopen(lockfile, "w+"); + return TRUE; + } + if (time(NULL) - sbuf.st_mtime > 10) + { + if (md_unlink(lockfile) < 0) + return FALSE; + } + md_sleep(1); + } + else + return FALSE; + } +#else + return TRUE; +#endif +} + +/* + * unlock_sc: + * Unlock the score file + */ + +void +unlock_sc(void) +{ +#if defined(SCOREFILE) && defined(LOCKFILE) + if (lfd != NULL) + fclose(lfd); + lfd = NULL; + md_unlink(LOCKFILE); +#endif +} + +/* + * flush_type: + * Flush typeahead for traps, etc. + */ + +void +flush_type(void) +{ + flushinp(); +}