diff options
Diffstat (limited to 'hunt')
-rw-r--r-- | hunt/hunt/Makefile | 4 | ||||
-rw-r--r-- | hunt/hunt/hunt.c | 203 | ||||
-rw-r--r-- | hunt/hunt/hunt_private.h | 18 | ||||
-rw-r--r-- | hunt/hunt/server.c | 235 |
4 files changed, 263 insertions, 197 deletions
diff --git a/hunt/hunt/Makefile b/hunt/hunt/Makefile index 2279cc19..602b31fd 100644 --- a/hunt/hunt/Makefile +++ b/hunt/hunt/Makefile @@ -1,7 +1,7 @@ -# $NetBSD: Makefile,v 1.8 2014/03/29 21:24:26 dholland Exp $ +# $NetBSD: Makefile,v 1.9 2014/03/30 02:26:09 dholland Exp $ PROG= hunt -SRCS= connect.c hunt.c otto.c playit.c +SRCS= connect.c hunt.c otto.c playit.c server.c MAN= hunt.6 LDADD= -lcurses -lterminfo DPADD= ${LIBCURSES} ${LIBTERMINFO} diff --git a/hunt/hunt/hunt.c b/hunt/hunt/hunt.c index 4cd9d7a5..8f577b27 100644 --- a/hunt/hunt/hunt.c +++ b/hunt/hunt/hunt.c @@ -1,4 +1,4 @@ -/* $NetBSD: hunt.c,v 1.47 2014/03/29 22:15:13 dholland Exp $ */ +/* $NetBSD: hunt.c,v 1.48 2014/03/30 02:26:09 dholland Exp $ */ /* * Copyright (c) 1983-2003, Regents of the University of California. * All rights reserved. @@ -32,7 +32,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: hunt.c,v 1.47 2014/03/29 22:15:13 dholland Exp $"); +__RCSID("$NetBSD: hunt.c,v 1.48 2014/03/30 02:26:09 dholland Exp $"); #endif /* not lint */ #include <sys/param.h> @@ -64,7 +64,7 @@ static const char Driver[] = PATH_HUNTD; #endif #ifdef INTERNET -static uint16_t Test_port = TEST_PORT; +uint16_t Test_port = TEST_PORT; #else static const char Sock_name[] = PATH_HUNTSOCKET; #endif @@ -79,14 +79,14 @@ char Buf[BUFSIZ]; /*static*/ int Socket; #ifdef INTERNET -static char *Sock_host; +char *Sock_host; static char *use_port; -static bool Query_driver = false; +bool Query_driver = false; char *Send_message = NULL; -static bool Show_scores = false; +bool Show_scores = false; #endif -static SOCKET Daemon; +SOCKET Daemon; #ifdef INTERNET #define DAEMON_SIZE (sizeof Daemon) #else @@ -106,18 +106,12 @@ extern int cur_row, cur_col; static void dump_scores(SOCKET); static long env_init(long); static void fill_in_blanks(void); -static void leave(int, const char *) __dead; -static void leavex(int, const char *) __dead; static void fincurs(void); static void rmnl(char *); static void sigterm(int) __dead; static void sigusr1(int) __dead; static void find_driver(bool); static void start_driver(void); -static int broadcast_vec(int, struct sockaddr_in **); -#ifdef INTERNET -static SOCKET *list_drivers(void); -#endif extern int Otto_mode; /* @@ -351,185 +345,6 @@ main(int ac, char **av) } #ifdef INTERNET -static int -broadcast_vec(int s /*socket*/, struct sockaddr_in **vector) -{ - int vec_cnt; - struct ifaddrs *ifp, *ip; - - *vector = NULL; - if (getifaddrs(&ifp) < 0) - return 0; - - vec_cnt = 0; - for (ip = ifp; ip; ip = ip->ifa_next) - if ((ip->ifa_addr->sa_family == AF_INET) && - (ip->ifa_flags & IFF_BROADCAST)) - vec_cnt++; - - *vector = malloc(vec_cnt * sizeof(struct sockaddr_in)); - - vec_cnt = 0; - for (ip = ifp; ip; ip = ip->ifa_next) - if ((ip->ifa_addr->sa_family == AF_INET) && - (ip->ifa_flags & IFF_BROADCAST)) - memcpy(&(*vector)[vec_cnt++], ip->ifa_broadaddr, - sizeof(struct sockaddr_in)); - - freeifaddrs(ifp); - return vec_cnt; -} - -static SOCKET * -list_drivers(void) -{ - int option; - u_short msg; - u_short port_num; - static SOCKET test; - int test_socket; - socklen_t namelen; - char local_name[MAXHOSTNAMELEN + 1]; - static bool initial = true; - static struct in_addr local_address; - struct hostent *hp; - static int brdc; - static SOCKET *brdv; - int i; - unsigned j; - static SOCKET *listv; - static unsigned int listmax; - unsigned int listc; - struct pollfd set[1]; - - if (initial) { /* do one time initialization */ - if (gethostname(local_name, sizeof local_name) < 0) { - leavex(1, "Sorry, I have no name."); - /* NOTREACHED */ - } - local_name[sizeof(local_name) - 1] = '\0'; - if ((hp = gethostbyname(local_name)) == NULL) { - leavex(1, "Can't find myself."); - /* NOTREACHED */ - } - local_address = * ((struct in_addr *) hp->h_addr); - - listmax = 20; - listv = (SOCKET *) malloc(listmax * sizeof (SOCKET)); - } else if (Sock_host != NULL) - return listv; /* address already valid */ - - test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0); - if (test_socket < 0) { - leave(1, "socket system call failed"); - /* NOTREACHED */ - } - test.sin_family = SOCK_FAMILY; - test.sin_port = htons(Test_port); - listc = 0; - - if (Sock_host != NULL) { /* explicit host given */ - if ((hp = gethostbyname(Sock_host)) == NULL) { - leavex(1, "Unknown host"); - /* NOTREACHED */ - } - test.sin_addr = *((struct in_addr *) hp->h_addr); - goto test_one_host; - } - - if (!initial) { - /* favor host of previous session by broadcasting to it first */ - test.sin_addr = Daemon.sin_addr; - msg = htons(C_PLAYER); /* Must be playing! */ - (void) sendto(test_socket, &msg, sizeof msg, 0, - (struct sockaddr *) &test, DAEMON_SIZE); - } - - if (initial) - brdc = broadcast_vec(test_socket, &brdv); - -#ifdef SO_BROADCAST - /* Sun's will broadcast even though this option can't be set */ - option = 1; - if (setsockopt(test_socket, SOL_SOCKET, SO_BROADCAST, - &option, sizeof option) < 0) { - leave(1, "setsockopt broadcast"); - /* NOTREACHED */ - } -#endif - - /* send broadcast packets on all interfaces */ - msg = htons(C_TESTMSG()); - for (i = 0; i < brdc; i++) { - test.sin_addr = brdv[i].sin_addr; - if (sendto(test_socket, &msg, sizeof msg, 0, - (struct sockaddr *) &test, DAEMON_SIZE) < 0) { - leave(1, "sendto"); - /* NOTREACHED */ - } - } - test.sin_addr = local_address; - if (sendto(test_socket, &msg, sizeof msg, 0, - (struct sockaddr *) &test, DAEMON_SIZE) < 0) { - leave(1, "sendto"); - /* NOTREACHED */ - } - -get_response: - namelen = DAEMON_SIZE; - errno = 0; - set[0].fd = test_socket; - set[0].events = POLLIN; - for (;;) { - if (listc + 1 >= listmax) { - SOCKET *newlistv; - - listmax += 20; - newlistv = realloc(listv, listmax * sizeof(*listv)); - if (newlistv == NULL) - leave(1, "realloc"); - listv = newlistv; - } - - if (poll(set, 1, 1000) == 1 && - recvfrom(test_socket, &port_num, sizeof(port_num), - 0, (struct sockaddr *) &listv[listc], &namelen) > 0) { - /* - * Note that we do *not* convert from network to host - * order since the port number *should* be in network - * order: - */ - for (j = 0; j < listc; j += 1) - if (listv[listc].sin_addr.s_addr - == listv[j].sin_addr.s_addr) - break; - if (j == listc) - listv[listc++].sin_port = port_num; - continue; - } - - if (errno != 0 && errno != EINTR) { - leave(1, "poll/recvfrom"); - /* NOTREACHED */ - } - - /* terminate list with local address */ - listv[listc].sin_family = SOCK_FAMILY; - listv[listc].sin_addr = local_address; - listv[listc].sin_port = htons(0); - - (void) close(test_socket); - initial = false; - return listv; - } - -test_one_host: - msg = htons(C_TESTMSG()); - (void) sendto(test_socket, &msg, sizeof msg, 0, - (struct sockaddr *) &test, DAEMON_SIZE); - goto get_response; -} - static void find_driver(bool do_startup) { @@ -772,7 +587,7 @@ fincurs(void) * Leave the game somewhat gracefully, restoring all current * tty stats, and print errno. */ -static void +void leave(int eval, const char *mesg) { int serrno = errno; @@ -786,7 +601,7 @@ leave(int eval, const char *mesg) * Leave the game somewhat gracefully, restoring all current * tty stats. */ -static void +void leavex(int eval, const char *mesg) { fincurs(); diff --git a/hunt/hunt/hunt_private.h b/hunt/hunt/hunt_private.h index c84f486b..4f7b8693 100644 --- a/hunt/hunt/hunt_private.h +++ b/hunt/hunt/hunt_private.h @@ -1,4 +1,4 @@ -/* $NetBSD: hunt_private.h,v 1.3 2014/03/29 22:15:26 dholland Exp $ */ +/* $NetBSD: hunt_private.h,v 1.4 2014/03/30 02:26:09 dholland Exp $ */ /* * Copyright (c) 1983-2003, Regents of the University of California. @@ -74,6 +74,15 @@ extern bool Am_monitor; extern char map_key[256]; extern bool no_beep; +#ifdef INTERNET +/* XXX this pile had to be made public to split off server.c; fix them up */ +extern SOCKET Daemon; +extern uint16_t Test_port; +extern char *Sock_host; +extern bool Query_driver; +extern bool Show_scores; +#endif + /* * function types */ @@ -84,6 +93,8 @@ void do_connect(char *, char, long); /* in hunt.c */ __dead void bad_con(void); __dead void bad_ver(void); +__dead void leave(int, const char *); +__dead void leavex(int, const char *); void intr(int); /* in otto.c */ @@ -94,3 +105,8 @@ void playit(void); int quit(int); void clear_the_screen(void); void do_message(void); + +/* in server.c */ +#ifdef INTERNET +SOCKET *list_drivers(void); +#endif diff --git a/hunt/hunt/server.c b/hunt/hunt/server.c new file mode 100644 index 00000000..da7f14d2 --- /dev/null +++ b/hunt/hunt/server.c @@ -0,0 +1,235 @@ +/* $NetBSD: server.c,v 1.1 2014/03/30 02:26:09 dholland Exp $ */ +/* + * Copyright (c) 1983-2003, Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * + Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + Neither the name of the University of California, San Francisco nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__RCSID("$NetBSD: server.c,v 1.1 2014/03/30 02:26:09 dholland Exp $"); + +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/poll.h> +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <curses.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ifaddrs.h> + +#include "hunt_common.h" +#include "pathnames.h" +#include "hunt_private.h" + +#ifdef INTERNET + +static int +broadcast_vec(int s /*socket*/, struct sockaddr_in **vector) +{ + int vec_cnt; + struct ifaddrs *ifp, *ip; + + *vector = NULL; + if (getifaddrs(&ifp) < 0) + return 0; + + vec_cnt = 0; + for (ip = ifp; ip; ip = ip->ifa_next) + if ((ip->ifa_addr->sa_family == AF_INET) && + (ip->ifa_flags & IFF_BROADCAST)) + vec_cnt++; + + *vector = malloc(vec_cnt * sizeof(struct sockaddr_in)); + + vec_cnt = 0; + for (ip = ifp; ip; ip = ip->ifa_next) + if ((ip->ifa_addr->sa_family == AF_INET) && + (ip->ifa_flags & IFF_BROADCAST)) + memcpy(&(*vector)[vec_cnt++], ip->ifa_broadaddr, + sizeof(struct sockaddr_in)); + + freeifaddrs(ifp); + return vec_cnt; +} + +SOCKET * +list_drivers(void) +{ + int option; + u_short msg; + u_short port_num; + static SOCKET test; + int test_socket; + socklen_t namelen; + char local_name[MAXHOSTNAMELEN + 1]; + static bool initial = true; + static struct in_addr local_address; + struct hostent *hp; + static int brdc; + static SOCKET *brdv; + int i; + unsigned j; + static SOCKET *listv; + static unsigned int listmax; + unsigned int listc; + struct pollfd set[1]; + + if (initial) { /* do one time initialization */ + if (gethostname(local_name, sizeof local_name) < 0) { + leavex(1, "Sorry, I have no name."); + /* NOTREACHED */ + } + local_name[sizeof(local_name) - 1] = '\0'; + if ((hp = gethostbyname(local_name)) == NULL) { + leavex(1, "Can't find myself."); + /* NOTREACHED */ + } + local_address = * ((struct in_addr *) hp->h_addr); + + listmax = 20; + listv = (SOCKET *) malloc(listmax * sizeof (SOCKET)); + } else if (Sock_host != NULL) + return listv; /* address already valid */ + + test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0); + if (test_socket < 0) { + leave(1, "socket system call failed"); + /* NOTREACHED */ + } + test.sin_family = SOCK_FAMILY; + test.sin_port = htons(Test_port); + listc = 0; + + if (Sock_host != NULL) { /* explicit host given */ + if ((hp = gethostbyname(Sock_host)) == NULL) { + leavex(1, "Unknown host"); + /* NOTREACHED */ + } + test.sin_addr = *((struct in_addr *) hp->h_addr); + goto test_one_host; + } + + if (!initial) { + /* favor host of previous session by broadcasting to it first */ + test.sin_addr = Daemon.sin_addr; + msg = htons(C_PLAYER); /* Must be playing! */ + (void) sendto(test_socket, &msg, sizeof msg, 0, + (struct sockaddr *) &test, sizeof(test)); + } + + if (initial) + brdc = broadcast_vec(test_socket, &brdv); + +#ifdef SO_BROADCAST + /* Sun's will broadcast even though this option can't be set */ + option = 1; + if (setsockopt(test_socket, SOL_SOCKET, SO_BROADCAST, + &option, sizeof option) < 0) { + leave(1, "setsockopt broadcast"); + /* NOTREACHED */ + } +#endif + + /* send broadcast packets on all interfaces */ + msg = htons(C_TESTMSG()); + for (i = 0; i < brdc; i++) { + test.sin_addr = brdv[i].sin_addr; + if (sendto(test_socket, &msg, sizeof msg, 0, + (struct sockaddr *) &test, sizeof(test)) < 0) { + leave(1, "sendto"); + /* NOTREACHED */ + } + } + test.sin_addr = local_address; + if (sendto(test_socket, &msg, sizeof msg, 0, + (struct sockaddr *) &test, sizeof(test)) < 0) { + leave(1, "sendto"); + /* NOTREACHED */ + } + +get_response: + namelen = sizeof(test); + errno = 0; + set[0].fd = test_socket; + set[0].events = POLLIN; + for (;;) { + if (listc + 1 >= listmax) { + SOCKET *newlistv; + + listmax += 20; + newlistv = realloc(listv, listmax * sizeof(*listv)); + if (newlistv == NULL) + leave(1, "realloc"); + listv = newlistv; + } + + if (poll(set, 1, 1000) == 1 && + recvfrom(test_socket, &port_num, sizeof(port_num), + 0, (struct sockaddr *) &listv[listc], &namelen) > 0) { + /* + * Note that we do *not* convert from network to host + * order since the port number *should* be in network + * order: + */ + for (j = 0; j < listc; j += 1) + if (listv[listc].sin_addr.s_addr + == listv[j].sin_addr.s_addr) + break; + if (j == listc) + listv[listc++].sin_port = port_num; + continue; + } + + if (errno != 0 && errno != EINTR) { + leave(1, "poll/recvfrom"); + /* NOTREACHED */ + } + + /* terminate list with local address */ + listv[listc].sin_family = SOCK_FAMILY; + listv[listc].sin_addr = local_address; + listv[listc].sin_port = htons(0); + + (void) close(test_socket); + initial = false; + return listv; + } + +test_one_host: + msg = htons(C_TESTMSG()); + (void) sendto(test_socket, &msg, sizeof msg, 0, + (struct sockaddr *) &test, sizeof(test)); + goto get_response; +} + +#endif /* INTERNET */ |