132216Sbostic /* 232216Sbostic * Copyright (c) 1987 Regents of the University of California. 332704Sbostic * All rights reserved. 432704Sbostic * 5*42576Sbostic * %sccs.include.redist.c% 632216Sbostic */ 732216Sbostic 832216Sbostic #ifndef lint 932216Sbostic char copyright[] = 1032216Sbostic "@(#) Copyright (c) 1987 Regents of the University of California.\n\ 1132216Sbostic All rights reserved.\n"; 1232704Sbostic #endif /* not lint */ 1332216Sbostic 1432216Sbostic #ifndef lint 15*42576Sbostic static char sccsid[] = "@(#)dm.c 5.15 (Berkeley) 06/01/90"; 1632704Sbostic #endif /* not lint */ 1732216Sbostic 1832216Sbostic #include <sys/param.h> 1932216Sbostic #include <sys/file.h> 2032216Sbostic #include <sys/time.h> 2132216Sbostic #include <sys/resource.h> 2232216Sbostic #include <pwd.h> 2332216Sbostic #include <utmp.h> 2432216Sbostic #include <nlist.h> 2532216Sbostic #include <stdio.h> 2632216Sbostic #include <ctype.h> 2737412Sbostic #include "pathnames.h" 2832216Sbostic 2941188Sbostic extern int errno; 3032216Sbostic static time_t now; /* current time value */ 3132227Sbostic static int priority = 0; /* priority game runs at */ 3232227Sbostic static char *game, /* requested game */ 3332227Sbostic *gametty; /* from tty? */ 3432216Sbostic 3533788Sbostic /*ARGSUSED*/ 3632216Sbostic main(argc, argv) 3733788Sbostic int argc; 3833788Sbostic char **argv; 3932216Sbostic { 4033788Sbostic char *cp, *rindex(), *ttyname(); 4133788Sbostic time_t time(); 4232216Sbostic 4332216Sbostic nogamefile(); 4432371Sbostic game = (cp = rindex(*argv, '/')) ? ++cp : *argv; 4532216Sbostic 4632371Sbostic if (!strcmp(game, "dm")) 4732227Sbostic exit(0); 4832216Sbostic 4932371Sbostic gametty = ttyname(0); 5032371Sbostic (void)time(&now); 5132371Sbostic read_config(); 5232216Sbostic #ifdef LOG 5332216Sbostic logfile(); 5432216Sbostic #endif 5532216Sbostic play(argv); 5632371Sbostic /*NOTREACHED*/ 5732216Sbostic } 5832216Sbostic 5932216Sbostic /* 6032216Sbostic * play -- 6132216Sbostic * play the game 6232216Sbostic */ 6332216Sbostic static 6432216Sbostic play(args) 6533788Sbostic char **args; 6632216Sbostic { 6736812Sbostic char pbuf[MAXPATHLEN], *strcpy(), *strerror(); 6833169Sbostic 6937412Sbostic (void)strcpy(pbuf, _PATH_HIDE); 7037412Sbostic (void)strcpy(pbuf + sizeof(_PATH_HIDE) - 1, game); 7132371Sbostic if (priority > 0) /* < 0 requires root */ 7232371Sbostic (void)setpriority(PRIO_PROCESS, 0, priority); 7332227Sbostic setgid(getgid()); /* we run setgid kmem; lose it */ 7433169Sbostic execv(pbuf, args); 7536812Sbostic (void)fprintf(stderr, "dm: %s: %s\n", pbuf, strerror(errno)); 7632216Sbostic exit(1); 7732216Sbostic } 7832216Sbostic 7932216Sbostic /* 8032371Sbostic * read_config -- 8132371Sbostic * read through config file, looking for key words. 8232216Sbostic */ 8332216Sbostic static 8432371Sbostic read_config() 8532216Sbostic { 8633788Sbostic FILE *cfp; 8739891Sbostic char lbuf[BUFSIZ], f1[40], f2[40], f3[40], f4[40], f5[40]; 8832371Sbostic 8939891Sbostic if (!(cfp = fopen(_PATH_CONFIG, "r"))) 9037412Sbostic return; 9132371Sbostic while (fgets(lbuf, sizeof(lbuf), cfp)) 9232371Sbostic switch(*lbuf) { 9332371Sbostic case 'b': /* badtty */ 9432371Sbostic if (sscanf(lbuf, "%s%s", f1, f2) != 2 || 9532371Sbostic strcasecmp(f1, "badtty")) 9632371Sbostic break; 9732371Sbostic c_tty(f2); 9832371Sbostic break; 9932371Sbostic case 'g': /* game */ 10032371Sbostic if (sscanf(lbuf, "%s%s%s%s%s", 10132371Sbostic f1, f2, f3, f4, f5) != 5 || strcasecmp(f1, "game")) 10232371Sbostic break; 10332371Sbostic c_game(f2, f3, f4, f5); 10432371Sbostic break; 10532371Sbostic case 't': /* time */ 10632371Sbostic if (sscanf(lbuf, "%s%s%s%s", f1, f2, f3, f4) != 4 || 10732371Sbostic strcasecmp(f1, "time")) 10832371Sbostic break; 10932371Sbostic c_day(f2, f3, f4); 11032371Sbostic } 11132371Sbostic (void)fclose(cfp); 11232371Sbostic } 11332371Sbostic 11432371Sbostic /* 11532371Sbostic * c_day -- 11632371Sbostic * if day is today, see if okay to play 11732371Sbostic */ 11832371Sbostic static 11932371Sbostic c_day(s_day, s_start, s_stop) 12033788Sbostic char *s_day, *s_start, *s_stop; 12132371Sbostic { 12233788Sbostic static char *days[] = { 12332227Sbostic "sunday", "monday", "tuesday", "wednesday", 12432227Sbostic "thursday", "friday", "saturday", 12532227Sbostic }; 12633788Sbostic static struct tm *ct; 12733788Sbostic int start, stop; 12832216Sbostic 12932371Sbostic if (!ct) 13032371Sbostic ct = localtime(&now); 13132371Sbostic if (strcasecmp(s_day, days[ct->tm_wday])) 13232371Sbostic return; 13332371Sbostic if (!isdigit(*s_start) || !isdigit(*s_stop)) 13432371Sbostic return; 13532371Sbostic start = atoi(s_start); 13632371Sbostic stop = atoi(s_stop); 13735718Sbostic if (ct->tm_hour >= start && ct->tm_hour < stop) { 13832371Sbostic fputs("dm: Sorry, games are not available from ", stderr); 13932371Sbostic hour(start); 14032371Sbostic fputs(" to ", stderr); 14132371Sbostic hour(stop); 14232371Sbostic fputs(" today.\n", stderr); 14332371Sbostic exit(0); 14432216Sbostic } 14532216Sbostic } 14632216Sbostic 14732216Sbostic /* 14832371Sbostic * c_tty -- 14932371Sbostic * decide if this tty can be used for games. 15032227Sbostic */ 15132227Sbostic static 15232371Sbostic c_tty(tty) 15333788Sbostic char *tty; 15432227Sbostic { 15533788Sbostic static int first = 1; 15633788Sbostic static char *p_tty; 15733788Sbostic char *rindex(); 15832227Sbostic 15932371Sbostic if (first) { 16032371Sbostic p_tty = rindex(gametty, '/'); 16132371Sbostic first = 0; 16232227Sbostic } 16332371Sbostic 16432371Sbostic if (!strcmp(gametty, tty) || p_tty && !strcmp(p_tty, tty)) { 16532371Sbostic fprintf(stderr, "dm: Sorry, you may not play games on %s.\n", gametty); 16632371Sbostic exit(0); 16732371Sbostic } 16832227Sbostic } 16932227Sbostic 17032227Sbostic /* 17132371Sbostic * c_game -- 17232371Sbostic * see if game can be played now. 17332216Sbostic */ 17432216Sbostic static 17532371Sbostic c_game(s_game, s_load, s_users, s_priority) 17633788Sbostic char *s_game, *s_load, *s_users, *s_priority; 17732216Sbostic { 17833788Sbostic static int found; 17933788Sbostic double load(); 18032216Sbostic 18132371Sbostic if (found) 18232371Sbostic return; 18332371Sbostic if (strcmp(game, s_game) && strcasecmp("default", s_game)) 18432371Sbostic return; 18532371Sbostic ++found; 18632371Sbostic if (isdigit(*s_load) && atoi(s_load) < load()) { 18732371Sbostic fputs("dm: Sorry, the load average is too high right now.\n", stderr); 18832371Sbostic exit(0); 18932216Sbostic } 19032371Sbostic if (isdigit(*s_users) && atoi(s_users) <= users()) { 19132371Sbostic fputs("dm: Sorry, there are too many users logged on right now.\n", stderr); 19232371Sbostic exit(0); 19332371Sbostic } 19432371Sbostic if (isdigit(*s_priority)) 19532371Sbostic priority = atoi(s_priority); 19632216Sbostic } 19732216Sbostic 19832216Sbostic /* 19932216Sbostic * load -- 20032216Sbostic * return 15 minute load average 20132216Sbostic */ 20232216Sbostic static double 20332216Sbostic load() 20432216Sbostic { 20533788Sbostic double avenrun[3]; 20632216Sbostic 20738197Smckusick if (getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])) < 0) { 20838197Smckusick fputs("dm: getloadavg() failed.\n", stderr); 20932216Sbostic exit(1); 21032216Sbostic } 21132216Sbostic return(avenrun[2]); 21232216Sbostic } 21332216Sbostic 21432216Sbostic /* 21532216Sbostic * users -- 21632216Sbostic * return current number of users 21732371Sbostic * todo: check idle time; if idle more than X minutes, don't 21832371Sbostic * count them. 21932216Sbostic */ 22032216Sbostic static 22132216Sbostic users() 22232216Sbostic { 22341188Sbostic 22433788Sbostic register int nusers, utmp; 22533788Sbostic struct utmp buf; 22632216Sbostic 22741188Sbostic if ((utmp = open(_PATH_UTMP, O_RDONLY, 0)) < 0) { 22841188Sbostic (void)fprintf(stderr, "dm: %s: %s\n", 22941188Sbostic _PATH_UTMP, strerror(errno)); 23032216Sbostic exit(1); 23132216Sbostic } 23232216Sbostic for (nusers = 0; read(utmp, (char *)&buf, sizeof(struct utmp)) > 0;) 23332216Sbostic if (buf.ut_name[0] != '\0') 23432216Sbostic ++nusers; 23532216Sbostic return(nusers); 23632216Sbostic } 23732216Sbostic 23832216Sbostic static 23932216Sbostic nogamefile() 24032216Sbostic { 24133788Sbostic register int fd, n; 24233788Sbostic char buf[BUFSIZ]; 24332216Sbostic 24437412Sbostic if ((fd = open(_PATH_NOGAMES, O_RDONLY, 0)) >= 0) { 24532216Sbostic #define MESG "Sorry, no games right now.\n\n" 24632216Sbostic (void)write(2, MESG, sizeof(MESG) - 1); 24732216Sbostic while ((n = read(fd, buf, sizeof(buf))) > 0) 24832216Sbostic (void)write(2, buf, n); 24932216Sbostic exit(1); 25032216Sbostic } 25132216Sbostic } 25232216Sbostic 25332216Sbostic /* 25432216Sbostic * hour -- 25532216Sbostic * print out the hour in human form 25632216Sbostic */ 25732227Sbostic static 25832216Sbostic hour(h) 25933788Sbostic int h; 26032216Sbostic { 26132227Sbostic switch(h) { 26232227Sbostic case 0: 26332227Sbostic fputs("midnight", stderr); 26432227Sbostic break; 26532227Sbostic case 12: 26632227Sbostic fputs("noon", stderr); 26732227Sbostic break; 26832227Sbostic default: 26932227Sbostic if (h > 12) 27032227Sbostic fprintf(stderr, "%dpm", h - 12); 27132227Sbostic else 27232227Sbostic fprintf(stderr, "%dam", h); 27332227Sbostic } 27432216Sbostic } 27532216Sbostic 27632216Sbostic #ifdef LOG 27733788Sbostic /* 27833788Sbostic * logfile -- 27933788Sbostic * log play of game 28033788Sbostic */ 28132216Sbostic static 28232216Sbostic logfile() 28332216Sbostic { 28433788Sbostic struct passwd *pw, *getpwuid(); 28533788Sbostic FILE *lp; 28633788Sbostic uid_t uid; 28733788Sbostic int lock_cnt; 28833788Sbostic char *ctime(); 28932216Sbostic 29037412Sbostic if (lp = fopen(_PATH_LOG, "a")) { 29132216Sbostic for (lock_cnt = 0;; ++lock_cnt) { 29232216Sbostic if (!flock(fileno(lp), LOCK_EX)) 29332216Sbostic break; 29432216Sbostic if (lock_cnt == 4) { 29532216Sbostic perror("dm: log lock"); 29632216Sbostic (void)fclose(lp); 29732216Sbostic return; 29832216Sbostic } 29932216Sbostic sleep((u_int)1); 30032216Sbostic } 30132216Sbostic if (pw = getpwuid(uid = getuid())) 30232216Sbostic fputs(pw->pw_name, lp); 30332216Sbostic else 30432216Sbostic fprintf(lp, "%u", uid); 30532227Sbostic fprintf(lp, "\t%s\t%s\t%s", game, gametty, ctime(&now)); 30632216Sbostic (void)fclose(lp); 30732216Sbostic (void)flock(fileno(lp), LOCK_UN); 30832216Sbostic } 30932216Sbostic } 31033788Sbostic #endif /* LOG */ 311