/*
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