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