From: kvik@a-b.xyz
To: 9front@9front.org
Subject: Re: [9front] [PATCH] ptrap: implement attribute filters
Date: Sat, 05 Dec 2020 19:07:31 GMT [thread overview]
Message-ID: <7BFBE5377160E95529838E329D9AEB60@hog> (raw)
In-Reply-To: <0236D9AD4D5FBA15B144E815E3EBCC47@eigenstate.org>
Quoth ori@eigenstate.org:
> Looking over the code, only thought is that this bit may read
> better as a nested loop, like:
That's quite true. Readability++ version follows.
diff -r 52827b94aac8 sys/man/4/ptrap
--- a/sys/man/4/ptrap Wed Dec 02 00:57:21 2020 +0100
+++ b/sys/man/4/ptrap Sat Dec 05 19:40:38 2020 +0100
@@ -7,10 +7,7 @@
.B ptrap
.I port
[\fB!\fR]\fIregexp\fR
-[
-.I port
-[\fB!\fR]\fIregexp\fR ...
-]
+[ +\fIattr\fR [\fB!\fR]\fIregexp\fR ... ] ...
.SH DESCRIPTION
.I Ptrap
is a program that mounts itself over a
@@ -20,20 +17,20 @@
and filters incoming messages according to the rules provided on the command line.
.PP
.I Ptrap
-accepts an arbitrary number of argument pairs; each pair consists of a port name
-.I port
-and a regular expression
-.I regexp
-(see
-.IR regexp (6)).
-Each incoming message that does not match
-.I regexp
-is discarded.
-The
-.I regexp
-can be optionally prefixed by
-.B !
-to indicate logical inversion (i.e. messages matching the regexp are discarded).
+accepts an arbitrary number of filters;
+each filter applies to a port, and may match over both the data and attributes of plumb messages.
+.PP
+A filter is formatted as a port name, a data filter, and a list of attribute filters.
+.PP
+The data filter is a
+.IR regex (6)
+that matches the plumbed data.
+The attribute filter consists of the attribute name prefixed with a '+', followed by a
+.IR regex (6)
+that matches the contents of the attribute.
+Any regex may be prefixed with a '!' in order to negate a match,
+causing all matches for that regex to be discarded.
+All parts of a filter must match in order for a plumb message to be forwarded.
.SH EXAMPLES
Start a
.IR sam (1)
@@ -52,6 +49,15 @@
ptrap edit '!^/sys/src/9/'
sam
.EE
+.PP
+Start an
+.IR acme (1)
+instance instance dedicated to reading plumbed manual pages:
+.IP
+.EX
+ptrap edit '.*' +action '^showdata' +filename '^/man/'
+acme -c1
+.EE
.SH SOURCE
.B /sys/src/cmd/ptrap.c
.SH SEE ALSO
diff -r 52827b94aac8 sys/src/cmd/ptrap.c
--- a/sys/src/cmd/ptrap.c Wed Dec 02 00:57:21 2020 +0100
+++ b/sys/src/cmd/ptrap.c Sat Dec 05 19:40:38 2020 +0100
@@ -8,6 +8,7 @@
typedef struct IOProc IOProc;
typedef struct PFilter PFilter;
+typedef struct FAttr FAttr;
typedef struct PFid PFid;
struct IOProc {
@@ -27,11 +28,19 @@
};
Qid rootqid = {.type QTDIR};
+struct FAttr {
+ char *name;
+ Reprog *filt;
+ int invert;
+ FAttr *next;
+};
+
struct PFilter {
char *name;
Reprog *filt;
+ int invert;
+ FAttr *attr;
PFilter *next;
- int invert;
};
PFilter *filters;
@@ -162,12 +171,32 @@
}
static int
+filter(PFilter *f, Plumbmsg *pm)
+{
+ FAttr *a;
+ char *value;
+
+ if(!(regexec(f->filt, pm->data, nil, 0) ^ f->invert))
+ return 0;
+ for(a = f->attr; a; a = a->next){
+ value = plumblookup(pm->attr, a->name);
+ if(value == nil)
+ return 0;
+ if(!(regexec(a->filt, value, nil, 0) ^ f->attr->invert))
+ return 0;
+ }
+ return 1;
+}
+
+static int
filterread(Req *r, PFid *pf)
{
int rc, len, more;
char *buf;
Plumbmsg *pm;
+ PFilter *f;
+ f = pf->filter;
for(;;){
if(pf->msg != nil){
rc = r->ifcall.count;
@@ -194,7 +223,7 @@
len += rc;
}
free(buf);
- if(regexec(pf->filter->filt, pm->data, nil, 0) ^ pf->filter->invert){
+ if(filter(f, pm)){
pf->msg = plumbpack(pm, &pf->msgn);
pf->msgp = 0;
}
@@ -341,7 +370,7 @@
void
usage(void)
{
- fprint(2, "usage: %s port regex [ port regex ... ]\n", argv0);
+ fprint(2, "usage: %s port regex [ +attr regex ... ] ...\n", argv0);
exits("usage");
}
@@ -349,6 +378,7 @@
threadmain(int argc, char **argv)
{
PFilter *f;
+ FAttr *fa;
char *p;
int i;
@@ -357,19 +387,33 @@
}ARGEND;
if(argc == 0 || argc % 2) usage();
- for(i = 0; i < argc; i += 2){
+ for(i = 0; i+1 < argc;){
+ p = argv[i];
f = emalloc9p(sizeof(PFilter));
- f->name = strdup(argv[i]);
+ f->name = estrdup9p(p);
p = argv[i+1];
- if(*p == '!'){
+ if(p[0] == '!'){
p++;
f->invert = 1;
}
- f->filt = regcomp(p);
- if(f->filt == nil)
- sysfatal("%r");
+ if((f->filt = regcomp(p)) == nil)
+ sysfatal("regcomp: %r");
f->next = filters;
filters = f;
+ for(i += 2; p = argv[i], i+1 < argc && p[0] == '+'; i += 2){
+ p++;
+ fa = emalloc9p(sizeof(FAttr));
+ fa->name = estrdup9p(p);
+ p = argv[i+1];
+ if(p[0] == '!'){
+ p++;
+ fa->invert = 1;
+ }
+ if((fa->filt = regcomp(p)) == nil)
+ sysfatal("regcomp: %r");
+ fa->next = f->attr;
+ f->attr = fa;
+ }
}
threadpostmountsrv(&ptrapsrv, nil, "/mnt/plumb", MREPL | MCREATE);
next prev parent reply other threads:[~2020-12-05 19:08 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-05 16:52 kvik
2020-12-05 17:32 ` ori
2020-12-05 19:07 ` kvik [this message]
2020-12-06 0:49 ` ori
2020-12-06 20:55 ` kvik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7BFBE5377160E95529838E329D9AEB60@hog \
--to=kvik@a-b.xyz \
--cc=9front@9front.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).