1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33: #include <sys/cdefs.h>
34: #ifndef lint
35: __RCSID("$NetBSD: driver.c,v 1.10 2004/01/27 20:30:29 jsm Exp $");
36: #endif
37:
38: # include <sys/ioctl.h>
39: # include <sys/stat.h>
40: # include <sys/time.h>
41: # include <err.h>
42: # include <errno.h>
43: # include <signal.h>
44: # include <stdlib.h>
45: # include <time.h>
46: # include <unistd.h>
47: # include "hunt.h"
48:
49: # ifndef pdp11
50: # define RN (((Seed = Seed * 11109 + 13849) >> 16) & 0xffff)
51: # else
52: # define RN ((Seed = Seed * 11109 + 13849) & 0x7fff)
53: # endif
54:
55: int Seed = 0;
56:
57:
58: SOCKET Daemon;
59: char *First_arg;
60: char *Last_arg;
61: # ifdef INTERNET
62: int Test_socket;
63: FLAG inetd_spawned;
64: FLAG standard_port = TRUE;
65: u_short sock_port;
66: u_short stat_port;
67: # define DAEMON_SIZE (sizeof Daemon)
68: # else
69: # define DAEMON_SIZE (sizeof Daemon - 1)
70: # endif
71:
72: static void clear_scores(void);
73: static int havechar(PLAYER *, int);
74: static void init(void);
75: int main(int, char *[], char *[]);
76: static void makeboots(void);
77: static void send_stats(void);
78: static void zap(PLAYER *, FLAG, int);
79:
80:
81:
82:
83:
84:
85: int
86: main(ac, av, ep)
87: int ac;
88: char **av, **ep;
89: {
90: PLAYER *pp;
91: # ifdef INTERNET
92: u_short msg;
93: short port_num, reply;
94: int namelen;
95: SOCKET test;
96: # endif
97: static FLAG first = TRUE;
98: static FLAG server = FALSE;
99: int c, i;
100: const int linger = 90 * 1000;
101:
102: First_arg = av[0];
103: if (ep == NULL || *ep == NULL)
104: ep = av + ac;
105: while (*ep)
106: ep++;
107: Last_arg = ep[-1] + strlen(ep[-1]);
108:
109: while ((c = getopt(ac, av, "sp:")) != -1) {
110: switch (c) {
111: case 's':
112: server = TRUE;
113: break;
114: # ifdef INTERNET
115: case 'p':
116: standard_port = FALSE;
117: Test_port = atoi(optarg);
118: break;
119: # endif
120: default:
121: erred:
122: fprintf(stderr, "Usage: %s [-s] [-p port]\n", av[0]);
123: exit(1);
124: }
125: }
126: if (optind < ac)
127: goto erred;
128:
129: init();
130:
131:
132: again:
133: do {
134: errno = 0;
135: while (poll(fdset, 3+MAXPL+MAXMON, INFTIM) < 0)
136: {
137: if (errno != EINTR)
138: # ifdef LOG
139: syslog(LOG_WARNING, "select: %m");
140: # else
141: warn("select");
142: # endif
143: errno = 0;
144: }
145: # ifdef INTERNET
146: if (fdset[2].revents & POLLIN) {
147: namelen = DAEMON_SIZE;
148: port_num = htons(sock_port);
149: (void) recvfrom(Test_socket, (char *) &msg, sizeof msg,
150: 0, (struct sockaddr *) &test, &namelen);
151: switch (ntohs(msg)) {
152: case C_MESSAGE:
153: if (Nplayer <= 0)
154: break;
155: reply = htons((u_short) Nplayer);
156: (void) sendto(Test_socket, (char *) &reply,
157: sizeof reply, 0,
158: (struct sockaddr *) &test, DAEMON_SIZE);
159: break;
160: case C_SCORES:
161: reply = htons(stat_port);
162: (void) sendto(Test_socket, (char *) &reply,
163: sizeof reply, 0,
164: (struct sockaddr *) &test, DAEMON_SIZE);
165: break;
166: case C_PLAYER:
167: case C_MONITOR:
168: if (msg == C_MONITOR && Nplayer <= 0)
169: break;
170: reply = htons(sock_port);
171: (void) sendto(Test_socket, (char *) &reply,
172: sizeof reply, 0,
173: (struct sockaddr *) &test, DAEMON_SIZE);
174: break;
175: }
176: }
177: # endif
178: {
179: for (pp = Player, i = 0; pp < End_player; pp++, i++)
180: if (havechar(pp, i + 3)) {
181: execute(pp);
182: pp->p_nexec++;
183: }
184: # ifdef MONITOR
185: for (pp = Monitor, i = 0; pp < End_monitor; pp++, i++)
186: if (havechar(pp, i + MAXPL + 3)) {
187: mon_execute(pp);
188: pp->p_nexec++;
189: }
190: # endif
191: moveshots();
192: for (pp = Player, i = 0; pp < End_player; )
193: if (pp->p_death[0] != '\0')
194: zap(pp, TRUE, i + 3);
195: else
196: pp++, i++;
197: # ifdef MONITOR
198: for (pp = Monitor, i = 0; pp < End_monitor; )
199: if (pp->p_death[0] != '\0')
200: zap(pp, FALSE, i + MAXPL + 3);
201: else
202: pp++, i++;
203: # endif
204: }
205: if (fdset[0].revents & POLLIN)
206: if (answer()) {
207: # ifdef INTERNET
208: if (first && standard_port)
209: faketalk();
210: # endif
211: first = FALSE;
212: }
213: if (fdset[1].revents & POLLIN)
214: send_stats();
215: for (pp = Player, i = 0; pp < End_player; pp++, i++) {
216: if (fdset[i + 3].revents & POLLIN)
217: sendcom(pp, READY, pp->p_nexec);
218: pp->p_nexec = 0;
219: (void) fflush(pp->p_output);
220: }
221: # ifdef MONITOR
222: for (pp = Monitor, i = 0; pp < End_monitor; pp++, i++) {
223: if (fdset[i + MAXPL + 3].revents & POLLIN)
224: sendcom(pp, READY, pp->p_nexec);
225: pp->p_nexec = 0;
226: (void) fflush(pp->p_output);
227: }
228: # endif
229: } while (Nplayer > 0);
230:
231: if (poll(fdset, 3+MAXPL+MAXMON, linger) > 0) {
232: goto again;
233: }
234: if (server) {
235: clear_scores();
236: makemaze();
237: clearwalls();
238: # ifdef BOOTS
239: makeboots();
240: # endif
241: first = TRUE;
242: goto again;
243: }
244:
245: # ifdef MONITOR
246: for (pp = Monitor, i = 0; pp < End_monitor; i++)
247: zap(pp, FALSE, i + MAXPL + 3);
248: # endif
249: cleanup(0);
250:
251: return(0);
252: }
253:
254:
255:
256:
257:
258: static void
259: init()
260: {
261: int i;
262: # ifdef INTERNET
263: SOCKET test_port;
264: int msg;
265: int len;
266: # endif
267:
268: # ifndef DEBUG
269: switch (fork()) {
270: case -1:
271: err(1, "fork");
272: case 0:
273: break;
274: default:
275: exit(0);
276: }
277: if (setsid() == -1)
278: err(1, "setsid");
279: (void) signal(SIGHUP, SIG_IGN);
280: (void) signal(SIGINT, SIG_IGN);
281: (void) signal(SIGQUIT, SIG_IGN);
282: (void) signal(SIGTERM, cleanup);
283: # endif
284:
285: (void) chdir("/var/tmp");
286: (void) umask(0);
287: (void) signal(SIGPIPE, SIG_IGN);
288:
289: # ifdef LOG
290: # ifdef SYSLOG_43
291: openlog("huntd", LOG_PID, LOG_DAEMON);
292: # endif
293: # ifdef SYSLOG_42
294: openlog("huntd", LOG_PID);
295: # endif
296: # endif
297:
298:
299:
300:
301: # ifdef INTERNET
302: Daemon.sin_family = SOCK_FAMILY;
303: Daemon.sin_addr.s_addr = INADDR_ANY;
304: Daemon.sin_port = 0;
305: # else
306: Daemon.sun_family = SOCK_FAMILY;
307: (void) strcpy(Daemon.sun_path, Stat_name);
308: # endif
309:
310: Status = socket(SOCK_FAMILY, SOCK_STREAM, 0);
311: if (bind(Status, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) {
312: if (errno == EADDRINUSE)
313: exit(0);
314: else {
315: # ifdef LOG
316: syslog(LOG_ERR, "bind: %m");
317: # else
318: warn("bind");
319: # endif
320: cleanup(1);
321: }
322: }
323: (void) listen(Status, 5);
324:
325: # ifdef INTERNET
326: len = sizeof (SOCKET);
327: if (getsockname(Status, (struct sockaddr *) &Daemon, &len) < 0) {
328: # ifdef LOG
329: syslog(LOG_ERR, "getsockname: %m");
330: # else
331: warn("getsockname");
332: # endif
333: exit(1);
334: }
335: stat_port = ntohs(Daemon.sin_port);
336: # endif
337:
338:
339:
340:
341: # ifdef INTERNET
342: Daemon.sin_family = SOCK_FAMILY;
343: Daemon.sin_addr.s_addr = INADDR_ANY;
344: Daemon.sin_port = 0;
345: # else
346: Daemon.sun_family = SOCK_FAMILY;
347: (void) strcpy(Daemon.sun_path, Sock_name);
348: # endif
349:
350: Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0);
351: # if defined(INTERNET)
352: msg = 1;
353: #ifdef SO_USELOOPBACK
354: if (setsockopt(Socket, SOL_SOCKET, SO_USELOOPBACK, &msg, sizeof msg)<0)
355: # ifdef LOG
356: syslog(LOG_WARNING, "setsockopt loopback %m");
357: # else
358: warn("setsockopt loopback");
359: # endif
360: #endif
361: # endif
362: if (bind(Socket, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) {
363: if (errno == EADDRINUSE)
364: exit(0);
365: else {
366: # ifdef LOG
367: syslog(LOG_ERR, "bind: %m");
368: # else
369: warn("bind");
370: # endif
371: cleanup(1);
372: }
373: }
374: (void) listen(Socket, 5);
375:
376: # ifdef INTERNET
377: len = sizeof (SOCKET);
378: if (getsockname(Socket, (struct sockaddr *) &Daemon, &len) < 0) {
379: # ifdef LOG
380: syslog(LOG_ERR, "getsockname: %m");
381: # else
382: warn("getsockname");
383: # endif
384: exit(1);
385: }
386: sock_port = ntohs(Daemon.sin_port);
387: # endif
388:
389:
390:
391:
392: fdset[0].fd = Socket;
393: fdset[0].events = POLLIN;
394: fdset[1].fd = Status;
395: fdset[1].events = POLLIN;
396:
397: # ifdef INTERNET
398: len = sizeof (SOCKET);
399: if (getsockname(0, (struct sockaddr *) &test_port, &len) >= 0
400: && test_port.sin_family == AF_INET) {
401: inetd_spawned = TRUE;
402: Test_socket = 0;
403: if (test_port.sin_port != htons((u_short) Test_port)) {
404: standard_port = FALSE;
405: Test_port = ntohs(test_port.sin_port);
406: }
407: } else {
408: test_port = Daemon;
409: test_port.sin_port = htons((u_short) Test_port);
410:
411: Test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0);
412: if (bind(Test_socket, (struct sockaddr *) &test_port,
413: DAEMON_SIZE) < 0) {
414: # ifdef LOG
415: syslog(LOG_ERR, "bind: %m");
416: # else
417: warn("bind");
418: # endif
419: exit(1);
420: }
421: (void) listen(Test_socket, 5);
422: }
423:
424: fdset[2].fd = Test_socket;
425: fdset[2].events = POLLIN;
426: # else
427: fdset[2].fd = -1;
428: # endif
429:
430: Seed = getpid() + time((time_t *) NULL);
431: makemaze();
432: # ifdef BOOTS
433: makeboots();
434: # endif
435:
436: for (i = 0; i < NASCII; i++)
437: See_over[i] = TRUE;
438: See_over[DOOR] = FALSE;
439: See_over[WALL1] = FALSE;
440: See_over[WALL2] = FALSE;
441: See_over[WALL3] = FALSE;
442: # ifdef REFLECT
443: See_over[WALL4] = FALSE;
444: See_over[WALL5] = FALSE;
445: # endif
446:
447: }
448:
449: # ifdef BOOTS
450:
451:
452:
453:
454: static void
455: makeboots()
456: {
457: int x, y;
458: PLAYER *pp;
459:
460: do {
461: x = rand_num(WIDTH - 1) + 1;
462: y = rand_num(HEIGHT - 1) + 1;
463: } while (Maze[y][x] != SPACE);
464: Maze[y][x] = BOOT_PAIR;
465: for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
466: pp->p_flying = -1;
467: }
468: # endif
469:
470:
471:
472:
473:
474:
475: void
476: checkdam(ouch, gotcha, credit, amt, shot_type)
477: PLAYER *ouch, *gotcha;
478: IDENT *credit;
479: int amt;
480: char shot_type;
481: {
482: const char *cp;
483:
484: if (ouch->p_death[0] != '\0')
485: return;
486: # ifdef BOOTS
487: if (shot_type == SLIME)
488: switch (ouch->p_nboots) {
489: default:
490: break;
491: case 1:
492: amt = (amt + 1) / 2;
493: break;
494: case 2:
495: if (gotcha != NULL)
496: message(gotcha, "He has boots on!");
497: return;
498: }
499: # endif
500: ouch->p_damage += amt;
501: if (ouch->p_damage <= ouch->p_damcap) {
502: (void) sprintf(Buf, "%2d", ouch->p_damage);
503: cgoto(ouch, STAT_DAM_ROW, STAT_VALUE_COL);
504: outstr(ouch, Buf, 2);
505: return;
506: }
507:
508:
509: switch (shot_type) {
510: default:
511: cp = "Killed";
512: break;
513: # ifdef FLY
514: case FALL:
515: cp = "Killed on impact";
516: break;
517: # endif
518: case KNIFE:
519: cp = "Stabbed to death";
520: ouch->p_ammo = 0;
521: break;
522: case SHOT:
523: cp = "Shot to death";
524: break;
525: