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