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