FreeBSD/Linux Kernel Cross Reference
sys/ip/chandial.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 #include "../ip/ip.h"
8
9 typedef struct DS DS;
10 static Chan* call(char*, char*, DS*);
11 static void _dial_string_parse(char*, DS*);
12
13 enum
14 {
15 Maxstring= 128,
16 };
17
18 struct DS
19 {
20 char buf[Maxstring]; /* dist string */
21 char *netdir;
22 char *proto;
23 char *rem;
24 char *local; /* other args */
25 char *dir;
26 Chan **ctlp;
27 };
28
29 /*
30 * the dialstring is of the form '[/net/]proto!dest'
31 */
32 Chan*
33 chandial(char *dest, char *local, char *dir, Chan **ctlp)
34 {
35 DS ds;
36 char clone[Maxpath];
37
38 ds.local = local;
39 ds.dir = dir;
40 ds.ctlp = ctlp;
41
42 _dial_string_parse(dest, &ds);
43 if(ds.netdir == 0)
44 ds.netdir = "/net";
45
46 /* no connection server, don't translate */
47 snprint(clone, sizeof(clone), "%s/%s/clone", ds.netdir, ds.proto);
48 return call(clone, ds.rem, &ds);
49 }
50
51 static Chan*
52 call(char *clone, char *dest, DS *ds)
53 {
54 int n;
55 Chan *dchan, *cchan;
56 char name[Maxpath], data[Maxpath], *p;
57
58 cchan = namec(clone, Aopen, ORDWR, 0);
59
60 /* get directory name */
61 if(waserror()){
62 cclose(cchan);
63 nexterror();
64 }
65 n = devtab[cchan->type]->read(cchan, name, sizeof(name)-1, 0);
66 name[n] = 0;
67 for(p = name; *p == ' '; p++)
68 ;
69 sprint(name, "%lud", strtoul(p, 0, 0));
70 p = strrchr(clone, '/');
71 *p = 0;
72 if(ds->dir)
73 snprint(ds->dir, Maxpath, "%s/%s", clone, name);
74 snprint(data, sizeof(data), "%s/%s/data", clone, name);
75
76 /* connect */
77 if(ds->local)
78 snprint(name, sizeof(name), "connect %s %s", dest, ds->local);
79 else
80 snprint(name, sizeof(name), "connect %s", dest);
81 devtab[cchan->type]->write(cchan, name, strlen(name), 0);
82
83 /* open data connection */
84 dchan = namec(data, Aopen, ORDWR, 0);
85 if(ds->ctlp)
86 *ds->ctlp = cchan;
87 else
88 cclose(cchan);
89 poperror();
90 return dchan;
91
92 }
93
94 /*
95 * parse a dial string
96 */
97 static void
98 _dial_string_parse(char *str, DS *ds)
99 {
100 char *p, *p2;
101
102 strncpy(ds->buf, str, Maxstring);
103 ds->buf[Maxstring-1] = 0;
104
105 p = strchr(ds->buf, '!');
106 if(p == 0) {
107 ds->netdir = 0;
108 ds->proto = "net";
109 ds->rem = ds->buf;
110 } else {
111 if(*ds->buf != '/' && *ds->buf != '#'){
112 ds->netdir = 0;
113 ds->proto = ds->buf;
114 } else {
115 for(p2 = p; *p2 != '/'; p2--)
116 ;
117 *p2++ = 0;
118 ds->netdir = ds->buf;
119 ds->proto = p2;
120 }
121 *p = 0;
122 ds->rem = p + 1;
123 }
124 }
Cache object: 41c3376bf248504dd012eb5b57b94791
|