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 | |
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 | |
21 | char 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 | 27 | static 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 | 41 | extern int errno; |
fadb9605 | 42 | static time_t now; /* current time value */ |
d671db58 KB |
43 | static int priority = 0; /* priority game runs at */ |
44 | static char *game, /* requested game */ | |
45 | *gametty; /* from tty? */ | |
fadb9605 | 46 | |
8cb55fc8 | 47 | /*ARGSUSED*/ |
fadb9605 | 48 | main(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 | */ | |
75 | static | |
76 | play(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 | */ | |
95 | static | |
96 | read_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 | */ |
130 | static | |
b3b5a8a7 | 131 | c_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 | */ |
163 | static | |
b3b5a8a7 | 164 | c_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 | */ |
186 | static | |
b3b5a8a7 | 187 | c_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 | */ | |
214 | static double | |
215 | load() | |
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 | */ |
232 | static | |
233 | users() | |
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 |
250 | static |
251 | nogamefile() | |
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 | 269 | static |
fadb9605 | 270 | hour(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 |
293 | static |
294 | logfile() | |
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 */ |