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