/*
  sockunix.c
  Written by D'Arcy J.M. Cain
  $Id: sockunix.c,v 1.4 2006/07/18 17:04:38 darcy Exp $

  Implements sock_open for Unix systems.  If anyone wants to make a DOS
  version I'll include it in the package.
*/

#undef		_POSIX_SOURCE

#include	<stdio.h>
#include	<stdlib.h>
#include	<stdio.h>
#include	<ctype.h>
#include	<string.h>
#include	<sys/types.h>
#include	<sys/socket.h>
#include	<netinet/in.h>
#include	<arpa/inet.h>
#include	<arpa/nameser.h>
#include	<netdb.h>
#include	<errno.h>

#ifndef NS_MAXDNAME
#define NS_MAXDNAME MAXDNAME
#endif

FILE *sock_open(const char *str, const char *mode);

FILE *
sock_open(const char *str, const char *mode)
{
	int					s;
	long				address;
	struct sockaddr_in	sock_in;
	const char			*host = "localhost";
	const char			*service = "unknown";
	char				buf[NS_MAXDNAME], *p;

	/* just in case */
	while (isspace((int) *str))
		str++;

	/* prevent buffer overrun */
	if (strlen(str) >= NS_MAXDNAME)
		return NULL;

	/* our own working copy */
	strcpy(buf, str);

	/* there should be no spaces in the spec */
	for (p = buf; *p && !isspace((int) *p); p++)
		;

	*p = 0;

	if ((p = strchr(buf, ':')) != NULL)
		*p++ = 0;

	if (buf[0])
		host = buf;

	if (*p)
		service = p;

	/* host and service now point to the relevant parts of the spec
	 * or the default if blank */

	/* nowadays one can find domains starting with digits so this gets
	   a little trickier than it used to */
	for (; *p && (*p == '.' || isdigit((int) *p)); p++)
		;

	/* if p is pointing at zero byte then it's a dotted IP address */
	/* error reporting is a problem */
	if (*p == 0)
	{
		if ((address = inet_addr(host)) == -1) 
			return(NULL);

		sock_in.sin_addr.s_addr = address;
		sock_in.sin_family = AF_INET;
	}
	else
	{
		struct hostent		*ph;

		if ((ph = gethostbyname(host)) == NULL)
			return NULL;

		sock_in.sin_family = ph->h_addrtype;
		memcpy(&sock_in.sin_addr, ph->h_addr, ph->h_length);
	}

	/* get TCP port number */
	if (isdigit((int) service[0]))
		sock_in.sin_port = strtol(service, NULL, 0);
	else
	{
		struct servent		*ps;

		if ((ps = getservbyname(service, "tcp")) == NULL)
			return NULL;

		sock_in.sin_port = ps->s_port;
	}

	if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
		return NULL;

	if (connect(s, (struct sockaddr *)(&sock_in), sizeof(sock_in)) < 0)
		return NULL;

	return fdopen(s, mode);
}



syntax highlighted by Code2HTML, v. 0.9.1