ref: 59402bf42b8b199218f1f0d111aaf273a3c1806a
parent: 9f31bb10802dc95999bf2923981a49486ccee3f0
author: sirjofri <sirjofri@sirjofri.de>
date: Thu Sep 4 07:30:44 EDT 2025
adds service listener fetcher
--- a/README
+++ b/README
@@ -5,7 +5,8 @@
netgraph - generate a network graph of the Plan 9 system
SYNOPSIS
- netgraph [ -ip ] [ -s systuples ] [ -n ipnettuples ]
+ netgraph [ -ipl ] [ -s systuples ] [ -n ipnettuples ] [ -x
+ netmtpt ]
fullnetgraph [ ... ]
DESCRIPTION
@@ -41,6 +42,11 @@
It is equivalent to running netgraph | ps2pdf
-g1191x842 -r72, but the size adjusts automatically to
the actual drawing.
+
+ -l Netgraph tries to fetch a list of network listeners
+ based on files in /cfg/$sysname/service.
+
+ -x Use this flag to use a different network device.
-s systuples
The user can adjust the relevant fields to search for
--- a/draw.c
+++ b/draw.c
@@ -6,6 +6,7 @@
static int lineheight = 10;
static int charwidth = 6;
+static int foldline = 32;
static int boxoffsetx = 2;
static int boxoffsety = 2;
@@ -78,6 +79,19 @@
p1.x, p2.y);
}
+static char*
+strrnchr(char *str, int n, int c)
+{
+ char *s;
+ s = &str[n];
+ while (s > str) {
+ if (*s == c)
+ return s;
+ s--;
+ }
+ return nil;
+}
+
static int
isipnet(Tuple *t)
{
@@ -89,6 +103,8 @@
{
Color c;
Pos *p = aux;
+ char *s, *s2;
+ int n, fl;
int ipnet = isipnet(t);
if (!showipnet && t->ipnet && !ipnet)
@@ -100,13 +116,29 @@
print("%f %f %f setrgbcolor\n", c.r, c.g, c.b);
}
- drawtext(*p, 1, "%s%s: %s", t->ipnet ? "*" : "", t->key, t->value);
+ fl = foldline - strlen(t->key) - 3;
+ s = t->value;
+ while (strlen(s) > fl) {
+ s2 = strrnchr(s, fl, ',');
+ if (!s2)
+ s2 = &s[fl];
+ n = s2 - s + 1;
+ drawtext(*p, 1, "%s%s: %.*s", t->ipnet ? "*" : "", t->key, n, s);
+ p->y -= lineheight;
+ s = s2;
+ if (*s == ',')
+ s++;
+ while (*s == ' ')
+ s++;
+ }
+ if (strlen(s)) {
+ drawtext(*p, 1, "%s%s: %s", t->ipnet ? "*" : "", t->key, s);
+ p->y -= lineheight;
+ }
if (ipnet) {
print("grestore\n");
}
-
- p->y -= lineheight;
}
void
@@ -125,14 +157,36 @@
tuplesize(Tuple *t, void *aux)
{
Block *b = aux;
- int w;
+ char *s, *s2;
+ int w, nw;
+ int fl;
if (!showipnet && t->ipnet && !isipnet(t))
return;
- b->height += lineheight;
+ fl = foldline - strlen(t->key) - 3;
+ w = 0;
+ s = t->value;
+ while (strlen(s) > fl) {
+ s2 = strrnchr(s, fl, ',');
+ if (!s2)
+ s2 = &s[fl];
+ nw = s2 - s + 1;
+ if (nw > w) w = nw;
+ b->height += lineheight;
+ s = s2;
+ if (*s == ',')
+ s++;
+ while (*s == ' ')
+ s++;
+ }
+ if (strlen(s)) {
+ nw = strlen(s);
+ if (nw > w) w = nw;
+ b->height += lineheight;
+ }
- w = strlen(t->key) + strlen(t->value) + 3;
+ w = strlen(t->key) + w + 3;
if (w > b->width)
b->width = w;
}
--- a/fns.h
+++ b/fns.h
@@ -22,6 +22,9 @@
int numsystems(void);
void forsysarg(int (*f)(char*,void*), void*);
+/* srv functions */
+void fetchsrv(Sys*,void*);
+
/* conn functions */
void addconn(Sys*, Sys*, char*);
void forconn(void (*f)(Conn*,void*), void*);
--- a/mkfile
+++ b/mkfile
@@ -9,6 +9,7 @@
ipnet.$O\
tuple.$O\
conns.$O\
+ srv.$O\
HFILES=dat.h fns.h
--- a/netgraph.c
+++ b/netgraph.c
@@ -9,7 +9,7 @@
static void
usage(void)
{
- fprint(2, "usage: %s [-ip] [-s systuples] [-n ipnettuples]\n", argv0);
+ fprint(2, "usage: %s [-ipl] [-s systuples] [-n ipnettuples] [-x netmtpt]\n", argv0);
exits("usage");
}
@@ -29,6 +29,7 @@
int pageheight = 842;
int showipnet = 0;
+int showsrv = 0;
static void
procrequest(char *key, char *val)
@@ -236,6 +237,9 @@
case 'i':
showipnet++;
break;
+ case 'l': /* listeners */
+ showsrv++;
+ break;
case 'p':
pdf++;
break;
@@ -259,6 +263,8 @@
Bterm(bin);
/* calculation stage */
+ if (showsrv)
+ forsys(fetchsrv, nil);
i = 0;
forsys(calcsyslayout, &i);
--- a/netgraph1
+++ b/netgraph1
@@ -4,15 +4,16 @@
.SH SYNOPSIS
.B netgraph
[
-.B -ip
-]
-[
+.B -ipl
+] [
.B -s
.I systuples
-]
-[
+] [
.B -n
.I ipnettuples
+] [
+.B -x
+.I netmtpt
]
.br
.B fullnetgraph
@@ -66,6 +67,12 @@
It is equivalent to running
.BR "netgraph | ps2pdf -g1191x842 -r72" ,
but the size adjusts automatically to the actual drawing.
+.IP \fL-l\fR
+.I Netgraph
+tries to fetch a list of network listeners based on files in
+.BR /cfg/$sysname/service .
+.IP \fL-x\fR \fInetmtpt\fR
+Use this flag to use a different network device.
.IP "\fL-s\fR \fIsystuples\fR"
The user can adjust the relevant fields to search for by providing a comma separated list of field names.
.IP "\fL-n\fR \fIipnettuples\fR"
--- /dev/null
+++ b/srv.c
@@ -1,0 +1,104 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ndb.h>
+#include <String.h>
+#include "dat.h"
+#include "fns.h"
+
+static char *protos[] = {
+ "tcp", "udp", "il",
+};
+
+static char*
+findnumber(char *s)
+{
+ while (*s) {
+ if (*s >= '0' && *s <= '9')
+ return s;
+ s++;
+ }
+ return nil;
+}
+
+static int
+validproto(char *proto)
+{
+ int n = sizeof(protos) / sizeof(*protos);
+ for (int i = 0; i < n; i++)
+ if (strcmp(proto, protos[i]) == 0)
+ return 1;
+ return 0;
+}
+
+static char*
+getport(char *num, char *proto)
+{
+ char *s;
+
+ if (!validproto(proto))
+ return nil;
+
+ s = csgetvalue(netdir, "port", num, proto, nil);
+ return s ? s : strdup(num);
+}
+
+static void
+condadd(Sys *sys, char *name)
+{
+ char *s;
+ char num[6];
+ Tuple *t;
+ int n;
+
+ if (name[0] == '!')
+ return;
+
+ s = findnumber(name);
+ strncpy(num, s, sizeof(num));
+ *s = 0;
+
+ s = getport(num, name);
+ if (!s)
+ return;
+
+ t = findtuple(sys, name);
+ if (!t) {
+ addtuple(sys, strdup(name), s, 0);
+ return;
+ }
+
+ /* lengths + ", " + 0 */
+ n = strlen(t->value);
+ t->value = realloc(t->value, n + strlen(s) + 2 + 1);
+ strcpy(&t->value[n], ", ");
+ strcpy(&t->value[n+2], s);
+ free(s);
+}
+
+void
+fetchsrv(Sys *sys, void*)
+{
+ char path[128];
+ int fd;
+ Tuple *t;
+ int n;
+ Dir *d;
+
+ t = findtuple(sys, "sys");
+ if (!t)
+ return;
+
+ snprint(path, sizeof(path), "/cfg/%s/service", t->value);
+ fd = open(path, OREAD);
+ if (fd < 0)
+ return;
+ while ((n = dirread(fd, &d)) > 0) {
+ for (int i = 0; i < n; i++) {
+ if (!(d[i].mode & DMEXEC))
+ continue;
+ condadd(sys, d[i].name);
+ }
+ free(d);
+ }
+}
--
⑨