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