don't need "make rall" (make install does it twice)
[unix-history] / usr / src / old / rogue / machdep.c
CommitLineData
e3325aaf
KM
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
8char 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
77c989a0 14static char sccsid[] = "@(#)machdep.c 5.2 (Berkeley) %G%";
e3325aaf
KM
15#endif not lint
16
7a6f3a77
KA
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>
77c989a0 53# include "machdep.h"
7a6f3a77
KA
54# include <signal.h>
55# include <sys/types.h>
56# include <sys/stat.h>
57# include <sys/file.h>
58
59# ifdef SCOREFILE
60
7a6f3a77 61static char *Lockfile = "/tmp/.fredlock";
7a6f3a77
KA
62
63# ifndef NUMSCORES
64# define NUMSCORES 10
65# define NUMNAME "Ten"
66# endif NUMSCORES
67
68unsigned int Numscores = NUMSCORES;
69
70char *Numname = NUMNAME;
71
72# ifdef ALLSCORES
73bool Allscore = TRUE;
74# else ALLSCORES
75bool Allscore = FALSE;
76# endif ALLSCORES
77
78# endif SCOREFILE
79
80# ifdef CHECKTIME
81static 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 */
92init_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 */
113open_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 */
128setup()
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 */
169getltchars()
170{
171# ifdef TIOCGLTC
172 ioctl(1, TIOCGLTC, &Ltc);
173 Got_ltc = TRUE;
174 Orig_dsusp = Ltc.t_dsuspc;
77c989a0
KM
175 if (Orig_dsusp == CTRL(Y)) {
176 Ltc.t_dsuspc = Ltc.t_suspc;
177 ioctl(1, TIOCSLTC, &Ltc);
178 }
7a6f3a77
KA
179# endif TIOCGLTC
180}
181
182/*
183 * start_score:
184 * Start the scoring sequence
185 */
186start_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 */
197symlink(sp)
198char *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 */
217too_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 */
242author()
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 */
263checkout()
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 */
299chmsg(fmt, arg)
300char *fmt;
301int 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
322struct nlist avenrun = {
323 "_avenrun"
324};
325
326# ifndef NAMELIST
327# define NAMELIST "/vmunix"
328# endif
329
330loadav(avg)
331register 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
360struct utmp buf;
361
362ucount()
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 */
387lock_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
396over:
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 */
443unlock_sc()
444{
445# ifdef SCOREFILE
446# ifdef LOCK_EX
447 flock(Fd, LOCK_UN);
448#else
449 unlink(Lockfile);
450# endif
451# endif
452}