ref: 9f31bb10802dc95999bf2923981a49486ccee3f0
dir: /netgraph.c/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ndb.h>
#include <String.h>
#include "dat.h"
#include "fns.h"
static void
usage(void)
{
fprint(2, "usage: %s [-ip] [-s systuples] [-n ipnettuples]\n", argv0);
exits("usage");
}
#define MAXSYSTP 24
char *Sipnet = "ipnet";
char *netdir = nil;
char *systuples[MAXSYSTP];
int nsystuples = 0;
char *ipnettuples[MAXSYSTP];
int nipnettuples = 0;
/* A3 format: 842 x 1191 */
int pagewidth = 1191;
int pageheight = 842;
int showipnet = 0;
static void
procrequest(char *key, char *val)
{
if (issysarg(key)) {
gensys(key, val);
return;
}
if (isnetarg(key)) {
genipnet(key, val);
return;
}
}
static void
procinput(char *s)
{
char *c;
c = strchr(s, '=');
if (!(c && c[0] && c[1]))
return;
c[0] = 0;
c++;
procrequest(s, c);
}
void
dumptuples(Tuple *t, void*)
{
fprint(2, " %s=%s\n", t->key, t->value);
}
void
dumpsys(Sys *s, void*)
{
fprint(2, "sys: %d %d\n", s->p.x, s->p.y);
fortuple(s, dumptuples, nil);
}
void
dumpipnet(Ipnet *n, void*)
{
fprint(2, "ipnet\n");
fortuple(n, dumptuples, nil);
}
static Color
hue2color(float h)
{
Color c;
int i = h;
float f = h * 6. - i;
float p = 0.;
float q = 1. - f;
float t = 1. - (1. - f);
switch (i % 6) {
case 0: c.r = 1; c.g = t; c.b = p; break;
case 1: c.r = q; c.g = 1; c.b = p; break;
case 2: c.r = p; c.g = 1; c.b = t; break;
case 3: c.r = p; c.g = q; c.b = 1; break;
case 4: c.r = t; c.g = p; c.b = 1; break;
case 5: c.r = 1; c.g = p; c.b = q; break;
}
c.r = c.r < 0 ? 0 : c.r;
c.g = c.g < 0 ? 0 : c.g;
c.b = c.b < 0 ? 0 : c.b;
return c;
}
typedef struct Calcipnetparams Calcipnetparams;
struct Calcipnetparams {
int i;
int x;
};
static void
calcnetlayout(Ipnet *n, void *aux)
{
Calcipnetparams *p = aux;
int num = numipnets();
int i = p->i;
float step = 2*PI / num;
float hue = (step * i) / PI;
n->color = hue2color(hue);
setblocksize(n);
n->p.x = p->x + 5;
n->p.y = 5;
p->i++;
p->x += n->width + 10;
}
static void
calcsyslayout(Sys *s, void *aux)
{
int n = numsystems();
int *ip = aux;
int i = *ip;
float step = 2*PI / n;
setblocksize(s);
float pagex = pagewidth/2.;
float pagey = pageheight/2.;
float spread = 0.6;
s->p.x = cos(step * i) * pagex * spread + pagex - s->width/2;
s->p.y = sin(step * i) * pagey * spread + pagey - s->height/2;
(*ip)++;
}
static void
calcconn(Tuple *t, void *aux)
{
Sys *from = aux;
Sys *to = findsys(t->key, t->value);
if (!to)
return;
if (to == from)
return;
addconn(from, to, t->key);
}
void
calcconns(Sys *s, void*)
{
fortuple(s, calcconn, s);
}
static void
drawconns(Conn *c, void*)
{
dconn(c->from, c->to, s_to_c(c->types));
}
static void
drawsystems(Sys *s, void*)
{
dblock(s);
}
static void
drawipnets(Ipnet *n, void*)
{
dblock(n);
}
static void
injectpdfout(void)
{
char *size;
int p[2];
pipe(p);
switch (fork()) {
case -1:
sysfatal("fork: %r");
case 0:
break;
default: /* parent */
dup(p[0], 1);
close(p[1]);
return;
}
/* child */
dup(p[1], 0);
close(p[0]);
size = smprint("-g%dx%d", pagewidth, pageheight);
execl("/bin/ps2pdf", "ps2pdf", size, "-r72", nil);
sysfatal("execl: %r");
}
void
main(int argc, char **argv)
{
Biobuf *bin;
Calcipnetparams netparams;
char *stp = "sys,ether,ip,ipgw,ipnet,dom,auth,authdom";
char *ntp = "ipnet,ip,ipmask,ipgw,authdom,auth,fs,dns";
char *s;
int i;
int pdf = 0;
ARGBEGIN{
case 'h':
usage();
case 's':
stp = EARGF(usage());
break;
case 'n':
ntp = EARGF(usage());
break;
case 'x':
netdir = EARGF(usage());
break;
case 'i':
showipnet++;
break;
case 'p':
pdf++;
break;
}ARGEND;
if (pdf)
injectpdfout();
nsystuples = getfields(stp, systuples, MAXSYSTP, 1, ",");
nipnettuples = getfields(ntp, ipnettuples, MAXSYSTP, 1, ",");
bin = Bfdopen(0, OREAD);
if (!bin)
sysfatal("%r");
while (s = Brdstr(bin, '\n', 1)) {
procinput(s);
free(s);
}
Bterm(bin);
/* calculation stage */
i = 0;
forsys(calcsyslayout, &i);
netparams.i = 0;
netparams.x = 0;
fornet(calcnetlayout, &netparams);
forsys(calcconns, nil);
/* drawing stage */
dheader();
forconn(drawconns, nil);
forsys(drawsystems, nil);
fornet(drawipnets, nil);
dfooter();
}
static int
tryaddsys(char *s, void *aux)
{
char *sys = aux;
return gensys(s, sys);
}
void
fillblockvalue(Block *b, char *key, char *ids, char *idv)
{
char *val;
Ndbtuple *t;
val = csgetvalue(netdir, ids, idv, key, nil);
if (val) {
addtuple(b, key, val, 0);
return;
}
t = csipinfo(netdir, ids, idv, &key, 1);
if (t) {
if (t->val)
val = strdup(t->val);
ndbfree(t);
}
if (!val)
return;
addtuple(b, key, val, 1);
if (!isconnsrv(key))
return;
forsysarg(tryaddsys, val);
}