/*
 * opensock.c
 *
 * server creates a socket to listen for connections
 */

#include <stdio.h>
#include "defs.h"
#include "local.h"


/*
 * Open main socket on given port and set sock_num to it.
 * If port is 0, get port from /etc/services.
 */
open_socket(port)
int	port;
{
	struct	sockaddr_in sockaddr;
	struct	hostent *host;
	struct	servent *distributor;
	int	sock_num;
	char	hostnm[SLEN];

	(void) gethostname(hostnm, SLEN);
	if ((sock_num = socket(AF_INET, SOCK_STREAM, 0)) < 0)  {
		perror("socket");
		exit(1);
	}
	if ((host = gethostbyname(hostnm)) == NULL)  {
		perror("gethostbyname");
		exit(1);
	}
	bzero((char *) &sockaddr, sizeof (sockaddr));
	bcopy(host->h_addr, (char *) &sockaddr.sin_addr, host->h_length);
	sockaddr.sin_family = AF_INET;
	if (port)
		sockaddr.sin_port = htons(port);
	else {
		if ((distributor = getservbyname(SERVICE, PROTO)) == NULL)  {
			fputs("hearts: service not found\n", stderr);
			exit(1);
		}
		sockaddr.sin_port = distributor->s_port;
	}
	/*
	 * Allow reuse of local addresses.
	 * Speeds up reinvocation of distributor.
	 */
	(void) setsockopt(sock_num, SOL_SOCKET, SO_REUSEADDR, (char *) 0, 0);
	/*
	 * Don't hang around if socket in use.
	 */
#ifdef SO_DONTLINGER
	(void) setsockopt(sock_num, SOL_SOCKET, SO_DONTLINGER, (char *) 0, 0);
#else
	{
		struct linger ling;

		(void) setsockopt(sock_num, SOL_SOCKET, SO_LINGER, (char *) &ling, 0);
	}
#endif
	if (bind(sock_num, (struct sockaddr *) &sockaddr, sizeof(sockaddr)) < 0)  {
		return(0);
	}
	if ((listen(sock_num, 5)) == -1)  {
		perror("listen");
		exit(1);
	}
	return(sock_num);
}
