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