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