]> git.lizzy.rs Git - plan9front.git/commitdiff
ptrap: implement filtering on plumb attributes
authorkvik <kvik@a-b.xyz>
Sun, 6 Dec 2020 20:52:01 +0000 (21:52 +0100)
committerkvik <kvik@a-b.xyz>
Sun, 6 Dec 2020 20:52:01 +0000 (21:52 +0100)
sys/man/4/ptrap
sys/src/cmd/ptrap.c

index 5c29956ad8da2353969b01ac7ed4aa3dd6172ffa..35238b4c94ec593c3956c494514eaf060dc85ad9 100644 (file)
@@ -7,10 +7,7 @@ filter
 .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 @@ service mounted at
 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 @@ instance for all other editing jobs:
 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
index 7cf60f7d431195b6f481884b2cff6944a28f3ad4..dae3c088d3e75fba6945b6c485149ab7b6dd2a7a 100644 (file)
@@ -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 @@ struct PFid {
 };
 Qid rootqid = {.type QTDIR};
 
+struct FAttr {
+       char *name;
+       Reprog *filt;
+       int invert;
+       FAttr *next;
+};
+
 struct PFilter {
        char *name;
        Reprog *filt;
-       PFilter *next;
        int invert;
+       FAttr *attr;
+       PFilter *next;
 };
 PFilter *filters;
 
@@ -161,13 +170,33 @@ ptrapopen(Req *r)
        respond(r, nil);
 }
 
+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 @@ filterread(Req *r, PFid *pf)
                        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 @@ Srv ptrapsrv = {
 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 @@ void
 threadmain(int argc, char **argv)
 {
        PFilter *f;
+       FAttr *fa;
        char *p;
        int i;
 
@@ -357,19 +387,33 @@ threadmain(int argc, char **argv)
        }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);