10 verbis(int obj, Plumbmsg *m, Rule *r)
14 fprint(2, "unimplemented 'is' object %d\n", obj);
17 return strcmp(m->data, r->qarg) == 0;
19 return strcmp(m->dst, r->qarg) == 0;
21 return strcmp(m->type, r->qarg) == 0;
23 return strcmp(m->wdir, r->qarg) == 0;
25 return strcmp(m->src, r->qarg) == 0;
31 setvar(Resub rs[10], char *match[10])
39 for(i=0; i<10 && rs[i].sp!=nil; i++){
40 n = rs[i].ep-rs[i].sp;
41 match[i] = emalloc(n+1);
42 memmove(match[i], rs[i].sp, n);
48 clickmatch(Reprog *re, char *text, Resub rs[10], int click)
54 /* click is in characters, not bytes */
55 for(i=0; i<click && text[i]!='\0'; i+=w)
56 w = chartorune(&r, text+i);
58 for(i=0; i<=click; i++){
59 memset(rs, 0, 10*sizeof(Resub));
60 if(regexec(re, text+i, rs, 10))
61 if(rs[0].sp<=clickp && clickp<=rs[0].ep)
68 verbmatches(int obj, Plumbmsg *m, Rule *r, Exec *e)
71 char *clickval, *alltext;
74 memset(rs, 0, sizeof rs);
78 fprint(2, "unimplemented 'matches' object %d\n", obj);
81 clickval = plumblookup(m->attr, "click");
87 if(!clickmatch(r->regex, m->data, rs, atoi(clickval)))
89 p0 = rs[0].sp - m->data;
90 p1 = rs[0].ep - m->data;
91 if(e->p0 >=0 && !(p0==e->p0 && p1==e->p1))
112 /* must match full text */
114 ntext = strlen(alltext);
115 if(!regexec(r->regex, alltext, rs, 10) || rs[0].sp!=alltext || rs[0].ep!=alltext+ntext)
117 setvar(rs, e->match);
124 isfile(char *file, ulong maskon, ulong maskoff)
134 if((mode & maskon) == 0)
142 absolute(char *dir, char *file)
147 return estrdup(file);
148 p = emalloc(strlen(dir)+1+strlen(file)+1);
149 sprint(p, "%s/%s", dir, file);
154 verbisfile(int obj, Plumbmsg *m, Rule *r, Exec *e, ulong maskon, ulong maskoff, char **var)
160 fprint(2, "unimplemented 'isfile' object %d\n", obj);
163 file = absolute(m->wdir, expand(e, r->arg, nil));
164 if(isfile(file, maskon, maskoff)){
172 file = absolute(m->wdir, obj==OData? m->data : m->wdir);
173 if(isfile(file, maskon, maskoff)){
184 verbset(int obj, Plumbmsg *m, Rule *r, Exec *e)
190 fprint(2, "unimplemented 'is' object %d\n", obj);
193 new = estrdup(expand(e, r->arg, nil));
194 m->ndata = strlen(new);
202 new = estrdup(expand(e, r->arg, nil));
207 new = estrdup(expand(e, r->arg, nil));
212 new = estrdup(expand(e, r->arg, nil));
217 new = estrdup(expand(e, r->arg, nil));
226 verbadd(int obj, Plumbmsg *m, Rule *r, Exec *e)
230 fprint(2, "unimplemented 'add' object %d\n", obj);
233 m->attr = plumbaddattr(m->attr, plumbunpackattr(expand(e, r->arg, nil)));
240 verbdelete(int obj, Plumbmsg *m, Rule *r, Exec *e)
246 fprint(2, "unimplemented 'delete' object %d\n", obj);
249 a = expand(e, r->arg, nil);
250 if(plumblookup(m->attr, a) == nil)
252 m->attr = plumbdelattr(m->attr, a);
259 matchpat(Plumbmsg *m, Exec *e, Rule *r)
263 fprint(2, "unimplemented verb %d\n", r->verb);
266 return verbadd(r->obj, m, r, e);
268 return verbdelete(r->obj, m, r, e);
270 return verbis(r->obj, m, r);
272 return verbisfile(r->obj, m, r, e, DMDIR, 0, &e->dir);
274 return verbisfile(r->obj, m, r, e, ~DMDIR, DMDIR, &e->file);
276 return verbmatches(r->obj, m, r, e);
278 verbset(r->obj, m, r, e);
294 free(exec->match[i]);
303 exec = emalloc(sizeof(Exec));
311 rewrite(Plumbmsg *m, Exec *e)
317 for(a=m->attr; a!=nil; a=a->next){
318 if(strcmp(a->name, "click") == 0){
322 prev->next = a->next;
332 m->data = estrdup(expand(e, "$0", nil));
333 m->ndata = strlen(m->data);
339 buildargv(char *s, Exec *e)
347 av = erealloc(av, (ac+1) * sizeof(char*));
349 while(*s==' ' || *s=='\t')
353 av[ac++] = estrdup(expand(e, s, &s));
359 matchruleset(Plumbmsg *m, Ruleset *rs)
364 if(m->dst!=nil && m->dst[0]!='\0' && rs->port!=nil && strcmp(m->dst, rs->port)!=0)
367 for(i=0; i<rs->npat; i++)
368 if(!matchpat(m, exec, rs->pat[i])){
372 if(rs->port!=nil && (m->dst==nil || m->dst[0]=='\0')){
374 m->dst = estrdup(rs->port);
384 EXECSTACK = 4096+(NARGS+1)*sizeof(char*)+NARGCHAR
387 /* copy argv to stack and free the incoming strings, so we don't leak argument vectors */
389 stackargv(char **inargv, char *argv[NARGS+1], char args[NARGCHAR])
395 for(i=0; i<NARGS; i++){
400 if((s-args)+n >= NARGCHAR) /* too many characters */
415 char buf[1024], *args[NARGS+1], argc[NARGCHAR];
419 open("/dev/null", OREAD);
421 stackargv(av, args, argc);
423 procexec(nil, args[0], args);
424 if(args[0][0]!='/' && strncmp(args[0], "./", 2)!=0 && strncmp(args[0], "../", 3)!=0)
425 snprint(buf, sizeof buf, "/bin/%s", args[0]);
426 procexec(nil, buf, args);
427 threadexits("can't exec");
431 startup(Ruleset *rs, Exec *e)
437 for(i=0; i<rs->nact; i++){
438 if(rs->act[i]->verb == VStart)
440 if(rs->act[i]->verb == VClient){
441 if(e->msg->dst==nil || e->msg->dst[0]=='\0')
442 return "no port for \"client\" rule";
443 e->holdforclient = 1;
447 return "no start action for plumb message";
450 argv = buildargv(rs->act[i]->arg, e);
452 return "empty argument list";
453 proccreate(execproc, argv, EXECSTACK);