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