Changed install command to reduce problems with access rights.
[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
14static char sccsid[] = "@(#)machdep.c 5.1 (Berkeley) %G%";
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>
53# include "extern.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# ifndef LOCK_EX
62static char *Lockfile = "/tmp/.fredlock";
63# endif
64
65# ifndef NUMSCORES
66# define NUMSCORES 10
67# define NUMNAME "Ten"
68# endif NUMSCORES
69
70unsigned int Numscores = NUMSCORES;
71
72char *Numname = NUMNAME;
73
74# ifdef ALLSCORES
75bool Allscore = TRUE;
76# else ALLSCORES
77bool Allscore = FALSE;
78# endif ALLSCORES
79
80# endif SCOREFILE
81
82# ifdef CHECKTIME
83static 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 */
94init_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 */
115open_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 */
130setup()
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 */
171getltchars()
172{
173# ifdef TIOCGLTC
174 ioctl(1, TIOCGLTC, &Ltc);
175 Got_ltc = TRUE;
176 Orig_dsusp = Ltc.t_dsuspc;
177 Ltc.t_dsuspc = Ltc.t_suspc;
178 ioctl(1, TIOCSLTC, &Ltc);
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}