shithub: riscv

Download patch

ref: 98aefdfc7862e39b7b8fa1aefe9d7af3b676da36
parent: 9e8e4444a3856877ed7632fb3a878a014ced994f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jun 4 17:42:17 EDT 2023

ndb/query: add -i and -c flags unifying the functionality of ndb/ipqeury

I'm a bit tired of ndb/ipquery having a different interface
than ndb/query. Given that most scripts are running it in a sed
pipeline to extact just the value without the attribute name
while ndb/query does the thing one would expect.

So this allows one to do ipinfo searches (also thru ndb/cs
using the -c flag) while only getting the values (when only
one rattr is specified). And honiuring the the -a and -m
flags as well.

--- a/sys/man/8/ndb
+++ b/sys/man/8/ndb
@@ -4,8 +4,11 @@
 .SH SYNOPSIS
 .B ndb/query
 [
-.B -am
+.B -acim
 ] [
+.B -x
+.I netmtpt
+] [
 .B -f
 .I dbfile
 ]
@@ -12,10 +15,7 @@
 .I "attr value"
 [
 .I rattr
-.\" [
-.\" .I reps
-.\" ]
-]
+]...
 .br
 .B ndb/ipquery
 .I "attr value"
@@ -134,36 +134,81 @@
 etc.
 .PP
 .I Ndb/query
-searches the database
-.I dbfile
-.RB ( /lib/ndb/local
-by default)
+searches the network database
 for an attribute of type
 .I attr
 and value
 .IR value .
-If
+If a single
 .I rattr
-is not specified, all entries matched by the search are printed.
-If
+is specified, only the value of the first matching pair
+with attribute
 .I rattr
-is specified, the value of the first pair with attribute
-.I rattr
-of all the matched entries normally is printed.
+is printed.
 Under
-.B -m
-and
-.IR rattr ,
+.BR -m ,
 the values of all pairs with a
 .I rattr
 attribute within the first matching entry are printed.
 Under
 .B -a
-and
+and with a single
 .IR rattr ,
 all values of pairs with a
 .I rattr
 attribute within all entries are printed.
+If none or more than one
+.I rattr
+where specified,
+all entries matched by the search are printed in
+.IR ndb (6)
+format.
+When the
+.B -i
+flag is present,
+the type attribute
+.I attr
+and its
+.I value
+are relating to systems with
+.B ip=
+tuples,
+and the search will return
+.I rattr
+attributes inherited from their corresponding
+.B ipnet=
+entries.
+(see the
+.I ndbipinfo
+and
+.I csipinfo
+functions in
+.IR ndb (2)).
+The
+.B -i
+flag requires at least one
+.IR rattr .
+When
+.B -c
+flag is specified,
+instead of opening the network database files directly,
+the connection server mounted on
+.I netmtpt
+is consulted.
+The
+.I netmtpt
+can be changed using the
+.B -x
+option
+(default
+.BR /net ).
+Without the
+.B -c
+flag,
+the network database is searched directly by opening
+.I dbfile
+.RB ( /lib/ndb/local
+by default).
 .PP
 .I Ndb/ipquery
 uses
@@ -172,7 +217,7 @@
 .IR ndb (2))
 to search for the values of the attributes
 .I rattr
-corresponding to the system
+corresponding to the systems
 with entries of attribute type
 .I attr
 and
--- a/sys/src/cmd/ndb/query.c
+++ b/sys/src/cmd/ndb/query.c
@@ -6,114 +6,169 @@
 #include <bio.h>
 #include <ndb.h>
 
-static int all, multiple;
+/* for ndbvalfmt */
+#pragma varargck type "$" char*
+
+static int all, multiple, ipinfo, csinfo;
+static Ndb *db = nil;
+static char *net = nil;
 static Biobuf bout;
 
-void
-usage(void)
+static char*
+skipat(char *s)
 {
-	fprint(2, "usage: query [-am] [-f ndbfile] attr value "
-		"[returned-attr [reps]]\n");
-	exits("usage");
+	if(*s == '@')
+		s++;
+	return s;
 }
 
+static int
+match(char *attr, char **rattr, int nrattr)
+{
+	int i;
+
+	if(nrattr == 0)
+		return 1;
+	for(i = 0; i < nrattr; i++){
+		if(strcmp(attr, skipat(rattr[i])) == 0)
+			return 1;
+	}
+	return 0;
+}
+
 /* print values of nt's attributes matching rattr */
 static void
-prmatch(Ndbtuple *nt, char *rattr)
+prmatch(Ndbtuple *nt, char **rattr, int nrattr)
 {
-	for(; nt; nt = nt->entry)
-		if (strcmp(nt->attr, rattr) == 0)
-			Bprint(&bout, "%s\n", nt->val);
+	if(nt == nil)
+		return;
+
+	if(nrattr == 1) {
+		for(; nt != nil; nt = nt->entry){
+			if(match(nt->attr, rattr, nrattr)){
+				Bprint(&bout, "%s\n", nt->val);
+				if(!multiple && !all)
+					break;
+			}
+		}
+	} else {
+		for(; nt != nil; nt = nt->entry){
+			if(match(nt->attr, rattr, nrattr)){
+				Bprint(&bout, "%s=%$ ", nt->attr, nt->val);
+				if(nt->entry != nt->line)
+					Bprint(&bout, "\n\t");
+			}
+		}
+		Bprint(&bout, "\n");
+	}
 }
 
