xref: /csrg-svn/games/dm/dm.c (revision 60782)
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