1*abca1099Srillig /* $NetBSD: main.c,v 1.25 2021/05/02 12:50:43 rillig Exp $ */
2101657d1Scgd
361f28255Scgd /*-
4101657d1Scgd * Copyright (c) 1990, 1993
5101657d1Scgd * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * This code is derived from software contributed to Berkeley by
861f28255Scgd * Ed James.
961f28255Scgd *
1061f28255Scgd * Redistribution and use in source and binary forms, with or without
1161f28255Scgd * modification, are permitted provided that the following conditions
1261f28255Scgd * are met:
1361f28255Scgd * 1. Redistributions of source code must retain the above copyright
1461f28255Scgd * notice, this list of conditions and the following disclaimer.
1561f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1661f28255Scgd * notice, this list of conditions and the following disclaimer in the
1761f28255Scgd * documentation and/or other materials provided with the distribution.
18e5aeb4eaSagc * 3. Neither the name of the University nor the names of its contributors
1961f28255Scgd * may be used to endorse or promote products derived from this software
2061f28255Scgd * without specific prior written permission.
2161f28255Scgd *
2261f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2361f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2461f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2561f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2661f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2761f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2861f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2961f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3061f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3161f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3261f28255Scgd * SUCH DAMAGE.
3361f28255Scgd */
3461f28255Scgd
3561f28255Scgd /*
3661f28255Scgd * Copyright (c) 1987 by Ed James, UC Berkeley. All rights reserved.
3761f28255Scgd *
3861f28255Scgd * Copy permission is hereby granted provided that this notice is
3961f28255Scgd * retained on all partial or complete copies.
4061f28255Scgd *
4161f28255Scgd * For more info on this and all of my stuff, mail edjames@berkeley.edu.
4261f28255Scgd */
4361f28255Scgd
44ca57cf90Slukem #include <sys/cdefs.h>
4561f28255Scgd #ifndef lint
462fe2731dSlukem __COPYRIGHT("@(#) Copyright (c) 1990, 1993\
472fe2731dSlukem The Regents of the University of California. All rights reserved.");
4861f28255Scgd #endif /* not lint */
4961f28255Scgd
5061f28255Scgd #ifndef lint
51101657d1Scgd #if 0
52101657d1Scgd static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 5/31/93";
53101657d1Scgd #else
54*abca1099Srillig __RCSID("$NetBSD: main.c,v 1.25 2021/05/02 12:50:43 rillig Exp $");
55101657d1Scgd #endif
5661f28255Scgd #endif /* not lint */
5761f28255Scgd
58220f2cd3Sdholland #include <stdio.h>
59220f2cd3Sdholland #include <stdlib.h>
60220f2cd3Sdholland #include <string.h>
61220f2cd3Sdholland #include <signal.h>
62220f2cd3Sdholland #include <termios.h>
63220f2cd3Sdholland #include <getopt.h>
64220f2cd3Sdholland #include <err.h>
65220f2cd3Sdholland
6661f28255Scgd #include "pathnames.h"
67220f2cd3Sdholland #include "def.h"
68220f2cd3Sdholland #include "struct.h"
69220f2cd3Sdholland #include "extern.h"
70220f2cd3Sdholland #include "tunable.h"
7161f28255Scgd
72a3807f8fSchristos extern FILE *yyin;
73ca57cf90Slukem
747a2ed764Sdholland static int read_file(const char *);
757a2ed764Sdholland static const char *default_game(void);
767a2ed764Sdholland static const char *okay_game(const char *);
777a2ed764Sdholland static int list_games(void);
7833e21aacSdholland static void quit(int);
797a2ed764Sdholland
80ca57cf90Slukem int
main(int argc,char * argv[])814931378aSjmc main(int argc, char *argv[])
8261f28255Scgd {
83d64494c7Sdholland unsigned long seed;
8461f28255Scgd int f_usage = 0, f_list = 0, f_showscore = 0;
8561f28255Scgd int f_printpath = 0;
86a9d35e83Shubertf const char *file = NULL;
87c5a4ae7aSmjl int ch;
88ca2582cfSmycroft struct sigaction sa;
8961f28255Scgd #ifdef BSD
9061f28255Scgd struct itimerval itv;
9161f28255Scgd #endif
9261f28255Scgd
93d5f85ed9Shubertf /* Open the score file then revoke setgid privileges */
94d5f85ed9Shubertf open_score_file();
95b0282a1eSrpaulo (void)setgid(getgid());
96d5f85ed9Shubertf
97d64494c7Sdholland start_time = time(NULL);
98d64494c7Sdholland seed = start_time;
9961f28255Scgd
100ca1e1e9cSjnemeth while ((ch = getopt(argc, argv, ":u?lstpg:f:r:")) != -1) {
101c5a4ae7aSmjl switch (ch) {
10261f28255Scgd case '?':
10361f28255Scgd case 'u':
104c5a4ae7aSmjl default:
105ac6377faSdholland f_usage = 1;
10661f28255Scgd break;
10761f28255Scgd case 'l':
108ac6377faSdholland f_list = 1;
10961f28255Scgd break;
11061f28255Scgd case 's':
11161f28255Scgd case 't':
112ac6377faSdholland f_showscore = 1;
11361f28255Scgd break;
11461f28255Scgd case 'p':
115ac6377faSdholland f_printpath = 1;
11661f28255Scgd break;
11761f28255Scgd case 'r':
118c5a4ae7aSmjl seed = atoi(optarg);
11961f28255Scgd break;
12061f28255Scgd case 'f':
12161f28255Scgd case 'g':
122c5a4ae7aSmjl file = optarg;
12361f28255Scgd break;
124c5a4ae7aSmjl }
125c5a4ae7aSmjl }
1264931378aSjmc if (optind < argc)
127ac6377faSdholland f_usage = 1;
128d64494c7Sdholland srandom(seed);
12961f28255Scgd
13061f28255Scgd if (f_usage)
131b0282a1eSrpaulo (void)fprintf(stderr,
13261f28255Scgd "Usage: %s -[u?lstp] [-[gf] game_name] [-r random seed]\n",
1334931378aSjmc argv[0]);
13461f28255Scgd if (f_showscore)
135b0282a1eSrpaulo (void)log_score(1);
13661f28255Scgd if (f_list)
137b0282a1eSrpaulo (void)list_games();
13861f28255Scgd if (f_printpath) {
13961f28255Scgd char buf[100];
14061f28255Scgd
141ca1e1e9cSjnemeth (void)strlcpy(buf, _PATH_GAMES, 100);
142b0282a1eSrpaulo (void)puts(buf);
14361f28255Scgd }
14461f28255Scgd
14561f28255Scgd if (f_usage || f_showscore || f_list || f_printpath)
14661f28255Scgd exit(0);
14761f28255Scgd
14861f28255Scgd if (file == NULL)
14961f28255Scgd file = default_game();
15061f28255Scgd else
15161f28255Scgd file = okay_game(file);
15261f28255Scgd
15361f28255Scgd if (file == NULL || read_file(file) < 0)
15461f28255Scgd exit(1);
15561f28255Scgd
15661f28255Scgd init_gr();
15761f28255Scgd setup_screen(sp);
15861f28255Scgd
159ebb2bc86Sdholland addplane();
16061f28255Scgd
161b0282a1eSrpaulo (void)signal(SIGINT, quit);
162b0282a1eSrpaulo (void)signal(SIGQUIT, quit);
16361f28255Scgd #ifdef BSD
164b0282a1eSrpaulo (void)signal(SIGTSTP, SIG_IGN);
16561f28255Scgd #endif
166b0282a1eSrpaulo (void)signal(SIGHUP, log_score_quit);
167b0282a1eSrpaulo (void)signal(SIGTERM, log_score_quit);
16861f28255Scgd
169b0282a1eSrpaulo (void)tcgetattr(fileno(stdin), &tty_start);
170ca2582cfSmycroft tty_new = tty_start;
171ca2582cfSmycroft tty_new.c_lflag &= ~(ICANON|ECHO);
1720056c879Shubertf tty_new.c_iflag |= ICRNL;
17361f28255Scgd tty_new.c_cc[VMIN] = 1;
17461f28255Scgd tty_new.c_cc[VTIME] = 0;
175b0282a1eSrpaulo (void)tcsetattr(fileno(stdin), TCSADRAIN, &tty_new);
17661f28255Scgd
177ca2582cfSmycroft sa.sa_handler = update;
178b0282a1eSrpaulo (void)sigemptyset(&sa.sa_mask);
179b0282a1eSrpaulo (void)sigaddset(&sa.sa_mask, SIGALRM);
180b0282a1eSrpaulo (void)sigaddset(&sa.sa_mask, SIGINT);
181ca2582cfSmycroft sa.sa_flags = 0;
182b0282a1eSrpaulo (void)sigaction(SIGALRM, &sa, (struct sigaction *)0);
18361f28255Scgd
18461f28255Scgd #ifdef BSD
18561f28255Scgd itv.it_value.tv_sec = 0;
18661f28255Scgd itv.it_value.tv_usec = 1;
18761f28255Scgd itv.it_interval.tv_sec = sp->update_secs;
18861f28255Scgd itv.it_interval.tv_usec = 0;
189b0282a1eSrpaulo (void)setitimer(ITIMER_REAL, &itv, NULL);
19061f28255Scgd #endif
19161f28255Scgd #ifdef SYSV
19261f28255Scgd alarm(sp->update_secs);
19361f28255Scgd #endif
19461f28255Scgd
19561f28255Scgd for (;;) {
19661f28255Scgd if (getcommand() != 1)
19761f28255Scgd planewin();
19861f28255Scgd else {
19961f28255Scgd #ifdef BSD
20061f28255Scgd itv.it_value.tv_sec = 0;
20161f28255Scgd itv.it_value.tv_usec = 0;
202b0282a1eSrpaulo (void)setitimer(ITIMER_REAL, &itv, NULL);
20361f28255Scgd #endif
20461f28255Scgd #ifdef SYSV
20561f28255Scgd alarm(0);
20661f28255Scgd #endif
20761f28255Scgd
208ca57cf90Slukem update(0);
20961f28255Scgd
21061f28255Scgd #ifdef BSD
21161f28255Scgd itv.it_value.tv_sec = sp->update_secs;
21261f28255Scgd itv.it_value.tv_usec = 0;
21361f28255Scgd itv.it_interval.tv_sec = sp->update_secs;
21461f28255Scgd itv.it_interval.tv_usec = 0;
215b0282a1eSrpaulo (void)setitimer(ITIMER_REAL, &itv, NULL);
21661f28255Scgd #endif
21761f28255Scgd #ifdef SYSV
21861f28255Scgd alarm(sp->update_secs);
21961f28255Scgd #endif
22061f28255Scgd }
22161f28255Scgd }
22261f28255Scgd }
22361f28255Scgd
2247a2ed764Sdholland static int
read_file(const char * s)2254931378aSjmc read_file(const char *s)
22661f28255Scgd {
22761f28255Scgd int retval;
22861f28255Scgd
2294931378aSjmc filename = s;
23061f28255Scgd yyin = fopen(s, "r");
23161f28255Scgd if (yyin == NULL) {
23236b47bd3Slukem warn("fopen %s", s);
23361f28255Scgd return (-1);
23461f28255Scgd }
23561f28255Scgd retval = yyparse();
236b0282a1eSrpaulo (void)fclose(yyin);
23761f28255Scgd
23861f28255Scgd if (retval != 0)
23961f28255Scgd return (-1);
24061f28255Scgd else
24161f28255Scgd return (0);
24261f28255Scgd }
24361f28255Scgd
2447a2ed764Sdholland static const char *
default_game(void)2454931378aSjmc default_game(void)
24661f28255Scgd {
24761f28255Scgd FILE *fp;
24861f28255Scgd static char file[256];
24961f28255Scgd char line[256], games[256];
25061f28255Scgd
251ca1e1e9cSjnemeth (void)strlcpy(games, _PATH_GAMES, 256);
252ca1e1e9cSjnemeth (void)strlcat(games, GAMES, 256);
25361f28255Scgd
25461f28255Scgd if ((fp = fopen(games, "r")) == NULL) {
25536b47bd3Slukem warn("fopen %s", games);
25661f28255Scgd return (NULL);
25761f28255Scgd }
25861f28255Scgd if (fgets(line, sizeof(line), fp) == NULL) {
259b0282a1eSrpaulo (void)fprintf(stderr, "%s: no default game available\n", games);
260f09b76beSchristos fclose(fp);
26161f28255Scgd return (NULL);
26261f28255Scgd }
263b0282a1eSrpaulo (void)fclose(fp);
26461f28255Scgd line[strlen(line) - 1] = '\0';
265ca1e1e9cSjnemeth (void)strlcpy(file, _PATH_GAMES, 256);
266ca1e1e9cSjnemeth (void)strlcat(file, line, 256);
26761f28255Scgd return (file);
26861f28255Scgd }
26961f28255Scgd
2707a2ed764Sdholland static const char *
okay_game(const char * s)2714931378aSjmc okay_game(const char *s)
27261f28255Scgd {
27361f28255Scgd FILE *fp;
27461f28255Scgd static char file[256];
275a9d35e83Shubertf const char *ret = NULL;
276a9d35e83Shubertf char line[256], games[256];
27761f28255Scgd
278ca1e1e9cSjnemeth (void)strlcpy(games, _PATH_GAMES, 256);
279ca1e1e9cSjnemeth (void)strlcat(games, GAMES, 256);
28061f28255Scgd
28161f28255Scgd if ((fp = fopen(games, "r")) == NULL) {
28236b47bd3Slukem warn("fopen %s", games);
28361f28255Scgd return (NULL);
28461f28255Scgd }
28561f28255Scgd while (fgets(line, sizeof(line), fp) != NULL) {
28661f28255Scgd line[strlen(line) - 1] = '\0';
28761f28255Scgd if (strcmp(s, line) == 0) {
288ca1e1e9cSjnemeth (void)strlcpy(file, _PATH_GAMES, 256);
289ca1e1e9cSjnemeth (void)strlcat(file, line, 256);
29061f28255Scgd ret = file;
29161f28255Scgd break;
29261f28255Scgd }
29361f28255Scgd }
294b0282a1eSrpaulo (void)fclose(fp);
29561f28255Scgd if (ret == NULL) {
29661f28255Scgd test_mode = 1;
29761f28255Scgd ret = s;
298b0282a1eSrpaulo (void)fprintf(stderr, "%s: %s: game not found\n", games, s);
299b0282a1eSrpaulo (void)fprintf(stderr, "Your score will not be logged.\n");
300b0282a1eSrpaulo (void)sleep(2); /* give the guy time to read it */
30161f28255Scgd }
30261f28255Scgd return (ret);
30361f28255Scgd }
30461f28255Scgd
3057a2ed764Sdholland static int
list_games(void)3064931378aSjmc list_games(void)
30761f28255Scgd {
30861f28255Scgd FILE *fp;
30961f28255Scgd char line[256], games[256];
31061f28255Scgd int num_games = 0;
31161f28255Scgd
312ca1e1e9cSjnemeth (void)strlcpy(games, _PATH_GAMES, 256);
313ca1e1e9cSjnemeth (void)strlcat(games, GAMES, 256);
31461f28255Scgd
31561f28255Scgd if ((fp = fopen(games, "r")) == NULL) {
31636b47bd3Slukem warn("fopen %s", games);
31761f28255Scgd return (-1);
31861f28255Scgd }
319b0282a1eSrpaulo (void)puts("available games:");
32061f28255Scgd while (fgets(line, sizeof(line), fp) != NULL) {
321b0282a1eSrpaulo (void)printf(" %s", line);
32261f28255Scgd num_games++;
32361f28255Scgd }
324b0282a1eSrpaulo (void)fclose(fp);
32561f28255Scgd if (num_games == 0) {
326b0282a1eSrpaulo (void)fprintf(stderr, "%s: no games available\n", games);
32761f28255Scgd return (-1);
32861f28255Scgd }
32961f28255Scgd return (0);
33061f28255Scgd }
33133e21aacSdholland
33233e21aacSdholland /* ARGSUSED */
33333e21aacSdholland static void
quit(int dummy __unused)33433e21aacSdholland quit(int dummy __unused)
33533e21aacSdholland {
33633e21aacSdholland int c;
33733e21aacSdholland #ifdef BSD
33833e21aacSdholland struct itimerval itv;
33933e21aacSdholland #endif
34033e21aacSdholland ioaskquit();
34133e21aacSdholland c = getAChar();
34233e21aacSdholland if (c == EOF || c == 'y') {
34333e21aacSdholland /* disable timer */
34433e21aacSdholland #ifdef BSD
34533e21aacSdholland itv.it_value.tv_sec = 0;
34633e21aacSdholland itv.it_value.tv_usec = 0;
34733e21aacSdholland (void)setitimer(ITIMER_REAL, &itv, NULL);
34833e21aacSdholland #endif
34933e21aacSdholland #ifdef SYSV
35033e21aacSdholland alarm(0);
35133e21aacSdholland #endif
35233e21aacSdholland shutdown_gr();
35333e21aacSdholland (void)log_score(0);
35433e21aacSdholland exit(0);
35533e21aacSdholland }
35633e21aacSdholland ionoquit();
35733e21aacSdholland }
358