|
|
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.