xref: /openbsd-src/games/atc/main.c (revision 99d0e43d6d3df12d3091fae0123ca1c90f1b1a8e)
1*99d0e43dSderaadt /*	$OpenBSD: main.c,v 1.33 2024/08/23 14:50:16 deraadt Exp $	*/
2df930be7Sderaadt /*	$NetBSD: main.c,v 1.4 1995/04/27 21:22:25 mycroft Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*-
5df930be7Sderaadt  * Copyright (c) 1990, 1993
6df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * This code is derived from software contributed to Berkeley by
9df930be7Sderaadt  * Ed James.
10df930be7Sderaadt  *
11df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
12df930be7Sderaadt  * modification, are permitted provided that the following conditions
13df930be7Sderaadt  * are met:
14df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
15df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
16df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
17df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
18df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
197a09557bSmillert  * 3. Neither the name of the University nor the names of its contributors
20df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
21df930be7Sderaadt  *    without specific prior written permission.
22df930be7Sderaadt  *
23df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33df930be7Sderaadt  * SUCH DAMAGE.
34df930be7Sderaadt  */
35df930be7Sderaadt 
36df930be7Sderaadt /*
37df930be7Sderaadt  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
38df930be7Sderaadt  *
39df930be7Sderaadt  * Copy permission is hereby granted provided that this notice is
40df930be7Sderaadt  * retained on all partial or complete copies.
41df930be7Sderaadt  *
42df930be7Sderaadt  * For more info on this and all of my stuff, mail edjames@berkeley.edu.
43df930be7Sderaadt  */
44df930be7Sderaadt 
452317ec67Smestre #include <err.h>
462317ec67Smestre #include <signal.h>
472317ec67Smestre #include <stdlib.h>
482317ec67Smestre #include <string.h>
492317ec67Smestre #include <termios.h>
50ee7acb09Stb #include <time.h>
512317ec67Smestre #include <unistd.h>
522317ec67Smestre 
532317ec67Smestre #include "extern.h"
54df930be7Sderaadt #include "pathnames.h"
55df930be7Sderaadt 
5631aab2a5Spjanzen int
5772a685fdStb main(int argc, char *argv[])
58df930be7Sderaadt {
5972a685fdStb 	int			ch;
60df930be7Sderaadt 	int			f_usage = 0, f_list = 0, f_showscore = 0;
61df930be7Sderaadt 	int			f_printpath = 0;
6231aab2a5Spjanzen 	const char		*file = NULL;
6372a685fdStb 	char			*seed;
64df930be7Sderaadt 	struct sigaction	sa;
65df930be7Sderaadt 	struct itimerval	itv;
66df930be7Sderaadt 
67f83b5105Skstailey 	open_score_file();
68f83b5105Skstailey 
69ffe3e522Smillert 	start_time = time(0);
7031aab2a5Spjanzen 	makenoise = 1;
71ffe3e522Smillert 	seed = NULL;
72df930be7Sderaadt 
736fa5e1daSmestre 	while ((ch = getopt(argc, argv, "f:g:hlpqr:st")) != -1) {
7472a685fdStb 		switch (ch) {
7572a685fdStb 		case 'f':
7672a685fdStb 		case 'g':
7772a685fdStb 			file = optarg;
78df930be7Sderaadt 			break;
79df930be7Sderaadt 		case 'l':
8072a685fdStb 			f_list = 1;
81df930be7Sderaadt 			break;
82df930be7Sderaadt 		case 'p':
8372a685fdStb 			f_printpath = 1;
84df930be7Sderaadt 			break;
8531aab2a5Spjanzen 		case 'q':
8631aab2a5Spjanzen 			makenoise = 0;
8731aab2a5Spjanzen 			break;
88df930be7Sderaadt 		case 'r':
8972a685fdStb 			seed = optarg;
90df930be7Sderaadt 			break;
9172a685fdStb 		case 's':
9272a685fdStb 		case 't':
9372a685fdStb 			f_showscore = 1;
94df930be7Sderaadt 			break;
956fa5e1daSmestre 		case 'h':
96df930be7Sderaadt 		default:
9772a685fdStb 			f_usage = 1;
98df930be7Sderaadt 			break;
99df930be7Sderaadt 		}
100df930be7Sderaadt 	}
10172a685fdStb 	argc -= optind;
10272a685fdStb 	argv += optind;
10372a685fdStb 
10472a685fdStb 	if (argc > 0)
10572a685fdStb 		f_usage = 1;
10672a685fdStb 
107ffe3e522Smillert 	if (seed != NULL)
1085b92e02dStedu 		setseed(seed);
109df930be7Sderaadt 
110df930be7Sderaadt 	if (f_usage)
111df930be7Sderaadt 		fprintf(stderr,
1124daa3df4Sjmc 		    "usage: %s [-lpqst] [-f game] [-g game] [-r seed]\n",
11372a685fdStb 		    getprogname());
114df930be7Sderaadt 	if (f_showscore)
115df930be7Sderaadt 		log_score(1);
116df930be7Sderaadt 	if (f_list)
117df930be7Sderaadt 		list_games();
118df930be7Sderaadt 	if (f_printpath) {
119c0eacc5cSray 		size_t	len;
12031aab2a5Spjanzen 		char	buf[256];
121df930be7Sderaadt 
12242ceebb3Sderaadt 		strlcpy(buf, _PATH_GAMES, sizeof buf);
123c0eacc5cSray 		len = strlen(buf);
124c0eacc5cSray 		if (len != 0 && buf[len - 1] == '/')
125c0eacc5cSray 			buf[len - 1] = '\0';
126df930be7Sderaadt 		puts(buf);
127df930be7Sderaadt 	}
128df930be7Sderaadt 
129df930be7Sderaadt 	if (f_usage || f_showscore || f_list || f_printpath)
13017641e31Stb 		return 0;
131df930be7Sderaadt 
132df930be7Sderaadt 	if (file == NULL)
133df930be7Sderaadt 		file = default_game();
134df930be7Sderaadt 	else
135df930be7Sderaadt 		file = okay_game(file);
136df930be7Sderaadt 
137df930be7Sderaadt 	if (file == NULL || read_file(file) < 0)
13817641e31Stb 		return 1;
139df930be7Sderaadt 
140df930be7Sderaadt 	setup_screen(sp);
141df930be7Sderaadt 
142bda84ce9Smestre 	if (pledge("stdio rpath wpath cpath flock tty", NULL) == -1)
143bda84ce9Smestre 		err(1, "pledge");
144bda84ce9Smestre 
145df930be7Sderaadt 	addplane();
146df930be7Sderaadt 
147df930be7Sderaadt 	signal(SIGINT, quit);
148df930be7Sderaadt 	signal(SIGQUIT, quit);
149df930be7Sderaadt 	signal(SIGTSTP, SIG_IGN);
150df930be7Sderaadt 	signal(SIGSTOP, SIG_IGN);
15131aab2a5Spjanzen 	signal(SIGHUP, log_score_quit);
15231aab2a5Spjanzen 	signal(SIGTERM, log_score_quit);
153df930be7Sderaadt 
154df930be7Sderaadt 	tcgetattr(fileno(stdin), &tty_start);
155df930be7Sderaadt 	tty_new = tty_start;
156df930be7Sderaadt 	tty_new.c_lflag &= ~(ICANON|ECHO);
157ef994a34Spjanzen 	tty_new.c_iflag |= ICRNL;
158df930be7Sderaadt 	tty_new.c_cc[VMIN] = 1;
159df930be7Sderaadt 	tty_new.c_cc[VTIME] = 0;
160df930be7Sderaadt 	tcsetattr(fileno(stdin), TCSADRAIN, &tty_new);
161df930be7Sderaadt 
1627df152abSderaadt 	memset(&sa, 0, sizeof sa);
163df930be7Sderaadt 	sa.sa_handler = update;
164df930be7Sderaadt 	sigemptyset(&sa.sa_mask);
165df930be7Sderaadt 	sigaddset(&sa.sa_mask, SIGALRM);
166df930be7Sderaadt 	sigaddset(&sa.sa_mask, SIGINT);
167df930be7Sderaadt 	sa.sa_flags = 0;
168df930be7Sderaadt 	sigaction(SIGALRM, &sa, (struct sigaction *)0);
169df930be7Sderaadt 
170df930be7Sderaadt 	itv.it_value.tv_sec = 0;
171df930be7Sderaadt 	itv.it_value.tv_usec = 1;
172df930be7Sderaadt 	itv.it_interval.tv_sec = sp->update_secs;
173df930be7Sderaadt 	itv.it_interval.tv_usec = 0;
174df930be7Sderaadt 	setitimer(ITIMER_REAL, &itv, NULL);
175df930be7Sderaadt 
176df930be7Sderaadt 	for (;;) {
177df930be7Sderaadt 		if (getcommand() != 1)
178df930be7Sderaadt 			planewin();
179df930be7Sderaadt 		else {
180df930be7Sderaadt 			itv.it_value.tv_sec = 0;
181df930be7Sderaadt 			itv.it_value.tv_usec = 0;
182df930be7Sderaadt 			setitimer(ITIMER_REAL, &itv, NULL);
183df930be7Sderaadt 
18431aab2a5Spjanzen 			update(0);
185df930be7Sderaadt 
186df930be7Sderaadt 			itv.it_value.tv_sec = sp->update_secs;
187df930be7Sderaadt 			itv.it_value.tv_usec = 0;
188df930be7Sderaadt 			itv.it_interval.tv_sec = sp->update_secs;
189df930be7Sderaadt 			itv.it_interval.tv_usec = 0;
190df930be7Sderaadt 			setitimer(ITIMER_REAL, &itv, NULL);
191df930be7Sderaadt 		}
192df930be7Sderaadt 	}
193df930be7Sderaadt }
194df930be7Sderaadt 
19531aab2a5Spjanzen int
1963eb8c9edSjsg read_file(const char *s)
197df930be7Sderaadt {
198df930be7Sderaadt 	extern FILE	*yyin;
199df930be7Sderaadt 	int		retval;
200df930be7Sderaadt 
201df930be7Sderaadt 	file = s;
202df930be7Sderaadt 	yyin = fopen(s, "r");
203df930be7Sderaadt 	if (yyin == NULL) {
20431aab2a5Spjanzen 		warn("fopen %s", s);
205df930be7Sderaadt 		return (-1);
206df930be7Sderaadt 	}
207df930be7Sderaadt 	retval = yyparse();
208df930be7Sderaadt 	fclose(yyin);
209df930be7Sderaadt 
210df930be7Sderaadt 	if (retval != 0)
211df930be7Sderaadt 		return (-1);
212df930be7Sderaadt 	else
213df930be7Sderaadt 		return (0);
214df930be7Sderaadt }
215df930be7Sderaadt 
21631aab2a5Spjanzen const char	*
2173eb8c9edSjsg default_game(void)
218df930be7Sderaadt {
219df930be7Sderaadt 	FILE		*fp;
220df930be7Sderaadt 	static char	file[256];
221*99d0e43dSderaadt 	char		line[256], games[256], *p;
222df930be7Sderaadt 
22342ceebb3Sderaadt 	strlcpy(games, _PATH_GAMES, sizeof games);
22442ceebb3Sderaadt 	strlcat(games, GAMES, sizeof games);
225df930be7Sderaadt 
226df930be7Sderaadt 	if ((fp = fopen(games, "r")) == NULL) {
22731aab2a5Spjanzen 		warn("fopen %s", games);
228df930be7Sderaadt 		return (NULL);
229df930be7Sderaadt 	}
2303d017125Sderaadt 	do {
231df930be7Sderaadt 		if (fgets(line, sizeof(line), fp) == NULL) {
23231aab2a5Spjanzen 			warnx("%s: no default game available", games);
23334944f90Stedu 			fclose(fp);
234df930be7Sderaadt 			return (NULL);
235df930be7Sderaadt 		}
236*99d0e43dSderaadt 		line[strcspn(line, "\n")] = '\0';
237*99d0e43dSderaadt 		p = strrchr(line, '#');
238*99d0e43dSderaadt 		if (p)
239*99d0e43dSderaadt 			*p = '\0';
240*99d0e43dSderaadt 	} while (line[0] == '\0');
241df930be7Sderaadt 	fclose(fp);
242712678dfSgilles 
24331aab2a5Spjanzen 	if (strlen(line) + strlen(_PATH_GAMES) >= sizeof(file)) {
24431aab2a5Spjanzen 		warnx("default game name too long");
24531aab2a5Spjanzen 		return (NULL);
24631aab2a5Spjanzen 	}
24742ceebb3Sderaadt 	strlcpy(file, _PATH_GAMES, sizeof file);
24842ceebb3Sderaadt 	strlcat(file, line, sizeof file);
249df930be7Sderaadt 	return (file);
250df930be7Sderaadt }
251df930be7Sderaadt 
25231aab2a5Spjanzen const char	*
2533eb8c9edSjsg okay_game(const char *s)
254df930be7Sderaadt {
255df930be7Sderaadt 	FILE		*fp;
256df930be7Sderaadt 	static char	file[256];
25731aab2a5Spjanzen 	const char	*ret = NULL;
258*99d0e43dSderaadt 	char		line[256], games[256], *p;
259df930be7Sderaadt 
26042ceebb3Sderaadt 	strlcpy(games, _PATH_GAMES, sizeof games);
26142ceebb3Sderaadt 	strlcat(games, GAMES, sizeof games);
262df930be7Sderaadt 
263df930be7Sderaadt 	if ((fp = fopen(games, "r")) == NULL) {
26431aab2a5Spjanzen 		warn("fopen %s", games);
265df930be7Sderaadt 		return (NULL);
266df930be7Sderaadt 	}
267df930be7Sderaadt 	while (fgets(line, sizeof(line), fp) != NULL) {
268712678dfSgilles 		line[strcspn(line, "\n")] = '\0';
269*99d0e43dSderaadt 		p = strrchr(line, '#');
270*99d0e43dSderaadt 		if (p)
271*99d0e43dSderaadt 			*p = '\0';
272df930be7Sderaadt 		if (strcmp(s, line) == 0) {
27331aab2a5Spjanzen 			if (strlen(line) + strlen(_PATH_GAMES) >= sizeof(file)) {
27431aab2a5Spjanzen 				warnx("game name too long");
27531aab2a5Spjanzen 				return (NULL);
27631aab2a5Spjanzen 			}
27742ceebb3Sderaadt 			strlcpy(file, _PATH_GAMES, sizeof file);
27842ceebb3Sderaadt 			strlcat(file, line, sizeof file);
279df930be7Sderaadt 			ret = file;
280df930be7Sderaadt 			break;
281df930be7Sderaadt 		}
282df930be7Sderaadt 	}
283df930be7Sderaadt 	fclose(fp);
284df930be7Sderaadt 	if (ret == NULL) {
285df930be7Sderaadt 		test_mode = 1;
286df930be7Sderaadt 		ret = s;
287df930be7Sderaadt 		fprintf(stderr, "%s: %s: game not found\n", games, s);
288df930be7Sderaadt 		fprintf(stderr, "Your score will not be logged.\n");
289df930be7Sderaadt 		sleep(2);	/* give the guy time to read it */
290df930be7Sderaadt 	}
291df930be7Sderaadt 	return (ret);
292df930be7Sderaadt }
293df930be7Sderaadt 
29431aab2a5Spjanzen int
2953eb8c9edSjsg list_games(void)
296df930be7Sderaadt {
297df930be7Sderaadt 	FILE		*fp;
298*99d0e43dSderaadt 	char		line[256], games[256], *p;
299df930be7Sderaadt 	int		num_games = 0;
300df930be7Sderaadt 
30142ceebb3Sderaadt 	strlcpy(games, _PATH_GAMES, sizeof games);
30242ceebb3Sderaadt 	strlcat(games, GAMES, sizeof games);
303df930be7Sderaadt 
304df930be7Sderaadt 	if ((fp = fopen(games, "r")) == NULL) {
30531aab2a5Spjanzen 		warn("fopen %s", games);
306df930be7Sderaadt 		return (-1);
307df930be7Sderaadt 	}
308df930be7Sderaadt 	puts("available games:");
309df930be7Sderaadt 	while (fgets(line, sizeof(line), fp) != NULL) {
310cf03695aSray 		line[strcspn(line, "\n")] = '\0';
311*99d0e43dSderaadt 		p = strrchr(line, '#');
312*99d0e43dSderaadt 		if (p)
313*99d0e43dSderaadt 			*p = '\0';
314*99d0e43dSderaadt 		if (line[0] == '\0')
315*99d0e43dSderaadt 			continue;
316cf03695aSray 		printf("	%s\n", line);
317df930be7Sderaadt 		num_games++;
318df930be7Sderaadt 	}
319df930be7Sderaadt 	fclose(fp);
320df930be7Sderaadt 	if (num_games == 0) {
321df930be7Sderaadt 		fprintf(stderr, "%s: no games available\n", games);
322df930be7Sderaadt 		return (-1);
323df930be7Sderaadt 	}
324df930be7Sderaadt 	return (0);
325df930be7Sderaadt }
326