*BSD News Article 44015


Return to BSD News archive

Xref: sserve comp.infosystems.www.browsers.misc:190 comp.unix.questions:64297 comp.unix.bsd.freebsd.misc:1109 comp.unix.bsd:16585 comp.lang.c:100314
Path: sserve!newshost.anu.edu.au!harbinger.cc.monash.edu.au!yarrina.connect.com.au!classic.iinet.com.au!news.uoknor.edu!news.ecn.uoknor.edu!constellation!convex!news.netins.net!newshost.marcam.com!news.mathworks.com!gatech!swrinde!elroy.jpl.nasa.gov!decwrl!vixie!nnrp!vixie
From: vixie@gw.home.vix.com (Paul A Vixie)
Newsgroups: comp.infosystems.www.browsers.misc,comp.unix.questions,comp.unix.bsd.freebsd.misc,comp.unix.bsd,comp.lang.c
Subject: Re: Simple socket/telnet library?
Date: 13 May 1995 00:33:10 GMT
Organization: Vixie Enterprises
Lines: 164
Message-ID: <VIXIE.95May12173310@gw.home.vix.com>
References: <3osqe0$5ei@gate.sinica.edu.tw>
NNTP-Posting-Host: gw.home.vix.com
In-reply-to: taob@gate.sinica.edu.tw's message of 11 May 1995 10:54:56 GMT

> If there is a ready-made library with functions akin to tcpopen(),
> tcpwrite(), tcpread() and tcpclose() that works with a 4.4BSD system
> (FreeBSD 2.0, in my case), that would be fantastic.  Source code fragments,
> tutorial files, primers, etc. also gratefully accepted.  Thanks.

Everybody's got one or more of these.  Here's (one of) mine.  Note that
your tcpopen() is hard (i call it rconnect() below) but after you get your
file descriptor you just use read(), write(), fdopen()/fprintf()/fscanf(),
and close().

/* rconnect - connect to a service on a remote host
 * vix 13sep91 [written - again, dammit]
 */

#ifndef LINT
static char RCSid[] = "$Id: connutil.c,v 1.5 1994/05/16 06:36:09 vixie Exp vixie $";
#endif

#ifdef WANT_TCPIP

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include "rtty.h"

extern	int		h_errno;
extern	char		*ProgName;

/* assume ip/tcp for now */

static	jmp_buf		jmpalrm;
static	void		sigalrm __P((int));

static
int doconnect(n, ns, to)
	struct sockaddr_in *n;
	int ns, to;
{
	int sock, ok, save;

	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock < 0) {
		return -1;
	}
		
	if (to) {
		if (!setjmp(jmpalrm)) {
			signal(SIGALRM, sigalrm);
			alarm(to);
		} else {
			errno = ETIMEDOUT;
			goto finito;
		}
	}
	ok = (connect(sock, (struct sockaddr *)n, ns) >= 0);
	save = errno;
finito:
	if (to) {
		alarm(0);
		signal(SIGALRM, SIG_DFL);
	}
	if (!ok) {
		close(sock);
		errno = save;
		return -1;
	}
	errno = save;
	return sock;
}

int
rconnect(host, service, verbose, errors, timeout)
	char *host;
	char *service;
	FILE *verbose;
	FILE *errors;
	int timeout;
{
	u_int32_t **hp;
	struct hostent *h;
	struct sockaddr_in n;
	int port, sock, done;

	if (!(port = htons(atoi(service)))) {
		struct servent *s = getservbyname(service, "tcp");
		if (!s) {
			if (errors) {
				fprintf(errors,
					"%s: unknown service\n", service);
			}
			errno = ENOPROTOOPT;
			return -1;
		}
		port = s->s_port;
	}

	n.sin_family = AF_INET;
#ifndef NO_SOCKADDR_LEN
	n.sin_len = sizeof(struct sockaddr_in);
#endif
	n.sin_port = port;

	if (inet_aton(host, &n.sin_addr)) {
		if (verbose) {
			fprintf(verbose, "trying [%s]\n",
				inet_ntoa(n.sin_addr.s_addr));
		}
		done = ((sock = doconnect(&n, sizeof n, timeout)) >= 0);
	} else {
		h = gethostbyname(host);
		if (!h) {
			if (errors) {
#ifndef NO_HSTRERROR
				fprintf(errors,
					"%s: %s\n", host, hstrerror(h_errno));
#else
				fprintf(errors,
					"%s: cannot resolve hostname\n", host);
#endif
			}
			return -1;
		}
		for (hp = (u_int32_t**)h->h_addr_list;  *hp;  hp++) {
			bcopy(*hp, (caddr_t)&n.sin_addr.s_addr, h->h_length);
			if (verbose) {
				fprintf(verbose,
					"trying [%s]\n", inet_ntoa(**hp));
			}
			if ((sock = doconnect(&n, sizeof n, timeout)) >= 0) {
				break;
			}
		}
		done = (*hp != NULL);
	}
	if (!done) {
		if (errors) {
			fprintf(errors, "%s: %s\n", host, strerror(errno));
		}
		close(sock);
		return -1;
	}
	return sock;
}

static void
sigalrm(x)
{
	longjmp(jmpalrm, 1);
	/*NOTREACHED*/
}

#endif /*WANT_TCPIP*/
--
Paul Vixie
La Honda, CA			"Illegitimi non carborundum."
<paul@vix.com>
pacbell!vixie!paul		(dont let the bastards grind you down)