Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/libthread/dial.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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