Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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