File:  [Research Unix] / researchv10no / cmd / nupas / ipc / otcpconnect.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:35 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Norman

untested - there are some minor changes in tcpconnect that have not been
moved to this routine.

#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sysexits.h>
#include <string.h>

extern int ipcdebug;

extern char syserrstr[];

/*
 * This is an older version of tcp_connect for systems that
 * use the old Berkeley 4.2 gethostbyname which returned
 * a single host entry instead of several.
 *
 * This code hasn't been tested as hard as the newer stuff.
 */
int
tcp_connect(dest, param)
char *dest, *param;
{
	struct hostent *hp;
	struct sockaddr_in sin;
	char	*inet_ntoa();
	int s, port, i;
	unsigned long addr;
	char buf[100];
	char *host, *service;
	char *h_addr_list[2];
	int errtype = 0;
	char errstr[256];

	strcpy(buf, dest);
	host = buf;

	if ((port = tcp_service(host)) < 0) {
		ipcseterror(EX_NOHOST, "unknown service", "tcp_connect");
		return(-1);
	}

	if (ipcdebug)
		fprintf(stderr, "TCP port number is %d\n", ntohs(port));

	if ((addr = inet_addr(host)) != (unsigned long) -1) {
		if (ipcdebug)
			fprintf(stderr, "Numeric address: %s %lx\n",
				host, addr);
		s = socket(AF_INET, SOCK_STREAM, 0);
		if(s < 0){
			ipcsyserr("can't open socket");
			return(-1);
		}
		bzero((char *)&sin, sizeof(sin));
		sin.sin_family = AF_INET;
		sin.sin_port = port;
		sin.sin_addr.s_addr = addr;
		if(connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0) {
			setopt(s);
			return s;
		}
		ipcsyserr("can't connect");
		close(s);
		return -1;
	}

	if((hp = gethostbyname(host)) == (struct hostent *)0){
		ipcseterror(EX_NOHOST,  "unknown host", "tcp_connect");
		return(-1);
	}
	h_addr_list[0] = hp->h_addr;
	h_addr_list[1] = 0;
	for(i=0; h_addr_list[i]; i++ ){ 
		bzero((char *)&sin, sizeof(sin));
		bcopy(h_addr_list[i], &sin.sin_addr, hp->h_length);
		sin.sin_family = hp->h_addrtype;
		sin.sin_port = port;
		if (ipcdebug)
			fprintf(stderr, "Trying address %s\n",
				inet_ntoa(sin.sin_addr));

		s = socket(AF_INET, SOCK_STREAM, 0);
		if(s < 0){
			ipcsyserr("can't open socket");
			return(-1);
		}
		if(connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0) {
			setopt(s);
			return s;
		}
		ipcgetsyserr();
		if (errtype == 0 || 
		   (errtype != EX_TEMPFAIL && ipcmaperror()==EX_TEMPFAIL)) {
			errtype = ipcmaperror();
			strcpy(errstr, syserrstr);
		}
		ipcsyserr("connect");
		close(s);
	}

	ipcseterror(errtype, errstr, "Can't connect to host");
	return -1;
}

setopt(s)
int s;
{
	/*
	 * for some reason, the following linger does not seem
	 * to have any effect, at least on the Sun `shamash'.
	 * I have placed a sleep before the close in ../pftp/ftp.c
	 * in the routine sendrequest.
	 *	suggestions are [email protected]
	 */
	struct linger linger;

	linger.l_onoff = 1;
	linger.l_linger = 3000;
	if (setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&linger,
	    sizeof (linger)) < 0)
		ipcsyserr("error setting socket option");
	return s;
}

int
tcp_service(path)
char *path;
{
	struct servent *sp;
	char *service;

	if ((service = strchr(path, '!')) == NULL)
		service = "";
	else
		*service++ = '\0';

	/*
	 *  translate service/port name
	 */
	if(strncmp(service, "tcp.", 4)==0)
		service += 4;
	if(strncmp(service, "/cs/", 4)==0)
		service += 4;
	if(strcmp(service, "")==0)
		return 0;
	else if(atoi(service)!=0)
		return atoi(htons(service));
	else if ((sp = getservbyname (service, "tcp")) != NULL)
		return sp->s_port;
	return -1;
}

int
tcp_close(fd)
int fd;
{
	write(fd, &fd, 0);	/* stub - is this useful or necessary? */
	if (shutdown(fd, 2) < 0)
		ipcseterror(EX_SOFTWARE, "shutdown failed", "tcp_close");
	return close(fd);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.