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