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