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