1 /* $OpenBSD: main.c,v 1.29 2016/03/07 13:48:25 jmc 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 <unistd.h> 51 52 #include "extern.h" 53 #include "pathnames.h" 54 55 int 56 main(int argc, char *argv[]) 57 { 58 int ch; 59 int f_usage = 0, f_list = 0, f_showscore = 0; 60 int f_printpath = 0; 61 const char *file = NULL; 62 char *seed; 63 struct sigaction sa; 64 struct itimerval itv; 65 66 if (pledge("stdio rpath wpath cpath flock tty", NULL) == -1) 67 err(1, "pledge"); 68 open_score_file(); 69 70 start_time = time(0); 71 makenoise = 1; 72 seed = NULL; 73 74 while ((ch = getopt(argc, argv, "f:g:hlpqr:st")) != -1) { 75 switch (ch) { 76 case 'f': 77 case 'g': 78 file = optarg; 79 break; 80 case 'l': 81 f_list = 1; 82 break; 83 case 'p': 84 f_printpath = 1; 85 break; 86 case 'q': 87 makenoise = 0; 88 break; 89 case 'r': 90 seed = optarg; 91 break; 92 case 's': 93 case 't': 94 f_showscore = 1; 95 break; 96 case 'h': 97 default: 98 f_usage = 1; 99 break; 100 } 101 } 102 argc -= optind; 103 argv += optind; 104 105 if (argc > 0) 106 f_usage = 1; 107 108 if (seed != NULL) 109 setseed(seed); 110 111 if (f_usage) 112 fprintf(stderr, 113 "usage: %s [-lpqst] [-f game] [-g game] [-r seed]\n", 114 getprogname()); 115 if (f_showscore) 116 log_score(1); 117 if (f_list) 118 list_games(); 119 if (f_printpath) { 120 size_t len; 121 char buf[256]; 122 123 strlcpy(buf, _PATH_GAMES, sizeof buf); 124 len = strlen(buf); 125 if (len != 0 && buf[len - 1] == '/') 126 buf[len - 1] = '\0'; 127 puts(buf); 128 } 129 130 if (f_usage || f_showscore || f_list || f_printpath) 131 return 0; 132 133 if (file == NULL) 134 file = default_game(); 135 else 136 file = okay_game(file); 137 138 if (file == NULL || read_file(file) < 0) 139 return 1; 140 141 setup_screen(sp); 142 143 addplane(); 144 145 signal(SIGINT, quit); 146 signal(SIGQUIT, quit); 147 signal(SIGTSTP, SIG_IGN); 148 signal(SIGSTOP, SIG_IGN); 149 signal(SIGHUP, log_score_quit); 150 signal(SIGTERM, log_score_quit); 151 152 tcgetattr(fileno(stdin), &tty_start); 153 tty_new = tty_start; 154 tty_new.c_lflag &= ~(ICANON|ECHO); 155 tty_new.c_iflag |= ICRNL; 156 tty_new.c_cc[VMIN] = 1; 157 tty_new.c_cc[VTIME] = 0; 158 tcsetattr(fileno(stdin), TCSADRAIN, &tty_new); 159 160 memset(&sa, 0, sizeof sa); 161 sa.sa_handler = update; 162 sigemptyset(&sa.sa_mask); 163 sigaddset(&sa.sa_mask, SIGALRM); 164 sigaddset(&sa.sa_mask, SIGINT); 165 sa.sa_flags = 0; 166 sigaction(SIGALRM, &sa, (struct sigaction *)0); 167 168 itv.it_value.tv_sec = 0; 169 itv.it_value.tv_usec = 1; 170 itv.it_interval.tv_sec = sp->update_secs; 171 itv.it_interval.tv_usec = 0; 172 setitimer(ITIMER_REAL, &itv, NULL); 173 174 for (;;) { 175 if (getcommand() != 1) 176 planewin(); 177 else { 178 itv.it_value.tv_sec = 0; 179 itv.it_value.tv_usec = 0; 180 setitimer(ITIMER_REAL, &itv, NULL); 181 182 update(0); 183 184 itv.it_value.tv_sec = sp->update_secs; 185 itv.it_value.tv_usec = 0; 186 itv.it_interval.tv_sec = sp->update_secs; 187 itv.it_interval.tv_usec = 0; 188 setitimer(ITIMER_REAL, &itv, NULL); 189 } 190 } 191 } 192 193 int 194 read_file(const char *s) 195 { 196 extern FILE *yyin; 197 int retval; 198 199 file = s; 200 yyin = fopen(s, "r"); 201 if (yyin == NULL) { 202 warn("fopen %s", s); 203 return (-1); 204 } 205 retval = yyparse(); 206 fclose(yyin); 207 208 if (retval != 0) 209 return (-1); 210 else 211 return (0); 212 } 213 214 const char * 215 default_game(void) 216 { 217 FILE *fp; 218 static char file[256]; 219 char line[256], games[256]; 220 221 strlcpy(games, _PATH_GAMES, sizeof games); 222 strlcat(games, GAMES, sizeof games); 223 224 if ((fp = fopen(games, "r")) == NULL) { 225 warn("fopen %s", games); 226 return (NULL); 227 } 228 if (fgets(line, sizeof(line), fp) == NULL) { 229 warnx("%s: no default game available", games); 230 fclose(fp); 231 return (NULL); 232 } 233 fclose(fp); 234 235 line[strcspn(line, "\n")] = '\0'; 236 if (strlen(line) + strlen(_PATH_GAMES) >= sizeof(file)) { 237 warnx("default game name too long"); 238 return (NULL); 239 } 240 strlcpy(file, _PATH_GAMES, sizeof file); 241 strlcat(file, line, sizeof file); 242 return (file); 243 } 244 245 const char * 246 okay_game(const char *s) 247 { 248 FILE *fp; 249 static char file[256]; 250 const char *ret = NULL; 251 char line[256], games[256]; 252 253 strlcpy(games, _PATH_GAMES, sizeof games); 254 strlcat(games, GAMES, sizeof games); 255 256 if ((fp = fopen(games, "r")) == NULL) { 257 warn("fopen %s", games); 258 return (NULL); 259 } 260 while (fgets(line, sizeof(line), fp) != NULL) { 261 line[strcspn(line, "\n")] = '\0'; 262 if (strcmp(s, line) == 0) { 263 if (strlen(line) + strlen(_PATH_GAMES) >= sizeof(file)) { 264 warnx("game name too long"); 265 return (NULL); 266 } 267 strlcpy(file, _PATH_GAMES, sizeof file); 268 strlcat(file, line, sizeof file); 269 ret = file; 270 break; 271 } 272 } 273 fclose(fp); 274 if (ret == NULL) { 275 test_mode = 1; 276 ret = s; 277 fprintf(stderr, "%s: %s: game not found\n", games, s); 278 fprintf(stderr, "Your score will not be logged.\n"); 279 sleep(2); /* give the guy time to read it */ 280 } 281 return (ret); 282 } 283 284 int 285 list_games(void) 286 { 287 FILE *fp; 288 char line[256], games[256]; 289 int num_games = 0; 290 291 strlcpy(games, _PATH_GAMES, sizeof games); 292 strlcat(games, GAMES, sizeof games); 293 294 if ((fp = fopen(games, "r")) == NULL) { 295 warn("fopen %s", games); 296 return (-1); 297 } 298 puts("available games:"); 299 while (fgets(line, sizeof(line), fp) != NULL) { 300 line[strcspn(line, "\n")] = '\0'; 301 printf(" %s\n", line); 302 num_games++; 303 } 304 fclose(fp); 305 if (num_games == 0) { 306 fprintf(stderr, "%s: no games available\n", games); 307 return (-1); 308 } 309 return (0); 310 } 311