17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <regexp.h>
57dd7cddfSDavid du Colombier #include <thread.h>
67dd7cddfSDavid du Colombier #include <plumb.h>
77dd7cddfSDavid du Colombier #include "plumber.h"
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier static char*
nonnil(char * s)107dd7cddfSDavid du Colombier nonnil(char *s)
117dd7cddfSDavid du Colombier {
127dd7cddfSDavid du Colombier if(s == nil)
137dd7cddfSDavid du Colombier return "";
147dd7cddfSDavid du Colombier return s;
157dd7cddfSDavid du Colombier }
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier int
verbis(int obj,Plumbmsg * m,Rule * r)187dd7cddfSDavid du Colombier verbis(int obj, Plumbmsg *m, Rule *r)
197dd7cddfSDavid du Colombier {
207dd7cddfSDavid du Colombier switch(obj){
217dd7cddfSDavid du Colombier default:
227dd7cddfSDavid du Colombier fprint(2, "unimplemented 'is' object %d\n", obj);
237dd7cddfSDavid du Colombier break;
247dd7cddfSDavid du Colombier case OData:
257dd7cddfSDavid du Colombier return strcmp(m->data, r->qarg) == 0;
267dd7cddfSDavid du Colombier case ODst:
277dd7cddfSDavid du Colombier return strcmp(m->dst, r->qarg) == 0;
287dd7cddfSDavid du Colombier case OType:
297dd7cddfSDavid du Colombier return strcmp(m->type, r->qarg) == 0;
3059cc4ca5SDavid du Colombier case OWdir:
3159cc4ca5SDavid du Colombier return strcmp(m->wdir, r->qarg) == 0;
327dd7cddfSDavid du Colombier case OSrc:
337dd7cddfSDavid du Colombier return strcmp(m->src, r->qarg) == 0;
347dd7cddfSDavid du Colombier }
357dd7cddfSDavid du Colombier return 0;
367dd7cddfSDavid du Colombier }
377dd7cddfSDavid du Colombier
387dd7cddfSDavid du Colombier static void
setvar(Resub rs[10],char * match[10])397dd7cddfSDavid du Colombier setvar(Resub rs[10], char *match[10])
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier int i, n;
427dd7cddfSDavid du Colombier
437dd7cddfSDavid du Colombier for(i=0; i<10; i++){
447dd7cddfSDavid du Colombier free(match[i]);
457dd7cddfSDavid du Colombier match[i] = nil;
467dd7cddfSDavid du Colombier }
477dd7cddfSDavid du Colombier for(i=0; i<10 && rs[i].sp!=nil; i++){
487dd7cddfSDavid du Colombier n = rs[i].ep-rs[i].sp;
497dd7cddfSDavid du Colombier match[i] = emalloc(n+1);
507dd7cddfSDavid du Colombier memmove(match[i], rs[i].sp, n);
517dd7cddfSDavid du Colombier match[i][n] = '\0';
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier }
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier int
clickmatch(Reprog * re,char * text,Resub rs[10],int click)567dd7cddfSDavid du Colombier clickmatch(Reprog *re, char *text, Resub rs[10], int click)
577dd7cddfSDavid du Colombier {
587dd7cddfSDavid du Colombier char *clickp;
597dd7cddfSDavid du Colombier int i, w;
607dd7cddfSDavid du Colombier Rune r;
617dd7cddfSDavid du Colombier
627dd7cddfSDavid du Colombier /* click is in characters, not bytes */
637dd7cddfSDavid du Colombier for(i=0; i<click && text[i]!='\0'; i+=w)
647dd7cddfSDavid du Colombier w = chartorune(&r, text+i);
657dd7cddfSDavid du Colombier clickp = text+i;
667dd7cddfSDavid du Colombier for(i=0; i<=click; i++){
677dd7cddfSDavid du Colombier memset(rs, 0, 10*sizeof(Resub));
687dd7cddfSDavid du Colombier if(regexec(re, text+i, rs, 10))
697dd7cddfSDavid du Colombier if(rs[0].sp<=clickp && clickp<=rs[0].ep)
707dd7cddfSDavid du Colombier return 1;
717dd7cddfSDavid du Colombier }
727dd7cddfSDavid du Colombier return 0;
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier
757dd7cddfSDavid du Colombier int
verbmatches(int obj,Plumbmsg * m,Rule * r,Exec * e)767dd7cddfSDavid du Colombier verbmatches(int obj, Plumbmsg *m, Rule *r, Exec *e)
777dd7cddfSDavid du Colombier {
787dd7cddfSDavid du Colombier Resub rs[10];
797dd7cddfSDavid du Colombier char *clickval, *alltext;
8059cc4ca5SDavid du Colombier int p0, p1, ntext;
817dd7cddfSDavid du Colombier
827dd7cddfSDavid du Colombier memset(rs, 0, sizeof rs);
8359cc4ca5SDavid du Colombier ntext = -1;
847dd7cddfSDavid du Colombier switch(obj){
857dd7cddfSDavid du Colombier default:
867dd7cddfSDavid du Colombier fprint(2, "unimplemented 'matches' object %d\n", obj);
877dd7cddfSDavid du Colombier break;
887dd7cddfSDavid du Colombier case OData:
897dd7cddfSDavid du Colombier clickval = plumblookup(m->attr, "click");
907dd7cddfSDavid du Colombier if(clickval == nil){
917dd7cddfSDavid du Colombier alltext = m->data;
9259cc4ca5SDavid du Colombier ntext = m->ndata;
937dd7cddfSDavid du Colombier goto caseAlltext;
947dd7cddfSDavid du Colombier }
957dd7cddfSDavid du Colombier if(!clickmatch(r->regex, m->data, rs, atoi(clickval)))
967dd7cddfSDavid du Colombier break;
977dd7cddfSDavid du Colombier p0 = rs[0].sp - m->data;
987dd7cddfSDavid du Colombier p1 = rs[0].ep - m->data;
997dd7cddfSDavid du Colombier if(e->p0 >=0 && !(p0==e->p0 && p1==e->p1))
1007dd7cddfSDavid du Colombier break;
1017dd7cddfSDavid du Colombier e->clearclick = 1;
1027dd7cddfSDavid du Colombier e->setdata = 1;
1037dd7cddfSDavid du Colombier e->p0 = p0;
1047dd7cddfSDavid du Colombier e->p1 = p1;
1057dd7cddfSDavid du Colombier setvar(rs, e->match);
1067dd7cddfSDavid du Colombier return 1;
1077dd7cddfSDavid du Colombier case ODst:
10859cc4ca5SDavid du Colombier alltext = m->dst;
10959cc4ca5SDavid du Colombier goto caseAlltext;
1107dd7cddfSDavid du Colombier case OType:
1117dd7cddfSDavid du Colombier alltext = m->type;
11259cc4ca5SDavid du Colombier goto caseAlltext;
11359cc4ca5SDavid du Colombier case OWdir:
11459cc4ca5SDavid du Colombier alltext = m->wdir;
11559cc4ca5SDavid du Colombier goto caseAlltext;
11659cc4ca5SDavid du Colombier case OSrc:
11759cc4ca5SDavid du Colombier alltext = m->src;
1187dd7cddfSDavid du Colombier /* fall through */
1197dd7cddfSDavid du Colombier caseAlltext:
1207dd7cddfSDavid du Colombier /* must match full text */
12159cc4ca5SDavid du Colombier if(ntext < 0)
12259cc4ca5SDavid du Colombier ntext = strlen(alltext);
12359cc4ca5SDavid du Colombier if(!regexec(r->regex, alltext, rs, 10) || rs[0].sp!=alltext || rs[0].ep!=alltext+ntext)
1247dd7cddfSDavid du Colombier break;
1257dd7cddfSDavid du Colombier setvar(rs, e->match);
1267dd7cddfSDavid du Colombier return 1;
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier return 0;
1297dd7cddfSDavid du Colombier }
1307dd7cddfSDavid du Colombier
1317dd7cddfSDavid du Colombier int
isfile(char * file,ulong maskon,ulong maskoff)1327dd7cddfSDavid du Colombier isfile(char *file, ulong maskon, ulong maskoff)
1337dd7cddfSDavid du Colombier {
1349a747e4fSDavid du Colombier Dir *d;
1359a747e4fSDavid du Colombier int mode;
1367dd7cddfSDavid du Colombier
1379a747e4fSDavid du Colombier d = dirstat(file);
1389a747e4fSDavid du Colombier if(d == nil)
1397dd7cddfSDavid du Colombier return 0;
1409a747e4fSDavid du Colombier mode = d->mode;
1419a747e4fSDavid du Colombier free(d);
1429a747e4fSDavid du Colombier if((mode & maskon) == 0)
1437dd7cddfSDavid du Colombier return 0;
1449a747e4fSDavid du Colombier if(mode & maskoff)
1457dd7cddfSDavid du Colombier return 0;
1467dd7cddfSDavid du Colombier return 1;
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier
1497dd7cddfSDavid du Colombier char*
absolute(char * dir,char * file)1507dd7cddfSDavid du Colombier absolute(char *dir, char *file)
1517dd7cddfSDavid du Colombier {
1527dd7cddfSDavid du Colombier char *p;
1537dd7cddfSDavid du Colombier
1547dd7cddfSDavid du Colombier if(file[0] == '/')
1557dd7cddfSDavid du Colombier return estrdup(file);
1567dd7cddfSDavid du Colombier p = emalloc(strlen(dir)+1+strlen(file)+1);
1577dd7cddfSDavid du Colombier sprint(p, "%s/%s", dir, file);
1587dd7cddfSDavid du Colombier return cleanname(p);
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier
1617dd7cddfSDavid du Colombier int
verbisfile(int obj,Plumbmsg * m,Rule * r,Exec * e,ulong maskon,ulong maskoff,char ** var)1627dd7cddfSDavid du Colombier verbisfile(int obj, Plumbmsg *m, Rule *r, Exec *e, ulong maskon, ulong maskoff, char **var)
1637dd7cddfSDavid du Colombier {
1647dd7cddfSDavid du Colombier char *file;
1657dd7cddfSDavid du Colombier
1667dd7cddfSDavid du Colombier switch(obj){
1677dd7cddfSDavid du Colombier default:
1687dd7cddfSDavid du Colombier fprint(2, "unimplemented 'isfile' object %d\n", obj);
1697dd7cddfSDavid du Colombier break;
1707dd7cddfSDavid du Colombier case OArg:
1717dd7cddfSDavid du Colombier file = absolute(m->wdir, expand(e, r->arg, nil));
1727dd7cddfSDavid du Colombier if(isfile(file, maskon, maskoff)){
1737dd7cddfSDavid du Colombier *var = file;
1747dd7cddfSDavid du Colombier return 1;
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier free(file);
1777dd7cddfSDavid du Colombier break;
1787dd7cddfSDavid du Colombier case OData:
17959cc4ca5SDavid du Colombier case OWdir:
18059cc4ca5SDavid du Colombier file = absolute(m->wdir, obj==OData? m->data : m->wdir);
1817dd7cddfSDavid du Colombier if(isfile(file, maskon, maskoff)){
1827dd7cddfSDavid du Colombier *var = file;
1837dd7cddfSDavid du Colombier return 1;
1847dd7cddfSDavid du Colombier }
1857dd7cddfSDavid du Colombier free(file);
1867dd7cddfSDavid du Colombier break;
1877dd7cddfSDavid du Colombier }
1887dd7cddfSDavid du Colombier return 0;
1897dd7cddfSDavid du Colombier }
1907dd7cddfSDavid du Colombier
1917dd7cddfSDavid du Colombier int
verbset(int obj,Plumbmsg * m,Rule * r,Exec * e)1927dd7cddfSDavid du Colombier verbset(int obj, Plumbmsg *m, Rule *r, Exec *e)
1937dd7cddfSDavid du Colombier {
1947dd7cddfSDavid du Colombier char *new;
1957dd7cddfSDavid du Colombier
1967dd7cddfSDavid du Colombier switch(obj){
1977dd7cddfSDavid du Colombier default:
1987dd7cddfSDavid du Colombier fprint(2, "unimplemented 'is' object %d\n", obj);
1997dd7cddfSDavid du Colombier break;
2007dd7cddfSDavid du Colombier case OData:
2017dd7cddfSDavid du Colombier new = estrdup(expand(e, r->arg, nil));
2027dd7cddfSDavid du Colombier m->ndata = strlen(new);
2037dd7cddfSDavid du Colombier free(m->data);
2047dd7cddfSDavid du Colombier m->data = new;
2057dd7cddfSDavid du Colombier e->p0 = -1;
2067dd7cddfSDavid du Colombier e->p1 = -1;
2077dd7cddfSDavid du Colombier e->setdata = 0;
2087dd7cddfSDavid du Colombier return 1;
2097dd7cddfSDavid du Colombier case ODst:
2107dd7cddfSDavid du Colombier new = estrdup(expand(e, r->arg, nil));
2117dd7cddfSDavid du Colombier free(m->dst);
2127dd7cddfSDavid du Colombier m->dst = new;
2137dd7cddfSDavid du Colombier return 1;
2147dd7cddfSDavid du Colombier case OType:
2157dd7cddfSDavid du Colombier new = estrdup(expand(e, r->arg, nil));
2167dd7cddfSDavid du Colombier free(m->type);
2177dd7cddfSDavid du Colombier m->type = new;
2187dd7cddfSDavid du Colombier return 1;
21959cc4ca5SDavid du Colombier case OWdir:
22059cc4ca5SDavid du Colombier new = estrdup(expand(e, r->arg, nil));
22159cc4ca5SDavid du Colombier free(m->wdir);
22259cc4ca5SDavid du Colombier m->wdir = new;
22359cc4ca5SDavid du Colombier return 1;
2247dd7cddfSDavid du Colombier case OSrc:
2257dd7cddfSDavid du Colombier new = estrdup(expand(e, r->arg, nil));
2267dd7cddfSDavid du Colombier free(m->src);
2277dd7cddfSDavid du Colombier m->src = new;
2287dd7cddfSDavid du Colombier return 1;
2297dd7cddfSDavid du Colombier }
2307dd7cddfSDavid du Colombier return 0;
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier int
verbadd(int obj,Plumbmsg * m,Rule * r,Exec * e)2347dd7cddfSDavid du Colombier verbadd(int obj, Plumbmsg *m, Rule *r, Exec *e)
2357dd7cddfSDavid du Colombier {
2367dd7cddfSDavid du Colombier switch(obj){
2377dd7cddfSDavid du Colombier default:
2387dd7cddfSDavid du Colombier fprint(2, "unimplemented 'add' object %d\n", obj);
2397dd7cddfSDavid du Colombier break;
2407dd7cddfSDavid du Colombier case OAttr:
2417dd7cddfSDavid du Colombier m->attr = plumbaddattr(m->attr, plumbunpackattr(expand(e, r->arg, nil)));
2427dd7cddfSDavid du Colombier return 1;
2437dd7cddfSDavid du Colombier }
2447dd7cddfSDavid du Colombier return 0;
2457dd7cddfSDavid du Colombier }
2467dd7cddfSDavid du Colombier
2477dd7cddfSDavid du Colombier int
verbdelete(int obj,Plumbmsg * m,Rule * r,Exec * e)2487dd7cddfSDavid du Colombier verbdelete(int obj, Plumbmsg *m, Rule *r, Exec *e)
2497dd7cddfSDavid du Colombier {
2507dd7cddfSDavid du Colombier char *a;
2517dd7cddfSDavid du Colombier
2527dd7cddfSDavid du Colombier switch(obj){
2537dd7cddfSDavid du Colombier default:
2547dd7cddfSDavid du Colombier fprint(2, "unimplemented 'delete' object %d\n", obj);
2557dd7cddfSDavid du Colombier break;
2567dd7cddfSDavid du Colombier case OAttr:
2577dd7cddfSDavid du Colombier a = expand(e, r->arg, nil);
2587dd7cddfSDavid du Colombier if(plumblookup(m->attr, a) == nil)
2597dd7cddfSDavid du Colombier break;
2607dd7cddfSDavid du Colombier m->attr = plumbdelattr(m->attr, a);
2617dd7cddfSDavid du Colombier return 1;
2627dd7cddfSDavid du Colombier }
2637dd7cddfSDavid du Colombier return 0;
2647dd7cddfSDavid du Colombier }
2657dd7cddfSDavid du Colombier
2667dd7cddfSDavid du Colombier int
matchpat(Plumbmsg * m,Exec * e,Rule * r)2677dd7cddfSDavid du Colombier matchpat(Plumbmsg *m, Exec *e, Rule *r)
2687dd7cddfSDavid du Colombier {
2697dd7cddfSDavid du Colombier switch(r->verb){
2707dd7cddfSDavid du Colombier default:
2717dd7cddfSDavid du Colombier fprint(2, "unimplemented verb %d\n", r->verb);
2727dd7cddfSDavid du Colombier break;
2737dd7cddfSDavid du Colombier case VAdd:
2747dd7cddfSDavid du Colombier return verbadd(r->obj, m, r, e);
2757dd7cddfSDavid du Colombier case VDelete:
2767dd7cddfSDavid du Colombier return verbdelete(r->obj, m, r, e);
2777dd7cddfSDavid du Colombier case VIs:
2787dd7cddfSDavid du Colombier return verbis(r->obj, m, r);
2797dd7cddfSDavid du Colombier case VIsdir:
2809a747e4fSDavid du Colombier return verbisfile(r->obj, m, r, e, DMDIR, 0, &e->dir);
2817dd7cddfSDavid du Colombier case VIsfile:
2829a747e4fSDavid du Colombier return verbisfile(r->obj, m, r, e, ~DMDIR, DMDIR, &e->file);
2837dd7cddfSDavid du Colombier case VMatches:
2847dd7cddfSDavid du Colombier return verbmatches(r->obj, m, r, e);
2857dd7cddfSDavid du Colombier case VSet:
2867dd7cddfSDavid du Colombier verbset(r->obj, m, r, e);
2877dd7cddfSDavid du Colombier return 1;
2887dd7cddfSDavid du Colombier }
2897dd7cddfSDavid du Colombier return 0;
2907dd7cddfSDavid du Colombier }
2917dd7cddfSDavid du Colombier
2927dd7cddfSDavid du Colombier void
freeexec(Exec * exec)2937dd7cddfSDavid du Colombier freeexec(Exec *exec)
2947dd7cddfSDavid du Colombier {
2957dd7cddfSDavid du Colombier int i;
2967dd7cddfSDavid du Colombier
2977dd7cddfSDavid du Colombier if(exec == nil)
2987dd7cddfSDavid du Colombier return;
2997dd7cddfSDavid du Colombier free(exec->dir);
3007dd7cddfSDavid du Colombier free(exec->file);
3017dd7cddfSDavid du Colombier for(i=0; i<10; i++)
3027dd7cddfSDavid du Colombier free(exec->match[i]);
3037dd7cddfSDavid du Colombier free(exec);
3047dd7cddfSDavid du Colombier }
3057dd7cddfSDavid du Colombier
3067dd7cddfSDavid du Colombier Exec*
newexec(Plumbmsg * m)3077dd7cddfSDavid du Colombier newexec(Plumbmsg *m)
3087dd7cddfSDavid du Colombier {
3097dd7cddfSDavid du Colombier Exec *exec;
3107dd7cddfSDavid du Colombier
3117dd7cddfSDavid du Colombier exec = emalloc(sizeof(Exec));
3127dd7cddfSDavid du Colombier exec->msg = m;
3137dd7cddfSDavid du Colombier exec->p0 = -1;
3147dd7cddfSDavid du Colombier exec->p1 = -1;
3157dd7cddfSDavid du Colombier return exec;
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier
3187dd7cddfSDavid du Colombier void
rewrite(Plumbmsg * m,Exec * e)3197dd7cddfSDavid du Colombier rewrite(Plumbmsg *m, Exec *e)
3207dd7cddfSDavid du Colombier {
3217dd7cddfSDavid du Colombier Plumbattr *a, *prev;
3227dd7cddfSDavid du Colombier
3237dd7cddfSDavid du Colombier if(e->clearclick){
3247dd7cddfSDavid du Colombier prev = nil;
3257dd7cddfSDavid du Colombier for(a=m->attr; a!=nil; a=a->next){
3267dd7cddfSDavid du Colombier if(strcmp(a->name, "click") == 0){
3277dd7cddfSDavid du Colombier if(prev == nil)
3287dd7cddfSDavid du Colombier m->attr = a->next;
3297dd7cddfSDavid du Colombier else
3307dd7cddfSDavid du Colombier prev->next = a->next;
3317dd7cddfSDavid du Colombier free(a->name);
3327dd7cddfSDavid du Colombier free(a->value);
3337dd7cddfSDavid du Colombier free(a);
3347dd7cddfSDavid du Colombier break;
3357dd7cddfSDavid du Colombier }
3367dd7cddfSDavid du Colombier prev = a;
3377dd7cddfSDavid du Colombier }
3387dd7cddfSDavid du Colombier if(e->setdata){
3397dd7cddfSDavid du Colombier free(m->data);
3407dd7cddfSDavid du Colombier m->data = estrdup(expand(e, "$0", nil));
3417dd7cddfSDavid du Colombier m->ndata = strlen(m->data);
3427dd7cddfSDavid du Colombier }
3437dd7cddfSDavid du Colombier }
3447dd7cddfSDavid du Colombier }
3457dd7cddfSDavid du Colombier
3467dd7cddfSDavid du Colombier char**
buildargv(char * s,Exec * e)3477dd7cddfSDavid du Colombier buildargv(char *s, Exec *e)
3487dd7cddfSDavid du Colombier {
3497dd7cddfSDavid du Colombier char **av;
3507dd7cddfSDavid du Colombier int ac;
3517dd7cddfSDavid du Colombier
3527dd7cddfSDavid du Colombier ac = 0;
3537dd7cddfSDavid du Colombier av = nil;
3547dd7cddfSDavid du Colombier for(;;){
3557dd7cddfSDavid du Colombier av = erealloc(av, (ac+1) * sizeof(char*));
3567dd7cddfSDavid du Colombier av[ac] = nil;
3577dd7cddfSDavid du Colombier while(*s==' ' || *s=='\t')
3587dd7cddfSDavid du Colombier s++;
3597dd7cddfSDavid du Colombier if(*s == '\0')
3607dd7cddfSDavid du Colombier break;
3617dd7cddfSDavid du Colombier av[ac++] = estrdup(expand(e, s, &s));
3627dd7cddfSDavid du Colombier }
3637dd7cddfSDavid du Colombier return av;
3647dd7cddfSDavid du Colombier }
3657dd7cddfSDavid du Colombier
3667dd7cddfSDavid du Colombier Exec*
matchruleset(Plumbmsg * m,Ruleset * rs)3677dd7cddfSDavid du Colombier matchruleset(Plumbmsg *m, Ruleset *rs)
3687dd7cddfSDavid du Colombier {
3697dd7cddfSDavid du Colombier int i;
3707dd7cddfSDavid du Colombier Exec *exec;
3717dd7cddfSDavid du Colombier
3727dd7cddfSDavid du Colombier if(m->dst!=nil && m->dst[0]!='\0' && rs->port!=nil && strcmp(m->dst, rs->port)!=0)
3737dd7cddfSDavid du Colombier return nil;
3747dd7cddfSDavid du Colombier exec = newexec(m);
3757dd7cddfSDavid du Colombier for(i=0; i<rs->npat; i++)
3767dd7cddfSDavid du Colombier if(!matchpat(m, exec, rs->pat[i])){
3777dd7cddfSDavid du Colombier freeexec(exec);
3787dd7cddfSDavid du Colombier return nil;
3797dd7cddfSDavid du Colombier }
3807dd7cddfSDavid du Colombier if(rs->port!=nil && (m->dst==nil || m->dst[0]=='\0')){
3817dd7cddfSDavid du Colombier free(m->dst);
3827dd7cddfSDavid du Colombier m->dst = estrdup(rs->port);
3837dd7cddfSDavid du Colombier }
3847dd7cddfSDavid du Colombier rewrite(m, exec);
3857dd7cddfSDavid du Colombier return exec;
3867dd7cddfSDavid du Colombier }
3877dd7cddfSDavid du Colombier
3887dd7cddfSDavid du Colombier enum
3897dd7cddfSDavid du Colombier {
3907dd7cddfSDavid du Colombier NARGS = 100,
3917dd7cddfSDavid du Colombier NARGCHAR = 8*1024,
392*853458f3SDavid du Colombier EXECSTACK = 8192+(NARGS+1)*sizeof(char*)+NARGCHAR
3937dd7cddfSDavid du Colombier };
3947dd7cddfSDavid du Colombier
3957dd7cddfSDavid du Colombier /* copy argv to stack and free the incoming strings, so we don't leak argument vectors */
3967dd7cddfSDavid du Colombier void
stackargv(char ** inargv,char * argv[NARGS+1],char args[NARGCHAR])3977dd7cddfSDavid du Colombier stackargv(char **inargv, char *argv[NARGS+1], char args[NARGCHAR])
3987dd7cddfSDavid du Colombier {
3997dd7cddfSDavid du Colombier int i, n;
4007dd7cddfSDavid du Colombier char *s, *a;
4017dd7cddfSDavid du Colombier
4027dd7cddfSDavid du Colombier s = args;
4037dd7cddfSDavid du Colombier for(i=0; i<NARGS; i++){
4047dd7cddfSDavid du Colombier a = inargv[i];
4057dd7cddfSDavid du Colombier if(a == nil)
4067dd7cddfSDavid du Colombier break;
4077dd7cddfSDavid du Colombier n = strlen(a)+1;
4087dd7cddfSDavid du Colombier if((s-args)+n >= NARGCHAR) /* too many characters */
4097dd7cddfSDavid du Colombier break;
4107dd7cddfSDavid du Colombier argv[i] = s;
4117dd7cddfSDavid du Colombier memmove(s, a, n);
4127dd7cddfSDavid du Colombier s += n;
4137dd7cddfSDavid du Colombier free(a);
4147dd7cddfSDavid du Colombier }
4157dd7cddfSDavid du Colombier argv[i] = nil;
4167dd7cddfSDavid du Colombier }
4177dd7cddfSDavid du Colombier
4187dd7cddfSDavid du Colombier
4197dd7cddfSDavid du Colombier void
execproc(void * v)4207dd7cddfSDavid du Colombier execproc(void *v)
4217dd7cddfSDavid du Colombier {
4227dd7cddfSDavid du Colombier char **av;
4237dd7cddfSDavid du Colombier char buf[1024], *args[NARGS+1], argc[NARGCHAR];
4247dd7cddfSDavid du Colombier
4257dd7cddfSDavid du Colombier rfork(RFFDG);
42639734e7eSDavid du Colombier close(0);
42739734e7eSDavid du Colombier open("/dev/null", OREAD);
4287dd7cddfSDavid du Colombier av = v;
4297dd7cddfSDavid du Colombier stackargv(av, args, argc);
4307dd7cddfSDavid du Colombier free(av);
4317dd7cddfSDavid du Colombier procexec(nil, args[0], args);
4327dd7cddfSDavid du Colombier if(args[0][0]!='/' && strncmp(args[0], "./", 2)!=0 && strncmp(args[0], "../", 3)!=0)
4337dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "/bin/%s", args[0]);
4347dd7cddfSDavid du Colombier procexec(nil, buf, args);
4357dd7cddfSDavid du Colombier threadexits("can't exec");
4367dd7cddfSDavid du Colombier }
4377dd7cddfSDavid du Colombier
4387dd7cddfSDavid du Colombier char*
startup(Ruleset * rs,Exec * e)4397dd7cddfSDavid du Colombier startup(Ruleset *rs, Exec *e)
4407dd7cddfSDavid du Colombier {
4417dd7cddfSDavid du Colombier char **argv;
4427dd7cddfSDavid du Colombier int i;
4437dd7cddfSDavid du Colombier
4447dd7cddfSDavid du Colombier if(rs != nil)
4457dd7cddfSDavid du Colombier for(i=0; i<rs->nact; i++){
4467dd7cddfSDavid du Colombier if(rs->act[i]->verb == VStart)
4477dd7cddfSDavid du Colombier goto Found;
4487dd7cddfSDavid du Colombier if(rs->act[i]->verb == VClient){
4497dd7cddfSDavid du Colombier if(e->msg->dst==nil || e->msg->dst[0]=='\0')
4507dd7cddfSDavid du Colombier return "no port for \"client\" rule";
4517dd7cddfSDavid du Colombier e->holdforclient = 1;
4527dd7cddfSDavid du Colombier goto Found;
4537dd7cddfSDavid du Colombier }
4547dd7cddfSDavid du Colombier }
4557dd7cddfSDavid du Colombier return "no start action for plumb message";
4567dd7cddfSDavid du Colombier
4577dd7cddfSDavid du Colombier Found:
4587dd7cddfSDavid du Colombier argv = buildargv(rs->act[i]->arg, e);
4597dd7cddfSDavid du Colombier if(argv[0] == nil)
4607dd7cddfSDavid du Colombier return "empty argument list";
4617dd7cddfSDavid du Colombier proccreate(execproc, argv, EXECSTACK);
4627dd7cddfSDavid du Colombier return nil;
4637dd7cddfSDavid du Colombier }
464