diff options
Diffstat (limited to 'games/hunt')
-rw-r--r-- | games/hunt/hunt/client.h | 8 | ||||
-rw-r--r-- | games/hunt/hunt/connect.c | 35 | ||||
-rw-r--r-- | games/hunt/hunt/display.c | 10 | ||||
-rw-r--r-- | games/hunt/hunt/hunt.c | 11 | ||||
-rw-r--r-- | games/hunt/hunt/otto.c | 60 | ||||
-rw-r--r-- | games/hunt/hunt/playit.c | 84 | ||||
-rw-r--r-- | games/hunt/huntd/answer.c | 310 | ||||
-rw-r--r-- | games/hunt/huntd/conf.c | 411 | ||||
-rw-r--r-- | games/hunt/huntd/conf.h | 86 | ||||
-rw-r--r-- | games/hunt/huntd/driver.c | 373 | ||||
-rw-r--r-- | games/hunt/huntd/execute.c | 4 | ||||
-rw-r--r-- | games/hunt/huntd/expl.c | 23 | ||||
-rw-r--r-- | games/hunt/huntd/huntd.6 | 11 | ||||
-rw-r--r-- | games/hunt/huntd/server.h | 32 | ||||
-rw-r--r-- | games/hunt/huntd/shots.c | 32 | ||||
-rw-r--r-- | games/hunt/huntd/terminal.c | 41 |
16 files changed, 1010 insertions, 521 deletions
diff --git a/games/hunt/hunt/client.h b/games/hunt/hunt/client.h index fd3187ba329..42f48e48e8a 100644 --- a/games/hunt/hunt/client.h +++ b/games/hunt/hunt/client.h @@ -1,4 +1,4 @@ -/* $OpenBSD: client.h,v 1.1 1999/01/29 07:30:33 d Exp $ */ +/* $OpenBSD: client.h,v 1.2 1999/02/01 06:53:55 d Exp $ */ /* hunt.c */ extern FLAG Am_monitor; /* -m flag */ @@ -12,7 +12,7 @@ void bad_ver __P((void)); void intr __P((int)); /* connect.c */ -void do_connect __P((char *, char, long)); +void do_connect __P((char *, u_int8_t, u_int32_t)); /* playit.c */ void playit __P((void)); @@ -21,5 +21,5 @@ int quit __P((int)); /* otto.c */ extern int Otto_mode; -extern int Otto_count; -void otto __P((int, int, char)); +int otto __P((int, int, char, char *, size_t)); +int otto_quit __P((int)); diff --git a/games/hunt/hunt/connect.c b/games/hunt/hunt/connect.c index 598db489fdd..06309e681f6 100644 --- a/games/hunt/hunt/connect.c +++ b/games/hunt/hunt/connect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: connect.c,v 1.3 1999/01/29 07:30:33 d Exp $ */ +/* $OpenBSD: connect.c,v 1.4 1999/02/01 06:53:55 d Exp $ */ /* $NetBSD: connect.c,v 1.3 1997/10/11 08:13:40 lukem Exp $ */ /* * Hunt @@ -14,32 +14,35 @@ void do_connect(name, team, enter_status) - char *name; - char team; - long enter_status; + char * name; + u_int8_t team; + u_int32_t enter_status; { u_int32_t uid; u_int32_t mode; char * Ttyname; char buf[NAMELEN]; - uid = htonl(getuid()); - (void) write(Socket, (char *) &uid, sizeof uid); - (void) write(Socket, name, NAMELEN); - (void) write(Socket, &team, sizeof team); - enter_status = htonl(enter_status); - (void) write(Socket, (char *) &enter_status, sizeof enter_status); - Ttyname = ttyname(STDOUT_FILENO); - if (Ttyname == NULL) - Ttyname = "not a tty"; - (void) strlcpy(buf, Ttyname, sizeof buf); - (void) write(Socket, buf, NAMELEN); if (Send_message != NULL) mode = C_MESSAGE; else if (Am_monitor) mode = C_MONITOR; else mode = C_PLAYER; + + Ttyname = ttyname(STDOUT_FILENO); + if (Ttyname == NULL) + Ttyname = "not a tty"; + (void) strlcpy(buf, Ttyname, sizeof buf); + + uid = htonl(getuid()); + enter_status = htonl(enter_status); mode = htonl(mode); - (void) write(Socket, (char *) &mode, sizeof mode); + + (void) write(Socket, &uid, sizeof uid); + (void) write(Socket, name, NAMELEN); + (void) write(Socket, &team, sizeof team); + (void) write(Socket, &enter_status, sizeof enter_status); + (void) write(Socket, buf, NAMELEN); + (void) write(Socket, &mode, sizeof mode); } diff --git a/games/hunt/hunt/display.c b/games/hunt/hunt/display.c index a24cfb3a46b..3c832f36df4 100644 --- a/games/hunt/hunt/display.c +++ b/games/hunt/hunt/display.c @@ -1,4 +1,4 @@ -/* $OpenBSD: display.c,v 1.1 1999/01/29 07:30:33 d Exp $ */ +/* $OpenBSD: display.c,v 1.2 1999/02/01 06:53:55 d Exp $ */ /* * Display abstraction. @@ -336,7 +336,13 @@ char display_atyx(y, x) int y, x; { - return mvinch(y, x) & 0x7f; + int oy, ox; + char c; + + display_getyx(&oy, &ox); + c = mvwinch(stdscr, y, x) & 0x7f; + display_move(oy, ox); + return (c); } void diff --git a/games/hunt/hunt/hunt.c b/games/hunt/hunt/hunt.c index a732ff474a3..a573dbfcb8e 100644 --- a/games/hunt/hunt/hunt.c +++ b/games/hunt/hunt/hunt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hunt.c,v 1.3 1999/01/29 07:30:33 d Exp $ */ +/* $OpenBSD: hunt.c,v 1.4 1999/02/01 06:53:55 d Exp $ */ /* $NetBSD: hunt.c,v 1.8 1998/09/13 15:27:28 hubertf Exp $ */ /* * Hunt @@ -164,9 +164,12 @@ main(ac, av) } exit(0); } - if (Otto_mode) + if (Otto_mode) { + if (Am_monitor) + errx(1, "otto mode incompatible with monitor mode"); (void) strlcpy(name, "otto", sizeof name); - else + team = ' '; + } else fill_in_blanks(); (void) fflush(stdout); @@ -179,7 +182,7 @@ main(ac, av) display_clear_the_screen(); (void) signal(SIGINT, intr); (void) signal(SIGTERM, sigterm); - (void) signal(SIGPIPE, SIG_IGN); + /* (void) signal(SIGPIPE, SIG_IGN); */ for (;;) { find_driver(TRUE); diff --git a/games/hunt/hunt/otto.c b/games/hunt/hunt/otto.c index bd5427eed11..00d445c94a3 100644 --- a/games/hunt/hunt/otto.c +++ b/games/hunt/hunt/otto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: otto.c,v 1.3 1999/01/29 07:30:33 d Exp $ */ +/* $OpenBSD: otto.c,v 1.4 1999/02/01 06:53:55 d Exp $ */ /* $NetBSD: otto.c,v 1.2 1997/10/10 16:32:39 lukem Exp $ */ /* * otto - a hunt otto-matic player @@ -20,8 +20,12 @@ #include "client.h" #include "display.h" +#include <stdio.h> +#define panic(m) _panic(__FILE__,__LINE__,m) + +useconds_t Otto_pause = 55000; + int Otto_mode; -int Otto_count; # undef WALL # undef NORTH @@ -89,7 +93,6 @@ static int facing; static int row, col; static int num_turns; /* for wandering */ static char been_there[HEIGHT][WIDTH2]; -static struct itimerval pause_time = { { 0, 0 }, { 0, 55000 }}; static void attack __P((int, struct item *)); static void duck __P((int)); @@ -97,29 +100,21 @@ static void face_and_move_direction __P((int, int)); static int go_for_ammo __P((char)); static void ottolook __P((int, struct item *)); static void look_around __P((void)); -static void nothing __P((int)); static int stop_look __P((struct item *, char, int, int)); static void wander __P((void)); +static void _panic __P((const char *, int, const char *)); -static void -nothing(dummy) - int dummy; -{ -} - -void -otto(y, x, face) +int +otto(y, x, face, buf, buflen) int y, x; char face; + char *buf; + size_t buflen; { int i; - int old_mask; - (void) signal(SIGALRM, nothing); - old_mask = sigblock(sigmask(SIGALRM)); - setitimer(ITIMER_REAL, &pause_time, NULL); - sigpause(old_mask); - sigsetmask(old_mask); + if (usleep(Otto_pause) < 0) + panic("usleep"); /* save away parameters so other functions may use/update info */ switch (face) { @@ -127,7 +122,7 @@ otto(y, x, face) case '<': facing = WEST; break; case 'v': facing = SOUTH; break; case '>': facing = EAST; break; - default: abort(); + default: panic("unknwown face"); } row = y; col = x; been_there[row][col] |= 1 << facing; @@ -160,8 +155,12 @@ otto(y, x, face) wander(); done: - (void) write(Socket, command, comlen); - Otto_count += comlen; + if (comlen) { + if (comlen > buflen) + panic("not enough buffer space"); + memcpy(buf, command, comlen); + } + return comlen; } static int @@ -331,7 +330,7 @@ ottolook(rel_dir, itemp) break; default: - abort(); + panic("unknown look"); } } @@ -543,3 +542,20 @@ wander() face_and_move_direction(rel_dir, 1); } +/* Otto always re-enters the game, cloaked. */ +int +otto_quit(old_status) +{ + return Q_CLOAK; +} + +static void +_panic(file, line, msg) + const char *file; + int line; + const char *msg; +{ + + fprintf(stderr, "%s:%d: panic! %s\n", file, line, msg); + abort(); +} diff --git a/games/hunt/hunt/playit.c b/games/hunt/hunt/playit.c index bbf8a2954fd..8444648c49f 100644 --- a/games/hunt/hunt/playit.c +++ b/games/hunt/hunt/playit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: playit.c,v 1.3 1999/01/29 07:30:34 d Exp $ */ +/* $OpenBSD: playit.c,v 1.4 1999/02/01 06:53:55 d Exp $ */ /* $NetBSD: playit.c,v 1.4 1997/10/20 00:37:15 lukem Exp $ */ /* * Hunt @@ -20,9 +20,9 @@ static int nchar_send; static FLAG Last_player; +static int Otto_expect; # define MAX_SEND 5 -# define STDIN 0 /* * ibuf is the input buffer used for the stream from the driver. @@ -49,7 +49,8 @@ playit() int y, x; u_int32_t version; int otto_y, otto_x; - char otto_face; + char otto_face = ' '; + int chars_processed; if (read(Socket, &version, sizeof version) != sizeof version) { bad_con(); @@ -60,8 +61,8 @@ playit() /* NOTREACHED */ } errno = 0; - Otto_count = 0; nchar_send = MAX_SEND; + Otto_expect = 0; while ((ch = GETCHR()) != EOF) { switch (ch & 0377) { case MOVE: @@ -69,22 +70,7 @@ playit() x = GETCHR(); display_move(y, x); break; - case ADDCH: - ch = GETCHR(); - if (Otto_mode) - switch (ch) { - - case '<': - case '>': - case '^': - case 'v': - otto_face = ch; - display_getyx(&otto_y, &otto_x); - break; - } - display_put_ch(ch); - break; case CLRTOEOL: display_clear_eol(); break; @@ -108,29 +94,51 @@ playit() display_beep(); break; case READY: + chars_processed = GETCHR(); display_refresh(); if (nchar_send < 0) - tcflush(STDIN, TCIFLUSH); + tcflush(STDIN_FILENO, TCIFLUSH); nchar_send = MAX_SEND; - Otto_count -= (GETCHR() & 0xff); - if (!Am_monitor) { - if (Otto_count == 0 && Otto_mode) - otto(otto_y, otto_x, otto_face); + if (Otto_mode) { + /* + * The driver returns the number of keypresses + * that it has processed. Use this to figure + * out if otto's commands have completed. + */ + Otto_expect -= chars_processed; + if (Otto_expect == 0) { + /* not very fair! */ + static char buf[MAX_SEND * 2]; + int len; + + /* Ask otto what it wants to do: */ + len = otto(otto_y, otto_x, otto_face, + buf, sizeof buf); + if (len) { + /* Pass it on to the driver: */ + write(Socket, buf, len); + /* Update expectations: */ + Otto_expect += len; + } + } } break; + case ADDCH: + ch = GETCHR(); + /* FALLTHROUGH */ default: + display_put_ch(ch); if (Otto_mode) switch (ch) { - case '<': case '>': case '^': case 'v': otto_face = ch; display_getyx(&otto_y, &otto_x); + otto_x--; break; } - display_put_ch(ch); break; } } @@ -153,8 +161,8 @@ getchr() FD_ZERO(&s_readfds); FD_SET(Socket, &s_readfds); - FD_SET(STDIN, &s_readfds); - s_nfds = (Socket > STDIN) ? Socket : STDIN; + FD_SET(STDIN_FILENO, &s_readfds); + s_nfds = (Socket > STDIN_FILENO) ? Socket : STDIN_FILENO; s_nfds++; one_more_time: @@ -165,17 +173,15 @@ one_more_time: nfds = select(nfds, &readfds, NULL, NULL, NULL); } while (nfds <= 0 && errno == EINTR); - if (FD_ISSET(STDIN, &readfds)) + if (FD_ISSET(STDIN_FILENO, &readfds)) send_stuff(); if (! FD_ISSET(Socket, &readfds)) goto one_more_time; icnt = read(Socket, ibuf, sizeof ibuf); - if (icnt < 0) { + if (icnt <= 0) { bad_con(); /* NOTREACHED */ } - if (icnt == 0) - goto one_more_time; iptr = ibuf; icnt--; return *iptr++; @@ -194,7 +200,7 @@ send_stuff() static char Buf[BUFSIZ]; /* Drain the user's keystrokes: */ - count = read(STDIN, Buf, sizeof Buf); + count = read(STDIN_FILENO, Buf, sizeof Buf); if (count <= 0) return; @@ -216,12 +222,18 @@ send_stuff() } count = nsp - inp; if (count) { - if (Otto_mode) - Otto_count += count; nchar_send -= count; if (nchar_send < 0) count += nchar_send; (void) write(Socket, inp, count); + if (Otto_mode) { + /* + * The user can insert commands over otto. + * So, otto shouldn't be alarmed when the + * server processes more than otto asks for. + */ + Otto_expect += count; + } } } @@ -238,7 +250,7 @@ quit(old_status) if (Last_player) return Q_QUIT; if (Otto_mode) - return Q_CLOAK; + return otto_quit(old_status); display_move(HEIGHT, 0); display_put_str("Re-enter game [ynwo]? "); display_clear_eol(); diff --git a/games/hunt/huntd/answer.c b/games/hunt/huntd/answer.c index 2adf3ba2bfd..e5e360afe86 100644 --- a/games/hunt/huntd/answer.c +++ b/games/hunt/huntd/answer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: answer.c,v 1.3 1999/01/29 07:30:34 d Exp $ */ +/* $OpenBSD: answer.c,v 1.4 1999/02/01 06:53:55 d Exp $ */ /* $NetBSD: answer.c,v 1.3 1997/10/10 16:32:50 lukem Exp $ */ /* * Hunt @@ -17,6 +17,7 @@ #include <string.h> #include <sys/socket.h> #include <netinet/in.h> +#include <arpa/inet.h> #include "hunt.h" #include "server.h" @@ -26,60 +27,58 @@ int allow_severity = LOG_INFO; int deny_severity = LOG_WARNING; + +/* List of spawning connections: */ +struct spawn *Spawn = NULL; + static void stplayer __P((PLAYER *, int)); static void stmonitor __P((PLAYER *)); -static IDENT * get_ident __P((u_long, u_long, char *, char, - struct request_info *)); +static IDENT * get_ident __P((struct sockaddr *, int, u_long, char *, char)); -int -answer() +void +answer_first() { - PLAYER *pp; + struct sockaddr sockstruct; int newsock; - u_int32_t mode; - char name[NAMELEN]; - u_int8_t team; - u_int32_t enter_status; int socklen; - u_long machine; - u_int32_t uid; - struct sockaddr_in sockstruct; - char *cp1, *cp2; int flags; - u_int32_t version; struct request_info ri; - char Ttyname[NAMELEN]; /* never used */ + struct spawn *sp; + /* Answer the call to hunt: */ socklen = sizeof sockstruct; - errno = 0; newsock = accept(Socket, (struct sockaddr *) &sockstruct, &socklen); - if (newsock < 0) - { - if (errno == EINTR) - return FALSE; - syslog(LOG_ERR, "accept: %m"); - cleanup(1); + if (newsock < 0) { + log(LOG_ERR, "accept"); + return; } /* Check for access permissions: */ request_init(&ri, RQ_DAEMON, "huntd", RQ_FILE, newsock, 0); if (hosts_access(&ri) == 0) { close(newsock); - return (FALSE); + logx(LOG_INFO, "rejected connection"); + return; } - machine = ntohl((u_int32_t)((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr); - version = htonl((u_int32_t) HUNT_VERSION); - (void) write(newsock, &version, sizeof version); - (void) read(newsock, &uid, sizeof uid); - uid = ntohl((unsigned long) uid); - (void) read(newsock, name, sizeof name); - (void) read(newsock, &team, sizeof team); - (void) read(newsock, &enter_status, sizeof enter_status); - enter_status = ntohl((unsigned long) enter_status); - (void) read(newsock, Ttyname, sizeof Ttyname); - (void) read(newsock, &mode, sizeof mode); - mode = ntohl(mode); + /* Remember this spawning connection: */ + sp = (struct spawn *)malloc(sizeof *sp); + if (sp == NULL) { + log(LOG_ERR, "malloc"); + close(newsock); + return; + } + memset(sp, '\0', sizeof *sp); + + /* Keep the calling machine's source addr for ident purposes: */ + memcpy(&sp->source, &sockstruct, sizeof sp->source); + sp->sourcelen = socklen; + + /* Warn if we lose connection info: */ + if (socklen > sizeof Spawn->source) + logx(LOG_WARNING, + "struct sockaddr is not big enough! (%d > %d)", + socklen, sizeof Spawn->source); /* * Turn off blocking I/O, so a slow or dead terminal won't stop @@ -89,69 +88,132 @@ answer() flags |= O_NDELAY; (void) fcntl(newsock, F_SETFL, flags); + /* Start listening to the spawning connection */ + sp->fd = newsock; + FD_SET(sp->fd, &Fds_mask); + if (sp->fd >= Num_fds) + Num_fds = sp->fd + 1; + + /* Initialise the spawn state */ + sp->state = 0; + + /* Add to the spawning list */ + if ((sp->next = Spawn) != NULL) + Spawn->prevnext = &sp->next; + sp->prevnext = &Spawn; + Spawn = sp; +} + +int +answer_next(sp) + struct spawn *sp; +{ + PLAYER *pp; + char *cp1, *cp2; + u_int32_t version; + FILE *conn; + int len; + + switch (sp->state) { + case 0: + len = read(sp->fd, &sp->uid, sizeof sp->uid); + break; + case 1: + len = read(sp->fd, sp->name, NAMELEN); + sp->name[NAMELEN] = '\0'; + break; + case 2: + len = read(sp->fd, &sp->team, sizeof sp->team); + break; + case 3: + len = read(sp->fd, &sp->enter_status, sizeof sp->enter_status); + break; + case 4: + len = read(sp->fd, sp->ttyname, NAMELEN); + break; + case 5: + len = read(sp->fd, &sp->mode, sizeof sp->mode); + break; + case 7: + len = sp->msglen = read(sp->fd, &sp->msg, sizeof sp->msg - 1); + break; + default: + log(LOG_ERR, "impossible state %d", sp->state); + goto close_it; + } + + if (len < 0) { + log(LOG_WARNING, "read"); + goto close_it; + } + if (len == 0) { + logx(LOG_WARNING, "lost connection to new client"); + goto close_it; + } + + if (sp->state == 7) { + /* Received message: */ + char teamstr[] = "[?]"; + + teamstr[1] = sp->team; + outyx(ALL_PLAYERS, HEIGHT, 0, "%s%s: %.*s", + sp->name, + sp->team == ' ' ? "": teamstr, + sp->msglen, + sp->msg); + ce(ALL_PLAYERS); + sendcom(ALL_PLAYERS, REFRESH); + sendcom(ALL_PLAYERS, READY, 0); + flush(ALL_PLAYERS); + goto close_it; + } + + sp->state++; + if (sp->state != 6) { + /* More to come: */ + return FALSE; + } + + /* Convert data from network byte order: */ + sp->uid = ntohl(sp->uid); + sp->enter_status = ntohl(sp->enter_status); + sp->mode = ntohl(sp->mode); + /* * Make sure the name contains only printable characters * since we use control characters for cursor control * between driver and player processes */ - for (cp1 = cp2 = name; *cp1 != '\0'; cp1++) + for (cp1 = cp2 = sp->name; *cp1 != '\0'; cp1++) if (isprint(*cp1) || *cp1 == ' ') *cp2++ = *cp1; *cp2 = '\0'; - /* The connection is solely for a message: */ - if (mode == C_MESSAGE) { - fd_set r; - struct timeval tmo = { 0, 1000000 / 2 }; - char buf[BUFSIZ + 1]; - int buflen; - int n; - - /* wait for 0.5 second for the message packet */ - FD_ZERO(&r); - FD_SET(newsock, &r); - n = select(newsock+1, &r, 0, 0, &tmo); - if (n < 0) - syslog(LOG_ERR, "select: %m"); - else if (n > 0) { - buflen = 0; - while (buflen < (BUFSIZ - 1) && (n = read(newsock, - buf + buflen, (BUFSIZ - 1) - buflen)) > 0) - buflen += n; - buf[buflen] = '\0'; - - if (team == ' ') - outyx(ALL_PLAYERS, HEIGHT, 0, "%s: %s", - name, buf); - else - outyx(ALL_PLAYERS, HEIGHT, 0, "%s[%c]: %s", - name, team, buf); - ce(ALL_PLAYERS); - sendcom(ALL_PLAYERS, REFRESH); - sendcom(ALL_PLAYERS, READY, 0); - flush(ALL_PLAYERS); - } + /* Tell the other end this server's hunt driver version: */ + version = htonl((u_int32_t) HUNT_VERSION); + (void) write(sp->fd, &version, sizeof version); - (void) close(newsock); + if (sp->mode == C_MESSAGE) { + /* The connection is solely for a message: */ + sp->state = 7; return FALSE; } + /* Use a stdio file descriptor from now on: */ + conn = fdopen(sp->fd, "w"); + /* The player is a monitor: */ - else if (mode == C_MONITOR) { + if (sp->mode == C_MONITOR) { if (conf_monitor && End_monitor < &Monitor[MAXMON]) { pp = End_monitor++; - if (team == ' ') - team = '*'; + if (sp->team == ' ') + sp->team = '*'; } else { - u_int32_t response; - /* Too many monitors */ - response = htonl(0); - (void) write(newsock, (char *) &response, - sizeof response); - (void) close(newsock); - syslog(LOG_NOTICE, "too many monitors"); - return FALSE; + fprintf(conn, "Too many monitors\n"); + fflush(conn); + logx(LOG_NOTICE, "too many monitors"); + goto close_it; } /* The player is a normal hunter: */ @@ -159,34 +221,46 @@ answer() if (End_player < &Player[MAXPL]) pp = End_player++; else { - u_int32_t response; - + fprintf(conn, "Too many players\n"); + fflush(conn); /* Too many players */ - response = htonl(0); - (void) write(newsock, (char *) &response, - sizeof response); - (void) close(newsock); - syslog(LOG_NOTICE, "too many players"); - return FALSE; + logx(LOG_NOTICE, "too many players"); + goto close_it; } } - pp->p_ident = get_ident(machine, uid, name, team, &ri); - pp->p_output = fdopen(newsock, "w"); + /* Find the player's running scorecard */ + pp->p_ident = get_ident(&sp->source, sp->sourcelen, sp->uid, + sp->name, sp->team); + pp->p_output = conn; pp->p_death[0] = '\0'; - pp->p_fd = newsock; - FD_SET(pp->p_fd, &Fds_mask); - if (pp->p_fd >= Num_fds) - Num_fds = pp->p_fd + 1; + pp->p_fd = sp->fd; + + /* Remove from the spawn list. (fd remains in read set) */ + *sp->prevnext = sp->next; + if (sp->next) sp->next->prevnext = sp->prevnext; + /* No idea where the player starts: */ pp->p_y = 0; pp->p_x = 0; - if (mode == C_MONITOR) + /* Mode-specific initialisation: */ + if (sp->mode == C_MONITOR) stmonitor(pp); else - stplayer(pp, enter_status); + stplayer(pp, sp->enter_status); + + /* And, they're off! */ return TRUE; + +close_it: + /* Destroy the spawn */ + *sp->prevnext = sp->next; + if (sp->next) sp->next->prevnext = sp->prevnext; + FD_CLR(sp->fd, &Fds_mask); + close(sp->fd); + free(sp); + return FALSE; } /* Start a monitor: */ @@ -360,15 +434,21 @@ rand_dir() * Get the score structure of a player */ static IDENT * -get_ident(machine, uid, name, team, ri) - u_long machine; +get_ident(sa, salen, uid, name, team) + struct sockaddr *sa; + int salen; u_long uid; char *name; char team; - struct request_info *ri; { IDENT *ip; static IDENT punt; + u_int32_t machine; + + if (sa->sa_family == AF_INET) + machine = ntohl((u_long)((struct sockaddr_in *)sa)->sin_addr.s_addr); + else + machine = 0; for (ip = Scores; ip != NULL; ip = ip->i_next) if (ip->i_machine == machine @@ -379,7 +459,7 @@ get_ident(machine, uid, name, team, ri) if (ip != NULL) { if (ip->i_team != team) { - syslog(LOG_INFO, "player %s %s team %c", + logx(LOG_INFO, "player %s %s team %c", name, team == ' ' ? "left" : ip->i_team == ' ' ? "joined" : "changed to", @@ -397,7 +477,7 @@ get_ident(machine, uid, name, team, ri) /* Alloc new entry -- it is released in clear_scores() */ ip = (IDENT *) malloc(sizeof (IDENT)); if (ip == NULL) { - syslog(LOG_ERR, "malloc: %m"); + log(LOG_ERR, "malloc"); /* Fourth down, time to punt */ ip = &punt; } @@ -420,7 +500,7 @@ get_ident(machine, uid, name, team, ri) ip->i_next = Scores; Scores = ip; - syslog(LOG_INFO, "new player: %s%s%c%s", + logx(LOG_INFO, "new player: %s%s%c%s", name, team == ' ' ? "" : " (team ", team, @@ -429,3 +509,27 @@ get_ident(machine, uid, name, team, ri) return ip; } + +void +answer_info(fp) + FILE *fp; +{ + struct spawn *sp; + char buf[128]; + const char *bf; + struct sockaddr_in *sa; + + if (Spawn == NULL) + return; + fprintf(fp, "\nSpawning connections:\n"); + for (sp = Spawn; sp; sp = sp->next) { + sa = (struct sockaddr_in *)&sp->source; + bf = inet_ntop(AF_INET, &sa->sin_addr, buf, sizeof buf); + if (!bf) { + log(LOG_WARNING, "inet_ntop"); + bf = "?"; + } + fprintf(fp, "fd %d: state %d, from %s:%d\n", + sp->fd, sp->state, bf, sa->sin_port); + } +} diff --git a/games/hunt/huntd/conf.c b/games/hunt/huntd/conf.c index 1d20d3436a1..875debd2cd1 100644 --- a/games/hunt/huntd/conf.c +++ b/games/hunt/huntd/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.1 1999/01/29 07:30:34 d Exp $ */ +/* $OpenBSD: conf.c,v 1.2 1999/02/01 06:53:55 d Exp $ */ /* David Leonard <d@openbsd.org>, 1999. Public domain. */ #include <stdio.h> @@ -6,198 +6,280 @@ #include <dirent.h> #include <stdlib.h> #include <ctype.h> +#include <syslog.h> +#include <errno.h> +#include "hunt.h" +#include "server.h" #include "conf.h" /* Configuration option variables for the server: */ -int conf_random = 1; /* enable dispersion doors */ -int conf_reflect = 1; /* enable generation of reflection walls */ -int conf_monitor = 1; /* enable monitors */ -int conf_ooze = 1; /* enable slime shots */ -int conf_fly = 1; /* enable flight */ -int conf_volcano = 1; /* enable volcanoes */ -int conf_drone = 1; /* enable drone */ -int conf_boots = 1; /* enable boots */ -int conf_scan = 1; /* enable scanning */ -int conf_cloak = 1; /* enable cloaking */ -int conf_logerr = 1; /* errors to stderr as well as syslog(8) */ - -int conf_scoredecay = 15; /* nr deaths before nr kills begins to decay */ -int conf_maxremove = 40; /* Maximum number of holes in the maze wall */ -int conf_linger = 90; /* Seconds to keep game open with no players */ - -int conf_flytime = 20; /* max time flying */ -int conf_flystep = 5; /* max displacement each flying time unit */ -int conf_volcano_max = 50; /* max size of volcano */ -int conf_ptrip_face = 2; /* chace of tripping a grenade on pickup, */ -int conf_ptrip_back = 95; /* - when backing onto it */ -int conf_ptrip_side = 50; /* - when walking sideways into it */ -int conf_prandom = 1; /* percentage of time dispersion doors appear */ -int conf_preflect = 1; /* percentage of time reflection walls appear */ -int conf_pshot_coll = 5; /* percent chance of shots colliding */ -int conf_pgren_coll = 10; /* percent chance of grenades colliding */ -int conf_pgren_catch = 10; /* facing player chance of catching grenade */ -int conf_pmiss = 5; /* chance of bullet missing player */ -int conf_pdroneabsorb = 1; /* chance of absorbing a drone */ -int conf_fall_frac = 5; /* divisor of damage used for fall damage */ - -int conf_bulspd = 5; /* speed of bullets */ -int conf_ishots = 15; /* initial ammo for player */ -int conf_nshots = 5; /* ammo boost for all when new player joins */ -int conf_maxncshot = 2; /* max number of simultaneous shots per player*/ -int conf_maxdam = 10; /* the initial shield for each player */ -int conf_mindam = 5; /* minimum damage from one unit of ammo */ -int conf_stabdam = 2; /* damage from stabbing */ -int conf_killgain = 2; /* shield gained from killing someone */ -int conf_slimefactor = 3; /* charge multiplier for slime */ -int conf_slimespeed = 5; /* speed of slime */ -int conf_lavaspeed = 1; /* speed of volcano lava */ -int conf_cloaklen = 20; /* duration of a cloak */ -int conf_scanlen = 20; /* duration of a scan */ -int conf_mindshot = 2; /* minium shot class needed to make a drone */ +int conf_random = 1; +int conf_reflect = 1; +int conf_monitor = 1; +int conf_ooze = 1; +int conf_fly = 1; +int conf_volcano = 1; +int conf_drone = 1; +int conf_boots = 1; +int conf_scan = 1; +int conf_cloak = 1; +int conf_logerr = 1; +int conf_syslog = 0; + +int conf_scoredecay = 15; +int conf_maxremove = 40; +int conf_linger = 90; + +int conf_flytime = 20; +int conf_flystep = 5; +int conf_volcano_max = 50; +int conf_ptrip_face = 2; +int conf_ptrip_back = 95; +int conf_ptrip_side = 50; +int conf_prandom = 1; +int conf_preflect = 1; +int conf_pshot_coll = 5; +int conf_pgren_coll = 10; +int conf_pgren_catch = 10; +int conf_pmiss = 5; +int conf_pdroneabsorb = 1; +int conf_fall_frac = 5; + +int conf_bulspd = 5; +int conf_ishots = 15; +int conf_nshots = 5; +int conf_maxncshot = 2; +int conf_maxdam = 10; +int conf_mindam = 5; +int conf_stabdam = 2; +int conf_killgain = 2; +int conf_slimefactor = 3; +int conf_slimespeed = 5; +int conf_lavaspeed = 1; +int conf_cloaklen = 20; +int conf_scanlen = 20; +int conf_mindshot = 2; +int conf_simstep = 0; + struct kwvar { char * kw; - int * var; + void * var; + enum vartype { Vint, Vchar, Vstring, Vdouble } type; }; static struct kwvar keywords[] = { - { "random", &conf_random }, - { "reflect", &conf_reflect }, - { "monitor", &conf_monitor }, - { "ooze", &conf_ooze }, - { "fly", &conf_fly }, - { "volcano", &conf_volcano }, - { "drone", &conf_drone }, - { "boots", &conf_boots }, - { "scan", &conf_scan }, - { "cloak", &conf_cloak }, - { "logerr", &conf_logerr }, - { "scoredecay", &conf_scoredecay }, - { "maxremove", &conf_maxremove }, - { "linger", &conf_linger }, - - { "flytime", &conf_flytime }, - { "flystep", &conf_flystep }, - { "volcano_max", &conf_volcano_max }, - { "ptrip_face", &conf_ptrip_face }, - { "ptrip_back", &conf_ptrip_back }, - { "ptrip_side", &conf_ptrip_side }, - { "prandom", &conf_prandom }, - { "preflect", &conf_preflect }, - { "pshot_coll", &conf_pshot_coll }, - { "pgren_coll", &conf_pgren_coll }, - { "pgren_catch", &conf_pgren_catch }, - { "pmiss", &conf_pmiss }, - { "pdroneabsorb", &conf_pdroneabsorb }, - { "fall_frac", &conf_fall_frac }, - - { "bulspd", &conf_bulspd }, - { "ishots", &conf_ishots }, - { "nshots", &conf_nshots }, - { "maxncshot", &conf_maxncshot }, - { "maxdam", &conf_maxdam }, - { "mindam", &conf_mindam }, - { "stabdam", &conf_stabdam }, - { "killgain", &conf_killgain }, - { "slimefactor", &conf_slimefactor }, - { "slimespeed", &conf_slimespeed }, - { "lavaspeed", &conf_lavaspeed }, - { "cloaklen", &conf_cloaklen }, - { "scanlen", &conf_scanlen }, - { "mindshot", &conf_mindshot }, - - { NULL, NULL} + { "random", &conf_random, Vint }, + { "reflect", &conf_reflect, Vint }, + { "monitor", &conf_monitor, Vint }, + { "ooze", &conf_ooze, Vint }, + { "fly", &conf_fly, Vint }, + { "volcano", &conf_volcano, Vint }, + { "drone", &conf_drone, Vint }, + { "boots", &conf_boots, Vint }, + { "scan", &conf_scan, Vint }, + { "cloak", &conf_cloak, Vint }, + { "logerr", &conf_logerr, Vint }, + { "syslog", &conf_syslog, Vint }, + { "scoredecay", &conf_scoredecay, Vint }, + { "maxremove", &conf_maxremove, Vint }, + { "linger", &conf_linger, Vint }, + + { "flytime", &conf_flytime, Vint }, + { "flystep", &conf_flystep, Vint }, + { "volcano_max", &conf_volcano_max, Vint }, + { "ptrip_face", &conf_ptrip_face, Vint }, + { "ptrip_back", &conf_ptrip_back, Vint }, + { "ptrip_side", &conf_ptrip_side, Vint }, + { "prandom", &conf_prandom, Vint }, + { "preflect", &conf_preflect, Vint }, + { "pshot_coll", &conf_pshot_coll, Vint }, + { "pgren_coll", &conf_pgren_coll, Vint }, + { "pgren_catch", &conf_pgren_catch, Vint }, + { "pmiss", &conf_pmiss, Vint }, + { "pdroneabsorb", &conf_pdroneabsorb, Vint }, + { "fall_frac", &conf_fall_frac, Vint }, + + { "bulspd", &conf_bulspd, Vint }, + { "ishots", &conf_ishots, Vint }, + { "nshots", &conf_nshots, Vint }, + { "maxncshot", &conf_maxncshot, Vint }, + { "maxdam", &conf_maxdam, Vint }, + { "mindam", &conf_mindam, Vint }, + { "stabdam", &conf_stabdam, Vint }, + { "killgain", &conf_killgain, Vint }, + { "slimefactor", &conf_slimefactor, Vint }, + { "slimespeed", &conf_slimespeed, Vint }, + { "lavaspeed", &conf_lavaspeed, Vint }, + { "cloaklen", &conf_cloaklen, Vint }, + { "scanlen", &conf_scanlen, Vint }, + { "mindshot", &conf_mindshot, Vint }, + { "simstep", &conf_simstep, Vint }, + + { NULL } }; +static char * +parse_int(p, kvp, fnm, linep) + char *p; + struct kwvar *kvp; + const char *fnm; + int *linep; +{ + char *valuestart, *digitstart; + char savec; + int newval; + + /* expect a number */ + valuestart = p; + if (*p == '-') + p++; + digitstart = p; + while (*p && isdigit(*p)) + p++; + if ((*p == '\0' || isspace(*p) || *p == '#') && digitstart != p) { + savec = *p; + *p = '\0'; + newval = atoi(valuestart); + *p = savec; + logx(LOG_INFO, "%s:%d: %s: %d -> %d", + fnm, *linep, kvp->kw, *(int *)kvp->var, newval); + *(int *)kvp->var = newval; + return p; + } else { + logx(LOG_ERR, "%s:%d: invalid integer value \"%s\"", + fnm, *linep, valuestart); + return NULL; + } +} + +static char * +parse_value(p, kvp, fnm, linep) + char *p; + struct kwvar *kvp; + const char *fnm; + int *linep; +{ + + switch (kvp->type) { + case Vint: + return parse_int(p, kvp, fnm, linep); + break; + case Vchar: + case Vstring: + case Vdouble: + /* tbd */ + default: + abort(); + } +} + static void -load_config(f, fnm) - FILE * f; - char * fnm; +parse_line(buf, fnm, line) + char *buf; + char *fnm; + int *line; { - char buf[BUFSIZ]; char *p; - char *word, *value; + char *word; + char *endword; struct kwvar *kvp; int *varp; - int *nextp; - int line = 0; - int len; - int newval; + char savec; - static const char *delim = " \t\n\r\f"; + p = buf; - while ((p = fgetln(f, &len)) != NULL) { - line++; - if (p[len-1] == '\n') - len--; - if (len >= sizeof(buf)) - continue; - (void)memcpy(buf, p, len); - buf[len] = '\0'; /* code assumes newlines later on */ - p = buf; + /* skip leading white */ + while (*p && isspace(*p)) + p++; + /* allow blank lines and comment lines */ + if (*p == '\0' || *p == '#') + return; - /* skip leading white */ - while (*p && isspace(*p)) + /* walk to the end of the word: */ + word = p; + if (*p && (isalpha(*p) || *p == '_')) { + p++; + while (*p && (isalpha(*p) || isdigit(*p) || *p == '_')) p++; - /* allow blank lines and comment lines */ - if (*p == '\0' || *p == '#') - continue; + } + endword = p; + if (endword == word) { + logx(LOG_ERR, "%s:%d: expected variable name", + fnm, *line); + return; + } - /* first word must match a keyword */ - varp = NULL; - for (kvp = keywords; kvp->kw; kvp++) { - int len; - len = strlen(kvp->kw); + /* match the configuration variable name */ + varp = NULL; + savec = *endword; + *endword = '\0'; + for (kvp = keywords; kvp->kw; kvp++) + if (strcmp(kvp->kw, word) == 0) + break; + *endword = savec; - if (strncmp(kvp->kw, p, len) != 0) - continue; - if (isspace(p[len]) || p[len] == '=') - break; - } + if (kvp->kw == NULL) { + logx(LOG_ERR, + "%s:%d: unrecognised variable \"%.*s\"", + fnm, *line, endword - word, word); + return; + } - if (kvp->kw == NULL) { - fprintf(stderr, "%s:%d: unrecognised keyword\n", - fnm, line); - continue; - } + /* skip whitespace */ + while (*p && isspace(*p)) + p++; - p += strlen(kvp->kw); + if (*p++ != '=') { + logx(LOG_ERR, "%s:%d: expected `='", fnm, *line); + return; + } - /* skip whitespace */ - while (*p && isspace(*p)) - p++; + /* skip whitespace */ + while (*p && isspace(*p)) + p++; - if (*p++ != '=') { - fprintf(stderr, "%s:%d: expected `='\n", fnm, line); - continue; - } + /* parse the value */ + p = parse_value(p, kvp, fnm, line); + if (!p) + return; - /* skip whitespace */ - while (*p && isspace(*p)) - p++; + /* skip trailing whitespace */ + while (*p && isspace(*p)) + p++; - /* expect a number */ - value = p; - while (*p && isdigit(*p)) - p++; - if (!(*p == '\0' || isspace(*p) || *p == '#') || value == p) { - fprintf(stderr, "%s:%d: invalid value\n", - fnm, line); - continue; - } - *p = '\0'; - newval = atoi(value); + if (*p && *p != '#') { + logx(LOG_WARNING, "%s:%d: trailing garbage ignored", + fnm, *line); + } +} -#ifdef DIAGNOSTIC - if (newval != *kvp->var) - printf("%s:%d: %s: %d -> %d\n", fnm, line, - kvp->kw, *kvp->var, newval); -#endif - *kvp->var = newval; +static void +load_config(f, fnm) + FILE * f; + char * fnm; +{ + char buf[BUFSIZ]; + int len; + int line; + char *p; + + line = 0; + while ((p = fgetln(f, &len)) != NULL) { + line++; + if (p[len-1] == '\n') + len--; + if (len >= sizeof(buf)) { + logx(LOG_ERR, "%s:%d: line too long", fnm, line); + continue; + } + (void)memcpy(buf, p, len); + buf[len] = '\0'; + parse_line(buf, fnm, &line); } } @@ -211,7 +293,7 @@ config() char *home; char nm[MAXNAMLEN + 1]; static char *fnms[] = { - "/etc/hunt.conf" + "/etc/hunt.conf", "%s/.hunt.conf", ".hunt.conf", NULL @@ -219,14 +301,17 @@ config() int fn; FILE *f; + /* All the %s's get converted to $HOME */ if ((home = getenv("HOME")) == NULL) home = ""; for (fn = 0; fnms[fn]; fn++) { snprintf(nm, sizeof nm, fnms[fn], home); - if (f = fopen(nm, "r")) { + if ((f = fopen(nm, "r")) != NULL) { load_config(f, nm); fclose(f); - } + } + else if (errno != ENOENT) + log(LOG_WARNING, "%s", nm); } } diff --git a/games/hunt/huntd/conf.h b/games/hunt/huntd/conf.h index e40d908253f..fb88e07acb0 100644 --- a/games/hunt/huntd/conf.h +++ b/games/hunt/huntd/conf.h @@ -1,51 +1,53 @@ -/* $OpenBSD: conf.h,v 1.1 1999/01/29 07:30:34 d Exp $ */ +/* $OpenBSD: conf.h,v 1.2 1999/02/01 06:53:55 d Exp $ */ /* Configuration option variables for the server: */ -extern int conf_random; /* enable dispersion doors */ -extern int conf_reflect; /* enable generation of reflection walls */ -extern int conf_monitor; /* enable monitors */ -extern int conf_ooze; /* enable slime shots */ -extern int conf_fly; /* enable flight */ -extern int conf_volcano; /* enable volcanoes */ -extern int conf_drone; /* enable drone */ -extern int conf_boots; /* enable boots */ -extern int conf_scan; /* enable scanning */ -extern int conf_cloak; /* enable cloaking */ -extern int conf_logerr; /* errors to stderr as well as syslog(8) */ +extern int conf_random; +extern int conf_reflect; +extern int conf_monitor; +extern int conf_ooze; +extern int conf_fly; +extern int conf_volcano; +extern int conf_drone; +extern int conf_boots; +extern int conf_scan; +extern int conf_cloak; +extern int conf_logerr; +extern int conf_syslog; extern int conf_scoredecay; -extern int conf_maxremove; /* Maximum number of holes in the maze wall */ -extern int conf_linger; /* Seconds to keep game open with no players */ +extern int conf_maxremove; +extern int conf_linger; -extern int conf_flytime; /* max time flying */ -extern int conf_flystep; /* max displacement each flying time unit */ -extern int conf_volcano_max; /* max size of volcano */ -extern int conf_ptrip_face; /* chace of tripping a grenade on pickup, */ -extern int conf_ptrip_back; /* - when backing onto it */ -extern int conf_ptrip_side; /* - when walking sideways into it */ -extern int conf_prandom; /* percentage of time dispersion doors appear */ -extern int conf_preflect; /* percentage of time reflection walls appear */ -extern int conf_pshot_coll; /* percent chance of shots colliding */ -extern int conf_pgren_coll; /* percent chance of grenades colliding */ -extern int conf_pgren_catch; /* facing player chance of catching grenade */ -extern int conf_pmiss; /* chance of bullet missing player */ -extern int conf_pdroneabsorb; /* chance of absorbing a drone */ -extern int conf_fall_frac; /* divisor of damage used for fall damage */ +extern int conf_flytime; +extern int conf_flystep; +extern int conf_volcano_max; +extern int conf_ptrip_face; +extern int conf_ptrip_back; +extern int conf_ptrip_side; +extern int conf_prandom; +extern int conf_preflect; +extern int conf_pshot_coll; +extern int conf_pgren_coll; +extern int conf_pgren_catch; +extern int conf_pmiss; +extern int conf_pdroneabsorb; +extern int conf_fall_frac; -extern int conf_bulspd; /* speed of bullets */ -extern int conf_ishots; /* initial ammo for player */ -extern int conf_nshots; /* ammo boost for all when new player joins */ -extern int conf_maxncshot; /* max number of simultaneous shots per player*/ -extern int conf_maxdam; /* the initial shield for each player */ -extern int conf_mindam; /* minimum damage from one unit of ammo */ -extern int conf_stabdam; /* damage from stabbing */ -extern int conf_killgain; /* shield gained from killing someone */ -extern int conf_slimefactor; /* charge multiplier for slime */ -extern int conf_slimespeed; /* speed of slime */ -extern int conf_lavaspeed; /* speed of volcano lava */ -extern int conf_cloaklen; /* duration of a cloak */ -extern int conf_scanlen; /* duration of a scan */ -extern int conf_mindshot; /* minium shot class needed to make a drone */ +extern int conf_bulspd; +extern int conf_ishots; +extern int conf_nshots; +extern int conf_maxncshot; +extern int conf_maxdam; +extern int conf_mindam; +extern int conf_stabdam; +extern int conf_killgain; +extern int conf_slimefactor; +extern int conf_slimespeed; +extern int conf_lavaspeed; +extern int conf_cloaklen; +extern int conf_scanlen; +extern int conf_mindshot; +extern int conf_simstep; void config __P((void)); diff --git a/games/hunt/huntd/driver.c b/games/hunt/huntd/driver.c index 9a8af5a4fbd..a33b68ebfa8 100644 --- a/games/hunt/huntd/driver.c +++ b/games/hunt/huntd/driver.c @@ -1,4 +1,4 @@ -/* $OpenBSD: driver.c,v 1.3 1999/01/29 07:30:35 d Exp $ */ +/* $OpenBSD: driver.c,v 1.4 1999/02/01 06:53:56 d Exp $ */ /* $NetBSD: driver.c,v 1.5 1997/10/20 00:37:16 lukem Exp $ */ /* * Hunt @@ -20,6 +20,8 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <paths.h> +#include <fcntl.h> #include "hunt.h" #include "conf.h" #include "server.h" @@ -44,6 +46,9 @@ static void makeboots __P((void)); static void send_stats __P((void)); static void zap __P((PLAYER *, FLAG)); static void announce_game __P((void)); +static void siginfo __P((int)); +static void print_stats __P((FILE *)); +static void handle_wkport __P((int)); /* * main: @@ -56,15 +61,17 @@ main(ac, av, ep) { PLAYER *pp; int had_char; - short port_num, reply; static fd_set read_fds; static FLAG first = TRUE; static FLAG server = FALSE; extern int optind; extern char *optarg; int c; - FILE * cffile; static struct timeval linger = { 0, 0 }; + static struct timeval timeout = { 0, 0 }, *to; + struct spawn *sp; + int ret; + int nready; First_arg = av[0]; if (ep == NULL || *ep == NULL) @@ -108,81 +115,72 @@ erred: again: do { - /* Wait for something to happen: */ - read_fds = Fds_mask; - errno = 0; - while (select(Num_fds, &read_fds, NULL, NULL, NULL) < 0) - { - if (errno != EINTR) { - syslog(LOG_ERR, "select: %m"); + /* First, poll to see if we can get input */ + timerclear(&timeout); + do { + read_fds = Fds_mask; + errno = 0; + nready = select(Num_fds, &read_fds, NULL, NULL, + &timeout); + if (nready < 0 && errno != EINTR) { + log(LOG_ERR, "select"); cleanup(1); } - errno = 0; + } while (nready < 0); + + if (nready == 0) { + /* + * Nothing was ready. We do some work now + * to see if the simulation has any pending work + * to do, and decide if we need to to block + * indefinitely or just timeout. + */ + if (conf_simstep && can_moveshots()) { + /* + * block for a short time before continuing + * with explosions, bullets and whatnot + */ + to = &timeout; + to->tv_sec = conf_simstep / 1000000; + to->tv_usec = conf_simstep % 1000000; + } else + /* + * since there's nothing going on, + * just block waiting for external activity + */ + to = NULL; + + do { + read_fds = Fds_mask; + errno = 0; + nready = select(Num_fds, &read_fds, NULL, NULL, + to); + if (nready < 0 && errno != EINTR) { + log(LOG_ERR, "select"); + cleanup(1); + } + } while (nready < 0); } /* Remember which descriptors are active: */ Have_inp = read_fds; - /* Handle a datagram sent to the server socket: */ - if (FD_ISSET(Server_socket, &read_fds)) { - struct sockaddr_in test; - int namelen; - u_int16_t msg; - - namelen = sizeof test; - (void) recvfrom(Server_socket, - &msg, sizeof msg, - 0, - (struct sockaddr *) &test, &namelen); - - port_num = htons(sock_port); - switch (ntohs(msg)) { - case C_MESSAGE: - if (Nplayer <= 0) - break; - reply = htons((u_short) Nplayer); - (void) sendto(Server_socket, - &reply, sizeof reply, - 0, - (struct sockaddr *) &test, sizeof test); - break; - case C_SCORES: - reply = htons(stat_port); - (void) sendto(Server_socket, - &reply, sizeof reply, - 0, - (struct sockaddr *) &test, sizeof test); - break; - case C_PLAYER: - case C_MONITOR: - if (msg == C_MONITOR && Nplayer <= 0) - break; - reply = htons(sock_port); - (void) sendto(Server_socket, - &reply, sizeof reply, - 0, - (struct sockaddr *) &test, sizeof test); - break; + /* Answer new player connections: */ + if (FD_ISSET(Socket, &read_fds)) + answer_first(); + + /* Continue answering new player connections: */ + for (sp = Spawn; sp; sp = sp->next) + if (FD_ISSET(sp->fd, &read_fds) && answer_next(sp)) { + if (first && should_announce) + announce_game(); + first = FALSE; } - } /* Process input and move bullets until we've exhausted input */ - for (;;) { - had_char = FALSE; - for (pp = Player; pp < End_player; pp++) - if (havechar(pp)) { - execute(pp); - pp->p_nexec++; - had_char++; - } - for (pp = Monitor; pp < End_monitor; pp++) - if (havechar(pp)) { - mon_execute(pp); - pp->p_nexec++; - had_char++; - } - if (!had_char) - break; + had_char = TRUE; + while (had_char) { + moveshots(); for (pp = Player; pp < End_player; ) if (pp->p_death[0] != '\0') @@ -194,15 +192,25 @@ again: zap(pp, FALSE); else pp++; + + had_char = FALSE; + for (pp = Player; pp < End_player; pp++) + if (havechar(pp)) { + execute(pp); + pp->p_nexec++; + had_char = TRUE; + } + for (pp = Monitor; pp < End_monitor; pp++) + if (havechar(pp)) { + mon_execute(pp); + pp->p_nexec++; + had_char = TRUE; + } } - /* Answer new player connections: */ - if (FD_ISSET(Socket, &read_fds)) - if (answer()) { - if (first && should_announce) - announce_game(); - first = FALSE; - } + /* Handle a datagram sent to the server socket: */ + if (FD_ISSET(Server_socket, &read_fds)) + handle_wkport(Server_socket); /* Answer statistics connections: */ if (FD_ISSET(Status, &read_fds)) @@ -223,15 +231,27 @@ again: } } while (Nplayer > 0); - /* No more players. Wait for a short while for one to come back: */ + /* No more players! */ + + /* Continuous game? */ + if (conf_linger < 0) + goto again; + + /* Wait a short while for one to come back: */ read_fds = Fds_mask; linger.tv_sec = conf_linger; - if (select(Num_fds, &read_fds, NULL, NULL, &linger) > 0) { + while ((ret = select(Num_fds, &read_fds, NULL, NULL, &linger)) < 0) { + if (errno != EINTR) { + log(LOG_WARNING, "select"); + break; + } + } + if (ret > 0) /* Someone returned! Resume the game: */ goto again; - } + /* else, it timed out, and the game is really over. */ - /* If we are an inetd server, we should restart: */ + /* If we are an inetd server, we should re-init the map and restart: */ if (server) { clear_scores(); makemaze(); @@ -241,11 +261,11 @@ again: goto again; } - /* Destroy all the monitors: */ + /* Get rid of any attached monitors: */ for (pp = Monitor; pp < End_monitor; ) zap(pp, FALSE); - /* The end: */ + /* Fin: */ cleanup(0); exit(0); } @@ -262,20 +282,39 @@ init() int msg; int len; struct sockaddr_in addr; + struct sigaction sact; - /* XXX should we call deamon() instead ??? */ (void) setsid(); - (void) setpgid(getpid(), getpid()); - - /* Handle some signals: */ - (void) signal(SIGHUP, SIG_IGN); - (void) signal(SIGINT, cleanup); - (void) signal(SIGQUIT, SIG_IGN); - (void) signal(SIGTERM, cleanup); - (void) signal(SIGPIPE, SIG_IGN); - - (void) chdir("/"); /* just in case it core dumps */ - (void) umask(0777); /* No privacy at all! */ + if (setpgid(getpid(), getpid()) == -1) + err(1, "setpgid"); + + sact.sa_flags = SA_RESTART; + sigemptyset(&sact.sa_mask); + + /* Ignore HUP, QUIT and PIPE: */ + sact.sa_handler = SIG_IGN; + if (sigaction(SIGHUP, &sact, NULL) == -1) + err(1, "sigaction SIGHUP"); + if (sigaction(SIGQUIT, &sact, NULL) == -1) + err(1, "sigaction SIGQUIT"); + if (sigaction(SIGPIPE, &sact, NULL) == -1) + err(1, "sigaction SIGPIPE"); + + /* Clean up gracefully on INT and TERM: */ + sact.sa_handler = cleanup; + if (sigaction(SIGINT, &sact, NULL) == -1) + err(1, "sigaction SIGINT"); + if (sigaction(SIGTERM, &sact, NULL) == -1) + err(1, "sigaction SIGTERM"); + + /* Handle INFO: */ + sact.sa_handler = siginfo; + if (sigaction(SIGINFO, &sact, NULL) == -1) + err(1, "sigaction SIGINFO"); + + if (chdir("/") == -1) + warn("chdir"); + (void) umask(0777); /* Initialize statistics socket: */ addr.sin_family = AF_INET; @@ -284,14 +323,17 @@ init() Status = socket(AF_INET, SOCK_STREAM, 0); if (bind(Status, (struct sockaddr *) &addr, sizeof addr) < 0) { - syslog(LOG_ERR, "bind: %m"); + log(LOG_ERR, "bind"); + cleanup(1); + } + if (listen(Status, 5) == -1) { + log(LOG_ERR, "listen"); cleanup(1); } - (void) listen(Status, 5); len = sizeof (struct sockaddr_in); if (getsockname(Status, (struct sockaddr *) &addr, &len) < 0) { - syslog(LOG_ERR, "getsockname: %m"); + log(LOG_ERR, "getsockname"); cleanup(1); } stat_port = ntohs(addr.sin_port); @@ -304,16 +346,19 @@ init() Socket = socket(AF_INET, SOCK_STREAM, 0); msg = 1; if (setsockopt(Socket, SOL_SOCKET, SO_USELOOPBACK, &msg, sizeof msg)<0) - syslog(LOG_ERR, "setsockopt loopback %m"); + log(LOG_ERR, "setsockopt loopback"); if (bind(Socket, (struct sockaddr *) &addr, sizeof addr) < 0) { - syslog(LOG_ERR, "bind: %m"); + log(LOG_ERR, "bind"); + cleanup(1); + } + if (listen(Socket, 5) == -1) { + log(LOG_ERR, "listen"); cleanup(1); } - (void) listen(Socket, 5); len = sizeof (struct sockaddr_in); if (getsockname(Socket, (struct sockaddr *) &addr, &len) < 0) { - syslog(LOG_ERR, "getsockname: %m"); + log(LOG_ERR, "getsockname"); cleanup(1); } sock_port = ntohs(addr.sin_port); @@ -343,10 +388,11 @@ init() Server_socket = socket(AF_INET, SOCK_DGRAM, 0); if (bind(Server_socket, (struct sockaddr *) &test_port, sizeof test_port) < 0) { - syslog(LOG_ERR, "bind port %d: %m", Server_port); + log(LOG_ERR, "bind port %d", Server_port); cleanup(1); } - (void) listen(Server_socket, 5); + + /* Datagram sockets do not need a listen() call. */ } /* We'll handle the broadcast listener in the main loop: */ @@ -373,7 +419,7 @@ init() See_over[WALL4] = FALSE; See_over[WALL5] = FALSE; - syslog(LOG_INFO, "game started"); + logx(LOG_INFO, "game started"); } /* @@ -821,19 +867,29 @@ havechar(pp) PLAYER *pp; { + /* Do we already have characters? */ if (pp->p_ncount < pp->p_nchar) return TRUE; + /* Is the player being quiet? */ if (!FD_ISSET(pp->p_fd, &Have_inp)) return FALSE; + /* Remove the player from the read set until we have drained them: */ FD_CLR(pp->p_fd, &Have_inp); + + /* Suck their keypresses into a buffer: */ check_again: - errno = 0; if ((pp->p_nchar = read(pp->p_fd, pp->p_cbuf, sizeof pp->p_cbuf)) <= 0) { if (errno == EINTR) goto check_again; - pp->p_cbuf[0] = 'q'; + if (errno != EAGAIN) { + log(LOG_INFO, "read"); + /* Assume their connection was lost/closed: */ + pp->p_cbuf[0] = 'q'; + pp->p_nchar = 1; + } } + /* Reset pointer into read buffer */ pp->p_ncount = 0; return TRUE; } @@ -864,7 +920,7 @@ cleanup(eval) (void) close(Socket); /* The end: */ - syslog(LOG_INFO, "game over"); + logx(LOG_INFO, "game over"); exit(eval); } @@ -876,7 +932,6 @@ cleanup(eval) static void send_stats() { - IDENT *ip; FILE *fp; int s; struct sockaddr_in sockstruct; @@ -889,7 +944,7 @@ send_stats() if (s < 0) { if (errno == EINTR) return; - syslog(LOG_ERR, "accept: %m"); + logx(LOG_ERR, "accept"); return; } @@ -902,11 +957,27 @@ send_stats() fp = fdopen(s, "w"); if (fp == NULL) { - syslog(LOG_ERR, "fdopen: %m"); + log(LOG_ERR, "fdopen"); (void) close(s); return; } + print_stats(fp); + + (void) fclose(fp); +} + +/* + * print_stats: + * emit the game statistics + */ +void +print_stats(fp) + FILE *fp; +{ + IDENT *ip; + PLAYER *pp; + /* Send the statistics as raw text down the socket: */ fputs("Name\t\tScore\tDucked\tAbsorb\tFaced\tShot\tRobbed\tMissed\tSlimeK\n", fp); for (ip = Scores; ip != NULL; ip = ip->i_next) { @@ -922,7 +993,7 @@ send_stats() ip->i_faced, ip->i_shot, ip->i_robbed, ip->i_missed, ip->i_slime); } - fputs("\n\nName\t\tEnemy\tFriend\tDeaths\tStill\tSaved\n", fp); + fputs("\n\nName\t\tEnemy\tFriend\tDeaths\tStill\tSaved\tConnect\n", fp); for (ip = Scores; ip != NULL; ip = ip->i_next) { fprintf(fp, "%s%c%c%c\t", ip->i_name, ip->i_team == ' ' ? ' ' : '[', @@ -931,12 +1002,36 @@ send_stats() ); if (strlen(ip->i_name) + 3 < 8) putc('\t', fp); - fprintf(fp, "%d\t%d\t%d\t%d\t%d\n", + fprintf(fp, "%d\t%d\t%d\t%d\t%d\t", ip->i_gkills, ip->i_bkills, ip->i_deaths, ip->i_stillb, ip->i_saved); + for (pp = Player; pp < End_player; pp++) + if (pp->p_ident == ip) + putc('p', fp); + for (pp = Monitor; pp < End_monitor; pp++) + if (pp->p_ident == ip) + putc('m', fp); + putc('\n', fp); } +} - (void) fclose(fp); + +/* + * Send the game statistics to the controlling tty + */ +static void +siginfo(sig) + int sig; +{ + int tty; + FILE *fp; + + if ((tty = open(_PATH_TTY, O_WRONLY)) >= 0) { + fp = fdopen(tty, "w"); + print_stats(fp); + answer_info(fp); + fclose(fp); + } } /* @@ -951,7 +1046,7 @@ clear_scores() /* Release the list of scores: */ for (ip = Scores; ip != NULL; ip = nextip) { nextip = ip->i_next; - (void) free((char *) ip); + free((char *) ip); } Scores = NULL; } @@ -966,3 +1061,55 @@ announce_game() /* Stub */ } + +/* + * Handle a UDP packet sent to the well known port. + */ +static void +handle_wkport(fd) + int fd; +{ + struct sockaddr fromaddr; + int fromlen; + u_int16_t query; + u_int16_t response; + + fromlen = sizeof fromaddr; + if (recvfrom(fd, &query, sizeof query, 0, &fromaddr, &fromlen) == -1) + { + log(LOG_WARNING, "recvfrom"); + return; + } + query = ntohs(query); + + switch (query) { + case C_MESSAGE: + if (Nplayer <= 0) + /* Don't bother replying if nobody to talk to: */ + return; + /* Return the number of people playing: */ + response = Nplayer; + break; + case C_SCORES: + /* Someone wants the statistics port: */ + response = stat_port; + break; + case C_PLAYER: + case C_MONITOR: + /* Someone wants to play or watch: */ + if (query == C_MONITOR && Nplayer <= 0) + /* Don't bother replying if there's nothing to watch: */ + return; + /* Otherwise, tell them how to get to the game: */ + response = sock_port; + break; + default: + log(LOG_INFO, "unknown udp query %d", query); + return; + } + + response = ntohs(response); + if (sendto(fd, &response, sizeof response, 0, + &fromaddr, sizeof fromaddr) == -1) + log(LOG_WARNING, "sendto"); +} diff --git a/games/hunt/huntd/execute.c b/games/hunt/huntd/execute.c index 8719f63dac3..6841907c2cb 100644 --- a/games/hunt/huntd/execute.c +++ b/games/hunt/huntd/execute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: execute.c,v 1.3 1999/01/29 07:30:35 d Exp $ */ +/* $OpenBSD: execute.c,v 1.4 1999/02/01 06:53:56 d Exp $ */ /* $NetBSD: execute.c,v 1.2 1997/10/10 16:33:13 lukem Exp $ */ /* * Hunt @@ -492,7 +492,7 @@ create_shot(type, y, x, face, charge, size, owner, score, expl, over) bp = (BULLET *) malloc(sizeof (BULLET)); /* NOSTRICT */ if (bp == NULL) { - syslog(LOG_ERR, "malloc: %m"); + log(LOG_ERR, "malloc"); if (owner != NULL) message(owner, "Out of memory"); return NULL; diff --git a/games/hunt/huntd/expl.c b/games/hunt/huntd/expl.c index bf0eeea5bc0..53b6669fc08 100644 --- a/games/hunt/huntd/expl.c +++ b/games/hunt/huntd/expl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: expl.c,v 1.3 1999/01/29 07:30:35 d Exp $ */ +/* $OpenBSD: expl.c,v 1.4 1999/02/01 06:53:56 d Exp $ */ /* $NetBSD: expl.c,v 1.2 1997/10/10 16:33:18 lukem Exp $ */ /* * Hunt @@ -8,6 +8,7 @@ #include <stdlib.h> #include <syslog.h> +#include <string.h> #include "hunt.h" #include "server.h" #include "conf.h" @@ -101,11 +102,23 @@ rollexpl() check(pp, y, x); free((char *) ep); } - for (x = EXPLEN - 1; x > 0; x--) - Expl[x] = Expl[x - 1]; + memmove(&Expl[1], &Expl[0], (EXPLEN - 1) * sizeof Expl[0]); + /* for (x = EXPLEN - 1; x > 0; x--) + Expl[x] = Expl[x - 1]; */ Last_expl = Expl[0] = NULL; } +int +can_rollexpl() +{ + int i; + + for (i = EXPLEN - 1; i >= 0; i--) + if (Expl[i] != NULL) + return 1; + return 0; +} + static REGEN *removed = NULL; static REGEN *rem_index = NULL; @@ -114,7 +127,7 @@ init_removed() { rem_index = removed = malloc(conf_maxremove * sizeof(REGEN)); if (rem_index == NULL) { - syslog(LOG_ERR, "malloc: %m"); + log(LOG_ERR, "malloc"); cleanup(1); } } @@ -133,7 +146,7 @@ remove_wall(y, x) char save_char = 0; if (removed == NULL) - init_removed(); + clearwalls(); r = rem_index; while (r->r_y != 0) { diff --git a/games/hunt/huntd/huntd.6 b/games/hunt/huntd/huntd.6 index b991bcf4ff7..e85a6261a8c 100644 --- a/games/hunt/huntd/huntd.6 +++ b/games/hunt/huntd/huntd.6 @@ -1,5 +1,5 @@ .\" $NetBSD: huntd.6,v 1.3 1998/01/09 08:03:42 perry Exp $ -.\" $OpenBSD: huntd.6,v 1.3 1999/01/29 07:30:36 d Exp $ +.\" $OpenBSD: huntd.6,v 1.4 1999/02/01 06:53:56 d Exp $ .\" .\" Hunt .\" Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold @@ -131,13 +131,15 @@ enable scanning (default 1) .It cloak enable cloaking (default 1) .It logerr -errors to stderr as well as syslog(8) (default 1) +errors to stderr (default 1) +.It syslog +errors to syslog(8) (default 0) .It scoredecay nr deaths before nr kills begins to decay (default 15) .It maxremove Maximum number of holes in the maze wall (default 40) .It linger -Seconds to keep game open with no players (default 90) +Seconds to keep game open with no players. \&-1 means forever. (default 90) .It flytime max time flying (default 20) .It flystep @@ -194,6 +196,9 @@ duration of a cloak (default 20) duration of a scan (default 20) .It mindshot minimum shot class needed to make a drone (default 2) +.It simstep +minimum simulation step in microseconds. Zero means traditional blocking +behaviour. Try 55000 for something reasonable (default 0) .El .Sh "SEE ALSO" .Xr hunt 6 , diff --git a/games/hunt/huntd/server.h b/games/hunt/huntd/server.h index b6c79f952df..9731d08da2a 100644 --- a/games/hunt/huntd/server.h +++ b/games/hunt/huntd/server.h @@ -1,4 +1,4 @@ -/* $OpenBSD: server.h,v 1.1 1999/01/29 07:30:36 d Exp $ */ +/* $OpenBSD: server.h,v 1.2 1999/02/01 06:53:56 d Exp $ */ /* $NetBSD: hunt.h,v 1.5 1998/09/13 15:27:28 hubertf Exp $ */ /* @@ -8,6 +8,7 @@ */ #include <stdio.h> +#include <sys/socket.h> /* * Choose MAXPL and MAXMON carefully. The screen is assumed to be @@ -158,11 +159,32 @@ struct regen_def { REGEN *r_next; }; +struct spawn { + int fd; + int state; + struct sockaddr source; + int sourcelen; + u_int32_t uid; + char name[NAMELEN+1]; + u_int8_t team; + u_int32_t enter_status; + char ttyname[NAMELEN]; + u_int32_t mode; + char msg[BUFSIZ]; + int msglen; + struct spawn * next; + struct spawn ** prevnext; +}; + +extern struct spawn * Spawn; + extern int Socket; /* answer.c */ -int answer __P((void)); +void answer_first __P((void)); +int answer_next __P((struct spawn *)); int rand_dir __P((void)); +void answer_info __P((FILE *)); /* draw.c */ void drawmaze __P((PLAYER *)); @@ -190,11 +212,13 @@ void showexpl __P((int, int, char)); void rollexpl __P((void)); void makemaze __P((void)); void clearwalls __P((void)); +int can_rollexpl __P((void)); /* makemaze.c */ void makemaze __P((void)); /* shots.c */ +int can_moveshots __P((void)); void moveshots __P((void)); PLAYER *play_at __P((int, int)); int opposite __P((int, char)); @@ -211,6 +235,10 @@ void clrscr __P((PLAYER *)); void ce __P((PLAYER *)); void sendcom __P((PLAYER *, int, ...)); void flush __P((PLAYER *)); +void log __P((int, const char *, ...)) + __attribute__((format (printf, 2, 3))); +void logx __P((int, const char *, ...)) + __attribute__((format (printf, 2, 3))); /* extern.c */ extern FLAG Am_monitor; diff --git a/games/hunt/huntd/shots.c b/games/hunt/huntd/shots.c index 9e06c95d585..dfbb716bc1a 100644 --- a/games/hunt/huntd/shots.c +++ b/games/hunt/huntd/shots.c @@ -1,4 +1,4 @@ -/* $OpenBSD: shots.c,v 1.3 1999/01/29 07:30:36 d Exp $ */ +/* $OpenBSD: shots.c,v 1.4 1999/02/01 06:53:56 d Exp $ */ /* $NetBSD: shots.c,v 1.3 1997/10/11 08:13:50 lukem Exp $ */ /* * Hunt @@ -31,6 +31,32 @@ static void move_slime __P((BULLET *, int, BULLET *)); static void save_bullet __P((BULLET *)); static void zapshot __P((BULLET *, BULLET *)); +/* Return true if there is pending activity */ +int +can_moveshots() +{ + PLAYER *pp; + + /* Bullets are moving? */ + if (Bullets) + return 1; + + /* Explosions are happening? */ + if (can_rollexpl()) + return 1; + + /* Things are flying? */ + for (pp = Boot; pp < &Boot[NBOOTS]; pp++) + if (pp->p_flying >= 0) + return 1; + for (pp = Player; pp < End_player; pp++) + if (pp->p_flying >= 0) + return 1; + + /* Everything is quiet: */ + return 0; +} + /* * moveshots: * Move the shots already in the air, taking explosions into account @@ -826,7 +852,7 @@ chkslime(bp, next) /* Duplicate the unit of slime: */ nbp = (BULLET *) malloc(sizeof (BULLET)); if (nbp == NULL) { - syslog(LOG_ERR, "malloc: %m"); + log(LOG_ERR, "malloc"); return; } *nbp = *bp; @@ -1078,7 +1104,7 @@ play_at(y, x) return pp; /* Internal fault: */ - syslog(LOG_ERR, "play_at: not a player"); + logx(LOG_ERR, "play_at: not a player"); abort(); } diff --git a/games/hunt/huntd/terminal.c b/games/hunt/huntd/terminal.c index 0b7efdd88b6..8b7780a9ff1 100644 --- a/games/hunt/huntd/terminal.c +++ b/games/hunt/huntd/terminal.c @@ -1,4 +1,4 @@ -/* $OpenBSD: terminal.c,v 1.3 1999/01/29 07:30:37 d Exp $ */ +/* $OpenBSD: terminal.c,v 1.4 1999/02/01 06:53:56 d Exp $ */ /* $NetBSD: terminal.c,v 1.2 1997/10/10 16:34:05 lukem Exp $ */ /* * Hunt @@ -7,8 +7,13 @@ */ #include <stdarg.h> +#include <syslog.h> +#include <err.h> +#include <string.h> + #include "hunt.h" #include "server.h" +#include "conf.h" #define TERM_WIDTH 80 /* Assume terminals are 80-char wide */ @@ -201,3 +206,37 @@ flush(pp) fflush(pp->p_output); } +void +logx(prio, fmt) + int prio; + const char *fmt; +{ + va_list ap; + + va_start(ap, fmt); + if (conf_syslog) + vsyslog(prio, fmt, ap); + else if (conf_logerr) + /* if (prio < LOG_NOTICE) */ + vwarnx(fmt, ap); + va_end(fmt); +} + +void +log(prio, fmt) + int prio; + const char *fmt; +{ + va_list ap; + char fmtm[1024]; + + va_start(ap, fmt); + if (conf_syslog) { + strlcpy(fmtm, fmt, sizeof fmtm); + strlcat(fmtm, ": %m", sizeof fmtm); + vsyslog(prio, fmtm, ap); + } else if (conf_logerr) + /* if (prio < LOG_NOTICE) */ + vwarn(fmt, ap); + va_end(fmt); +} |