xref: /plan9/sys/src/9/ip/chandial.c (revision 4e3613ab15c331a9ada113286cc0f2a35bc0373d)
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*
chandial(char * dest,char * local,char * dir,Chan ** ctlp)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*
call(char * clone,char * dest,DS * ds)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 	snprint(name, sizeof 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
_dial_string_parse(char * str,DS * ds)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 }
125