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