|
|
1.1 root 1: /*
2: * Copyright (c) 1987 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
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.
16: */
17:
18: #ifndef lint
19: char copyright[] =
20: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
21: All rights reserved.\n";
22: #endif /* not lint */
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)dm.c 5.8 (Berkeley) 6/18/88";
26: #endif /* not lint */
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:
38: static time_t now; /* current time value */
39: static int priority = 0; /* priority game runs at */
40: static char *game, /* requested game */
41: *gametty; /* from tty? */
42:
43: /*ARGSUSED*/
44: main(argc, argv)
45: int argc;
46: char **argv;
47: {
48: char *cp, *rindex(), *ttyname();
49: time_t time();
50:
51: nogamefile();
52: game = (cp = rindex(*argv, '/')) ? ++cp : *argv;
53:
54: if (!strcmp(game, "dm"))
55: exit(0);
56:
57: gametty = ttyname(0);
58: (void)time(&now);
59: read_config();
60: #ifdef LOG
61: logfile();
62: #endif
63: play(argv);
64: /*NOTREACHED*/
65: }
66:
67: /*
68: * play --
69: * play the game
70: */
71: #define GAMEHIDE "/usr/games/hide/"
72: static
73: play(args)
74: char **args;
75: {
76: char pbuf[MAXPATHLEN], *strcpy();
77:
78: (void)strcpy(pbuf, GAMEHIDE);
79: (void)strcpy(pbuf + sizeof(GAMEHIDE) - 1, game);
80: if (priority > 0) /* < 0 requires root */
81: (void)setpriority(PRIO_PROCESS, 0, priority);
82: setgid(getgid()); /* we run setgid kmem; lose it */
83: execv(pbuf, args);
84: perror("dm");
85: exit(1);
86: }
87:
88: /*
89: * read_config --
90: * read through config file, looking for key words.
91: */
92: #define CONTROL "/usr/games/dm.config"
93: static
94: read_config()
95: {
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];
100:
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);
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
141: */
142: static
143: c_day(s_day, s_start, s_stop)
144: char *s_day, *s_start, *s_stop;
145: {
146: static char *days[] = {
147: "sunday", "monday", "tuesday", "wednesday",
148: "thursday", "friday", "saturday",
149: };
150: static struct tm *ct;
151: int start, stop;
152:
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);
168: }
169: }
170:
171: /*
172: * c_tty --
173: * decide if this tty can be used for games.
174: */
175: static
176: c_tty(tty)
177: char *tty;
178: {
179: static int first = 1;
180: static char *p_tty;
181: char *rindex();
182:
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);
191: }
192: }
193:
194: /*
195: * c_game --
196: * see if game can be played now.
197: */
198: static
199: c_game(s_game, s_load, s_users, s_priority)
200: char *s_game, *s_load, *s_users, *s_priority;
201: {
202: static int found;
203: double load();
204:
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);
217: }
218: if (isdigit(*s_priority))
219: priority = atoi(s_priority);
220: }
221:
222: static struct nlist nl[] = {
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: {
235: double avenrun[3];
236: int kmem;
237: long lseek();
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);
248: (void)read(kmem, (char *)avenrun, sizeof(avenrun));
249: return(avenrun[2]);
250: }
251:
252: /*
253: * users --
254: * return current number of users
255: * todo: check idle time; if idle more than X minutes, don't
256: * count them.
257: */
258: static
259: users()
260: {
261: register int nusers, utmp;
262: struct utmp buf;
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: */
279: #define NOGAMING "/usr/games/nogames"
280: static
281: nogamefile()
282: {
283: register int fd, n;
284: char buf[BUFSIZ];
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: */
299: static
300: hour(h)
301: int h;
302: {
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: }
316: }
317:
318: #ifdef LOG
319: /*
320: * logfile --
321: * log play of game
322: */
323: #define LOGFILE "/usr/adm/dm.log"
324: static
325: logfile()
326: {
327: struct passwd *pw, *getpwuid();
328: FILE *lp;
329: uid_t uid;
330: int lock_cnt;
331: char *ctime();
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);
348: fprintf(lp, "\t%s\t%s\t%s", game, gametty, ctime(&now));
349: (void)fclose(lp);
350: (void)flock(fileno(lp), LOCK_UN);
351: }
352: }
353: #endif /* LOG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.