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