Annotation of early-roguelike/rogue5/mach_dep.c, Revision 1.1.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