<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"
http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf8">
<title>/usr/web/sources/contrib/cinap_lenrek/dial.c - Plan 9 from Bell Labs</title>
<!-- THIS FILE IS AUTOMATICALLY GENERATED. -->
<!-- EDIT sources.tr INSTEAD. -->
</meta>
</head>
<body>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"><a href="/plan9/">Plan 9 from Bell Labs</a>’s /usr/web/sources/contrib/cinap_lenrek/dial.c</span></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
Copyright © 2009 Alcatel-Lucent.<br />
Distributed under the
<a href="/plan9/license.html">Lucent Public License version 1.02</a>.
<br />
<a href="/plan9/download.html">Download the Plan 9 distribution.</a>
</font>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<table width="100%" cellspacing=0 border=0><tr><td align="center">
<table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left">
<pre>
<!-- END HEADER -->
#include <u.h>
#include <libc.h>
enum
{
Maxconcurr = 4,
Maxstring = 128,
};
typedef struct DS DS;
typedef struct Conn Conn;
struct DS {
/* dist string */
char *netdir;
char *proto;
char *rem;
/* other args */
char *local;
char *dir;
int *cfdp;
};
struct Conn {
Conn *next;
int pid;
int cfd;
int dfd;
char dest[Maxstring];
char dir[NETPATHLEN];
};
static Conn*
openconn(char *clone, char *dest, char *netdir)
{
char *x, *p, *e;
Conn *c;
int n;
if((c = malloc(sizeof(Conn))) == nil)
return nil;
c->next = nil;
c->pid = 0;
c->cfd = -1;
c->dfd = -1;
snprint(c->dest, sizeof c->dest, "%s", dest);
if(netdir){
if(*clone == '/' && (p = strchr(clone+1, '/')))
clone = ++p;
snprint(c->dir, sizeof c->dir, "%s/%s", netdir, clone);
} else
snprint(c->dir, sizeof c->dir, "%s", clone);
e = c->dir + sizeof c->dir;
if((p = strrchr(c->dir, '/')) == nil)
goto err;
if((c->cfd = open(c->dir, ORDWR)) < 0)
goto err;
if((n = (e - p)-1) <= 0)
goto err;
if((n = read(c->cfd, p, n)) <= 0)
goto err;
p[n] = 0;
for(x = p; *x == ' '; x++)
;
snprint(p, e - p, "/%ld/data", strtoul(x, 0, 0));
if((c->dfd = open(c->dir, ORDWR)) < 0)
goto err;
if(p = strrchr(c->dir, '/'))
*p = 0;
return c;
err:
if(c->cfd >= 0)
close(c->cfd);
if(c->dfd >= 0)
close(c->dfd);
free(c);
return nil;
}
static char*
readcs(int cs, char *buf, int nbuf, char **destp)
{
char *p;
int n;
if((n = read(cs, buf, nbuf-1)) <= 0)
return nil;
if(buf[n-1] == '\n')
n--;
buf[n] = 0;
if((p = strchr(buf, ' ')) == nil)
return nil;
*p++ = 0;
if(destp)
*destp = p;
return buf;
}
static Conn*
getconn(int cs, char *buf, int nbuf, char *netdir)
{
char *clone, *dest;
if(clone = readcs(cs, buf, nbuf, &dest))
return openconn(clone, dest, netdir);
return nil;
}
static int
connect(Conn *c, char *local)
{
if(local)
return fprint(c->cfd, "connect %s %s", c->dest, local) > 0;
else
return fprint(c->cfd, "connect %s", c->dest) > 0;
}
static int
aconnect(Conn *c, char *local)
{
if((c->pid = rfork(RFPROC)) < 0)
return 0;
else if(c->pid > 0)
return 1;
notify(nil);
if(connect(c, local))
_exits(nil);
_exits("%r");
return -1;
}
static int
canfork(char *buf, int nbuf)
{
int fd;
snprint(buf, nbuf, "/proc/%d/note", getpid());
if((fd = open(buf, OWRITE)) >= 0)
close(fd);
return fd >= 0;
}
static int
csdial(DS *ds)
{
char buf[Maxstring+NETPATHLEN+4];
Conn *conns, *winner, *c;
int cs, ret, kids, more;
conns = winner = nil;
snprint(buf, sizeof buf, "%s/cs", ds->netdir);
if((cs = open(buf, ORDWR)) < 0){
snprint(buf, sizeof buf, "%s/%s/clone", ds->netdir, ds->proto);
if((conns = openconn(buf, ds->rem, nil)) == nil)
goto out;
if(connect(conns, ds->local))
winner = conns;
goto out;
}
if(fprint(cs, "%s!%s", ds->proto, ds->rem) < 0)
goto out;
seek(cs, 0, 0);
if((conns = getconn(cs, buf, sizeof buf, ds->netdir)) == nil){
werrstr("no address to dial");
goto out;
}
conns->next = getconn(cs, buf, sizeof buf, ds->netdir);
if(conns->next == nil || !canfork(buf, sizeof buf)){
if(connect(c = conns, ds->local)){
winner = c;
goto out;
}
if((c = c->next) == nil)
goto out;
if(connect(c, ds->local)){
winner = c;
goto out;
}
while(c->next = getconn(cs, buf, sizeof buf, ds->netdir)){
if(connect(c = c->next, ds->local)){
winner = c;
goto out;
}
}
goto out;
}
more = 1;
kids = 0;
if(aconnect(conns, ds->local))
kids++;
if(aconnect(conns->next, ds->local))
kids++;
for(;;){
Waitmsg *m;
while(more && kids < Maxconcurr){
if((c = getconn(cs, buf, sizeof buf, ds->netdir)) == nil){
more = 0;
break;
}
c->next = conns;
conns = c;
if(aconnect(c, ds->local))
kids++;
}
if(kids == 0)
break;
if(m = wait()){
for(c = conns; c; c = c->next){
if(c->pid != m->pid)
continue;
c->pid = 0;
--kids;
if(m->msg[0]){
char *p;
if(p = strchr(m->msg, ':'))
p++;
else
p = m->msg;
while(*p == ' ')
p++;
werrstr("%s", p);
} else if(winner)
fprint(c->cfd, "hangup");
else
winner = c;
break;
}
free(m);
}
if(winner || m == nil){
more = 0;
for(c = conns; c; c = c->next)
if(c->pid)
postnote(PNPROC, c->pid, "die");
}
}
out:
if(cs >= 0)
close(cs);
if(c = winner){
if(ds->dir)
strncpy(ds->dir, c->dir, NETPATHLEN);
if(ds->cfdp)
*ds->cfdp = c->cfd;
else
close(c->cfd);
ret = c->dfd;
} else
ret = -1;
while(c = conns){
conns = c->next;
if(c != winner){
close(c->cfd);
close(c->dfd);
}
free(c);
}
return ret;
}
int
dial(char *dest, char *local, char *dir, int *cfdp)
{
char buf[Maxstring], *p, *x;
int ret;
DS ds;
ds.local = local;
ds.dir = dir;
ds.cfdp = cfdp;
snprint(buf, sizeof buf, "%s", dest);
if((p = strchr(buf, '!')) == 0) {
ds.netdir = 0;
ds.proto = "net";
ds.rem = buf;
} else {
if(buf[0] != '/' && buf[0] != '#'){
ds.netdir = 0;
ds.proto = buf;
} else {
for(x = p; *x != '/'; x--)
;
*x++ = 0;
ds.netdir = buf;
ds.proto = x;
}
*p++ = 0;
ds.rem = p;
}
if(ds.netdir)
return csdial(&ds);
ds.netdir = "/net";
if((ret = csdial(&ds)) < 0){
char err[ERRMAX];
rerrstr(err, sizeof err);
if(strstr(err, "refused"))
return ret;
ds.netdir = "/net.alt";
if((ret = csdial(&ds)) < 0){
char alterr[ERRMAX];
/* use previous error if /net.alt was not available */
rerrstr(alterr, sizeof alterr);
if(strstr(alterr, "translate") || strstr(alterr, "does not exist"))
werrstr("%s", err);
}
}
return ret;
}
<!-- BEGIN TAIL -->
</pre>
</td></tr></table>
</td></tr></table>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"></span></p>
<p style="margin-top: 0; margin-bottom: 0.50in"></p>
<p style="margin-top: 0; margin-bottom: 0.33in"></p>
<center><table border="0"><tr>
<td valign="middle"><a href="
http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" />
</a></td>
<td valign="middle"><a href="
http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" />
</a></td>
<td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" />
</td>
</tr></table></center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center>
<span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
<span style="font-size: 10pt"><a href="
http://www.lucent.com/copyright.html">Copyright</a></span>
<span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span>
<span style="font-size: 10pt">All Rights Reserved.</span>
<br />
<span style="font-size: 10pt">Comments to</span>
<span style="font-size: 10pt"><a href="mailto:
[email protected]">
[email protected]</a>.</span>
</font></center>
</body>
</html>