Commit | Line | Data |
---|---|---|
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 | |
19 | char 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 | 25 | static 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 | 38 | static time_t now; /* current time value */ |
d671db58 KB |
39 | static int priority = 0; /* priority game runs at */ |
40 | static char *game, /* requested game */ | |
41 | *gametty; /* from tty? */ | |
fadb9605 | 42 | |
8cb55fc8 | 43 | /*ARGSUSED*/ |
fadb9605 | 44 | main(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 |
72 | static |
73 | play(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 |
93 | static |
94 | read_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 | */ |
142 | static | |
b3b5a8a7 | 143 | c_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 | */ |
175 | static | |
b3b5a8a7 | 176 | c_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 | */ |
198 | static | |
b3b5a8a7 | 199 | c_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 | 222 | static 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 | */ | |
232 | static double | |
233 | load() | |
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 | */ |
258 | static | |
259 | users() | |
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 |
280 | static |
281 | nogamefile() | |
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 | 299 | static |
fadb9605 | 300 | hour(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 |
324 | static |
325 | logfile() | |
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 */ |