dist -> vaxdist
[unix-history] / usr / src / games / dm / dm.c
CommitLineData
fadb9605
KB
1/*
2 * Copyright (c) 1987 Regents of the University of California.
0d65e553
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific written prior permission. This software
10 * is provided ``as is'' without express or implied warranty.
fadb9605
KB
11 */
12
13#ifndef lint
14char copyright[] =
15"@(#) Copyright (c) 1987 Regents of the University of California.\n\
16 All rights reserved.\n";
0d65e553 17#endif /* not lint */
fadb9605
KB
18
19#ifndef lint
8cb55fc8 20static char sccsid[] = "@(#)dm.c 5.7 (Berkeley) %G%";
0d65e553 21#endif /* not lint */
fadb9605
KB
22
23#include <sys/param.h>
24#include <sys/file.h>
25#include <sys/time.h>
26#include <sys/resource.h>
27#include <pwd.h>
28#include <utmp.h>
29#include <nlist.h>
30#include <stdio.h>
31#include <ctype.h>
32
fadb9605 33static time_t now; /* current time value */
d671db58
KB
34static int priority = 0; /* priority game runs at */
35static char *game, /* requested game */
36 *gametty; /* from tty? */
fadb9605 37
8cb55fc8 38/*ARGSUSED*/
fadb9605 39main(argc, argv)
8cb55fc8
KB
40 int argc;
41 char **argv;
fadb9605 42{
8cb55fc8
KB
43 char *cp, *rindex(), *ttyname();
44 time_t time();
fadb9605
KB
45
46 nogamefile();
b3b5a8a7 47 game = (cp = rindex(*argv, '/')) ? ++cp : *argv;
fadb9605 48
b3b5a8a7 49 if (!strcmp(game, "dm"))
d671db58 50 exit(0);
fadb9605 51
b3b5a8a7
KB
52 gametty = ttyname(0);
53 (void)time(&now);
54 read_config();
fadb9605
KB
55#ifdef LOG
56 logfile();
57#endif
58 play(argv);
b3b5a8a7 59 /*NOTREACHED*/
fadb9605
KB
60}
61
62/*
63 * play --
64 * play the game
65 */
8cb55fc8 66#define GAMEHIDE "/usr/games/hide/"
fadb9605
KB
67static
68play(args)
8cb55fc8 69 char **args;
fadb9605 70{
8cb55fc8 71 char pbuf[MAXPATHLEN], *strcpy();
e4c72460
KB
72
73 (void)strcpy(pbuf, GAMEHIDE);
74 (void)strcpy(pbuf + sizeof(GAMEHIDE) - 1, game);
b3b5a8a7
KB
75 if (priority > 0) /* < 0 requires root */
76 (void)setpriority(PRIO_PROCESS, 0, priority);
d671db58 77 setgid(getgid()); /* we run setgid kmem; lose it */
e4c72460 78 execv(pbuf, args);
d671db58 79 perror("dm");
fadb9605
KB
80 exit(1);
81}
82
83/*
b3b5a8a7
KB
84 * read_config --
85 * read through config file, looking for key words.
86 */
8cb55fc8 87#define CONTROL "/usr/games/dm.config"
b3b5a8a7
KB
88static
89read_config()
90{
8cb55fc8
KB
91 FILE *cfp;
92 char *control, *host, *index(), *strcpy();
93 char lbuf[BUFSIZ], path[MAXHOSTNAMELEN + sizeof(CONTROL)];
94 char f1[40], f2[40], f3[40], f4[40], f5[40];
b3b5a8a7 95
8cb55fc8
KB
96 host = &path[sizeof(CONTROL)];
97 if (gethostname(host, MAXHOSTNAMELEN)) {
98 perror("dm: gethostname");
99 exit(1);
100 }
101 (void)strcpy(path, control = CONTROL);
102 host[-1] = '.';
103 if (host = index(host, '.'))
104 *host = '\0';
105 if (!(cfp = fopen(path, "r")) && !(cfp = fopen(control, "r"))) {
106 fprintf(stderr, "dm: unable to read %s or %s.\n",
107 path, control);
b3b5a8a7
KB
108 exit(1);
109 }
110 while (fgets(lbuf, sizeof(lbuf), cfp))
111 switch(*lbuf) {
112 case 'b': /* badtty */
113 if (sscanf(lbuf, "%s%s", f1, f2) != 2 ||
114 strcasecmp(f1, "badtty"))
115 break;
116 c_tty(f2);
117 break;
118 case 'g': /* game */
119 if (sscanf(lbuf, "%s%s%s%s%s",
120 f1, f2, f3, f4, f5) != 5 || strcasecmp(f1, "game"))
121 break;
122 c_game(f2, f3, f4, f5);
123 break;
124 case 't': /* time */
125 if (sscanf(lbuf, "%s%s%s%s", f1, f2, f3, f4) != 4 ||
126 strcasecmp(f1, "time"))
127 break;
128 c_day(f2, f3, f4);
129 }
130 (void)fclose(cfp);
131}
132
133/*
134 * c_day --
135 * if day is today, see if okay to play
fadb9605
KB
136 */
137static
b3b5a8a7 138c_day(s_day, s_start, s_stop)
8cb55fc8 139 char *s_day, *s_start, *s_stop;
fadb9605 140{
8cb55fc8 141 static char *days[] = {
d671db58
KB
142 "sunday", "monday", "tuesday", "wednesday",
143 "thursday", "friday", "saturday",
144 };
8cb55fc8
KB
145 static struct tm *ct;
146 int start, stop;
d671db58 147
b3b5a8a7
KB
148 if (!ct)
149 ct = localtime(&now);
150 if (strcasecmp(s_day, days[ct->tm_wday]))
151 return;
152 if (!isdigit(*s_start) || !isdigit(*s_stop))
153 return;
154 start = atoi(s_start);
155 stop = atoi(s_stop);
156 if (ct->tm_hour >= start && ct->tm_hour <= stop) {
157 fputs("dm: Sorry, games are not available from ", stderr);
158 hour(start);
159 fputs(" to ", stderr);
160 hour(stop);
161 fputs(" today.\n", stderr);
162 exit(0);
d671db58
KB
163 }
164}
165
166/*
b3b5a8a7
KB
167 * c_tty --
168 * decide if this tty can be used for games.
d671db58
KB
169 */
170static
b3b5a8a7 171c_tty(tty)
8cb55fc8 172 char *tty;
d671db58 173{
8cb55fc8
KB
174 static int first = 1;
175 static char *p_tty;
176 char *rindex();
d671db58 177
b3b5a8a7
KB
178 if (first) {
179 p_tty = rindex(gametty, '/');
180 first = 0;
181 }
182
183 if (!strcmp(gametty, tty) || p_tty && !strcmp(p_tty, tty)) {
184 fprintf(stderr, "dm: Sorry, you may not play games on %s.\n", gametty);
185 exit(0);
fadb9605
KB
186 }
187}
188
189/*
b3b5a8a7
KB
190 * c_game --
191 * see if game can be played now.
fadb9605
KB
192 */
193static
b3b5a8a7 194c_game(s_game, s_load, s_users, s_priority)
8cb55fc8 195 char *s_game, *s_load, *s_users, *s_priority;
fadb9605 196{
8cb55fc8
KB
197 static int found;
198 double load();
fadb9605 199
b3b5a8a7
KB
200 if (found)
201 return;
202 if (strcmp(game, s_game) && strcasecmp("default", s_game))
203 return;
204 ++found;
205 if (isdigit(*s_load) && atoi(s_load) < load()) {
206 fputs("dm: Sorry, the load average is too high right now.\n", stderr);
207 exit(0);
208 }
209 if (isdigit(*s_users) && atoi(s_users) <= users()) {
210 fputs("dm: Sorry, there are too many users logged on right now.\n", stderr);
211 exit(0);
fadb9605 212 }
b3b5a8a7
KB
213 if (isdigit(*s_priority))
214 priority = atoi(s_priority);
fadb9605
KB
215}
216
8cb55fc8 217static struct nlist nl[] = {
fadb9605
KB
218 { "_avenrun" },
219#define X_AVENRUN 0
220 { "" },
221};
222
223/*
224 * load --
225 * return 15 minute load average
226 */
227static double
228load()
229{
8cb55fc8
KB
230 double avenrun[3];
231 int kmem;
232 long lseek();
fadb9605
KB
233
234 if (nlist("/vmunix", nl)) {
235 fputs("dm: nlist of /vmunix failed.\n", stderr);
236 exit(1);
237 }
238 if ((kmem = open("/dev/kmem", O_RDONLY, 0)) < 0) {
239 perror("dm: /dev/kmem");
240 exit(1);
241 }
242 (void)lseek(kmem, (long)nl[X_AVENRUN].n_value, L_SET);
b3b5a8a7 243 (void)read(kmem, (char *)avenrun, sizeof(avenrun));
fadb9605
KB
244 return(avenrun[2]);
245}
246
247/*
248 * users --
249 * return current number of users
b3b5a8a7
KB
250 * todo: check idle time; if idle more than X minutes, don't
251 * count them.
fadb9605
KB
252 */
253static
254users()
255{
8cb55fc8
KB
256 register int nusers, utmp;
257 struct utmp buf;
fadb9605
KB
258
259 if ((utmp = open("/etc/utmp", O_RDONLY, 0)) < 0) {
260 perror("dm: /etc/utmp");
261 exit(1);
262 }
263 for (nusers = 0; read(utmp, (char *)&buf, sizeof(struct utmp)) > 0;)
264 if (buf.ut_name[0] != '\0')
265 ++nusers;
266 return(nusers);
267}
268
269/*
270 * nogamefile --
271 * if the file NOGAMING exists, no games allowed.
272 * file may also contain a message for the user.
273 */
8cb55fc8 274#define NOGAMING "/usr/games/nogames"
fadb9605
KB
275static
276nogamefile()
277{
8cb55fc8
KB
278 register int fd, n;
279 char buf[BUFSIZ];
fadb9605
KB
280
281 if ((fd = open(NOGAMING, O_RDONLY, 0)) >= 0) {
282#define MESG "Sorry, no games right now.\n\n"
283 (void)write(2, MESG, sizeof(MESG) - 1);
284 while ((n = read(fd, buf, sizeof(buf))) > 0)
285 (void)write(2, buf, n);
286 exit(1);
287 }
288}
289
290/*
291 * hour --
292 * print out the hour in human form
293 */
d671db58 294static
fadb9605 295hour(h)
8cb55fc8 296 int h;
fadb9605 297{
d671db58
KB
298 switch(h) {
299 case 0:
300 fputs("midnight", stderr);
301 break;
302 case 12:
303 fputs("noon", stderr);
304 break;
305 default:
306 if (h > 12)
307 fprintf(stderr, "%dpm", h - 12);
308 else
309 fprintf(stderr, "%dam", h);
310 }
fadb9605
KB
311}
312
313#ifdef LOG
8cb55fc8
KB
314/*
315 * logfile --
316 * log play of game
317 */
318#define LOGFILE "/usr/adm/dm.log"
fadb9605
KB
319static
320logfile()
321{
8cb55fc8
KB
322 struct passwd *pw, *getpwuid();
323 FILE *lp;
324 uid_t uid;
325 int lock_cnt;
326 char *ctime();
fadb9605
KB
327
328 if (lp = fopen(LOGFILE, "a")) {
329 for (lock_cnt = 0;; ++lock_cnt) {
330 if (!flock(fileno(lp), LOCK_EX))
331 break;
332 if (lock_cnt == 4) {
333 perror("dm: log lock");
334 (void)fclose(lp);
335 return;
336 }
337 sleep((u_int)1);
338 }
339 if (pw = getpwuid(uid = getuid()))
340 fputs(pw->pw_name, lp);
341 else
342 fprintf(lp, "%u", uid);
d671db58 343 fprintf(lp, "\t%s\t%s\t%s", game, gametty, ctime(&now));
fadb9605
KB
344 (void)fclose(lp);
345 (void)flock(fileno(lp), LOCK_UN);
346 }
347}
8cb55fc8 348#endif /* LOG */