goto considered harmful

This commit is contained in:
dholland 2014-03-30 02:46:57 +00:00
parent 082c40f53a
commit 61623de9c7
1 changed files with 116 additions and 100 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: server.c,v 1.1 2014/03/30 02:26:09 dholland Exp $ */
/* $NetBSD: server.c,v 1.2 2014/03/30 02:46:57 dholland Exp $ */
/*
* Copyright (c) 1983-2003, Regents of the University of California.
* All rights reserved.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: server.c,v 1.1 2014/03/30 02:26:09 dholland Exp $");
__RCSID("$NetBSD: server.c,v 1.2 2014/03/30 02:46:57 dholland Exp $");
#include <sys/param.h>
#include <sys/stat.h>
@ -53,8 +53,43 @@ __RCSID("$NetBSD: server.c,v 1.1 2014/03/30 02:26:09 dholland Exp $");
#ifdef INTERNET
/*
* Code for finding and talking to hunt daemons.
*/
static SOCKET *listv;
static unsigned int listmax;
static SOCKET test;
static bool initial = true;
static struct in_addr local_address;
struct hostent *hp;
static int brdc;
static SOCKET *brdv;
static void
serverlist_setup(void)
{
char local_name[MAXHOSTNAMELEN + 1];
if (gethostname(local_name, sizeof(local_name)) < 0) {
leavex(1, "Sorry, I have no hostname.");
}
local_name[sizeof(local_name) - 1] = '\0';
if ((hp = gethostbyname(local_name)) == NULL) {
leavex(1, "Can't find myself.");
}
memcpy(&local_address, hp->h_addr, sizeof(local_address));
listmax = 20;
listv = malloc(listmax * sizeof(listv[0]));
if (listv == NULL) {
leavex(1, "Out of memory.");
}
}
static int
broadcast_vec(int s /*socket*/, struct sockaddr_in **vector)
getbroadcastaddrs(int s /*socket*/, struct sockaddr_in **vector)
{
int vec_cnt;
struct ifaddrs *ifp, *ip;
@ -82,105 +117,19 @@ broadcast_vec(int s /*socket*/, struct sockaddr_in **vector)
return vec_cnt;
}
SOCKET *
list_drivers(void)
static void
get_responses(int contactsock)
{
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];
socklen_t namelen;
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].fd = contactsock;
set[0].events = POLLIN;
for (;;) {
if (listc + 1 >= listmax) {
@ -194,7 +143,7 @@ get_response:
}
if (poll(set, 1, 1000) == 1 &&
recvfrom(test_socket, &port_num, sizeof(port_num),
recvfrom(contactsock, &port_num, sizeof(port_num),
0, (struct sockaddr *) &listv[listc], &namelen) > 0) {
/*
* Note that we do *not* convert from network to host
@ -212,7 +161,6 @@ get_response:
if (errno != 0 && errno != EINTR) {
leave(1, "poll/recvfrom");
/* NOTREACHED */
}
/* terminate list with local address */
@ -220,16 +168,84 @@ get_response:
listv[listc].sin_addr = local_address;
listv[listc].sin_port = htons(0);
(void) close(test_socket);
(void) close(contactsock);
initial = false;
break;
}
}
SOCKET *
list_drivers(void)
{
int option;
u_short msg;
int contactsock;
int i;
if (initial) {
/* do one time initialization */
serverlist_setup();
} else if (Sock_host != NULL)
return listv; /* address already valid */
contactsock = socket(SOCK_FAMILY, SOCK_DGRAM, 0);
if (contactsock < 0) {
leave(1, "socket system call failed");
}
test.sin_family = SOCK_FAMILY;
test.sin_port = htons(Test_port);
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);
msg = htons(C_TESTMSG());
(void) sendto(contactsock, &msg, sizeof msg, 0,
(struct sockaddr *) &test, sizeof(test));
get_responses(contactsock);
return listv;
}
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(contactsock, &msg, sizeof msg, 0,
(struct sockaddr *) &test, sizeof(test));
}
if (initial)
brdc = getbroadcastaddrs(contactsock, &brdv);
#ifdef SO_BROADCAST
/* Sun's will broadcast even though this option can't be set */
option = 1;
if (setsockopt(contactsock, SOL_SOCKET, SO_BROADCAST,
&option, sizeof option) < 0) {
leave(1, "setsockopt broadcast");
/* NOTREACHED */
}
#endif
/* send broadcast packets on all interfaces */
msg = htons(C_TESTMSG());
(void) sendto(test_socket, &msg, sizeof msg, 0,
(struct sockaddr *) &test, sizeof(test));
goto get_response;
for (i = 0; i < brdc; i++) {
test.sin_addr = brdv[i].sin_addr;
if (sendto(contactsock, &msg, sizeof msg, 0,
(struct sockaddr *) &test, sizeof(test)) < 0) {
leave(1, "sendto");
}
}
test.sin_addr = local_address;
if (sendto(contactsock, &msg, sizeof msg, 0,
(struct sockaddr *) &test, sizeof(test)) < 0) {
leave(1, "sendto");
}
get_responses(contactsock);
return listv;
}
#endif /* INTERNET */