132216Sbostic /*
2*60782Sbostic * Copyright (c) 1987, 1993
3*60782Sbostic * The Regents of the University of California. All rights reserved.
432704Sbostic *
542576Sbostic * %sccs.include.redist.c%
632216Sbostic */
732216Sbostic
832216Sbostic #ifndef lint
9*60782Sbostic static char copyright[] =
10*60782Sbostic "@(#) Copyright (c) 1987, 1993\n\
11*60782Sbostic The Regents of the University of California. All rights reserved.\n";
1232704Sbostic #endif /* not lint */
1332216Sbostic
1432216Sbostic #ifndef lint
15*60782Sbostic static char sccsid[] = "@(#)dm.c 8.1 (Berkeley) 05/31/93";
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>
2258760Sbostic
2358760Sbostic #include <ctype.h>
2458760Sbostic #include <nlist.h>
2532216Sbostic #include <pwd.h>
2658760Sbostic #include <stdio.h>
2758760Sbostic #include <string.h>
2858760Sbostic #include <time.h>
2958760Sbostic #include <unistd.h>
3032216Sbostic #include <utmp.h>
3158760Sbostic
3237412Sbostic #include "pathnames.h"
3332216Sbostic
3441188Sbostic extern int errno;
3532216Sbostic static time_t now; /* current time value */
3632227Sbostic static int priority = 0; /* priority game runs at */
3732227Sbostic static char *game, /* requested game */
3832227Sbostic *gametty; /* from tty? */
3932216Sbostic
4058760Sbostic int
main(argc,argv)4132216Sbostic main(argc, argv)
4233788Sbostic int argc;
4358760Sbostic char *argv[];
4432216Sbostic {
4558760Sbostic char *cp;
4632216Sbostic
4732216Sbostic nogamefile();
4832371Sbostic game = (cp = rindex(*argv, '/')) ? ++cp : *argv;
4932216Sbostic
5032371Sbostic if (!strcmp(game, "dm"))
5132227Sbostic exit(0);
5232216Sbostic
5332371Sbostic gametty = ttyname(0);
5432371Sbostic (void)time(&now);
5532371Sbostic read_config();
5632216Sbostic #ifdef LOG
5732216Sbostic logfile();
5832216Sbostic #endif
5932216Sbostic play(argv);
6032371Sbostic /*NOTREACHED*/
6132216Sbostic }
6232216Sbostic
6332216Sbostic /*
6432216Sbostic * play --
6532216Sbostic * play the game
6632216Sbostic */
play(args)6732216Sbostic play(args)
6833788Sbostic char **args;
6932216Sbostic {
7058760Sbostic char pbuf[MAXPATHLEN];
7133169Sbostic
7237412Sbostic (void)strcpy(pbuf, _PATH_HIDE);
7337412Sbostic (void)strcpy(pbuf + sizeof(_PATH_HIDE) - 1, game);
7432371Sbostic if (priority > 0) /* < 0 requires root */
7532371Sbostic (void)setpriority(PRIO_PROCESS, 0, priority);
7632227Sbostic setgid(getgid()); /* we run setgid kmem; lose it */
7733169Sbostic execv(pbuf, args);
7836812Sbostic (void)fprintf(stderr, "dm: %s: %s\n", pbuf, strerror(errno));
7932216Sbostic exit(1);
8032216Sbostic }
8132216Sbostic
8232216Sbostic /*
8332371Sbostic * read_config --
8432371Sbostic * read through config file, looking for key words.
8532216Sbostic */
read_config()8632371Sbostic read_config()
8732216Sbostic {
8833788Sbostic FILE *cfp;
8939891Sbostic char lbuf[BUFSIZ], f1[40], f2[40], f3[40], f4[40], f5[40];
9032371Sbostic
9139891Sbostic if (!(cfp = fopen(_PATH_CONFIG, "r")))
9237412Sbostic return;
9332371Sbostic while (fgets(lbuf, sizeof(lbuf), cfp))
9432371Sbostic switch(*lbuf) {
9532371Sbostic case 'b': /* badtty */
9632371Sbostic if (sscanf(lbuf, "%s%s", f1, f2) != 2 ||
9732371Sbostic strcasecmp(f1, "badtty"))
9832371Sbostic break;
9932371Sbostic c_tty(f2);
10032371Sbostic break;
10132371Sbostic case 'g': /* game */
10232371Sbostic if (sscanf(lbuf, "%s%s%s%s%s",
10332371Sbostic f1, f2, f3, f4, f5) != 5 || strcasecmp(f1, "game"))
10432371Sbostic break;
10532371Sbostic c_game(f2, f3, f4, f5);
10632371Sbostic break;
10732371Sbostic case 't': /* time */
10832371Sbostic if (sscanf(lbuf, "%s%s%s%s", f1, f2, f3, f4) != 4 ||
10932371Sbostic strcasecmp(f1, "time"))
11032371Sbostic break;
11132371Sbostic c_day(f2, f3, f4);
11232371Sbostic }
11332371Sbostic (void)fclose(cfp);
11432371Sbostic }
11532371Sbostic
11632371Sbostic /*
11732371Sbostic * c_day --
11832371Sbostic * if day is today, see if okay to play
11932371Sbostic */
c_day(s_day,s_start,s_stop)12032371Sbostic c_day(s_day, s_start, s_stop)
12133788Sbostic char *s_day, *s_start, *s_stop;
12232371Sbostic {
12333788Sbostic static char *days[] = {
12432227Sbostic "sunday", "monday", "tuesday", "wednesday",
12532227Sbostic "thursday", "friday", "saturday",
12632227Sbostic };
12733788Sbostic static struct tm *ct;
12833788Sbostic int start, stop;
12932216Sbostic
13032371Sbostic if (!ct)
13132371Sbostic ct = localtime(&now);
13232371Sbostic if (strcasecmp(s_day, days[ct->tm_wday]))
13332371Sbostic return;
13432371Sbostic if (!isdigit(*s_start) || !isdigit(*s_stop))
13532371Sbostic return;
13632371Sbostic start = atoi(s_start);
13732371Sbostic stop = atoi(s_stop);
13835718Sbostic if (ct->tm_hour >= start && ct->tm_hour < stop) {
13932371Sbostic fputs("dm: Sorry, games are not available from ", stderr);
14032371Sbostic hour(start);
14132371Sbostic fputs(" to ", stderr);
14232371Sbostic hour(stop);
14332371Sbostic fputs(" today.\n", stderr);
14432371Sbostic exit(0);
14532216Sbostic }
14632216Sbostic }
14732216Sbostic
14832216Sbostic /*
14932371Sbostic * c_tty --
15032371Sbostic * decide if this tty can be used for games.
15132227Sbostic */
c_tty(tty)15232371Sbostic c_tty(tty)
15333788Sbostic char *tty;
15432227Sbostic {
15533788Sbostic static int first = 1;
15633788Sbostic static char *p_tty;
15732227Sbostic
15832371Sbostic if (first) {
15932371Sbostic p_tty = rindex(gametty, '/');
16032371Sbostic first = 0;
16132227Sbostic }
16232371Sbostic
16332371Sbostic if (!strcmp(gametty, tty) || p_tty && !strcmp(p_tty, tty)) {
16432371Sbostic fprintf(stderr, "dm: Sorry, you may not play games on %s.\n", gametty);
16532371Sbostic exit(0);
16632371Sbostic }
16732227Sbostic }
16832227Sbostic
16932227Sbostic /*
17032371Sbostic * c_game --
17132371Sbostic * see if game can be played now.
17232216Sbostic */
c_game(s_game,s_load,s_users,s_priority)17332371Sbostic c_game(s_game, s_load, s_users, s_priority)
17433788Sbostic char *s_game, *s_load, *s_users, *s_priority;
17532216Sbostic {
17633788Sbostic static int found;
17733788Sbostic double load();
17832216Sbostic
17932371Sbostic if (found)
18032371Sbostic return;
18132371Sbostic if (strcmp(game, s_game) && strcasecmp("default", s_game))
18232371Sbostic return;
18332371Sbostic ++found;
18432371Sbostic if (isdigit(*s_load) && atoi(s_load) < load()) {
18532371Sbostic fputs("dm: Sorry, the load average is too high right now.\n", stderr);
18632371Sbostic exit(0);
18732216Sbostic }
18832371Sbostic if (isdigit(*s_users) && atoi(s_users) <= users()) {
18932371Sbostic fputs("dm: Sorry, there are too many users logged on right now.\n", stderr);
19032371Sbostic exit(0);
19132371Sbostic }
19232371Sbostic if (isdigit(*s_priority))
19332371Sbostic priority = atoi(s_priority);
19432216Sbostic }
19532216Sbostic
19632216Sbostic /*
19732216Sbostic * load --
19832216Sbostic * return 15 minute load average
19932216Sbostic */
20046741Sbostic double
load()20132216Sbostic load()
20232216Sbostic {
20333788Sbostic double avenrun[3];
20432216Sbostic
20538197Smckusick if (getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])) < 0) {
20638197Smckusick fputs("dm: getloadavg() failed.\n", stderr);
20732216Sbostic exit(1);
20832216Sbostic }
20932216Sbostic return(avenrun[2]);
21032216Sbostic }
21132216Sbostic
21232216Sbostic /*
21332216Sbostic * users --
21432216Sbostic * return current number of users
21532371Sbostic * todo: check idle time; if idle more than X minutes, don't
21632371Sbostic * count them.
21732216Sbostic */
users()21832216Sbostic users()
21932216Sbostic {
22041188Sbostic
22133788Sbostic register int nusers, utmp;
22233788Sbostic struct utmp buf;
22332216Sbostic
22441188Sbostic if ((utmp = open(_PATH_UTMP, O_RDONLY, 0)) < 0) {
22541188Sbostic (void)fprintf(stderr, "dm: %s: %s\n",
22641188Sbostic _PATH_UTMP, strerror(errno));
22732216Sbostic exit(1);
22832216Sbostic }
22932216Sbostic for (nusers = 0; read(utmp, (char *)&buf, sizeof(struct utmp)) > 0;)
23032216Sbostic if (buf.ut_name[0] != '\0')
23132216Sbostic ++nusers;
23232216Sbostic return(nusers);
23332216Sbostic }
23432216Sbostic
nogamefile()23532216Sbostic nogamefile()
23632216Sbostic {
23733788Sbostic register int fd, n;
23833788Sbostic char buf[BUFSIZ];
23932216Sbostic
24037412Sbostic if ((fd = open(_PATH_NOGAMES, O_RDONLY, 0)) >= 0) {
24132216Sbostic #define MESG "Sorry, no games right now.\n\n"
24232216Sbostic (void)write(2, MESG, sizeof(MESG) - 1);
24332216Sbostic while ((n = read(fd, buf, sizeof(buf))) > 0)
24432216Sbostic (void)write(2, buf, n);
24532216Sbostic exit(1);
24632216Sbostic }
24732216Sbostic }
24832216Sbostic
24932216Sbostic /*
25032216Sbostic * hour --
25132216Sbostic * print out the hour in human form
25232216Sbostic */
hour(h)25332216Sbostic hour(h)
25433788Sbostic int h;
25532216Sbostic {
25632227Sbostic switch(h) {
25732227Sbostic case 0:
25832227Sbostic fputs("midnight", stderr);
25932227Sbostic break;
26032227Sbostic case 12:
26132227Sbostic fputs("noon", stderr);
26232227Sbostic break;
26332227Sbostic default:
26432227Sbostic if (h > 12)
26532227Sbostic fprintf(stderr, "%dpm", h - 12);
26632227Sbostic else
26732227Sbostic fprintf(stderr, "%dam", h);
26832227Sbostic }
26932216Sbostic }
27032216Sbostic
27132216Sbostic #ifdef LOG
27233788Sbostic /*
27333788Sbostic * logfile --
27433788Sbostic * log play of game
27533788Sbostic */
logfile()27632216Sbostic logfile()
27732216Sbostic {
27858760Sbostic struct passwd *pw;
27933788Sbostic FILE *lp;
28033788Sbostic uid_t uid;
28133788Sbostic int lock_cnt;
28232216Sbostic
28337412Sbostic if (lp = fopen(_PATH_LOG, "a")) {
28432216Sbostic for (lock_cnt = 0;; ++lock_cnt) {
28532216Sbostic if (!flock(fileno(lp), LOCK_EX))
28632216Sbostic break;
28732216Sbostic if (lock_cnt == 4) {
28832216Sbostic perror("dm: log lock");
28932216Sbostic (void)fclose(lp);
29032216Sbostic return;
29132216Sbostic }
29232216Sbostic sleep((u_int)1);
29332216Sbostic }
29432216Sbostic if (pw = getpwuid(uid = getuid()))
29532216Sbostic fputs(pw->pw_name, lp);
29632216Sbostic else
29732216Sbostic fprintf(lp, "%u", uid);
29832227Sbostic fprintf(lp, "\t%s\t%s\t%s", game, gametty, ctime(&now));
29932216Sbostic (void)fclose(lp);
30032216Sbostic (void)flock(fileno(lp), LOCK_UN);
30132216Sbostic }
30232216Sbostic }
30333788Sbostic #endif /* LOG */
304