blob: d9fad8a9c977e396474c16eb718fdbe3778cf006 [file] [log] [blame]
#include <vfs.h>
#include <kfs.h>
#include <slab.h>
#include <kmalloc.h>
#include <kref.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <error.h>
#include <cpio.h>
#include <pmap.h>
#include <smp.h>
struct ds;
static struct chan *call(char *unused_char_p_t, char *, struct ds *);
static void _dial_string_parse(char *unused_char_p_t, struct ds *);
enum {
Maxstring = 128,
};
struct ds {
char buf[Maxstring]; /* dist string */
char *netdir;
char *proto;
char *rem;
char *local; /* other args */
char *dir;
struct chan **ctlp;
};
/*
* the dialstring is of the form '[/net/]proto!dest'
*/
struct chan *chandial(char *dest, char *local, char *dir, struct chan **ctlp)
{
struct 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 */
snprintf(clone, sizeof(clone), "%s/%s/clone", ds.netdir, ds.proto);
return call(clone, ds.rem, &ds);
}
static struct chan *call(char *clone, char *dest, struct ds *ds)
{
ERRSTACK(2);
int n;
struct chan *dchan, *cchan;
char name[Maxpath], data[Maxpath], *p;
cchan = namec(clone, Aopen, ORDWR, 0);
/* get directory name */
if (waserror()) {
cclose(cchan);
nexterror();
}
n = cchan->dev->read(cchan, name, sizeof(name) - 1, 0);
name[n] = 0;
for (p = name; *p == ' '; p++) ;
snprintf(name, sizeof(name), "%lu", strtoul(p, 0, 0));
p = strrchr(clone, '/');
*p = 0;
if (ds->dir)
snprintf(ds->dir, Maxpath, "%s/%s", clone, name);
snprintf(data, sizeof(data), "%s/%s/data", clone, name);
/* connect */
if (ds->local)
snprintf(name, sizeof(name), "connect %s %s", dest, ds->local);
else
snprintf(name, sizeof(name), "connect %s", dest);
cchan->dev->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, struct 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;
}
}