xref: /plan9-contrib/sys/src/ape/lib/net/dial.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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, "connect %.*s %.*s", 2*NAMELEN, dest, NAMELEN, local);
40 	else
41 		sprintf(name, "connect %.*s", 2*NAMELEN, dest);
42 
43 	/* connect */
44 	if(write(cfd, name, strlen(name)) < 0){
45 		close(cfd);
46 		return -1;
47 	}
48 
49 	/* open data connection */
50 	fd = open(data, O_RDWR);
51 	if(fd < 0){
52 		close(cfd);
53 		return -1;
54 	}
55 	if(cfdp)
56 		*cfdp = cfd;
57 	else
58 		close(cfd);
59 	return fd;
60 }
61 
62 int
63 dial(char *dest, char *local, char *dir, int *cfdp)
64 {
65 	char net[128];
66 	char clone[NAMELEN+12];
67 	char *p;
68 	int n;
69 	int fd;
70 	int rv;
71 
72 	/* go for a standard form net!... */
73 	p = strchr(dest, '!');
74 	if(p == 0){
75 		sprintf(net, "net!%.*s", sizeof(net)-5, dest);
76 	} else {
77 		strncpy(net, dest, sizeof(net)-1);
78 		net[sizeof(net)-1] = 0;
79 	}
80 
81 	/* call the connection server */
82 	fd = open("/net/cs", O_RDWR);
83 	if(fd < 0){
84 		/* no connection server, don't translate */
85 		p = strchr(net, '!');
86 		*p++ = 0;
87 		sprintf(clone, "/net/%s/clone", net);
88 		return call(clone, p, cfdp, dir, local);
89 	}
90 
91 	/*
92 	 *  send dest to connection to translate
93 	 */
94 	if(write(fd, net, strlen(net)) < 0){
95 		close(fd);
96 		return -1;
97 	}
98 
99 	/*
100 	 *  loop through each address from the connection server till
101 	 *  we get one that works.
102 	 */
103 	rv = -1;
104 	lseek(fd, 0, 0);
105 	while((n = read(fd, net, sizeof(net) - 1)) > 0){
106 		net[n] = 0;
107 		p = strchr(net, ' ');
108 		if(p == 0)
109 			continue;
110 		*p++ = 0;
111 		rv = call(net, p, cfdp, dir, local);
112 		if(rv >= 0)
113 			break;
114 	}
115 	close(fd);
116 	return rv;
117 }
118