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