-/* for ndbvalfmt */
-#pragma varargck type "$" char*
-
-void
-search(Ndb *db, char *attr, char *val, char *rattr)
+static void
+search(char *attr, char *val, char **rattr, int nrattr)
 {
 	char *p;
 	Ndbs s;
-	Ndbtuple *t, *nt;
+	Ndbtuple *t;
 
-	/* first entry with a matching rattr */
-	if(rattr && !all){
-		p = ndbgetvalue(db, &s, attr, val, rattr, &t);
-		if (multiple)
-			prmatch(t, rattr);
-		else if(p)
+	if(ipinfo){
+		if(csinfo)
+			t = csipinfo(net, attr, val, rattr, nrattr);
+		else
+			t = ndbipinfo(db, attr, val, rattr, nrattr);
+		prmatch(t, rattr, nrattr);
+		ndbfree(t);
+		return;
+	}
+
+	if(nrattr == 1 && !all){
+		if(csinfo)
+			p = csgetvalue(net, attr, val, rattr[0], &t);
+		else
+			p = ndbgetvalue(db, &s, attr, val, rattr[0], &t);
+		if(p != nil && !multiple)
 			Bprint(&bout, "%s\n", p);
+		else
+			prmatch(t, rattr, nrattr);
 		ndbfree(t);
 		free(p);
 		return;
 	}
 
-	/* all entries with matching rattrs */
-	if(rattr) {
-		for(t = ndbsearch(db, &s, attr, val); t != nil;
-		    t = ndbsnext(&s, attr, val)){
-			prmatch(t, rattr);
-			ndbfree(t);
-		}
+	if(csinfo)
 		return;
-	}
 
-	/* all entries */
-	for(t = ndbsearch(db, &s, attr, val); t; t = ndbsnext(&s, attr, val)){
-		for(nt = t; nt; nt = nt->entry)
-			Bprint(&bout, "%s=%$ ", nt->attr, nt->val);
-		Bprint(&bout, "\n");
+	for(t = ndbsearch(db, &s, attr, val); t != nil; t = ndbsnext(&s, attr, val)){
+		prmatch(t, rattr, nrattr);
 		ndbfree(t);
+		if(!all)
+			break;
 	}
 }
 
+static void
+usage(void)
+{
+	fprint(2, "usage: %s [-acim] [-x netmtpt] [-f ndbfile] attr value [rattr]...\n", argv0);
+	exits("usage");
+}
+
 void
 main(int argc, char **argv)
 {
-	int reps = 1;
-	char *rattr = nil, *dbfile = nil;
-	Ndb *db;
-	
-	fmtinstall('$', ndbvalfmt);
+	char *dbfile = nil;
 
 	ARGBEGIN{
 	case 'a':
-		all++;
+		all = 1;
 		break;
-	case 'm':
-		multiple++;
+	case 'c':
+		csinfo = 1;
 		break;
 	case 'f':
 		dbfile = EARGF(usage());
 		break;
+	case 'i':
+		ipinfo = 1;
+		break;
+	case 'm':
+		multiple = 1;
+		break;
+	case 'x':
+		net = EARGF(usage());
+		break;
 	default:
 		usage();
 	}ARGEND;
 
 	switch(argc){
-	case 4:
-		reps = atoi(argv[3]);	/* wtf use is this? */
-		/* fall through */
-	case 3:
-		rattr = argv[2];
+	case 0:
+	case 1:
+		usage();
 		break;
 	case 2:
-		rattr = nil;
+		if(ipinfo)
+			usage();
+		csinfo = 0;
 		break;
 	default:
-		usage();
+		break;
 	}
 
+	fmtinstall('$', ndbvalfmt);
+
 	if(Binit(&bout, 1, OWRITE) == -1)
 		sysfatal("Binit: %r");
-	db = ndbopen(dbfile);
-	if(db == nil){
-		fprint(2, "%s: no db files\n", argv0);
-		exits("no db");
-	}
-	while(reps--)
-		search(db, argv[0], argv[1], rattr);
-	ndbclose(db);
 
-	exits(0);
+	if(csinfo)
+		search(argv[0], argv[1], argv+2, argc-2);
+	else {
+		db = ndbopen(dbfile);
+		if(db == nil){
+			fprint(2, "%s: no db files\n", argv0);
+			exits("no db");
+		}
+		search(argv[0], argv[1], argv+2, argc-2);
+		ndbclose(db);
+	}
+	exits(nil);
 }