xref: /plan9-contrib/sys/src/ape/lib/net/dial.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <stdlib.h>
2 #include <sys/types.h>
3 #include <string.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <libnet.h>
8 
9 #define NAMELEN 28
10 
11 static int
12 call(char *clone, char *dest, int *cfdp, char *dir, char *local)
13 {
14 	int fd, cfd;
15 	int n;
16 	char name[3*NAMELEN+5];
17 	char data[3*NAMELEN+10];
18 	char *p;
19 
20 	cfd = open(clone, O_RDWR);
21 	if(cfd < 0)
22 		return -1;
23 
24 	/* get directory name */
25 	n = read(cfd, name, sizeof(name)-1);
26 	if(n < 0){
27 		close(cfd);
28 		return -1;
29 	}
30 	name[n] = 0;
31 	p = strrchr(clone, '/');
32 	*p = 0;
33 	if(dir)
34 		sprintf(dir, "%.*s/%.*s", 2*NAMELEN+1, clone, NAMELEN, name);
35 	sprintf(data, "%.*s/%.*s/data", 2*NAMELEN+1, clone, NAMELEN, name);
36 
37 	/* set local side (port number, for example) if we need to */
38 	if(local){
39 		sprintf(name, "announce %s", 2*NAMELEN, local);
40 		if(write(cfd, name, strlen(name)) < 0){
41 			close(cfd);
42 			return -1;
43 		}
44 	}
45 
46 	/* connect */
47 	sprintf(name, "connect %.*s", 2*NAMELEN, dest);
48 	if(write(cfd, name, strlen(name)) < 0){
49 		close(cfd);
50 		return -1;
51 	}
52 
53 	/* open data connection */
54 	fd = open(data, O_RDWR);
55 	if(fd < 0){
56 		close(cfd);
57 		return -1;
58 	}
59 	if(cfdp)
60 		*cfdp = cfd;
61 	else
62 		close(cfd);
63 	return fd;
64 }
65 
66 int
67 dial(char *dest, char *local, char *dir, int *cfdp)
68 {
69 	char net[128];
70 	char clone[NAMELEN+12];
71 	char *p;
72 	int n;
73 	int fd;
74 	int rv;
75 
76 	/* go for a standard form net!... */
77 	p = strchr(dest, '!');
78 	if(p == 0){
79 		sprintf(net, "net!%.*s", sizeof(net)-5, dest);
80 	} else {
81 		strncpy(net, dest, sizeof(net)-1);
82 		net[sizeof(net)-1] = 0;
83 	}
84 
85 	/* call the connection server */
86 	fd = open("/net/cs", O_RDWR);
87 	if(fd < 0){
88 		/* no connection server, don't translate */
89 		p = strchr(net, '!');
90 		*p++ = 0;
91 		sprintf(clone, "/net/%s/clone", net);
92 		return call(clone, p, cfdp, dir, local);
93 	}
94 
95 	/*
96 	 *  send dest to connection to translate
97 	 */
98 	if(write(fd, net, strlen(net)) < 0){
99 		close(fd);
100 		return -1;
101 	}
102 
103 	/*
104 	 *  loop through each address from the connection server till
105 	 *  we get one that works.
106 	 */
107 	rv = -1;
108 	lseek(fd, 0, 0);
109 	while((n = read(fd, net, sizeof(net) - 1)) > 0){
110 		net[n] = 0;
111 		p = strchr(net, ' ');
112 		if(p == 0)
113 			continue;
114 		*p++ = 0;
115 		rv = call(net, p, cfdp, dir, local);
116 		if(rv >= 0)
117 			break;
118 	}
119 	close(fd);
120 	return rv;
121 }
122