19a747e4fSDavid du Colombier /*
29a747e4fSDavid du Colombier * ``Exec'' network device. Mounted on net, provides /net/exec.
39a747e4fSDavid du Colombier *
49a747e4fSDavid du Colombier * exec protocol directory
59a747e4fSDavid du Colombier * n connection directory
69a747e4fSDavid du Colombier * ctl control messages (like connect)
79a747e4fSDavid du Colombier * data data
89a747e4fSDavid du Colombier * err errors
99a747e4fSDavid du Colombier * local local address (pid of command)
109a747e4fSDavid du Colombier * remote remote address (command)
119a747e4fSDavid du Colombier * status status
129a747e4fSDavid du Colombier */
139a747e4fSDavid du Colombier
149a747e4fSDavid du Colombier #include <u.h>
159a747e4fSDavid du Colombier #include <libc.h>
169a747e4fSDavid du Colombier #include <fcall.h>
179a747e4fSDavid du Colombier #include <thread.h>
189a747e4fSDavid du Colombier #include <9p.h>
199a747e4fSDavid du Colombier #include "dat.h"
209a747e4fSDavid du Colombier
219a747e4fSDavid du Colombier int fsdebug;
229a747e4fSDavid du Colombier
239a747e4fSDavid du Colombier enum
249a747e4fSDavid du Colombier {
259a747e4fSDavid du Colombier Qroot,
269a747e4fSDavid du Colombier Qexec,
279a747e4fSDavid du Colombier Qclone,
289a747e4fSDavid du Colombier Qn,
299a747e4fSDavid du Colombier Qctl,
309a747e4fSDavid du Colombier Qdata,
319a747e4fSDavid du Colombier Qlocal,
329a747e4fSDavid du Colombier Qremote,
339a747e4fSDavid du Colombier Qstatus,
349a747e4fSDavid du Colombier };
359a747e4fSDavid du Colombier
369a747e4fSDavid du Colombier #define PATH(type, n) ((type)|((n)<<8))
379a747e4fSDavid du Colombier #define TYPE(path) ((int)(path) & 0xFF)
389a747e4fSDavid du Colombier #define NUM(path) ((uint)(path)>>8)
399a747e4fSDavid du Colombier
409a747e4fSDavid du Colombier typedef struct Tab Tab;
419a747e4fSDavid du Colombier struct Tab
429a747e4fSDavid du Colombier {
439a747e4fSDavid du Colombier char *name;
449a747e4fSDavid du Colombier ulong mode;
459a747e4fSDavid du Colombier };
469a747e4fSDavid du Colombier
479a747e4fSDavid du Colombier Tab tab[] =
489a747e4fSDavid du Colombier {
499a747e4fSDavid du Colombier "/", DMDIR|0555,
509a747e4fSDavid du Colombier "exec", DMDIR|0555,
519a747e4fSDavid du Colombier "clone", 0666,
529a747e4fSDavid du Colombier nil, DMDIR|0555,
539a747e4fSDavid du Colombier "ctl", 0666,
549a747e4fSDavid du Colombier "data", 0666,
559a747e4fSDavid du Colombier "local", 0444,
569a747e4fSDavid du Colombier "remote", 0444,
579a747e4fSDavid du Colombier "status", 0444,
589a747e4fSDavid du Colombier };
599a747e4fSDavid du Colombier
609a747e4fSDavid du Colombier void
setexecname(char * s)619a747e4fSDavid du Colombier setexecname(char *s)
629a747e4fSDavid du Colombier {
639a747e4fSDavid du Colombier tab[Qexec].name = s;
649a747e4fSDavid du Colombier }
659a747e4fSDavid du Colombier
669a747e4fSDavid du Colombier ulong time0;
679a747e4fSDavid du Colombier
689a747e4fSDavid du Colombier static void
fillstat(Dir * d,ulong path)699a747e4fSDavid du Colombier fillstat(Dir *d, ulong path)
709a747e4fSDavid du Colombier {
719a747e4fSDavid du Colombier Tab *t;
729a747e4fSDavid du Colombier int type;
739a747e4fSDavid du Colombier char buf[32];
749a747e4fSDavid du Colombier
759a747e4fSDavid du Colombier memset(d, 0, sizeof(*d));
769a747e4fSDavid du Colombier d->uid = estrdup("exec");
779a747e4fSDavid du Colombier d->gid = estrdup("exec");
789a747e4fSDavid du Colombier d->qid.path = path;
799a747e4fSDavid du Colombier d->atime = d->mtime = time0;
809a747e4fSDavid du Colombier d->length = 0;
819a747e4fSDavid du Colombier
829a747e4fSDavid du Colombier type = TYPE(path);
839a747e4fSDavid du Colombier t = &tab[type];
849a747e4fSDavid du Colombier if(t->name)
859a747e4fSDavid du Colombier d->name = estrdup(t->name);
869a747e4fSDavid du Colombier else{
879a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%ud", NUM(path));
889a747e4fSDavid du Colombier d->name = estrdup(buf);
899a747e4fSDavid du Colombier }
909a747e4fSDavid du Colombier d->qid.type = t->mode>>24;
919a747e4fSDavid du Colombier d->mode = t->mode;
929a747e4fSDavid du Colombier }
939a747e4fSDavid du Colombier
949a747e4fSDavid du Colombier static void
fsstat(Req * r)959a747e4fSDavid du Colombier fsstat(Req *r)
969a747e4fSDavid du Colombier {
979a747e4fSDavid du Colombier fillstat(&r->d, r->fid->qid.path);
989a747e4fSDavid du Colombier respond(r, nil);
999a747e4fSDavid du Colombier }
1009a747e4fSDavid du Colombier
1019a747e4fSDavid du Colombier static int
rootgen(int i,Dir * d,void *)1029a747e4fSDavid du Colombier rootgen(int i, Dir *d, void*)
1039a747e4fSDavid du Colombier {
1049a747e4fSDavid du Colombier if(i < 1){
1059a747e4fSDavid du Colombier fillstat(d, PATH(Qexec, 0));
1069a747e4fSDavid du Colombier return 0;
1079a747e4fSDavid du Colombier }
1089a747e4fSDavid du Colombier return -1;
1099a747e4fSDavid du Colombier }
1109a747e4fSDavid du Colombier
1119a747e4fSDavid du Colombier static int
execgen(int i,Dir * d,void *)1129a747e4fSDavid du Colombier execgen(int i, Dir *d, void*)
1139a747e4fSDavid du Colombier {
1149a747e4fSDavid du Colombier if(i < 1){
1159a747e4fSDavid du Colombier fillstat(d, PATH(Qclone, 0));
1169a747e4fSDavid du Colombier return 0;
1179a747e4fSDavid du Colombier }
1189a747e4fSDavid du Colombier i -= 1;
1199a747e4fSDavid du Colombier
1209a747e4fSDavid du Colombier if(i < nclient){
1219a747e4fSDavid du Colombier fillstat(d, PATH(Qn, i));
1229a747e4fSDavid du Colombier return 0;
1239a747e4fSDavid du Colombier }
1249a747e4fSDavid du Colombier return -1;
1259a747e4fSDavid du Colombier }
1269a747e4fSDavid du Colombier
1279a747e4fSDavid du Colombier static int
conngen(int i,Dir * d,void * aux)1289a747e4fSDavid du Colombier conngen(int i, Dir *d, void *aux)
1299a747e4fSDavid du Colombier {
1309a747e4fSDavid du Colombier Client *c;
1319a747e4fSDavid du Colombier
1329a747e4fSDavid du Colombier c = aux;
1339a747e4fSDavid du Colombier i += Qn+1;
1349a747e4fSDavid du Colombier if(i <= Qstatus){
1359a747e4fSDavid du Colombier fillstat(d, PATH(i, c->num));
1369a747e4fSDavid du Colombier return 0;
1379a747e4fSDavid du Colombier }
1389a747e4fSDavid du Colombier return -1;
1399a747e4fSDavid du Colombier }
1409a747e4fSDavid du Colombier
1419a747e4fSDavid du Colombier char *statusstr[] =
1429a747e4fSDavid du Colombier {
1439a747e4fSDavid du Colombier "Closed",
1449a747e4fSDavid du Colombier "Exec",
1459a747e4fSDavid du Colombier "Established",
1469a747e4fSDavid du Colombier "Hangup",
1479a747e4fSDavid du Colombier };
1489a747e4fSDavid du Colombier
1499a747e4fSDavid du Colombier static void
fsread(Req * r)1509a747e4fSDavid du Colombier fsread(Req *r)
1519a747e4fSDavid du Colombier {
1529a747e4fSDavid du Colombier char e[ERRMAX], *s;
1539a747e4fSDavid du Colombier ulong path;
1549a747e4fSDavid du Colombier
1559a747e4fSDavid du Colombier path = r->fid->qid.path;
1569a747e4fSDavid du Colombier switch(TYPE(path)){
1579a747e4fSDavid du Colombier default:
1589a747e4fSDavid du Colombier snprint(e, sizeof e, "bug in execnet path=%lux", path);
1599a747e4fSDavid du Colombier respond(r, e);
1609a747e4fSDavid du Colombier break;
1619a747e4fSDavid du Colombier
1629a747e4fSDavid du Colombier case Qroot:
1639a747e4fSDavid du Colombier dirread9p(r, rootgen, nil);
1649a747e4fSDavid du Colombier respond(r, nil);
1659a747e4fSDavid du Colombier break;
1669a747e4fSDavid du Colombier
1679a747e4fSDavid du Colombier case Qexec:
1689a747e4fSDavid du Colombier dirread9p(r, execgen, nil);
1699a747e4fSDavid du Colombier respond(r, nil);
1709a747e4fSDavid du Colombier break;
1719a747e4fSDavid du Colombier
1729a747e4fSDavid du Colombier case Qn:
1739a747e4fSDavid du Colombier dirread9p(r, conngen, client[NUM(path)]);
1749a747e4fSDavid du Colombier respond(r, nil);
1759a747e4fSDavid du Colombier break;
1769a747e4fSDavid du Colombier
1779a747e4fSDavid du Colombier case Qctl:
1789a747e4fSDavid du Colombier snprint(e, sizeof e, "%ud", NUM(path));
1799a747e4fSDavid du Colombier readstr(r, e);
1809a747e4fSDavid du Colombier respond(r, nil);
1819a747e4fSDavid du Colombier break;
1829a747e4fSDavid du Colombier
1839a747e4fSDavid du Colombier case Qdata:
1849a747e4fSDavid du Colombier dataread(r, client[NUM(path)]);
1859a747e4fSDavid du Colombier break;
1869a747e4fSDavid du Colombier
1879a747e4fSDavid du Colombier case Qlocal:
1889a747e4fSDavid du Colombier snprint(e, sizeof e, "%d", client[NUM(path)]->pid);
1899a747e4fSDavid du Colombier readstr(r, e);
1909a747e4fSDavid du Colombier respond(r, nil);
1919a747e4fSDavid du Colombier break;
1929a747e4fSDavid du Colombier
1939a747e4fSDavid du Colombier case Qremote:
1949a747e4fSDavid du Colombier s = client[NUM(path)]->cmd;
1959a747e4fSDavid du Colombier if(strlen(s) >= 5) /* "exec " */
1969a747e4fSDavid du Colombier readstr(r, s+5);
1979a747e4fSDavid du Colombier else
1989a747e4fSDavid du Colombier readstr(r, s);
1999a747e4fSDavid du Colombier respond(r, nil);
2009a747e4fSDavid du Colombier break;
2019a747e4fSDavid du Colombier
2029a747e4fSDavid du Colombier case Qstatus:
2039a747e4fSDavid du Colombier readstr(r, statusstr[client[NUM(path)]->status]);
2049a747e4fSDavid du Colombier respond(r, nil);
2059a747e4fSDavid du Colombier break;
2069a747e4fSDavid du Colombier }
2079a747e4fSDavid du Colombier }
2089a747e4fSDavid du Colombier
2099a747e4fSDavid du Colombier static void
fswrite(Req * r)2109a747e4fSDavid du Colombier fswrite(Req *r)
2119a747e4fSDavid du Colombier {
2129a747e4fSDavid du Colombier char e[ERRMAX];
2139a747e4fSDavid du Colombier ulong path;
2149a747e4fSDavid du Colombier
2159a747e4fSDavid du Colombier path = r->fid->qid.path;
2169a747e4fSDavid du Colombier switch(TYPE(path)){
2179a747e4fSDavid du Colombier default:
2189a747e4fSDavid du Colombier snprint(e, sizeof e, "bug in execnet path=%lux", path);
2199a747e4fSDavid du Colombier respond(r, e);
2209a747e4fSDavid du Colombier break;
2219a747e4fSDavid du Colombier
2229a747e4fSDavid du Colombier case Qctl:
2239a747e4fSDavid du Colombier ctlwrite(r, client[NUM(path)]);
2249a747e4fSDavid du Colombier break;
2259a747e4fSDavid du Colombier
2269a747e4fSDavid du Colombier case Qdata:
2279a747e4fSDavid du Colombier datawrite(r, client[NUM(path)]);
2289a747e4fSDavid du Colombier break;
2299a747e4fSDavid du Colombier }
2309a747e4fSDavid du Colombier }
2319a747e4fSDavid du Colombier
2329a747e4fSDavid du Colombier
2339a747e4fSDavid du Colombier static void
fsflush(Req * r)2349a747e4fSDavid du Colombier fsflush(Req *r)
2359a747e4fSDavid du Colombier {
2369a747e4fSDavid du Colombier ulong path;
2379a747e4fSDavid du Colombier Req *or;
2389a747e4fSDavid du Colombier
2399a747e4fSDavid du Colombier for(or=r; or->ifcall.type==Tflush; or=or->oldreq)
2409a747e4fSDavid du Colombier ;
2419a747e4fSDavid du Colombier
2429a747e4fSDavid du Colombier if(or->ifcall.type != Tread && or->ifcall.type != Twrite)
2439a747e4fSDavid du Colombier abort();
2449a747e4fSDavid du Colombier
2459a747e4fSDavid du Colombier path = or->fid->qid.path;
2469a747e4fSDavid du Colombier if(TYPE(path) != Qdata)
2479a747e4fSDavid du Colombier abort();
2489a747e4fSDavid du Colombier
2499a747e4fSDavid du Colombier clientflush(or, client[NUM(path)]);
250*fb7f0c93SDavid du Colombier respond(r, nil);
2519a747e4fSDavid du Colombier }
2529a747e4fSDavid du Colombier
2539a747e4fSDavid du Colombier static void
fsattach(Req * r)2549a747e4fSDavid du Colombier fsattach(Req *r)
2559a747e4fSDavid du Colombier {
2569a747e4fSDavid du Colombier if(r->ifcall.aname && r->ifcall.aname[0]){
2579a747e4fSDavid du Colombier respond(r, "invalid attach specifier");
2589a747e4fSDavid du Colombier return;
2599a747e4fSDavid du Colombier }
2609a747e4fSDavid du Colombier r->fid->qid.path = PATH(Qroot, 0);
2619a747e4fSDavid du Colombier r->fid->qid.type = QTDIR;
2629a747e4fSDavid du Colombier r->fid->qid.vers = 0;
2639a747e4fSDavid du Colombier r->ofcall.qid = r->fid->qid;
2649a747e4fSDavid du Colombier respond(r, nil);
2659a747e4fSDavid du Colombier }
2669a747e4fSDavid du Colombier
2679a747e4fSDavid du Colombier static char*
fswalk1(Fid * fid,char * name,Qid * qid)2689a747e4fSDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid)
2699a747e4fSDavid du Colombier {
2709a747e4fSDavid du Colombier char buf[32];
2719a747e4fSDavid du Colombier int i, n;
2729a747e4fSDavid du Colombier ulong path;
2739a747e4fSDavid du Colombier
2749a747e4fSDavid du Colombier if(!(fid->qid.type&QTDIR))
2759a747e4fSDavid du Colombier return "walk in non-directory";
2769a747e4fSDavid du Colombier
2779a747e4fSDavid du Colombier path = fid->qid.path;
2789a747e4fSDavid du Colombier if(strcmp(name, "..") == 0){
2799a747e4fSDavid du Colombier switch(TYPE(path)){
2809a747e4fSDavid du Colombier case Qn:
2819a747e4fSDavid du Colombier qid->path = PATH(Qexec, 0);
2829a747e4fSDavid du Colombier qid->type = QTDIR;
2839a747e4fSDavid du Colombier return nil;
2849a747e4fSDavid du Colombier case Qroot:
2859a747e4fSDavid du Colombier case Qexec:
2869a747e4fSDavid du Colombier qid->path = PATH(Qroot, 0);
2879a747e4fSDavid du Colombier qid->type = QTDIR;
2889a747e4fSDavid du Colombier return nil;
2899a747e4fSDavid du Colombier default:
2909a747e4fSDavid du Colombier return "bug in fswalk1";
2919a747e4fSDavid du Colombier }
2929a747e4fSDavid du Colombier }
2939a747e4fSDavid du Colombier
2949a747e4fSDavid du Colombier i = TYPE(path)+1;
2959a747e4fSDavid du Colombier for(; i<nelem(tab); i++){
2969a747e4fSDavid du Colombier if(i==Qn){
2979a747e4fSDavid du Colombier n = atoi(name);
2989a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%d", n);
2999a747e4fSDavid du Colombier if(n < nclient && strcmp(buf, name) == 0){
3009a747e4fSDavid du Colombier qid->path = PATH(Qn, n);
3019a747e4fSDavid du Colombier qid->type = QTDIR;
3029a747e4fSDavid du Colombier return nil;
3039a747e4fSDavid du Colombier }
3049a747e4fSDavid du Colombier break;
3059a747e4fSDavid du Colombier }
3069a747e4fSDavid du Colombier if(strcmp(tab[i].name, name) == 0){
3079a747e4fSDavid du Colombier qid->path = PATH(i, NUM(path));
3089a747e4fSDavid du Colombier qid->type = tab[i].mode>>24;
3099a747e4fSDavid du Colombier return nil;
3109a747e4fSDavid du Colombier }
3119a747e4fSDavid du Colombier if(tab[i].mode&DMDIR)
3129a747e4fSDavid du Colombier break;
3139a747e4fSDavid du Colombier }
3149a747e4fSDavid du Colombier return "directory entry not found";
3159a747e4fSDavid du Colombier }
3169a747e4fSDavid du Colombier
3179a747e4fSDavid du Colombier static void
fsopen(Req * r)3189a747e4fSDavid du Colombier fsopen(Req *r)
3199a747e4fSDavid du Colombier {
3209a747e4fSDavid du Colombier static int need[4] = { 4, 2, 6, 1 };
3219a747e4fSDavid du Colombier ulong path;
3229a747e4fSDavid du Colombier int n;
3239a747e4fSDavid du Colombier Tab *t;
3249a747e4fSDavid du Colombier
3259a747e4fSDavid du Colombier /*
3269a747e4fSDavid du Colombier * lib9p already handles the blatantly obvious.
3279a747e4fSDavid du Colombier * we just have to enforce the permissions we have set.
3289a747e4fSDavid du Colombier */
3299a747e4fSDavid du Colombier path = r->fid->qid.path;
3309a747e4fSDavid du Colombier t = &tab[TYPE(path)];
3319a747e4fSDavid du Colombier n = need[r->ifcall.mode&3];
3329a747e4fSDavid du Colombier if((n&t->mode) != n){
3339a747e4fSDavid du Colombier respond(r, "permission denied");
3349a747e4fSDavid du Colombier return;
3359a747e4fSDavid du Colombier }
3369a747e4fSDavid du Colombier
3379a747e4fSDavid du Colombier switch(TYPE(path)){
3389a747e4fSDavid du Colombier case Qclone:
3399a747e4fSDavid du Colombier n = newclient();
3409a747e4fSDavid du Colombier path = PATH(Qctl, n);
3419a747e4fSDavid du Colombier r->fid->qid.path = path;
3429a747e4fSDavid du Colombier r->ofcall.qid.path = path;
3439a747e4fSDavid du Colombier if(fsdebug)
3449a747e4fSDavid du Colombier fprint(2, "open clone => path=%lux\n", path);
3459a747e4fSDavid du Colombier t = &tab[Qctl];
3469a747e4fSDavid du Colombier /* fall through */
3479a747e4fSDavid du Colombier default:
3489a747e4fSDavid du Colombier if(t-tab >= Qn)
3499a747e4fSDavid du Colombier client[NUM(path)]->ref++;
3509a747e4fSDavid du Colombier respond(r, nil);
3519a747e4fSDavid du Colombier break;
3529a747e4fSDavid du Colombier }
3539a747e4fSDavid du Colombier }
3549a747e4fSDavid du Colombier
3559a747e4fSDavid du Colombier Channel *cclunk;
3569a747e4fSDavid du Colombier Channel *cclunkwait;
3579a747e4fSDavid du Colombier Channel *creq;
3589a747e4fSDavid du Colombier Channel *creqwait;
3599a747e4fSDavid du Colombier
3609a747e4fSDavid du Colombier static void
fsthread(void *)3619a747e4fSDavid du Colombier fsthread(void*)
3629a747e4fSDavid du Colombier {
3639a747e4fSDavid du Colombier ulong path;
3649a747e4fSDavid du Colombier Alt a[3];
3659a747e4fSDavid du Colombier Fid *fid;
3669a747e4fSDavid du Colombier Req *r;
3679a747e4fSDavid du Colombier
3689a747e4fSDavid du Colombier threadsetname("fsthread");
3699a747e4fSDavid du Colombier
3709a747e4fSDavid du Colombier a[0].op = CHANRCV;
3719a747e4fSDavid du Colombier a[0].c = cclunk;
3729a747e4fSDavid du Colombier a[0].v = &fid;
3739a747e4fSDavid du Colombier a[1].op = CHANRCV;
3749a747e4fSDavid du Colombier a[1].c = creq;
3759a747e4fSDavid du Colombier a[1].v = &r;
3769a747e4fSDavid du Colombier a[2].op = CHANEND;
3779a747e4fSDavid du Colombier
3789a747e4fSDavid du Colombier for(;;){
3799a747e4fSDavid du Colombier switch(alt(a)){
3809a747e4fSDavid du Colombier case 0:
3819a747e4fSDavid du Colombier path = fid->qid.path;
3829a747e4fSDavid du Colombier if(fid->omode != -1 && TYPE(path) >= Qn)
3839a747e4fSDavid du Colombier closeclient(client[NUM(path)]);
3849a747e4fSDavid du Colombier sendp(cclunkwait, nil);
3859a747e4fSDavid du Colombier break;
3869a747e4fSDavid du Colombier case 1:
3879a747e4fSDavid du Colombier switch(r->ifcall.type){
3889a747e4fSDavid du Colombier case Tattach:
3899a747e4fSDavid du Colombier fsattach(r);
3909a747e4fSDavid du Colombier break;
3919a747e4fSDavid du Colombier case Topen:
3929a747e4fSDavid du Colombier fsopen(r);
3939a747e4fSDavid du Colombier break;
3949a747e4fSDavid du Colombier case Tread:
3959a747e4fSDavid du Colombier fsread(r);
3969a747e4fSDavid du Colombier break;
3979a747e4fSDavid du Colombier case Twrite:
3989a747e4fSDavid du Colombier fswrite(r);
3999a747e4fSDavid du Colombier break;
4009a747e4fSDavid du Colombier case Tstat:
4019a747e4fSDavid du Colombier fsstat(r);
4029a747e4fSDavid du Colombier break;
4039a747e4fSDavid du Colombier case Tflush:
4049a747e4fSDavid du Colombier fsflush(r);
4059a747e4fSDavid du Colombier break;
4069a747e4fSDavid du Colombier default:
4079a747e4fSDavid du Colombier respond(r, "bug in fsthread");
4089a747e4fSDavid du Colombier break;
4099a747e4fSDavid du Colombier }
4109a747e4fSDavid du Colombier sendp(creqwait, 0);
4119a747e4fSDavid du Colombier break;
4129a747e4fSDavid du Colombier }
4139a747e4fSDavid du Colombier }
4149a747e4fSDavid du Colombier }
4159a747e4fSDavid du Colombier
4169a747e4fSDavid du Colombier static void
fsdestroyfid(Fid * fid)4179a747e4fSDavid du Colombier fsdestroyfid(Fid *fid)
4189a747e4fSDavid du Colombier {
4199a747e4fSDavid du Colombier sendp(cclunk, fid);
4209a747e4fSDavid du Colombier recvp(cclunkwait);
4219a747e4fSDavid du Colombier }
4229a747e4fSDavid du Colombier
4239a747e4fSDavid du Colombier static void
fssend(Req * r)4249a747e4fSDavid du Colombier fssend(Req *r)
4259a747e4fSDavid du Colombier {
4269a747e4fSDavid du Colombier sendp(creq, r);
4279a747e4fSDavid du Colombier recvp(creqwait); /* avoids need to deal with spurious flushes */
4289a747e4fSDavid du Colombier }
4299a747e4fSDavid du Colombier
4309a747e4fSDavid du Colombier void
initfs(void)4319a747e4fSDavid du Colombier initfs(void)
4329a747e4fSDavid du Colombier {
4339a747e4fSDavid du Colombier time0 = time(0);
4349a747e4fSDavid du Colombier creq = chancreate(sizeof(void*), 0);
4359a747e4fSDavid du Colombier creqwait = chancreate(sizeof(void*), 0);
4369a747e4fSDavid du Colombier cclunk = chancreate(sizeof(void*), 0);
4379a747e4fSDavid du Colombier cclunkwait = chancreate(sizeof(void*), 0);
4389a747e4fSDavid du Colombier procrfork(fsthread, nil, STACK, RFNAMEG);
4399a747e4fSDavid du Colombier }
4409a747e4fSDavid du Colombier
4419a747e4fSDavid du Colombier Srv fs =
4429a747e4fSDavid du Colombier {
4439a747e4fSDavid du Colombier .attach= fssend,
4449a747e4fSDavid du Colombier .destroyfid= fsdestroyfid,
4459a747e4fSDavid du Colombier .walk1= fswalk1,
4469a747e4fSDavid du Colombier .open= fssend,
4479a747e4fSDavid du Colombier .read= fssend,
4489a747e4fSDavid du Colombier .write= fssend,
4499a747e4fSDavid du Colombier .stat= fssend,
4509a747e4fSDavid du Colombier .flush= fssend,
4519a747e4fSDavid du Colombier };
452