xref: /csrg-svn/games/dm/dm.c (revision 46741)
132216Sbostic /*
232216Sbostic  * Copyright (c) 1987 Regents of the University of California.
332704Sbostic  * All rights reserved.
432704Sbostic  *
542576Sbostic  * %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*46741Sbostic static char sccsid[] = "@(#)dm.c	5.16 (Berkeley) 02/28/91";
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 play(args)
6433788Sbostic 	char **args;
6532216Sbostic {
6636812Sbostic 	char pbuf[MAXPATHLEN], *strcpy(), *strerror();
6733169Sbostic 
6837412Sbostic 	(void)strcpy(pbuf, _PATH_HIDE);
6937412Sbostic 	(void)strcpy(pbuf + sizeof(_PATH_HIDE) - 1, game);
7032371Sbostic 	if (priority > 0)	/* < 0 requires root */
7132371Sbostic 		(void)setpriority(PRIO_PROCESS, 0, priority);
7232227Sbostic 	setgid(getgid());	/* we run setgid kmem; lose it */
7333169Sbostic 	execv(pbuf, args);
7436812Sbostic 	(void)fprintf(stderr, "dm: %s: %s\n", pbuf, strerror(errno));
7532216Sbostic 	exit(1);
7632216Sbostic }
7732216Sbostic 
7832216Sbostic /*
7932371Sbostic  * read_config --
8032371Sbostic  *	read through config file, looking for key words.
8132216Sbostic  */
8232371Sbostic read_config()
8332216Sbostic {
8433788Sbostic 	FILE *cfp;
8539891Sbostic 	char lbuf[BUFSIZ], f1[40], f2[40], f3[40], f4[40], f5[40];
8632371Sbostic 
8739891Sbostic 	if (!(cfp = fopen(_PATH_CONFIG, "r")))
8837412Sbostic 		return;
8932371Sbostic 	while (fgets(lbuf, sizeof(lbuf), cfp))
9032371Sbostic 		switch(*lbuf) {
9132371Sbostic 		case 'b':		/* badtty */
9232371Sbostic 			if (sscanf(lbuf, "%s%s", f1, f2) != 2 ||
9332371Sbostic 			    strcasecmp(f1, "badtty"))
9432371Sbostic 				break;
9532371Sbostic 			c_tty(f2);
9632371Sbostic 			break;
9732371Sbostic 		case 'g':		/* game */
9832371Sbostic 			if (sscanf(lbuf, "%s%s%s%s%s",
9932371Sbostic 			    f1, f2, f3, f4, f5) != 5 || strcasecmp(f1, "game"))
10032371Sbostic 				break;
10132371Sbostic 			c_game(f2, f3, f4, f5);
10232371Sbostic 			break;
10332371Sbostic 		case 't':		/* time */
10432371Sbostic 			if (sscanf(lbuf, "%s%s%s%s", f1, f2, f3, f4) != 4 ||
10532371Sbostic 			    strcasecmp(f1, "time"))
10632371Sbostic 				break;
10732371Sbostic 			c_day(f2, f3, f4);
10832371Sbostic 		}
10932371Sbostic 	(void)fclose(cfp);
11032371Sbostic }
11132371Sbostic 
11232371Sbostic /*
11332371Sbostic  * c_day --
11432371Sbostic  *	if day is today, see if okay to play
11532371Sbostic  */
11632371Sbostic c_day(s_day, s_start, s_stop)
11733788Sbostic 	char *s_day, *s_start, *s_stop;
11832371Sbostic {
11933788Sbostic 	static char *days[] = {
12032227Sbostic 		"sunday", "monday", "tuesday", "wednesday",
12132227Sbostic 		"thursday", "friday", "saturday",
12232227Sbostic 	};
12333788Sbostic 	static struct tm *ct;
12433788Sbostic 	int start, stop;
12532216Sbostic 
12632371Sbostic 	if (!ct)
12732371Sbostic 		ct = localtime(&now);
12832371Sbostic 	if (strcasecmp(s_day, days[ct->tm_wday]))
12932371Sbostic 		return;
13032371Sbostic 	if (!isdigit(*s_start) || !isdigit(*s_stop))
13132371Sbostic 		return;
13232371Sbostic 	start = atoi(s_start);
13332371Sbostic 	stop = atoi(s_stop);
13435718Sbostic 	if (ct->tm_hour >= start && ct->tm_hour < stop) {
13532371Sbostic 		fputs("dm: Sorry, games are not available from ", stderr);
13632371Sbostic 		hour(start);
13732371Sbostic 		fputs(" to ", stderr);
13832371Sbostic 		hour(stop);
13932371Sbostic 		fputs(" today.\n", stderr);
14032371Sbostic 		exit(0);
14132216Sbostic 	}
14232216Sbostic }
14332216Sbostic 
14432216Sbostic /*
14532371Sbostic  * c_tty --
14632371Sbostic  *	decide if this tty can be used for games.
14732227Sbostic  */
14832371Sbostic c_tty(tty)
14933788Sbostic 	char *tty;
15032227Sbostic {
15133788Sbostic 	static int first = 1;
15233788Sbostic 	static char *p_tty;
15333788Sbostic 	char *rindex();
15432227Sbostic 
15532371Sbostic 	if (first) {
15632371Sbostic 		p_tty = rindex(gametty, '/');
15732371Sbostic 		first = 0;
15832227Sbostic 	}
15932371Sbostic 
16032371Sbostic 	if (!strcmp(gametty, tty) || p_tty && !strcmp(p_tty, tty)) {
16132371Sbostic 		fprintf(stderr, "dm: Sorry, you may not play games on %s.\n", gametty);
16232371Sbostic 		exit(0);
16332371Sbostic 	}
16432227Sbostic }
16532227Sbostic 
16632227Sbostic /*
16732371Sbostic  * c_game --
16832371Sbostic  *	see if game can be played now.
16932216Sbostic  */
17032371Sbostic c_game(s_game, s_load, s_users, s_priority)
17133788Sbostic 	char *s_game, *s_load, *s_users, *s_priority;
17232216Sbostic {
17333788Sbostic 	static int found;
17433788Sbostic 	double load();
17532216Sbostic 
17632371Sbostic 	if (found)
17732371Sbostic 		return;
17832371Sbostic 	if (strcmp(game, s_game) && strcasecmp("default", s_game))
17932371Sbostic 		return;
18032371Sbostic 	++found;
18132371Sbostic 	if (isdigit(*s_load) && atoi(s_load) < load()) {
18232371Sbostic 		fputs("dm: Sorry, the load average is too high right now.\n", stderr);
18332371Sbostic 		exit(0);
18432216Sbostic 	}
18532371Sbostic 	if (isdigit(*s_users) && atoi(s_users) <= users()) {
18632371Sbostic 		fputs("dm: Sorry, there are too many users logged on right now.\n", stderr);
18732371Sbostic 		exit(0);
18832371Sbostic 	}
18932371Sbostic 	if (isdigit(*s_priority))
19032371Sbostic 		priority = atoi(s_priority);
19132216Sbostic }
19232216Sbostic 
19332216Sbostic /*
19432216Sbostic  * load --
19532216Sbostic  *	return 15 minute load average
19632216Sbostic  */
197*46741Sbostic double
19832216Sbostic load()
19932216Sbostic {
20033788Sbostic 	double avenrun[3];
20132216Sbostic 
20238197Smckusick 	if (getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])) < 0) {
20338197Smckusick 		fputs("dm: getloadavg() failed.\n", stderr);
20432216Sbostic 		exit(1);
20532216Sbostic 	}
20632216Sbostic 	return(avenrun[2]);
20732216Sbostic }
20832216Sbostic 
20932216Sbostic /*
21032216Sbostic  * users --
21132216Sbostic  *	return current number of users
21232371Sbostic  *	todo: check idle time; if idle more than X minutes, don't
21332371Sbostic  *	count them.
21432216Sbostic  */
21532216Sbostic users()
21632216Sbostic {
21741188Sbostic 
21833788Sbostic 	register int nusers, utmp;
21933788Sbostic 	struct utmp buf;
22032216Sbostic 
22141188Sbostic 	if ((utmp = open(_PATH_UTMP, O_RDONLY, 0)) < 0) {
22241188Sbostic 		(void)fprintf(stderr, "dm: %s: %s\n",
22341188Sbostic 		    _PATH_UTMP, strerror(errno));
22432216Sbostic 		exit(1);
22532216Sbostic 	}
22632216Sbostic 	for (nusers = 0; read(utmp, (char *)&buf, sizeof(struct utmp)) > 0;)
22732216Sbostic 		if (buf.ut_name[0] != '\0')
22832216Sbostic 			++nusers;
22932216Sbostic 	return(nusers);
23032216Sbostic }
23132216Sbostic 
23232216Sbostic nogamefile()
23332216Sbostic {
23433788Sbostic 	register int fd, n;
23533788Sbostic 	char buf[BUFSIZ];
23632216Sbostic 
23737412Sbostic 	if ((fd = open(_PATH_NOGAMES, O_RDONLY, 0)) >= 0) {
23832216Sbostic #define	MESG	"Sorry, no games right now.\n\n"
23932216Sbostic 		(void)write(2, MESG, sizeof(MESG) - 1);
24032216Sbostic 		while ((n = read(fd, buf, sizeof(buf))) > 0)
24132216Sbostic 			(void)write(2, buf, n);
24232216Sbostic 		exit(1);
24332216Sbostic 	}
24432216Sbostic }
24532216Sbostic 
24632216Sbostic /*
24732216Sbostic  * hour --
24832216Sbostic  *	print out the hour in human form
24932216Sbostic  */
25032216Sbostic hour(h)
25133788Sbostic 	int h;
25232216Sbostic {
25332227Sbostic 	switch(h) {
25432227Sbostic 	case 0:
25532227Sbostic 		fputs("midnight", stderr);
25632227Sbostic 		break;
25732227Sbostic 	case 12:
25832227Sbostic 		fputs("noon", stderr);
25932227Sbostic 		break;
26032227Sbostic 	default:
26132227Sbostic 		if (h > 12)
26232227Sbostic 			fprintf(stderr, "%dpm", h - 12);
26332227Sbostic 		else
26432227Sbostic 			fprintf(stderr, "%dam", h);
26532227Sbostic 	}
26632216Sbostic }
26732216Sbostic 
26832216Sbostic #ifdef LOG
26933788Sbostic /*
27033788Sbostic  * logfile --
27133788Sbostic  *	log play of game
27233788Sbostic  */
27332216Sbostic logfile()
27432216Sbostic {
27533788Sbostic 	struct passwd *pw, *getpwuid();
27633788Sbostic 	FILE *lp;
27733788Sbostic 	uid_t uid;
27833788Sbostic 	int lock_cnt;
27933788Sbostic 	char *ctime();
28032216Sbostic 
28137412Sbostic 	if (lp = fopen(_PATH_LOG, "a")) {
28232216Sbostic 		for (lock_cnt = 0;; ++lock_cnt) {
28332216Sbostic 			if (!flock(fileno(lp), LOCK_EX))
28432216Sbostic 				break;
28532216Sbostic 			if (lock_cnt == 4) {
28632216Sbostic 				perror("dm: log lock");
28732216Sbostic 				(void)fclose(lp);
28832216Sbostic 				return;
28932216Sbostic 			}
29032216Sbostic 			sleep((u_int)1);
29132216Sbostic 		}
29232216Sbostic 		if (pw = getpwuid(uid = getuid()))
29332216Sbostic 			fputs(pw->pw_name, lp);
29432216Sbostic 		else
29532216Sbostic 			fprintf(lp, "%u", uid);
29632227Sbostic 		fprintf(lp, "\t%s\t%s\t%s", game, gametty, ctime(&now));
29732216Sbostic 		(void)fclose(lp);
29832216Sbostic 		(void)flock(fileno(lp), LOCK_UN);
29932216Sbostic 	}
30032216Sbostic }
30133788Sbostic #endif /* LOG */
302