From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: ** X-Spam-Status: No, score=2.3 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, FROM_SUSPICIOUS_NTLD,FROM_SUSPICIOUS_NTLD_FP,PDS_OTHER_BAD_TLD, RCVD_IN_DNSWL_NONE autolearn=no autolearn_force=no version=3.4.4 Received: (qmail 30428 invoked from network); 5 Dec 2020 16:53:33 -0000 Received: from ewsd.inri.net (107.191.116.128) by inbox.vuxu.org with ESMTPUTF8; 5 Dec 2020 16:53:33 -0000 Received: from out1.migadu.com ([91.121.223.63]) by ewsd; Sat Dec 5 11:51:56 -0500 2020 Message-ID: <7FEC8FB4A961AC2CBF0FB20FA1FBCDDB@hog> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=a-b.xyz; s=key1; t=1607187153; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=UOG1fPUoHWULyUu6w/0VqvHc3PD8x5da2ss/tN82uJg=; b=q0macdam5UTGahondn3i1lR7w0TFgxcES/J4bLOMinPcO6Z7R7AagDlt0nk7yY/Z8YLWnX b1nDPJAtI99RmbMTDQ6cN929q89Z79niAGGGVSYdtcT2RDoilQs69vUYokIT4o3fG1cyhi 5/PXgZHF1TqP3nYj6sm60cdhBWamtn0ESmJwXPEDNZbHuk8LZixluOQs0ZHZ1YAeskLu6a yjcP46deBS0Smc8tJ5mJCmsry+t3NqHzdR3Q/Jcb+eL3zq8KyE5DmMh3s4lpzOUlHr5uUs zUvR6MXWZrBuiLLOl05Y2tPQ3QTvtPhdhq0PbD2jiBJnhRQwA238j5eEq9qIvQ== To: 9front@9front.org X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: kvik@a-b.xyz MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Migadu-Flow: FLOW_OUT X-Migadu-Auth-User: kvik@a-b.xyz Date: Sat, 05 Dec 2020 16:52:33 GMT List-ID: <9front.9front.org> List-Help: X-Glyph: ➈ X-Bullshit: secure decentralized software-based element hypervisor GPU event Subject: [9front] [PATCH] ptrap: implement attribute filters Reply-To: 9front@9front.org Precedence: bulk This adds support for filtering plumbs based on message attributes. An example use case is to make a specific acme instance display the manual pages produced by man -b or plumbing the manual reference words: ptrap edit '.*' +action '^showdata' +filename '^/man/' --- Works fine on my machine, but I'd appreciate some eyes and testing from more prolific ptrap users than myself. 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 17:37:27 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 17:37:27 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,40 @@ }ARGEND; if(argc == 0 || argc % 2) usage(); - for(i = 0; i < argc; i += 2){ + for(i = 0; i < argc; ){ + p = argv[i++]; f = emalloc9p(sizeof(PFilter)); - f->name = strdup(argv[i]); - p = argv[i+1]; - if(*p == '!'){ + f->name = estrdup9p(p); + p = argv[i++]; + 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; + +next: + p = argv[i++]; + if(p == nil || p[0] != '+'){ + i--; + continue; + } + p++; + fa = emalloc9p(sizeof(FAttr)); + fa->name = estrdup9p(p); + p = argv[i++]; + if(p[0] == '!'){ + p++; + fa->invert = 1; + } + if((fa->filt = regcomp(p)) == nil) + sysfatal("regcomp: %r"); + fa->next = f->attr; + f->attr = fa; + + goto next; } threadpostmountsrv(&ptrapsrv, nil, "/mnt/plumb", MREPL | MCREATE);