add lint
[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
b02d33b6 14static char sccsid[] = "@(#)machdep.c 5.3 (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
b02d33b6
KM
59# undef LOADAV /* use getloadavg() by default */
60
7a6f3a77
KA
61# ifdef SCOREFILE
62
7a6f3a77 63static char *Lockfile = "/tmp/.fredlock";
7a6f3a77
KA
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;
77c989a0
KM
177 if (Orig_dsusp == CTRL(Y)) {
178 Ltc.t_dsuspc = Ltc.t_suspc;
179 ioctl(1, TIOCSLTC, &Ltc);
180 }
7a6f3a77
KA
181# endif TIOCGLTC
182}
183
184/*
185 * start_score:
186 * Start the scoring sequence
187 */
188start_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 */
199symlink(sp)
200char *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 */
219too_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
b02d33b6 229# ifdef LOADAV
7a6f3a77 230 loadav(avec);
b02d33b6
KM
231# else
232 if (getloadavg(avec, sizeof(avec)/sizeof(avec[0])) < 0)
233 avec[0] = avec[1] = avec[2] = 0.0;
234# endif
7a6f3a77
KA
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 */
249author()
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 */
270checkout()
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 */
306chmsg(fmt, arg)
307char *fmt;
308int 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
329struct nlist avenrun = {
330 "_avenrun"
331};
332
333# ifndef NAMELIST
334# define NAMELIST "/vmunix"
335# endif
336
337loadav(avg)
338register 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
367struct utmp buf;
368
369ucount()
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 */
394lock_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
403over:
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 */
450unlock_sc()
451{
452# ifdef SCOREFILE
453# ifdef LOCK_EX
454 flock(Fd, LOCK_UN);
455#else
456 unlink(Lockfile);
457# endif
458# endif
459}