1 /* $OpenBSD: main.c,v 1.31 2021/10/23 11:22:48 mestre Exp $ */ 2 /* $NetBSD: main.c,v 1.4 1995/04/27 21:22:25 mycroft Exp $ */ 3 4 /*- 5 * Copyright (c) 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Ed James. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 /* 37 * Copyright (c) 1987 by Ed James, UC Berkeley. All rights reserved. 38 * 39 * Copy permission is hereby granted provided that this notice is 40 * retained on all partial or complete copies. 41 * 42 * For more info on this and all of my stuff, mail edjames@berkeley.edu. 43 */ 44 45 #include <err.h> 46 #include <signal.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <termios.h> 50 #include <time.h> 51 #include <unistd.h> 52 53 #include "extern.h" 54 #include "pathnames.h" 55 56 int 57 main(int argc, char *argv[]) 58 { 59 int ch; 60 int f_usage = 0, f_list = 0, f_showscore = 0; 61 int f_printpath = 0; 62 const char *file = NULL; 63 char *seed; 64 struct sigaction sa; 65 struct itimerval itv; 66 67 open_score_file(); 68 69 start_time = time(0); 70 makenoise = 1; 71 seed = NULL; 72 73 while ((ch = getopt(argc, argv, "f:g:hlpqr:st")) != -1) { 74 switch (ch) { 75 case 'f': 76 case 'g': 77 file = optarg; 78 break; 79 case 'l': 80 f_list = 1; 81 break; 82 case 'p': 83 f_printpath = 1; 84 break; 85 case 'q': 86 makenoise = 0; 87 break; 88 case 'r': 89 seed = optarg; 90 break; 91 case 's': 92 case 't': 93 f_showscore = 1; 94 break; 95 case 'h': 96 default: 97 f_usage = 1; 98 break; 99 } 100 } 101 argc -= optind; 102 argv += optind; 103 104 if (argc > 0) 105 f_usage = 1; 106 107 if (seed != NULL) 108 setseed(seed); 109 110 if (f_usage) 111 fprintf(stderr, 112 "usage: %s [-lpqst] [-f game] [-g game] [-r seed]\n", 113 getprogname()); 114 if (f_showscore) 115 log_score(1); 116 if (f_list) 117 list_games(); 118 if (f_printpath) { 119 size_t len; 120 char buf[256]; 121 122 strlcpy(buf, _PATH_GAMES, sizeof buf); 123 len = strlen(buf); 124 if (len != 0 && buf[len - 1] == '/') 125 buf[len - 1] = '\0'; 126 puts(buf); 127 } 128 129 if (f_usage || f_showscore || f_list || f_printpath) 130 return 0; 131 132 if (file == NULL) 133 file = default_game(); 134 else 135 file = okay_game(file); 136 137 if (file == NULL || read_file(file) < 0) 138 return 1; 139 140 setup_screen(sp); 141 142 if (pledge("stdio rpath wpath cpath flock tty", NULL) == -1) 143 err(1, "pledge"); 144 145 addplane(); 146 147 signal(SIGINT, quit); 148 signal(SIGQUIT, quit); 149 signal(SIGTSTP, SIG_IGN); 150 signal(SIGSTOP, SIG_IGN); 151 signal(SIGHUP, log_score_quit); 152 signal(SIGTERM, log_score_quit); 153 154 tcgetattr(fileno(stdin), &tty_start); 155 tty_new = tty_start; 156 tty_new.c_lflag &= ~(ICANON|ECHO); 157 tty_new.c_iflag |= ICRNL; 158 tty_new.c_cc[VMIN] = 1; 159 tty_new.c_cc[VTIME] = 0; 160 tcsetattr(fileno(stdin), TCSADRAIN, &tty_new); 161 162 memset(&sa, 0, sizeof sa); 163 sa.sa_handler = update; 164 sigemptyset(&sa.sa_mask); 165 sigaddset(&sa.sa_mask, SIGALRM); 166 sigaddset(&sa.sa_mask, SIGINT); 167 sa.sa_flags = 0; 168 sigaction(SIGALRM, &sa, (struct sigaction *)0); 169 170 itv.it_value.tv_sec = 0; 171 itv.it_value.tv_usec = 1; 172 itv.it_interval.tv_sec = sp->update_secs; 173 itv.it_interval.tv_usec = 0; 174 setitimer(ITIMER_REAL, &itv, NULL); 175 176 for (;;) { 177 if (getcommand() != 1) 178 planewin(); 179 else { 180 itv.it_value.tv_sec = 0; 181 itv.it_value.tv_usec = 0; 182 setitimer(ITIMER_REAL, &itv, NULL); 183 184 update(0); 185 186 itv.it_value.tv_sec = sp->update_secs; 187 itv.it_value.tv_usec = 0; 188 itv.it_interval.tv_sec = sp->update_secs; 189 itv.it_interval.tv_usec = 0; 190 setitimer(ITIMER_REAL, &itv, NULL); 191 } 192 } 193 } 194 195 int 196 read_file(const char *s) 197 { 198 extern FILE *yyin; 199 int retval; 200 201 file = s; 202 yyin = fopen(s, "r"); 203 if (yyin == NULL) { 204 warn("fopen %s", s); 205 return (-1); 206 } 207 retval = yyparse(); 208 fclose(yyin); 209 210 if (retval != 0) 211 return (-1); 212 else 213 return (0); 214 } 215 216 const char * 217 default_game(void) 218 { 219 FILE *fp; 220 static char file[256]; 221 char line[256], games[256]; 222 223 strlcpy(games, _PATH_GAMES, sizeof games); 224 strlcat(games, GAMES, sizeof games); 225 226 if ((fp = fopen(games, "r")) == NULL) { 227 warn("fopen %s", games); 228 return (NULL); 229 } 230 if (fgets(line, sizeof(line), fp) == NULL) { 231 warnx("%s: no default game available", games); 232 fclose(fp); 233 return (NULL); 234 } 235 fclose(fp); 236 237 line[strcspn(line, "\n")] = '\0'; 238 if (strlen(line) + strlen(_PATH_GAMES) >= sizeof(file)) { 239 warnx("default game name too long"); 240 return (NULL); 241 } 242 strlcpy(file, _PATH_GAMES, sizeof file); 243 strlcat(file, line, sizeof file); 244 return (file); 245 } 246 247 const char * 248 okay_game(const char *s) 249 { 250 FILE *fp; 251 static char file[256]; 252 const char *ret = NULL; 253 char line[256], games[256]; 254 255 strlcpy(games, _PATH_GAMES, sizeof games); 256 strlcat(games, GAMES, sizeof games); 257 258 if ((fp = fopen(games, "r")) == NULL) { 259 warn("fopen %s", games); 260 return (NULL); 261 } 262 while (fgets(line, sizeof(line), fp) != NULL) { 263 line[strcspn(line, "\n")] = '\0'; 264 if (strcmp(s, line) == 0) { 265 if (strlen(line) + strlen(_PATH_GAMES) >= sizeof(file)) { 266 warnx("game name too long"); 267 return (NULL); 268 } 269 strlcpy(file, _PATH_GAMES, sizeof file); 270 strlcat(file, line, sizeof file); 271 ret = file; 272 break; 273 } 274 } 275 fclose(fp); 276 if (ret == NULL) { 277 test_mode = 1; 278 ret = s; 279 fprintf(stderr, "%s: %s: game not found\n", games, s); 280 fprintf(stderr, "Your score will not be logged.\n"); 281 sleep(2); /* give the guy time to read it */ 282 } 283 return (ret); 284 } 285 286 int 287 list_games(void) 288 { 289 FILE *fp; 290 char line[256], games[256]; 291 int num_games = 0; 292 293 strlcpy(games, _PATH_GAMES, sizeof games); 294 strlcat(games, GAMES, sizeof games); 295 296 if ((fp = fopen(games, "r")) == NULL) { 297 warn("fopen %s", games); 298 return (-1); 299 } 300 puts("available games:"); 301 while (fgets(line, sizeof(line), fp) != NULL) { 302 line[strcspn(line, "\n")] = '\0'; 303 printf(" %s\n", line); 304 num_games++; 305 } 306 fclose(fp); 307 if (num_games == 0) { 308 fprintf(stderr, "%s: no games available\n", games); 309 return (-1); 310 } 311 return (0); 312 } 313