xref: /plan9/sys/src/ape/lib/net/dial.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
13e12c5d1SDavid du Colombier #include <stdlib.h>
23e12c5d1SDavid du Colombier #include <sys/types.h>
33e12c5d1SDavid du Colombier #include <string.h>
43e12c5d1SDavid du Colombier #include <fcntl.h>
53e12c5d1SDavid du Colombier #include <stdio.h>
63e12c5d1SDavid du Colombier #include <unistd.h>
73e12c5d1SDavid du Colombier #include <libnet.h>
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier #define NAMELEN 28
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier static int
call(char * clone,char * dest,int * cfdp,char * dir,char * local)123e12c5d1SDavid du Colombier call(char *clone, char *dest, int *cfdp, char *dir, char *local)
133e12c5d1SDavid du Colombier {
143e12c5d1SDavid du Colombier 	int fd, cfd;
153e12c5d1SDavid du Colombier 	int n;
163e12c5d1SDavid du Colombier 	char name[3*NAMELEN+5];
173e12c5d1SDavid du Colombier 	char data[3*NAMELEN+10];
183e12c5d1SDavid du Colombier 	char *p;
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier 	cfd = open(clone, O_RDWR);
213e12c5d1SDavid du Colombier 	if(cfd < 0)
223e12c5d1SDavid du Colombier 		return -1;
233e12c5d1SDavid du Colombier 
243e12c5d1SDavid du Colombier 	/* get directory name */
253e12c5d1SDavid du Colombier 	n = read(cfd, name, sizeof(name)-1);
263e12c5d1SDavid du Colombier 	if(n < 0){
273e12c5d1SDavid du Colombier 		close(cfd);
283e12c5d1SDavid du Colombier 		return -1;
293e12c5d1SDavid du Colombier 	}
303e12c5d1SDavid du Colombier 	name[n] = 0;
313e12c5d1SDavid du Colombier 	p = strrchr(clone, '/');
323e12c5d1SDavid du Colombier 	*p = 0;
333e12c5d1SDavid du Colombier 	if(dir)
343e12c5d1SDavid du Colombier 		sprintf(dir, "%.*s/%.*s", 2*NAMELEN+1, clone, NAMELEN, name);
353e12c5d1SDavid du Colombier 	sprintf(data, "%.*s/%.*s/data", 2*NAMELEN+1, clone, NAMELEN, name);
363e12c5d1SDavid du Colombier 
373e12c5d1SDavid du Colombier 	/* set local side (port number, for example) if we need to */
387dd7cddfSDavid du Colombier 	if(local)
397dd7cddfSDavid du Colombier 		sprintf(name, "connect %.*s %.*s", 2*NAMELEN, dest, NAMELEN, local);
407dd7cddfSDavid du Colombier 	else
417dd7cddfSDavid du Colombier 		sprintf(name, "connect %.*s", 2*NAMELEN, dest);
423e12c5d1SDavid du Colombier 
433e12c5d1SDavid du Colombier 	/* connect */
443e12c5d1SDavid du Colombier 	if(write(cfd, name, strlen(name)) < 0){
453e12c5d1SDavid du Colombier 		close(cfd);
463e12c5d1SDavid du Colombier 		return -1;
473e12c5d1SDavid du Colombier 	}
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier 	/* open data connection */
503e12c5d1SDavid du Colombier 	fd = open(data, O_RDWR);
513e12c5d1SDavid du Colombier 	if(fd < 0){
523e12c5d1SDavid du Colombier 		close(cfd);
533e12c5d1SDavid du Colombier 		return -1;
543e12c5d1SDavid du Colombier 	}
553e12c5d1SDavid du Colombier 	if(cfdp)
563e12c5d1SDavid du Colombier 		*cfdp = cfd;
573e12c5d1SDavid du Colombier 	else
583e12c5d1SDavid du Colombier 		close(cfd);
593e12c5d1SDavid du Colombier 	return fd;
603e12c5d1SDavid du Colombier }
613e12c5d1SDavid du Colombier 
623e12c5d1SDavid du Colombier int
dial(char * dest,char * local,char * dir,int * cfdp)633e12c5d1SDavid du Colombier dial(char *dest, char *local, char *dir, int *cfdp)
643e12c5d1SDavid du Colombier {
653e12c5d1SDavid du Colombier 	char net[128];
66*9a747e4fSDavid du Colombier 	char netdir[128], csname[NETPATHLEN], *slp;
673e12c5d1SDavid du Colombier 	char clone[NAMELEN+12];
683e12c5d1SDavid du Colombier 	char *p;
693e12c5d1SDavid du Colombier 	int n;
703e12c5d1SDavid du Colombier 	int fd;
713e12c5d1SDavid du Colombier 	int rv;
723e12c5d1SDavid du Colombier 
733e12c5d1SDavid du Colombier 	/* go for a standard form net!... */
743e12c5d1SDavid du Colombier 	p = strchr(dest, '!');
753e12c5d1SDavid du Colombier 	if(p == 0){
763e12c5d1SDavid du Colombier 		sprintf(net, "net!%.*s", sizeof(net)-5, dest);
773e12c5d1SDavid du Colombier 	} else {
783e12c5d1SDavid du Colombier 		strncpy(net, dest, sizeof(net)-1);
793e12c5d1SDavid du Colombier 		net[sizeof(net)-1] = 0;
803e12c5d1SDavid du Colombier 	}
813e12c5d1SDavid du Colombier 
82*9a747e4fSDavid du Colombier 	slp = strrchr(net, '/');
83*9a747e4fSDavid du Colombier 	if (slp != 0) {
84*9a747e4fSDavid du Colombier 		*slp++ = '\0';
85*9a747e4fSDavid du Colombier 		strcpy(netdir, net);
86*9a747e4fSDavid du Colombier 		memmove(net, slp, strlen(slp)+1);
87*9a747e4fSDavid du Colombier 	} else
88*9a747e4fSDavid du Colombier 		strcpy(netdir, "/net");
89*9a747e4fSDavid du Colombier 
90*9a747e4fSDavid du Colombier 
913e12c5d1SDavid du Colombier 	/* call the connection server */
92*9a747e4fSDavid du Colombier 	sprintf(csname, "%s/cs", netdir);
93*9a747e4fSDavid du Colombier 	fd = open(csname, O_RDWR);
943e12c5d1SDavid du Colombier 	if(fd < 0){
953e12c5d1SDavid du Colombier 		/* no connection server, don't translate */
963e12c5d1SDavid du Colombier 		p = strchr(net, '!');
973e12c5d1SDavid du Colombier 		*p++ = 0;
98*9a747e4fSDavid du Colombier 		sprintf(clone, "%s/%s/clone", netdir, net);
993e12c5d1SDavid du Colombier 		return call(clone, p, cfdp, dir, local);
1003e12c5d1SDavid du Colombier 	}
1013e12c5d1SDavid du Colombier 
1023e12c5d1SDavid du Colombier 	/*
1033e12c5d1SDavid du Colombier 	 *  send dest to connection to translate
1043e12c5d1SDavid du Colombier 	 */
1053e12c5d1SDavid du Colombier 	if(write(fd, net, strlen(net)) < 0){
1063e12c5d1SDavid du Colombier 		close(fd);
1073e12c5d1SDavid du Colombier 		return -1;
1083e12c5d1SDavid du Colombier 	}
1093e12c5d1SDavid du Colombier 
1103e12c5d1SDavid du Colombier 	/*
1113e12c5d1SDavid du Colombier 	 *  loop through each address from the connection server till
1123e12c5d1SDavid du Colombier 	 *  we get one that works.
1133e12c5d1SDavid du Colombier 	 */
1143e12c5d1SDavid du Colombier 	rv = -1;
1153e12c5d1SDavid du Colombier 	lseek(fd, 0, 0);
1163e12c5d1SDavid du Colombier 	while((n = read(fd, net, sizeof(net) - 1)) > 0){
1173e12c5d1SDavid du Colombier 		net[n] = 0;
1183e12c5d1SDavid du Colombier 		p = strchr(net, ' ');
1193e12c5d1SDavid du Colombier 		if(p == 0)
1203e12c5d1SDavid du Colombier 			continue;
1213e12c5d1SDavid du Colombier 		*p++ = 0;
1223e12c5d1SDavid du Colombier 		rv = call(net, p, cfdp, dir, local);
1233e12c5d1SDavid du Colombier 		if(rv >= 0)
1243e12c5d1SDavid du Colombier 			break;
1253e12c5d1SDavid du Colombier 	}
1263e12c5d1SDavid du Colombier 	close(fd);
1273e12c5d1SDavid du Colombier 	return rv;
1283e12c5d1SDavid du Colombier }
129