## 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
|