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