## diffname port/devmux.c 1991/1114 ## diff -e /dev/null /n/bootesdump/1991/1114/sys/src/9/port/devmux.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" #include "fcall.h" #include "devtab.h" typedef struct Mux Mux; typedef struct Con Con; typedef struct Dtq Dtq; enum { Qdir = 0, Qhead, Qclone, }; enum { Nmux = 20, }; struct Dtq { QLock rd; Rendez r; Lock listlk; Block *list; int ndelim; }; struct Con { int ref; char user[NAMELEN]; ulong perm; Dtq conq; }; struct Mux { Ref; char name[NAMELEN]; char user[NAMELEN]; ulong perm; int headopen; Dtq headq; Con connects[Nmux]; }; Mux *muxes; ulong muxreadq(Mux *m, Dtq*, char*, ulong); void muxwriteq(Dtq*, char*, long, int, int); #define NMUX(c) (((c->qid.path>>8)&0xffff)-1) #define NQID(m, c) (Qid){(m)<<8|(c)&0xff, 0} #define NCON(c) (c->qid.path&0xff) int muxgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) { Mux *m; int mux; Con *cm; char buf[10]; if(c->qid.path == CHDIR) { if(s >= conf.nmux) return -1; m = &muxes[s]; if(m->name[0] == '\0') return 0; devdir(c, (Qid){CHDIR|((s+1)<<8), 0}, m->name, 0, m->user, m->perm, dp); return 1; } if(s >= Nmux+2) return -1; mux = NMUX(c); m = &muxes[mux]; switch(s) { case Qhead: devdir(c, NQID(mux, Qhead), "head", m->headq.ndelim, m->user, m->perm, dp); break; case Qclone: devdir(c, NQID(mux, Qclone), "clone", 0, m->user, m->perm, dp); break; default: cm = &m->connects[s-Qclone]; if(cm->ref == 0) return 0; sprint(buf, "%d", s-Qclone); devdir(c, NQID(mux, Qclone+s), buf, cm->conq.ndelim, cm->user, cm->perm, dp); break; } return 1; } void muxinit(void) { } void muxreset(void) { muxes = ialloc(conf.nmux*sizeof(Mux), 0); } Chan * muxattach(char *spec) { Chan *c; c = devattach('m', spec); c->qid.path = CHDIR|Qdir; return c; } Chan * muxclone(Chan *c, Chan *nc) { int ncon; Mux *m; if(c->qid.path == CHDIR) return devclone(c, nc);; m = &muxes[NMUX(c)]; ncon = NCON(c); c = devclone(c, nc); switch(ncon) { case Qhead: incref(m); break; case Qclone: break; default: lock(m); m->connects[ncon].ref++; m->ref++; unlock(m); } return c; } int muxwalk(Chan *c, char *name) { if(strcmp(name, "..") == 0) { c->qid.path = CHDIR|Qdir; return 1; } return devwalk(c, name, 0, 0, muxgen); } void muxstat(Chan *c, char *db) { devstat(c, db, 0, 0, muxgen); } Chan * muxopen(Chan *c, int omode) { Mux *m; Con *cm, *e; if(c->qid.path & CHDIR) return devopen(c, omode, 0, 0, muxgen); m = &muxes[NMUX(c)]; switch(NCON(c)) { case Qhead: if(m->headopen) errors("server channel busy"); c = devopen(c, omode, 0, 0,muxgen); m->headopen = 1; incref(m); break; case Qclone: if(m->headopen == 0) errors("server shutdown"); c = devopen(c, omode, 0, 0, muxgen); lock(m); cm = m->connects; for(e = &cm[Nmux]; cm < e; cm++) if(cm->ref == 0) break; if(cm == e) { unlock(m); errors("all cannels busy"); } cm->ref++; m->ref++; unlock(m); strncpy(cm->user, u->p->user, NAMELEN); cm->perm = 0600; c->qid = NQID(NMUX(c), cm-m->connects); break; default: c = devopen(c, omode, 0, 0,muxgen); cm = &m->connects[NCON(c)]; cm->ref++; incref(m); break; } return c; } void muxcreate(Chan *c, char *name, int omode, ulong perm) { int n; Mux *m, *e; if(c->qid.path != CHDIR) error(Eperm); omode = openmode(omode); m = muxes; for(e = &m[conf.nmux]; m < e; m++) { if(m->ref == 0 && canlock(m)) { if(m->ref != 0) { unlock(m); continue; } m->ref++; break; } } if(m == e) errors("no multiplexors"); strncpy(m->name, name, NAMELEN); strncpy(m->user, u->p->user, NAMELEN); m->perm = perm&~CHDIR; unlock(m); n = m - muxes; c->qid = (Qid){CHDIR|(n+1)<<8, 0}; c->flag |= COPEN; c->mode = omode; } void muxremove(Chan *c) { Mux *m; if(c->qid.path == CHDIR || (c->qid.path&CHDIR) == 0) error(Eperm); m = &muxes[NMUX(c)]; if(strcmp(u->p->user, m->user) != 0) errors("not owner"); m->name[0] = '\0'; } void muxwstat(Chan *c, char *db) { Mux *m; Dir d; int nc; if(c->qid.path == CHDIR) error(Eperm); m = &muxes[NMUX(c)]; if(strcmp(u->p->user, m->user) != 0) errors("not owner"); convM2D(db, &d); d.mode &= 0777; if(c->qid.path&CHDIR) { strcpy(m->name, d.name); strcpy(m->user, d.uid); m->perm = d.mode; return; } nc = NCON(c); switch(nc) { case Qclone: error(Eperm); case Qhead: m->perm = d.mode; break; default: m->connects[nc].perm = d.mode; break; } } void muxclose(Chan *c) { Block *f1, *f2; Con *cm, *e; Mux *m; int nc; if(c->qid.path == CHDIR) return; m = &muxes[NMUX(c)]; nc = NCON(c); f1 = 0; f2 = 0; switch(nc) { case Qhead: m->headopen = 0; cm = m->connects; for(e = &cm[Nmux]; cm < e; cm++) if(cm->ref) wakeup(&cm->conq.r); lock(m); if(--m->ref == 0) { f1 = m->headq.list; m->headq.list = 0; } unlock(m); break; case Qclone: panic("muxclose"); default: lock(m); cm = &m->connects[nc]; if(--cm->ref == 0) { f1 = cm->conq.list; cm->conq.list = 0; } if(--m->ref == 0) { m->name[0] = '\0'; f2 = m->headq.list; m->headq.list = 0; } unlock(m); } if(f1) freeb(f1); if(f2) freeb(f2); } long muxread(Chan *c, void *va, long n, ulong offset) { Mux *m; Con *cm; int bread; if(c->qid.path & CHDIR) return devdirread(c, va, n, 0, 0, muxgen); m = &muxes[NMUX(c)]; switch(NCON(c)) { case Qhead: bread = muxreadq(m, &m->headq, va, n); break; case Qclone: error(Eperm); default: cm = &m->connects[NCON(c)]; bread = muxreadq(m, &cm->conq, va, n); break; } return bread; } Con * muxhdr(Mux *m, char *h) { Con *c; if(h[0] != Tmux) error(Ebadmsg); c = &m->connects[h[1]]; if(c < m->connects || c > &m->connects[Nmux]) error(Ebadmsg); if(c->ref == 0) return 0; return c; } long muxwrite(Chan *c, void *va, long n, ulong offset) { Mux *m; Con *cm; int muxid; Block *f, *bp; char *a, hdr[2]; if(c->qid.path & CHDIR) error(Eisdir); m = &muxes[NMUX(c)]; switch(NCON(c)) { case Qclone: error(Eperm); case Qhead: if(n < 2) error(Ebadmsg); a = (char*)va; memmove(hdr, a, sizeof(hdr)); cm = muxhdr(m, hdr); if(cm == 0) error(Ehungup); muxwriteq(&cm->conq, a+sizeof(hdr), n-sizeof(hdr), 0, 0); break; default: if(m->headopen == 0) error(Ehungup); muxid = NCON(c); muxwriteq(&m->headq, va, n, 1, muxid); break; } return n; } void muxwriteq(Dtq *q, char *va, long n, int addid, int muxid) { Block *head, *tail, *bp; ulong l; head = 0; SET(tail); if(waserror()) { if(head) freeb(head); nexterror(); } while(n) { bp = allocb(n); bp->type = M_DATA; l = bp->lim - bp->wptr; memmove(bp->wptr, va, l); /* Interruptable thru fault */ va += l; bp->wptr += l; n -= l; if(head == 0) head = bp; else tail->next = bp; tail = bp; } poperror(); tail->flags |= S_DELIM; lock(&q->listlk); for(tail = q->list; tail->next; tail = tail->next) ; tail->next = head; q->ndelim++; unlock(&q->listlk); } int nodata(Dtq *q) { int n; lock(&q->listlk); n = q->ndelim; unlock(&q->listlk); return n; } ulong muxreadq(Mux *m, Dtq *q, char *va, ulong n) { int l, nread, gotdelim; Block *bp; qlock(&q->rd); bp = 0; if(waserror()) { qunlock(&q->rd); lock(&q->listlk); if(bp) { bp->next = q->list; q->list = bp; } unlock(&q->listlk); nexterror(); } while(nodata(q)) sleep(&q->r, nodata, q); if(m->headopen == 0) errors("server shutdown"); nread = 0; while(n) { lock(&q->listlk); bp = q->list; q->list = bp->next; bp->next = 0; unlock(&q->listlk); l = BLEN(bp); if(n < l) n = l; memmove(va, bp->rptr, l); /* Interruptable thru fault */ va += l; bp->rptr += l; n -= l; gotdelim = bp->flags&S_DELIM; lock(&q->listlk); if(bp->rptr != bp->wptr) { bp->next = q->list; q->list = bp; } else if(gotdelim) q->ndelim--; unlock(&q->listlk); if(bp->rptr == bp->wptr) freeb(bp); if(gotdelim) break; } qunlock(&q->rd); return nread; } . ## diffname port/devmux.c 1991/1115 ## diff -e /n/bootesdump/1991/1114/sys/src/9/port/devmux.c /n/bootesdump/1991/1115/sys/src/9/port/devmux.c 549a } Block * muxclq(Dtq *q) { Block *f; f = q->list; q->list = 0; q->nb = 0; q->ndelim = 0; return f; . 548a poperror(); if(q->nb < Flowctl) wakeup(&q->flowr); . 547a q->nb -= nread; unlock(&q->listlk); if(f1) freeb(f1); . 546a } . 542,545d 540c if(bp->flags&S_DELIM) { . 536c if(bp->rptr == bp->wptr) f1 = bp; else { . 534c nread += l; . 528,529c if(l > n) l = n; . 526c if(f1) { freeb(f1); f1 = 0; } . 521d 519a f1 = 0; lock(&q->listlk); . 516,518d 513,514c while(!havedata(q)) { sleep(&q->r, havedata, q); if(m->headopen == 0) errors("server shutdown"); } . 499c Block *bp, *f1; . 486a return q->nb < Flowctl; } void muxflow(Dtq *q) { qlock(&q->flow); if(waserror()) { qunlock(&q->flow); nexterror(); } sleep(&q->flowr, muxflw, q); poperror(); qunlock(&q->flow); } int havedata(Dtq *q) { . 485c muxflw(Dtq *q) . 481a wakeup(&q->r); . 480a q->nb += bwrite; . 477,479c if(q->list == 0) q->list = head; else { for(tail = q->list; tail->next; tail = tail->next) ; tail->next = head; } . 475a if(q->nb > Flowctl) muxflow(q); . 466a bwrite += l; . 463a if(l > n) l = n; . 461,462c if(addid) { bp = allocb(n+3); bp->wptr[0] = Tmux; bp->wptr[1] = muxid; bp->wptr[2] = 0; bp->wptr += 3; bwrite += 3; addid = 0; } else bp = allocb(n); . 459a bwrite = 0; . 450c ulong l, bwrite; . 438c muxid = NCON(c)-Qoffset; . 417a if(n > Maxmsg) error(Etoobig); . 415c if(c->qid.path&CHDIR) . 413c char *a, hdr[3]; . 393c if(h[0] != Tmux || h[2] != 0) . 380c cm = &m->connects[NCON(c)-Qoffset]; . 344,353c cm = &m->connects[nc-Qoffset]; if(--cm->ref == 0) f1 = muxclq(&cm->conq); if(--m->ref == 0) f1 = muxclq(&m->headq); . 341c break; . 334,337c if(--m->ref == 0) f1 = muxclq(&m->headq); . 321a if((c->flag&COPEN) == 0) return; . 319c if(c->qid.path&CHDIR) . 306c m->connects[nc-Qoffset].perm = d.mode; . 294d 237c if(m->name[0] == '\0' && m->ref == 0 && canlock(m)) { . 217c m->ref++; unlock(m); . 214,215c c = devopen(c, omode, 0, 0, muxgen); cm = &m->connects[NCON(c)-Qoffset]; lock(m); . 211c c->qid = NQID(mux, (cm-m->connects)+Qoffset); . 206c cm->ref = 1; . 187,190c } . 185a ok = 0; else { ok = 1; m->headopen = 1; m->ref++; } unlock(m); if(!ok) { c->flag &= ~COPEN; . 184a c = devopen(c, omode, 0, 0, muxgen); lock(m); . 182c mux = NMUX(c); m = &muxes[mux]; . 177a int mux, ok; . 149c m->connects[ncon-Qoffset].ref++; . 140a if((c->flag&COPEN) == 0) return c; . 139d 123d 99,100c sprint(buf, "%d", nq); devdir(c, NQID(mux, Qoffset+s), buf, cm->conq.nb, cm->user, cm->perm, dp); . 96c nq = s-Qoffset; cm = &m->connects[nq]; . 90c devdir(c, NQID(mux, Qhead), "head", m->headq.nb, m->user, m->perm, dp); . 87a . 79c devdir(c, DQID(s), m->name, 0, m->user, m->perm, dp); . 70a int nq; . 61c #define NQID(m, c) (Qid){(m+1)<<8|(c)&0xff, 0} #define DQID(m) (Qid){(m+1)<<8|CHDIR, 0} . 58a void muxflow(Dtq*); Block *muxclq(Dtq *q); . 46a int type; . 33a int nb; QLock flow; Rendez flowr; . 24a Maxmsg = (32*1024), Flowctl = Maxmsg/2, . 19a Qoffset, . 18c Qhead = 0, . ## diffname port/devmux.c 1991/1117 ## diff -e /n/bootesdump/1991/1115/sys/src/9/port/devmux.c /n/bootesdump/1991/1117/sys/src/9/port/devmux.c 577a qunlock(&q->rd); . 571d 478c tail = 0; . 443c if(m->srv) { memmove(buf, va, n); /* so we can NUL-terminate */ buf[n] = 0; fd = strtoul(buf, 0, 0); fdtochan(fd, -1, 0); /* error check */ m->c = u->p->fgrp->fd[fd]; incref(m->c); return n; } . 440c m = &muxes[NMUX(c)]; if(n > Maxmsg || (m->srv && n >= sizeof(buf))) . 435c char *a, hdr[3], buf[10]; . 433c int muxid, fd; . 351d 348c m = &muxes[NMUX(c)]; if(!(c->flag&COPEN) || m->srv) . 319c if(c->qid.path&CHDIR || m->srv) { . 300a unlock(m); if(srv) close(srv); muxclose(c); . 299a srv = 0; lock(m); if(m->srv) { srv = m->c; m->c = 0; } . 296a if((c->qid.path&CHDIR) == 0 && m->srv == 0) error(Eperm); . 293c if(c->qid.path == CHDIR) . 291a Chan *srv; . 283c c->qid = (Qid){(CHDIR&perm)|(n+1)<<8, 0}; . 279a m->srv = 1; if(perm&CHDIR) m->srv = 0; . 269d 247c unlock(m); poperror(); . 244d 241d 239d 233d 230d 227,228c if(cm == e) . 221,222d 215c m->headopen = 1; m->ref++; . 205,213d 202,203d 199a lock(m); if(waserror()) { c->flag &= ~COPEN; unlock(m); nexterror(); } if(m->srv) { if(m->c == 0) error(Eshutdown); new = m->c; incref(new); unlock(m); poperror(); close(c); return new; } . 196c return c; . 194a c = devopen(c, omode, 0, 0, muxgen); . 193a Chan *new; . 90c if(m->srv) devdir(c, NQID(s, 0), m->name, 0, m->user, m->perm, dp); else devdir(c, DQID(s), m->name, 0, m->user, m->perm, dp); . 63d 59a Chan *c; . 53c int srv; . 25c Nmux = 32, . ## diffname port/devmux.c 1992/0111 ## diff -e /n/bootesdump/1991/1117/sys/src/9/port/devmux.c /n/bootesdump/1992/0111/sys/src/9/port/devmux.c 6c #include "../port/error.h" . ## diffname port/devmux.c 1992/0113 ## diff -e /n/bootesdump/1992/0111/sys/src/9/port/devmux.c /n/bootesdump/1992/0113/sys/src/9/port/devmux.c 613c errors(Emuxshutdown); . 479c error(Emuxmsg); . 441c error(Emuxmsg); . 437c error(Emuxmsg); . 335,336c if(strncmp(u->p->user, m->user, NAMELEN)) error(Eperm); . 307,308c if(strncmp(u->p->user, m->user, NAMELEN)) error(Eperm); . 278c error(Enomux); . 237c error(Emuxbusy); . 230c error(Emuxshutdown); . 224c error(Einuse); . ## diffname port/devmux.c 1992/0114 ## diff -e /n/bootesdump/1992/0113/sys/src/9/port/devmux.c /n/bootesdump/1992/0114/sys/src/9/port/devmux.c 613c error(Emuxshutdown); . 278c exhausted("multiplexers"); . ## diffname port/devmux.c 1992/0201 ## diff -e /n/bootesdump/1992/0114/sys/src/9/port/devmux.c /n/bootesdump/1992/0201/sys/src/9/port/devmux.c 138c c = devattach('s', spec); . ## diffname port/devmux.c 1992/0303 ## diff -e /n/bootesdump/1992/0201/sys/src/9/port/devmux.c /n/bootesdump/1992/0303/sys/src/9/port/devmux.c 356,402d 294a muxclose(Chan *c) { Block *f1, *f2; Con *cm, *e; Mux *m; int nc; if(c->qid.path&CHDIR) return; m = &muxes[NMUX(c)]; if(!(c->flag&COPEN) || m->srv) return; nc = NCON(c); f1 = 0; f2 = 0; switch(nc) { case Qhead: m->headopen = 0; cm = m->connects; for(e = &cm[Nmux]; cm < e; cm++) if(cm->ref) wakeup(&cm->conq.r); lock(m); if(--m->ref == 0) f1 = muxclq(&m->headq); unlock(m); break; case Qclone: break; default: lock(m); cm = &m->connects[nc-Qoffset]; if(--cm->ref == 0) f1 = muxclq(&cm->conq); if(--m->ref == 0) f1 = muxclq(&m->headq); unlock(m); } if(f1) freeb(f1); if(f2) freeb(f2); } void . ## diffname port/devmux.c 1992/0321 ## diff -e /n/bootesdump/1992/0303/sys/src/9/port/devmux.c /n/bootesdump/1992/0321/sys/src/9/port/devmux.c 2c #include "../port/lib.h" . ## diffname port/devmux.c 1992/0622 ## diff -e /n/bootesdump/1992/0321/sys/src/9/port/devmux.c /n/bootesdump/1992/0622/sys/src/9/port/devmux.c 130c muxes = xalloc(conf.nmux*sizeof(Mux)); . ## diffname port/devmux.c 1992/0630 ## diff -e /n/bootesdump/1992/0622/sys/src/9/port/devmux.c /n/bootesdump/1992/0630/sys/src/9/port/devmux.c 267c for(e = &m[Nmuxchan]; m < e; m++) { . 130c muxes = xalloc(Nmuxchan*sizeof(Mux)); . 84c if(s >= Nmuxchan) . 23,24c Nmuxchan= 64, . 21d 7d ## diffname port/devmux.c 1992/0711 ## diff -e /n/bootesdump/1992/0630/sys/src/9/port/devmux.c /n/bootesdump/1992/0711/sys/src/9/port/devmux.c 592c int l, nread; . 454a USED(offset); . 452d 408a USED(offset); . 193c int mux; . 79a USED(tab, ntab); . ## diffname port/devmux.c 1992/0825 ## diff -e /n/bootesdump/1992/0711/sys/src/9/port/devmux.c /n/bootesdump/1992/0825/sys/src/9/port/devmux.c 468c fdtochan(fd, -1, 0, 0); /* error check */ . ## diffname port/devmux.c 1993/0501 # deleted ## diff -e /n/bootesdump/1992/0825/sys/src/9/port/devmux.c /n/fornaxdump/1993/0501/sys/src/brazil/port/devmux.c 1,668d