xref: /plan9/sys/src/libthread/dial.c (revision b8b257802f7f811fbf50141a6401409bebd29327)
1*b8b25780SDavid du Colombier /*
2*b8b25780SDavid du Colombier  * old single-process version of dial that libthread can cope with
3*b8b25780SDavid du Colombier  */
4*b8b25780SDavid du Colombier #include <u.h>
5*b8b25780SDavid du Colombier #include <libc.h>
6*b8b25780SDavid du Colombier 
7*b8b25780SDavid du Colombier typedef struct DS DS;
8*b8b25780SDavid du Colombier 
9*b8b25780SDavid du Colombier static int	call(char*, char*, DS*);
10*b8b25780SDavid du Colombier static int	csdial(DS*);
11*b8b25780SDavid du Colombier static void	_dial_string_parse(char*, DS*);
12*b8b25780SDavid du Colombier 
13*b8b25780SDavid du Colombier enum
14*b8b25780SDavid du Colombier {
15*b8b25780SDavid du Colombier 	Maxstring	= 128,
16*b8b25780SDavid du Colombier 	Maxpath		= 256,
17*b8b25780SDavid du Colombier };
18*b8b25780SDavid du Colombier 
19*b8b25780SDavid du Colombier struct DS {
20*b8b25780SDavid du Colombier 	/* dist string */
21*b8b25780SDavid du Colombier 	char	buf[Maxstring];
22*b8b25780SDavid du Colombier 	char	*netdir;
23*b8b25780SDavid du Colombier 	char	*proto;
24*b8b25780SDavid du Colombier 	char	*rem;
25*b8b25780SDavid du Colombier 
26*b8b25780SDavid du Colombier 	/* other args */
27*b8b25780SDavid du Colombier 	char	*local;
28*b8b25780SDavid du Colombier 	char	*dir;
29*b8b25780SDavid du Colombier 	int	*cfdp;
30*b8b25780SDavid du Colombier };
31*b8b25780SDavid du Colombier 
32*b8b25780SDavid du Colombier 
33*b8b25780SDavid du Colombier /*
34*b8b25780SDavid du Colombier  *  the dialstring is of the form '[/net/]proto!dest'
35*b8b25780SDavid du Colombier  */
36*b8b25780SDavid du Colombier int
_threaddial(char * dest,char * local,char * dir,int * cfdp)37*b8b25780SDavid du Colombier _threaddial(char *dest, char *local, char *dir, int *cfdp)
38*b8b25780SDavid du Colombier {
39*b8b25780SDavid du Colombier 	DS ds;
40*b8b25780SDavid du Colombier 	int rv;
41*b8b25780SDavid du Colombier 	char err[ERRMAX], alterr[ERRMAX];
42*b8b25780SDavid du Colombier 
43*b8b25780SDavid du Colombier 	ds.local = local;
44*b8b25780SDavid du Colombier 	ds.dir = dir;
45*b8b25780SDavid du Colombier 	ds.cfdp = cfdp;
46*b8b25780SDavid du Colombier 
47*b8b25780SDavid du Colombier 	_dial_string_parse(dest, &ds);
48*b8b25780SDavid du Colombier 	if(ds.netdir)
49*b8b25780SDavid du Colombier 		return csdial(&ds);
50*b8b25780SDavid du Colombier 
51*b8b25780SDavid du Colombier 	ds.netdir = "/net";
52*b8b25780SDavid du Colombier 	rv = csdial(&ds);
53*b8b25780SDavid du Colombier 	if(rv >= 0)
54*b8b25780SDavid du Colombier 		return rv;
55*b8b25780SDavid du Colombier 	err[0] = '\0';
56*b8b25780SDavid du Colombier 	errstr(err, sizeof err);
57*b8b25780SDavid du Colombier 	if(strstr(err, "refused") != 0){
58*b8b25780SDavid du Colombier 		werrstr("%s", err);
59*b8b25780SDavid du Colombier 		return rv;
60*b8b25780SDavid du Colombier 	}
61*b8b25780SDavid du Colombier 	ds.netdir = "/net.alt";
62*b8b25780SDavid du Colombier 	rv = csdial(&ds);
63*b8b25780SDavid du Colombier 	if(rv >= 0)
64*b8b25780SDavid du Colombier 		return rv;
65*b8b25780SDavid du Colombier 
66*b8b25780SDavid du Colombier 	alterr[0] = 0;
67*b8b25780SDavid du Colombier 	errstr(alterr, sizeof alterr);
68*b8b25780SDavid du Colombier 	if(strstr(alterr, "translate") || strstr(alterr, "does not exist"))
69*b8b25780SDavid du Colombier 		werrstr("%s", err);
70*b8b25780SDavid du Colombier 	else
71*b8b25780SDavid du Colombier 		werrstr("%s", alterr);
72*b8b25780SDavid du Colombier 	return rv;
73*b8b25780SDavid du Colombier }
74*b8b25780SDavid du Colombier 
75*b8b25780SDavid du Colombier static int
csdial(DS * ds)76*b8b25780SDavid du Colombier csdial(DS *ds)
77*b8b25780SDavid du Colombier {
78*b8b25780SDavid du Colombier 	int n, fd, rv;
79*b8b25780SDavid du Colombier 	char *p, buf[Maxstring], clone[Maxpath], err[ERRMAX], besterr[ERRMAX];
80*b8b25780SDavid du Colombier 
81*b8b25780SDavid du Colombier 	/*
82*b8b25780SDavid du Colombier 	 *  open connection server
83*b8b25780SDavid du Colombier 	 */
84*b8b25780SDavid du Colombier 	snprint(buf, sizeof(buf), "%s/cs", ds->netdir);
85*b8b25780SDavid du Colombier 	fd = open(buf, ORDWR);
86*b8b25780SDavid du Colombier 	if(fd < 0){
87*b8b25780SDavid du Colombier 		/* no connection server, don't translate */
88*b8b25780SDavid du Colombier 		snprint(clone, sizeof(clone), "%s/%s/clone", ds->netdir, ds->proto);
89*b8b25780SDavid du Colombier 		return call(clone, ds->rem, ds);
90*b8b25780SDavid du Colombier 	}
91*b8b25780SDavid du Colombier 
92*b8b25780SDavid du Colombier 	/*
93*b8b25780SDavid du Colombier 	 *  ask connection server to translate
94*b8b25780SDavid du Colombier 	 */
95*b8b25780SDavid du Colombier 	snprint(buf, sizeof(buf), "%s!%s", ds->proto, ds->rem);
96*b8b25780SDavid du Colombier 	if(write(fd, buf, strlen(buf)) < 0){
97*b8b25780SDavid du Colombier 		close(fd);
98*b8b25780SDavid du Colombier 		return -1;
99*b8b25780SDavid du Colombier 	}
100*b8b25780SDavid du Colombier 
101*b8b25780SDavid du Colombier 	/*
102*b8b25780SDavid du Colombier 	 *  loop through each address from the connection server till
103*b8b25780SDavid du Colombier 	 *  we get one that works.
104*b8b25780SDavid du Colombier 	 */
105*b8b25780SDavid du Colombier 	*besterr = 0;
106*b8b25780SDavid du Colombier 	rv = -1;
107*b8b25780SDavid du Colombier 	seek(fd, 0, 0);
108*b8b25780SDavid du Colombier 	while((n = read(fd, buf, sizeof(buf) - 1)) > 0){
109*b8b25780SDavid du Colombier 		buf[n] = 0;
110*b8b25780SDavid du Colombier 		p = strchr(buf, ' ');
111*b8b25780SDavid du Colombier 		if(p == 0)
112*b8b25780SDavid du Colombier 			continue;
113*b8b25780SDavid du Colombier 		*p++ = 0;
114*b8b25780SDavid du Colombier 		rv = call(buf, p, ds);
115*b8b25780SDavid du Colombier 		if(rv >= 0)
116*b8b25780SDavid du Colombier 			break;
117*b8b25780SDavid du Colombier 		err[0] = '\0';
118*b8b25780SDavid du Colombier 		errstr(err, sizeof err);
119*b8b25780SDavid du Colombier 		if(strstr(err, "does not exist") == 0)
120*b8b25780SDavid du Colombier 			strcpy(besterr, err);
121*b8b25780SDavid du Colombier 	}
122*b8b25780SDavid du Colombier 	close(fd);
123*b8b25780SDavid du Colombier 
124*b8b25780SDavid du Colombier 	if(rv < 0 && *besterr)
125*b8b25780SDavid du Colombier 		werrstr("%s", besterr);
126*b8b25780SDavid du Colombier 	else
127*b8b25780SDavid du Colombier 		werrstr("%s", err);
128*b8b25780SDavid du Colombier 	return rv;
129*b8b25780SDavid du Colombier }
130*b8b25780SDavid du Colombier 
131*b8b25780SDavid du Colombier static int
call(char * clone,char * dest,DS * ds)132*b8b25780SDavid du Colombier call(char *clone, char *dest, DS *ds)
133*b8b25780SDavid du Colombier {
134*b8b25780SDavid du Colombier 	int fd, cfd, n;
135*b8b25780SDavid du Colombier 	char cname[Maxpath], name[Maxpath], data[Maxpath], *p;
136*b8b25780SDavid du Colombier 
137*b8b25780SDavid du Colombier 	/* because cs is in a different name space, replace the mount point */
138*b8b25780SDavid du Colombier 	if(*clone == '/'){
139*b8b25780SDavid du Colombier 		p = strchr(clone+1, '/');
140*b8b25780SDavid du Colombier 		if(p == nil)
141*b8b25780SDavid du Colombier 			p = clone;
142*b8b25780SDavid du Colombier 		else
143*b8b25780SDavid du Colombier 			p++;
144*b8b25780SDavid du Colombier 	} else
145*b8b25780SDavid du Colombier 		p = clone;
146*b8b25780SDavid du Colombier 	snprint(cname, sizeof cname, "%s/%s", ds->netdir, p);
147*b8b25780SDavid du Colombier 
148*b8b25780SDavid du Colombier 	cfd = open(cname, ORDWR);
149*b8b25780SDavid du Colombier 	if(cfd < 0)
150*b8b25780SDavid du Colombier 		return -1;
151*b8b25780SDavid du Colombier 
152*b8b25780SDavid du Colombier 	/* get directory name */
153*b8b25780SDavid du Colombier 	n = read(cfd, name, sizeof(name)-1);
154*b8b25780SDavid du Colombier 	if(n < 0){
155*b8b25780SDavid du Colombier 		close(cfd);
156*b8b25780SDavid du Colombier 		return -1;
157*b8b25780SDavid du Colombier 	}
158*b8b25780SDavid du Colombier 	name[n] = 0;
159*b8b25780SDavid du Colombier 	for(p = name; *p == ' '; p++)
160*b8b25780SDavid du Colombier 		;
161*b8b25780SDavid du Colombier 	snprint(name, sizeof(name), "%ld", strtoul(p, 0, 0));
162*b8b25780SDavid du Colombier 	p = strrchr(cname, '/');
163*b8b25780SDavid du Colombier 	*p = 0;
164*b8b25780SDavid du Colombier 	if(ds->dir)
165*b8b25780SDavid du Colombier 		snprint(ds->dir, NETPATHLEN, "%s/%s", cname, name);
166*b8b25780SDavid du Colombier 	snprint(data, sizeof(data), "%s/%s/data", cname, name);
167*b8b25780SDavid du Colombier 
168*b8b25780SDavid du Colombier 	/* connect */
169*b8b25780SDavid du Colombier 	if(ds->local)
170*b8b25780SDavid du Colombier 		snprint(name, sizeof(name), "connect %s %s", dest, ds->local);
171*b8b25780SDavid du Colombier 	else
172*b8b25780SDavid du Colombier 		snprint(name, sizeof(name), "connect %s", dest);
173*b8b25780SDavid du Colombier 	if(write(cfd, name, strlen(name)) < 0){
174*b8b25780SDavid du Colombier 		close(cfd);
175*b8b25780SDavid du Colombier 		return -1;
176*b8b25780SDavid du Colombier 	}
177*b8b25780SDavid du Colombier 
178*b8b25780SDavid du Colombier 	/* open data connection */
179*b8b25780SDavid du Colombier 	fd = open(data, ORDWR);
180*b8b25780SDavid du Colombier 	if(fd < 0){
181*b8b25780SDavid du Colombier 		close(cfd);
182*b8b25780SDavid du Colombier 		return -1;
183*b8b25780SDavid du Colombier 	}
184*b8b25780SDavid du Colombier 	if(ds->cfdp)
185*b8b25780SDavid du Colombier 		*ds->cfdp = cfd;
186*b8b25780SDavid du Colombier 	else
187*b8b25780SDavid du Colombier 		close(cfd);
188*b8b25780SDavid du Colombier 	return fd;
189*b8b25780SDavid du Colombier }
190*b8b25780SDavid du Colombier 
191*b8b25780SDavid du Colombier /*
192*b8b25780SDavid du Colombier  *  parse a dial string
193*b8b25780SDavid du Colombier  */
194*b8b25780SDavid du Colombier static void
_dial_string_parse(char * str,DS * ds)195*b8b25780SDavid du Colombier _dial_string_parse(char *str, DS *ds)
196*b8b25780SDavid du Colombier {
197*b8b25780SDavid du Colombier 	char *p, *p2;
198*b8b25780SDavid du Colombier 
199*b8b25780SDavid du Colombier 	strncpy(ds->buf, str, Maxstring);
200*b8b25780SDavid du Colombier 	ds->buf[Maxstring-1] = 0;
201*b8b25780SDavid du Colombier 
202*b8b25780SDavid du Colombier 	p = strchr(ds->buf, '!');
203*b8b25780SDavid du Colombier 	if(p == 0) {
204*b8b25780SDavid du Colombier 		ds->netdir = 0;
205*b8b25780SDavid du Colombier 		ds->proto = "net";
206*b8b25780SDavid du Colombier 		ds->rem = ds->buf;
207*b8b25780SDavid du Colombier 	} else {
208*b8b25780SDavid du Colombier 		if(*ds->buf != '/' && *ds->buf != '#'){
209*b8b25780SDavid du Colombier 			ds->netdir = 0;
210*b8b25780SDavid du Colombier 			ds->proto = ds->buf;
211*b8b25780SDavid du Colombier 		} else {
212*b8b25780SDavid du Colombier 			for(p2 = p; *p2 != '/'; p2--)
213*b8b25780SDavid du Colombier 				;
214*b8b25780SDavid du Colombier 			*p2++ = 0;
215*b8b25780SDavid du Colombier 			ds->netdir = ds->buf;
216*b8b25780SDavid du Colombier 			ds->proto = p2;
217*b8b25780SDavid du Colombier 		}
218*b8b25780SDavid du Colombier 		*p = 0;
219*b8b25780SDavid du Colombier 		ds->rem = p + 1;
220*b8b25780SDavid du Colombier 	}
221*b8b25780SDavid du Colombier }
222