summaryrefslogtreecommitdiff
path: root/sys/src/9/ip/chandial.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/ip/chandial.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/ip/chandial.c')
-rwxr-xr-xsys/src/9/ip/chandial.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/sys/src/9/ip/chandial.c b/sys/src/9/ip/chandial.c
new file mode 100755
index 000000000..38139ceec
--- /dev/null
+++ b/sys/src/9/ip/chandial.c
@@ -0,0 +1,124 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../ip/ip.h"
+
+typedef struct DS DS;
+static Chan* call(char*, char*, DS*);
+static void _dial_string_parse(char*, DS*);
+
+enum
+{
+ Maxstring= 128,
+};
+
+struct DS
+{
+ char buf[Maxstring]; /* dist string */
+ char *netdir;
+ char *proto;
+ char *rem;
+ char *local; /* other args */
+ char *dir;
+ Chan **ctlp;
+};
+
+/*
+ * the dialstring is of the form '[/net/]proto!dest'
+ */
+Chan*
+chandial(char *dest, char *local, char *dir, Chan **ctlp)
+{
+ DS ds;
+ char clone[Maxpath];
+
+ ds.local = local;
+ ds.dir = dir;
+ ds.ctlp = ctlp;
+
+ _dial_string_parse(dest, &ds);
+ if(ds.netdir == 0)
+ ds.netdir = "/net";
+
+ /* no connection server, don't translate */
+ snprint(clone, sizeof(clone), "%s/%s/clone", ds.netdir, ds.proto);
+ return call(clone, ds.rem, &ds);
+}
+
+static Chan*
+call(char *clone, char *dest, DS *ds)
+{
+ int n;
+ Chan *dchan, *cchan;
+ char name[Maxpath], data[Maxpath], *p;
+
+ cchan = namec(clone, Aopen, ORDWR, 0);
+
+ /* get directory name */
+ if(waserror()){
+ cclose(cchan);
+ nexterror();
+ }
+ n = devtab[cchan->type]->read(cchan, name, sizeof(name)-1, 0);
+ name[n] = 0;
+ for(p = name; *p == ' '; p++)
+ ;
+ sprint(name, "%lud", strtoul(p, 0, 0));
+ p = strrchr(clone, '/');
+ *p = 0;
+ if(ds->dir)
+ snprint(ds->dir, Maxpath, "%s/%s", clone, name);
+ snprint(data, sizeof(data), "%s/%s/data", clone, name);
+
+ /* connect */
+ if(ds->local)
+ snprint(name, sizeof(name), "connect %s %s", dest, ds->local);
+ else
+ snprint(name, sizeof(name), "connect %s", dest);
+ devtab[cchan->type]->write(cchan, name, strlen(name), 0);
+
+ /* open data connection */
+ dchan = namec(data, Aopen, ORDWR, 0);
+ if(ds->ctlp)
+ *ds->ctlp = cchan;
+ else
+ cclose(cchan);
+ poperror();
+ return dchan;
+
+}
+
+/*
+ * parse a dial string
+ */
+static void
+_dial_string_parse(char *str, DS *ds)
+{
+ char *p, *p2;
+
+ strncpy(ds->buf, str, Maxstring);
+ ds->buf[Maxstring-1] = 0;
+
+ p = strchr(ds->buf, '!');
+ if(p == 0) {
+ ds->netdir = 0;
+ ds->proto = "net";
+ ds->rem = ds->buf;
+ } else {
+ if(*ds->buf != '/' && *ds->buf != '#'){
+ ds->netdir = 0;
+ ds->proto = ds->buf;
+ } else {
+ for(p2 = p; *p2 != '/'; p2--)
+ ;
+ *p2++ = 0;
+ ds->netdir = ds->buf;
+ ds->proto = p2;
+ }
+ *p = 0;
+ ds->rem = p + 1;
+ }
+}