File: | src/games/worms/worms.c |
Warning: | line 313, column 9 Array access results in a null pointer dereference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: worms.c,v 1.30 2021/10/23 11:22:49 mestre Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 1980, 1993 | |||
5 | * The Regents of the University of California. All rights reserved. | |||
6 | * | |||
7 | * Redistribution and use in source and binary forms, with or without | |||
8 | * modification, are permitted provided that the following conditions | |||
9 | * are met: | |||
10 | * 1. Redistributions of source code must retain the above copyright | |||
11 | * notice, this list of conditions and the following disclaimer. | |||
12 | * 2. Redistributions in binary form must reproduce the above copyright | |||
13 | * notice, this list of conditions and the following disclaimer in the | |||
14 | * documentation and/or other materials provided with the distribution. | |||
15 | * 3. Neither the name of the University nor the names of its contributors | |||
16 | * may be used to endorse or promote products derived from this software | |||
17 | * without specific prior written permission. | |||
18 | * | |||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
29 | * SUCH DAMAGE. | |||
30 | */ | |||
31 | ||||
32 | /* | |||
33 | * | |||
34 | * @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@ | |||
35 | * @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@ | |||
36 | * @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@ | |||
37 | * @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ | |||
38 | * @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@ | |||
39 | * @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ | |||
40 | * @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ | |||
41 | * @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@ | |||
42 | * @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@ | |||
43 | * | |||
44 | * Eric P. Scott | |||
45 | * Caltech High Energy Physics | |||
46 | * October, 1980 | |||
47 | * | |||
48 | */ | |||
49 | #include <curses.h> | |||
50 | #include <err.h> | |||
51 | #include <signal.h> | |||
52 | #include <stdlib.h> | |||
53 | #include <termios.h> | |||
54 | #include <unistd.h> | |||
55 | ||||
56 | static const struct options { | |||
57 | int nopts; | |||
58 | int opts[3]; | |||
59 | } | |||
60 | normal[8] = { | |||
61 | { 3, { 7, 0, 1 } }, | |||
62 | { 3, { 0, 1, 2 } }, | |||
63 | { 3, { 1, 2, 3 } }, | |||
64 | { 3, { 2, 3, 4 } }, | |||
65 | { 3, { 3, 4, 5 } }, | |||
66 | { 3, { 4, 5, 6 } }, | |||
67 | { 3, { 5, 6, 7 } }, | |||
68 | { 3, { 6, 7, 0 } } | |||
69 | }, upper[8] = { | |||
70 | { 1, { 1, 0, 0 } }, | |||
71 | { 2, { 1, 2, 0 } }, | |||
72 | { 0, { 0, 0, 0 } }, | |||
73 | { 0, { 0, 0, 0 } }, | |||
74 | { 0, { 0, 0, 0 } }, | |||
75 | { 2, { 4, 5, 0 } }, | |||
76 | { 1, { 5, 0, 0 } }, | |||
77 | { 2, { 1, 5, 0 } } | |||
78 | }, | |||
79 | left[8] = { | |||
80 | { 0, { 0, 0, 0 } }, | |||
81 | { 0, { 0, 0, 0 } }, | |||
82 | { 0, { 0, 0, 0 } }, | |||
83 | { 2, { 2, 3, 0 } }, | |||
84 | { 1, { 3, 0, 0 } }, | |||
85 | { 2, { 3, 7, 0 } }, | |||
86 | { 1, { 7, 0, 0 } }, | |||
87 | { 2, { 7, 0, 0 } } | |||
88 | }, | |||
89 | right[8] = { | |||
90 | { 1, { 7, 0, 0 } }, | |||
91 | { 2, { 3, 7, 0 } }, | |||
92 | { 1, { 3, 0, 0 } }, | |||
93 | { 2, { 3, 4, 0 } }, | |||
94 | { 0, { 0, 0, 0 } }, | |||
95 | { 0, { 0, 0, 0 } }, | |||
96 | { 0, { 0, 0, 0 } }, | |||
97 | { 2, { 6, 7, 0 } } | |||
98 | }, | |||
99 | lower[8] = { | |||
100 | { 0, { 0, 0, 0 } }, | |||
101 | { 2, { 0, 1, 0 } }, | |||
102 | { 1, { 1, 0, 0 } }, | |||
103 | { 2, { 1, 5, 0 } }, | |||
104 | { 1, { 5, 0, 0 } }, | |||
105 | { 2, { 5, 6, 0 } }, | |||
106 | { 0, { 0, 0, 0 } }, | |||
107 | { 0, { 0, 0, 0 } } | |||
108 | }, | |||
109 | upleft[8] = { | |||
110 | { 0, { 0, 0, 0 } }, | |||
111 | { 0, { 0, 0, 0 } }, | |||
112 | { 0, { 0, 0, 0 } }, | |||
113 | { 0, { 0, 0, 0 } }, | |||
114 | { 0, { 0, 0, 0 } }, | |||
115 | { 1, { 3, 0, 0 } }, | |||
116 | { 2, { 1, 3, 0 } }, | |||
117 | { 1, { 1, 0, 0 } } | |||
118 | }, | |||
119 | upright[8] = { | |||
120 | { 2, { 3, 5, 0 } }, | |||
121 | { 1, { 3, 0, 0 } }, | |||
122 | { 0, { 0, 0, 0 } }, | |||
123 | { 0, { 0, 0, 0 } }, | |||
124 | { 0, { 0, 0, 0 } }, | |||
125 | { 0, { 0, 0, 0 } }, | |||
126 | { 0, { 0, 0, 0 } }, | |||
127 | { 1, { 5, 0, 0 } } | |||
128 | }, | |||
129 | lowleft[8] = { | |||
130 | { 3, { 7, 0, 1 } }, | |||
131 | { 0, { 0, 0, 0 } }, | |||
132 | { 0, { 0, 0, 0 } }, | |||
133 | { 1, { 1, 0, 0 } }, | |||
134 | { 2, { 1, 7, 0 } }, | |||
135 | { 1, { 7, 0, 0 } }, | |||
136 | { 0, { 0, 0, 0 } }, | |||
137 | { 0, { 0, 0, 0 } } | |||
138 | }, | |||
139 | lowright[8] = { | |||
140 | { 0, { 0, 0, 0 } }, | |||
141 | { 1, { 7, 0, 0 } }, | |||
142 | { 2, { 5, 7, 0 } }, | |||
143 | { 1, { 5, 0, 0 } }, | |||
144 | { 0, { 0, 0, 0 } }, | |||
145 | { 0, { 0, 0, 0 } }, | |||
146 | { 0, { 0, 0, 0 } }, | |||
147 | { 0, { 0, 0, 0 } } | |||
148 | }; | |||
149 | ||||
150 | static const char flavor[] = { | |||
151 | 'O', '*', '#', '$', '%', '0', '@', '~' | |||
152 | }; | |||
153 | static const short xinc[] = { | |||
154 | 1, 1, 1, 0, -1, -1, -1, 0 | |||
155 | }, yinc[] = { | |||
156 | -1, 0, 1, 1, 1, 0, -1, -1 | |||
157 | }; | |||
158 | static struct worm { | |||
159 | int orientation, head; | |||
160 | short *xpos, *ypos; | |||
161 | } *worm; | |||
162 | ||||
163 | volatile sig_atomic_t sig_caught = 0; | |||
164 | ||||
165 | void nomem(void); | |||
166 | void onsig(int); | |||
167 | ||||
168 | int | |||
169 | main(int argc, char *argv[]) | |||
170 | { | |||
171 | int x, y, h, n; | |||
172 | struct worm *w; | |||
173 | const struct options *op; | |||
174 | short *ip; | |||
175 | int CO, LI, last, bottom, ch, length, number, trail; | |||
176 | short **ref; | |||
177 | const char *field, *errstr; | |||
178 | struct timespec sleeptime; | |||
179 | struct termios term; | |||
180 | speed_t speed; | |||
181 | time_t delay = 0; | |||
182 | ||||
183 | /* set default delay based on terminal baud rate */ | |||
184 | if (tcgetattr(STDOUT_FILENO1, &term) == 0 && | |||
| ||||
185 | (speed = cfgetospeed(&term)) > B96009600) | |||
186 | delay = (speed / B96009600) - 1; | |||
187 | ||||
188 | length = 16; | |||
189 | number = 3; | |||
190 | trail = ' '; | |||
191 | field = NULL((void *)0); | |||
192 | while ((ch = getopt(argc, argv, "d:fhl:n:t")) != -1) | |||
193 | switch(ch) { | |||
194 | case 'd': | |||
195 | delay = (time_t)strtonum(optarg, 0, 1000, &errstr); | |||
196 | if (errstr) | |||
197 | errx(1, "delay (0-1000) is %s: %s", errstr, | |||
198 | optarg); | |||
199 | break; | |||
200 | case 'f': | |||
201 | field = "WORM"; | |||
202 | break; | |||
203 | case 'l': | |||
204 | length = strtonum(optarg, 2, 1024, &errstr); | |||
205 | if (errstr) | |||
206 | errx(1, "length (2-1024) is %s: %s", errstr, | |||
207 | optarg); | |||
208 | break; | |||
209 | case 'n': | |||
210 | number = strtonum(optarg, 1, 100, &errstr); | |||
211 | if (errstr) | |||
212 | errx(1, "number of worms (1-100) is %s: %s", | |||
213 | errstr, optarg); | |||
214 | break; | |||
215 | case 't': | |||
216 | trail = '.'; | |||
217 | break; | |||
218 | case 'h': | |||
219 | default: | |||
220 | (void)fprintf(stderr(&__sF[2]), "usage: %s [-ft] [-d delay] " | |||
221 | "[-l length] [-n number]\n", getprogname()); | |||
222 | return 1; | |||
223 | } | |||
224 | ||||
225 | /* Convert delay from ms -> ns */ | |||
226 | sleeptime.tv_sec = 0; | |||
227 | sleeptime.tv_nsec = delay * 500000; | |||
228 | timespecadd(&sleeptime, &sleeptime, &sleeptime)do { (&sleeptime)->tv_sec = (&sleeptime)->tv_sec + (&sleeptime)->tv_sec; (&sleeptime)->tv_nsec = (&sleeptime)->tv_nsec + (&sleeptime)->tv_nsec; if ((&sleeptime)->tv_nsec >= 1000000000L) { (& sleeptime)->tv_sec++; (&sleeptime)->tv_nsec -= 1000000000L ; } } while (0); | |||
229 | ||||
230 | if (!(worm = calloc(number, sizeof(struct worm)))) | |||
231 | nomem(); | |||
232 | initscr(); | |||
233 | ||||
234 | if (pledge("stdio tty", NULL((void *)0)) == -1) | |||
235 | err(1, "pledge"); | |||
236 | ||||
237 | curs_set(0); | |||
238 | CO = COLS; | |||
239 | LI = LINES; | |||
240 | last = CO - 1; | |||
241 | bottom = LI - 1; | |||
242 | if (!(ip = reallocarray(NULL((void *)0), LI, CO * sizeof(short))) || | |||
243 | !(ref = calloc(LI, sizeof(short *)))) { | |||
244 | endwin(); | |||
245 | nomem(); | |||
246 | } | |||
247 | for (n = 0; n < LI; ++n) { | |||
248 | ref[n] = ip; | |||
249 | ip += CO; | |||
250 | } | |||
251 | for (ip = ref[0], n = LI * CO; --n >= 0;) | |||
252 | *ip++ = 0; | |||
253 | for (n = number, w = &worm[0]; --n >= 0; w++) { | |||
254 | w->orientation = w->head = 0; | |||
255 | if (!(ip = calloc(length, sizeof(short)))) { | |||
256 | endwin(); | |||
257 | nomem(); | |||
258 | } | |||
259 | w->xpos = ip; | |||
260 | for (x = length; --x >= 0;) | |||
261 | *ip++ = -1; | |||
262 | if (!(ip = calloc(length, sizeof(short)))) { | |||
263 | endwin(); | |||
264 | nomem(); | |||
265 | } | |||
266 | w->ypos = ip; | |||
267 | for (y = length; --y >= 0;) | |||
268 | *ip++ = -1; | |||
269 | } | |||
270 | ||||
271 | (void)signal(SIGHUP1, onsig); | |||
272 | (void)signal(SIGINT2, onsig); | |||
273 | (void)signal(SIGQUIT3, onsig); | |||
274 | (void)signal(SIGSTOP17, onsig); | |||
275 | (void)signal(SIGTSTP18, onsig); | |||
276 | (void)signal(SIGTERM15, onsig); | |||
277 | ||||
278 | if (field
| |||
279 | const char *p = field; | |||
280 | ||||
281 | for (y = LI; --y >= 0;) { | |||
282 | for (x = CO; --x >= 0;) { | |||
283 | addch(*p++)waddch(stdscr,(*p++)); | |||
284 | if (!*p) | |||
285 | p = field; | |||
286 | } | |||
287 | refresh()wrefresh(stdscr); | |||
288 | } | |||
289 | } | |||
290 | for (;;) { | |||
291 | refresh()wrefresh(stdscr); | |||
292 | if (sig_caught) { | |||
293 | endwin(); | |||
294 | return 0; | |||
295 | } | |||
296 | nanosleep(&sleeptime, NULL((void *)0)); | |||
297 | for (n = 0, w = &worm[0]; n < number; n++, w++) { | |||
298 | if ((x = w->xpos[h = w->head]) < 0) { | |||
299 | mvaddch(y = w->ypos[h] = bottom,(wmove((stdscr),((y = w->ypos[h] = bottom)),((x = w->xpos [h] = 0))) == (-1) ? (-1) : waddch((stdscr),((flavor[n % sizeof (flavor)])))) | |||
300 | x = w->xpos[h] = 0,(wmove((stdscr),((y = w->ypos[h] = bottom)),((x = w->xpos [h] = 0))) == (-1) ? (-1) : waddch((stdscr),((flavor[n % sizeof (flavor)])))) | |||
301 | flavor[n % sizeof(flavor)])(wmove((stdscr),((y = w->ypos[h] = bottom)),((x = w->xpos [h] = 0))) == (-1) ? (-1) : waddch((stdscr),((flavor[n % sizeof (flavor)])))); | |||
302 | ref[y][x]++; | |||
303 | } | |||
304 | else | |||
305 | y = w->ypos[h]; | |||
306 | if (++h == length) | |||
307 | h = 0; | |||
308 | if (w->xpos[w->head = h] >= 0) { | |||
309 | int x1, y1; | |||
310 | ||||
311 | x1 = w->xpos[h]; | |||
312 | y1 = w->ypos[h]; | |||
313 | if (--ref[y1][x1] == 0) | |||
| ||||
314 | mvaddch(y1, x1, trail)(wmove((stdscr),((y1)),((x1))) == (-1) ? (-1) : waddch((stdscr ),((trail)))); | |||
315 | } | |||
316 | ||||
317 | if (x == 0) { | |||
318 | if (y == 0) | |||
319 | op = &upleft[w->orientation]; | |||
320 | else if (y == bottom) | |||
321 | op = &lowleft[w->orientation]; | |||
322 | else | |||
323 | op = &left[w->orientation]; | |||
324 | } else if (x == last) { | |||
325 | if (y == 0) | |||
326 | op = &upright[w->orientation]; | |||
327 | else if (y == bottom) | |||
328 | op = &lowright[w->orientation]; | |||
329 | else | |||
330 | op = &right[w->orientation]; | |||
331 | } else { | |||
332 | if (y == 0) | |||
333 | op = &upper[w->orientation]; | |||
334 | else if (y == bottom) | |||
335 | op = &lower[w->orientation]; | |||
336 | else | |||
337 | op = &normal[w->orientation]; | |||
338 | } | |||
339 | ||||
340 | switch (op->nopts) { | |||
341 | case 0: | |||
342 | endwin(); | |||
343 | return(1); | |||
344 | case 1: | |||
345 | w->orientation = op->opts[0]; | |||
346 | break; | |||
347 | default: | |||
348 | w->orientation = | |||
349 | op->opts[arc4random_uniform(op->nopts)]; | |||
350 | } | |||
351 | mvaddch(y += yinc[w->orientation],(wmove((stdscr),((y += yinc[w->orientation])),((x += xinc[ w->orientation]))) == (-1) ? (-1) : waddch((stdscr),((flavor [n % sizeof(flavor)])))) | |||
352 | x += xinc[w->orientation],(wmove((stdscr),((y += yinc[w->orientation])),((x += xinc[ w->orientation]))) == (-1) ? (-1) : waddch((stdscr),((flavor [n % sizeof(flavor)])))) | |||
353 | flavor[n % sizeof(flavor)])(wmove((stdscr),((y += yinc[w->orientation])),((x += xinc[ w->orientation]))) == (-1) ? (-1) : waddch((stdscr),((flavor [n % sizeof(flavor)])))); | |||
354 | ref[w->ypos[h] = y][w->xpos[h] = x]++; | |||
355 | } | |||
356 | } | |||
357 | } | |||
358 | ||||
359 | void | |||
360 | onsig(int signo) | |||
361 | { | |||
362 | sig_caught = 1; | |||
363 | } | |||
364 | ||||
365 | void | |||
366 | nomem(void) | |||
367 | { | |||
368 | errx(1, "not enough memory."); | |||
369 | } |