2 * ``Exec'' network device. Mounted on net, provides /net/exec.
4 * exec protocol directory
5 * n connection directory
6 * ctl control messages (like connect)
9 * local local address (pid of command)
10 * remote remote address (command)
36 #define PATH(type, n) ((type)|((n)<<8))
37 #define TYPE(path) ((int)(path) & 0xFF)
38 #define NUM(path) ((uint)(path)>>8)
40 typedef struct Tab Tab;
69 fillstat(Dir *d, ulong path)
75 memset(d, 0, sizeof(*d));
76 d->uid = estrdup("exec");
77 d->gid = estrdup("exec");
79 d->atime = d->mtime = time0;
85 d->name = estrdup(t->name);
87 snprint(buf, sizeof buf, "%ud", NUM(path));
88 d->name = estrdup(buf);
90 d->qid.type = t->mode>>24;
97 fillstat(&r->d, r->fid->qid.path);
102 rootgen(int i, Dir *d, void*)
105 fillstat(d, PATH(Qexec, 0));
112 execgen(int i, Dir *d, void*)
115 fillstat(d, PATH(Qclone, 0));
121 fillstat(d, PATH(Qn, i));
128 conngen(int i, Dir *d, void *aux)
135 fillstat(d, PATH(i, c->num));
155 path = r->fid->qid.path;
158 snprint(e, sizeof e, "bug in execnet path=%lux", path);
163 dirread9p(r, rootgen, nil);
168 dirread9p(r, execgen, nil);
173 dirread9p(r, conngen, client[NUM(path)]);
178 snprint(e, sizeof e, "%ud", NUM(path));
184 dataread(r, client[NUM(path)]);
188 snprint(e, sizeof e, "%d", client[NUM(path)]->pid);
194 s = client[NUM(path)]->cmd;
195 if(strlen(s) >= 5) /* "exec " */
203 readstr(r, statusstr[client[NUM(path)]->status]);
215 path = r->fid->qid.path;
218 snprint(e, sizeof e, "bug in execnet path=%lux", path);
223 ctlwrite(r, client[NUM(path)]);
227 datawrite(r, client[NUM(path)]);
239 for(or=r; or->ifcall.type==Tflush; or=or->oldreq)
242 if(or->ifcall.type != Tread && or->ifcall.type != Twrite)
245 path = or->fid->qid.path;
246 if(TYPE(path) != Qdata)
249 clientflush(or, client[NUM(path)]);
256 if(r->ifcall.aname && r->ifcall.aname[0]){
257 respond(r, "invalid attach specifier");
260 r->fid->qid.path = PATH(Qroot, 0);
261 r->fid->qid.type = QTDIR;
262 r->fid->qid.vers = 0;
263 r->ofcall.qid = r->fid->qid;
268 fswalk1(Fid *fid, char *name, Qid *qid)
274 if(!(fid->qid.type&QTDIR))
275 return "walk in non-directory";
277 path = fid->qid.path;
278 if(strcmp(name, "..") == 0){
281 qid->path = PATH(Qexec, 0);
286 qid->path = PATH(Qroot, 0);
290 return "bug in fswalk1";
295 for(; i<nelem(tab); i++){
298 snprint(buf, sizeof buf, "%d", n);
299 if(n < nclient && strcmp(buf, name) == 0){
300 qid->path = PATH(Qn, n);
306 if(strcmp(tab[i].name, name) == 0){
307 qid->path = PATH(i, NUM(path));
308 qid->type = tab[i].mode>>24;
311 if(tab[i].mode&DMDIR)
314 return "directory entry not found";
320 static int need[4] = { 4, 2, 6, 1 };
326 * lib9p already handles the blatantly obvious.
327 * we just have to enforce the permissions we have set.
329 path = r->fid->qid.path;
330 t = &tab[TYPE(path)];
331 n = need[r->ifcall.mode&3];
332 if((n&t->mode) != n){
333 respond(r, "permission denied");
340 path = PATH(Qctl, n);
341 r->fid->qid.path = path;
342 r->ofcall.qid.path = path;
344 fprint(2, "open clone => path=%lux\n", path);
349 client[NUM(path)]->ref++;
368 threadsetname("fsthread");
381 path = fid->qid.path;
382 if(fid->omode != -1 && TYPE(path) >= Qn)
383 closeclient(client[NUM(path)]);
384 sendp(cclunkwait, nil);
387 switch(r->ifcall.type){
407 respond(r, "bug in fsthread");
417 fsdestroyfid(Fid *fid)
427 recvp(creqwait); /* avoids need to deal with spurious flushes */
434 creq = chancreate(sizeof(void*), 0);
435 creqwait = chancreate(sizeof(void*), 0);
436 cclunk = chancreate(sizeof(void*), 0);
437 cclunkwait = chancreate(sizeof(void*), 0);
438 procrfork(fsthread, nil, STACK, RFNAMEG);
444 .destroyfid= fsdestroyfid,