10 #define Zmsg ((Msg*)~0)
13 static void readthread(void*);
14 static void writethread(void*);
15 static void kickwriter(Client*);
23 for(i=0; i<nclient; i++)
24 if(client[i]->ref==0 && !client[i]->moribund)
27 c = emalloc(sizeof(Client));
28 c->writerkick = chancreate(sizeof(void*), 1);
29 c->execpid = chancreate(sizeof(ulong), 0);
32 c->readerproc = ioproc();
33 c->writerproc = ioproc();
36 client = erealloc(client, (nclient+16)*sizeof(client[0]));
37 client[nclient++] = c;
49 iointerrupt(c->readerproc);
50 iointerrupt(c->writerproc);
51 if(--c->activethread == 0){
59 for(m=c->mq; m && m != Zmsg; m=next){
65 for(r=c->rq; r; r=rnext){
72 for(r=c->wq; r; r=rnext){
87 closeclient(Client *c)
91 postnote(PNPROC, c->pid, "kill");
94 c->fd[0] = c->fd[1] = -1;
97 iointerrupt(c->readerproc);
98 iointerrupt(c->writerproc);
105 queuerdreq(Client *c, Req *r)
111 c->erq = (Req**)&r->aux;
115 queuewrreq(Client *c, Req *r)
121 c->ewq = (Req**)&r->aux;
125 queuemsg(Client *c, Msg *m)
132 c->emq = (Msg**)&m->link;
144 while(c->rq && c->mq){
151 respond(r, "execnet: no more data");
155 if(n >= m->ep - m->rp){
161 memmove(r->ofcall.data, m->rp, n);
172 findrdreq(Client *c, Req *r)
176 for(l=&c->rq; *l; l=(Req**)&(*l)->aux){
181 respond(r, "interrupted");
188 findwrreq(Client *c, Req *r)
192 for(l=&c->wq; *l; l=(Req**)&(*l)->aux){
197 respond(r, "interrupted");
204 dataread(Req *r, Client *c)
220 threadsetname("read%d", c->num);
224 while((n = ioread(io, c->fd[0], buf, 8192)) >= 0){
225 m = emalloc(sizeof(Msg)+n);
226 m->rp = (uchar*)&m[1];
229 memmove(m->rp, buf, n);
239 kickwriter(Client *c)
241 nbsendp(c->writerkick, nil);
245 clientflush(Req *or, Client *c)
247 if(or->ifcall.type == Tread)
250 if(c->execreq == or){
252 iointerrupt(c->writerproc);
253 ioflush(c->writerproc);
258 iointerrupt(c->writerproc);
265 datawrite(Req *r, Client *c)
282 threadsetname("write%d", c->num);
290 recvp(c->writerkick);
297 n = iowrite(io, c->fd[1], r->ifcall.data, r->ifcall.count);
300 fprint(2, "io->write returns %d\n", n);
305 rerrstr(e, sizeof e);
321 threadsetname("execproc%d", c->num);
323 rerrstr(c->err, sizeof c->err);
324 sendul(c->execpid, -1);
332 for(i=3; i<100; i++) /* should do better */
334 strcpy(c->err, "exec failed");
335 procexecl(c->execpid, "/bin/rc", "rc", "-c", c->cmd, nil);
345 threadsetname("exec%d", c->num);
346 c->execpid = chancreate(sizeof(ulong), 0);
347 proccreate(execproc, c, STACK);
348 p = recvul(c->execpid);
349 chanfree(c->execpid);
356 threadcreate(readthread, c, STACK);
357 threadcreate(writethread, c, STACK);
359 respond(c->execreq, nil);
362 respond(c->execreq, c->err);
367 ctlwrite(Req *r, Client *c)
372 s = emalloc(r->ifcall.count+1);
373 memmove(s, r->ifcall.data, r->ifcall.count);
374 s[r->ifcall.count] = '\0';
392 r->ofcall.count = r->ifcall.count;
393 if(strcmp(f[0], "hangup") == 0){
395 respond(r, "connection already hung up");
398 postnote(PNPROC, c->pid, "kill");
403 if(strcmp(f[0], "connect") == 0){
405 respond(r, "already have connection");
409 respond(r, "need argument to connect");
413 if(p = strrchr(f[1], '!'))
415 c->cmd = emalloc(4+1+strlen(f[1])+1);
416 strcpy(c->cmd, "exec ");
417 strcat(c->cmd, f[1]);
419 threadcreate(execthread, c, STACK);
423 respond(r, "bad or inappropriate control message");