]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/ip/chandial.c
ip/chandial: fail with Ebadarg instead of printing memory contents
[plan9front.git] / sys / src / 9 / 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 == nil)
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 = nil;
113                         ds->proto = ds->buf;
114                 } else {
115                         for(p2 = p; *p2 != '/' && p2 != ds->buf; p2--)
116                                 ;
117                         if(p2 == ds->buf)
118                                 error(Ebadarg);
119                         *p2++ = 0;
120                         ds->netdir = ds->buf;
121                         ds->proto = p2;
122                 }
123                 *p = 0;
124                 ds->rem = p + 1;
125         }
126 }