xref: /original-bsd/games/dm/dm.c (revision 4da674f5)
1 /*
2  * Copyright (c) 1987 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1987 Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)dm.c	5.16 (Berkeley) 02/28/91";
16 #endif /* not lint */
17 
18 #include <sys/param.h>
19 #include <sys/file.h>
20 #include <sys/time.h>
21 #include <sys/resource.h>
22 #include <pwd.h>
23 #include <utmp.h>
24 #include <nlist.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include "pathnames.h"
28 
29 extern int errno;
30 static time_t	now;			/* current time value */
31 static int	priority = 0;		/* priority game runs at */
32 static char	*game,			/* requested game */
33 		*gametty;		/* from tty? */
34 
35 /*ARGSUSED*/
36 main(argc, argv)
37 	int argc;
38 	char **argv;
39 {
40 	char *cp, *rindex(), *ttyname();
41 	time_t time();
42 
43 	nogamefile();
44 	game = (cp = rindex(*argv, '/')) ? ++cp : *argv;
45 
46 	if (!strcmp(game, "dm"))
47 		exit(0);
48 
49 	gametty = ttyname(0);
50 	(void)time(&now);
51 	read_config();
52 #ifdef LOG
53 	logfile();
54 #endif
55 	play(argv);
56 	/*NOTREACHED*/
57 }
58 
59 /*
60  * play --
61  *	play the game
62  */
63 play(args)
64 	char **args;
65 {
66 	char pbuf[MAXPATHLEN], *strcpy(), *strerror();
67 
68 	(void)strcpy(pbuf, _PATH_HIDE);
69 	(void)strcpy(pbuf + sizeof(_PATH_HIDE) - 1, game);
70 	if (priority > 0)	/* < 0 requires root */
71 		(void)setpriority(PRIO_PROCESS, 0, priority);
72 	setgid(getgid());	/* we run setgid kmem; lose it */
73 	execv(pbuf, args);
74 	(void)fprintf(stderr, "dm: %s: %s\n", pbuf, strerror(errno));
75 	exit(1);
76 }
77 
78 /*
79  * read_config --
80  *	read through config file, looking for key words.
81  */
82 read_config()
83 {
84 	FILE *cfp;
85 	char lbuf[BUFSIZ], f1[40], f2[40], f3[40], f4[40], f5[40];
86 
87 	if (!(cfp = fopen(_PATH_CONFIG, "r")))
88 		return;
89 	while (fgets(lbuf, sizeof(lbuf), cfp))
90 		switch(*lbuf) {
91 		case 'b':		/* badtty */
92 			if (sscanf(lbuf, "%s%s", f1, f2) != 2 ||
93 			    strcasecmp(f1, "badtty"))
94 				break;
95 			c_tty(f2);
96 			break;
97 		case 'g':		/* game */
98 			if (sscanf(lbuf, "%s%s%s%s%s",
99 			    f1, f2, f3, f4, f5) != 5 || strcasecmp(f1, "game"))
100 				break;
101 			c_game(f2, f3, f4, f5);
102 			break;
103 		case 't':		/* time */
104 			if (sscanf(lbuf, "%s%s%s%s", f1, f2, f3, f4) != 4 ||
105 			    strcasecmp(f1, "time"))
106 				break;
107 			c_day(f2, f3, f4);
108 		}
109 	(void)fclose(cfp);
110 }
111 
112 /*
113  * c_day --
114  *	if day is today, see if okay to play
115  */
116 c_day(s_day, s_start, s_stop)
117 	char *s_day, *s_start, *s_stop;
118 {
119 	static char *days[] = {
120 		"sunday", "monday", "tuesday", "wednesday",
121 		"thursday", "friday", "saturday",
122 	};
123 	static struct tm *ct;
124 	int start, stop;
125 
126 	if (!ct)
127 		ct = localtime(&now);
128 	if (strcasecmp(s_day, days[ct->tm_wday]))
129 		return;
130 	if (!isdigit(*s_start) || !isdigit(*s_stop))
131 		return;
132 	start = atoi(s_start);
133 	stop = atoi(s_stop);
134 	if (ct->tm_hour >= start && ct->tm_hour < stop) {
135 		fputs("dm: Sorry, games are not available from ", stderr);
136 		hour(start);
137 		fputs(" to ", stderr);
138 		hour(stop);
139 		fputs(" today.\n", stderr);
140 		exit(0);
141 	}
142 }
143 
144 /*
145  * c_tty --
146  *	decide if this tty can be used for games.
147  */
148 c_tty(tty)
149 	char *tty;
150 {
151 	static int first = 1;
152 	static char *p_tty;
153 	char *rindex();
154 
155 	if (first) {
156 		p_tty = rindex(gametty, '/');
157 		first = 0;
158 	}
159 
160 	if (!strcmp(gametty, tty) || p_tty && !strcmp(p_tty, tty)) {
161 		fprintf(stderr, "dm: Sorry, you may not play games on %s.\n", gametty);
162 		exit(0);
163 	}
164 }
165 
166 /*
167  * c_game --
168  *	see if game can be played now.
169  */
170 c_game(s_game, s_load, s_users, s_priority)
171 	char *s_game, *s_load, *s_users, *s_priority;
172 {
173 	static int found;
174 	double load();
175 
176 	if (found)
177 		return;
178 	if (strcmp(game, s_game) && strcasecmp("default", s_game))
179 		return;
180 	++found;
181 	if (isdigit(*s_load) && atoi(s_load) < load()) {
182 		fputs("dm: Sorry, the load average is too high right now.\n", stderr);
183 		exit(0);
184 	}
185 	if (isdigit(*s_users) && atoi(s_users) <= users()) {
186 		fputs("dm: Sorry, there are too many users logged on right now.\n", stderr);
187 		exit(0);
188 	}
189 	if (isdigit(*s_priority))
190 		priority = atoi(s_priority);
191 }
192 
193 /*
194  * load --
195  *	return 15 minute load average
196  */
197 double
198 load()
199 {
200 	double avenrun[3];
201 
202 	if (getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])) < 0) {
203 		fputs("dm: getloadavg() failed.\n", stderr);
204 		exit(1);
205 	}
206 	return(avenrun[2]);
207 }
208 
209 /*
210  * users --
211  *	return current number of users
212  *	todo: check idle time; if idle more than X minutes, don't
213  *	count them.
214  */
215 users()
216 {
217 
218 	register int nusers, utmp;
219 	struct utmp buf;
220 
221 	if ((utmp = open(_PATH_UTMP, O_RDONLY, 0)) < 0) {
222 		(void)fprintf(stderr, "dm: %s: %s\n",
223 		    _PATH_UTMP, strerror(errno));
224 		exit(1);
225 	}
226 	for (nusers = 0; read(utmp, (char *)&buf, sizeof(struct utmp)) > 0;)
227 		if (buf.ut_name[0] != '\0')
228 			++nusers;
229 	return(nusers);
230 }
231 
232 nogamefile()
233 {
234 	register int fd, n;
235 	char buf[BUFSIZ];
236 
237 	if ((fd = open(_PATH_NOGAMES, O_RDONLY, 0)) >= 0) {
238 #define	MESG	"Sorry, no games right now.\n\n"
239 		(void)write(2, MESG, sizeof(MESG) - 1);
240 		while ((n = read(fd, buf, sizeof(buf))) > 0)
241 			(void)write(2, buf, n);
242 		exit(1);
243 	}
244 }
245 
246 /*
247  * hour --
248  *	print out the hour in human form
249  */
250 hour(h)
251 	int h;
252 {
253 	switch(h) {
254 	case 0:
255 		fputs("midnight", stderr);
256 		break;
257 	case 12:
258 		fputs("noon", stderr);
259 		break;
260 	default:
261 		if (h > 12)
262 			fprintf(stderr, "%dpm", h - 12);
263 		else
264 			fprintf(stderr, "%dam", h);
265 	}
266 }
267 
268 #ifdef LOG
269 /*
270  * logfile --
271  *	log play of game
272  */
273 logfile()
274 {
275 	struct passwd *pw, *getpwuid();
276 	FILE *lp;
277 	uid_t uid;
278 	int lock_cnt;
279 	char *ctime();
280 
281 	if (lp = fopen(_PATH_LOG, "a")) {
282 		for (lock_cnt = 0;; ++lock_cnt) {
283 			if (!flock(fileno(lp), LOCK_EX))
284 				break;
285 			if (lock_cnt == 4) {
286 				perror("dm: log lock");
287 				(void)fclose(lp);
288 				return;
289 			}
290 			sleep((u_int)1);
291 		}
292 		if (pw = getpwuid(uid = getuid()))
293 			fputs(pw->pw_name, lp);
294 		else
295 			fprintf(lp, "%u", uid);
296 		fprintf(lp, "\t%s\t%s\t%s", game, gametty, ctime(&now));
297 		(void)fclose(lp);
298 		(void)flock(fileno(lp), LOCK_UN);
299 	}
300 }
301 #endif /* LOG */
302