static void ipclose(Chan* c) { Fs *f; f = ipfs[c->dev]; switch(TYPE(c->qid)) { default: break; case Qlog: if(c->flag & COPEN) netlogclose(f); break; case Qdata: case Qctl: case Qerr: if(c->flag & COPEN) closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]); break; case Qsnoop: if(c->flag & COPEN) decref(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers); break; } free(((IPaux*)c->aux)->owner); free(c->aux); }
void closeconv(Conv *cv) { Conv *nc; Ipmulti *mp; qlock(cv); if(--cv->inuse > 0) { qunlock(cv); return; } /* close all incoming calls since no listen will ever happen */ for(nc = cv->incall; nc; nc = cv->incall){ cv->incall = nc->next; closeconv(nc); } cv->incall = nil; kstrdup(&cv->owner, network); cv->perm = 0660; while((mp = cv->multi) != nil) ipifcremmulti(cv, mp->ma, mp->ia); cv->r = nil; cv->rgen = 0; cv->p->close(cv); cv->state = Idle; qunlock(cv); }
static void cmdproc(void *a) { Conv *c; int n = 0; char status[ERRMAX]; void *t = NULL; c = a; qlock(&c->l); if(Debug) print("f[0]=%q f[1]=%q\n", c->cmd->f[0], c->cmd->f[1]); if(waserror()){ if(Debug) print("failed: %q\n", up->errstr); kstrdup(&c->error, up->errstr); c->state = "Done"; qunlock(&c->l); // Wakeup(&c->startr); pexit("cmdproc", 0); } // t = oscmd(c->cmd->f+1, c->nice, c->dir, c->fd); // if(t == nil) // oserror(); c->child = t; /* to allow oscmdkill */ poperror(); qunlock(&c->l); // Wakeup(&c->startr); if(Debug) print("started\n"); // while(waserror()) // oscmdkill(t); // osenter(); mwait(&c->p->ac->icc->fn); // n = oscmdwait(t, status, sizeof(status)); // osleave(); if(n < 0){ // oserrstr(up->genbuf, sizeof(up->genbuf)); n = snprint(status, sizeof(status), "0 0 0 0 %q", up->genbuf); } qlock(&c->l); c->child = nil; // oscmdfree(t); if(Debug){ status[n]=0; print("done %d %d %d: %q\n", c->fd[0], c->fd[1], c->fd[2], status); } if(c->inuse > 0){ c->state = "Done"; if(c->waitq != nil) qproduce(c->waitq, status, n); }else closeconv(c); qunlock(&c->l); pexit("", 0); }
static void ipclose(Chan *c) { Fs *f; f = ipfs[c->dev]; switch(TYPE(c->qid)) { case Qdata: case Qctl: if(c->flag & COPEN) closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]); break; } }
static void cmdclose(Chan *c) { Conv *cc; int r; if((c->flag & COPEN) == 0) return; switch(TYPE(c->qid)) { case Qctl: case Qalloc: case Qexec: case Qdata: case Qstderr: case Qwait: cc = cmd.conv[CONV(c->qid)]; qlock(&cc->l); if(TYPE(c->qid) == Qdata){ if(c->mode == OWRITE || c->mode == ORDWR) cmdfdclose(cc, 0); if(c->mode == OREAD || c->mode == ORDWR) cmdfdclose(cc, 1); }else if(TYPE(c->qid) == Qstderr) cmdfdclose(cc, 2); r = --cc->inuse; if(cc->child != nil){ if(!cc->killed) if(r == 0 || (cc->killonclose && TYPE(c->qid) == Qctl)){ // oscmdkill(cc->child); cc->killed = 1; } }else if(r == 0) closeconv(cc); qunlock(&cc->l); break; } }
static Chan* ipopen(Chan* c, int omode) { Conv *cv, *nc; Proto *p; int perm; Fs *f; perm = m2p[omode&3]; f = ipfs[c->dev]; switch(TYPE(c->qid)) { default: break; case Qndb: if(omode & (OWRITE|OTRUNC) && !iseve()) error(Eperm); if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC)) f->ndb[0] = 0; break; case Qlog: netlogopen(f); break; case Qiproute: case Qarp: if(omode != OREAD && !iseve()) error(Eperm); break; case Qtopdir: case Qprotodir: case Qconvdir: case Qstatus: case Qremote: case Qlocal: case Qstats: case Qbootp: case Qipselftab: if(omode != OREAD) error(Eperm); break; case Qsnoop: if(omode != OREAD) error(Eperm); p = f->p[PROTO(c->qid)]; cv = p->conv[CONV(c->qid)]; if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve()) error(Eperm); incref(&cv->snoopers); break; case Qclone: p = f->p[PROTO(c->qid)]; qlock(p); if(waserror()){ qunlock(p); nexterror(); } cv = Fsprotoclone(p, ATTACHER(c)); qunlock(p); poperror(); if(cv == nil) { error(Enodev); break; } mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE); break; case Qdata: case Qctl: case Qerr: p = f->p[PROTO(c->qid)]; qlock(p); cv = p->conv[CONV(c->qid)]; qlock(cv); if(waserror()) { qunlock(cv); qunlock(p); nexterror(); } if((perm & (cv->perm>>6)) != perm) { if(strcmp(ATTACHER(c), cv->owner) != 0) error(Eperm); if((perm & cv->perm) != perm) error(Eperm); } cv->inuse++; if(cv->inuse == 1){ kstrdup(&cv->owner, ATTACHER(c)); cv->perm = 0660; } qunlock(cv); qunlock(p); poperror(); break; case Qlisten: cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)]; if((perm & (cv->perm>>6)) != perm) { if(strcmp(ATTACHER(c), cv->owner) != 0) error(Eperm); if((perm & cv->perm) != perm) error(Eperm); } if(cv->state != Announced) error("not announced"); if(waserror()){ closeconv(cv); nexterror(); } qlock(cv); cv->inuse++; qunlock(cv); nc = nil; while(nc == nil) { /* give up if we got a hangup */ if(qisclosed(cv->rq)) error("listen hungup"); qlock(&cv->listenq); if(waserror()) { qunlock(&cv->listenq); nexterror(); } /* wait for a connect */ sleep(&cv->listenr, incoming, cv); qlock(cv); nc = cv->incall; if(nc != nil){ cv->incall = nc->next; mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE); kstrdup(&cv->owner, ATTACHER(c)); } qunlock(cv); qunlock(&cv->listenq); poperror(); } closeconv(cv); poperror(); break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; }