diff options
Diffstat (limited to 'sys/src/cmd/unix/drawterm/kern')
51 files changed, 0 insertions, 22519 deletions
diff --git a/sys/src/cmd/unix/drawterm/kern/Makefile b/sys/src/cmd/unix/drawterm/kern/Makefile deleted file mode 100644 index c4cf4b21b..000000000 --- a/sys/src/cmd/unix/drawterm/kern/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -ROOT=.. -include ../Make.config -LIB=libkern.a - -OFILES=\ - allocb.$O\ - cache.$O\ - chan.$O\ - data.$O\ - dev.$O\ - devaudio.$O\ - devaudio-$(AUDIO).$O\ - devcons.$O\ - devdraw.$O\ - devfs-$(OS).$O\ - devip.$O\ - devip-$(OS).$O\ - devlfd.$O\ - devmnt.$O\ - devmouse.$O\ - devpipe.$O\ - devroot.$O\ - devssl.$O\ - devtls.$O\ - devtab.$O\ - error.$O\ - parse.$O\ - pgrp.$O\ - procinit.$O\ - rwlock.$O\ - sleep.$O\ - smalloc.$O\ - stub.$O\ - sysfile.$O\ - sysproc.$O\ - qio.$O\ - qlock.$O\ - term.$O\ - uart.$O\ - waserror.$O\ - $(OS).$O - -default: $(LIB) -$(LIB): $(OFILES) - $(AR) r $(LIB) $(OFILES) - $(RANLIB) $(LIB) - -%.$O: %.c - $(CC) $(CFLAGS) $*.c - diff --git a/sys/src/cmd/unix/drawterm/kern/allocb.c b/sys/src/cmd/unix/drawterm/kern/allocb.c deleted file mode 100644 index ab1595c89..000000000 --- a/sys/src/cmd/unix/drawterm/kern/allocb.c +++ /dev/null @@ -1,165 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -enum -{ - Hdrspc = 64, /* leave room for high-level headers */ - Bdead = 0x51494F42, /* "QIOB" */ -}; - -struct -{ - Lock lk; - ulong bytes; -} ialloc; - -static Block* -_allocb(int size) -{ - Block *b; - uintptr addr; - - if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil) - return nil; - - b->next = nil; - b->list = nil; - b->free = 0; - b->flag = 0; - - /* align start of data portion by rounding up */ - addr = (uintptr)b; - addr = ROUND(addr + sizeof(Block), BLOCKALIGN); - b->base = (uchar*)addr; - - /* align end of data portion by rounding down */ - b->lim = ((uchar*)b) + sizeof(Block)+size+Hdrspc; - addr = (uintptr)(b->lim); - addr = addr & ~(BLOCKALIGN-1); - b->lim = (uchar*)addr; - - /* leave sluff at beginning for added headers */ - b->rp = b->lim - ROUND(size, BLOCKALIGN); - if(b->rp < b->base) - panic("_allocb"); - b->wp = b->rp; - - return b; -} - -Block* -allocb(int size) -{ - Block *b; - - /* - * Check in a process and wait until successful. - * Can still error out of here, though. - */ - if(up == nil) - panic("allocb without up: %p\n", getcallerpc(&size)); - if((b = _allocb(size)) == nil){ - panic("allocb: no memory for %d bytes\n", size); - } - setmalloctag(b, getcallerpc(&size)); - - return b; -} - -Block* -iallocb(int size) -{ - Block *b; - static int m1, m2; - - if(ialloc.bytes > conf.ialloc){ - if((m1++%10000)==0) - print("iallocb: limited %lud/%lud\n", - ialloc.bytes, conf.ialloc); - return 0; - } - - if((b = _allocb(size)) == nil){ - if((m2++%10000)==0) - print("iallocb: no memory %lud/%lud\n", - ialloc.bytes, conf.ialloc); - return nil; - } - setmalloctag(b, getcallerpc(&size)); - b->flag = BINTR; - - ilock(&ialloc.lk); - ialloc.bytes += b->lim - b->base; - iunlock(&ialloc.lk); - - return b; -} - -void -freeb(Block *b) -{ - void *dead = (void*)Bdead; - - if(b == nil) - return; - - /* - * drivers which perform non cache coherent DMA manage their own buffer - * pool of uncached buffers and provide their own free routine. - */ - if(b->free) { - b->free(b); - return; - } - if(b->flag & BINTR) { - ilock(&ialloc.lk); - ialloc.bytes -= b->lim - b->base; - iunlock(&ialloc.lk); - } - - /* poison the block in case someone is still holding onto it */ - b->next = dead; - b->rp = dead; - b->wp = dead; - b->lim = dead; - b->base = dead; - - free(b); -} - -void -checkb(Block *b, char *msg) -{ - void *dead = (void*)Bdead; - - if(b == dead) - panic("checkb b %s %lux", msg, b); - if(b->base == dead || b->lim == dead || b->next == dead - || b->rp == dead || b->wp == dead){ - print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n", - b->base, b->lim, b->next); - print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp); - panic("checkb dead: %s\n", msg); - } - - if(b->base > b->lim) - panic("checkb 0 %s %lux %lux", msg, b->base, b->lim); - if(b->rp < b->base) - panic("checkb 1 %s %lux %lux", msg, b->base, b->rp); - if(b->wp < b->base) - panic("checkb 2 %s %lux %lux", msg, b->base, b->wp); - if(b->rp > b->lim) - panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim); - if(b->wp > b->lim) - panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim); - -} - -void -iallocsummary(void) -{ - print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc); -} diff --git a/sys/src/cmd/unix/drawterm/kern/cache.c b/sys/src/cmd/unix/drawterm/kern/cache.c deleted file mode 100644 index 56ee23ca7..000000000 --- a/sys/src/cmd/unix/drawterm/kern/cache.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - - -void -cinit(void) -{ -} - -void -copen(Chan *c) -{ - USED(c); -} - -int -cread(Chan *c, uchar *buf, int len, vlong off) -{ - USED(c); - USED(buf); - USED(len); - USED(off); - - return 0; -} - -void -cupdate(Chan *c, uchar *buf, int len, vlong off) -{ - USED(c); - USED(buf); - USED(len); - USED(off); -} - -void -cwrite(Chan* c, uchar *buf, int len, vlong off) -{ - USED(c); - USED(buf); - USED(len); - USED(off); -} diff --git a/sys/src/cmd/unix/drawterm/kern/chan.c b/sys/src/cmd/unix/drawterm/kern/chan.c deleted file mode 100644 index 7105f3a69..000000000 --- a/sys/src/cmd/unix/drawterm/kern/chan.c +++ /dev/null @@ -1,1494 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -int chandebug=0; /* toggled by sysr1 */ -QLock chanprint; /* probably asking for trouble (deadlocks) -rsc */ - -int domount(Chan**, Mhead**); - -void -dumpmount(void) /* DEBUGGING */ -{ - Pgrp *pg; - Mount *t; - Mhead **h, **he, *f; - - if(up == nil){ - print("no process for dumpmount\n"); - return; - } - pg = up->pgrp; - if(pg == nil){ - print("no pgrp for dumpmount\n"); - return; - } - rlock(&pg->ns); - if(waserror()) { - runlock(&pg->ns); - nexterror(); - } - - he = &pg->mnthash[MNTHASH]; - for(h = pg->mnthash; h < he; h++) { - for(f = *h; f; f = f->hash) { - print("head: %p: %s 0x%llux.%lud %C %lud -> \n", f, - f->from->name->s, f->from->qid.path, - f->from->qid.vers, devtab[f->from->type]->dc, - f->from->dev); - for(t = f->mount; t; t = t->next) - print("\t%p: %s (umh %p) (path %.8llux dev %C %lud)\n", t, t->to->name->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev); - } - } - poperror(); - runlock(&pg->ns); -} - - -char* -c2name(Chan *c) /* DEBUGGING */ -{ - if(c == nil) - return "<nil chan>"; - if(c->name == nil) - return "<nil name>"; - if(c->name->s == nil) - return "<nil name.s>"; - return c->name->s; -} - -enum -{ - CNAMESLOP = 20 -}; - -struct -{ - Lock lk; - int fid; - Chan *free; - Chan *list; -}chanalloc; - -typedef struct Elemlist Elemlist; - -struct Elemlist -{ - char *name; /* copy of name, so '/' can be overwritten */ - int nelems; - char **elems; - int *off; - int mustbedir; -}; - -#define SEP(c) ((c) == 0 || (c) == '/') -void cleancname(Cname*); - -int -isdotdot(char *p) -{ - return p[0]=='.' && p[1]=='.' && p[2]=='\0'; -} - -int -incref(Ref *r) -{ - int x; - - lock(&r->lk); - x = ++r->ref; - unlock(&r->lk); - return x; -} - -int -decref(Ref *r) -{ - int x; - - lock(&r->lk); - x = --r->ref; - unlock(&r->lk); - if(x < 0) - panic("decref, pc=0x%p", getcallerpc(&r)); - - return x; -} - -/* - * Rather than strncpy, which zeros the rest of the buffer, kstrcpy - * truncates if necessary, always zero terminates, does not zero fill, - * and puts ... at the end of the string if it's too long. Usually used to - * save a string in up->genbuf; - */ -void -kstrcpy(char *s, char *t, int ns) -{ - int nt; - - nt = strlen(t); - if(nt+1 <= ns){ - memmove(s, t, nt+1); - return; - } - /* too long */ - if(ns < 4){ - /* but very short! */ - strncpy(s, t, ns); - return; - } - /* truncate with ... at character boundary (very rare case) */ - memmove(s, t, ns-4); - ns -= 4; - s[ns] = '\0'; - /* look for first byte of UTF-8 sequence by skipping continuation bytes */ - while(ns>0 && (s[--ns]&0xC0)==0x80) - ; - strcpy(s+ns, "..."); -} - -int -emptystr(char *s) -{ - if(s == nil) - return 1; - if(s[0] == '\0') - return 1; - return 0; -} - -/* - * Atomically replace *p with copy of s - */ -void -kstrdup(char **p, char *s) -{ - int n; - char *t, *prev; - - n = strlen(s)+1; - /* if it's a user, we can wait for memory; if not, something's very wrong */ - if(up){ - t = smalloc(n); - setmalloctag(t, getcallerpc(&p)); - }else{ - t = malloc(n); - if(t == nil) - panic("kstrdup: no memory"); - } - memmove(t, s, n); - prev = *p; - *p = t; - free(prev); -} - -void -chandevreset(void) -{ - int i; - - for(i=0; devtab[i] != nil; i++) - devtab[i]->reset(); -} - -void -chandevinit(void) -{ - int i; - - for(i=0; devtab[i] != nil; i++) - devtab[i]->init(); -} - -void -chandevshutdown(void) -{ - int i; - - /* shutdown in reverse order */ - for(i=0; devtab[i] != nil; i++) - ; - for(i--; i >= 0; i--) - devtab[i]->shutdown(); -} - -Chan* -newchan(void) -{ - Chan *c; - - lock(&chanalloc.lk); - c = chanalloc.free; - if(c != 0) - chanalloc.free = c->next; - unlock(&chanalloc.lk); - - if(c == nil) { - c = smalloc(sizeof(Chan)); - lock(&chanalloc.lk); - c->fid = ++chanalloc.fid; - c->link = chanalloc.list; - chanalloc.list = c; - unlock(&chanalloc.lk); - } - - /* if you get an error before associating with a dev, - close calls rootclose, a nop */ - c->type = 0; - c->flag = 0; - c->ref.ref = 1; - c->dev = 0; - c->offset = 0; - c->iounit = 0; - c->umh = 0; - c->uri = 0; - c->dri = 0; - c->aux = 0; - c->mchan = 0; - c->mcp = 0; - c->mux = 0; - memset(&c->mqid, 0, sizeof(c->mqid)); - c->name = 0; - return c; -} - -static Ref ncname; - -Cname* -newcname(char *s) -{ - Cname *n; - int i; - - n = smalloc(sizeof(Cname)); - i = strlen(s); - n->len = i; - n->alen = i+CNAMESLOP; - n->s = smalloc(n->alen); - memmove(n->s, s, i+1); - n->ref.ref = 1; - incref(&ncname); - return n; -} - -void -cnameclose(Cname *n) -{ - if(n == nil) - return; - if(decref(&n->ref)) - return; - decref(&ncname); - free(n->s); - free(n); -} - -Cname* -addelem(Cname *n, char *s) -{ - int i, a; - char *t; - Cname *new; - - if(s[0]=='.' && s[1]=='\0') - return n; - - if(n->ref.ref > 1){ - /* copy on write */ - new = newcname(n->s); - cnameclose(n); - n = new; - } - - i = strlen(s); - if(n->len+1+i+1 > n->alen){ - a = n->len+1+i+1 + CNAMESLOP; - t = smalloc(a); - memmove(t, n->s, n->len+1); - free(n->s); - n->s = t; - n->alen = a; - } - if(n->len>0 && n->s[n->len-1]!='/' && s[0]!='/') /* don't insert extra slash if one is present */ - n->s[n->len++] = '/'; - memmove(n->s+n->len, s, i+1); - n->len += i; - if(isdotdot(s)) - cleancname(n); - return n; -} - -void -chanfree(Chan *c) -{ - c->flag = CFREE; - - if(c->umh != nil){ - putmhead(c->umh); - c->umh = nil; - } - if(c->umc != nil){ - cclose(c->umc); - c->umc = nil; - } - if(c->mux != nil){ - muxclose(c->mux); - c->mux = nil; - } - if(c->mchan != nil){ - cclose(c->mchan); - c->mchan = nil; - } - - cnameclose(c->name); - - lock(&chanalloc.lk); - c->next = chanalloc.free; - chanalloc.free = c; - unlock(&chanalloc.lk); -} - -void -cclose(Chan *c) -{ - if(c->flag&CFREE) - panic("cclose %p", getcallerpc(&c)); - - if(decref(&c->ref)) - return; - - if(!waserror()){ - devtab[c->type]->close(c); - poperror(); - } - chanfree(c); -} - -/* - * Make sure we have the only copy of c. (Copy on write.) - */ -Chan* -cunique(Chan *c) -{ - Chan *nc; - - if(c->ref.ref != 1) { - nc = cclone(c); - cclose(c); - c = nc; - } - - return c; -} - -int -eqqid(Qid a, Qid b) -{ - return a.path==b.path && a.vers==b.vers; -} - -int -eqchan(Chan *a, Chan *b, int pathonly) -{ - if(a->qid.path != b->qid.path) - return 0; - if(!pathonly && a->qid.vers!=b->qid.vers) - return 0; - if(a->type != b->type) - return 0; - if(a->dev != b->dev) - return 0; - return 1; -} - -int -eqchantdqid(Chan *a, int type, int dev, Qid qid, int pathonly) -{ - if(a->qid.path != qid.path) - return 0; - if(!pathonly && a->qid.vers!=qid.vers) - return 0; - if(a->type != type) - return 0; - if(a->dev != dev) - return 0; - return 1; -} - -Mhead* -newmhead(Chan *from) -{ - Mhead *mh; - - mh = smalloc(sizeof(Mhead)); - mh->ref.ref = 1; - mh->from = from; - incref(&from->ref); - -/* - n = from->name->len; - if(n >= sizeof(mh->fromname)) - n = sizeof(mh->fromname)-1; - memmove(mh->fromname, from->name->s, n); - mh->fromname[n] = 0; -*/ - return mh; -} - -int -cmount(Chan **newp, Chan *old, int flag, char *spec) -{ - Pgrp *pg; - int order, flg; - Mhead *m, **l, *mh; - Mount *nm, *f, *um, **h; - Chan *new; - - if(QTDIR & (old->qid.type^(*newp)->qid.type)) - error(Emount); - -if(old->umh)print("cmount old extra umh\n"); - - order = flag&MORDER; - - if((old->qid.type&QTDIR)==0 && order != MREPL) - error(Emount); - - new = *newp; - mh = new->umh; - - /* - * Not allowed to bind when the old directory - * is itself a union. (Maybe it should be allowed, but I don't see - * what the semantics would be.) - * - * We need to check mh->mount->next to tell unions apart from - * simple mount points, so that things like - * mount -c fd /root - * bind -c /root / - * work. The check of mount->mflag catches things like - * mount fd /root - * bind -c /root / - * - * This is far more complicated than it should be, but I don't - * see an easier way at the moment. -rsc - */ - if((flag&MCREATE) && mh && mh->mount - && (mh->mount->next || !(mh->mount->mflag&MCREATE))) - error(Emount); - - pg = up->pgrp; - wlock(&pg->ns); - - l = &MOUNTH(pg, old->qid); - for(m = *l; m; m = m->hash) { - if(eqchan(m->from, old, 1)) - break; - l = &m->hash; - } - - if(m == nil) { - /* - * nothing mounted here yet. create a mount - * head and add to the hash table. - */ - m = newmhead(old); - *l = m; - - /* - * if this is a union mount, add the old - * node to the mount chain. - */ - if(order != MREPL) - m->mount = newmount(m, old, 0, 0); - } - wlock(&m->lock); - if(waserror()){ - wunlock(&m->lock); - nexterror(); - } - wunlock(&pg->ns); - - nm = newmount(m, new, flag, spec); - if(mh != nil && mh->mount != nil) { - /* - * copy a union when binding it onto a directory - */ - flg = order; - if(order == MREPL) - flg = MAFTER; - h = &nm->next; - um = mh->mount; - for(um = um->next; um; um = um->next) { - f = newmount(m, um->to, flg, um->spec); - *h = f; - h = &f->next; - } - } - - if(m->mount && order == MREPL) { - mountfree(m->mount); - m->mount = 0; - } - - if(flag & MCREATE) - nm->mflag |= MCREATE; - - if(m->mount && order == MAFTER) { - for(f = m->mount; f->next; f = f->next) - ; - f->next = nm; - } - else { - for(f = nm; f->next; f = f->next) - ; - f->next = m->mount; - m->mount = nm; - } - - wunlock(&m->lock); - poperror(); - return nm->mountid; -} - -void -cunmount(Chan *mnt, Chan *mounted) -{ - Pgrp *pg; - Mhead *m, **l; - Mount *f, **p; - - if(mnt->umh) /* should not happen */ - print("cunmount newp extra umh %p has %p\n", mnt, mnt->umh); - - /* - * It _can_ happen that mounted->umh is non-nil, - * because mounted is the result of namec(Aopen) - * (see sysfile.c:/^sysunmount). - * If we open a union directory, it will have a umh. - * Although surprising, this is okay, since the - * cclose will take care of freeing the umh. - */ - - pg = up->pgrp; - wlock(&pg->ns); - - l = &MOUNTH(pg, mnt->qid); - for(m = *l; m; m = m->hash) { - if(eqchan(m->from, mnt, 1)) - break; - l = &m->hash; - } - - if(m == 0) { - wunlock(&pg->ns); - error(Eunmount); - } - - wlock(&m->lock); - if(mounted == 0) { - *l = m->hash; - wunlock(&pg->ns); - mountfree(m->mount); - m->mount = nil; - cclose(m->from); - wunlock(&m->lock); - putmhead(m); - return; - } - - p = &m->mount; - for(f = *p; f; f = f->next) { - /* BUG: Needs to be 2 pass */ - if(eqchan(f->to, mounted, 1) || - (f->to->mchan && eqchan(f->to->mchan, mounted, 1))) { - *p = f->next; - f->next = 0; - mountfree(f); - if(m->mount == nil) { - *l = m->hash; - cclose(m->from); - wunlock(&m->lock); - wunlock(&pg->ns); - putmhead(m); - return; - } - wunlock(&m->lock); - wunlock(&pg->ns); - return; - } - p = &f->next; - } - wunlock(&m->lock); - wunlock(&pg->ns); - error(Eunion); -} - -Chan* -cclone(Chan *c) -{ - Chan *nc; - Walkqid *wq; - - wq = devtab[c->type]->walk(c, nil, nil, 0); - if(wq == nil) - error("clone failed"); - nc = wq->clone; - free(wq); - nc->name = c->name; - if(c->name) - incref(&c->name->ref); - return nc; -} - -int -findmount(Chan **cp, Mhead **mp, int type, int dev, Qid qid) -{ - Pgrp *pg; - Mhead *m; - - pg = up->pgrp; - rlock(&pg->ns); - for(m = MOUNTH(pg, qid); m; m = m->hash){ - rlock(&m->lock); -if(m->from == nil){ - print("m %p m->from 0\n", m); - runlock(&m->lock); - continue; -} - if(eqchantdqid(m->from, type, dev, qid, 1)) { - runlock(&pg->ns); - if(mp != nil){ - incref(&m->ref); - if(*mp != nil) - putmhead(*mp); - *mp = m; - } - if(*cp != nil) - cclose(*cp); - incref(&m->mount->to->ref); - *cp = m->mount->to; - runlock(&m->lock); - return 1; - } - runlock(&m->lock); - } - - runlock(&pg->ns); - return 0; -} - -int -domount(Chan **cp, Mhead **mp) -{ - return findmount(cp, mp, (*cp)->type, (*cp)->dev, (*cp)->qid); -} - -Chan* -undomount(Chan *c, Cname *name) -{ - Chan *nc; - Pgrp *pg; - Mount *t; - Mhead **h, **he, *f; - - pg = up->pgrp; - rlock(&pg->ns); - if(waserror()) { - runlock(&pg->ns); - nexterror(); - } - - he = &pg->mnthash[MNTHASH]; - for(h = pg->mnthash; h < he; h++) { - for(f = *h; f; f = f->hash) { - if(strcmp(f->from->name->s, name->s) != 0) - continue; - for(t = f->mount; t; t = t->next) { - if(eqchan(c, t->to, 1)) { - /* - * We want to come out on the left hand side of the mount - * point using the element of the union that we entered on. - * To do this, find the element that has a from name of - * c->name->s. - */ - if(strcmp(t->head->from->name->s, name->s) != 0) - continue; - nc = t->head->from; - incref(&nc->ref); - cclose(c); - c = nc; - break; - } - } - } - } - poperror(); - runlock(&pg->ns); - return c; -} - -/* - * Either walks all the way or not at all. No partial results in *cp. - * *nerror is the number of names to display in an error message. - */ -static char Edoesnotexist[] = "does not exist"; -int -walk(Chan **cp, char **names, int nnames, int nomount, int *nerror) -{ - int dev, dotdot, i, n, nhave, ntry, type; - Chan *c, *nc; - Cname *cname; - Mount *f; - Mhead *mh, *nmh; - Walkqid *wq; - - c = *cp; - incref(&c->ref); - cname = c->name; - incref(&cname->ref); - mh = nil; - - /* - * While we haven't gotten all the way down the path: - * 1. step through a mount point, if any - * 2. send a walk request for initial dotdot or initial prefix without dotdot - * 3. move to the first mountpoint along the way. - * 4. repeat. - * - * An invariant is that each time through the loop, c is on the undomount - * side of the mount point, and c's name is cname. - */ - for(nhave=0; nhave<nnames; nhave+=n){ - if((c->qid.type&QTDIR)==0){ - if(nerror) - *nerror = nhave; - cnameclose(cname); - cclose(c); - strcpy(up->errstr, Enotdir); - if(mh != nil) -{print("walk 1\n"); - putmhead(mh); -} - return -1; - } - ntry = nnames - nhave; - if(ntry > MAXWELEM) - ntry = MAXWELEM; - dotdot = 0; - for(i=0; i<ntry; i++){ - if(isdotdot(names[nhave+i])){ - if(i==0) { - dotdot = 1; - ntry = 1; - } else - ntry = i; - break; - } - } - - if(!dotdot && !nomount) - domount(&c, &mh); - - type = c->type; - dev = c->dev; - - if((wq = devtab[type]->walk(c, nil, names+nhave, ntry)) == nil){ - /* try a union mount, if any */ - if(mh && !nomount){ - /* - * mh->mount == c, so start at mh->mount->next - */ - rlock(&mh->lock); - for(f = mh->mount->next; f; f = f->next) - if((wq = devtab[f->to->type]->walk(f->to, nil, names+nhave, ntry)) != nil) - break; - runlock(&mh->lock); - if(f != nil){ - type = f->to->type; - dev = f->to->dev; - } - } - if(wq == nil){ - cclose(c); - cnameclose(cname); - if(nerror) - *nerror = nhave+1; - if(mh != nil) - putmhead(mh); - return -1; - } - } - - nmh = nil; - if(dotdot) { - assert(wq->nqid == 1); - assert(wq->clone != nil); - - cname = addelem(cname, ".."); - nc = undomount(wq->clone, cname); - n = 1; - } else { - nc = nil; - if(!nomount) - for(i=0; i<wq->nqid && i<ntry-1; i++) - if(findmount(&nc, &nmh, type, dev, wq->qid[i])) - break; - if(nc == nil){ /* no mount points along path */ - if(wq->clone == nil){ - cclose(c); - cnameclose(cname); - if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){ - if(nerror) - *nerror = nhave+wq->nqid+1; - strcpy(up->errstr, Edoesnotexist); - }else{ - if(nerror) - *nerror = nhave+wq->nqid; - strcpy(up->errstr, Enotdir); - } - free(wq); - if(mh != nil) - putmhead(mh); - return -1; - } - n = wq->nqid; - nc = wq->clone; - }else{ /* stopped early, at a mount point */ - if(wq->clone != nil){ - cclose(wq->clone); - wq->clone = nil; - } - n = i+1; - } - for(i=0; i<n; i++) - cname = addelem(cname, names[nhave+i]); - } - cclose(c); - c = nc; - putmhead(mh); - mh = nmh; - free(wq); - } - - putmhead(mh); - - c = cunique(c); - - if(c->umh != nil){ //BUG - print("walk umh\n"); - putmhead(c->umh); - c->umh = nil; - } - - cnameclose(c->name); - c->name = cname; - - cclose(*cp); - *cp = c; - if(nerror) - *nerror = 0; - return 0; -} - -/* - * c is a mounted non-creatable directory. find a creatable one. - */ -Chan* -createdir(Chan *c, Mhead *m) -{ - Chan *nc; - Mount *f; - - rlock(&m->lock); - if(waserror()) { - runlock(&m->lock); - nexterror(); - } - for(f = m->mount; f; f = f->next) { - if(f->mflag&MCREATE) { - nc = cclone(f->to); - runlock(&m->lock); - poperror(); - cclose(c); - return nc; - } - } - error(Enocreate); - return 0; -} - -void -saveregisters(void) -{ -} - -/* - * In place, rewrite name to compress multiple /, eliminate ., and process .. - */ -void -cleancname(Cname *n) -{ - char *p; - - if(n->s[0] == '#'){ - p = strchr(n->s, '/'); - if(p == nil) - return; - cleanname(p); - - /* - * The correct name is #i rather than #i/, - * but the correct name of #/ is #/. - */ - if(strcmp(p, "/")==0 && n->s[1] != '/') - *p = '\0'; - }else - cleanname(n->s); - n->len = strlen(n->s); -} - -static void -growparse(Elemlist *e) -{ - char **new; - int *inew; - enum { Delta = 8 }; - - if(e->nelems % Delta == 0){ - new = smalloc((e->nelems+Delta) * sizeof(char*)); - memmove(new, e->elems, e->nelems*sizeof(char*)); - free(e->elems); - e->elems = new; - inew = smalloc((e->nelems+Delta+1) * sizeof(int)); - memmove(inew, e->off, e->nelems*sizeof(int)); - free(e->off); - e->off = inew; - } -} - -/* - * The name is known to be valid. - * Copy the name so slashes can be overwritten. - * An empty string will set nelem=0. - * A path ending in / or /. or /.//./ etc. will have - * e.mustbedir = 1, so that we correctly - * reject, e.g., "/adm/users/." when /adm/users is a file - * rather than a directory. - */ -static void -parsename(char *name, Elemlist *e) -{ - char *slash; - - kstrdup(&e->name, name); - name = e->name; - e->nelems = 0; - e->elems = nil; - e->off = smalloc(sizeof(int)); - e->off[0] = skipslash(name) - name; - for(;;){ - name = skipslash(name); - if(*name=='\0'){ - e->mustbedir = 1; - break; - } - growparse(e); - e->elems[e->nelems++] = name; - slash = utfrune(name, '/'); - if(slash == nil){ - e->off[e->nelems] = name+strlen(name) - e->name; - e->mustbedir = 0; - break; - } - e->off[e->nelems] = slash - e->name; - *slash++ = '\0'; - name = slash; - } -} - -void* -mymemrchr(void *va, int c, long n) -{ - uchar *a, *e; - - a = va; - for(e=a+n-1; e>a; e--) - if(*e == c) - return e; - return nil; -} - -/* - * Turn a name into a channel. - * &name[0] is known to be a valid address. It may be a kernel address. - * - * Opening with amode Aopen, Acreate, or Aremove guarantees - * that the result will be the only reference to that particular fid. - * This is necessary since we might pass the result to - * devtab[]->remove(). - * - * Opening Atodir, Amount, or Aaccess does not guarantee this. - * - * Opening Aaccess can, under certain conditions, return a - * correct Chan* but with an incorrect Cname attached. - * Since the functions that open Aaccess (sysstat, syswstat, sys_stat) - * do not use the Cname*, this avoids an unnecessary clone. - */ -Chan* -namec(char *aname, int amode, int omode, ulong perm) -{ - int n, prefix, len, t, nomount, npath; - Chan *c, *cnew; - Cname *cname; - Elemlist e; - Rune r; - Mhead *m; - char *createerr, tmperrbuf[ERRMAX]; - char *name; - - name = aname; - if(name[0] == '\0') - error("empty file name"); - validname(name, 1); - - /* - * Find the starting off point (the current slash, the root of - * a device tree, or the current dot) as well as the name to - * evaluate starting there. - */ - nomount = 0; - switch(name[0]){ - case '/': - c = up->slash; - incref(&c->ref); - break; - - case '#': - nomount = 1; - up->genbuf[0] = '\0'; - n = 0; - while(*name!='\0' && (*name != '/' || n < 2)){ - if(n >= sizeof(up->genbuf)-1) - error(Efilename); - up->genbuf[n++] = *name++; - } - up->genbuf[n] = '\0'; - /* - * noattach is sandboxing. - * - * the OK exceptions are: - * | it only gives access to pipes you create - * d this process's file descriptors - * e this process's environment - * the iffy exceptions are: - * c time and pid, but also cons and consctl - * p control of your own processes (and unfortunately - * any others left unprotected) - */ - n = chartorune(&r, up->genbuf+1)+1; - /* actually / is caught by parsing earlier */ - if(utfrune("M", r)) - error(Enoattach); - if(up->pgrp->noattach && utfrune("|decp", r)==nil) - error(Enoattach); - t = devno(r, 1); - if(t == -1) - error(Ebadsharp); - c = devtab[t]->attach(up->genbuf+n); - break; - - default: - c = up->dot; - incref(&c->ref); - break; - } - prefix = name - aname; - - e.name = nil; - e.elems = nil; - e.off = nil; - e.nelems = 0; - if(waserror()){ - cclose(c); - free(e.name); - free(e.elems); - free(e.off); -//dumpmount(); - nexterror(); - } - - /* - * Build a list of elements in the path. - */ - parsename(name, &e); - - /* - * On create, .... - */ - if(amode == Acreate){ - /* perm must have DMDIR if last element is / or /. */ - if(e.mustbedir && !(perm&DMDIR)){ - npath = e.nelems; - strcpy(tmperrbuf, "create without DMDIR"); - goto NameError; - } - - /* don't try to walk the last path element just yet. */ - if(e.nelems == 0) - error(Eexist); - e.nelems--; - } - - if(walk(&c, e.elems, e.nelems, nomount, &npath) < 0){ - if(npath < 0 || npath > e.nelems){ - print("namec %s walk error npath=%d\n", aname, npath); - nexterror(); - } - strcpy(tmperrbuf, up->errstr); - NameError: - len = prefix+e.off[npath]; - if(len < ERRMAX/3 || (name=mymemrchr(aname, '/', len))==nil || name==aname) - snprint(up->genbuf, sizeof up->genbuf, "%.*s", len, aname); - else - snprint(up->genbuf, sizeof up->genbuf, "...%.*s", (int)(len-(name-aname)), name); - snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, tmperrbuf); - nexterror(); - } - - if(e.mustbedir && !(c->qid.type&QTDIR)){ - npath = e.nelems; - strcpy(tmperrbuf, "not a directory"); - goto NameError; - } - - if(amode == Aopen && (omode&3) == OEXEC && (c->qid.type&QTDIR)){ - npath = e.nelems; - error("cannot exec directory"); - } - - switch(amode){ - case Aaccess: - if(!nomount) - domount(&c, nil); - break; - - case Abind: - m = nil; - if(!nomount) - domount(&c, &m); - if(c->umh != nil) - putmhead(c->umh); - c->umh = m; - break; - - case Aremove: - case Aopen: - Open: - /* save the name; domount might change c */ - cname = c->name; - incref(&cname->ref); - m = nil; - if(!nomount) - domount(&c, &m); - - /* our own copy to open or remove */ - c = cunique(c); - - /* now it's our copy anyway, we can put the name back */ - cnameclose(c->name); - c->name = cname; - - switch(amode){ - case Aremove: - putmhead(m); - break; - - case Aopen: - case Acreate: -if(c->umh != nil){ - print("cunique umh Open\n"); - putmhead(c->umh); - c->umh = nil; -} - - /* only save the mount head if it's a multiple element union */ - if(m && m->mount && m->mount->next) - c->umh = m; - else - putmhead(m); - - /* save registers else error() in open has wrong value of c saved */ - saveregisters(); - - if(omode == OEXEC) - c->flag &= ~CCACHE; - - c = devtab[c->type]->open(c, omode&~OCEXEC); - - if(omode & OCEXEC) - c->flag |= CCEXEC; - if(omode & ORCLOSE) - c->flag |= CRCLOSE; - break; - } - break; - - case Atodir: - /* - * Directories (e.g. for cd) are left before the mount point, - * so one may mount on / or . and see the effect. - */ - if(!(c->qid.type & QTDIR)) - error(Enotdir); - break; - - case Amount: - /* - * When mounting on an already mounted upon directory, - * one wants subsequent mounts to be attached to the - * original directory, not the replacement. Don't domount. - */ - break; - - case Acreate: - /* - * We've already walked all but the last element. - * If the last exists, try to open it OTRUNC. - * If omode&OEXCL is set, just give up. - */ - e.nelems++; - if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){ - if(omode&OEXCL) - error(Eexist); - omode |= OTRUNC; - goto Open; - } - - /* - * The semantics of the create(2) system call are that if the - * file exists and can be written, it is to be opened with truncation. - * On the other hand, the create(5) message fails if the file exists. - * If we get two create(2) calls happening simultaneously, - * they might both get here and send create(5) messages, but only - * one of the messages will succeed. To provide the expected create(2) - * semantics, the call with the failed message needs to try the above - * walk again, opening for truncation. This correctly solves the - * create/create race, in the sense that any observable outcome can - * be explained as one happening before the other. - * The create/create race is quite common. For example, it happens - * when two rc subshells simultaneously update the same - * environment variable. - * - * The implementation still admits a create/create/remove race: - * (A) walk to file, fails - * (B) walk to file, fails - * (A) create file, succeeds, returns - * (B) create file, fails - * (A) remove file, succeeds, returns - * (B) walk to file, return failure. - * - * This is hardly as common as the create/create race, and is really - * not too much worse than what might happen if (B) got a hold of a - * file descriptor and then the file was removed -- either way (B) can't do - * anything with the result of the create call. So we don't care about this race. - * - * Applications that care about more fine-grained decision of the races - * can use the OEXCL flag to get at the underlying create(5) semantics; - * by default we provide the common case. - * - * We need to stay behind the mount point in case we - * need to do the first walk again (should the create fail). - * - * We also need to cross the mount point and find the directory - * in the union in which we should be creating. - * - * The channel staying behind is c, the one moving forward is cnew. - */ - m = nil; - cnew = nil; /* is this assignment necessary? */ - if(!waserror()){ /* try create */ - if(!nomount && findmount(&cnew, &m, c->type, c->dev, c->qid)) - cnew = createdir(cnew, m); - else{ - cnew = c; - incref(&cnew->ref); - } - - /* - * We need our own copy of the Chan because we're - * about to send a create, which will move it. Once we have - * our own copy, we can fix the name, which might be wrong - * if findmount gave us a new Chan. - */ - cnew = cunique(cnew); - cnameclose(cnew->name); - cnew->name = c->name; - incref(&cnew->name->ref); - - devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm); - poperror(); - if(omode & OCEXEC) - cnew->flag |= CCEXEC; - if(omode & ORCLOSE) - cnew->flag |= CRCLOSE; - if(m) - putmhead(m); - cclose(c); - c = cnew; - c->name = addelem(c->name, e.elems[e.nelems-1]); - break; - }else{ /* create failed */ - cclose(cnew); - if(m) - putmhead(m); - if(omode & OEXCL) - nexterror(); - /* save error */ - createerr = up->errstr; - up->errstr = tmperrbuf; - /* note: we depend that walk does not error */ - if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){ - up->errstr = createerr; - error(createerr); /* report true error */ - } - up->errstr = createerr; - omode |= OTRUNC; - goto Open; - } - panic("namec: not reached"); - - default: - panic("unknown namec access %d\n", amode); - } - - poperror(); - - /* place final element in genbuf for e.g. exec */ - if(e.nelems > 0) - kstrcpy(up->genbuf, e.elems[e.nelems-1], sizeof up->genbuf); - else - kstrcpy(up->genbuf, ".", sizeof up->genbuf); - free(e.name); - free(e.elems); - free(e.off); - - return c; -} - -/* - * name is valid. skip leading / and ./ as much as possible - */ -char* -skipslash(char *name) -{ - while(name[0]=='/' || (name[0]=='.' && (name[1]==0 || name[1]=='/'))) - name++; - return name; -} - -char isfrog[256]={ - /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1, /* 0 */ - /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1, /* 0x08 */ - /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1, /* 0x10 */ - /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1, /* 0x18 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */ - 0, 0, 0, 0, 0, 0, 0, 1, /* 0x28 (1 is '/', 0x2F) */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x38 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x58 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68 */ - 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */ - 0, 0, 0, 0, 0, 0, 0, 1, /* 0x78 (1 is DEL, 0x7F) */ -}; - -/* - * Check that the name - * a) is in valid memory. - * b) is shorter than 2^16 bytes, so it can fit in a 9P string field. - * c) contains no frogs. - * The first byte is known to be addressible by the requester, so the - * routine works for kernel and user memory both. - * The parameter slashok flags whether a slash character is an error - * or a valid character. - */ -void -validname(char *aname, int slashok) -{ - char *ename, *name; - int c; - Rune r; - - name = aname; -/* - if(((ulong)name & KZERO) != KZERO) { - p = name; - t = BY2PG-((ulong)p&(BY2PG-1)); - while((ename=vmemchr(p, 0, t)) == nil) { - p += t; - t = BY2PG; - } - }else -*/ - ename = memchr(name, 0, (1<<16)); - - if(ename==nil || ename-name>=(1<<16)) - error("name too long"); - - while(*name){ - /* all characters above '~' are ok */ - c = *(uchar*)name; - if(c >= Runeself) - name += chartorune(&r, name); - else{ - if(isfrog[c]) - if(!slashok || c!='/'){ - snprint(up->genbuf, sizeof(up->genbuf), "%s: %q", Ebadchar, aname); - error(up->genbuf); - } - name++; - } - } -} - -void -isdir(Chan *c) -{ - if(c->qid.type & QTDIR) - return; - error(Enotdir); -} - -/* - * This is necessary because there are many - * pointers to the top of a given mount list: - * - * - the mhead in the namespace hash table - * - the mhead in chans returned from findmount: - * used in namec and then by unionread. - * - the mhead in chans returned from createdir: - * used in the open/create race protect, which is gone. - * - * The RWlock in the Mhead protects the mount list it contains. - * The mount list is deleted when we cunmount. - * The RWlock ensures that nothing is using the mount list at that time. - * - * It is okay to replace c->mh with whatever you want as - * long as you are sure you have a unique reference to it. - * - * This comment might belong somewhere else. - */ -void -putmhead(Mhead *m) -{ - if(m && decref(&m->ref) == 0){ - m->mount = (Mount*)0xCafeBeef; - free(m); - } -} diff --git a/sys/src/cmd/unix/drawterm/kern/dat.h b/sys/src/cmd/unix/drawterm/kern/dat.h deleted file mode 100644 index 9d00d0085..000000000 --- a/sys/src/cmd/unix/drawterm/kern/dat.h +++ /dev/null @@ -1,519 +0,0 @@ -#define KNAMELEN 28 /* max length of name held in kernel */ -#define DOMLEN 64 - -#define BLOCKALIGN 8 - -typedef struct Alarms Alarms; -typedef struct Block Block; -typedef struct CSN CSN; -typedef struct Chan Chan; -typedef struct Cmdbuf Cmdbuf; -typedef struct Cmdtab Cmdtab; -typedef struct Cname Cname; -typedef struct Conf Conf; -typedef struct Dev Dev; -typedef struct Dirtab Dirtab; -typedef struct Edfinterface Edfinterface; -typedef struct Egrp Egrp; -typedef struct Evalue Evalue; -typedef struct Fgrp Fgrp; -typedef struct FPsave FPsave; -typedef struct DevConf DevConf; -typedef struct Label Label; -typedef struct List List; -typedef struct Log Log; -typedef struct Logflag Logflag; -typedef struct Mntcache Mntcache; -typedef struct Mount Mount; -typedef struct Mntrpc Mntrpc; -typedef struct Mntwalk Mntwalk; -typedef struct Mnt Mnt; -typedef struct Mhead Mhead; -typedef struct Note Note; -typedef struct Page Page; -typedef struct Palloc Palloc; -typedef struct Perf Perf; -typedef struct Pgrps Pgrps; -typedef struct PhysUart PhysUart; -typedef struct Pgrp Pgrp; -typedef struct Physseg Physseg; -typedef struct Proc Proc; -typedef struct Pte Pte; -typedef struct Pthash Pthash; -typedef struct Queue Queue; -typedef struct Ref Ref; -typedef struct Rendez Rendez; -typedef struct Rgrp Rgrp; -typedef struct RWlock RWlock; -typedef struct Schedq Schedq; -typedef struct Segment Segment; -typedef struct Session Session; -typedef struct Task Task; -typedef struct Talarm Talarm; -typedef struct Timer Timer; -typedef struct Uart Uart; -typedef struct Ureg Ureg; -typedef struct Waitq Waitq; -typedef struct Walkqid Walkqid; -typedef int Devgen(Chan*, char*, Dirtab*, int, int, Dir*); - -#include "fcall.h" - -enum -{ - SnarfSize = 64*1024, -}; - -struct Conf -{ - ulong nmach; /* processors */ - ulong nproc; /* processes */ - ulong monitor; /* has monitor? */ - ulong npage0; /* total physical pages of memory */ - ulong npage1; /* total physical pages of memory */ - ulong npage; /* total physical pages of memory */ - ulong upages; /* user page pool */ - ulong nimage; /* number of page cache image headers */ - ulong nswap; /* number of swap pages */ - int nswppo; /* max # of pageouts per segment pass */ - ulong base0; /* base of bank 0 */ - ulong base1; /* base of bank 1 */ - ulong copymode; /* 0 is copy on write, 1 is copy on reference */ - ulong ialloc; /* max interrupt time allocation in bytes */ - ulong pipeqsize; /* size in bytes of pipe queues */ - int nuart; /* number of uart devices */ -}; - -struct Label -{ - jmp_buf buf; -}; - -struct Ref -{ - Lock lk; - long ref; -}; - -struct Rendez -{ - Lock lk; - Proc *p; -}; - -struct RWlock /* changed from kernel */ -{ - int readers; - Lock lk; - QLock x; - QLock k; -}; - -struct Talarm -{ - Lock lk; - Proc *list; -}; - -struct Alarms -{ - QLock lk; - Proc *head; -}; - -/* - * Access types in namec & channel flags - */ -enum -{ - Aaccess, /* as in stat, wstat */ - Abind, /* for left-hand-side of bind */ - Atodir, /* as in chdir */ - Aopen, /* for i/o */ - Amount, /* to be mounted or mounted upon */ - Acreate, /* is to be created */ - Aremove, /* will be removed by caller */ - - COPEN = 0x0001, /* for i/o */ - CMSG = 0x0002, /* the message channel for a mount */ -/* CCREATE = 0x0004, permits creation if c->mnt */ - CCEXEC = 0x0008, /* close on exec */ - CFREE = 0x0010, /* not in use */ - CRCLOSE = 0x0020, /* remove on close */ - CCACHE = 0x0080, /* client cache */ -}; - -/* flag values */ -enum -{ - BINTR = (1<<0), - BFREE = (1<<1), - Bipck = (1<<2), /* ip checksum */ - Budpck = (1<<3), /* udp checksum */ - Btcpck = (1<<4), /* tcp checksum */ - Bpktck = (1<<5), /* packet checksum */ -}; - -struct Block -{ - Block* next; - Block* list; - uchar* rp; /* first unconsumed byte */ - uchar* wp; /* first empty byte */ - uchar* lim; /* 1 past the end of the buffer */ - uchar* base; /* start of the buffer */ - void (*free)(Block*); - ushort flag; - ushort checksum; /* IP checksum of complete packet (minus media header) */ -}; -#define BLEN(s) ((s)->wp - (s)->rp) -#define BALLOC(s) ((s)->lim - (s)->base) - -struct Chan -{ - Ref ref; - Chan* next; /* allocation */ - Chan* link; - vlong offset; /* in file */ - ushort type; - ulong dev; - ushort mode; /* read/write */ - ushort flag; - Qid qid; - int fid; /* for devmnt */ - ulong iounit; /* chunk size for i/o; 0==default */ - Mhead* umh; /* mount point that derived Chan; used in unionread */ - Chan* umc; /* channel in union; held for union read */ - QLock umqlock; /* serialize unionreads */ - int uri; /* union read index */ - int dri; /* devdirread index */ - ulong mountid; - Mntcache *mcp; /* Mount cache pointer */ - Mnt *mux; /* Mnt for clients using me for messages */ - void* aux; - Qid pgrpid; /* for #p/notepg */ - ulong mid; /* for ns in devproc */ - Chan* mchan; /* channel to mounted server */ - Qid mqid; /* qid of root of mount point */ - Session*session; - Cname *name; -}; - -struct Cname -{ - Ref ref; - int alen; /* allocated length */ - int len; /* strlen(s) */ - char *s; -}; - -struct Dev -{ - int dc; - char* name; - - void (*reset)(void); - void (*init)(void); - void (*shutdown)(void); - Chan* (*attach)(char*); - Walkqid* (*walk)(Chan*, Chan*, char**, int); - int (*stat)(Chan*, uchar*, int); - Chan* (*open)(Chan*, int); - void (*create)(Chan*, char*, int, ulong); - void (*close)(Chan*); - long (*read)(Chan*, void*, long, vlong); - Block* (*bread)(Chan*, long, ulong); - long (*write)(Chan*, void*, long, vlong); - long (*bwrite)(Chan*, Block*, ulong); - void (*remove)(Chan*); - int (*wstat)(Chan*, uchar*, int); - void (*power)(int); /* power mgt: power(1) => on, power (0) => off */ - int (*config)(int, char*, DevConf*); // returns nil on error -}; - -struct Dirtab -{ - char name[KNAMELEN]; - Qid qid; - vlong length; - ulong perm; -}; - -struct Walkqid -{ - Chan *clone; - int nqid; - Qid qid[1]; -}; - -enum -{ - NSMAX = 1000, - NSLOG = 7, - NSCACHE = (1<<NSLOG), -}; - -struct Mntwalk /* state for /proc/#/ns */ -{ - int cddone; - ulong id; - Mhead* mh; - Mount* cm; -}; - -struct Mount -{ - ulong mountid; - Mount* next; - Mhead* head; - Mount* copy; - Mount* order; - Chan* to; /* channel replacing channel */ - int mflag; - char *spec; -}; - -struct Mhead -{ - Ref ref; - RWlock lock; - Chan* from; /* channel mounted upon */ - Mount* mount; /* what's mounted upon it */ - Mhead* hash; /* Hash chain */ -}; - -struct Mnt -{ - Lock lk; - /* references are counted using c->ref; channels on this mount point incref(c->mchan) == Mnt.c */ - Chan *c; /* Channel to file service */ - Proc *rip; /* Reader in progress */ - Mntrpc *queue; /* Queue of pending requests on this channel */ - ulong id; /* Multiplexer id for channel check */ - Mnt *list; /* Free list */ - int flags; /* cache */ - int msize; /* data + IOHDRSZ */ - char *version; /* 9P version */ - Queue *q; /* input queue */ -}; - -enum -{ - NUser, /* note provided externally */ - NExit, /* deliver note quietly */ - NDebug, /* print debug message */ -}; - -struct Note -{ - char msg[ERRMAX]; - int flag; /* whether system posted it */ -}; - -enum -{ - RENDLOG = 5, - RENDHASH = 1<<RENDLOG, /* Hash to lookup rendezvous tags */ - MNTLOG = 5, - MNTHASH = 1<<MNTLOG, /* Hash to walk mount table */ - NFD = 100, /* per process file descriptors */ - PGHLOG = 9, - PGHSIZE = 1<<PGHLOG, /* Page hash for image lookup */ -}; -#define REND(p,s) ((p)->rendhash[(s)&((1<<RENDLOG)-1)]) -#define MOUNTH(p,qid) ((p)->mnthash[(qid).path&((1<<MNTLOG)-1)]) - -struct Pgrp -{ - Ref ref; /* also used as a lock when mounting */ - int noattach; - ulong pgrpid; - QLock debug; /* single access via devproc.c */ - RWlock ns; /* Namespace n read/one write lock */ - Mhead *mnthash[MNTHASH]; -}; - -struct Rgrp -{ - Ref ref; - Proc *rendhash[RENDHASH]; /* Rendezvous tag hash */ -}; - -struct Egrp -{ - Ref ref; - RWlock lk; - Evalue **ent; - int nent; - int ment; - ulong path; /* qid.path of next Evalue to be allocated */ - ulong vers; /* of Egrp */ -}; - -struct Evalue -{ - char *name; - char *value; - int len; - Evalue *link; - Qid qid; -}; - -struct Fgrp -{ - Ref ref; - Chan **fd; - int nfd; /* number allocated */ - int maxfd; /* highest fd in use */ - int exceed; /* debugging */ -}; - -enum -{ - DELTAFD = 20, /* incremental increase in Fgrp.fd's */ - NERR = 20 -}; - -typedef uvlong Ticks; - -enum -{ - Running, - Rendezvous, - Wakeme, -}; - -struct Proc -{ - uint state; - uint mach; - - ulong pid; - ulong parentpid; - - Pgrp *pgrp; /* Process group for namespace */ - Fgrp *fgrp; /* File descriptor group */ - Rgrp *rgrp; - - Lock rlock; /* sync sleep/wakeup with postnote */ - Rendez *r; /* rendezvous point slept on */ - Rendez sleep; /* place for syssleep/debug */ - int notepending; /* note issued but not acted on */ - int kp; /* true if a kernel process */ - - void* rendtag; /* Tag for rendezvous */ - void* rendval; /* Value for rendezvous */ - Proc *rendhash; /* Hash list for tag values */ - - int nerrlab; - Label errlab[NERR]; - char user[KNAMELEN]; - char *syserrstr; /* last error from a system call, errbuf0 or 1 */ - char *errstr; /* reason we're unwinding the error stack, errbuf1 or 0 */ - char errbuf0[ERRMAX]; - char errbuf1[ERRMAX]; - char genbuf[128]; /* buffer used e.g. for last name element from namec */ - char text[KNAMELEN]; - - Chan *slash; - Chan *dot; - - Proc *qnext; - - void (*fn)(void*); - void *arg; - - char oproc[1024]; /* reserved for os */ - -}; - -enum -{ - PRINTSIZE = 256, - MAXCRYPT = 127, - NUMSIZE = 12, /* size of formatted number */ - MB = (1024*1024), - READSTR = 1000, /* temporary buffer size for device reads */ -}; - -extern char* conffile; -extern int cpuserver; -extern Dev* devtab[]; -extern char *eve; -extern char hostdomain[]; -extern uchar initcode[]; -extern Queue* kbdq; -extern Queue* kprintoq; -extern Ref noteidalloc; -extern Palloc palloc; -extern Queue *serialoq; -extern char* statename[]; -extern int nsyscall; -extern char *sysname; -extern uint qiomaxatomic; -extern Conf conf; -enum -{ - LRESPROF = 3, -}; - -/* - * action log - */ -struct Log { - Lock lk; - int opens; - char* buf; - char *end; - char *rptr; - int len; - int nlog; - int minread; - - int logmask; /* mask of things to debug */ - - QLock readq; - Rendez readr; -}; - -struct Logflag { - char* name; - int mask; -}; - -enum -{ - NCMDFIELD = 128 -}; - -struct Cmdbuf -{ - char *buf; - char **f; - int nf; -}; - -struct Cmdtab -{ - int index; /* used by client to switch on result */ - char *cmd; /* command name */ - int narg; /* expected #args; 0 ==> variadic */ -}; - -/* queue state bits, Qmsg, Qcoalesce, and Qkick can be set in qopen */ -enum -{ - /* Queue.state */ - Qstarve = (1<<0), /* consumer starved */ - Qmsg = (1<<1), /* message stream */ - Qclosed = (1<<2), /* queue has been closed/hungup */ - Qflow = (1<<3), /* producer flow controlled */ - Qcoalesce = (1<<4), /* coallesce packets on read */ - Qkick = (1<<5), /* always call the kick routine after qwrite */ -}; - -#define DEVDOTDOT -1 - -extern Proc *_getproc(void); -extern void _setproc(Proc*); -#define up (_getproc()) diff --git a/sys/src/cmd/unix/drawterm/kern/data.c b/sys/src/cmd/unix/drawterm/kern/data.c deleted file mode 100644 index 735e5e0c4..000000000 --- a/sys/src/cmd/unix/drawterm/kern/data.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -Proc *up; -Conf conf = -{ - 1, - 100, - 0, - 1024*1024*1024, - 1024*1024*1024, - 1024*1024*1024, - 1024*1024*1024, - 1024*1024*1024, - 1024*1024*1024, - 1024*1024*1024, - 1024*1024*1024, - 1024*1024*1024, - 1024*1024*1024, - 1024*1024*1024, - 1024*1024*1024, - 0, -}; - -char *eve = "eve"; -ulong kerndate; -int cpuserver; -char hostdomain[] = "drawterm.net"; diff --git a/sys/src/cmd/unix/drawterm/kern/dev.c b/sys/src/cmd/unix/drawterm/kern/dev.c deleted file mode 100644 index 83bf624f3..000000000 --- a/sys/src/cmd/unix/drawterm/kern/dev.c +++ /dev/null @@ -1,468 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -extern ulong kerndate; - -void -mkqid(Qid *q, vlong path, ulong vers, int type) -{ - q->type = type; - q->vers = vers; - q->path = path; -} - -int -devno(int c, int user) -{ - int i; - - for(i = 0; devtab[i] != nil; i++) { - if(devtab[i]->dc == c) - return i; - } - if(user == 0) - panic("devno %C 0x%ux", c, c); - - return -1; -} - -void -devdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db) -{ - db->name = n; - if(c->flag&CMSG) - qid.type |= QTMOUNT; - db->qid = qid; - db->type = devtab[c->type]->dc; - db->dev = c->dev; - db->mode = perm; - db->mode |= qid.type << 24; - db->atime = seconds(); - db->mtime = kerndate; - db->length = length; - db->uid = user; - db->gid = eve; - db->muid = user; -} - -/* - * (here, Devgen is the prototype; devgen is the function in dev.c.) - * - * a Devgen is expected to return the directory entry for ".." - * if you pass it s==DEVDOTDOT (-1). otherwise... - * - * there are two contradictory rules. - * - * (i) if c is a directory, a Devgen is expected to list its children - * as you iterate s. - * - * (ii) whether or not c is a directory, a Devgen is expected to list - * its siblings as you iterate s. - * - * devgen always returns the list of children in the root - * directory. thus it follows (i) when c is the root and (ii) otherwise. - * many other Devgens follow (i) when c is a directory and (ii) otherwise. - * - * devwalk assumes (i). it knows that devgen breaks (i) - * for children that are themselves directories, and explicitly catches them. - * - * devstat assumes (ii). if the Devgen in question follows (i) - * for this particular c, devstat will not find the necessary info. - * with our particular Devgen functions, this happens only for - * directories, so devstat makes something up, assuming - * c->name, c->qid, eve, DMDIR|0555. - * - * devdirread assumes (i). the callers have to make sure - * that the Devgen satisfies (i) for the chan being read. - */ -/* - * the zeroth element of the table MUST be the directory itself for .. -*/ -int -devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp) -{ - if(tab == 0) - return -1; - if(i == DEVDOTDOT){ - /* nothing */ - }else if(name){ - for(i=1; i<ntab; i++) - if(strcmp(tab[i].name, name) == 0) - break; - if(i==ntab) - return -1; - tab += i; - }else{ - /* skip over the first element, that for . itself */ - i++; - if(i >= ntab) - return -1; - tab += i; - } - devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp); - return 1; -} - -void -devreset(void) -{ -} - -void -devinit(void) -{ -} - -void -devshutdown(void) -{ -} - -Chan* -devattach(int tc, char *spec) -{ - Chan *c; - char *buf; - - c = newchan(); - mkqid(&c->qid, 0, 0, QTDIR); - c->type = devno(tc, 0); - if(spec == nil) - spec = ""; - buf = smalloc(4+strlen(spec)+1); - sprint(buf, "#%C%s", tc, spec); - c->name = newcname(buf); - free(buf); - return c; -} - - -Chan* -devclone(Chan *c) -{ - Chan *nc; - - if(c->flag & COPEN) - panic("clone of open file type %C\n", devtab[c->type]->dc); - - nc = newchan(); - - nc->type = c->type; - nc->dev = c->dev; - nc->mode = c->mode; - nc->qid = c->qid; - nc->offset = c->offset; - nc->umh = nil; - nc->mountid = c->mountid; - nc->aux = c->aux; - nc->pgrpid = c->pgrpid; - nc->mid = c->mid; - nc->mqid = c->mqid; - nc->mcp = c->mcp; - return nc; -} - -Walkqid* -devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen) -{ - int i, j, alloc; - Walkqid *wq; - char *n; - Dir dir; - - if(nname > 0) - isdir(c); - - alloc = 0; - wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); - if(waserror()){ - if(alloc && wq->clone!=nil) - cclose(wq->clone); - free(wq); - return nil; - } - if(nc == nil){ - nc = devclone(c); - nc->type = 0; /* device doesn't know about this channel yet */ - alloc = 1; - } - wq->clone = nc; - - for(j=0; j<nname; j++){ - if(!(nc->qid.type&QTDIR)){ - if(j==0) - error(Enotdir); - goto Done; - } - n = name[j]; - if(strcmp(n, ".") == 0){ - Accept: - wq->qid[wq->nqid++] = nc->qid; - continue; - } - if(strcmp(n, "..") == 0){ - if((*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir) != 1){ - print("devgen walk .. in dev%s %llux broken\n", - devtab[nc->type]->name, nc->qid.path); - error("broken devgen"); - } - nc->qid = dir.qid; - goto Accept; - } - /* - * Ugly problem: If we're using devgen, make sure we're - * walking the directory itself, represented by the first - * entry in the table, and not trying to step into a sub- - * directory of the table, e.g. /net/net. Devgen itself - * should take care of the problem, but it doesn't have - * the necessary information (that we're doing a walk). - */ - if(gen==devgen && nc->qid.path!=tab[0].qid.path) - goto Notfound; - for(i=0;; i++) { - switch((*gen)(nc, n, tab, ntab, i, &dir)){ - case -1: - Notfound: - if(j == 0) - error(Enonexist); - kstrcpy(up->errstr, Enonexist, ERRMAX); - goto Done; - case 0: - continue; - case 1: - if(strcmp(n, dir.name) == 0){ - nc->qid = dir.qid; - goto Accept; - } - continue; - } - } - } - /* - * We processed at least one name, so will return some data. - * If we didn't process all nname entries succesfully, we drop - * the cloned channel and return just the Qids of the walks. - */ -Done: - poperror(); - if(wq->nqid < nname){ - if(alloc) - cclose(wq->clone); - wq->clone = nil; - }else if(wq->clone){ - /* attach cloned channel to same device */ - wq->clone->type = c->type; - } - return wq; -} - -int -devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen) -{ - int i; - Dir dir; - char *p, *elem; - - for(i=0;; i++) - switch((*gen)(c, nil, tab, ntab, i, &dir)){ - case -1: - if(c->qid.type & QTDIR){ - if(c->name == nil) - elem = "???"; - else if(strcmp(c->name->s, "/") == 0) - elem = "/"; - else - for(elem=p=c->name->s; *p; p++) - if(*p == '/') - elem = p+1; - devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir); - n = convD2M(&dir, db, n); - if(n == 0) - error(Ebadarg); - return n; - } - print("devstat %C %llux\n", devtab[c->type]->dc, c->qid.path); - - error(Enonexist); - case 0: - break; - case 1: - if(c->qid.path == dir.qid.path) { - if(c->flag&CMSG) - dir.mode |= DMMOUNT; - n = convD2M(&dir, db, n); - if(n == 0) - error(Ebadarg); - return n; - } - break; - } - error(Egreg); /* not reached? */ - return -1; -} - -long -devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen) -{ - long m, dsz; - struct{ - Dir d; - char slop[100]; - }dir; - - for(m=0; m<n; c->dri++) { - switch((*gen)(c, nil, tab, ntab, c->dri, &dir.d)){ - case -1: - return m; - - case 0: - break; - - case 1: - dsz = convD2M(&dir.d, (uchar*)d, n-m); - if(dsz <= BIT16SZ){ /* <= not < because this isn't stat; read is stuck */ - if(m == 0) - error(Eshort); - return m; - } - m += dsz; - d += dsz; - break; - } - } - - return m; -} - -/* - * error(Eperm) if open permission not granted for up->user. - */ -void -devpermcheck(char *fileuid, ulong perm, int omode) -{ - ulong t; - static int access[] = { 0400, 0200, 0600, 0100 }; - - if(strcmp(up->user, fileuid) == 0) - perm <<= 0; - else - if(strcmp(up->user, eve) == 0) - perm <<= 3; - else - perm <<= 6; - - t = access[omode&3]; - if((t&perm) != t) - error(Eperm); -} - -Chan* -devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen) -{ - int i; - Dir dir; - - for(i=0;; i++) { - switch((*gen)(c, nil, tab, ntab, i, &dir)){ - case -1: - goto Return; - case 0: - break; - case 1: - if(c->qid.path == dir.qid.path) { - devpermcheck(dir.uid, dir.mode, omode); - goto Return; - } - break; - } - } -Return: - c->offset = 0; - if((c->qid.type&QTDIR) && omode!=OREAD) - error(Eperm); - c->mode = openmode(omode); - c->flag |= COPEN; - return c; -} - -void -devcreate(Chan *c, char *name, int mode, ulong perm) -{ - USED(c); - USED(name); - USED(mode); - USED(perm); - - error(Eperm); -} - -Block* -devbread(Chan *c, long n, ulong offset) -{ - Block *bp; - - bp = allocb(n); - if(bp == 0) - error(Enomem); - if(waserror()) { - freeb(bp); - nexterror(); - } - bp->wp += devtab[c->type]->read(c, bp->wp, n, offset); - poperror(); - return bp; -} - -long -devbwrite(Chan *c, Block *bp, ulong offset) -{ - long n; - - if(waserror()) { - freeb(bp); - nexterror(); - } - n = devtab[c->type]->write(c, bp->rp, BLEN(bp), offset); - poperror(); - freeb(bp); - - return n; -} - -void -devremove(Chan *c) -{ - USED(c); - error(Eperm); -} - -int -devwstat(Chan *c, uchar *a, int n) -{ - USED(c); - USED(a); - USED(n); - - error(Eperm); - return 0; -} - -void -devpower(int a) -{ - USED(a); - error(Eperm); -} - -int -devconfig(int a, char *b, DevConf *c) -{ - USED(a); - USED(b); - USED(c); - error(Eperm); - return 0; -} diff --git a/sys/src/cmd/unix/drawterm/kern/devaudio-none.c b/sys/src/cmd/unix/drawterm/kern/devaudio-none.c deleted file mode 100644 index 57a536651..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devaudio-none.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Linux and BSD - */ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" -#include "devaudio.h" - -/* maybe this should return -1 instead of sysfatal */ -void -audiodevopen(void) -{ - error("no audio support"); -} - -void -audiodevclose(void) -{ - error("no audio support"); -} - -int -audiodevread(void *a, int n) -{ - error("no audio support"); - return -1; -} - -int -audiodevwrite(void *a, int n) -{ - error("no audio support"); - return -1; -} - -void -audiodevsetvol(int what, int left, int right) -{ - error("no audio support"); -} - -void -audiodevgetvol(int what, int *left, int *right) -{ - error("no audio support"); -} - diff --git a/sys/src/cmd/unix/drawterm/kern/devaudio-unix.c b/sys/src/cmd/unix/drawterm/kern/devaudio-unix.c deleted file mode 100644 index ad5af7458..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devaudio-unix.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Linux and BSD - */ -#include <sys/ioctl.h> -#ifdef __linux__ -#include <linux/soundcard.h> -#else -#include <sys/soundcard.h> -#endif -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" -#include "devaudio.h" - -enum -{ - Channels = 2, - Rate = 44100, - Bits = 16, - Bigendian = 1, -}; - -static int afd = -1; -static int cfd= -1; -static int speed; - -/* maybe this should return -1 instead of sysfatal */ -void -audiodevopen(void) -{ - int t; - ulong ul; - - afd = -1; - cfd = -1; - if((afd = open("/dev/dsp", OWRITE)) < 0) - goto err; - if((cfd = open("/dev/mixer", ORDWR)) < 0) - goto err; - - t = Bits; - if(ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &t) < 0) - goto err; - - t = Channels-1; - if(ioctl(afd, SNDCTL_DSP_STEREO, &t) < 0) - goto err; - - speed = Rate; - ul = Rate; - if(ioctl(afd, SNDCTL_DSP_SPEED, &ul) < 0) - goto err; - - return; - -err: - if(afd >= 0) - close(afd); - afd = -1; - oserror(); -} - -void -audiodevclose(void) -{ - close(afd); - close(cfd); - afd = -1; - cfd = -1; -} - -static struct { - int id9; - int id; -} names[] = { - Vaudio, SOUND_MIXER_VOLUME, - Vbass, SOUND_MIXER_BASS, - Vtreb, SOUND_MIXER_TREBLE, - Vline, SOUND_MIXER_LINE, - Vpcm, SOUND_MIXER_PCM, - Vsynth, SOUND_MIXER_SYNTH, - Vcd, SOUND_MIXER_CD, - Vmic, SOUND_MIXER_MIC, -// "record", SOUND_MIXER_RECLEV, -// "mix", SOUND_MIXER_IMIX, -// "pcm2", SOUND_MIXER_ALTPCM, - Vspeaker, SOUND_MIXER_SPEAKER -// "line1", SOUND_MIXER_LINE1, -// "line2", SOUND_MIXER_LINE2, -// "line3", SOUND_MIXER_LINE3, -// "digital1", SOUND_MIXER_DIGITAL1, -// "digital2", SOUND_MIXER_DIGITAL2, -// "digital3", SOUND_MIXER_DIGITAL3, -// "phonein", SOUND_MIXER_PHONEIN, -// "phoneout", SOUND_MIXER_PHONEOUT, -// "radio", SOUND_MIXER_RADIO, -// "video", SOUND_MIXER_VIDEO, -// "monitor", SOUND_MIXER_MONITOR, -// "igain", SOUND_MIXER_IGAIN, -// "ogain", SOUND_MIXER_OGAIN, -}; - -static int -lookname(int id9) -{ - int i; - - for(i=0; i<nelem(names); i++) - if(names[i].id9 == id9) - return names[i].id; - return -1; -} - -void -audiodevsetvol(int what, int left, int right) -{ - int id; - ulong x; - int can, v; - - if(cfd < 0) - error("audio device not open"); - if(what == Vspeed){ - x = left; - if(ioctl(afd, SNDCTL_DSP_SPEED, &x) < 0) - oserror(); - speed = x; - return; - } - if((id = lookname(what)) < 0) - return; - if(ioctl(cfd, SOUND_MIXER_READ_DEVMASK, &can) < 0) - can = ~0; - if(!(can & (1<<id))) - return; - v = left | (right<<8); - if(ioctl(cfd, MIXER_WRITE(id), &v) < 0) - oserror(); -} - -void -audiodevgetvol(int what, int *left, int *right) -{ - int id; - int can, v; - - if(cfd < 0) - error("audio device not open"); - if(what == Vspeed){ - *left = *right = speed; - return; - } - if((id = lookname(what)) < 0) - return; - if(ioctl(cfd, SOUND_MIXER_READ_DEVMASK, &can) < 0) - can = ~0; - if(!(can & (1<<id))) - return; - if(ioctl(cfd, MIXER_READ(id), &v) < 0) - oserror(); - *left = v&0xFF; - *right = (v>>8)&0xFF; -} - -int -audiodevwrite(void *v, int n) -{ - int m, tot; - - for(tot=0; tot<n; tot+=m) - if((m = write(afd, (uchar*)v+tot, n-tot)) <= 0) - oserror(); - return tot; -} - -int -audiodevread(void *v, int n) -{ - error("no reading"); - return -1; -} diff --git a/sys/src/cmd/unix/drawterm/kern/devaudio.c b/sys/src/cmd/unix/drawterm/kern/devaudio.c deleted file mode 100644 index b6d0cc512..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devaudio.c +++ /dev/null @@ -1,372 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" -#include "devaudio.h" - -enum -{ - Qdir = 0, - Qaudio, - Qvolume, - - Aclosed = 0, - Aread, - Awrite, - - Speed = 44100, - Ncmd = 50, /* max volume command words */ -}; - -Dirtab -audiodir[] = -{ - ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, - "audio", {Qaudio}, 0, 0666, - "volume", {Qvolume}, 0, 0666, -}; - -static struct -{ - QLock lk; - Rendez vous; - int amode; /* Aclosed/Aread/Awrite for /audio */ -} audio; - -#define aqlock(a) qlock(&(a)->lk) -#define aqunlock(a) qunlock(&(a)->lk) - -static struct -{ - char* name; - int flag; - int ilval; /* initial values */ - int irval; -} volumes[] = -{ - "audio", Fout, 50, 50, - "synth", Fin|Fout, 0, 0, - "cd", Fin|Fout, 0, 0, - "line", Fin|Fout, 0, 0, - "mic", Fin|Fout|Fmono, 0, 0, - "speaker", Fout|Fmono, 0, 0, - - "treb", Fout, 50, 50, - "bass", Fout, 50, 50, - - "speed", Fin|Fout|Fmono, Speed, Speed, - 0 -}; - -static char Emode[] = "illegal open mode"; -static char Evolume[] = "illegal volume specifier"; - -static void -resetlevel(void) -{ - int i; - - for(i=0; volumes[i].name; i++) - audiodevsetvol(i, volumes[i].ilval, volumes[i].irval); -} - -static void -audioinit(void) -{ -} - -static Chan* -audioattach(char *param) -{ - return devattach('A', param); -} - -static Walkqid* -audiowalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, audiodir, nelem(audiodir), devgen); -} - -static int -audiostat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, audiodir, nelem(audiodir), devgen); -} - -static Chan* -audioopen(Chan *c, int omode) -{ - int amode; - - switch((ulong)c->qid.path) { - default: - error(Eperm); - break; - - case Qvolume: - case Qdir: - break; - - case Qaudio: - amode = Awrite; - if((omode&7) == OREAD) - amode = Aread; - aqlock(&audio); - if(waserror()){ - aqunlock(&audio); - nexterror(); - } - if(audio.amode != Aclosed) - error(Einuse); - audiodevopen(); - audio.amode = amode; - poperror(); - aqunlock(&audio); - break; - } - c = devopen(c, omode, audiodir, nelem(audiodir), devgen); - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - - return c; -} - -static void -audioclose(Chan *c) -{ - switch((ulong)c->qid.path) { - default: - error(Eperm); - break; - - case Qdir: - case Qvolume: - break; - - case Qaudio: - if(c->flag & COPEN) { - aqlock(&audio); - audiodevclose(); - audio.amode = Aclosed; - aqunlock(&audio); - } - break; - } -} - -static long -audioread(Chan *c, void *v, long n, vlong off) -{ - int liv, riv, lov, rov; - long m; - char buf[300]; - int j; - ulong offset = off; - char *a; - - a = v; - switch((ulong)c->qid.path) { - default: - error(Eperm); - break; - - case Qdir: - return devdirread(c, a, n, audiodir, nelem(audiodir), devgen); - - case Qaudio: - if(audio.amode != Aread) - error(Emode); - aqlock(&audio); - if(waserror()){ - aqunlock(&audio); - nexterror(); - } - n = audiodevread(v, n); - poperror(); - aqunlock(&audio); - break; - - case Qvolume: - j = 0; - buf[0] = 0; - for(m=0; volumes[m].name; m++){ - audiodevgetvol(m, &lov, &rov); - liv = lov; - riv = rov; - j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name); - if((volumes[m].flag & Fmono) || (liv==riv && lov==rov)){ - if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov) - j += snprint(buf+j, sizeof(buf)-j, " %d", liv); - else{ - if(volumes[m].flag & Fin) - j += snprint(buf+j, sizeof(buf)-j, - " in %d", liv); - if(volumes[m].flag & Fout) - j += snprint(buf+j, sizeof(buf)-j, - " out %d", lov); - } - }else{ - if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && - liv==lov && riv==rov) - j += snprint(buf+j, sizeof(buf)-j, - " left %d right %d", - liv, riv); - else{ - if(volumes[m].flag & Fin) - j += snprint(buf+j, sizeof(buf)-j, - " in left %d right %d", - liv, riv); - if(volumes[m].flag & Fout) - j += snprint(buf+j, sizeof(buf)-j, - " out left %d right %d", - lov, rov); - } - } - j += snprint(buf+j, sizeof(buf)-j, "\n"); - } - return readstr(offset, a, n, buf); - } - return n; -} - -static long -audiowrite(Chan *c, void *vp, long n, vlong off) -{ - long m; - int i, v, left, right, in, out; - Cmdbuf *cb; - char *a; - - USED(off); - a = vp; - switch((ulong)c->qid.path) { - default: - error(Eperm); - break; - - case Qvolume: - v = Vaudio; - left = 1; - right = 1; - in = 1; - out = 1; - cb = parsecmd(vp, n); - if(waserror()){ - free(cb); - nexterror(); - } - - for(i = 0; i < cb->nf; i++){ - /* - * a number is volume - */ - if(cb->f[i][0] >= '0' && cb->f[i][0] <= '9') { - m = strtoul(cb->f[i], 0, 10); - if(!out) - goto cont0; - if(left && right) - audiodevsetvol(v, m, m); - else if(left) - audiodevsetvol(v, m, -1); - else if(right) - audiodevsetvol(v, -1, m); - goto cont0; - } - - for(m=0; volumes[m].name; m++) { - if(strcmp(cb->f[i], volumes[m].name) == 0) { - v = m; - in = 1; - out = 1; - left = 1; - right = 1; - goto cont0; - } - } - - if(strcmp(cb->f[i], "reset") == 0) { - resetlevel(); - goto cont0; - } - if(strcmp(cb->f[i], "in") == 0) { - in = 1; - out = 0; - goto cont0; - } - if(strcmp(cb->f[i], "out") == 0) { - in = 0; - out = 1; - goto cont0; - } - if(strcmp(cb->f[i], "left") == 0) { - left = 1; - right = 0; - goto cont0; - } - if(strcmp(cb->f[i], "right") == 0) { - left = 0; - right = 1; - goto cont0; - } - error(Evolume); - break; - cont0:; - } - free(cb); - poperror(); - break; - - case Qaudio: - if(audio.amode != Awrite) - error(Emode); - aqlock(&audio); - if(waserror()){ - aqunlock(&audio); - nexterror(); - } - n = audiodevwrite(vp, n); - poperror(); - aqunlock(&audio); - break; - } - return n; -} - -void -audioswab(uchar *a, uint n) -{ - ulong *p, *ep, b; - - p = (ulong*)a; - ep = p + (n>>2); - while(p < ep) { - b = *p; - b = (b>>24) | (b<<24) | - ((b&0xff0000) >> 8) | - ((b&0x00ff00) << 8); - *p++ = b; - } -} - -Dev audiodevtab = { - 'A', - "audio", - - devreset, - audioinit, - devshutdown, - audioattach, - audiowalk, - audiostat, - audioopen, - devcreate, - audioclose, - audioread, - devbread, - audiowrite, - devbwrite, - devremove, - devwstat, -}; diff --git a/sys/src/cmd/unix/drawterm/kern/devaudio.h b/sys/src/cmd/unix/drawterm/kern/devaudio.h deleted file mode 100644 index e6cc7ed21..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devaudio.h +++ /dev/null @@ -1,25 +0,0 @@ -enum -{ - Fmono = 1, - Fin = 2, - Fout = 4, - - Vaudio = 0, - Vsynth, - Vcd, - Vline, - Vmic, - Vspeaker, - Vtreb, - Vbass, - Vspeed, - Vpcm, - Nvol, -}; - -void audiodevopen(void); -void audiodevclose(void); -int audiodevread(void*, int); -int audiodevwrite(void*, int); -void audiodevgetvol(int, int*, int*); -void audiodevsetvol(int, int, int); diff --git a/sys/src/cmd/unix/drawterm/kern/devcons.c b/sys/src/cmd/unix/drawterm/kern/devcons.c deleted file mode 100644 index bd80d6eae..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devcons.c +++ /dev/null @@ -1,1193 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#include "keyboard.h" - -void (*consdebug)(void) = 0; -void (*screenputs)(char*, int) = 0; - -Queue* kbdq; /* unprocessed console input */ -Queue* lineq; /* processed console input */ -Queue* serialoq; /* serial console output */ -Queue* kprintoq; /* console output, for /dev/kprint */ -long kprintinuse; /* test and set whether /dev/kprint is open */ -Lock kprintlock; -int iprintscreenputs = 0; - -int panicking; - -struct -{ - int exiting; - int machs; -} active; - -static struct -{ - QLock lk; - - int raw; /* true if we shouldn't process input */ - int ctl; /* number of opens to the control file */ - int x; /* index into line */ - char line[1024]; /* current input line */ - - int count; - int ctlpoff; - - /* a place to save up characters at interrupt time before dumping them in the queue */ - Lock lockputc; - char istage[1024]; - char *iw; - char *ir; - char *ie; -} kbd = { - { 0 }, - 0, - 0, - 0, - { 0 }, - 0, - 0, - { 0 }, - { 0 }, - kbd.istage, - kbd.istage, - kbd.istage + sizeof(kbd.istage), -}; - -char *sysname; -vlong fasthz; - -static int readtime(ulong, char*, int); -static int readbintime(char*, int); -static int writetime(char*, int); -static int writebintime(char*, int); - -enum -{ - CMreboot, - CMpanic, -}; - -Cmdtab rebootmsg[] = -{ - CMreboot, "reboot", 0, - CMpanic, "panic", 0, -}; - -int -return0(void *v) -{ - return 0; -} - -void -printinit(void) -{ - lineq = qopen(2*1024, 0, 0, nil); - if(lineq == nil) - panic("printinit"); - qnoblock(lineq, 1); - - kbdq = qopen(4*1024, 0, 0, 0); - if(kbdq == nil) - panic("kbdinit"); - qnoblock(kbdq, 1); -} - -int -consactive(void) -{ - if(serialoq) - return qlen(serialoq) > 0; - return 0; -} - -void -prflush(void) -{ -/* - ulong now; - - now = m->ticks; - while(consactive()) - if(m->ticks - now >= HZ) - break; -*/ -} - -/* - * Print a string on the console. Convert \n to \r\n for serial - * line consoles. Locking of the queues is left up to the screen - * or uart code. Multi-line messages to serial consoles may get - * interspersed with other messages. - */ -static void -putstrn0(char *str, int n, int usewrite) -{ - /* - * if someone is reading /dev/kprint, - * put the message there. - * if not and there's an attached bit mapped display, - * put the message there. - * - * if there's a serial line being used as a console, - * put the message there. - */ - if(kprintoq != nil && !qisclosed(kprintoq)){ - if(usewrite) - qwrite(kprintoq, str, n); - else - qiwrite(kprintoq, str, n); - }else if(screenputs != 0) - screenputs(str, n); -} - -void -putstrn(char *str, int n) -{ - putstrn0(str, n, 0); -} - -int noprint; - -int -print(char *fmt, ...) -{ - int n; - va_list arg; - char buf[PRINTSIZE]; - - if(noprint) - return -1; - - va_start(arg, fmt); - n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; - va_end(arg); - putstrn(buf, n); - - return n; -} - -void -panic(char *fmt, ...) -{ - int n; - va_list arg; - char buf[PRINTSIZE]; - - kprintoq = nil; /* don't try to write to /dev/kprint */ - - if(panicking) - for(;;); - panicking = 1; - - splhi(); - strcpy(buf, "panic: "); - va_start(arg, fmt); - n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf; - va_end(arg); - buf[n] = '\n'; - uartputs(buf, n+1); - if(consdebug) - (*consdebug)(); - spllo(); - prflush(); - putstrn(buf, n+1); - dumpstack(); - - exit(1); -} - -int -pprint(char *fmt, ...) -{ - int n; - Chan *c; - va_list arg; - char buf[2*PRINTSIZE]; - - if(up == nil || up->fgrp == nil) - return 0; - - c = up->fgrp->fd[2]; - if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR)) - return 0; - n = sprint(buf, "%s %lud: ", up->text, up->pid); - va_start(arg, fmt); - n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf; - va_end(arg); - - if(waserror()) - return 0; - devtab[c->type]->write(c, buf, n, c->offset); - poperror(); - - lock(&c->ref.lk); - c->offset += n; - unlock(&c->ref.lk); - - return n; -} - -static void -echoscreen(char *buf, int n) -{ - char *e, *p; - char ebuf[128]; - int x; - - p = ebuf; - e = ebuf + sizeof(ebuf) - 4; - while(n-- > 0){ - if(p >= e){ - screenputs(ebuf, p - ebuf); - p = ebuf; - } - x = *buf++; - if(x == 0x15){ - *p++ = '^'; - *p++ = 'U'; - *p++ = '\n'; - } else - *p++ = x; - } - if(p != ebuf) - screenputs(ebuf, p - ebuf); -} - -static void -echoserialoq(char *buf, int n) -{ - char *e, *p; - char ebuf[128]; - int x; - - p = ebuf; - e = ebuf + sizeof(ebuf) - 4; - while(n-- > 0){ - if(p >= e){ - qiwrite(serialoq, ebuf, p - ebuf); - p = ebuf; - } - x = *buf++; - if(x == '\n'){ - *p++ = '\r'; - *p++ = '\n'; - } else if(x == 0x15){ - *p++ = '^'; - *p++ = 'U'; - *p++ = '\n'; - } else - *p++ = x; - } - if(p != ebuf) - qiwrite(serialoq, ebuf, p - ebuf); -} - -static void -echo(char *buf, int n) -{ - static int ctrlt; - int x; - char *e, *p; - - e = buf+n; - for(p = buf; p < e; p++){ - switch(*p){ - case 0x10: /* ^P */ - if(cpuserver && !kbd.ctlpoff){ - active.exiting = 1; - return; - } - break; - case 0x14: /* ^T */ - ctrlt++; - if(ctrlt > 2) - ctrlt = 2; - continue; - } - - if(ctrlt != 2) - continue; - - /* ^T escapes */ - ctrlt = 0; - switch(*p){ - case 'S': - x = splhi(); - dumpstack(); - procdump(); - splx(x); - return; - case 's': - dumpstack(); - return; - case 'x': - xsummary(); - ixsummary(); - mallocsummary(); - pagersummary(); - return; - case 'd': - if(consdebug == 0) - consdebug = rdb; - else - consdebug = 0; - print("consdebug now 0x%p\n", consdebug); - return; - case 'D': - if(consdebug == 0) - consdebug = rdb; - consdebug(); - return; - case 'p': - x = spllo(); - procdump(); - splx(x); - return; - case 'q': - scheddump(); - return; - case 'k': - killbig(); - return; - case 'r': - exit(0); - return; - } - } - - qproduce(kbdq, buf, n); - if(kbd.raw) - return; - if(screenputs != 0) - echoscreen(buf, n); - if(serialoq) - echoserialoq(buf, n); -} - -/* - * Called by a uart interrupt for console input. - * - * turn '\r' into '\n' before putting it into the queue. - */ -int -kbdcr2nl(Queue *q, int ch) -{ - char *next; - - USED(q); - ilock(&kbd.lockputc); /* just a mutex */ - if(ch == '\r' && !kbd.raw) - ch = '\n'; - next = kbd.iw+1; - if(next >= kbd.ie) - next = kbd.istage; - if(next != kbd.ir){ - *kbd.iw = ch; - kbd.iw = next; - } - iunlock(&kbd.lockputc); - return 0; -} -static -void -_kbdputc(int c) -{ - Rune r; - char buf[UTFmax]; - int n; - - r = c; - n = runetochar(buf, &r); - if(n == 0) - return; - echo(buf, n); -// kbd.c = r; -// qproduce(kbdq, buf, n); -} - -/* _kbdputc, but with compose translation */ -int -kbdputc(Queue *q, int c) -{ - int i; - static int collecting, nk; - static Rune kc[5]; - - if(c == Kalt){ - collecting = 1; - nk = 0; - return 0; - } - - if(!collecting){ - _kbdputc(c); - return 0; - } - - kc[nk++] = c; - c = latin1(kc, nk); - if(c < -1) /* need more keystrokes */ - return 0; - if(c != -1) /* valid sequence */ - _kbdputc(c); - else - for(i=0; i<nk; i++) - _kbdputc(kc[i]); - nk = 0; - collecting = 0; - - return 0; -} - - -enum{ - Qdir, - Qbintime, - Qcons, - Qconsctl, - Qcpunote, - Qcputime, - Qdrivers, - Qkprint, - Qhostdomain, - Qhostowner, - Qnull, - Qosversion, - Qpgrpid, - Qpid, - Qppid, - Qrandom, - Qreboot, - Qsecstore, - Qshowfile, - Qsnarf, - Qswap, - Qsysname, - Qsysstat, - Qtime, - Quser, - Qzero, -}; - -enum -{ - VLNUMSIZE= 22, -}; - -static Dirtab consdir[]={ - ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, - "bintime", {Qbintime}, 24, 0664, - "cons", {Qcons}, 0, 0660, - "consctl", {Qconsctl}, 0, 0220, - "cpunote", {Qcpunote}, 0, 0444, - "cputime", {Qcputime}, 6*NUMSIZE, 0444, - "drivers", {Qdrivers}, 0, 0444, - "hostdomain", {Qhostdomain}, DOMLEN, 0664, - "hostowner", {Qhostowner}, 0, 0664, - "kprint", {Qkprint, 0, QTEXCL}, 0, DMEXCL|0440, - "null", {Qnull}, 0, 0666, - "osversion", {Qosversion}, 0, 0444, - "pgrpid", {Qpgrpid}, NUMSIZE, 0444, - "pid", {Qpid}, NUMSIZE, 0444, - "ppid", {Qppid}, NUMSIZE, 0444, - "random", {Qrandom}, 0, 0444, - "reboot", {Qreboot}, 0, 0664, - "secstore", {Qsecstore}, 0, 0666, - "showfile", {Qshowfile}, 0, 0220, - "snarf", {Qsnarf}, 0, 0666, - "swap", {Qswap}, 0, 0664, - "sysname", {Qsysname}, 0, 0664, - "sysstat", {Qsysstat}, 0, 0666, - "time", {Qtime}, NUMSIZE+3*VLNUMSIZE, 0664, - "user", {Quser}, 0, 0666, - "zero", {Qzero}, 0, 0444, -}; - -char secstorebuf[65536]; -Dirtab *secstoretab = &consdir[Qsecstore]; -Dirtab *snarftab = &consdir[Qsnarf]; - -int -readnum(ulong off, char *buf, ulong n, ulong val, int size) -{ - char tmp[64]; - - snprint(tmp, sizeof(tmp), "%*.0lud", size-1, val); - tmp[size-1] = ' '; - if(off >= size) - return 0; - if(off+n > size) - n = size-off; - memmove(buf, tmp+off, n); - return n; -} - -int -readstr(ulong off, char *buf, ulong n, char *str) -{ - int size; - - size = strlen(str); - if(off >= size) - return 0; - if(off+n > size) - n = size-off; - memmove(buf, str+off, n); - return n; -} - -static void -consinit(void) -{ - todinit(); - randominit(); - /* - * at 115200 baud, the 1024 char buffer takes 56 ms to process, - * processing it every 22 ms should be fine - */ -/* addclock0link(kbdputcclock, 22); */ -} - -static Chan* -consattach(char *spec) -{ - return devattach('c', spec); -} - -static Walkqid* -conswalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen); -} - -static int -consstat(Chan *c, uchar *dp, int n) -{ - return devstat(c, dp, n, consdir, nelem(consdir), devgen); -} - -static Chan* -consopen(Chan *c, int omode) -{ - c->aux = nil; - c = devopen(c, omode, consdir, nelem(consdir), devgen); - switch((ulong)c->qid.path){ - case Qconsctl: - qlock(&kbd.lk); - kbd.ctl++; - qunlock(&kbd.lk); - break; - - case Qkprint: - lock(&kprintlock); - if(kprintinuse != 0){ - c->flag &= ~COPEN; - unlock(&kprintlock); - error(Einuse); - } - kprintinuse = 1; - unlock(&kprintlock); - if(kprintoq == nil){ - kprintoq = qopen(8*1024, Qcoalesce, 0, 0); - if(kprintoq == nil){ - c->flag &= ~COPEN; - error(Enomem); - } - qnoblock(kprintoq, 1); - }else - qreopen(kprintoq); - c->iounit = qiomaxatomic; - break; - - case Qsecstore: - if(omode == ORDWR) - error(Eperm); - if(omode != OREAD) - memset(secstorebuf, 0, sizeof secstorebuf); - break; - - case Qsnarf: - if(omode == ORDWR) - error(Eperm); - if(omode == OREAD) - c->aux = strdup(""); - else - c->aux = mallocz(SnarfSize, 1); - break; - } - return c; -} - -static void -consclose(Chan *c) -{ - switch((ulong)c->qid.path){ - /* last close of control file turns off raw */ - case Qconsctl: - if(c->flag&COPEN){ - qlock(&kbd.lk); - if(--kbd.ctl == 0) - kbd.raw = 0; - qunlock(&kbd.lk); - } - break; - - /* close of kprint allows other opens */ - case Qkprint: - if(c->flag & COPEN){ - kprintinuse = 0; - qhangup(kprintoq, nil); - } - break; - - case Qsnarf: - if(c->mode == OWRITE) - clipwrite(c->aux); - free(c->aux); - break; - } -} - -static long -consread(Chan *c, void *buf, long n, vlong off) -{ - char *b; - char tmp[128]; /* must be >= 6*NUMSIZE */ - char *cbuf = buf; - int ch, i, eol; - vlong offset = off; - - if(n <= 0) - return n; - switch((ulong)c->qid.path){ - case Qdir: - return devdirread(c, buf, n, consdir, nelem(consdir), devgen); - - case Qcons: - qlock(&kbd.lk); - if(waserror()) { - qunlock(&kbd.lk); - nexterror(); - } - if(kbd.raw) { - if(qcanread(lineq)) - n = qread(lineq, buf, n); - else { - /* read as much as possible */ - do { - i = qread(kbdq, cbuf, n); - cbuf += i; - n -= i; - } while (n>0 && qcanread(kbdq)); - n = cbuf - (char*)buf; - } - } else { - while(!qcanread(lineq)) { - qread(kbdq, &kbd.line[kbd.x], 1); - ch = kbd.line[kbd.x]; - eol = 0; - switch(ch){ - case '\b': - if(kbd.x) - kbd.x--; - break; - case 0x15: - kbd.x = 0; - break; - case '\n': - case 0x04: - eol = 1; - default: - kbd.line[kbd.x++] = ch; - break; - } - if(kbd.x == sizeof(kbd.line) || eol){ - if(ch == 0x04) - kbd.x--; - qwrite(lineq, kbd.line, kbd.x); - kbd.x = 0; - } - } - n = qread(lineq, buf, n); - } - qunlock(&kbd.lk); - poperror(); - return n; - - case Qcpunote: - sleep(&up->sleep, return0, nil); - - case Qcputime: - return 0; - - case Qkprint: - return qread(kprintoq, buf, n); - - case Qpgrpid: - return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE); - - case Qpid: - return readnum((ulong)offset, buf, n, up->pid, NUMSIZE); - - case Qppid: - return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE); - - case Qtime: - return readtime((ulong)offset, buf, n); - - case Qbintime: - return readbintime(buf, n); - - case Qhostowner: - return readstr((ulong)offset, buf, n, eve); - - case Qhostdomain: - return readstr((ulong)offset, buf, n, hostdomain); - - case Quser: - return readstr((ulong)offset, buf, n, up->user); - - case Qnull: - return 0; - - case Qsnarf: - if(offset == 0){ - free(c->aux); - c->aux = clipread(); - } - if(c->aux == nil) - return 0; - return readstr(offset, buf, n, c->aux); - - case Qsecstore: - return readstr(offset, buf, n, secstorebuf); - - case Qsysstat: - return 0; - - case Qswap: - return 0; - - case Qsysname: - if(sysname == nil) - return 0; - return readstr((ulong)offset, buf, n, sysname); - - case Qrandom: - return randomread(buf, n); - - case Qdrivers: - b = malloc(READSTR); - if(b == nil) - error(Enomem); - n = 0; - for(i = 0; devtab[i] != nil; i++) - n += snprint(b+n, READSTR-n, "#%C %s\n", devtab[i]->dc, devtab[i]->name); - if(waserror()){ - free(b); - nexterror(); - } - n = readstr((ulong)offset, buf, n, b); - free(b); - poperror(); - return n; - - case Qzero: - memset(buf, 0, n); - return n; - - case Qosversion: - snprint(tmp, sizeof tmp, "2000"); - n = readstr((ulong)offset, buf, n, tmp); - return n; - - default: - print("consread 0x%llux\n", c->qid.path); - error(Egreg); - } - return -1; /* never reached */ -} - -static long -conswrite(Chan *c, void *va, long n, vlong off) -{ - char buf[256]; - long l, bp; - char *a = va; - int fd; - Chan *swc; - ulong offset = off; - Cmdbuf *cb; - Cmdtab *ct; - - switch((ulong)c->qid.path){ - case Qcons: - /* - * Can't page fault in putstrn, so copy the data locally. - */ - l = n; - while(l > 0){ - bp = l; - if(bp > sizeof buf) - bp = sizeof buf; - memmove(buf, a, bp); - putstrn0(buf, bp, 1); - a += bp; - l -= bp; - } - break; - - case Qconsctl: - if(n >= sizeof(buf)) - n = sizeof(buf)-1; - strncpy(buf, a, n); - buf[n] = 0; - for(a = buf; a;){ - if(strncmp(a, "rawon", 5) == 0){ - qlock(&kbd.lk); - if(kbd.x){ - qwrite(kbdq, kbd.line, kbd.x); - kbd.x = 0; - } - kbd.raw = 1; - qunlock(&kbd.lk); - } else if(strncmp(a, "rawoff", 6) == 0){ - qlock(&kbd.lk); - kbd.raw = 0; - kbd.x = 0; - qunlock(&kbd.lk); - } else if(strncmp(a, "ctlpon", 6) == 0){ - kbd.ctlpoff = 0; - } else if(strncmp(a, "ctlpoff", 7) == 0){ - kbd.ctlpoff = 1; - } - if((a = strchr(a, ' '))) - a++; - } - break; - - case Qtime: - if(!iseve()) - error(Eperm); - return writetime(a, n); - - case Qbintime: - if(!iseve()) - error(Eperm); - return writebintime(a, n); - - case Qhostowner: - return hostownerwrite(a, n); - - case Qhostdomain: - return hostdomainwrite(a, n); - - case Quser: - return userwrite(a, n); - - case Qnull: - break; - - case Qreboot: - if(!iseve()) - error(Eperm); - cb = parsecmd(a, n); - - if(waserror()) { - free(cb); - nexterror(); - } - ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg)); - switch(ct->index) { - case CMreboot: - rebootcmd(cb->nf-1, cb->f+1); - break; - case CMpanic: - panic("/dev/reboot"); - } - poperror(); - free(cb); - break; - - case Qsecstore: - if(offset >= sizeof secstorebuf || offset+n+1 >= sizeof secstorebuf) - error(Etoobig); - secstoretab->qid.vers++; - memmove(secstorebuf+offset, va, n); - return n; - - case Qshowfile: - return showfilewrite(a, n); - - case Qsnarf: - if(offset >= SnarfSize || offset+n >= SnarfSize) - error(Etoobig); - snarftab->qid.vers++; - memmove((uchar*)c->aux+offset, va, n); - return n; - - case Qsysstat: - n = 0; - break; - - case Qswap: - if(n >= sizeof buf) - error(Egreg); - memmove(buf, va, n); /* so we can NUL-terminate */ - buf[n] = 0; - /* start a pager if not already started */ - if(strncmp(buf, "start", 5) == 0){ - kickpager(); - break; - } - if(cpuserver && !iseve()) - error(Eperm); - if(buf[0]<'0' || '9'<buf[0]) - error(Ebadarg); - fd = strtoul(buf, 0, 0); - swc = fdtochan(fd, -1, 1, 1); - setswapchan(swc); - break; - - case Qsysname: - if(offset != 0) - error(Ebadarg); - if(n <= 0 || n >= sizeof buf) - error(Ebadarg); - strncpy(buf, a, n); - buf[n] = 0; - if(buf[n-1] == '\n') - buf[n-1] = 0; - kstrdup(&sysname, buf); - break; - - default: - print("conswrite: 0x%llux\n", c->qid.path); - error(Egreg); - } - return n; -} - -Dev consdevtab = { - 'c', - "cons", - - devreset, - consinit, - devshutdown, - consattach, - conswalk, - consstat, - consopen, - devcreate, - consclose, - consread, - devbread, - conswrite, - devbwrite, - devremove, - devwstat, -}; - -static uvlong uvorder = (uvlong) 0x0001020304050607ULL; - -static uchar* -le2vlong(vlong *to, uchar *f) -{ - uchar *t, *o; - int i; - - t = (uchar*)to; - o = (uchar*)&uvorder; - for(i = 0; i < sizeof(vlong); i++) - t[o[i]] = f[i]; - return f+sizeof(vlong); -} - -static uchar* -vlong2le(uchar *t, vlong from) -{ - uchar *f, *o; - int i; - - f = (uchar*)&from; - o = (uchar*)&uvorder; - for(i = 0; i < sizeof(vlong); i++) - t[i] = f[o[i]]; - return t+sizeof(vlong); -} - -static long order = 0x00010203; - -static uchar* -le2long(long *to, uchar *f) -{ - uchar *t, *o; - int i; - - t = (uchar*)to; - o = (uchar*)ℴ - for(i = 0; i < sizeof(long); i++) - t[o[i]] = f[i]; - return f+sizeof(long); -} - -/* -static uchar* -long2le(uchar *t, long from) -{ - uchar *f, *o; - int i; - - f = (uchar*)&from; - o = (uchar*)ℴ - for(i = 0; i < sizeof(long); i++) - t[i] = f[o[i]]; - return t+sizeof(long); -} -*/ - -char *Ebadtimectl = "bad time control"; - -/* - * like the old #c/time but with added info. Return - * - * secs nanosecs fastticks fasthz - */ -static int -readtime(ulong off, char *buf, int n) -{ - vlong nsec, ticks; - long sec; - char str[7*NUMSIZE]; - - nsec = todget(&ticks); - if(fasthz == (vlong)0) - fastticks((uvlong*)&fasthz); - sec = nsec/((uvlong) 1000000000); - snprint(str, sizeof(str), "%*.0lud %*.0llud %*.0llud %*.0llud ", - NUMSIZE-1, sec, - VLNUMSIZE-1, nsec, - VLNUMSIZE-1, ticks, - VLNUMSIZE-1, fasthz); - return readstr(off, buf, n, str); -} - -/* - * set the time in seconds - */ -static int -writetime(char *buf, int n) -{ - char b[13]; - long i; - vlong now; - - if(n >= sizeof(b)) - error(Ebadtimectl); - strncpy(b, buf, n); - b[n] = 0; - i = strtol(b, 0, 0); - if(i <= 0) - error(Ebadtimectl); - now = i*((vlong) 1000000000); - todset(now, 0, 0); - return n; -} - -/* - * read binary time info. all numbers are little endian. - * ticks and nsec are syncronized. - */ -static int -readbintime(char *buf, int n) -{ - int i; - vlong nsec, ticks; - uchar *b = (uchar*)buf; - - i = 0; - if(fasthz == (vlong)0) - fastticks((uvlong*)&fasthz); - nsec = todget(&ticks); - if(n >= 3*sizeof(uvlong)){ - vlong2le(b+2*sizeof(uvlong), fasthz); - i += sizeof(uvlong); - } - if(n >= 2*sizeof(uvlong)){ - vlong2le(b+sizeof(uvlong), ticks); - i += sizeof(uvlong); - } - if(n >= 8){ - vlong2le(b, nsec); - i += sizeof(vlong); - } - return i; -} - -/* - * set any of the following - * - time in nsec - * - nsec trim applied over some seconds - * - clock frequency - */ -static int -writebintime(char *buf, int n) -{ - uchar *p; - vlong delta; - long period; - - n--; - p = (uchar*)buf + 1; - switch(*buf){ - case 'n': - if(n < sizeof(vlong)) - error(Ebadtimectl); - le2vlong(&delta, p); - todset(delta, 0, 0); - break; - case 'd': - if(n < sizeof(vlong)+sizeof(long)) - error(Ebadtimectl); - p = le2vlong(&delta, p); - le2long(&period, p); - todset(-1, delta, period); - break; - case 'f': - if(n < sizeof(uvlong)) - error(Ebadtimectl); - le2vlong(&fasthz, p); - todsetfreq(fasthz); - break; - } - return n; -} - - -int -iprint(char *fmt, ...) -{ - int n, s; - va_list arg; - char buf[PRINTSIZE]; - - s = splhi(); - va_start(arg, fmt); - n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; - va_end(arg); - if(screenputs != 0 && iprintscreenputs) - screenputs(buf, n); -#undef write - write(2, buf, n); - splx(s); - - return n; -} - diff --git a/sys/src/cmd/unix/drawterm/kern/devdraw.c b/sys/src/cmd/unix/drawterm/kern/devdraw.c deleted file mode 100644 index 8b6148e3c..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devdraw.c +++ /dev/null @@ -1,2148 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#define Image IMAGE -#include <draw.h> -#include <memdraw.h> -#include <memlayer.h> -#include <cursor.h> -#include "screen.h" - -enum -{ - Qtopdir = 0, - Qnew, - Q3rd, - Q2nd, - Qcolormap, - Qctl, - Qdata, - Qrefresh, -}; - -/* - * Qid path is: - * 4 bits of file type (qids above) - * 24 bits of mux slot number +1; 0 means not attached to client - */ -#define QSHIFT 4 /* location in qid of client # */ - -#define QID(q) ((((ulong)(q).path)&0x0000000F)>>0) -#define CLIENTPATH(q) ((((ulong)q)&0x7FFFFFF0)>>QSHIFT) -#define CLIENT(q) CLIENTPATH((q).path) - -#define NHASH (1<<5) -#define HASHMASK (NHASH-1) -#define IOUNIT (64*1024) - -typedef struct Client Client; -typedef struct Draw Draw; -typedef struct DImage DImage; -typedef struct DScreen DScreen; -typedef struct CScreen CScreen; -typedef struct FChar FChar; -typedef struct Refresh Refresh; -typedef struct Refx Refx; -typedef struct DName DName; - -ulong blanktime = 30; /* in minutes; a half hour */ - -struct Draw -{ - QLock lk; - int clientid; - int nclient; - Client** client; - int nname; - DName* name; - int vers; - int softscreen; - int blanked; /* screen turned off */ - ulong blanktime; /* time of last operation */ - ulong savemap[3*256]; -}; - -struct Client -{ - Ref r; - DImage* dimage[NHASH]; - CScreen* cscreen; - Refresh* refresh; - Rendez refrend; - uchar* readdata; - int nreaddata; - int busy; - int clientid; - int slot; - int refreshme; - int infoid; - int op; -}; - -struct Refresh -{ - DImage* dimage; - Rectangle r; - Refresh* next; -}; - -struct Refx -{ - Client* client; - DImage* dimage; -}; - -struct DName -{ - char *name; - Client *client; - DImage* dimage; - int vers; -}; - -struct FChar -{ - int minx; /* left edge of bits */ - int maxx; /* right edge of bits */ - uchar miny; /* first non-zero scan-line */ - uchar maxy; /* last non-zero scan-line + 1 */ - schar left; /* offset of baseline */ - uchar width; /* width of baseline */ -}; - -/* - * Reference counts in DImages: - * one per open by original client - * one per screen image or fill - * one per image derived from this one by name - */ -struct DImage -{ - int id; - int ref; - char *name; - int vers; - Memimage* image; - int ascent; - int nfchar; - FChar* fchar; - DScreen* dscreen; /* 0 if not a window */ - DImage* fromname; /* image this one is derived from, by name */ - DImage* next; -}; - -struct CScreen -{ - DScreen* dscreen; - CScreen* next; -}; - -struct DScreen -{ - int id; - int public; - int ref; - DImage *dimage; - DImage *dfill; - Memscreen* screen; - Client* owner; - DScreen* next; -}; - -static Draw sdraw; -static Memimage *screenimage; -static Memdata screendata; -static Rectangle flushrect; -static int waste; -static DScreen* dscreen; -extern void flushmemscreen(Rectangle); - void drawmesg(Client*, void*, int); - void drawuninstall(Client*, int); - void drawfreedimage(DImage*); - Client* drawclientofpath(ulong); - -static char Enodrawimage[] = "unknown id for draw image"; -static char Enodrawscreen[] = "unknown id for draw screen"; -static char Eshortdraw[] = "short draw message"; -static char Eshortread[] = "draw read too short"; -static char Eimageexists[] = "image id in use"; -static char Escreenexists[] = "screen id in use"; -static char Edrawmem[] = "image memory allocation failed"; -static char Ereadoutside[] = "readimage outside image"; -static char Ewriteoutside[] = "writeimage outside image"; -static char Enotfont[] = "image not a font"; -static char Eindex[] = "character index out of range"; -static char Enoclient[] = "no such draw client"; -/* static char Edepth[] = "image has bad depth"; */ -static char Enameused[] = "image name in use"; -static char Enoname[] = "no image with that name"; -static char Eoldname[] = "named image no longer valid"; -static char Enamed[] = "image already has name"; -static char Ewrongname[] = "wrong name for image"; - -int -drawcanqlock(void) -{ - return canqlock(&sdraw.lk); -} - -void -drawqlock(void) -{ - qlock(&sdraw.lk); -} - -void -drawqunlock(void) -{ - qunlock(&sdraw.lk); -} - -static int -drawgen(Chan *c, char *name, Dirtab *dt, int ndt, int s, Dir *dp) -{ - int t; - Qid q; - ulong path; - Client *cl; - - USED(name); - USED(dt); - USED(ndt); - - q.vers = 0; - - if(s == DEVDOTDOT){ - switch(QID(c->qid)){ - case Qtopdir: - case Q2nd: - mkqid(&q, Qtopdir, 0, QTDIR); - devdir(c, q, "#i", 0, eve, 0500, dp); - break; - case Q3rd: - cl = drawclientofpath(c->qid.path); - if(cl == nil) - strcpy(up->genbuf, "??"); - else - sprint(up->genbuf, "%d", cl->clientid); - mkqid(&q, Q2nd, 0, QTDIR); - devdir(c, q, up->genbuf, 0, eve, 0500, dp); - break; - default: - panic("drawwalk %llux", c->qid.path); - } - return 1; - } - - /* - * Top level directory contains the name of the device. - */ - t = QID(c->qid); - if(t == Qtopdir){ - switch(s){ - case 0: - mkqid(&q, Q2nd, 0, QTDIR); - devdir(c, q, "draw", 0, eve, 0555, dp); - break; - default: - return -1; - } - return 1; - } - - /* - * Second level contains "new" plus all the clients. - */ - if(t == Q2nd || t == Qnew){ - if(s == 0){ - mkqid(&q, Qnew, 0, QTFILE); - devdir(c, q, "new", 0, eve, 0666, dp); - } - else if(s <= sdraw.nclient){ - cl = sdraw.client[s-1]; - if(cl == 0) - return 0; - sprint(up->genbuf, "%d", cl->clientid); - mkqid(&q, (s<<QSHIFT)|Q3rd, 0, QTDIR); - devdir(c, q, up->genbuf, 0, eve, 0555, dp); - return 1; - } - else - return -1; - return 1; - } - - /* - * Third level. - */ - path = c->qid.path&~((1<<QSHIFT)-1); /* slot component */ - q.vers = c->qid.vers; - q.type = QTFILE; - switch(s){ - case 0: - q.path = path|Qcolormap; - devdir(c, q, "colormap", 0, eve, 0600, dp); - break; - case 1: - q.path = path|Qctl; - devdir(c, q, "ctl", 0, eve, 0600, dp); - break; - case 2: - q.path = path|Qdata; - devdir(c, q, "data", 0, eve, 0600, dp); - break; - case 3: - q.path = path|Qrefresh; - devdir(c, q, "refresh", 0, eve, 0400, dp); - break; - default: - return -1; - } - return 1; -} - -static -int -drawrefactive(void *a) -{ - Client *c; - - c = a; - return c->refreshme || c->refresh!=0; -} - -static -void -drawrefreshscreen(DImage *l, Client *client) -{ - while(l != nil && l->dscreen == nil) - l = l->fromname; - if(l != nil && l->dscreen->owner != client) - l->dscreen->owner->refreshme = 1; -} - -static -void -drawrefresh(Memimage *m, Rectangle r, void *v) -{ - Refx *x; - DImage *d; - Client *c; - Refresh *ref; - - USED(m); - - if(v == 0) - return; - x = v; - c = x->client; - d = x->dimage; - for(ref=c->refresh; ref; ref=ref->next) - if(ref->dimage == d){ - combinerect(&ref->r, r); - return; - } - ref = malloc(sizeof(Refresh)); - if(ref){ - ref->dimage = d; - ref->r = r; - ref->next = c->refresh; - c->refresh = ref; - } -} - -static void -addflush(Rectangle r) -{ - int abb, ar, anbb; - Rectangle nbb; - - if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r)) - return; - - if(flushrect.min.x >= flushrect.max.x){ - flushrect = r; - waste = 0; - return; - } - nbb = flushrect; - combinerect(&nbb, r); - ar = Dx(r)*Dy(r); - abb = Dx(flushrect)*Dy(flushrect); - anbb = Dx(nbb)*Dy(nbb); - /* - * Area of new waste is area of new bb minus area of old bb, - * less the area of the new segment, which we assume is not waste. - * This could be negative, but that's OK. - */ - waste += anbb-abb - ar; - if(waste < 0) - waste = 0; - /* - * absorb if: - * total area is small - * waste is less than half total area - * rectangles touch - */ - if(anbb<=1024 || waste*2<anbb || rectXrect(flushrect, r)){ - flushrect = nbb; - return; - } - /* emit current state */ - if(flushrect.min.x < flushrect.max.x) - flushmemscreen(flushrect); - flushrect = r; - waste = 0; -} - -static -void -dstflush(int dstid, Memimage *dst, Rectangle r) -{ - Memlayer *l; - - if(dstid == 0){ - combinerect(&flushrect, r); - return; - } - /* how can this happen? -rsc, dec 12 2002 */ - if(dst == 0){ - print("nil dstflush\n"); - return; - } - l = dst->layer; - if(l == nil) - return; - do{ - if(l->screen->image->data != screenimage->data) - return; - r = rectaddpt(r, l->delta); - l = l->screen->image->layer; - }while(l); - addflush(r); -} - -void -drawflush(void) -{ - if(flushrect.min.x < flushrect.max.x) - flushmemscreen(flushrect); - flushrect = Rect(10000, 10000, -10000, -10000); -} - -void -drawflushr(Rectangle r) -{ - qlock(&sdraw.lk); - flushmemscreen(r); - qunlock(&sdraw.lk); -} - -static -int -drawcmp(char *a, char *b, int n) -{ - if(strlen(a) != n) - return 1; - return memcmp(a, b, n); -} - -DName* -drawlookupname(int n, char *str) -{ - DName *name, *ename; - - name = sdraw.name; - ename = &name[sdraw.nname]; - for(; name<ename; name++) - if(drawcmp(name->name, str, n) == 0) - return name; - return 0; -} - -int -drawgoodname(DImage *d) -{ - DName *n; - - /* if window, validate the screen's own images */ - if(d->dscreen) - if(drawgoodname(d->dscreen->dimage) == 0 - || drawgoodname(d->dscreen->dfill) == 0) - return 0; - if(d->name == nil) - return 1; - n = drawlookupname(strlen(d->name), d->name); - if(n==nil || n->vers!=d->vers) - return 0; - return 1; -} - -DImage* -drawlookup(Client *client, int id, int checkname) -{ - DImage *d; - - d = client->dimage[id&HASHMASK]; - while(d){ - if(d->id == id){ - if(checkname && !drawgoodname(d)) - error(Eoldname); - return d; - } - d = d->next; - } - return 0; -} - -DScreen* -drawlookupdscreen(int id) -{ - DScreen *s; - - s = dscreen; - while(s){ - if(s->id == id) - return s; - s = s->next; - } - return 0; -} - -DScreen* -drawlookupscreen(Client *client, int id, CScreen **cs) -{ - CScreen *s; - - s = client->cscreen; - while(s){ - if(s->dscreen->id == id){ - *cs = s; - return s->dscreen; - } - s = s->next; - } - error(Enodrawscreen); - return 0; -} - -Memimage* -drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen) -{ - DImage *d; - - d = malloc(sizeof(DImage)); - if(d == 0) - return 0; - d->id = id; - d->ref = 1; - d->name = 0; - d->vers = 0; - d->image = i; - d->nfchar = 0; - d->fchar = 0; - d->fromname = 0; - d->dscreen = dscreen; - d->next = client->dimage[id&HASHMASK]; - client->dimage[id&HASHMASK] = d; - return i; -} - -Memscreen* -drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public) -{ - Memscreen *s; - CScreen *c; - - c = malloc(sizeof(CScreen)); - if(dimage && dimage->image && dimage->image->chan == 0) - panic("bad image %p in drawinstallscreen", dimage->image); - - if(c == 0) - return 0; - if(d == 0){ - d = malloc(sizeof(DScreen)); - if(d == 0){ - free(c); - return 0; - } - s = malloc(sizeof(Memscreen)); - if(s == 0){ - free(c); - free(d); - return 0; - } - s->frontmost = 0; - s->rearmost = 0; - d->dimage = dimage; - if(dimage){ - s->image = dimage->image; - dimage->ref++; - } - d->dfill = dfill; - if(dfill){ - s->fill = dfill->image; - dfill->ref++; - } - d->ref = 0; - d->id = id; - d->screen = s; - d->public = public; - d->next = dscreen; - d->owner = client; - dscreen = d; - } - c->dscreen = d; - d->ref++; - c->next = client->cscreen; - client->cscreen = c; - return d->screen; -} - -void -drawdelname(DName *name) -{ - int i; - - i = name-sdraw.name; - memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName)); - sdraw.nname--; -} - -void -drawfreedscreen(DScreen *this) -{ - DScreen *ds, *next; - - this->ref--; - if(this->ref < 0) - print("negative ref in drawfreedscreen\n"); - if(this->ref > 0) - return; - ds = dscreen; - if(ds == this){ - dscreen = this->next; - goto Found; - } - while((next = ds->next)){ /* assign = */ - if(next == this){ - ds->next = this->next; - goto Found; - } - ds = next; - } - error(Enodrawimage); - - Found: - if(this->dimage) - drawfreedimage(this->dimage); - if(this->dfill) - drawfreedimage(this->dfill); - free(this->screen); - free(this); -} - -void -drawfreedimage(DImage *dimage) -{ - int i; - Memimage *l; - DScreen *ds; - - dimage->ref--; - if(dimage->ref < 0) - print("negative ref in drawfreedimage\n"); - if(dimage->ref > 0) - return; - - /* any names? */ - for(i=0; i<sdraw.nname; ) - if(sdraw.name[i].dimage == dimage) - drawdelname(sdraw.name+i); - else - i++; - if(dimage->fromname){ /* acquired by name; owned by someone else*/ - drawfreedimage(dimage->fromname); - goto Return; - } - if(dimage->image == screenimage) /* don't free the display */ - goto Return; - ds = dimage->dscreen; - if(ds){ - l = dimage->image; - if(l->data == screenimage->data) - addflush(l->layer->screenr); - if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */ - free(l->layer->refreshptr); - l->layer->refreshptr = nil; - if(drawgoodname(dimage)) - memldelete(l); - else - memlfree(l); - drawfreedscreen(ds); - }else - freememimage(dimage->image); - Return: - free(dimage->fchar); - free(dimage); -} - -void -drawuninstallscreen(Client *client, CScreen *this) -{ - CScreen *cs, *next; - - cs = client->cscreen; - if(cs == this){ - client->cscreen = this->next; - drawfreedscreen(this->dscreen); - free(this); - return; - } - while((next = cs->next)){ /* assign = */ - if(next == this){ - cs->next = this->next; - drawfreedscreen(this->dscreen); - free(this); - return; - } - cs = next; - } -} - -void -drawuninstall(Client *client, int id) -{ - DImage *d, *next; - - d = client->dimage[id&HASHMASK]; - if(d == 0) - error(Enodrawimage); - if(d->id == id){ - client->dimage[id&HASHMASK] = d->next; - drawfreedimage(d); - return; - } - while((next = d->next)){ /* assign = */ - if(next->id == id){ - d->next = next->next; - drawfreedimage(next); - return; - } - d = next; - } - error(Enodrawimage); -} - -void -drawaddname(Client *client, DImage *di, int n, char *str) -{ - DName *name, *ename, *new, *t; - - name = sdraw.name; - ename = &name[sdraw.nname]; - for(; name<ename; name++) - if(drawcmp(name->name, str, n) == 0) - error(Enameused); - t = smalloc((sdraw.nname+1)*sizeof(DName)); - memmove(t, sdraw.name, sdraw.nname*sizeof(DName)); - free(sdraw.name); - sdraw.name = t; - new = &sdraw.name[sdraw.nname++]; - new->name = smalloc(n+1); - memmove(new->name, str, n); - new->name[n] = 0; - new->dimage = di; - new->client = client; - new->vers = ++sdraw.vers; -} - -Client* -drawnewclient(void) -{ - Client *cl, **cp; - int i; - - for(i=0; i<sdraw.nclient; i++){ - cl = sdraw.client[i]; - if(cl == 0) - break; - } - if(i == sdraw.nclient){ - cp = malloc((sdraw.nclient+1)*sizeof(Client*)); - if(cp == 0) - return 0; - memmove(cp, sdraw.client, sdraw.nclient*sizeof(Client*)); - free(sdraw.client); - sdraw.client = cp; - sdraw.nclient++; - cp[i] = 0; - } - cl = malloc(sizeof(Client)); - if(cl == 0) - return 0; - memset(cl, 0, sizeof(Client)); - cl->slot = i; - cl->clientid = ++sdraw.clientid; - cl->op = SoverD; - sdraw.client[i] = cl; - return cl; -} - -static int -drawclientop(Client *cl) -{ - int op; - - op = cl->op; - cl->op = SoverD; - return op; -} - -int -drawhasclients(void) -{ - /* - * if draw has ever been used, we can't resize the frame buffer, - * even if all clients have exited (nclients is cumulative); it's too - * hard to make work. - */ - return sdraw.nclient != 0; -} - -Client* -drawclientofpath(ulong path) -{ - Client *cl; - int slot; - - slot = CLIENTPATH(path); - if(slot == 0) - return nil; - cl = sdraw.client[slot-1]; - if(cl==0 || cl->clientid==0) - return nil; - return cl; -} - - -Client* -drawclient(Chan *c) -{ - Client *client; - - client = drawclientofpath(c->qid.path); - if(client == nil) - error(Enoclient); - return client; -} - -Memimage* -drawimage(Client *client, uchar *a) -{ - DImage *d; - - d = drawlookup(client, BGLONG(a), 1); - if(d == nil) - error(Enodrawimage); - return d->image; -} - -void -drawrectangle(Rectangle *r, uchar *a) -{ - r->min.x = BGLONG(a+0*4); - r->min.y = BGLONG(a+1*4); - r->max.x = BGLONG(a+2*4); - r->max.y = BGLONG(a+3*4); -} - -void -drawpoint(Point *p, uchar *a) -{ - p->x = BGLONG(a+0*4); - p->y = BGLONG(a+1*4); -} - -#define isvgascreen(dst) 1 - - -Point -drawchar(Memimage *dst, Memimage *rdst, Point p, - Memimage *src, Point *sp, DImage *font, int index, int op) -{ - FChar *fc; - Rectangle r; - Point sp1; - static Memimage *tmp; - - fc = &font->fchar[index]; - r.min.x = p.x+fc->left; - r.min.y = p.y-(font->ascent-fc->miny); - r.max.x = r.min.x+(fc->maxx-fc->minx); - r.max.y = r.min.y+(fc->maxy-fc->miny); - sp1.x = sp->x+fc->left; - sp1.y = sp->y+fc->miny; - - /* - * If we're drawing greyscale fonts onto a VGA screen, - * it's very costly to read the screen memory to do the - * alpha blending inside memdraw. If this is really a stringbg, - * then rdst is the bg image (in main memory) which we can - * refer to for the underlying dst pixels instead of reading dst - * directly. - */ - if(1 || (isvgascreen(dst) && !isvgascreen(rdst) /*&& font->image->depth > 1*/)){ - if(tmp == nil || tmp->chan != dst->chan || Dx(tmp->r) < Dx(r) || Dy(tmp->r) < Dy(r)){ - if(tmp) - freememimage(tmp); - tmp = allocmemimage(Rect(0,0,Dx(r),Dy(r)), dst->chan); - if(tmp == nil) - goto fallback; - } - memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), rdst, r.min, memopaque, ZP, S); - memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), src, sp1, font->image, Pt(fc->minx, fc->miny), op); - memdraw(dst, r, tmp, ZP, memopaque, ZP, S); - }else{ - fallback: - memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op); - } - - p.x += fc->width; - sp->x += fc->width; - return p; -} - -static int -initscreenimage(void) -{ - int width, depth; - ulong chan; - void *X; - Rectangle r; - - if(screenimage != nil) - return 1; - - screendata.base = nil; - screendata.bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen, &X); - if(screendata.bdata == nil && X == nil) - return 0; - screendata.ref = 1; - - screenimage = allocmemimaged(r, chan, &screendata, X); - if(screenimage == nil){ - /* RSC: BUG: detach screen */ - return 0; - } - - screenimage->width = width; - screenimage->clipr = r; - return 1; -} - -void -deletescreenimage(void) -{ - qlock(&sdraw.lk); - /* RSC: BUG: detach screen */ - if(screenimage) - freememimage(screenimage); - screenimage = nil; - qunlock(&sdraw.lk); -} - -static Chan* -drawattach(char *spec) -{ - qlock(&sdraw.lk); - if(!initscreenimage()){ - qunlock(&sdraw.lk); - error("no frame buffer"); - } - qunlock(&sdraw.lk); - return devattach('i', spec); -} - -static Walkqid* -drawwalk(Chan *c, Chan *nc, char **name, int nname) -{ - if(screendata.bdata == nil) - error("no frame buffer"); - return devwalk(c, nc, name, nname, 0, 0, drawgen); -} - -static int -drawstat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, 0, 0, drawgen); -} - -static Chan* -drawopen(Chan *c, int omode) -{ - Client *cl; - - if(c->qid.type & QTDIR){ - c = devopen(c, omode, 0, 0, drawgen); - c->iounit = IOUNIT; - } - - qlock(&sdraw.lk); - if(waserror()){ - qunlock(&sdraw.lk); - nexterror(); - } - - if(QID(c->qid) == Qnew){ - cl = drawnewclient(); - if(cl == 0) - error(Enodev); - c->qid.path = Qctl|((cl->slot+1)<<QSHIFT); - } - - switch(QID(c->qid)){ - case Qnew: - break; - - case Qctl: - cl = drawclient(c); - if(cl->busy) - error(Einuse); - cl->busy = 1; - flushrect = Rect(10000, 10000, -10000, -10000); - drawinstall(cl, 0, screenimage, 0); - incref(&cl->r); - break; - case Qcolormap: - case Qdata: - case Qrefresh: - cl = drawclient(c); - incref(&cl->r); - break; - } - qunlock(&sdraw.lk); - poperror(); - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - c->iounit = IOUNIT; - return c; -} - -static void -drawclose(Chan *c) -{ - int i; - DImage *d, **dp; - Client *cl; - Refresh *r; - - if(QID(c->qid) < Qcolormap) /* Qtopdir, Qnew, Q3rd, Q2nd have no client */ - return; - qlock(&sdraw.lk); - if(waserror()){ - qunlock(&sdraw.lk); - nexterror(); - } - - cl = drawclient(c); - if(QID(c->qid) == Qctl) - cl->busy = 0; - if((c->flag&COPEN) && (decref(&cl->r)==0)){ - while((r = cl->refresh)){ /* assign = */ - cl->refresh = r->next; - free(r); - } - /* free names */ - for(i=0; i<sdraw.nname; ) - if(sdraw.name[i].client == cl) - drawdelname(sdraw.name+i); - else - i++; - while(cl->cscreen) - drawuninstallscreen(cl, cl->cscreen); - /* all screens are freed, so now we can free images */ - dp = cl->dimage; - for(i=0; i<NHASH; i++){ - while((d = *dp) != nil){ - *dp = d->next; - drawfreedimage(d); - } - dp++; - } - sdraw.client[cl->slot] = 0; - drawflush(); /* to erase visible, now dead windows */ - free(cl); - } - qunlock(&sdraw.lk); - poperror(); -} - -long -drawread(Chan *c, void *a, long n, vlong off) -{ - int index, m; - ulong red, green, blue; - Client *cl; - uchar *p; - Refresh *r; - DImage *di; - Memimage *i; - ulong offset = off; - char buf[16]; - - if(c->qid.type & QTDIR) - return devdirread(c, a, n, 0, 0, drawgen); - cl = drawclient(c); - qlock(&sdraw.lk); - if(waserror()){ - qunlock(&sdraw.lk); - nexterror(); - } - switch(QID(c->qid)){ - case Qctl: - if(n < 12*12) - error(Eshortread); - if(cl->infoid < 0) - error(Enodrawimage); - if(cl->infoid == 0){ - i = screenimage; - if(i == nil) - error(Enodrawimage); - }else{ - di = drawlookup(cl, cl->infoid, 1); - if(di == nil) - error(Enodrawimage); - i = di->image; - } - n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d ", - cl->clientid, cl->infoid, chantostr(buf, i->chan), (i->flags&Frepl)==Frepl, - i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y, - i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y); - cl->infoid = -1; - break; - - case Qcolormap: - drawactive(1); /* to restore map from backup */ - p = malloc(4*12*256+1); - if(p == 0) - error(Enomem); - m = 0; - for(index = 0; index < 256; index++){ - getcolor(index, &red, &green, &blue); - m += sprint((char*)p+m, "%11d %11lud %11lud %11lud\n", index, red>>24, green>>24, blue>>24); - } - n = readstr(offset, a, n, (char*)p); - free(p); - break; - - case Qdata: - if(cl->readdata == nil) - error("no draw data"); - if(n < cl->nreaddata) - error(Eshortread); - n = cl->nreaddata; - memmove(a, cl->readdata, cl->nreaddata); - free(cl->readdata); - cl->readdata = nil; - break; - - case Qrefresh: - if(n < 5*4) - error(Ebadarg); - for(;;){ - if(cl->refreshme || cl->refresh) - break; - qunlock(&sdraw.lk); - if(waserror()){ - qlock(&sdraw.lk); /* restore lock for waserror() above */ - nexterror(); - } - sleep(&cl->refrend, drawrefactive, cl); - poperror(); - qlock(&sdraw.lk); - } - p = a; - while(cl->refresh && n>=5*4){ - r = cl->refresh; - BPLONG(p+0*4, r->dimage->id); - BPLONG(p+1*4, r->r.min.x); - BPLONG(p+2*4, r->r.min.y); - BPLONG(p+3*4, r->r.max.x); - BPLONG(p+4*4, r->r.max.y); - cl->refresh = r->next; - free(r); - p += 5*4; - n -= 5*4; - } - cl->refreshme = 0; - n = p-(uchar*)a; - } - qunlock(&sdraw.lk); - poperror(); - return n; -} - -void -drawwakeall(void) -{ - Client *cl; - int i; - - for(i=0; i<sdraw.nclient; i++){ - cl = sdraw.client[i]; - if(cl && (cl->refreshme || cl->refresh)) - wakeup(&cl->refrend); - } -} - -static long -drawwrite(Chan *c, void *a, long n, vlong offset) -{ - char buf[128], *fields[4], *q; - Client *cl; - int i, m, red, green, blue, x; - - USED(offset); - - if(c->qid.type & QTDIR) - error(Eisdir); - cl = drawclient(c); - qlock(&sdraw.lk); - if(waserror()){ - drawwakeall(); - qunlock(&sdraw.lk); - nexterror(); - } - switch(QID(c->qid)){ - case Qctl: - if(n != 4) - error("unknown draw control request"); - cl->infoid = BGLONG((uchar*)a); - break; - - case Qcolormap: - drawactive(1); /* to restore map from backup */ - m = n; - n = 0; - while(m > 0){ - x = m; - if(x > sizeof(buf)-1) - x = sizeof(buf)-1; - q = memccpy(buf, a, '\n', x); - if(q == 0) - break; - i = q-buf; - n += i; - a = (char*)a + i; - m -= i; - *q = 0; - if(tokenize(buf, fields, nelem(fields)) != 4) - error(Ebadarg); - i = strtoul(fields[0], 0, 0); - red = strtoul(fields[1], 0, 0); - green = strtoul(fields[2], 0, 0); - blue = strtoul(fields[3], &q, 0); - if(fields[3] == q) - error(Ebadarg); - if(red>255 || green>255 || blue>255 || i<0 || i>255) - error(Ebadarg); - red |= red<<8; - red |= red<<16; - green |= green<<8; - green |= green<<16; - blue |= blue<<8; - blue |= blue<<16; - setcolor(i, red, green, blue); - } - break; - - case Qdata: - drawmesg(cl, a, n); - drawwakeall(); - break; - - default: - error(Ebadusefd); - } - qunlock(&sdraw.lk); - poperror(); - return n; -} - -uchar* -drawcoord(uchar *p, uchar *maxp, int oldx, int *newx) -{ - int b, x; - - if(p >= maxp) - error(Eshortdraw); - b = *p++; - x = b & 0x7F; - if(b & 0x80){ - if(p+1 >= maxp) - error(Eshortdraw); - x |= *p++ << 7; - x |= *p++ << 15; - if(x & (1<<22)) - x |= ~0<<23; - }else{ - if(b & 0x40) - x |= ~0<<7; - x += oldx; - } - *newx = x; - return p; -} - -static void -printmesg(char *fmt, uchar *a, int plsprnt) -{ - char buf[256]; - char *p, *q; - int s; - - if(1|| plsprnt==0){ - SET(s); - SET(q); - SET(p); - USED(fmt); - USED(a); - p = buf; - USED(p); - USED(q); - USED(s); - return; - } - q = buf; - *q++ = *a++; - for(p=fmt; *p; p++){ - switch(*p){ - case 'l': - q += sprint(q, " %ld", (long)BGLONG(a)); - a += 4; - break; - case 'L': - q += sprint(q, " %.8lux", (ulong)BGLONG(a)); - a += 4; - break; - case 'R': - q += sprint(q, " [%d %d %d %d]", BGLONG(a), BGLONG(a+4), BGLONG(a+8), BGLONG(a+12)); - a += 16; - break; - case 'P': - q += sprint(q, " [%d %d]", BGLONG(a), BGLONG(a+4)); - a += 8; - break; - case 'b': - q += sprint(q, " %d", *a++); - break; - case 's': - q += sprint(q, " %d", BGSHORT(a)); - a += 2; - break; - case 'S': - q += sprint(q, " %.4ux", BGSHORT(a)); - a += 2; - break; - } - } - *q++ = '\n'; - *q = 0; - iprint("%.*s", (int)(q-buf), buf); -} - -void -drawmesg(Client *client, void *av, int n) -{ - int c, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, op, ox, oy, oesize, esize, doflush; - uchar *u, *a, refresh; - char *fmt; - ulong value, chan; - Rectangle r, clipr; - Point p, q, *pp, sp; - Memimage *i, *dst, *src, *mask; - Memimage *l, **lp; - Memscreen *scrn; - DImage *font, *ll, *di, *ddst, *dsrc; - DName *dn; - DScreen *dscrn; - FChar *fc; - Refx *refx; - CScreen *cs; - Refreshfn reffn; - - a = av; - m = 0; - fmt = nil; - if(waserror()){ - if(fmt) printmesg(fmt, a, 1); - /* iprint("error: %s\n", up->errstr); */ - nexterror(); - } - while((n-=m) > 0){ - USED(fmt); - a += m; - switch(*a){ - default: - error("bad draw command"); - /* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbaa[4] */ - case 'b': - printmesg(fmt="LLbLbRRL", a, 0); - m = 1+4+4+1+4+1+4*4+4*4+4; - if(n < m) - error(Eshortdraw); - dstid = BGLONG(a+1); - scrnid = BGSHORT(a+5); - refresh = a[9]; - chan = BGLONG(a+10); - repl = a[14]; - drawrectangle(&r, a+15); - drawrectangle(&clipr, a+31); - value = BGLONG(a+47); - if(drawlookup(client, dstid, 0)) - error(Eimageexists); - if(scrnid){ - dscrn = drawlookupscreen(client, scrnid, &cs); - scrn = dscrn->screen; - if(repl || chan!=scrn->image->chan) - error("image parameters incompatible with screen"); - reffn = 0; - switch(refresh){ - case Refbackup: - break; - case Refnone: - reffn = memlnorefresh; - break; - case Refmesg: - reffn = drawrefresh; - break; - default: - error("unknown refresh method"); - } - l = memlalloc(scrn, r, reffn, 0, value); - if(l == 0) - error(Edrawmem); - addflush(l->layer->screenr); - l->clipr = clipr; - rectclip(&l->clipr, r); - if(drawinstall(client, dstid, l, dscrn) == 0){ - memldelete(l); - error(Edrawmem); - } - dscrn->ref++; - if(reffn){ - refx = nil; - if(reffn == drawrefresh){ - refx = malloc(sizeof(Refx)); - if(refx == 0){ - drawuninstall(client, dstid); - error(Edrawmem); - } - refx->client = client; - refx->dimage = drawlookup(client, dstid, 1); - } - memlsetrefresh(l, reffn, refx); - } - continue; - } - i = allocmemimage(r, chan); - if(i == 0) - error(Edrawmem); - if(repl) - i->flags |= Frepl; - i->clipr = clipr; - if(!repl) - rectclip(&i->clipr, r); - if(drawinstall(client, dstid, i, 0) == 0){ - freememimage(i); - error(Edrawmem); - } - memfillcolor(i, value); - continue; - - /* allocate screen: 'A' id[4] imageid[4] fillid[4] public[1] */ - case 'A': - printmesg(fmt="LLLb", a, 1); - m = 1+4+4+4+1; - if(n < m) - error(Eshortdraw); - dstid = BGLONG(a+1); - if(dstid == 0) - error(Ebadarg); - if(drawlookupdscreen(dstid)) - error(Escreenexists); - ddst = drawlookup(client, BGLONG(a+5), 1); - dsrc = drawlookup(client, BGLONG(a+9), 1); - if(ddst==0 || dsrc==0) - error(Enodrawimage); - if(drawinstallscreen(client, 0, dstid, ddst, dsrc, a[13]) == 0) - error(Edrawmem); - continue; - - /* set repl and clip: 'c' dstid[4] repl[1] clipR[4*4] */ - case 'c': - printmesg(fmt="LbR", a, 0); - m = 1+4+1+4*4; - if(n < m) - error(Eshortdraw); - ddst = drawlookup(client, BGLONG(a+1), 1); - if(ddst == nil) - error(Enodrawimage); - if(ddst->name) - error("can't change repl/clipr of shared image"); - dst = ddst->image; - if(a[5]) - dst->flags |= Frepl; - drawrectangle(&dst->clipr, a+6); - continue; - - /* draw: 'd' dstid[4] srcid[4] maskid[4] R[4*4] P[2*4] P[2*4] */ - case 'd': - printmesg(fmt="LLLRPP", a, 0); - m = 1+4+4+4+4*4+2*4+2*4; - if(n < m) - error(Eshortdraw); - dst = drawimage(client, a+1); - dstid = BGLONG(a+1); - src = drawimage(client, a+5); - mask = drawimage(client, a+9); - drawrectangle(&r, a+13); - drawpoint(&p, a+29); - drawpoint(&q, a+37); - op = drawclientop(client); - memdraw(dst, r, src, p, mask, q, op); - dstflush(dstid, dst, r); - continue; - - /* toggle debugging: 'D' val[1] */ - case 'D': - printmesg(fmt="b", a, 0); - m = 1+1; - if(n < m) - error(Eshortdraw); - drawdebug = a[1]; - continue; - - /* ellipse: 'e' dstid[4] srcid[4] center[2*4] a[4] b[4] thick[4] sp[2*4] alpha[4] phi[4]*/ - case 'e': - case 'E': - printmesg(fmt="LLPlllPll", a, 0); - m = 1+4+4+2*4+4+4+4+2*4+2*4; - if(n < m) - error(Eshortdraw); - dst = drawimage(client, a+1); - dstid = BGLONG(a+1); - src = drawimage(client, a+5); - drawpoint(&p, a+9); - e0 = BGLONG(a+17); - e1 = BGLONG(a+21); - if(e0<0 || e1<0) - error("invalid ellipse semidiameter"); - j = BGLONG(a+25); - if(j < 0) - error("negative ellipse thickness"); - drawpoint(&sp, a+29); - c = j; - if(*a == 'E') - c = -1; - ox = BGLONG(a+37); - oy = BGLONG(a+41); - op = drawclientop(client); - /* high bit indicates arc angles are present */ - if(ox & (1U<<31)){ - if((ox & (1<<30)) == 0) - ox &= ~(1U<<31); - memarc(dst, p, e0, e1, c, src, sp, ox, oy, op); - }else - memellipse(dst, p, e0, e1, c, src, sp, op); - dstflush(dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1)); - continue; - - /* free: 'f' id[4] */ - case 'f': - printmesg(fmt="L", a, 1); - m = 1+4; - if(n < m) - error(Eshortdraw); - ll = drawlookup(client, BGLONG(a+1), 0); - if(ll && ll->dscreen && ll->dscreen->owner != client) - ll->dscreen->owner->refreshme = 1; - drawuninstall(client, BGLONG(a+1)); - continue; - - /* free screen: 'F' id[4] */ - case 'F': - printmesg(fmt="L", a, 1); - m = 1+4; - if(n < m) - error(Eshortdraw); - drawlookupscreen(client, BGLONG(a+1), &cs); - drawuninstallscreen(client, cs); - continue; - - /* initialize font: 'i' fontid[4] nchars[4] ascent[1] */ - case 'i': - printmesg(fmt="Llb", a, 1); - m = 1+4+4+1; - if(n < m) - error(Eshortdraw); - dstid = BGLONG(a+1); - if(dstid == 0) - error("can't use display as font"); - font = drawlookup(client, dstid, 1); - if(font == 0) - error(Enodrawimage); - if(font->image->layer) - error("can't use window as font"); - ni = BGLONG(a+5); - if(ni<=0 || ni>4096) - error("bad font size (4096 chars max)"); - free(font->fchar); /* should we complain if non-zero? */ - font->fchar = malloc(ni*sizeof(FChar)); - if(font->fchar == 0) - error("no memory for font"); - memset(font->fchar, 0, ni*sizeof(FChar)); - font->nfchar = ni; - font->ascent = a[9]; - continue; - - /* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */ - case 'l': - printmesg(fmt="LLSRPbb", a, 0); - m = 1+4+4+2+4*4+2*4+1+1; - if(n < m) - error(Eshortdraw); - font = drawlookup(client, BGLONG(a+1), 1); - if(font == 0) - error(Enodrawimage); - if(font->nfchar == 0) - error(Enotfont); - src = drawimage(client, a+5); - ci = BGSHORT(a+9); - if(ci >= font->nfchar) - error(Eindex); - drawrectangle(&r, a+11); - drawpoint(&p, a+27); - memdraw(font->image, r, src, p, memopaque, p, S); - fc = &font->fchar[ci]; - fc->minx = r.min.x; - fc->maxx = r.max.x; - fc->miny = r.min.y; - fc->maxy = r.max.y; - fc->left = a[35]; - fc->width = a[36]; - continue; - - /* draw line: 'L' dstid[4] p0[2*4] p1[2*4] end0[4] end1[4] radius[4] srcid[4] sp[2*4] */ - case 'L': - printmesg(fmt="LPPlllLP", a, 0); - m = 1+4+2*4+2*4+4+4+4+4+2*4; - if(n < m) - error(Eshortdraw); - dst = drawimage(client, a+1); - dstid = BGLONG(a+1); - drawpoint(&p, a+5); - drawpoint(&q, a+13); - e0 = BGLONG(a+21); - e1 = BGLONG(a+25); - j = BGLONG(a+29); - if(j < 0) - error("negative line width"); - src = drawimage(client, a+33); - drawpoint(&sp, a+37); - op = drawclientop(client); - memline(dst, p, q, e0, e1, j, src, sp, op); - /* avoid memlinebbox if possible */ - if(dstid==0 || dst->layer!=nil){ - /* BUG: this is terribly inefficient: update maximal containing rect*/ - r = memlinebbox(p, q, e0, e1, j); - dstflush(dstid, dst, insetrect(r, -(1+1+j))); - } - continue; - - /* create image mask: 'm' newid[4] id[4] */ -/* - * - case 'm': - printmesg("LL", a, 0); - m = 4+4; - if(n < m) - error(Eshortdraw); - break; - * - */ - - /* attach to a named image: 'n' dstid[4] j[1] name[j] */ - case 'n': - printmesg(fmt="Lz", a, 0); - m = 1+4+1; - if(n < m) - error(Eshortdraw); - j = a[5]; - if(j == 0) /* give me a non-empty name please */ - error(Eshortdraw); - m += j; - if(n < m) - error(Eshortdraw); - dstid = BGLONG(a+1); - if(drawlookup(client, dstid, 0)) - error(Eimageexists); - dn = drawlookupname(j, (char*)a+6); - if(dn == nil) - error(Enoname); - if(drawinstall(client, dstid, dn->dimage->image, 0) == 0) - error(Edrawmem); - di = drawlookup(client, dstid, 0); - if(di == 0) - error("draw: can't happen"); - di->vers = dn->vers; - di->name = smalloc(j+1); - di->fromname = dn->dimage; - di->fromname->ref++; - memmove(di->name, a+6, j); - di->name[j] = 0; - client->infoid = dstid; - continue; - - /* name an image: 'N' dstid[4] in[1] j[1] name[j] */ - case 'N': - printmesg(fmt="Lbz", a, 0); - m = 1+4+1+1; - if(n < m) - error(Eshortdraw); - c = a[5]; - j = a[6]; - if(j == 0) /* give me a non-empty name please */ - error(Eshortdraw); - m += j; - if(n < m) - error(Eshortdraw); - di = drawlookup(client, BGLONG(a+1), 0); - if(di == 0) - error(Enodrawimage); - if(di->name) - error(Enamed); - if(c) - drawaddname(client, di, j, (char*)a+7); - else{ - dn = drawlookupname(j, (char*)a+7); - if(dn == nil) - error(Enoname); - if(dn->dimage != di) - error(Ewrongname); - drawdelname(dn); - } - continue; - - /* position window: 'o' id[4] r.min [2*4] screenr.min [2*4] */ - case 'o': - printmesg(fmt="LPP", a, 0); - m = 1+4+2*4+2*4; - if(n < m) - error(Eshortdraw); - dst = drawimage(client, a+1); - if(dst->layer){ - drawpoint(&p, a+5); - drawpoint(&q, a+13); - r = dst->layer->screenr; - ni = memlorigin(dst, p, q); - if(ni < 0) - error("image origin failed"); - if(ni > 0){ - addflush(r); - addflush(dst->layer->screenr); - ll = drawlookup(client, BGLONG(a+1), 1); - drawrefreshscreen(ll, client); - } - } - continue; - - /* set compositing operator for next draw operation: 'O' op */ - case 'O': - printmesg(fmt="b", a, 0); - m = 1+1; - if(n < m) - error(Eshortdraw); - client->op = a[1]; - continue; - - /* filled polygon: 'P' dstid[4] n[2] wind[4] ignore[2*4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */ - /* polygon: 'p' dstid[4] n[2] end0[4] end1[4] radius[4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */ - case 'p': - case 'P': - printmesg(fmt="LslllLPP", a, 0); - m = 1+4+2+4+4+4+4+2*4; - if(n < m) - error(Eshortdraw); - dstid = BGLONG(a+1); - dst = drawimage(client, a+1); - ni = BGSHORT(a+5); - if(ni < 0) - error("negative count in polygon"); - e0 = BGLONG(a+7); - e1 = BGLONG(a+11); - j = 0; - if(*a == 'p'){ - j = BGLONG(a+15); - if(j < 0) - error("negative polygon line width"); - } - src = drawimage(client, a+19); - drawpoint(&sp, a+23); - drawpoint(&p, a+31); - ni++; - pp = malloc(ni*sizeof(Point)); - if(pp == nil) - error(Enomem); - doflush = 0; - if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data)) - doflush = 1; /* simplify test in loop */ - ox = oy = 0; - esize = 0; - u = a+m; - for(y=0; y<ni; y++){ - q = p; - oesize = esize; - u = drawcoord(u, a+n, ox, &p.x); - u = drawcoord(u, a+n, oy, &p.y); - ox = p.x; - oy = p.y; - if(doflush){ - esize = j; - if(*a == 'p'){ - if(y == 0){ - c = memlineendsize(e0); - if(c > esize) - esize = c; - } - if(y == ni-1){ - c = memlineendsize(e1); - if(c > esize) - esize = c; - } - } - if(*a=='P' && e0!=1 && e0 !=~0) - r = dst->clipr; - else if(y > 0){ - r = Rect(q.x-oesize, q.y-oesize, q.x+oesize+1, q.y+oesize+1); - combinerect(&r, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1)); - } - if(rectclip(&r, dst->clipr)) /* should perhaps be an arg to dstflush */ - dstflush(dstid, dst, r); - } - pp[y] = p; - } - if(y == 1) - dstflush(dstid, dst, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1)); - op = drawclientop(client); - if(*a == 'p') - mempoly(dst, pp, ni, e0, e1, j, src, sp, op); - else - memfillpoly(dst, pp, ni, e0, src, sp, op); - free(pp); - m = u-a; - continue; - - /* read: 'r' id[4] R[4*4] */ - case 'r': - printmesg(fmt="LR", a, 0); - m = 1+4+4*4; - if(n < m) - error(Eshortdraw); - i = drawimage(client, a+1); - drawrectangle(&r, a+5); - if(!rectinrect(r, i->r)) - error(Ereadoutside); - c = bytesperline(r, i->depth); - c *= Dy(r); - free(client->readdata); - client->readdata = mallocz(c, 0); - if(client->readdata == nil) - error("readimage malloc failed"); - client->nreaddata = memunload(i, r, client->readdata, c); - if(client->nreaddata < 0){ - free(client->readdata); - client->readdata = nil; - error("bad readimage call"); - } - continue; - - /* string: 's' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] ni*(index[2]) */ - /* stringbg: 'x' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] bgid[4] bgpt[2*4] ni*(index[2]) */ - case 's': - case 'x': - printmesg(fmt="LLLPRPs", a, 0); - m = 1+4+4+4+2*4+4*4+2*4+2; - if(*a == 'x') - m += 4+2*4; - if(n < m) - error(Eshortdraw); - - dst = drawimage(client, a+1); - dstid = BGLONG(a+1); - src = drawimage(client, a+5); - font = drawlookup(client, BGLONG(a+9), 1); - if(font == 0) - error(Enodrawimage); - if(font->nfchar == 0) - error(Enotfont); - drawpoint(&p, a+13); - drawrectangle(&r, a+21); - drawpoint(&sp, a+37); - ni = BGSHORT(a+45); - u = a+m; - m += ni*2; - if(n < m) - error(Eshortdraw); - clipr = dst->clipr; - dst->clipr = r; - op = drawclientop(client); - l = dst; - if(*a == 'x'){ - /* paint background */ - l = drawimage(client, a+47); - drawpoint(&q, a+51); - r.min.x = p.x; - r.min.y = p.y-font->ascent; - r.max.x = p.x; - r.max.y = r.min.y+Dy(font->image->r); - j = ni; - while(--j >= 0){ - ci = BGSHORT(u); - if(ci<0 || ci>=font->nfchar){ - dst->clipr = clipr; - error(Eindex); - } - r.max.x += font->fchar[ci].width; - u += 2; - } - memdraw(dst, r, l, q, memopaque, ZP, op); - u -= 2*ni; - } - q = p; - while(--ni >= 0){ - ci = BGSHORT(u); - if(ci<0 || ci>=font->nfchar){ - dst->clipr = clipr; - error(Eindex); - } - q = drawchar(dst, l, q, src, &sp, font, ci, op); - u += 2; - } - dst->clipr = clipr; - p.y -= font->ascent; - dstflush(dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r))); - continue; - - /* use public screen: 'S' id[4] chan[4] */ - case 'S': - printmesg(fmt="Ll", a, 0); - m = 1+4+4; - if(n < m) - error(Eshortdraw); - dstid = BGLONG(a+1); - if(dstid == 0) - error(Ebadarg); - dscrn = drawlookupdscreen(dstid); - if(dscrn==0 || (dscrn->public==0 && dscrn->owner!=client)) - error(Enodrawscreen); - if(dscrn->screen->image->chan != BGLONG(a+5)) - error("inconsistent chan"); - if(drawinstallscreen(client, dscrn, 0, 0, 0, 0) == 0) - error(Edrawmem); - continue; - - /* top or bottom windows: 't' top[1] nw[2] n*id[4] */ - case 't': - printmesg(fmt="bsL", a, 0); - m = 1+1+2; - if(n < m) - error(Eshortdraw); - nw = BGSHORT(a+2); - if(nw < 0) - error(Ebadarg); - if(nw == 0) - continue; - m += nw*4; - if(n < m) - error(Eshortdraw); - lp = malloc(nw*sizeof(Memimage*)); - if(lp == 0) - error(Enomem); - if(waserror()){ - free(lp); - nexterror(); - } - for(j=0; j<nw; j++) - lp[j] = drawimage(client, a+1+1+2+j*4); - if(lp[0]->layer == 0) - error("images are not windows"); - for(j=1; j<nw; j++) - if(lp[j]->layer->screen != lp[0]->layer->screen) - error("images not on same screen"); - if(a[1]) - memltofrontn(lp, nw); - else - memltorearn(lp, nw); - if(lp[0]->layer->screen->image->data == screenimage->data) - for(j=0; j<nw; j++) - addflush(lp[j]->layer->screenr); - ll = drawlookup(client, BGLONG(a+1+1+2), 1); - drawrefreshscreen(ll, client); - poperror(); - free(lp); - continue; - - /* visible: 'v' */ - case 'v': - printmesg(fmt="", a, 0); - m = 1; - drawflush(); - continue; - - /* write: 'y' id[4] R[4*4] data[x*1] */ - /* write from compressed data: 'Y' id[4] R[4*4] data[x*1] */ - case 'y': - case 'Y': - printmesg(fmt="LR", a, 0); - // iprint("load %c\n", *a); - m = 1+4+4*4; - if(n < m) - error(Eshortdraw); - dstid = BGLONG(a+1); - dst = drawimage(client, a+1); - drawrectangle(&r, a+5); - if(!rectinrect(r, dst->r)) - error(Ewriteoutside); - y = memload(dst, r, a+m, n-m, *a=='Y'); - if(y < 0) - error("bad writeimage call"); - dstflush(dstid, dst, r); - m += y; - continue; - } - } - poperror(); -} - -Dev drawdevtab = { - 'i', - "draw", - - devreset, - devinit, - devshutdown, - drawattach, - drawwalk, - drawstat, - drawopen, - devcreate, - drawclose, - drawread, - devbread, - drawwrite, - devbwrite, - devremove, - devwstat, -}; - -/* - * On 8 bit displays, load the default color map - */ -void -drawcmap(void) -{ - int r, g, b, cr, cg, cb, v; - int num, den; - int i, j; - - drawactive(1); /* to restore map from backup */ - for(r=0,i=0; r!=4; r++) - for(v=0; v!=4; v++,i+=16){ - for(g=0,j=v-r; g!=4; g++) - for(b=0;b!=4;b++,j++){ - den = r; - if(g > den) - den = g; - if(b > den) - den = b; - if(den == 0) /* divide check -- pick grey shades */ - cr = cg = cb = v*17; - else{ - num = 17*(4*den+v); - cr = r*num/den; - cg = g*num/den; - cb = b*num/den; - } - setcolor(i+(j&15), - cr*0x01010101, cg*0x01010101, cb*0x01010101); - } - } -} - -void -drawblankscreen(int blank) -{ - int i, nc; - ulong *p; - - if(blank == sdraw.blanked) - return; - if(!canqlock(&sdraw.lk)) - return; - if(!initscreenimage()){ - qunlock(&sdraw.lk); - return; - } - p = sdraw.savemap; - nc = screenimage->depth > 8 ? 256 : 1<<screenimage->depth; - - /* - * blankscreen uses the hardware to blank the screen - * when possible. to help in cases when it is not possible, - * we set the color map to be all black. - */ - if(blank == 0){ /* turn screen on */ - for(i=0; i<nc; i++, p+=3) - setcolor(i, p[0], p[1], p[2]); - // blankscreen(0); - }else{ /* turn screen off */ - // blankscreen(1); - for(i=0; i<nc; i++, p+=3){ - getcolor(i, &p[0], &p[1], &p[2]); - setcolor(i, 0, 0, 0); - } - } - sdraw.blanked = blank; - qunlock(&sdraw.lk); -} - -/* - * record activity on screen, changing blanking as appropriate - */ -void -drawactive(int active) -{ -/* - if(active){ - drawblankscreen(0); - sdraw.blanktime = MACHP(0)->ticks; - }else{ - if(blanktime && sdraw.blanktime && TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60 >= blanktime) - drawblankscreen(1); - } -*/ -} - -int -drawidletime(void) -{ - return 0; -/* return TK2SEC(MACHP(0)->ticks - sdraw.blanktime)/60; */ -} - diff --git a/sys/src/cmd/unix/drawterm/kern/devfs-posix.c b/sys/src/cmd/unix/drawterm/kern/devfs-posix.c deleted file mode 100644 index 23a7dbc4f..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devfs-posix.c +++ /dev/null @@ -1,635 +0,0 @@ -#include "u.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> /* for remove, rename */ -#include <limits.h> - -#ifndef NAME_MAX -# define NAME_MAX 256 -#endif -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - - -typedef struct Ufsinfo Ufsinfo; - -enum -{ - NUID = 256, - NGID = 256, - MAXPATH = 1024, - MAXCOMP = 128 -}; - -struct Ufsinfo -{ - int mode; - int fd; - int uid; - int gid; - DIR* dir; - vlong offset; - QLock oq; - char nextname[NAME_MAX]; -}; - -char *base = "/"; - -static Qid fsqid(char*, struct stat *); -static void fspath(Chan*, char*, char*); -static ulong fsdirread(Chan*, uchar*, int, ulong); -static int fsomode(int); - -/* clumsy hack, but not worse than the Path stuff in the last one */ -static char* -uc2name(Chan *c) -{ - char *s; - - if(c->name == nil) - return "/"; - s = c2name(c); - if(s[0]=='#' && s[1]=='U') - return s+2; - return s; -} - -static char* -lastelem(Chan *c) -{ - char *s, *t; - - s = uc2name(c); - if((t = strrchr(s, '/')) == nil) - return s; - if(t[1] == 0) - return t; - return t+1; -} - -static Chan* -fsattach(char *spec) -{ - Chan *c; - struct stat stbuf; - static int devno; - Ufsinfo *uif; - - if(stat(base, &stbuf) < 0) - error(strerror(errno)); - - c = devattach('U', spec); - - uif = mallocz(sizeof(Ufsinfo), 1); - uif->mode = stbuf.st_mode; - uif->uid = stbuf.st_uid; - uif->gid = stbuf.st_gid; - - c->aux = uif; - c->dev = devno++; - c->qid.type = QTDIR; -/*print("fsattach %s\n", c2name(c));*/ - - return c; -} - -static Chan* -fsclone(Chan *c, Chan *nc) -{ - Ufsinfo *uif; - - uif = mallocz(sizeof(Ufsinfo), 1); - *uif = *(Ufsinfo*)c->aux; - nc->aux = uif; - - return nc; -} - -static int -fswalk1(Chan *c, char *name) -{ - struct stat stbuf; - char path[MAXPATH]; - Ufsinfo *uif; - - fspath(c, name, path); - - /*print("** fs walk '%s' -> %s\n", path, name); */ - - if(stat(path, &stbuf) < 0) - return 0; - - uif = c->aux; - - uif->mode = stbuf.st_mode; - uif->uid = stbuf.st_uid; - uif->gid = stbuf.st_gid; - - c->qid = fsqid(path, &stbuf); - - return 1; -} - -extern Cname* addelem(Cname*, char*); - -static Walkqid* -fswalk(Chan *c, Chan *nc, char **name, int nname) -{ - int i; - Cname *cname; - Walkqid *wq; - - if(nc != nil) - panic("fswalk: nc != nil"); - wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); - nc = devclone(c); - cname = c->name; - incref(&cname->ref); - - fsclone(c, nc); - wq->clone = nc; - for(i=0; i<nname; i++){ - nc->name = cname; - if(fswalk1(nc, name[i]) == 0) - break; - cname = addelem(cname, name[i]); - wq->qid[i] = nc->qid; - } - nc->name = cname; - if(i != nname){ - cclose(nc); - wq->clone = nil; - } - wq->nqid = i; - return wq; -} - -static int -fsstat(Chan *c, uchar *buf, int n) -{ - Dir d; - struct stat stbuf; - char path[MAXPATH]; - - if(n < BIT16SZ) - error(Eshortstat); - - fspath(c, 0, path); - if(stat(path, &stbuf) < 0) - error(strerror(errno)); - - d.name = lastelem(c); - d.uid = "unknown"; - d.gid = "unknown"; - d.muid = "unknown"; - d.qid = c->qid; - d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777); - d.atime = stbuf.st_atime; - d.mtime = stbuf.st_mtime; - d.length = stbuf.st_size; - d.type = 'U'; - d.dev = c->dev; - return convD2M(&d, buf, n); -} - -static Chan* -fsopen(Chan *c, int mode) -{ - char path[MAXPATH]; - int m, isdir; - Ufsinfo *uif; - -/*print("fsopen %s\n", c2name(c));*/ - m = mode & (OTRUNC|3); - switch(m) { - case 0: - break; - case 1: - case 1|16: - break; - case 2: - case 0|16: - case 2|16: - break; - case 3: - break; - default: - error(Ebadarg); - } - - isdir = c->qid.type & QTDIR; - - if(isdir && mode != OREAD) - error(Eperm); - - m = fsomode(m & 3); - c->mode = openmode(mode); - - uif = c->aux; - - fspath(c, 0, path); - if(isdir) { - uif->dir = opendir(path); - if(uif->dir == 0) - error(strerror(errno)); - } - else { - if(mode & OTRUNC) - m |= O_TRUNC; - uif->fd = open(path, m, 0666); - - if(uif->fd < 0) - error(strerror(errno)); - } - uif->offset = 0; - - c->offset = 0; - c->flag |= COPEN; - return c; -} - -static void -fscreate(Chan *c, char *name, int mode, ulong perm) -{ - int fd, m; - char path[MAXPATH]; - struct stat stbuf; - Ufsinfo *uif; - - m = fsomode(mode&3); - - fspath(c, name, path); - - uif = c->aux; - - if(perm & DMDIR) { - if(m) - error(Eperm); - - if(mkdir(path, perm & 0777) < 0) - error(strerror(errno)); - - fd = open(path, 0); - if(fd >= 0) { - chmod(path, perm & 0777); - chown(path, uif->uid, uif->uid); - } - close(fd); - - uif->dir = opendir(path); - if(uif->dir == 0) - error(strerror(errno)); - } - else { - fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666); - if(fd >= 0) { - if(m != 1) { - close(fd); - fd = open(path, m); - } - chmod(path, perm & 0777); - chown(path, uif->uid, uif->gid); - } - if(fd < 0) - error(strerror(errno)); - uif->fd = fd; - } - - if(stat(path, &stbuf) < 0) - error(strerror(errno)); - c->qid = fsqid(path, &stbuf); - c->offset = 0; - c->flag |= COPEN; - c->mode = openmode(mode); -} - -static void -fsclose(Chan *c) -{ - Ufsinfo *uif; - - uif = c->aux; - - if(c->flag & COPEN) { - if(c->qid.type & QTDIR) - closedir(uif->dir); - else - close(uif->fd); - } - - free(uif); -} - -static long -fsread(Chan *c, void *va, long n, vlong offset) -{ - int fd, r; - Ufsinfo *uif; - -/*print("fsread %s\n", c2name(c));*/ - if(c->qid.type & QTDIR) - return fsdirread(c, va, n, offset); - - uif = c->aux; - qlock(&uif->oq); - if(waserror()) { - qunlock(&uif->oq); - nexterror(); - } - fd = uif->fd; - if(uif->offset != offset) { - r = lseek(fd, offset, 0); - if(r < 0) - error(strerror(errno)); - uif->offset = offset; - } - - n = read(fd, va, n); - if(n < 0) - error(strerror(errno)); - - uif->offset += n; - qunlock(&uif->oq); - poperror(); - - return n; -} - -static long -fswrite(Chan *c, void *va, long n, vlong offset) -{ - int fd, r; - Ufsinfo *uif; - - uif = c->aux; - - qlock(&uif->oq); - if(waserror()) { - qunlock(&uif->oq); - nexterror(); - } - fd = uif->fd; - if(uif->offset != offset) { - r = lseek(fd, offset, 0); - if(r < 0) - error(strerror(errno)); - uif->offset = offset; - } - - n = write(fd, va, n); - if(n < 0) - error(strerror(errno)); - - uif->offset += n; - qunlock(&uif->oq); - poperror(); - - return n; -} - -static void -fsremove(Chan *c) -{ - int n; - char path[MAXPATH]; - - fspath(c, 0, path); - if(c->qid.type & QTDIR) - n = rmdir(path); - else - n = remove(path); - if(n < 0) - error(strerror(errno)); -} - -int -fswstat(Chan *c, uchar *buf, int n) -{ - Dir d; - struct stat stbuf; - char old[MAXPATH], new[MAXPATH]; - char strs[MAXPATH*3], *p; - Ufsinfo *uif; - - if(convM2D(buf, n, &d, strs) != n) - error(Ebadstat); - - fspath(c, 0, old); - if(stat(old, &stbuf) < 0) - error(strerror(errno)); - - uif = c->aux; - - if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) { - fspath(c, 0, old); - strcpy(new, old); - p = strrchr(new, '/'); - strcpy(p+1, d.name); - if(rename(old, new) < 0) - error(strerror(errno)); - } - - fspath(c, 0, old); - if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) { - if(chmod(old, d.mode&0777) < 0) - error(strerror(errno)); - uif->mode &= ~0777; - uif->mode |= d.mode&0777; - } -/* - p = name2pass(gid, d.gid); - if(p == 0) - error(Eunknown); - - if(p->id != stbuf.st_gid) { - if(chown(old, stbuf.st_uid, p->id) < 0) - error(strerror(errno)); - - uif->gid = p->id; - } -*/ - return n; -} - -static Qid -fsqid(char *p, struct stat *st) -{ - Qid q; - int dev; - ulong h; - static int nqdev; - static uchar *qdev; - - if(qdev == 0) - qdev = mallocz(65536U, 1); - - q.type = 0; - if((st->st_mode&S_IFMT) == S_IFDIR) - q.type = QTDIR; - - dev = st->st_dev & 0xFFFFUL; - if(qdev[dev] == 0) - qdev[dev] = ++nqdev; - - h = 0; - while(*p != '\0') - h += *p++ * 13; - - q.path = (vlong)qdev[dev]<<32; - q.path |= h; - q.vers = st->st_mtime; - - return q; -} - -static void -fspath(Chan *c, char *ext, char *path) -{ - strcpy(path, base); - strcat(path, "/"); - strcat(path, uc2name(c)); - if(ext){ - strcat(path, "/"); - strcat(path, ext); - } - cleanname(path); -} - -static int -isdots(char *name) -{ - if(name[0] != '.') - return 0; - if(name[1] == '\0') - return 1; - if(name[1] != '.') - return 0; - if(name[2] == '\0') - return 1; - return 0; -} - -static int -p9readdir(char *name, Ufsinfo *uif) -{ - struct dirent *de; - - if(uif->nextname[0]){ - strcpy(name, uif->nextname); - uif->nextname[0] = 0; - return 1; - } - - de = readdir(uif->dir); - if(de == NULL) - return 0; - - strcpy(name, de->d_name); - return 1; -} - -static ulong -fsdirread(Chan *c, uchar *va, int count, ulong offset) -{ - int i; - Dir d; - long n; - char de[NAME_MAX]; - struct stat stbuf; - char path[MAXPATH], dirpath[MAXPATH]; - Ufsinfo *uif; - -/*print("fsdirread %s\n", c2name(c));*/ - i = 0; - uif = c->aux; - - errno = 0; - if(uif->offset != offset) { - if(offset != 0) - error("bad offset in fsdirread"); - uif->offset = offset; /* sync offset */ - uif->nextname[0] = 0; - rewinddir(uif->dir); - } - - fspath(c, 0, dirpath); - - while(i+BIT16SZ < count) { - if(!p9readdir(de, uif)) - break; - - if(de[0]==0 || isdots(de)) - continue; - - d.name = de; - sprint(path, "%s/%s", dirpath, de); - memset(&stbuf, 0, sizeof stbuf); - - if(stat(path, &stbuf) < 0) { - /* fprint(2, "dir: bad path %s\n", path); */ - /* but continue... probably a bad symlink */ - } - - d.uid = "unknown"; - d.gid = "unknown"; - d.muid = "unknown"; - d.qid = fsqid(path, &stbuf); - d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777); - d.atime = stbuf.st_atime; - d.mtime = stbuf.st_mtime; - d.length = stbuf.st_size; - d.type = 'U'; - d.dev = c->dev; - n = convD2M(&d, (uchar*)va+i, count-i); - if(n == BIT16SZ){ - strcpy(uif->nextname, de); - break; - } - i += n; - } -/*print("got %d\n", i);*/ - uif->offset += i; - return i; -} - -static int -fsomode(int m) -{ - switch(m) { - case 0: /* OREAD */ - case 3: /* OEXEC */ - return 0; - case 1: /* OWRITE */ - return 1; - case 2: /* ORDWR */ - return 2; - } - error(Ebadarg); - return 0; -} - -Dev fsdevtab = { - 'U', - "fs", - - devreset, - devinit, - devshutdown, - fsattach, - fswalk, - fsstat, - fsopen, - fscreate, - fsclose, - fsread, - devbread, - fswrite, - devbwrite, - fsremove, - fswstat, -}; diff --git a/sys/src/cmd/unix/drawterm/kern/devfs-win32.c b/sys/src/cmd/unix/drawterm/kern/devfs-win32.c deleted file mode 100644 index 9997bd027..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devfs-win32.c +++ /dev/null @@ -1,707 +0,0 @@ -/* - * Disable Unicode until the calls to FindFirstFile etc - * are changed to use wide character strings. - */ -#undef UNICODE -#include <windows.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#ifndef NAME_MAX -# define NAME_MAX 256 -#endif -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -typedef struct DIR DIR; -typedef struct Ufsinfo Ufsinfo; - -enum -{ - NUID = 256, - NGID = 256, - MAXPATH = 1024, - MAXCOMP = 128 -}; - -struct DIR -{ - HANDLE handle; - char* path; - int index; - WIN32_FIND_DATA wfd; -}; - -struct Ufsinfo -{ - int mode; - int fd; - int uid; - int gid; - DIR* dir; - ulong offset; - QLock oq; - char nextname[NAME_MAX]; -}; - -DIR* opendir(char*); -int readdir(char*, DIR*); -void closedir(DIR*); -void rewinddir(DIR*); - -char *base = "c:/."; - -static Qid fsqid(char*, struct stat *); -static void fspath(Chan*, char*, char*); -// static void fsperm(Chan*, int); -static ulong fsdirread(Chan*, uchar*, int, ulong); -static int fsomode(int); -static int chown(char *path, int uid, int); - -/* clumsy hack, but not worse than the Path stuff in the last one */ -static char* -uc2name(Chan *c) -{ - char *s; - - if(c->name == nil) - return "/"; - s = c2name(c); - if(s[0]=='#' && s[1]=='U') - return s+2; - return s; -} - -static char* -lastelem(Chan *c) -{ - char *s, *t; - - s = uc2name(c); - if((t = strrchr(s, '/')) == nil) - return s; - if(t[1] == 0) - return t; - return t+1; -} - -static Chan* -fsattach(char *spec) -{ - Chan *c; - struct stat stbuf; - static int devno; - Ufsinfo *uif; - - if(stat(base, &stbuf) < 0) - error(strerror(errno)); - - c = devattach('U', spec); - - uif = mallocz(sizeof(Ufsinfo), 1); - uif->gid = stbuf.st_gid; - uif->uid = stbuf.st_uid; - uif->mode = stbuf.st_mode; - - c->aux = uif; - c->dev = devno++; - c->qid.type = QTDIR; -/*print("fsattach %s\n", c2name(c));*/ - - return c; -} - -static Chan* -fsclone(Chan *c, Chan *nc) -{ - Ufsinfo *uif; - - uif = mallocz(sizeof(Ufsinfo), 1); - *uif = *(Ufsinfo*)c->aux; - nc->aux = uif; - - return nc; -} - -static int -fswalk1(Chan *c, char *name) -{ - struct stat stbuf; - char path[MAXPATH]; - Ufsinfo *uif; - - fspath(c, name, path); - - /* print("** fs walk '%s' -> %s\n", path, name); */ - - if(stat(path, &stbuf) < 0) - return 0; - - uif = c->aux; - - uif->gid = stbuf.st_gid; - uif->uid = stbuf.st_uid; - uif->mode = stbuf.st_mode; - - c->qid = fsqid(path, &stbuf); - - return 1; -} - -extern Cname* addelem(Cname*, char*); - -static Walkqid* -fswalk(Chan *c, Chan *nc, char **name, int nname) -{ - int i; - Cname *cname; - Walkqid *wq; - - if(nc != nil) - panic("fswalk: nc != nil"); - wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); - nc = devclone(c); - cname = c->name; - incref(&cname->ref); - - fsclone(c, nc); - wq->clone = nc; - for(i=0; i<nname; i++){ - nc->name = cname; - if(fswalk1(nc, name[i]) == 0) - break; - cname = addelem(cname, name[i]); - wq->qid[i] = nc->qid; - } - nc->name = cname; - if(i != nname){ - cclose(nc); - wq->clone = nil; - } - wq->nqid = i; - return wq; -} - -static int -fsstat(Chan *c, uchar *buf, int n) -{ - Dir d; - struct stat stbuf; - char path[MAXPATH]; - - if(n < BIT16SZ) - error(Eshortstat); - - fspath(c, 0, path); - if(stat(path, &stbuf) < 0) - error(strerror(errno)); - - d.name = lastelem(c); - d.uid = "unknown"; - d.gid = "unknown"; - d.muid = "unknown"; - d.qid = c->qid; - d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777); - d.atime = stbuf.st_atime; - d.mtime = stbuf.st_mtime; - d.length = stbuf.st_size; - d.type = 'U'; - d.dev = c->dev; - return convD2M(&d, buf, n); -} - -static Chan* -fsopen(Chan *c, int mode) -{ - char path[MAXPATH]; - int m, isdir; - Ufsinfo *uif; - -/*print("fsopen %s\n", c2name(c));*/ - m = mode & (OTRUNC|3); - switch(m) { - case 0: - break; - case 1: - case 1|16: - break; - case 2: - case 0|16: - case 2|16: - break; - case 3: - break; - default: - error(Ebadarg); - } - - isdir = c->qid.type & QTDIR; - - if(isdir && mode != OREAD) - error(Eperm); - - m = fsomode(m & 3); - c->mode = openmode(mode); - - uif = c->aux; - - fspath(c, 0, path); - if(isdir) { - uif->dir = opendir(path); - if(uif->dir == 0) - error(strerror(errno)); - } - else { - if(mode & OTRUNC) - m |= O_TRUNC; - uif->fd = open(path, m|_O_BINARY, 0666); - - if(uif->fd < 0) - error(strerror(errno)); - } - uif->offset = 0; - - c->offset = 0; - c->flag |= COPEN; - return c; -} - -static void -fscreate(Chan *c, char *name, int mode, ulong perm) -{ - int fd, m; - char path[MAXPATH]; - struct stat stbuf; - Ufsinfo *uif; - - m = fsomode(mode&3); - - fspath(c, name, path); - - uif = c->aux; - - if(perm & DMDIR) { - if(m) - error(Eperm); - - if(mkdir(path) < 0) - error(strerror(errno)); - - fd = open(path, 0); - if(fd >= 0) { - chmod(path, perm & 0777); - chown(path, uif->uid, uif->uid); - } - close(fd); - - uif->dir = opendir(path); - if(uif->dir == 0) - error(strerror(errno)); - } - else { - fd = open(path, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, 0666); - if(fd >= 0) { - if(m != 1) { - close(fd); - fd = open(path, m|_O_BINARY); - } - chmod(path, perm & 0777); - chown(path, uif->uid, uif->gid); - } - if(fd < 0) - error(strerror(errno)); - uif->fd = fd; - } - - if(stat(path, &stbuf) < 0) - error(strerror(errno)); - c->qid = fsqid(path, &stbuf); - c->offset = 0; - c->flag |= COPEN; - c->mode = openmode(mode); -} - -static void -fsclose(Chan *c) -{ - Ufsinfo *uif; - - uif = c->aux; - - if(c->flag & COPEN) { - if(c->qid.type & QTDIR) - closedir(uif->dir); - else - close(uif->fd); - } - - free(uif); -} - -static long -fsread(Chan *c, void *va, long n, vlong offset) -{ - int fd, r; - Ufsinfo *uif; - -/*print("fsread %s\n", c2name(c));*/ - if(c->qid.type & QTDIR) - return fsdirread(c, va, n, offset); - - uif = c->aux; - qlock(&uif->oq); - if(waserror()) { - qunlock(&uif->oq); - nexterror(); - } - fd = uif->fd; - if(uif->offset != offset) { - r = lseek(fd, offset, 0); - if(r < 0) - error(strerror(errno)); - uif->offset = offset; - } - - n = read(fd, va, n); - if(n < 0) - error(strerror(errno)); - - uif->offset += n; - qunlock(&uif->oq); - poperror(); - - return n; -} - -static long -fswrite(Chan *c, void *va, long n, vlong offset) -{ - int fd, r; - Ufsinfo *uif; - - uif = c->aux; - - qlock(&uif->oq); - if(waserror()) { - qunlock(&uif->oq); - nexterror(); - } - fd = uif->fd; - if(uif->offset != offset) { - r = lseek(fd, offset, 0); - if(r < 0) - error(strerror(errno)); - uif->offset = offset; - } - - n = write(fd, va, n); - if(n < 0) - error(strerror(errno)); - - uif->offset += n; - qunlock(&uif->oq); - poperror(); - - return n; -} - -static void -fsremove(Chan *c) -{ - int n; - char path[MAXPATH]; - - fspath(c, 0, path); - if(c->qid.type & QTDIR) - n = rmdir(path); - else - n = remove(path); - if(n < 0) - error(strerror(errno)); -} - -static int -fswstat(Chan *c, uchar *buf, int n) -{ - Dir d; - struct stat stbuf; - char old[MAXPATH], new[MAXPATH]; - char strs[MAXPATH*3], *p; - Ufsinfo *uif; - - if (convM2D(buf, n, &d, strs) != n) - error(Ebadstat); - - fspath(c, 0, old); - if(stat(old, &stbuf) < 0) - error(strerror(errno)); - - uif = c->aux; - -// if(uif->uid != stbuf.st_uid) -// error(Eowner); - - if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) { - fspath(c, 0, old); - strcpy(new, old); - p = strrchr(new, '/'); - strcpy(p+1, d.name); - if(rename(old, new) < 0) - error(strerror(errno)); - } - - fspath(c, 0, old); - if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) { - if(chmod(old, d.mode&0777) < 0) - error(strerror(errno)); - uif->mode &= ~0777; - uif->mode |= d.mode&0777; - } -/* - p = name2pass(gid, d.gid); - if(p == 0) - error(Eunknown); - - if(p->id != stbuf.st_gid) { - if(chown(old, stbuf.st_uid, p->id) < 0) - error(sys_errlist[errno]); - - uif->gid = p->id; - } -*/ - return n; -} - -static Qid -fsqid(char *p, struct stat *st) -{ - Qid q; - int dev; - ulong h; - static int nqdev; - static uchar *qdev; - - if(qdev == 0) - qdev = mallocz(65536U, 1); - - q.type = 0; - if((st->st_mode&S_IFMT) == S_IFDIR) - q.type = QTDIR; - - dev = st->st_dev & 0xFFFFUL; - if(qdev[dev] == 0) - qdev[dev] = ++nqdev; - - h = 0; - while(*p != '\0') - h += *p++ * 13; - - q.path = (vlong)qdev[dev]<<32; - q.path |= h; - q.vers = st->st_mtime; - - return q; -} - -static void -fspath(Chan *c, char *ext, char *path) -{ - strcpy(path, base); - strcat(path, "/"); - strcat(path, uc2name(c)); - if(ext) { - strcat(path, "/"); - strcat(path, ext); - } - cleanname(path); -} - -static int -isdots(char *name) -{ - if(name[0] != '.') - return 0; - if(name[1] == '\0') - return 1; - if(name[1] != '.') - return 0; - if(name[2] == '\0') - return 1; - return 0; -} - -static int -p9readdir(char *name, Ufsinfo *uif) -{ - if(uif->nextname[0]){ - strcpy(name, uif->nextname); - uif->nextname[0] = 0; - return 1; - } - - return readdir(name, uif->dir); -} - -static ulong -fsdirread(Chan *c, uchar *va, int count, ulong offset) -{ - int i; - Dir d; - long n; - char de[NAME_MAX]; - struct stat stbuf; - char path[MAXPATH], dirpath[MAXPATH]; - Ufsinfo *uif; - -/*print("fsdirread %s\n", c2name(c));*/ - i = 0; - uif = c->aux; - - errno = 0; - if(uif->offset != offset) { - if(offset != 0) - error("bad offset in fsdirread"); - uif->offset = offset; /* sync offset */ - uif->nextname[0] = 0; - rewinddir(uif->dir); - } - - fspath(c, 0, dirpath); - - while(i+BIT16SZ < count) { - if(!p9readdir(de, uif)) - break; - - if(de[0]==0 || isdots(de)) - continue; - - d.name = de; - sprint(path, "%s/%s", dirpath, de); - memset(&stbuf, 0, sizeof stbuf); - - if(stat(path, &stbuf) < 0) { - print("dir: bad path %s\n", path); - /* but continue... probably a bad symlink */ - } - - d.uid = "unknown"; - d.gid = "unknown"; - d.muid = "unknown"; - d.qid = fsqid(path, &stbuf); - d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777); - d.atime = stbuf.st_atime; - d.mtime = stbuf.st_mtime; - d.length = stbuf.st_size; - d.type = 'U'; - d.dev = c->dev; - n = convD2M(&d, (uchar*)va+i, count-i); - if(n == BIT16SZ){ - strcpy(uif->nextname, de); - break; - } - i += n; - } -/*print("got %d\n", i);*/ - uif->offset += i; - return i; -} - -static int -fsomode(int m) -{ - switch(m) { - case 0: /* OREAD */ - case 3: /* OEXEC */ - return 0; - case 1: /* OWRITE */ - return 1; - case 2: /* ORDWR */ - return 2; - } - error(Ebadarg); - return 0; -} -void -closedir(DIR *d) -{ - FindClose(d->handle); - free(d->path); -} - -int -readdir(char *name, DIR *d) -{ - if(d->index != 0) { - if(FindNextFile(d->handle, &d->wfd) == FALSE) - return 0; - } - strcpy(name, (char*)d->wfd.cFileName); - d->index++; - - return 1; -} - -void -rewinddir(DIR *d) -{ - FindClose(d->handle); - d->handle = FindFirstFile(d->path, &d->wfd); - d->index = 0; -} - -static int -chown(char *path, int uid, int perm) -{ -/* panic("chown"); */ - return 0; -} - -DIR* -opendir(char *p) -{ - DIR *d; - char path[MAX_PATH]; - - - snprint(path, sizeof(path), "%s/*.*", p); - - d = mallocz(sizeof(DIR), 1); - if(d == 0) - return 0; - - d->index = 0; - - d->handle = FindFirstFile(path, &d->wfd); - if(d->handle == INVALID_HANDLE_VALUE) { - free(d); - return 0; - } - - d->path = strdup(path); - return d; -} - -Dev fsdevtab = { - 'U', - "fs", - - devreset, - devinit, - devshutdown, - fsattach, - fswalk, - fsstat, - fsopen, - fscreate, - fsclose, - fsread, - devbread, - fswrite, - devbwrite, - fsremove, - fswstat, -}; diff --git a/sys/src/cmd/unix/drawterm/kern/devip-posix.c b/sys/src/cmd/unix/drawterm/kern/devip-posix.c deleted file mode 100644 index 7f6171e4e..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devip-posix.c +++ /dev/null @@ -1,210 +0,0 @@ -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <netdb.h> - -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#include "devip.h" - -#undef listen -#undef accept -#undef bind - -void -osipinit(void) -{ - char buf[1024]; - gethostname(buf, sizeof(buf)); - kstrdup(&sysname, buf); - -} - -int -so_socket(int type) -{ - int fd, one; - - switch(type) { - default: - error("bad protocol type"); - case S_TCP: - type = SOCK_STREAM; - break; - case S_UDP: - type = SOCK_DGRAM; - break; - } - - fd = socket(AF_INET, type, 0); - if(fd < 0) - oserror(); - - one = 1; - if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0){ - oserrstr(); - print("setsockopt: %r"); - } - - return fd; -} - - -void -so_connect(int fd, unsigned long raddr, unsigned short rport) -{ - struct sockaddr_in sin; - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, rport); - hnputl(&sin.sin_addr.s_addr, raddr); - - if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) - oserror(); -} - -void -so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) -{ - socklen_t len; - struct sockaddr_in sin; - - len = sizeof(sin); - if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0) - oserror(); - - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *laddr = nhgetl(&sin.sin_addr.s_addr); - *lport = nhgets(&sin.sin_port); -} - -void -so_listen(int fd) -{ - if(listen(fd, 5) < 0) - oserror(); -} - -int -so_accept(int fd, unsigned long *raddr, unsigned short *rport) -{ - int nfd; - socklen_t len; - struct sockaddr_in sin; - - len = sizeof(sin); - nfd = accept(fd, (struct sockaddr*)&sin, &len); - if(nfd < 0) - oserror(); - - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *raddr = nhgetl(&sin.sin_addr.s_addr); - *rport = nhgets(&sin.sin_port); - return nfd; -} - -void -so_bind(int fd, int su, unsigned short port) -{ - int i, one; - struct sockaddr_in sin; - - one = 1; - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ - oserrstr(); - print("setsockopt: %r"); - } - - if(su) { - for(i = 600; i < 1024; i++) { - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = i; - - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0) - return; - } - oserror(); - } - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, port); - - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) - oserror(); -} - -int -so_gethostbyname(char *host, char**hostv, int n) -{ - int i; - char buf[32]; - unsigned char *p; - struct hostent *hp; - - hp = gethostbyname(host); - if(hp == 0) - return 0; - - for(i = 0; hp->h_addr_list[i] && i < n; i++) { - p = (unsigned char*)hp->h_addr_list[i]; - sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - hostv[i] = strdup(buf); - if(hostv[i] == 0) - break; - } - return i; -} - -char* -hostlookup(char *host) -{ - char buf[100]; - uchar *p; - struct hostent *he; - - he = gethostbyname(host); - if(he != 0 && he->h_addr_list[0]) { - p = (uchar*)he->h_addr_list[0]; - sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); - } else - strcpy(buf, host); - - return strdup(buf); -} - -int -so_getservbyname(char *service, char *net, char *port) -{ - struct servent *s; - - s = getservbyname(service, net); - if(s == 0) - return -1; - - sprint(port, "%d", nhgets(&s->s_port)); - return 0; -} - -int -so_send(int fd, void *d, int n, int f) -{ - return send(fd, d, n, f); -} - -int -so_recv(int fd, void *d, int n, int f) -{ - return recv(fd, d, n, f); -} diff --git a/sys/src/cmd/unix/drawterm/kern/devip-win32.c b/sys/src/cmd/unix/drawterm/kern/devip-win32.c deleted file mode 100644 index 3caa67ad1..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devip-win32.c +++ /dev/null @@ -1,212 +0,0 @@ -#include <windows.h> -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#include "devip.h" - -#ifdef MSVC -#pragma comment(lib, "wsock32.lib") -#endif - -#undef listen -#undef accept -#undef bind - -void -osipinit(void) -{ - WSADATA wasdat; - char buf[1024]; - - if(WSAStartup(MAKEWORD(1, 1), &wasdat) != 0) - panic("no winsock.dll"); - - gethostname(buf, sizeof(buf)); - kstrdup(&sysname, buf); -} - -int -so_socket(int type) -{ - int fd, one; - - switch(type) { - default: - error("bad protocol type"); - case S_TCP: - type = SOCK_STREAM; - break; - case S_UDP: - type = SOCK_DGRAM; - break; - } - - fd = socket(AF_INET, type, 0); - if(fd < 0) - oserror(); - - one = 1; - if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0){ - oserrstr(); - print("setsockopt: %s\n", up->errstr); - } - - return fd; -} - - -void -so_connect(int fd, unsigned long raddr, unsigned short rport) -{ - struct sockaddr_in sin; - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, rport); - hnputl(&sin.sin_addr.s_addr, raddr); - - if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) - oserror(); -} - -void -so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) -{ - int len; - struct sockaddr_in sin; - - len = sizeof(sin); - if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0) - oserror(); - - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *laddr = nhgetl(&sin.sin_addr.s_addr); - *lport = nhgets(&sin.sin_port); -} - -void -so_listen(int fd) -{ - if(listen(fd, 5) < 0) - oserror(); -} - -int -so_accept(int fd, unsigned long *raddr, unsigned short *rport) -{ - int nfd, len; - struct sockaddr_in sin; - - len = sizeof(sin); - nfd = accept(fd, (struct sockaddr*)&sin, &len); - if(nfd < 0) - oserror(); - - if(sin.sin_family != AF_INET || len != sizeof(sin)) - error("not AF_INET"); - - *raddr = nhgetl(&sin.sin_addr.s_addr); - *rport = nhgets(&sin.sin_port); - return nfd; -} - -void -so_bind(int fd, int su, unsigned short port) -{ - int i, one; - struct sockaddr_in sin; - - one = 1; - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ - oserrstr(); - print("setsockopt: %s", up->errstr); - } - - if(su) { - for(i = 600; i < 1024; i++) { - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = i; - - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0) - return; - } - oserror(); - } - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - hnputs(&sin.sin_port, port); - - if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) - oserror(); -} - -int -so_gethostbyname(char *host, char**hostv, int n) -{ - int i; - char buf[32]; - unsigned char *p; - struct hostent *hp; - - hp = gethostbyname(host); - if(hp == 0) - return 0; - - for(i = 0; hp->h_addr_list[i] && i < n; i++) { - p = (unsigned char*)hp->h_addr_list[i]; - sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - hostv[i] = strdup(buf); - if(hostv[i] == 0) - break; - } - return i; -} - -char* -hostlookup(char *host) -{ - char buf[100]; - uchar *p; - HOSTENT *he; - - he = gethostbyname(host); - if(he != 0 && he->h_addr_list[0]) { - p = (uchar*)he->h_addr_list[0]; - sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); - } else - strcpy(buf, host); - - return strdup(buf); -} - -int -so_getservbyname(char *service, char *net, char *port) -{ - struct servent *s; - - s = getservbyname(service, net); - if(s == 0) - return -1; - - sprint(port, "%d", nhgets(&s->s_port)); - return 0; -} - -int -so_send(int fd, void *d, int n, int f) -{ - return send(fd, d, n, f); -} - -int -so_recv(int fd, void *d, int n, int f) -{ - return recv(fd, d, n, f); -} diff --git a/sys/src/cmd/unix/drawterm/kern/devip.c b/sys/src/cmd/unix/drawterm/kern/devip.c deleted file mode 100644 index f192aebcb..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devip.c +++ /dev/null @@ -1,938 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#include "devip.h" - -void hnputl(void *p, unsigned long v); -void hnputs(void *p, unsigned short v); -unsigned long nhgetl(void *p); -unsigned short nhgets(void *p); -unsigned long parseip(char *to, char *from); -void csclose(Chan*); -long csread(Chan*, void*, long, vlong); -long cswrite(Chan*, void*, long, vlong); - -void osipinit(void); - -enum -{ - Qtopdir = 1, /* top level directory */ - Qcs, - Qprotodir, /* directory for a protocol */ - Qclonus, - Qconvdir, /* directory for a conversation */ - Qdata, - Qctl, - Qstatus, - Qremote, - Qlocal, - Qlisten, - - MAXPROTO = 4 -}; -#define TYPE(x) ((int)((x).path & 0xf)) -#define CONV(x) ((int)(((x).path >> 4)&0xfff)) -#define PROTO(x) ((int)(((x).path >> 16)&0xff)) -#define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y)) - -typedef struct Proto Proto; -typedef struct Conv Conv; -struct Conv -{ - int x; - Ref r; - int sfd; - int perm; - char owner[KNAMELEN]; - char* state; - ulong laddr; - ushort lport; - ulong raddr; - ushort rport; - int restricted; - char cerr[KNAMELEN]; - Proto* p; -}; - -struct Proto -{ - Lock l; - int x; - int stype; - char name[KNAMELEN]; - int nc; - int maxconv; - Conv** conv; - Qid qid; -}; - -static int np; -static Proto proto[MAXPROTO]; -int eipfmt(Fmt*); - -static Conv* protoclone(Proto*, char*, int); -static void setladdr(Conv*); - -int -ipgen(Chan *c, char *nname, Dirtab *d, int nd, int s, Dir *dp) -{ - Qid q; - Conv *cv; - char *p; - - USED(nname); - q.vers = 0; - q.type = 0; - switch(TYPE(c->qid)) { - case Qtopdir: - if(s >= 1+np) - return -1; - - if(s == 0){ - q.path = QID(s, 0, Qcs); - devdir(c, q, "cs", 0, "network", 0666, dp); - }else{ - s--; - q.path = QID(s, 0, Qprotodir); - q.type = QTDIR; - devdir(c, q, proto[s].name, 0, "network", DMDIR|0555, dp); - } - return 1; - case Qprotodir: - if(s < proto[PROTO(c->qid)].nc) { - cv = proto[PROTO(c->qid)].conv[s]; - sprint(up->genbuf, "%d", s); - q.path = QID(PROTO(c->qid), s, Qconvdir); - q.type = QTDIR; - devdir(c, q, up->genbuf, 0, cv->owner, DMDIR|0555, dp); - return 1; - } - s -= proto[PROTO(c->qid)].nc; - switch(s) { - default: - return -1; - case 0: - p = "clone"; - q.path = QID(PROTO(c->qid), 0, Qclonus); - break; - } - devdir(c, q, p, 0, "network", 0555, dp); - return 1; - case Qconvdir: - cv = proto[PROTO(c->qid)].conv[CONV(c->qid)]; - switch(s) { - default: - return -1; - case 0: - q.path = QID(PROTO(c->qid), CONV(c->qid), Qdata); - devdir(c, q, "data", 0, cv->owner, cv->perm, dp); - return 1; - case 1: - q.path = QID(PROTO(c->qid), CONV(c->qid), Qctl); - devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp); - return 1; - case 2: - p = "status"; - q.path = QID(PROTO(c->qid), CONV(c->qid), Qstatus); - break; - case 3: - p = "remote"; - q.path = QID(PROTO(c->qid), CONV(c->qid), Qremote); - break; - case 4: - p = "local"; - q.path = QID(PROTO(c->qid), CONV(c->qid), Qlocal); - break; - case 5: - p = "listen"; - q.path = QID(PROTO(c->qid), CONV(c->qid), Qlisten); - break; - } - devdir(c, q, p, 0, cv->owner, 0444, dp); - return 1; - } - return -1; -} - -static void -newproto(char *name, int type, int maxconv) -{ - int l; - Proto *p; - - if(np >= MAXPROTO) { - print("no %s: increase MAXPROTO", name); - return; - } - - p = &proto[np]; - strcpy(p->name, name); - p->stype = type; - p->qid.path = QID(np, 0, Qprotodir); - p->qid.type = QTDIR; - p->x = np++; - p->maxconv = maxconv; - l = sizeof(Conv*)*(p->maxconv+1); - p->conv = mallocz(l, 1); - if(p->conv == 0) - panic("no memory"); -} - -void -ipinit(void) -{ - osipinit(); - - newproto("udp", S_UDP, 10); - newproto("tcp", S_TCP, 30); - - fmtinstall('I', eipfmt); - fmtinstall('E', eipfmt); - -} - -Chan * -ipattach(char *spec) -{ - Chan *c; - - c = devattach('I', spec); - c->qid.path = QID(0, 0, Qtopdir); - c->qid.type = QTDIR; - c->qid.vers = 0; - return c; -} - -static Walkqid* -ipwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, 0, 0, ipgen); -} - -int -ipstat(Chan *c, uchar *dp, int n) -{ - return devstat(c, dp, n, 0, 0, ipgen); -} - -Chan * -ipopen(Chan *c, int omode) -{ - Proto *p; - ulong raddr; - ushort rport; - int perm, sfd; - Conv *cv, *lcv; - - omode &= 3; - perm = 0; - switch(omode) { - case OREAD: - perm = 4; - break; - case OWRITE: - perm = 2; - break; - case ORDWR: - perm = 6; - break; - } - - switch(TYPE(c->qid)) { - default: - break; - case Qtopdir: - case Qprotodir: - case Qconvdir: - case Qstatus: - case Qremote: - case Qlocal: - if(omode != OREAD) - error(Eperm); - break; - case Qclonus: - p = &proto[PROTO(c->qid)]; - cv = protoclone(p, up->user, -1); - if(cv == 0) - error(Enodev); - c->qid.path = QID(p->x, cv->x, Qctl); - c->qid.vers = 0; - break; - case Qdata: - case Qctl: - p = &proto[PROTO(c->qid)]; - lock(&p->l); - cv = p->conv[CONV(c->qid)]; - lock(&cv->r.lk); - if((perm & (cv->perm>>6)) != perm) { - if(strcmp(up->user, cv->owner) != 0 || - (perm & cv->perm) != perm) { - unlock(&cv->r.lk); - unlock(&p->l); - error(Eperm); - } - } - cv->r.ref++; - if(cv->r.ref == 1) { - memmove(cv->owner, up->user, KNAMELEN); - cv->perm = 0660; - } - unlock(&cv->r.lk); - unlock(&p->l); - break; - case Qlisten: - p = &proto[PROTO(c->qid)]; - lcv = p->conv[CONV(c->qid)]; - sfd = so_accept(lcv->sfd, &raddr, &rport); - cv = protoclone(p, up->user, sfd); - if(cv == 0) { - close(sfd); - error(Enodev); - } - cv->raddr = raddr; - cv->rport = rport; - setladdr(cv); - cv->state = "Established"; - c->qid.path = QID(p->x, cv->x, Qctl); - break; - } - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - return c; -} - -void -ipclose(Chan *c) -{ - Conv *cc; - - switch(TYPE(c->qid)) { - case Qcs: - csclose(c); - break; - case Qdata: - case Qctl: - if((c->flag & COPEN) == 0) - break; - cc = proto[PROTO(c->qid)].conv[CONV(c->qid)]; - if(decref(&cc->r) != 0) - break; - strcpy(cc->owner, "network"); - cc->perm = 0666; - cc->state = "Closed"; - cc->laddr = 0; - cc->raddr = 0; - cc->lport = 0; - cc->rport = 0; - close(cc->sfd); - break; - } -} - -long -ipread(Chan *ch, void *a, long n, vlong offset) -{ - int r; - Conv *c; - Proto *x; - uchar ip[4]; - char buf[128], *p; - -/*print("ipread %s %lux\n", c2name(ch), (long)ch->qid.path);*/ - p = a; - switch(TYPE(ch->qid)) { - default: - error(Eperm); - case Qcs: - return csread(ch, a, n, offset); - case Qprotodir: - case Qtopdir: - case Qconvdir: - return devdirread(ch, a, n, 0, 0, ipgen); - case Qctl: - sprint(buf, "%d", CONV(ch->qid)); - return readstr(offset, p, n, buf); - case Qremote: - c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; - hnputl(ip, c->raddr); - sprint(buf, "%I!%d\n", ip, c->rport); - return readstr(offset, p, n, buf); - case Qlocal: - c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; - hnputl(ip, c->laddr); - sprint(buf, "%I!%d\n", ip, c->lport); - return readstr(offset, p, n, buf); - case Qstatus: - x = &proto[PROTO(ch->qid)]; - c = x->conv[CONV(ch->qid)]; - sprint(buf, "%s/%d %d %s \n", - c->p->name, c->x, c->r.ref, c->state); - return readstr(offset, p, n, buf); - case Qdata: - c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)]; - r = so_recv(c->sfd, a, n, 0); - if(r < 0){ - oserrstr(); - nexterror(); - } - return r; - } -} - -static void -setladdr(Conv *c) -{ - so_getsockname(c->sfd, &c->laddr, &c->lport); -} - -static void -setlport(Conv *c) -{ - if(c->restricted == 0 && c->lport == 0) - return; - - so_bind(c->sfd, c->restricted, c->lport); -} - -static void -setladdrport(Conv *c, char *str) -{ - char *p, addr[4]; - - p = strchr(str, '!'); - if(p == 0) { - p = str; - c->laddr = 0; - } - else { - *p++ = 0; - parseip(addr, str); - c->laddr = nhgetl((uchar*)addr); - } - if(*p == '*') - c->lport = 0; - else - c->lport = atoi(p); - - setlport(c); -} - -static char* -setraddrport(Conv *c, char *str) -{ - char *p, addr[4]; - - p = strchr(str, '!'); - if(p == 0) - return "malformed address"; - *p++ = 0; - parseip(addr, str); - c->raddr = nhgetl((uchar*)addr); - c->rport = atoi(p); - p = strchr(p, '!'); - if(p) { - if(strcmp(p, "!r") == 0) - c->restricted = 1; - } - return 0; -} - -long -ipwrite(Chan *ch, void *a, long n, vlong offset) -{ - Conv *c; - Proto *x; - int r, nf; - char *p, *fields[3], buf[128]; - - switch(TYPE(ch->qid)) { - default: - error(Eperm); - case Qcs: - return cswrite(ch, a, n, offset); - case Qctl: - x = &proto[PROTO(ch->qid)]; - c = x->conv[CONV(ch->qid)]; - if(n > sizeof(buf)-1) - n = sizeof(buf)-1; - memmove(buf, a, n); - buf[n] = '\0'; - - nf = tokenize(buf, fields, 3); - if(strcmp(fields[0], "connect") == 0){ - switch(nf) { - default: - error("bad args to connect"); - case 2: - p = setraddrport(c, fields[1]); - if(p != 0) - error(p); - break; - case 3: - p = setraddrport(c, fields[1]); - if(p != 0) - error(p); - c->lport = atoi(fields[2]); - setlport(c); - break; - } - so_connect(c->sfd, c->raddr, c->rport); - setladdr(c); - c->state = "Established"; - return n; - } - if(strcmp(fields[0], "announce") == 0) { - switch(nf){ - default: - error("bad args to announce"); - case 2: - setladdrport(c, fields[1]); - break; - } - so_listen(c->sfd); - c->state = "Announced"; - return n; - } - if(strcmp(fields[0], "bind") == 0){ - switch(nf){ - default: - error("bad args to bind"); - case 2: - c->lport = atoi(fields[1]); - break; - } - setlport(c); - return n; - } - error("bad control message"); - case Qdata: - x = &proto[PROTO(ch->qid)]; - c = x->conv[CONV(ch->qid)]; - r = so_send(c->sfd, a, n, 0); - if(r < 0){ - oserrstr(); - nexterror(); - } - return r; - } - return n; -} - -static Conv* -protoclone(Proto *p, char *user, int nfd) -{ - Conv *c, **pp, **ep; - - c = 0; - lock(&p->l); - if(waserror()) { - unlock(&p->l); - nexterror(); - } - ep = &p->conv[p->maxconv]; - for(pp = p->conv; pp < ep; pp++) { - c = *pp; - if(c == 0) { - c = mallocz(sizeof(Conv), 1); - if(c == 0) - error(Enomem); - lock(&c->r.lk); - c->r.ref = 1; - c->p = p; - c->x = pp - p->conv; - p->nc++; - *pp = c; - break; - } - lock(&c->r.lk); - if(c->r.ref == 0) { - c->r.ref++; - break; - } - unlock(&c->r.lk); - } - if(pp >= ep) { - unlock(&p->l); - poperror(); - return 0; - } - - strcpy(c->owner, user); - c->perm = 0660; - c->state = "Closed"; - c->restricted = 0; - c->laddr = 0; - c->raddr = 0; - c->lport = 0; - c->rport = 0; - c->sfd = nfd; - if(nfd == -1) - c->sfd = so_socket(p->stype); - - unlock(&c->r.lk); - unlock(&p->l); - poperror(); - return c; -} - -enum -{ - Isprefix= 16, -}; - -uchar prefixvals[256] = -{ -/*0x00*/ 0 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x80*/ 1 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0x90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xA0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xB0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xC0*/ 2 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xD0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xE0*/ 3 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*0xF0*/ 4 | Isprefix, - 0, 0, 0, 0, 0, 0, 0, -/*0xF8*/ 5 | Isprefix, - 0, 0, 0, -/*0xFC*/ 6 | Isprefix, - 0, -/*0xFE*/ 7 | Isprefix, -/*0xFF*/ 8 | Isprefix, -}; - -int -eipfmt(Fmt *f) -{ - char buf[5*8]; - static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux"; - static char *ifmt = "%d.%d.%d.%d"; - uchar *p, ip[16]; - ulong ul; - - switch(f->r) { - case 'E': /* Ethernet address */ - p = va_arg(f->args, uchar*); - snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); - return fmtstrcpy(f, buf); - - case 'I': - ul = va_arg(f->args, ulong); - hnputl(ip, ul); - snprint(buf, sizeof buf, ifmt, ip[0], ip[1], ip[2], ip[3]); - return fmtstrcpy(f, buf); - } - return fmtstrcpy(f, "(eipfmt)"); -} - -void -hnputl(void *p, unsigned long v) -{ - unsigned char *a; - - a = p; - a[0] = v>>24; - a[1] = v>>16; - a[2] = v>>8; - a[3] = v; -} - -void -hnputs(void *p, unsigned short v) -{ - unsigned char *a; - - a = p; - a[0] = v>>8; - a[1] = v; -} - -unsigned long -nhgetl(void *p) -{ - unsigned char *a; - a = p; - return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0); -} - -unsigned short -nhgets(void *p) -{ - unsigned char *a; - a = p; - return (a[0]<<8)|(a[1]<<0); -} - -#define CLASS(p) ((*(unsigned char*)(p))>>6) - -unsigned long -parseip(char *to, char *from) -{ - int i; - char *p; - - p = from; - memset(to, 0, 4); - for(i = 0; i < 4 && *p; i++){ - to[i] = strtoul(p, &p, 10); - if(*p != '.' && *p != 0){ - memset(to, 0, 4); - return 0; - } - if(*p == '.') - p++; - } - switch(CLASS(to)){ - case 0: /* class A - 1 byte net */ - case 1: - if(i == 3){ - to[3] = to[2]; - to[2] = to[1]; - to[1] = 0; - } else if (i == 2){ - to[3] = to[1]; - to[1] = 0; - } - break; - case 2: /* class B - 2 byte net */ - if(i == 3){ - to[3] = to[2]; - to[2] = 0; - } - break; - } - return nhgetl(to); -} - -void -csclose(Chan *c) -{ - free(c->aux); -} - -long -csread(Chan *c, void *a, long n, vlong offset) -{ - if(c->aux == nil) - return 0; - return readstr(offset, a, n, c->aux); -} - -static struct -{ - char *name; - uint num; -} tab[] = { - "cs", 1, - "echo", 7, - "discard", 9, - "systat", 11, - "daytime", 13, - "netstat", 15, - "chargen", 19, - "ftp-data", 20, - "ftp", 21, - "ssh", 22, - "telnet", 23, - "smtp", 25, - "time", 37, - "whois", 43, - "dns", 53, - "domain", 53, - "uucp", 64, - "gopher", 70, - "rje", 77, - "finger", 79, - "http", 80, - "link", 87, - "supdup", 95, - "hostnames", 101, - "iso-tsap", 102, - "x400", 103, - "x400-snd", 104, - "csnet-ns", 105, - "pop-2", 109, - "pop3", 110, - "portmap", 111, - "uucp-path", 117, - "nntp", 119, - "netbios", 139, - "imap4", 143, - "NeWS", 144, - "print-srv", 170, - "z39.50", 210, - "fsb", 400, - "sysmon", 401, - "proxy", 402, - "proxyd", 404, - "https", 443, - "cifs", 445, - "ssmtp", 465, - "rexec", 512, - "login", 513, - "shell", 514, - "printer", 515, - "courier", 530, - "cscan", 531, - "uucp", 540, - "snntp", 563, - "9fs", 564, - "whoami", 565, - "guard", 566, - "ticket", 567, - "dlsftp", 666, - "fmclient", 729, - "imaps", 993, - "pop3s", 995, - "ingreslock", 1524, - "pptp", 1723, - "nfs", 2049, - "webster", 2627, - "weather", 3000, - "secstore", 5356, - "Xdisplay", 6000, - "styx", 6666, - "mpeg", 6667, - "rstyx", 6668, - "infdb", 6669, - "infsigner", 6671, - "infcsigner", 6672, - "inflogin", 6673, - "bandt", 7330, - "face", 32000, - "dhashgate", 11978, - "exportfs", 17007, - "rexexec", 17009, - "ncpu", 17010, - "cpu", 17013, - "glenglenda1", 17020, - "glenglenda2", 17021, - "glenglenda3", 17022, - "glenglenda4", 17023, - "glenglenda5", 17024, - "glenglenda6", 17025, - "glenglenda7", 17026, - "glenglenda8", 17027, - "glenglenda9", 17028, - "glenglenda10", 17029, - "flyboy", 17032, - "dlsftp", 17033, - "venti", 17034, - "wiki", 17035, - "vica", 17036, - 0 -}; - -static int -lookupport(char *s) -{ - int i; - char buf[10], *p; - - i = strtol(s, &p, 0); - if(*s && *p == 0) - return i; - - i = so_getservbyname(s, "tcp", buf); - if(i != -1) - return atoi(buf); - for(i=0; tab[i].name; i++) - if(strcmp(s, tab[i].name) == 0) - return tab[i].num; - return 0; -} - -static ulong -lookuphost(char *s) -{ - char to[4]; - ulong ip; - - memset(to, 0, sizeof to); - parseip(to, s); - ip = nhgetl(to); - if(ip != 0) - return ip; - if((s = hostlookup(s)) == nil) - return 0; - parseip(to, s); - ip = nhgetl(to); - free(s); - return ip; -} - -long -cswrite(Chan *c, void *a, long n, vlong offset) -{ - char *f[4]; - char *s, *ns; - ulong ip; - int nf, port; - - s = malloc(n+1); - if(s == nil) - error(Enomem); - if(waserror()){ - free(s); - nexterror(); - } - memmove(s, a, n); - s[n] = 0; - nf = getfields(s, f, nelem(f), 0, "!"); - if(nf != 3) - error("can't translate"); - - port = lookupport(f[2]); - if(port <= 0) - error("no translation for port found"); - - ip = lookuphost(f[1]); - if(ip == 0) - error("no translation for host found"); - - ns = smprint("/net/%s/clone %I!%d", f[0], ip, port); - if(ns == nil) - error(Enomem); - free(c->aux); - c->aux = ns; - poperror(); - free(s); - return n; -} - -Dev ipdevtab = -{ - 'I', - "ip", - - devreset, - ipinit, - devshutdown, - ipattach, - ipwalk, - ipstat, - ipopen, - devcreate, - ipclose, - ipread, - devbread, - ipwrite, - devbwrite, - devremove, - devwstat, -}; - diff --git a/sys/src/cmd/unix/drawterm/kern/devip.h b/sys/src/cmd/unix/drawterm/kern/devip.h deleted file mode 100644 index 950ad398d..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devip.h +++ /dev/null @@ -1,19 +0,0 @@ -enum -{ - S_TCP, - S_UDP -}; - -int so_socket(int type); -void so_connect(int, unsigned long, unsigned short); -void so_getsockname(int, unsigned long*, unsigned short*); -void so_bind(int, int, unsigned short); -void so_listen(int); -int so_send(int, void*, int, int); -int so_recv(int, void*, int, int); -int so_accept(int, unsigned long*, unsigned short*); -int so_getservbyname(char*, char*, char*); -int so_gethostbyname(char*, char**, int); - -char* hostlookup(char*); - diff --git a/sys/src/cmd/unix/drawterm/kern/devlfd.c b/sys/src/cmd/unix/drawterm/kern/devlfd.c deleted file mode 100644 index 7c61e0c1e..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devlfd.c +++ /dev/null @@ -1,126 +0,0 @@ -#include "u.h" -#include <errno.h> -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#undef pread -#undef pwrite - -Chan* -lfdchan(int fd) -{ - Chan *c; - - c = newchan(); - c->type = devno('L', 0); - c->aux = (void*)(uintptr)fd; - c->name = newcname("fd"); - c->mode = ORDWR; - c->qid.type = 0; - c->qid.path = 0; - c->qid.vers = 0; - c->dev = 0; - c->offset = 0; - return c; -} - -int -lfdfd(int fd) -{ - return newfd(lfdchan(fd)); -} - -static Chan* -lfdattach(char *x) -{ - USED(x); - - error(Egreg); - return nil; -} - -static Walkqid* -lfdwalk(Chan *c, Chan *nc, char **name, int nname) -{ - USED(c); - USED(nc); - USED(name); - USED(nname); - - error(Egreg); - return nil; -} - -static int -lfdstat(Chan *c, uchar *dp, int n) -{ - USED(c); - USED(dp); - USED(n); - error(Egreg); - return -1; -} - -static Chan* -lfdopen(Chan *c, int omode) -{ - USED(c); - USED(omode); - - error(Egreg); - return nil; -} - -static void -lfdclose(Chan *c) -{ - close((int)(uintptr)c->aux); -} - -static long -lfdread(Chan *c, void *buf, long n, vlong off) -{ - USED(off); /* can't pread on pipes */ - n = read((int)(uintptr)c->aux, buf, n); - if(n < 0){ - iprint("error %d\n", errno); - oserror(); - } - return n; -} - -static long -lfdwrite(Chan *c, void *buf, long n, vlong off) -{ - USED(off); /* can't pread on pipes */ - - n = write((int)(uintptr)c->aux, buf, n); - if(n < 0){ - iprint("error %d\n", errno); - oserror(); - } - return n; -} - -Dev lfddevtab = { - 'L', - "lfd", - - devreset, - devinit, - devshutdown, - lfdattach, - lfdwalk, - lfdstat, - lfdopen, - devcreate, - lfdclose, - lfdread, - devbread, - lfdwrite, - devbwrite, - devremove, - devwstat, -}; diff --git a/sys/src/cmd/unix/drawterm/kern/devmnt.c b/sys/src/cmd/unix/drawterm/kern/devmnt.c deleted file mode 100644 index 9121bfdb4..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devmnt.c +++ /dev/null @@ -1,1216 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -/* - * References are managed as follows: - * The channel to the server - a network connection or pipe - has one - * reference for every Chan open on the server. The server channel has - * c->mux set to the Mnt used for muxing control to that server. Mnts - * have no reference count; they go away when c goes away. - * Each channel derived from the mount point has mchan set to c, - * and increfs/decrefs mchan to manage references on the server - * connection. - */ - -#define MAXRPC (IOHDRSZ+8192) - -struct Mntrpc -{ - Chan* c; /* Channel for whom we are working */ - Mntrpc* list; /* Free/pending list */ - Fcall request; /* Outgoing file system protocol message */ - Fcall reply; /* Incoming reply */ - Mnt* m; /* Mount device during rpc */ - Rendez r; /* Place to hang out */ - uchar* rpc; /* I/O Data buffer */ - uint rpclen; /* len of buffer */ - Block *b; /* reply blocks */ - char done; /* Rpc completed */ - uvlong stime; /* start time for mnt statistics */ - ulong reqlen; /* request length for mnt statistics */ - ulong replen; /* reply length for mnt statistics */ - Mntrpc* flushed; /* message this one flushes */ -}; - -enum -{ - TAGSHIFT = 5, /* ulong has to be 32 bits */ - TAGMASK = (1<<TAGSHIFT)-1, - NMASK = (64*1024)>>TAGSHIFT, -}; - -struct Mntalloc -{ - Lock lk; - Mnt* list; /* Mount devices in use */ - Mnt* mntfree; /* Free list */ - Mntrpc* rpcfree; - int nrpcfree; - int nrpcused; - ulong id; - ulong tagmask[NMASK]; -}mntalloc; - -void mattach(Mnt*, Chan*, char*); -Mnt* mntchk(Chan*); -void mntdirfix(uchar*, Chan*); -Mntrpc* mntflushalloc(Mntrpc*, ulong); -void mntflushfree(Mnt*, Mntrpc*); -void mntfree(Mntrpc*); -void mntgate(Mnt*); -void mntpntfree(Mnt*); -void mntqrm(Mnt*, Mntrpc*); -Mntrpc* mntralloc(Chan*, ulong); -long mntrdwr(int, Chan*, void*, long, vlong); -int mntrpcread(Mnt*, Mntrpc*); -void mountio(Mnt*, Mntrpc*); -void mountmux(Mnt*, Mntrpc*); -void mountrpc(Mnt*, Mntrpc*); -int rpcattn(void*); -Chan* mntchan(void); - -char Esbadstat[] = "invalid directory entry received from server"; -char Enoversion[] = "version not established for mount channel"; - - -void (*mntstats)(int, Chan*, uvlong, ulong); - -static void -mntreset(void) -{ - mntalloc.id = 1; - mntalloc.tagmask[0] = 1; /* don't allow 0 as a tag */ - mntalloc.tagmask[NMASK-1] = 0x80000000UL; /* don't allow NOTAG */ - fmtinstall('F', fcallfmt); - fmtinstall('D', dirfmt); -/* We can't install %M since eipfmt does and is used in the kernel [sape] */ - - cinit(); -} - -/* - * Version is not multiplexed: message sent only once per connection. - */ -long -mntversion(Chan *c, char *version, int msize, int returnlen) -{ - Fcall f; - uchar *msg; - Mnt *m; - char *v; - long k, l; - uvlong oo; - char buf[128]; - - qlock(&c->umqlock); /* make sure no one else does this until we've established ourselves */ - if(waserror()){ - qunlock(&c->umqlock); - nexterror(); - } - - /* defaults */ - if(msize == 0) - msize = MAXRPC; - if(msize > c->iounit && c->iounit != 0) - msize = c->iounit; - v = version; - if(v == nil || v[0] == '\0') - v = VERSION9P; - - /* validity */ - if(msize < 0) - error("bad iounit in version call"); - if(strncmp(v, VERSION9P, strlen(VERSION9P)) != 0) - error("bad 9P version specification"); - - m = c->mux; - - if(m != nil){ - qunlock(&c->umqlock); - poperror(); - - strecpy(buf, buf+sizeof buf, m->version); - k = strlen(buf); - if(strncmp(buf, v, k) != 0){ - snprint(buf, sizeof buf, "incompatible 9P versions %s %s", m->version, v); - error(buf); - } - if(returnlen > 0){ - if(returnlen < k) - error(Eshort); - memmove(version, buf, k); - } - return k; - } - - f.type = Tversion; - f.tag = NOTAG; - f.msize = msize; - f.version = v; - msg = malloc(8192+IOHDRSZ); - if(msg == nil) - exhausted("version memory"); - if(waserror()){ - free(msg); - nexterror(); - } - k = convS2M(&f, msg, 8192+IOHDRSZ); - if(k == 0) - error("bad fversion conversion on send"); - - lock(&c->ref.lk); - oo = c->offset; - c->offset += k; - unlock(&c->ref.lk); - - l = devtab[c->type]->write(c, msg, k, oo); - - if(l < k){ - lock(&c->ref.lk); - c->offset -= k - l; - unlock(&c->ref.lk); - error("short write in fversion"); - } - - /* message sent; receive and decode reply */ - k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset); - if(k <= 0) - error("EOF receiving fversion reply"); - - lock(&c->ref.lk); - c->offset += k; - unlock(&c->ref.lk); - - l = convM2S(msg, k, &f); - if(l != k) - error("bad fversion conversion on reply"); - if(f.type != Rversion){ - if(f.type == Rerror) - error(f.ename); - error("unexpected reply type in fversion"); - } - if(f.msize > msize) - error("server tries to increase msize in fversion"); - if(f.msize<256 || f.msize>1024*1024) - error("nonsense value of msize in fversion"); - k = strlen(f.version); - if(strncmp(f.version, v, k) != 0) - error("bad 9P version returned from server"); - - /* now build Mnt associated with this connection */ - lock(&mntalloc.lk); - m = mntalloc.mntfree; - if(m != 0) - mntalloc.mntfree = m->list; - else { - m = malloc(sizeof(Mnt)); - if(m == 0) { - unlock(&mntalloc.lk); - exhausted("mount devices"); - } - } - m->list = mntalloc.list; - mntalloc.list = m; - m->version = nil; - kstrdup(&m->version, f.version); - m->id = mntalloc.id++; - m->q = qopen(10*MAXRPC, 0, 0, nil); - m->msize = f.msize; - unlock(&mntalloc.lk); - - if(returnlen > 0){ - if(returnlen < k) - error(Eshort); - memmove(version, f.version, k); - } - - poperror(); /* msg */ - free(msg); - - lock(&m->lk); - m->queue = 0; - m->rip = 0; - - c->flag |= CMSG; - c->mux = m; - m->c = c; - unlock(&m->lk); - - poperror(); /* c */ - qunlock(&c->umqlock); - - return k; -} - -Chan* -mntauth(Chan *c, char *spec) -{ - Mnt *m; - Mntrpc *r; - - m = c->mux; - - if(m == nil){ - mntversion(c, VERSION9P, MAXRPC, 0); - m = c->mux; - if(m == nil) - error(Enoversion); - } - - c = mntchan(); - if(waserror()) { - /* Close must not be called since it will - * call mnt recursively - */ - chanfree(c); - nexterror(); - } - - r = mntralloc(0, m->msize); - - if(waserror()) { - mntfree(r); - nexterror(); - } - - r->request.type = Tauth; - r->request.afid = c->fid; - r->request.uname = up->user; - r->request.aname = spec; - mountrpc(m, r); - - c->qid = r->reply.aqid; - c->mchan = m->c; - incref(&m->c->ref); - c->mqid = c->qid; - c->mode = ORDWR; - - poperror(); /* r */ - mntfree(r); - - poperror(); /* c */ - - return c; - -} - -static Chan* -mntattach(char *muxattach) -{ - Mnt *m; - Chan *c; - Mntrpc *r; - struct bogus{ - Chan *chan; - Chan *authchan; - char *spec; - int flags; - }bogus; - - bogus = *((struct bogus *)muxattach); - c = bogus.chan; - - m = c->mux; - - if(m == nil){ - mntversion(c, nil, 0, 0); - m = c->mux; - if(m == nil) - error(Enoversion); - } - - c = mntchan(); - if(waserror()) { - /* Close must not be called since it will - * call mnt recursively - */ - chanfree(c); - nexterror(); - } - - r = mntralloc(0, m->msize); - - if(waserror()) { - mntfree(r); - nexterror(); - } - - r->request.type = Tattach; - r->request.fid = c->fid; - if(bogus.authchan == nil) - r->request.afid = NOFID; - else - r->request.afid = bogus.authchan->fid; - r->request.uname = up->user; - r->request.aname = bogus.spec; - mountrpc(m, r); - - c->qid = r->reply.qid; - c->mchan = m->c; - incref(&m->c->ref); - c->mqid = c->qid; - - poperror(); /* r */ - mntfree(r); - - poperror(); /* c */ - - if(bogus.flags&MCACHE) - c->flag |= CCACHE; - return c; -} - -Chan* -mntchan(void) -{ - Chan *c; - - c = devattach('M', 0); - lock(&mntalloc.lk); - c->dev = mntalloc.id++; - unlock(&mntalloc.lk); - - if(c->mchan) - panic("mntchan non-zero %p", c->mchan); - return c; -} - -static Walkqid* -mntwalk(Chan *c, Chan *nc, char **name, int nname) -{ - int i, alloc; - Mnt *m; - Mntrpc *r; - Walkqid *wq; - - if(nc != nil) - print("mntwalk: nc != nil\n"); - if(nname > MAXWELEM) - error("devmnt: too many name elements"); - alloc = 0; - wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); - if(waserror()){ - if(alloc && wq->clone!=nil) - cclose(wq->clone); - free(wq); - return nil; - } - - alloc = 0; - m = mntchk(c); - r = mntralloc(c, m->msize); - if(nc == nil){ - nc = devclone(c); - /* - * Until the other side accepts this fid, we can't mntclose it. - * Therefore set type to 0 for now; rootclose is known to be safe. - */ - nc->type = 0; - alloc = 1; - } - wq->clone = nc; - - if(waserror()) { - mntfree(r); - nexterror(); - } - r->request.type = Twalk; - r->request.fid = c->fid; - r->request.newfid = nc->fid; - r->request.nwname = nname; - memmove(r->request.wname, name, nname*sizeof(char*)); - - mountrpc(m, r); - - if(r->reply.nwqid > nname) - error("too many QIDs returned by walk"); - if(r->reply.nwqid < nname){ - if(alloc) - cclose(nc); - wq->clone = nil; - if(r->reply.nwqid == 0){ - free(wq); - wq = nil; - goto Return; - } - } - - /* move new fid onto mnt device and update its qid */ - if(wq->clone != nil){ - if(wq->clone != c){ - wq->clone->type = c->type; - wq->clone->mchan = c->mchan; - incref(&c->mchan->ref); - } - if(r->reply.nwqid > 0) - wq->clone->qid = r->reply.wqid[r->reply.nwqid-1]; - } - wq->nqid = r->reply.nwqid; - for(i=0; i<wq->nqid; i++) - wq->qid[i] = r->reply.wqid[i]; - - Return: - poperror(); - mntfree(r); - poperror(); - return wq; -} - -static int -mntstat(Chan *c, uchar *dp, int n) -{ - Mnt *m; - Mntrpc *r; - - if(n < BIT16SZ) - error(Eshortstat); - m = mntchk(c); - r = mntralloc(c, m->msize); - if(waserror()) { - mntfree(r); - nexterror(); - } - r->request.type = Tstat; - r->request.fid = c->fid; - mountrpc(m, r); - -/* r->reply.nstat is 16 bits - if(r->reply.nstat >= 1<<16) - error("returned stat buffer count too large"); -*/ - - if(r->reply.nstat > n){ - /* - * 12/31/2002 RSC - * - * This should be nstat-2, which is the first two - * bytes of the stat buffer. But dirstat and dirfstat - * depended on getting the full nstat (they didn't - * add BIT16SZ themselves). I fixed dirstat and dirfstat - * but am leaving this unchanged for now. After a - * few months, once enough of the relevant binaries - * have been recompiled for other reasons, we can - * change this to nstat-2. Devstat gets this right - * (via convD2M). - */ - /* doesn't fit; just patch the count and return */ - PBIT16((uchar*)dp, r->reply.nstat); - n = BIT16SZ; - }else{ - n = r->reply.nstat; - memmove(dp, r->reply.stat, n); - validstat(dp, n); - mntdirfix(dp, c); - } - poperror(); - mntfree(r); - return n; -} - -static Chan* -mntopencreate(int type, Chan *c, char *name, int omode, ulong perm) -{ - Mnt *m; - Mntrpc *r; - - m = mntchk(c); - r = mntralloc(c, m->msize); - if(waserror()) { - mntfree(r); - nexterror(); - } - r->request.type = type; - r->request.fid = c->fid; - r->request.mode = omode; - if(type == Tcreate){ - r->request.perm = perm; - r->request.name = name; - } - mountrpc(m, r); - - c->qid = r->reply.qid; - c->offset = 0; - c->mode = openmode(omode); - c->iounit = r->reply.iounit; - if(c->iounit == 0 || c->iounit > m->msize-IOHDRSZ) - c->iounit = m->msize-IOHDRSZ; - c->flag |= COPEN; - poperror(); - mntfree(r); - - if(c->flag & CCACHE) - copen(c); - - return c; -} - -static Chan* -mntopen(Chan *c, int omode) -{ - return mntopencreate(Topen, c, nil, omode, 0); -} - -static void -mntcreate(Chan *c, char *name, int omode, ulong perm) -{ - mntopencreate(Tcreate, c, name, omode, perm); -} - -static void -mntclunk(Chan *c, int t) -{ - Mnt *m; - Mntrpc *r; - - m = mntchk(c); - r = mntralloc(c, m->msize); - if(waserror()){ - mntfree(r); - nexterror(); - } - - r->request.type = t; - r->request.fid = c->fid; - mountrpc(m, r); - mntfree(r); - poperror(); -} - -void -muxclose(Mnt *m) -{ - Mntrpc *q, *r; - - for(q = m->queue; q; q = r) { - r = q->list; - mntfree(q); - } - m->id = 0; - free(m->version); - m->version = nil; - mntpntfree(m); -} - -void -mntpntfree(Mnt *m) -{ - Mnt *f, **l; - Queue *q; - - lock(&mntalloc.lk); - l = &mntalloc.list; - for(f = *l; f; f = f->list) { - if(f == m) { - *l = m->list; - break; - } - l = &f->list; - } - m->list = mntalloc.mntfree; - mntalloc.mntfree = m; - q = m->q; - unlock(&mntalloc.lk); - - qfree(q); -} - -static void -mntclose(Chan *c) -{ - mntclunk(c, Tclunk); -} - -static void -mntremove(Chan *c) -{ - mntclunk(c, Tremove); -} - -static int -mntwstat(Chan *c, uchar *dp, int n) -{ - Mnt *m; - Mntrpc *r; - - m = mntchk(c); - r = mntralloc(c, m->msize); - if(waserror()) { - mntfree(r); - nexterror(); - } - r->request.type = Twstat; - r->request.fid = c->fid; - r->request.nstat = n; - r->request.stat = dp; - mountrpc(m, r); - poperror(); - mntfree(r); - return n; -} - -static long -mntread(Chan *c, void *buf, long n, vlong off) -{ - uchar *p, *e; - int nc, cache, isdir, dirlen; - - isdir = 0; - cache = c->flag & CCACHE; - if(c->qid.type & QTDIR) { - cache = 0; - isdir = 1; - } - - p = buf; - if(cache) { - nc = cread(c, buf, n, off); - if(nc > 0) { - n -= nc; - if(n == 0) - return nc; - p += nc; - off += nc; - } - n = mntrdwr(Tread, c, p, n, off); - cupdate(c, p, n, off); - return n + nc; - } - - n = mntrdwr(Tread, c, buf, n, off); - if(isdir) { - for(e = &p[n]; p+BIT16SZ < e; p += dirlen){ - dirlen = BIT16SZ+GBIT16(p); - if(p+dirlen > e) - break; - validstat(p, dirlen); - mntdirfix(p, c); - } - if(p != e) - error(Esbadstat); - } - return n; -} - -static long -mntwrite(Chan *c, void *buf, long n, vlong off) -{ - return mntrdwr(Twrite, c, buf, n, off); -} - -long -mntrdwr(int type, Chan *c, void *buf, long n, vlong off) -{ - Mnt *m; - Mntrpc *r; - char *uba; - int cache; - ulong cnt, nr, nreq; - - m = mntchk(c); - uba = buf; - cnt = 0; - cache = c->flag & CCACHE; - if(c->qid.type & QTDIR) - cache = 0; - for(;;) { - r = mntralloc(c, m->msize); - if(waserror()) { - mntfree(r); - nexterror(); - } - r->request.type = type; - r->request.fid = c->fid; - r->request.offset = off; - r->request.data = uba; - nr = n; - if(nr > m->msize-IOHDRSZ) - nr = m->msize-IOHDRSZ; - r->request.count = nr; - mountrpc(m, r); - nreq = r->request.count; - nr = r->reply.count; - if(nr > nreq) - nr = nreq; - - if(type == Tread) - r->b = bl2mem((uchar*)uba, r->b, nr); - else if(cache) - cwrite(c, (uchar*)uba, nr, off); - - poperror(); - mntfree(r); - off += nr; - uba += nr; - cnt += nr; - n -= nr; - if(nr != nreq || n == 0) - break; - } - return cnt; -} - -void -mountrpc(Mnt *m, Mntrpc *r) -{ - char *sn, *cn; - int t; - - r->reply.tag = 0; - r->reply.type = Tmax; /* can't ever be a valid message type */ - - mountio(m, r); - - t = r->reply.type; - switch(t) { - case Rerror: - error(r->reply.ename); - case Rflush: - error(Eintr); - default: - if(t == r->request.type+1) - break; - sn = "?"; - if(m->c->name != nil) - sn = m->c->name->s; - cn = "?"; - if(r->c != nil && r->c->name != nil) - cn = r->c->name->s; - print("mnt: proc %lud: mismatch from %s %s rep 0x%lux tag %d fid %d T%d R%d rp %d\n", - up->pid, sn, cn, - r, r->request.tag, r->request.fid, r->request.type, - r->reply.type, r->reply.tag); - error(Emountrpc); - } -} - -void -mountio(Mnt *m, Mntrpc *r) -{ - int n; - - while(waserror()) { - if(m->rip == up) - mntgate(m); - if(strcmp(up->errstr, Eintr) != 0){ - mntflushfree(m, r); - nexterror(); - } - r = mntflushalloc(r, m->msize); - } - - lock(&m->lk); - r->m = m; - r->list = m->queue; - m->queue = r; - unlock(&m->lk); - - /* Transmit a file system rpc */ - if(m->msize == 0) - panic("msize"); - n = convS2M(&r->request, r->rpc, m->msize); - if(n < 0) - panic("bad message type in mountio"); - if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n) - error(Emountrpc); - r->stime = fastticks(nil); - r->reqlen = n; - - /* Gate readers onto the mount point one at a time */ - for(;;) { - lock(&m->lk); - if(m->rip == 0) - break; - unlock(&m->lk); - sleep(&r->r, rpcattn, r); - if(r->done){ - poperror(); - mntflushfree(m, r); - return; - } - } - m->rip = up; - unlock(&m->lk); - while(r->done == 0) { - if(mntrpcread(m, r) < 0) - error(Emountrpc); - mountmux(m, r); - } - mntgate(m); - poperror(); - mntflushfree(m, r); -} - -static int -doread(Mnt *m, int len) -{ - Block *b; - - while(qlen(m->q) < len){ - b = devtab[m->c->type]->bread(m->c, m->msize, 0); - if(b == nil) - return -1; - if(BLEN(b) == 0){ - freeblist(b); - return -1; - } - qaddlist(m->q, b); - } - return 0; -} - -int -mntrpcread(Mnt *m, Mntrpc *r) -{ - int i, t, len, hlen; - Block *b, **l, *nb; - - r->reply.type = 0; - r->reply.tag = 0; - - /* read at least length, type, and tag and pullup to a single block */ - if(doread(m, BIT32SZ+BIT8SZ+BIT16SZ) < 0) - return -1; - nb = pullupqueue(m->q, BIT32SZ+BIT8SZ+BIT16SZ); - - /* read in the rest of the message, avoid rediculous (for now) message sizes */ - len = GBIT32(nb->rp); - if(len > m->msize){ - qdiscard(m->q, qlen(m->q)); - return -1; - } - if(doread(m, len) < 0) - return -1; - - /* pullup the header (i.e. everything except data) */ - t = nb->rp[BIT32SZ]; - switch(t){ - case Rread: - hlen = BIT32SZ+BIT8SZ+BIT16SZ+BIT32SZ; - break; - default: - hlen = len; - break; - } - nb = pullupqueue(m->q, hlen); - - if(convM2S(nb->rp, len, &r->reply) <= 0){ - /* bad message, dump it */ - print("mntrpcread: convM2S failed\n"); - qdiscard(m->q, len); - return -1; - } - - /* hang the data off of the fcall struct */ - l = &r->b; - *l = nil; - do { - b = qremove(m->q); - if(hlen > 0){ - b->rp += hlen; - len -= hlen; - hlen = 0; - } - i = BLEN(b); - if(i <= len){ - len -= i; - *l = b; - l = &(b->next); - } else { - /* split block and put unused bit back */ - nb = allocb(i-len); - memmove(nb->wp, b->rp+len, i-len); - b->wp = b->rp+len; - nb->wp += i-len; - qputback(m->q, nb); - *l = b; - return 0; - } - }while(len > 0); - - return 0; -} - -void -mntgate(Mnt *m) -{ - Mntrpc *q; - - lock(&m->lk); - m->rip = 0; - for(q = m->queue; q; q = q->list) { - if(q->done == 0) - if(wakeup(&q->r)) - break; - } - unlock(&m->lk); -} - -void -mountmux(Mnt *m, Mntrpc *r) -{ - Mntrpc **l, *q; - - lock(&m->lk); - l = &m->queue; - for(q = *l; q; q = q->list) { - /* look for a reply to a message */ - if(q->request.tag == r->reply.tag) { - *l = q->list; - if(q != r) { - /* - * Completed someone else. - * Trade pointers to receive buffer. - */ - q->reply = r->reply; - q->b = r->b; - r->b = nil; - } - q->done = 1; - unlock(&m->lk); - if(mntstats != 0) - (*mntstats)(q->request.type, - m->c, q->stime, - q->reqlen + r->replen); - if(q != r) - wakeup(&q->r); - return; - } - l = &q->list; - } - unlock(&m->lk); - print("unexpected reply tag %ud; type %d\n", r->reply.tag, r->reply.type); -} - -/* - * Create a new flush request and chain the previous - * requests from it - */ -Mntrpc* -mntflushalloc(Mntrpc *r, ulong iounit) -{ - Mntrpc *fr; - - fr = mntralloc(0, iounit); - - fr->request.type = Tflush; - if(r->request.type == Tflush) - fr->request.oldtag = r->request.oldtag; - else - fr->request.oldtag = r->request.tag; - fr->flushed = r; - - return fr; -} - -/* - * Free a chain of flushes. Remove each unanswered - * flush and the original message from the unanswered - * request queue. Mark the original message as done - * and if it hasn't been answered set the reply to to - * Rflush. - */ -void -mntflushfree(Mnt *m, Mntrpc *r) -{ - Mntrpc *fr; - - while(r){ - fr = r->flushed; - if(!r->done){ - r->reply.type = Rflush; - mntqrm(m, r); - } - if(fr) - mntfree(r); - r = fr; - } -} - -int -alloctag(void) -{ - int i, j; - ulong v; - - for(i = 0; i < NMASK; i++){ - v = mntalloc.tagmask[i]; - if(v == ~0) - continue; - for(j = 0; j < 1<<TAGSHIFT; j++) - if((v & (1<<j)) == 0){ - mntalloc.tagmask[i] |= 1<<j; - return (i<<TAGSHIFT) + j; - } - } - panic("no friggin tags left"); - return NOTAG; -} - -void -freetag(int t) -{ - mntalloc.tagmask[t>>TAGSHIFT] &= ~(1<<(t&TAGMASK)); -} - -Mntrpc* -mntralloc(Chan *c, ulong msize) -{ - Mntrpc *new; - - lock(&mntalloc.lk); - new = mntalloc.rpcfree; - if(new == nil){ - new = malloc(sizeof(Mntrpc)); - if(new == nil) { - unlock(&mntalloc.lk); - exhausted("mount rpc header"); - } - /* - * The header is split from the data buffer as - * mountmux may swap the buffer with another header. - */ - new->rpc = mallocz(msize, 0); - if(new->rpc == nil){ - free(new); - unlock(&mntalloc.lk); - exhausted("mount rpc buffer"); - } - new->rpclen = msize; - new->request.tag = alloctag(); - } - else { - mntalloc.rpcfree = new->list; - mntalloc.nrpcfree--; - if(new->rpclen < msize){ - free(new->rpc); - new->rpc = mallocz(msize, 0); - if(new->rpc == nil){ - free(new); - mntalloc.nrpcused--; - unlock(&mntalloc.lk); - exhausted("mount rpc buffer"); - } - new->rpclen = msize; - } - } - mntalloc.nrpcused++; - unlock(&mntalloc.lk); - new->c = c; - new->done = 0; - new->flushed = nil; - new->b = nil; - return new; -} - -void -mntfree(Mntrpc *r) -{ - if(r->b != nil) - freeblist(r->b); - lock(&mntalloc.lk); - if(mntalloc.nrpcfree >= 10){ - free(r->rpc); - free(r); - freetag(r->request.tag); - } - else{ - r->list = mntalloc.rpcfree; - mntalloc.rpcfree = r; - mntalloc.nrpcfree++; - } - mntalloc.nrpcused--; - unlock(&mntalloc.lk); -} - -void -mntqrm(Mnt *m, Mntrpc *r) -{ - Mntrpc **l, *f; - - lock(&m->lk); - r->done = 1; - - l = &m->queue; - for(f = *l; f; f = f->list) { - if(f == r) { - *l = r->list; - break; - } - l = &f->list; - } - unlock(&m->lk); -} - -Mnt* -mntchk(Chan *c) -{ - Mnt *m; - - /* This routine is mostly vestiges of prior lives; now it's just sanity checking */ - - if(c->mchan == nil) - panic("mntchk 1: nil mchan c %s\n", c2name(c)); - - m = c->mchan->mux; - - if(m == nil) - print("mntchk 2: nil mux c %s c->mchan %s \n", c2name(c), c2name(c->mchan)); - - /* - * Was it closed and reused (was error(Eshutdown); now, it can't happen) - */ - if(m->id == 0 || m->id >= c->dev) - panic("mntchk 3: can't happen"); - - return m; -} - -/* - * Rewrite channel type and dev for in-flight data to - * reflect local values. These entries are known to be - * the first two in the Dir encoding after the count. - */ -void -mntdirfix(uchar *dirbuf, Chan *c) -{ - uint r; - - r = devtab[c->type]->dc; - dirbuf += BIT16SZ; /* skip count */ - PBIT16(dirbuf, r); - dirbuf += BIT16SZ; - PBIT32(dirbuf, c->dev); -} - -int -rpcattn(void *v) -{ - Mntrpc *r; - - r = v; - return r->done || r->m->rip == 0; -} - -Dev mntdevtab = { - 'M', - "mnt", - - mntreset, - devinit, - devshutdown, - mntattach, - mntwalk, - mntstat, - mntopen, - mntcreate, - mntclose, - mntread, - devbread, - mntwrite, - devbwrite, - mntremove, - mntwstat, -}; diff --git a/sys/src/cmd/unix/drawterm/kern/devmouse.c b/sys/src/cmd/unix/drawterm/kern/devmouse.c deleted file mode 100644 index 3ee0c8b6b..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devmouse.c +++ /dev/null @@ -1,237 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#include "draw.h" -#include "memdraw.h" -#include "screen.h" - -int mousequeue = 1; - -Mouseinfo mouse; -Cursorinfo cursor; - -static int mousechanged(void*); - -enum{ - Qdir, - Qcursor, - Qmouse -}; - -Dirtab mousedir[]={ - ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, - "cursor", {Qcursor}, 0, 0666, - "mouse", {Qmouse}, 0, 0666, -}; - -#define NMOUSE (sizeof(mousedir)/sizeof(Dirtab)) - -static Chan* -mouseattach(char *spec) -{ - return devattach('m', spec); -} - -static Walkqid* -mousewalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, mousedir, NMOUSE, devgen); -} - -static int -mousestat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, mousedir, NMOUSE, devgen); -} - -static Chan* -mouseopen(Chan *c, int omode) -{ - switch((long)c->qid.path){ - case Qdir: - if(omode != OREAD) - error(Eperm); - break; - case Qmouse: - lock(&mouse.lk); - if(mouse.open){ - unlock(&mouse.lk); - error(Einuse); - } - mouse.open = 1; - unlock(&mouse.lk); - break; - } - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - return c; -} - -void -mouseclose(Chan *c) -{ - if(!(c->flag&COPEN)) - return; - - switch((long)c->qid.path) { - case Qmouse: - lock(&mouse.lk); - mouse.open = 0; - unlock(&mouse.lk); - cursorarrow(); - } -} - - -long -mouseread(Chan *c, void *va, long n, vlong offset) -{ - char buf[4*12+1]; - uchar *p; - int i, nn; - ulong msec; -/* static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; */ - - p = va; - switch((long)c->qid.path){ - case Qdir: - return devdirread(c, va, n, mousedir, NMOUSE, devgen); - - case Qcursor: - if(offset != 0) - return 0; - if(n < 2*4+2*2*16) - error(Eshort); - n = 2*4+2*2*16; - lock(&cursor.lk); - BPLONG(p+0, cursor.offset.x); - BPLONG(p+4, cursor.offset.y); - memmove(p+8, cursor.clr, 2*16); - memmove(p+40, cursor.set, 2*16); - unlock(&cursor.lk); - return n; - - case Qmouse: - while(mousechanged(0) == 0) - sleep(&mouse.r, mousechanged, 0); - - lock(&screen.lk); - if(screen.reshaped) { - screen.reshaped = 0; - sprint(buf, "t%11d %11d", 0, ticks()); - if(n > 1+2*12) - n = 1+2*12; - memmove(va, buf, n); - unlock(&screen.lk); - return n; - } - unlock(&screen.lk); - - lock(&mouse.lk); - i = mouse.ri; - nn = (mouse.wi + Mousequeue - i) % Mousequeue; - if(nn < 1) - panic("empty mouse queue"); - msec = ticks(); - while(nn > 1) { - if(mouse.queue[i].msec + Mousewindow > msec) - break; - i = (i+1)%Mousequeue; - nn--; - } - sprint(buf, "m%11d %11d %11d %11d", - mouse.queue[i].xy.x, - mouse.queue[i].xy.y, - mouse.queue[i].buttons, - mouse.queue[i].msec); - mouse.ri = (i+1)%Mousequeue; - unlock(&mouse.lk); - if(n > 1+4*12) - n = 1+4*12; - memmove(va, buf, n); - return n; - } - return 0; -} - -long -mousewrite(Chan *c, void *va, long n, vlong offset) -{ - char *p; - Point pt; - char buf[64]; - - USED(offset); - - p = va; - switch((long)c->qid.path){ - case Qdir: - error(Eisdir); - - case Qcursor: - if(n < 2*4+2*2*16){ - cursorarrow(); - }else{ - n = 2*4+2*2*16; - lock(&cursor.lk); - cursor.offset.x = BGLONG(p+0); - cursor.offset.y = BGLONG(p+4); - memmove(cursor.clr, p+8, 2*16); - memmove(cursor.set, p+40, 2*16); - unlock(&cursor.lk); - setcursor(); - } - return n; - - case Qmouse: - if(n > sizeof buf-1) - n = sizeof buf -1; - memmove(buf, va, n); - buf[n] = 0; - p = 0; - pt.x = strtoul(buf+1, &p, 0); - if(p == 0) - error(Eshort); - pt.y = strtoul(p, 0, 0); - if(ptinrect(pt, gscreen->r)) - mouseset(pt); - return n; - } - - error(Egreg); - return -1; -} - -int -mousechanged(void *a) -{ - USED(a); - - return mouse.ri != mouse.wi || screen.reshaped; -} - -Dev mousedevtab = { - 'm', - "mouse", - - devreset, - devinit, - devshutdown, - mouseattach, - mousewalk, - mousestat, - mouseopen, - devcreate, - mouseclose, - mouseread, - devbread, - mousewrite, - devbwrite, - devremove, - devwstat, -}; - diff --git a/sys/src/cmd/unix/drawterm/kern/devpipe.c b/sys/src/cmd/unix/drawterm/kern/devpipe.c deleted file mode 100644 index 73401f99f..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devpipe.c +++ /dev/null @@ -1,398 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#include "netif.h" - -typedef struct Pipe Pipe; -struct Pipe -{ - QLock lk; - Pipe *next; - int ref; - ulong path; - Queue *q[2]; - int qref[2]; -}; - -struct -{ - Lock lk; - ulong path; -} pipealloc; - -enum -{ - Qdir, - Qdata0, - Qdata1, -}; - -Dirtab pipedir[] = -{ - ".", {Qdir,0,QTDIR}, 0, DMDIR|0500, - "data", {Qdata0}, 0, 0600, - "data1", {Qdata1}, 0, 0600, -}; -#define NPIPEDIR 3 - -static void -pipeinit(void) -{ - if(conf.pipeqsize == 0){ - if(conf.nmach > 1) - conf.pipeqsize = 256*1024; - else - conf.pipeqsize = 32*1024; - } -} - -/* - * create a pipe, no streams are created until an open - */ -static Chan* -pipeattach(char *spec) -{ - Pipe *p; - Chan *c; - - c = devattach('|', spec); - p = malloc(sizeof(Pipe)); - if(p == 0) - exhausted("memory"); - p->ref = 1; - - p->q[0] = qopen(conf.pipeqsize, 0, 0, 0); - if(p->q[0] == 0){ - free(p); - exhausted("memory"); - } - p->q[1] = qopen(conf.pipeqsize, 0, 0, 0); - if(p->q[1] == 0){ - free(p->q[0]); - free(p); - exhausted("memory"); - } - - lock(&pipealloc.lk); - p->path = ++pipealloc.path; - unlock(&pipealloc.lk); - - mkqid(&c->qid, NETQID(2*p->path, Qdir), 0, QTDIR); - c->aux = p; - c->dev = 0; - return c; -} - -static int -pipegen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp) -{ - Qid q; - int len; - Pipe *p; - - USED(name); - - if(i == DEVDOTDOT){ - devdir(c, c->qid, "#|", 0, eve, DMDIR|0555, dp); - return 1; - } - i++; /* skip . */ - if(tab==0 || i>=ntab) - return -1; - - tab += i; - p = c->aux; - switch((ulong)tab->qid.path){ - case Qdata0: - len = qlen(p->q[0]); - break; - case Qdata1: - len = qlen(p->q[1]); - break; - default: - len = tab->length; - break; - } - mkqid(&q, NETQID(NETID(c->qid.path), tab->qid.path), 0, QTFILE); - devdir(c, q, tab->name, len, eve, tab->perm, dp); - return 1; -} - - -static Walkqid* -pipewalk(Chan *c, Chan *nc, char **name, int nname) -{ - Walkqid *wq; - Pipe *p; - - wq = devwalk(c, nc, name, nname, pipedir, NPIPEDIR, pipegen); - if(wq != nil && wq->clone != nil && wq->clone != c){ - p = c->aux; - qlock(&p->lk); - p->ref++; - if(c->flag & COPEN){ - print("channel open in pipewalk\n"); - switch(NETTYPE(c->qid.path)){ - case Qdata0: - p->qref[0]++; - break; - case Qdata1: - p->qref[1]++; - break; - } - } - qunlock(&p->lk); - } - return wq; -} - -static int -pipestat(Chan *c, uchar *db, int n) -{ - Pipe *p; - Dir dir; - - p = c->aux; - - switch(NETTYPE(c->qid.path)){ - case Qdir: - devdir(c, c->qid, ".", 0, eve, DMDIR|0555, &dir); - break; - case Qdata0: - devdir(c, c->qid, "data", qlen(p->q[0]), eve, 0600, &dir); - break; - case Qdata1: - devdir(c, c->qid, "data1", qlen(p->q[1]), eve, 0600, &dir); - break; - default: - panic("pipestat"); - } - n = convD2M(&dir, db, n); - if(n < BIT16SZ) - error(Eshortstat); - return n; -} - -/* - * if the stream doesn't exist, create it - */ -static Chan* -pipeopen(Chan *c, int omode) -{ - Pipe *p; - - if(c->qid.type & QTDIR){ - if(omode != OREAD) - error(Ebadarg); - c->mode = omode; - c->flag |= COPEN; - c->offset = 0; - return c; - } - - p = c->aux; - qlock(&p->lk); - switch(NETTYPE(c->qid.path)){ - case Qdata0: - p->qref[0]++; - break; - case Qdata1: - p->qref[1]++; - break; - } - qunlock(&p->lk); - - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - c->iounit = qiomaxatomic; - return c; -} - -static void -pipeclose(Chan *c) -{ - Pipe *p; - - p = c->aux; - qlock(&p->lk); - - if(c->flag & COPEN){ - /* - * closing either side hangs up the stream - */ - switch(NETTYPE(c->qid.path)){ - case Qdata0: - p->qref[0]--; - if(p->qref[0] == 0){ - qhangup(p->q[1], 0); - qclose(p->q[0]); - } - break; - case Qdata1: - p->qref[1]--; - if(p->qref[1] == 0){ - qhangup(p->q[0], 0); - qclose(p->q[1]); - } - break; - } - } - - - /* - * if both sides are closed, they are reusable - */ - if(p->qref[0] == 0 && p->qref[1] == 0){ - qreopen(p->q[0]); - qreopen(p->q[1]); - } - - /* - * free the structure on last close - */ - p->ref--; - if(p->ref == 0){ - qunlock(&p->lk); - free(p->q[0]); - free(p->q[1]); - free(p); - } else - qunlock(&p->lk); -} - -static long -piperead(Chan *c, void *va, long n, vlong offset) -{ - Pipe *p; - - USED(offset); - - p = c->aux; - - switch(NETTYPE(c->qid.path)){ - case Qdir: - return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen); - case Qdata0: - return qread(p->q[0], va, n); - case Qdata1: - return qread(p->q[1], va, n); - default: - panic("piperead"); - } - return -1; /* not reached */ -} - -static Block* -pipebread(Chan *c, long n, ulong offset) -{ - Pipe *p; - - p = c->aux; - - switch(NETTYPE(c->qid.path)){ - case Qdata0: - return qbread(p->q[0], n); - case Qdata1: - return qbread(p->q[1], n); - } - - return devbread(c, n, offset); -} - -/* - * a write to a closed pipe causes a note to be sent to - * the process. - */ -static long -pipewrite(Chan *c, void *va, long n, vlong offset) -{ - Pipe *p; - - USED(offset); - if(!islo()) - print("pipewrite hi %lux\n", getcallerpc(&c)); - - if(waserror()) { - /* avoid notes when pipe is a mounted queue */ - if((c->flag & CMSG) == 0) - postnote(up, 1, "sys: write on closed pipe", NUser); - nexterror(); - } - - p = c->aux; - - switch(NETTYPE(c->qid.path)){ - case Qdata0: - n = qwrite(p->q[1], va, n); - break; - - case Qdata1: - n = qwrite(p->q[0], va, n); - break; - - default: - panic("pipewrite"); - } - - poperror(); - return n; -} - -static long -pipebwrite(Chan *c, Block *bp, ulong offset) -{ - long n; - Pipe *p; - - USED(offset); - - if(waserror()) { - /* avoid notes when pipe is a mounted queue */ - if((c->flag & CMSG) == 0) - postnote(up, 1, "sys: write on closed pipe", NUser); - nexterror(); - } - - p = c->aux; - switch(NETTYPE(c->qid.path)){ - case Qdata0: - n = qbwrite(p->q[1], bp); - break; - - case Qdata1: - n = qbwrite(p->q[0], bp); - break; - - default: - n = 0; - panic("pipebwrite"); - } - - poperror(); - return n; -} - -Dev pipedevtab = { - '|', - "pipe", - - devreset, - pipeinit, - devshutdown, - pipeattach, - pipewalk, - pipestat, - pipeopen, - devcreate, - pipeclose, - piperead, - pipebread, - pipewrite, - pipebwrite, - devremove, - devwstat, -}; diff --git a/sys/src/cmd/unix/drawterm/kern/devroot.c b/sys/src/cmd/unix/drawterm/kern/devroot.c deleted file mode 100644 index db081ff1f..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devroot.c +++ /dev/null @@ -1,299 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -enum -{ - Qdir = 0, - Qboot = 0x1000, - Qmnt = 0x2000, - Qfactotum, - - Nrootfiles = 32, - Nbootfiles = 32, - Nmntfiles = 2, -}; - -typedef struct Dirlist Dirlist; -struct Dirlist -{ - uint base; - Dirtab *dir; - uchar **data; - int ndir; - int mdir; -}; - -static Dirtab rootdir[Nrootfiles] = { - "#/", {Qdir, 0, QTDIR}, 0, DMDIR|0555, - "boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555, - "mnt", {Qmnt, 0, QTDIR}, 0, DMDIR|0555, -}; -static uchar *rootdata[Nrootfiles]; -static Dirlist rootlist = -{ - 0, - rootdir, - rootdata, - 3, - Nrootfiles -}; - -static Dirtab bootdir[Nbootfiles] = { - "boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555, -}; -static uchar *bootdata[Nbootfiles]; -static Dirlist bootlist = -{ - Qboot, - bootdir, - bootdata, - 1, - Nbootfiles -}; - -static uchar *mntdata[Nmntfiles]; -static Dirtab mntdir[Nmntfiles] = { - "mnt", {Qmnt, 0, QTDIR}, 0, DMDIR|0555, - "factotum", {Qfactotum, 0, QTDIR}, 0, DMDIR|0555, -}; -static Dirlist mntlist = -{ - Qmnt, - mntdir, - mntdata, - 2, - Nmntfiles -}; - -/* - * add a file to the list - */ -static void -addlist(Dirlist *l, char *name, uchar *contents, ulong len, int perm) -{ - Dirtab *d; - - if(l->ndir >= l->mdir) - panic("too many root files"); - l->data[l->ndir] = contents; - d = &l->dir[l->ndir]; - strcpy(d->name, name); - d->length = len; - d->perm = perm; - d->qid.type = 0; - d->qid.vers = 0; - d->qid.path = ++l->ndir + l->base; - if(perm & DMDIR) - d->qid.type |= QTDIR; -} - -/* - * add a root file - */ -void -addbootfile(char *name, uchar *contents, ulong len) -{ - addlist(&bootlist, name, contents, len, 0555); -} - -/* - * add a root directory - */ -static void -addrootdir(char *name) -{ - addlist(&rootlist, name, nil, 0, DMDIR|0555); -} - -static void -rootreset(void) -{ - addrootdir("bin"); - addrootdir("dev"); - addrootdir("env"); - addrootdir("fd"); - addrootdir("net"); - addrootdir("net.alt"); - addrootdir("proc"); - addrootdir("root"); - addrootdir("srv"); -} - -static Chan* -rootattach(char *spec) -{ - return devattach('/', spec); -} - -static int -rootgen(Chan *c, char *name, Dirtab *dirt, int ndirt, int s, Dir *dp) -{ - int t; - Dirtab *d; - Dirlist *l; - - USED(dirt); - USED(ndirt); - - switch((int)c->qid.path){ - case Qdir: - if(s == DEVDOTDOT){ - Qid tqiddir = {Qdir, 0, QTDIR}; - devdir(c, tqiddir, "#/", 0, eve, 0555, dp); - return 1; - } - return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp); - case Qmnt: - if(s == DEVDOTDOT){ - Qid tqiddir = {Qdir, 0, QTDIR}; - devdir(c, tqiddir, "#/", 0, eve, 0555, dp); - return 1; - } - return devgen(c, name, mntlist.dir, mntlist.ndir, s, dp); - case Qboot: - if(s == DEVDOTDOT){ - Qid tqiddir = {Qdir, 0, QTDIR}; - devdir(c, tqiddir, "#/", 0, eve, 0555, dp); - return 1; - } - return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp); - default: - if(s == DEVDOTDOT){ - Qid tqiddir = {Qdir, 0, QTDIR}; - tqiddir.path = c->qid.path&0xF000; - devdir(c, tqiddir, "#/", 0, eve, 0555, dp); - return 1; - } - if(s != 0) - return -1; - switch((int)c->qid.path & 0xF000){ - case Qdir: - t = c->qid.path-1; - l = &rootlist; - break; - case Qboot: - t = c->qid.path - Qboot - 1; - l = &bootlist; - break; - case Qmnt: - t = c->qid.path - Qmnt - 1; - l = &mntlist; - break; - default: - return -1; - } - if(t >= l->ndir) - return -1; -if(t < 0){ -print("rootgen %llud %d %d\n", c->qid.path, s, t); -panic("whoops"); -} - d = &l->dir[t]; - devdir(c, d->qid, d->name, d->length, eve, d->perm, dp); - return 1; - } - return -1; -} - -static Walkqid* -rootwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, nil, 0, rootgen); -} - -static int -rootstat(Chan *c, uchar *dp, int n) -{ - return devstat(c, dp, n, nil, 0, rootgen); -} - -static Chan* -rootopen(Chan *c, int omode) -{ - return devopen(c, omode, nil, 0, devgen); -} - -/* - * sysremove() knows this is a nop - */ -static void -rootclose(Chan *c) -{ - USED(c); -} - -static long -rootread(Chan *c, void *buf, long n, vlong off) -{ - ulong t; - Dirtab *d; - Dirlist *l; - uchar *data; - ulong offset = off; - - t = c->qid.path; - switch(t){ - case Qdir: - case Qboot: - case Qmnt: - return devdirread(c, buf, n, nil, 0, rootgen); - } - - if(t&Qboot) - l = &bootlist; - else if(t&Qmnt) - l = &mntlist; - else - l = &bootlist; - t &= 0xFFF; - t--; - - if(t >= l->ndir) - error(Egreg); - - d = &l->dir[t]; - data = l->data[t]; - if(offset >= d->length) - return 0; - if(offset+n > d->length) - n = d->length - offset; - memmove(buf, data+offset, n); - return n; -} - -static long -rootwrite(Chan *c, void *v, long n, vlong o) -{ - USED(c); - USED(v); - USED(n); - USED(o); - - error(Egreg); - return 0; -} - -Dev rootdevtab = { - '/', - "root", - - rootreset, - devinit, - devshutdown, - rootattach, - rootwalk, - rootstat, - rootopen, - devcreate, - rootclose, - rootread, - devbread, - rootwrite, - devbwrite, - devremove, - devwstat, -}; - diff --git a/sys/src/cmd/unix/drawterm/kern/devssl.c b/sys/src/cmd/unix/drawterm/kern/devssl.c deleted file mode 100644 index 3ad021f9f..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devssl.c +++ /dev/null @@ -1,1517 +0,0 @@ -/* - * devssl - secure sockets layer - */ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#include "libsec.h" - -#define NOSPOOKS 1 - -typedef struct OneWay OneWay; -struct OneWay -{ - QLock q; - QLock ctlq; - - void *state; /* encryption state */ - int slen; /* hash data length */ - uchar *secret; /* secret */ - ulong mid; /* message id */ -}; - -enum -{ - /* connection states */ - Sincomplete= 0, - Sclear= 1, - Sencrypting= 2, - Sdigesting= 4, - Sdigenc= Sencrypting|Sdigesting, - - /* encryption algorithms */ - Noencryption= 0, - DESCBC= 1, - DESECB= 2, - RC4= 3 -}; - -typedef struct Dstate Dstate; -struct Dstate -{ - Chan *c; /* io channel */ - uchar state; /* state of connection */ - int ref; /* serialized by dslock for atomic destroy */ - - uchar encryptalg; /* encryption algorithm */ - ushort blocklen; /* blocking length */ - - ushort diglen; /* length of digest */ - DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*); /* hash func */ - - /* for SSL format */ - int max; /* maximum unpadded data per msg */ - int maxpad; /* maximum padded data per msg */ - - /* input side */ - OneWay in; - Block *processed; - Block *unprocessed; - - /* output side */ - OneWay out; - - /* protections */ - char *user; - int perm; -}; - -enum -{ - Maxdmsg= 1<<16, - Maxdstate= 128, /* must be a power of 2 */ -}; - -Lock dslock; -int dshiwat; -char *dsname[Maxdstate]; -Dstate *dstate[Maxdstate]; -char *encalgs; -char *hashalgs; - -enum{ - Qtopdir = 1, /* top level directory */ - Qprotodir, - Qclonus, - Qconvdir, /* directory for a conversation */ - Qdata, - Qctl, - Qsecretin, - Qsecretout, - Qencalgs, - Qhashalgs, -}; - -#define TYPE(x) ((x).path & 0xf) -#define CONV(x) (((x).path >> 5)&(Maxdstate-1)) -#define QID(c, y) (((c)<<5) | (y)) - -static void ensure(Dstate*, Block**, int); -static void consume(Block**, uchar*, int); -static void setsecret(OneWay*, uchar*, int); -static Block* encryptb(Dstate*, Block*, int); -static Block* decryptb(Dstate*, Block*); -static Block* digestb(Dstate*, Block*, int); -static void checkdigestb(Dstate*, Block*); -static Chan* buftochan(char*); -static void sslhangup(Dstate*); -static Dstate* dsclone(Chan *c); -static void dsnew(Chan *c, Dstate **); -static long sslput(Dstate *s, Block * volatile b); - -char *sslnames[] = { - /* unused */ 0, - /* topdir */ 0, - /* protodir */ 0, - "clone", - /* convdir */ 0, - "data", - "ctl", - "secretin", - "secretout", - "encalgs", - "hashalgs", -}; - -static int -sslgen(Chan *c, char *n, Dirtab *d, int nd, int s, Dir *dp) -{ - Qid q; - Dstate *ds; - char name[16], *p, *nm; - int ft; - - USED(n); - USED(nd); - USED(d); - - q.type = QTFILE; - q.vers = 0; - - ft = TYPE(c->qid); - switch(ft) { - case Qtopdir: - if(s == DEVDOTDOT){ - q.path = QID(0, Qtopdir); - q.type = QTDIR; - devdir(c, q, "#D", 0, eve, 0555, dp); - return 1; - } - if(s > 0) - return -1; - q.path = QID(0, Qprotodir); - q.type = QTDIR; - devdir(c, q, "ssl", 0, eve, 0555, dp); - return 1; - case Qprotodir: - if(s == DEVDOTDOT){ - q.path = QID(0, Qtopdir); - q.type = QTDIR; - devdir(c, q, ".", 0, eve, 0555, dp); - return 1; - } - if(s < dshiwat) { - q.path = QID(s, Qconvdir); - q.type = QTDIR; - ds = dstate[s]; - if(ds != 0) - nm = ds->user; - else - nm = eve; - if(dsname[s] == nil){ - sprint(name, "%d", s); - kstrdup(&dsname[s], name); - } - devdir(c, q, dsname[s], 0, nm, 0555, dp); - return 1; - } - if(s > dshiwat) - return -1; - q.path = QID(0, Qclonus); - devdir(c, q, "clone", 0, eve, 0555, dp); - return 1; - case Qconvdir: - if(s == DEVDOTDOT){ - q.path = QID(0, Qprotodir); - q.type = QTDIR; - devdir(c, q, "ssl", 0, eve, 0555, dp); - return 1; - } - ds = dstate[CONV(c->qid)]; - if(ds != 0) - nm = ds->user; - else - nm = eve; - switch(s) { - default: - return -1; - case 0: - q.path = QID(CONV(c->qid), Qctl); - p = "ctl"; - break; - case 1: - q.path = QID(CONV(c->qid), Qdata); - p = "data"; - break; - case 2: - q.path = QID(CONV(c->qid), Qsecretin); - p = "secretin"; - break; - case 3: - q.path = QID(CONV(c->qid), Qsecretout); - p = "secretout"; - break; - case 4: - q.path = QID(CONV(c->qid), Qencalgs); - p = "encalgs"; - break; - case 5: - q.path = QID(CONV(c->qid), Qhashalgs); - p = "hashalgs"; - break; - } - devdir(c, q, p, 0, nm, 0660, dp); - return 1; - case Qclonus: - devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, eve, 0555, dp); - return 1; - default: - ds = dstate[CONV(c->qid)]; - if(ds != 0) - nm = ds->user; - else - nm = eve; - devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, nm, 0660, dp); - return 1; - } - return -1; -} - -static Chan* -sslattach(char *spec) -{ - Chan *c; - - c = devattach('D', spec); - c->qid.path = QID(0, Qtopdir); - c->qid.vers = 0; - c->qid.type = QTDIR; - return c; -} - -static Walkqid* -sslwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, nil, 0, sslgen); -} - -static int -sslstat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, nil, 0, sslgen); -} - -static Chan* -sslopen(Chan *c, int omode) -{ - Dstate *s, **pp; - int perm; - int ft; - - perm = 0; - omode &= 3; - switch(omode) { - case OREAD: - perm = 4; - break; - case OWRITE: - perm = 2; - break; - case ORDWR: - perm = 6; - break; - } - - ft = TYPE(c->qid); - switch(ft) { - default: - panic("sslopen"); - case Qtopdir: - case Qprotodir: - case Qconvdir: - if(omode != OREAD) - error(Eperm); - break; - case Qclonus: - s = dsclone(c); - if(s == 0) - error(Enodev); - break; - case Qctl: - case Qdata: - case Qsecretin: - case Qsecretout: - if(waserror()) { - unlock(&dslock); - nexterror(); - } - lock(&dslock); - pp = &dstate[CONV(c->qid)]; - s = *pp; - if(s == 0) - dsnew(c, pp); - else { - if((perm & (s->perm>>6)) != perm - && (strcmp(up->user, s->user) != 0 - || (perm & s->perm) != perm)) - error(Eperm); - - s->ref++; - } - unlock(&dslock); - poperror(); - break; - case Qencalgs: - case Qhashalgs: - if(omode != OREAD) - error(Eperm); - break; - } - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - return c; -} - -static int -sslwstat(Chan *c, uchar *db, int n) -{ - Dir *dir; - Dstate *s; - int m; - - s = dstate[CONV(c->qid)]; - if(s == 0) - error(Ebadusefd); - if(strcmp(s->user, up->user) != 0) - error(Eperm); - - dir = smalloc(sizeof(Dir)+n); - m = convM2D(db, n, &dir[0], (char*)&dir[1]); - if(m == 0){ - free(dir); - error(Eshortstat); - } - - if(!emptystr(dir->uid)) - kstrdup(&s->user, dir->uid); - if(dir->mode != ~0) - s->perm = dir->mode; - - free(dir); - return m; -} - -static void -sslclose(Chan *c) -{ - Dstate *s; - int ft; - - ft = TYPE(c->qid); - switch(ft) { - case Qctl: - case Qdata: - case Qsecretin: - case Qsecretout: - if((c->flag & COPEN) == 0) - break; - - s = dstate[CONV(c->qid)]; - if(s == 0) - break; - - lock(&dslock); - if(--s->ref > 0) { - unlock(&dslock); - break; - } - dstate[CONV(c->qid)] = 0; - unlock(&dslock); - - if(s->user != nil) - free(s->user); - sslhangup(s); - if(s->c) - cclose(s->c); - if(s->in.secret) - free(s->in.secret); - if(s->out.secret) - free(s->out.secret); - if(s->in.state) - free(s->in.state); - if(s->out.state) - free(s->out.state); - free(s); - - } -} - -/* - * make sure we have at least 'n' bytes in list 'l' - */ -static void -ensure(Dstate *s, Block **l, int n) -{ - int sofar, i; - Block *b, *bl; - - sofar = 0; - for(b = *l; b; b = b->next){ - sofar += BLEN(b); - if(sofar >= n) - return; - l = &b->next; - } - - while(sofar < n){ - bl = devtab[s->c->type]->bread(s->c, Maxdmsg, 0); - if(bl == 0) - nexterror(); - *l = bl; - i = 0; - for(b = bl; b; b = b->next){ - i += BLEN(b); - l = &b->next; - } - if(i == 0) - error(Ehungup); - sofar += i; - } -} - -/* - * copy 'n' bytes from 'l' into 'p' and free - * the bytes in 'l' - */ -static void -consume(Block **l, uchar *p, int n) -{ - Block *b; - int i; - - for(; *l && n > 0; n -= i){ - b = *l; - i = BLEN(b); - if(i > n) - i = n; - memmove(p, b->rp, i); - b->rp += i; - p += i; - if(BLEN(b) < 0) - panic("consume"); - if(BLEN(b)) - break; - *l = b->next; - freeb(b); - } -} - -/* - * give back n bytes -static void -regurgitate(Dstate *s, uchar *p, int n) -{ - Block *b; - - if(n <= 0) - return; - b = s->unprocessed; - if(s->unprocessed == nil || b->rp - b->base < n) { - b = allocb(n); - memmove(b->wp, p, n); - b->wp += n; - b->next = s->unprocessed; - s->unprocessed = b; - } else { - b->rp -= n; - memmove(b->rp, p, n); - } -} - */ - -/* - * remove at most n bytes from the queue, if discard is set - * dump the remainder - */ -static Block* -qtake(Block **l, int n, int discard) -{ - Block *nb, *b, *first; - int i; - - first = *l; - for(b = first; b; b = b->next){ - i = BLEN(b); - if(i == n){ - if(discard){ - freeblist(b->next); - *l = 0; - } else - *l = b->next; - b->next = 0; - return first; - } else if(i > n){ - i -= n; - if(discard){ - freeblist(b->next); - b->wp -= i; - *l = 0; - } else { - nb = allocb(i); - memmove(nb->wp, b->rp+n, i); - nb->wp += i; - b->wp -= i; - nb->next = b->next; - *l = nb; - } - b->next = 0; - if(BLEN(b) < 0) - panic("qtake"); - return first; - } else - n -= i; - if(BLEN(b) < 0) - panic("qtake"); - } - *l = 0; - return first; -} - -/* - * We can't let Eintr's lose data since the program - * doing the read may be able to handle it. The only - * places Eintr is possible is during the read's in consume. - * Therefore, we make sure we can always put back the bytes - * consumed before the last ensure. - */ -static Block* -sslbread(Chan *c, long n, ulong o) -{ - Dstate * volatile s; - Block *b; - uchar consumed[3], *p; - int toconsume; - int len, pad; - - USED(o); - s = dstate[CONV(c->qid)]; - if(s == 0) - panic("sslbread"); - if(s->state == Sincomplete) - error(Ebadusefd); - - qlock(&s->in.q); - if(waserror()){ - qunlock(&s->in.q); - nexterror(); - } - - if(s->processed == 0){ - /* - * Read in the whole message. Until we've got it all, - * it stays on s->unprocessed, so that if we get Eintr, - * we'll pick up where we left off. - */ - ensure(s, &s->unprocessed, 3); - s->unprocessed = pullupblock(s->unprocessed, 2); - p = s->unprocessed->rp; - if(p[0] & 0x80){ - len = ((p[0] & 0x7f)<<8) | p[1]; - ensure(s, &s->unprocessed, len); - pad = 0; - toconsume = 2; - } else { - s->unprocessed = pullupblock(s->unprocessed, 3); - len = ((p[0] & 0x3f)<<8) | p[1]; - pad = p[2]; - if(pad > len){ - print("pad %d buf len %d\n", pad, len); - error("bad pad in ssl message"); - } - toconsume = 3; - } - ensure(s, &s->unprocessed, toconsume+len); - - /* skip header */ - consume(&s->unprocessed, consumed, toconsume); - - /* grab the next message and decode/decrypt it */ - b = qtake(&s->unprocessed, len, 0); - - if(blocklen(b) != len) - print("devssl: sslbread got wrong count %d != %d", blocklen(b), len); - - if(waserror()){ - qunlock(&s->in.ctlq); - if(b != nil) - freeb(b); - nexterror(); - } - qlock(&s->in.ctlq); - switch(s->state){ - case Sencrypting: - if(b == nil) - error("ssl message too short (encrypting)"); - b = decryptb(s, b); - break; - case Sdigesting: - b = pullupblock(b, s->diglen); - if(b == nil) - error("ssl message too short (digesting)"); - checkdigestb(s, b); - pullblock(&b, s->diglen); - len -= s->diglen; - break; - case Sdigenc: - b = decryptb(s, b); - b = pullupblock(b, s->diglen); - if(b == nil) - error("ssl message too short (dig+enc)"); - checkdigestb(s, b); - pullblock(&b, s->diglen); - len -= s->diglen; - break; - } - - /* remove pad */ - if(pad) - s->processed = qtake(&b, len - pad, 1); - else - s->processed = b; - b = nil; - s->in.mid++; - qunlock(&s->in.ctlq); - poperror(); - } - - /* return at most what was asked for */ - b = qtake(&s->processed, n, 0); - - qunlock(&s->in.q); - poperror(); - - return b; -} - -static long -sslread(Chan *c, void *a, long n, vlong off) -{ - Block * volatile b; - Block *nb; - uchar *va; - int i; - char buf[128]; - ulong offset = off; - int ft; - - if(c->qid.type & QTDIR) - return devdirread(c, a, n, 0, 0, sslgen); - - ft = TYPE(c->qid); - switch(ft) { - default: - error(Ebadusefd); - case Qctl: - ft = CONV(c->qid); - sprint(buf, "%d", ft); - return readstr(offset, a, n, buf); - case Qdata: - b = sslbread(c, n, offset); - break; - case Qencalgs: - return readstr(offset, a, n, encalgs); - break; - case Qhashalgs: - return readstr(offset, a, n, hashalgs); - break; - } - - if(waserror()){ - freeblist(b); - nexterror(); - } - - n = 0; - va = a; - for(nb = b; nb; nb = nb->next){ - i = BLEN(nb); - memmove(va+n, nb->rp, i); - n += i; - } - - freeblist(b); - poperror(); - - return n; -} - -/* - * this algorithm doesn't have to be great since we're just - * trying to obscure the block fill - */ -static void -randfill(uchar *buf, int len) -{ - while(len-- > 0) - *buf++ = fastrand(); -} - -static long -sslbwrite(Chan *c, Block *b, ulong o) -{ - Dstate * volatile s; - long rv; - - USED(o); - s = dstate[CONV(c->qid)]; - if(s == nil) - panic("sslbwrite"); - - if(s->state == Sincomplete){ - freeb(b); - error(Ebadusefd); - } - - /* lock so split writes won't interleave */ - if(waserror()){ - qunlock(&s->out.q); - nexterror(); - } - qlock(&s->out.q); - - rv = sslput(s, b); - - poperror(); - qunlock(&s->out.q); - - return rv; -} - -/* - * use SSL record format, add in count, digest and/or encrypt. - * the write is interruptable. if it is interrupted, we'll - * get out of sync with the far side. not much we can do about - * it since we don't know if any bytes have been written. - */ -static long -sslput(Dstate *s, Block * volatile b) -{ - Block *nb; - int h, n, m, pad, rv; - uchar *p; - int offset; - - if(waserror()){ -iprint("error: %s\n", up->errstr); - if(b != nil) - free(b); - nexterror(); - } - - rv = 0; - while(b != nil){ - m = n = BLEN(b); - h = s->diglen + 2; - - /* trim to maximum block size */ - pad = 0; - if(m > s->max){ - m = s->max; - } else if(s->blocklen != 1){ - pad = (m + s->diglen)%s->blocklen; - if(pad){ - if(m > s->maxpad){ - pad = 0; - m = s->maxpad; - } else { - pad = s->blocklen - pad; - h++; - } - } - } - - rv += m; - if(m != n){ - nb = allocb(m + h + pad); - memmove(nb->wp + h, b->rp, m); - nb->wp += m + h; - b->rp += m; - } else { - /* add header space */ - nb = padblock(b, h); - b = 0; - } - m += s->diglen; - - /* SSL style count */ - if(pad){ - nb = padblock(nb, -pad); - randfill(nb->wp, pad); - nb->wp += pad; - m += pad; - - p = nb->rp; - p[0] = (m>>8); - p[1] = m; - p[2] = pad; - offset = 3; - } else { - p = nb->rp; - p[0] = (m>>8) | 0x80; - p[1] = m; - offset = 2; - } - - switch(s->state){ - case Sencrypting: - nb = encryptb(s, nb, offset); - break; - case Sdigesting: - nb = digestb(s, nb, offset); - break; - case Sdigenc: - nb = digestb(s, nb, offset); - nb = encryptb(s, nb, offset); - break; - } - - s->out.mid++; - - m = BLEN(nb); - devtab[s->c->type]->bwrite(s->c, nb, s->c->offset); - s->c->offset += m; - } - - poperror(); - return rv; -} - -static void -setsecret(OneWay *w, uchar *secret, int n) -{ - if(w->secret) - free(w->secret); - - w->secret = smalloc(n); - memmove(w->secret, secret, n); - w->slen = n; -} - -static void -initDESkey(OneWay *w) -{ - if(w->state){ - free(w->state); - w->state = 0; - } - - w->state = smalloc(sizeof(DESstate)); - if(w->slen >= 16) - setupDESstate(w->state, w->secret, w->secret+8); - else if(w->slen >= 8) - setupDESstate(w->state, w->secret, 0); - else - error("secret too short"); -} - -/* - * 40 bit DES is the same as 56 bit DES. However, - * 16 bits of the key are masked to zero. - */ -static void -initDESkey_40(OneWay *w) -{ - uchar key[8]; - - if(w->state){ - free(w->state); - w->state = 0; - } - - if(w->slen >= 8){ - memmove(key, w->secret, 8); - key[0] &= 0x0f; - key[2] &= 0x0f; - key[4] &= 0x0f; - key[6] &= 0x0f; - } - - w->state = malloc(sizeof(DESstate)); - if(w->slen >= 16) - setupDESstate(w->state, key, w->secret+8); - else if(w->slen >= 8) - setupDESstate(w->state, key, 0); - else - error("secret too short"); -} - -static void -initRC4key(OneWay *w) -{ - if(w->state){ - free(w->state); - w->state = 0; - } - - w->state = smalloc(sizeof(RC4state)); - setupRC4state(w->state, w->secret, w->slen); -} - -/* - * 40 bit RC4 is the same as n-bit RC4. However, - * we ignore all but the first 40 bits of the key. - */ -static void -initRC4key_40(OneWay *w) -{ - if(w->state){ - free(w->state); - w->state = 0; - } - - if(w->slen > 5) - w->slen = 5; - - w->state = malloc(sizeof(RC4state)); - setupRC4state(w->state, w->secret, w->slen); -} - -/* - * 128 bit RC4 is the same as n-bit RC4. However, - * we ignore all but the first 128 bits of the key. - */ -static void -initRC4key_128(OneWay *w) -{ - if(w->state){ - free(w->state); - w->state = 0; - } - - if(w->slen > 16) - w->slen = 16; - - w->state = malloc(sizeof(RC4state)); - setupRC4state(w->state, w->secret, w->slen); -} - - -typedef struct Hashalg Hashalg; -struct Hashalg -{ - char *name; - int diglen; - DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*); -}; - -Hashalg hashtab[] = -{ - { "md4", MD4dlen, md4, }, - { "md5", MD5dlen, md5, }, - { "sha1", SHA1dlen, sha1, }, - { "sha", SHA1dlen, sha1, }, - { 0 } -}; - -static int -parsehashalg(char *p, Dstate *s) -{ - Hashalg *ha; - - for(ha = hashtab; ha->name; ha++){ - if(strcmp(p, ha->name) == 0){ - s->hf = ha->hf; - s->diglen = ha->diglen; - s->state &= ~Sclear; - s->state |= Sdigesting; - return 0; - } - } - return -1; -} - -typedef struct Encalg Encalg; -struct Encalg -{ - char *name; - int blocklen; - int alg; - void (*keyinit)(OneWay*); -}; - -#ifdef NOSPOOKS -Encalg encrypttab[] = -{ - { "descbc", 8, DESCBC, initDESkey, }, /* DEPRECATED -- use des_56_cbc */ - { "desecb", 8, DESECB, initDESkey, }, /* DEPRECATED -- use des_56_ecb */ - { "des_56_cbc", 8, DESCBC, initDESkey, }, - { "des_56_ecb", 8, DESECB, initDESkey, }, - { "des_40_cbc", 8, DESCBC, initDESkey_40, }, - { "des_40_ecb", 8, DESECB, initDESkey_40, }, - { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */ - { "rc4_256", 1, RC4, initRC4key, }, - { "rc4_128", 1, RC4, initRC4key_128, }, - { "rc4_40", 1, RC4, initRC4key_40, }, - { 0 } -}; -#else -Encalg encrypttab[] = -{ - { "des_40_cbc", 8, DESCBC, initDESkey_40, }, - { "des_40_ecb", 8, DESECB, initDESkey_40, }, - { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */ - { "rc4_40", 1, RC4, initRC4key_40, }, - { 0 } -}; -#endif /* NOSPOOKS */ - -static int -parseencryptalg(char *p, Dstate *s) -{ - Encalg *ea; - - for(ea = encrypttab; ea->name; ea++){ - if(strcmp(p, ea->name) == 0){ - s->encryptalg = ea->alg; - s->blocklen = ea->blocklen; - (*ea->keyinit)(&s->in); - (*ea->keyinit)(&s->out); - s->state &= ~Sclear; - s->state |= Sencrypting; - return 0; - } - } - return -1; -} - -static long -sslwrite(Chan *c, void *a, long n, vlong o) -{ - Dstate * volatile s; - Block * volatile b; - int m, t; - char *p, *np, *e, buf[128]; - uchar *x; - - USED(o); - s = dstate[CONV(c->qid)]; - if(s == 0) - panic("sslwrite"); - - t = TYPE(c->qid); - if(t == Qdata){ - if(s->state == Sincomplete) - error(Ebadusefd); - - /* lock should a write gets split over multiple records */ - if(waserror()){ - qunlock(&s->out.q); - nexterror(); - } - qlock(&s->out.q); - p = a; -if(0) iprint("write %d %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux\n", - n, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); - e = p + n; - do { - m = e - p; - if(m > s->max) - m = s->max; - - b = allocb(m); - if(waserror()){ - freeb(b); - nexterror(); - } - memmove(b->wp, p, m); - poperror(); - b->wp += m; - - sslput(s, b); - - p += m; - } while(p < e); - p = a; -if(0) iprint("wrote %d %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux\n", - n, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); - poperror(); - qunlock(&s->out.q); - return n; - } - - /* mutex with operations using what we're about to change */ - if(waserror()){ - qunlock(&s->in.ctlq); - qunlock(&s->out.q); - nexterror(); - } - qlock(&s->in.ctlq); - qlock(&s->out.q); - - switch(t){ - default: - panic("sslwrite"); - case Qsecretin: - setsecret(&s->in, a, n); - goto out; - case Qsecretout: - setsecret(&s->out, a, n); - goto out; - case Qctl: - break; - } - - if(n >= sizeof(buf)) - error("arg too long"); - strncpy(buf, a, n); - buf[n] = 0; - p = strchr(buf, '\n'); - if(p) - *p = 0; - p = strchr(buf, ' '); - if(p) - *p++ = 0; - - if(strcmp(buf, "fd") == 0){ - s->c = buftochan(p); - - /* default is clear (msg delimiters only) */ - s->state = Sclear; - s->blocklen = 1; - s->diglen = 0; - s->maxpad = s->max = (1<<15) - s->diglen - 1; - s->in.mid = 0; - s->out.mid = 0; - } else if(strcmp(buf, "alg") == 0 && p != 0){ - s->blocklen = 1; - s->diglen = 0; - - if(s->c == 0) - error("must set fd before algorithm"); - - s->state = Sclear; - s->maxpad = s->max = (1<<15) - s->diglen - 1; - if(strcmp(p, "clear") == 0){ - goto out; - } - - if(s->in.secret && s->out.secret == 0) - setsecret(&s->out, s->in.secret, s->in.slen); - if(s->out.secret && s->in.secret == 0) - setsecret(&s->in, s->out.secret, s->out.slen); - if(s->in.secret == 0 || s->out.secret == 0) - error("algorithm but no secret"); - - s->hf = 0; - s->encryptalg = Noencryption; - s->blocklen = 1; - - for(;;){ - np = strchr(p, ' '); - if(np) - *np++ = 0; - - if(parsehashalg(p, s) < 0) - if(parseencryptalg(p, s) < 0) - error("bad algorithm"); - - if(np == 0) - break; - p = np; - } - - if(s->hf == 0 && s->encryptalg == Noencryption) - error("bad algorithm"); - - if(s->blocklen != 1){ - s->max = (1<<15) - s->diglen - 1; - s->max -= s->max % s->blocklen; - s->maxpad = (1<<14) - s->diglen - 1; - s->maxpad -= s->maxpad % s->blocklen; - } else - s->maxpad = s->max = (1<<15) - s->diglen - 1; - } else if(strcmp(buf, "secretin") == 0 && p != 0) { - m = (strlen(p)*3)/2; - x = smalloc(m); - t = dec64(x, m, p, strlen(p)); - setsecret(&s->in, x, t); - free(x); - } else if(strcmp(buf, "secretout") == 0 && p != 0) { - m = (strlen(p)*3)/2 + 1; - x = smalloc(m); - t = dec64(x, m, p, strlen(p)); - setsecret(&s->out, x, t); - free(x); - } else - error(Ebadarg); - -out: - qunlock(&s->in.ctlq); - qunlock(&s->out.q); - poperror(); - return n; -} - -static void -sslinit(void) -{ - struct Encalg *e; - struct Hashalg *h; - int n; - char *cp; - - n = 1; - for(e = encrypttab; e->name != nil; e++) - n += strlen(e->name) + 1; - cp = encalgs = smalloc(n); - for(e = encrypttab;;){ - strcpy(cp, e->name); - cp += strlen(e->name); - e++; - if(e->name == nil) - break; - *cp++ = ' '; - } - *cp = 0; - - n = 1; - for(h = hashtab; h->name != nil; h++) - n += strlen(h->name) + 1; - cp = hashalgs = smalloc(n); - for(h = hashtab;;){ - strcpy(cp, h->name); - cp += strlen(h->name); - h++; - if(h->name == nil) - break; - *cp++ = ' '; - } - *cp = 0; -} - -Dev ssldevtab = { - 'D', - "ssl", - - devreset, - sslinit, - devshutdown, - sslattach, - sslwalk, - sslstat, - sslopen, - devcreate, - sslclose, - sslread, - sslbread, - sslwrite, - sslbwrite, - devremove, - sslwstat, -}; - -static Block* -encryptb(Dstate *s, Block *b, int offset) -{ - uchar *p, *ep, *p2, *ip, *eip; - DESstate *ds; - - switch(s->encryptalg){ - case DESECB: - ds = s->out.state; - ep = b->rp + BLEN(b); - for(p = b->rp + offset; p < ep; p += 8) - block_cipher(ds->expanded, p, 0); - break; - case DESCBC: - ds = s->out.state; - ep = b->rp + BLEN(b); - for(p = b->rp + offset; p < ep; p += 8){ - p2 = p; - ip = ds->ivec; - for(eip = ip+8; ip < eip; ) - *p2++ ^= *ip++; - block_cipher(ds->expanded, p, 0); - memmove(ds->ivec, p, 8); - } - break; - case RC4: - rc4(s->out.state, b->rp + offset, BLEN(b) - offset); - break; - } - return b; -} - -static Block* -decryptb(Dstate *s, Block *bin) -{ - Block *b, **l; - uchar *p, *ep, *tp, *ip, *eip; - DESstate *ds; - uchar tmp[8]; - int i; - - l = &bin; - for(b = bin; b; b = b->next){ - /* make sure we have a multiple of s->blocklen */ - if(s->blocklen > 1){ - i = BLEN(b); - if(i % s->blocklen){ - *l = b = pullupblock(b, i + s->blocklen - (i%s->blocklen)); - if(b == 0) - error("ssl encrypted message too short"); - } - } - l = &b->next; - - /* decrypt */ - switch(s->encryptalg){ - case DESECB: - ds = s->in.state; - ep = b->rp + BLEN(b); - for(p = b->rp; p < ep; p += 8) - block_cipher(ds->expanded, p, 1); - break; - case DESCBC: - ds = s->in.state; - ep = b->rp + BLEN(b); - for(p = b->rp; p < ep;){ - memmove(tmp, p, 8); - block_cipher(ds->expanded, p, 1); - tp = tmp; - ip = ds->ivec; - for(eip = ip+8; ip < eip; ){ - *p++ ^= *ip; - *ip++ = *tp++; - } - } - break; - case RC4: - rc4(s->in.state, b->rp, BLEN(b)); - break; - } - } - return bin; -} - -static Block* -digestb(Dstate *s, Block *b, int offset) -{ - uchar *p; - DigestState ss; - uchar msgid[4]; - ulong n, h; - OneWay *w; - - w = &s->out; - - memset(&ss, 0, sizeof(ss)); - h = s->diglen + offset; - n = BLEN(b) - h; - - /* hash secret + message */ - (*s->hf)(w->secret, w->slen, 0, &ss); - (*s->hf)(b->rp + h, n, 0, &ss); - - /* hash message id */ - p = msgid; - n = w->mid; - *p++ = n>>24; - *p++ = n>>16; - *p++ = n>>8; - *p = n; - (*s->hf)(msgid, 4, b->rp + offset, &ss); - - return b; -} - -static void -checkdigestb(Dstate *s, Block *bin) -{ - uchar *p; - DigestState ss; - uchar msgid[4]; - int n, h; - OneWay *w; - uchar digest[128]; - Block *b; - - w = &s->in; - - memset(&ss, 0, sizeof(ss)); - - /* hash secret */ - (*s->hf)(w->secret, w->slen, 0, &ss); - - /* hash message */ - h = s->diglen; - for(b = bin; b; b = b->next){ - n = BLEN(b) - h; - if(n < 0) - panic("checkdigestb"); - (*s->hf)(b->rp + h, n, 0, &ss); - h = 0; - } - - /* hash message id */ - p = msgid; - n = w->mid; - *p++ = n>>24; - *p++ = n>>16; - *p++ = n>>8; - *p = n; - (*s->hf)(msgid, 4, digest, &ss); - - if(memcmp(digest, bin->rp, s->diglen) != 0) - error("bad digest"); -} - -/* get channel associated with an fd */ -static Chan* -buftochan(char *p) -{ - Chan *c; - int fd; - - if(p == 0) - error(Ebadarg); - fd = strtoul(p, 0, 0); - if(fd < 0) - error(Ebadarg); - c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ - if(devtab[c->type] == &ssldevtab){ - cclose(c); - error("cannot ssl encrypt devssl files"); - } - return c; -} - -/* hand up a digest connection */ -static void -sslhangup(Dstate *s) -{ - Block *b; - - qlock(&s->in.q); - for(b = s->processed; b; b = s->processed){ - s->processed = b->next; - freeb(b); - } - if(s->unprocessed){ - freeb(s->unprocessed); - s->unprocessed = 0; - } - s->state = Sincomplete; - qunlock(&s->in.q); -} - -static Dstate* -dsclone(Chan *ch) -{ - int i; - Dstate *ret; - - if(waserror()) { - unlock(&dslock); - nexterror(); - } - lock(&dslock); - ret = nil; - for(i=0; i<Maxdstate; i++){ - if(dstate[i] == nil){ - dsnew(ch, &dstate[i]); - ret = dstate[i]; - break; - } - } - unlock(&dslock); - poperror(); - return ret; -} - -static void -dsnew(Chan *ch, Dstate **pp) -{ - Dstate *s; - int t; - - *pp = s = malloc(sizeof(*s)); - if(!s) - error(Enomem); - if(pp - dstate >= dshiwat) - dshiwat++; - memset(s, 0, sizeof(*s)); - s->state = Sincomplete; - s->ref = 1; - kstrdup(&s->user, up->user); - s->perm = 0660; - t = TYPE(ch->qid); - if(t == Qclonus) - t = Qctl; - ch->qid.path = QID(pp - dstate, t); - ch->qid.vers = 0; -} diff --git a/sys/src/cmd/unix/drawterm/kern/devtab.c b/sys/src/cmd/unix/drawterm/kern/devtab.c deleted file mode 100644 index e16a188fd..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devtab.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -extern Dev consdevtab; -extern Dev rootdevtab; -extern Dev pipedevtab; -extern Dev ssldevtab; -extern Dev tlsdevtab; -extern Dev mousedevtab; -extern Dev drawdevtab; -extern Dev ipdevtab; -extern Dev fsdevtab; -extern Dev mntdevtab; -extern Dev lfddevtab; -extern Dev audiodevtab; - -Dev *devtab[] = { - &rootdevtab, - &consdevtab, - &pipedevtab, - &ssldevtab, - &tlsdevtab, - &mousedevtab, - &drawdevtab, - &ipdevtab, - &fsdevtab, - &mntdevtab, - &lfddevtab, - &audiodevtab, - 0 -}; - diff --git a/sys/src/cmd/unix/drawterm/kern/devtls.c b/sys/src/cmd/unix/drawterm/kern/devtls.c deleted file mode 100644 index 6f439a241..000000000 --- a/sys/src/cmd/unix/drawterm/kern/devtls.c +++ /dev/null @@ -1,2185 +0,0 @@ -/* - * devtls - record layer for transport layer security 1.0 and secure sockets layer 3.0 - */ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#include "libsec.h" - -typedef struct OneWay OneWay; -typedef struct Secret Secret; -typedef struct TlsRec TlsRec; -typedef struct TlsErrs TlsErrs; - -enum { - Statlen= 1024, /* max. length of status or stats message */ - /* buffer limits */ - MaxRecLen = 1<<14, /* max payload length of a record layer message */ - MaxCipherRecLen = MaxRecLen + 2048, - RecHdrLen = 5, - MaxMacLen = SHA1dlen, - - /* protocol versions we can accept */ - TLSVersion = 0x0301, - SSL3Version = 0x0300, - ProtocolVersion = 0x0301, /* maximum version we speak */ - MinProtoVersion = 0x0300, /* limits on version we accept */ - MaxProtoVersion = 0x03ff, - - /* connection states */ - SHandshake = 1 << 0, /* doing handshake */ - SOpen = 1 << 1, /* application data can be sent */ - SRClose = 1 << 2, /* remote side has closed down */ - SLClose = 1 << 3, /* sent a close notify alert */ - SAlert = 1 << 5, /* sending or sent a fatal alert */ - SError = 1 << 6, /* some sort of error has occured */ - SClosed = 1 << 7, /* it is all over */ - - /* record types */ - RChangeCipherSpec = 20, - RAlert, - RHandshake, - RApplication, - - SSL2ClientHello = 1, - HSSL2ClientHello = 9, /* local convention; see tlshand.c */ - - /* alerts */ - ECloseNotify = 0, - EUnexpectedMessage = 10, - EBadRecordMac = 20, - EDecryptionFailed = 21, - ERecordOverflow = 22, - EDecompressionFailure = 30, - EHandshakeFailure = 40, - ENoCertificate = 41, - EBadCertificate = 42, - EUnsupportedCertificate = 43, - ECertificateRevoked = 44, - ECertificateExpired = 45, - ECertificateUnknown = 46, - EIllegalParameter = 47, - EUnknownCa = 48, - EAccessDenied = 49, - EDecodeError = 50, - EDecryptError = 51, - EExportRestriction = 60, - EProtocolVersion = 70, - EInsufficientSecurity = 71, - EInternalError = 80, - EUserCanceled = 90, - ENoRenegotiation = 100, - - EMAX = 256 -}; - -struct Secret -{ - char *encalg; /* name of encryption alg */ - char *hashalg; /* name of hash alg */ - int (*enc)(Secret*, uchar*, int); - int (*dec)(Secret*, uchar*, int); - int (*unpad)(uchar*, int, int); - DigestState *(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*); - int block; /* encryption block len, 0 if none */ - int maclen; - void *enckey; - uchar mackey[MaxMacLen]; -}; - -struct OneWay -{ - QLock io; /* locks io access */ - QLock seclock; /* locks secret paramaters */ - ulong seq; - Secret *sec; /* cipher in use */ - Secret *new; /* cipher waiting for enable */ -}; - -struct TlsRec -{ - Chan *c; /* io channel */ - int ref; /* serialized by tdlock for atomic destroy */ - int version; /* version of the protocol we are speaking */ - char verset; /* version has been set */ - char opened; /* opened command every issued? */ - char err[ERRMAX]; /* error message to return to handshake requests */ - vlong handin; /* bytes communicated by the record layer */ - vlong handout; - vlong datain; - vlong dataout; - - Lock statelk; - int state; - int debug; - - /* record layer mac functions for different protocol versions */ - void (*packMac)(Secret*, uchar*, uchar*, uchar*, uchar*, int, uchar*); - - /* input side -- protected by in.io */ - OneWay in; - Block *processed; /* next bunch of application data */ - Block *unprocessed; /* data read from c but not parsed into records */ - - /* handshake queue */ - Lock hqlock; /* protects hqref, alloc & free of handq, hprocessed */ - int hqref; - Queue *handq; /* queue of handshake messages */ - Block *hprocessed; /* remainder of last block read from handq */ - QLock hqread; /* protects reads for hprocessed, handq */ - - /* output side */ - OneWay out; - - /* protections */ - char *user; - int perm; -}; - -struct TlsErrs{ - int err; - int sslerr; - int tlserr; - int fatal; - char *msg; -}; - -static TlsErrs tlserrs[] = { - {ECloseNotify, ECloseNotify, ECloseNotify, 0, "close notify"}, - {EUnexpectedMessage, EUnexpectedMessage, EUnexpectedMessage, 1, "unexpected message"}, - {EBadRecordMac, EBadRecordMac, EBadRecordMac, 1, "bad record mac"}, - {EDecryptionFailed, EIllegalParameter, EDecryptionFailed, 1, "decryption failed"}, - {ERecordOverflow, EIllegalParameter, ERecordOverflow, 1, "record too long"}, - {EDecompressionFailure, EDecompressionFailure, EDecompressionFailure, 1, "decompression failed"}, - {EHandshakeFailure, EHandshakeFailure, EHandshakeFailure, 1, "could not negotiate acceptable security parameters"}, - {ENoCertificate, ENoCertificate, ECertificateUnknown, 1, "no appropriate certificate available"}, - {EBadCertificate, EBadCertificate, EBadCertificate, 1, "corrupted or invalid certificate"}, - {EUnsupportedCertificate, EUnsupportedCertificate, EUnsupportedCertificate, 1, "unsupported certificate type"}, - {ECertificateRevoked, ECertificateRevoked, ECertificateRevoked, 1, "revoked certificate"}, - {ECertificateExpired, ECertificateExpired, ECertificateExpired, 1, "expired certificate"}, - {ECertificateUnknown, ECertificateUnknown, ECertificateUnknown, 1, "unacceptable certificate"}, - {EIllegalParameter, EIllegalParameter, EIllegalParameter, 1, "illegal parameter"}, - {EUnknownCa, EHandshakeFailure, EUnknownCa, 1, "unknown certificate authority"}, - {EAccessDenied, EHandshakeFailure, EAccessDenied, 1, "access denied"}, - {EDecodeError, EIllegalParameter, EDecodeError, 1, "error decoding message"}, - {EDecryptError, EIllegalParameter, EDecryptError, 1, "error decrypting message"}, - {EExportRestriction, EHandshakeFailure, EExportRestriction, 1, "export restriction violated"}, - {EProtocolVersion, EIllegalParameter, EProtocolVersion, 1, "protocol version not supported"}, - {EInsufficientSecurity, EHandshakeFailure, EInsufficientSecurity, 1, "stronger security routines required"}, - {EInternalError, EHandshakeFailure, EInternalError, 1, "internal error"}, - {EUserCanceled, ECloseNotify, EUserCanceled, 0, "handshake canceled by user"}, - {ENoRenegotiation, EUnexpectedMessage, ENoRenegotiation, 0, "no renegotiation"}, -}; - -enum -{ - /* max. open tls connections */ - MaxTlsDevs = 1024 -}; - -static Lock tdlock; -static int tdhiwat; -static int maxtlsdevs = 128; -static TlsRec **tlsdevs; -static char **trnames; -static char *encalgs; -static char *hashalgs; - -enum{ - Qtopdir = 1, /* top level directory */ - Qprotodir, - Qclonus, - Qencalgs, - Qhashalgs, - Qconvdir, /* directory for a conversation */ - Qdata, - Qctl, - Qhand, - Qstatus, - Qstats, -}; - -#define TYPE(x) ((x).path & 0xf) -#define CONV(x) (((x).path >> 5)&(MaxTlsDevs-1)) -#define QID(c, y) (((c)<<5) | (y)) - -static void checkstate(TlsRec *, int, int); -static void ensure(TlsRec*, Block**, int); -static void consume(Block**, uchar*, int); -static Chan* buftochan(char*); -static void tlshangup(TlsRec*); -static void tlsError(TlsRec*, char *); -static void alertHand(TlsRec*, char *); -static TlsRec *newtls(Chan *c); -static TlsRec *mktlsrec(void); -static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s); -static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s); -static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s); -static void sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac); -static void tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac); -static void put64(uchar *p, vlong x); -static void put32(uchar *p, u32int); -static void put24(uchar *p, int); -static void put16(uchar *p, int); -/* static u32int get32(uchar *p); */ -static int get16(uchar *p); -static void tlsSetState(TlsRec *tr, int new, int old); -static void rcvAlert(TlsRec *tr, int err); -static void sendAlert(TlsRec *tr, int err); -static void rcvError(TlsRec *tr, int err, char *msg, ...); -static int rc4enc(Secret *sec, uchar *buf, int n); -static int des3enc(Secret *sec, uchar *buf, int n); -static int des3dec(Secret *sec, uchar *buf, int n); -static int noenc(Secret *sec, uchar *buf, int n); -static int sslunpad(uchar *buf, int n, int block); -static int tlsunpad(uchar *buf, int n, int block); -static void freeSec(Secret *sec); -static char *tlsstate(int s); -static void pdump(int, void*, char*); - -static char *tlsnames[] = { - /* unused */ 0, - /* topdir */ 0, - /* protodir */ 0, - "clone", - "encalgs", - "hashalgs", - /* convdir */ 0, - "data", - "ctl", - "hand", - "status", - "stats", -}; - -static int convdir[] = { Qctl, Qdata, Qhand, Qstatus, Qstats }; - -static int -tlsgen(Chan *c, char*unused1, Dirtab *unused2, int unused3, int s, Dir *dp) -{ - Qid q; - TlsRec *tr; - char *name, *nm; - int perm, t; - - q.vers = 0; - q.type = QTFILE; - - t = TYPE(c->qid); - switch(t) { - case Qtopdir: - if(s == DEVDOTDOT){ - q.path = QID(0, Qtopdir); - q.type = QTDIR; - devdir(c, q, "#a", 0, eve, 0555, dp); - return 1; - } - if(s > 0) - return -1; - q.path = QID(0, Qprotodir); - q.type = QTDIR; - devdir(c, q, "tls", 0, eve, 0555, dp); - return 1; - case Qprotodir: - if(s == DEVDOTDOT){ - q.path = QID(0, Qtopdir); - q.type = QTDIR; - devdir(c, q, ".", 0, eve, 0555, dp); - return 1; - } - if(s < 3){ - switch(s) { - default: - return -1; - case 0: - q.path = QID(0, Qclonus); - break; - case 1: - q.path = QID(0, Qencalgs); - break; - case 2: - q.path = QID(0, Qhashalgs); - break; - } - perm = 0444; - if(TYPE(q) == Qclonus) - perm = 0555; - devdir(c, q, tlsnames[TYPE(q)], 0, eve, perm, dp); - return 1; - } - s -= 3; - if(s >= tdhiwat) - return -1; - q.path = QID(s, Qconvdir); - q.type = QTDIR; - lock(&tdlock); - tr = tlsdevs[s]; - if(tr != nil) - nm = tr->user; - else - nm = eve; - if((name = trnames[s]) == nil){ - name = trnames[s] = smalloc(16); - sprint(name, "%d", s); - } - devdir(c, q, name, 0, nm, 0555, dp); - unlock(&tdlock); - return 1; - case Qconvdir: - if(s == DEVDOTDOT){ - q.path = QID(0, Qprotodir); - q.type = QTDIR; - devdir(c, q, "tls", 0, eve, 0555, dp); - return 1; - } - if(s < 0 || s >= nelem(convdir)) - return -1; - lock(&tdlock); - tr = tlsdevs[CONV(c->qid)]; - if(tr != nil){ - nm = tr->user; - perm = tr->perm; - }else{ - perm = 0; - nm = eve; - } - t = convdir[s]; - if(t == Qstatus || t == Qstats) - perm &= 0444; - q.path = QID(CONV(c->qid), t); - devdir(c, q, tlsnames[t], 0, nm, perm, dp); - unlock(&tdlock); - return 1; - case Qclonus: - case Qencalgs: - case Qhashalgs: - perm = 0444; - if(t == Qclonus) - perm = 0555; - devdir(c, c->qid, tlsnames[t], 0, eve, perm, dp); - return 1; - default: - lock(&tdlock); - tr = tlsdevs[CONV(c->qid)]; - if(tr != nil){ - nm = tr->user; - perm = tr->perm; - }else{ - perm = 0; - nm = eve; - } - if(t == Qstatus || t == Qstats) - perm &= 0444; - devdir(c, c->qid, tlsnames[t], 0, nm, perm, dp); - unlock(&tdlock); - return 1; - } - return -1; -} - -static Chan* -tlsattach(char *spec) -{ - Chan *c; - - c = devattach('a', spec); - c->qid.path = QID(0, Qtopdir); - c->qid.type = QTDIR; - c->qid.vers = 0; - return c; -} - -static Walkqid* -tlswalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, nil, 0, tlsgen); -} - -static int -tlsstat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, nil, 0, tlsgen); -} - -static Chan* -tlsopen(Chan *c, int omode) -{ - TlsRec *tr, **pp; - int t, perm; - - perm = 0; - omode &= 3; - switch(omode) { - case OREAD: - perm = 4; - break; - case OWRITE: - perm = 2; - break; - case ORDWR: - perm = 6; - break; - } - - t = TYPE(c->qid); - switch(t) { - default: - panic("tlsopen"); - case Qtopdir: - case Qprotodir: - case Qconvdir: - if(omode != OREAD) - error(Eperm); - break; - case Qclonus: - tr = newtls(c); - if(tr == nil) - error(Enodev); - break; - case Qctl: - case Qdata: - case Qhand: - case Qstatus: - case Qstats: - if((t == Qstatus || t == Qstats) && omode != OREAD) - error(Eperm); - if(waserror()) { - unlock(&tdlock); - nexterror(); - } - lock(&tdlock); - pp = &tlsdevs[CONV(c->qid)]; - tr = *pp; - if(tr == nil) - error("must open connection using clone"); - if((perm & (tr->perm>>6)) != perm - && (strcmp(up->user, tr->user) != 0 - || (perm & tr->perm) != perm)) - error(Eperm); - if(t == Qhand){ - if(waserror()){ - unlock(&tr->hqlock); - nexterror(); - } - lock(&tr->hqlock); - if(tr->handq != nil) - error(Einuse); - tr->handq = qopen(2 * MaxCipherRecLen, 0, 0, nil); - if(tr->handq == nil) - error("cannot allocate handshake queue"); - tr->hqref = 1; - unlock(&tr->hqlock); - poperror(); - } - tr->ref++; - unlock(&tdlock); - poperror(); - break; - case Qencalgs: - case Qhashalgs: - if(omode != OREAD) - error(Eperm); - break; - } - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - c->iounit = qiomaxatomic; - return c; -} - -static int -tlswstat(Chan *c, uchar *dp, int n) -{ - Dir *d; - TlsRec *tr; - int rv; - - d = nil; - if(waserror()){ - free(d); - unlock(&tdlock); - nexterror(); - } - - lock(&tdlock); - tr = tlsdevs[CONV(c->qid)]; - if(tr == nil) - error(Ebadusefd); - if(strcmp(tr->user, up->user) != 0) - error(Eperm); - - d = smalloc(n + sizeof *d); - rv = convM2D(dp, n, &d[0], (char*) &d[1]); - if(rv == 0) - error(Eshortstat); - if(!emptystr(d->uid)) - kstrdup(&tr->user, d->uid); - if(d->mode != ~0UL) - tr->perm = d->mode; - - free(d); - poperror(); - unlock(&tdlock); - - return rv; -} - -static void -dechandq(TlsRec *tr) -{ - lock(&tr->hqlock); - if(--tr->hqref == 0){ - if(tr->handq != nil){ - qfree(tr->handq); - tr->handq = nil; - } - if(tr->hprocessed != nil){ - freeb(tr->hprocessed); - tr->hprocessed = nil; - } - } - unlock(&tr->hqlock); -} - -static void -tlsclose(Chan *c) -{ - TlsRec *tr; - int t; - - t = TYPE(c->qid); - switch(t) { - case Qctl: - case Qdata: - case Qhand: - case Qstatus: - case Qstats: - if((c->flag & COPEN) == 0) - break; - - tr = tlsdevs[CONV(c->qid)]; - if(tr == nil) - break; - - if(t == Qhand) - dechandq(tr); - - lock(&tdlock); - if(--tr->ref > 0) { - unlock(&tdlock); - return; - } - tlsdevs[CONV(c->qid)] = nil; - unlock(&tdlock); - - if(tr->c != nil && !waserror()){ - checkstate(tr, 0, SOpen|SHandshake|SRClose); - sendAlert(tr, ECloseNotify); - poperror(); - } - tlshangup(tr); - if(tr->c != nil) - cclose(tr->c); - freeSec(tr->in.sec); - freeSec(tr->in.new); - freeSec(tr->out.sec); - freeSec(tr->out.new); - free(tr->user); - free(tr); - break; - } -} - -/* - * make sure we have at least 'n' bytes in list 'l' - */ -static void -ensure(TlsRec *s, Block **l, int n) -{ - int sofar, i; - Block *b, *bl; - - sofar = 0; - for(b = *l; b; b = b->next){ - sofar += BLEN(b); - if(sofar >= n) - return; - l = &b->next; - } - - while(sofar < n){ - bl = devtab[s->c->type]->bread(s->c, MaxCipherRecLen + RecHdrLen, 0); - if(bl == 0) - error(Ehungup); - *l = bl; - i = 0; - for(b = bl; b; b = b->next){ - i += BLEN(b); - l = &b->next; - } - if(i == 0) - error(Ehungup); - sofar += i; - } -if(s->debug) pprint("ensure read %d\n", sofar); -} - -/* - * copy 'n' bytes from 'l' into 'p' and free - * the bytes in 'l' - */ -static void -consume(Block **l, uchar *p, int n) -{ - Block *b; - int i; - - for(; *l && n > 0; n -= i){ - b = *l; - i = BLEN(b); - if(i > n) - i = n; - memmove(p, b->rp, i); - b->rp += i; - p += i; - if(BLEN(b) < 0) - panic("consume"); - if(BLEN(b)) - break; - *l = b->next; - freeb(b); - } -} - -/* - * give back n bytes - */ -static void -regurgitate(TlsRec *s, uchar *p, int n) -{ - Block *b; - - if(n <= 0) - return; - b = s->unprocessed; - if(s->unprocessed == nil || b->rp - b->base < n) { - b = allocb(n); - memmove(b->wp, p, n); - b->wp += n; - b->next = s->unprocessed; - s->unprocessed = b; - } else { - b->rp -= n; - memmove(b->rp, p, n); - } -} - -/* - * remove at most n bytes from the queue - */ -static Block* -qgrab(Block **l, int n) -{ - Block *bb, *b; - int i; - - b = *l; - if(BLEN(b) == n){ - *l = b->next; - b->next = nil; - return b; - } - - i = 0; - for(bb = b; bb != nil && i < n; bb = bb->next) - i += BLEN(bb); - if(i > n) - i = n; - - bb = allocb(i); - consume(l, bb->wp, i); - bb->wp += i; - return bb; -} - -static void -tlsclosed(TlsRec *tr, int new) -{ - lock(&tr->statelk); - if(tr->state == SOpen || tr->state == SHandshake) - tr->state = new; - else if((new | tr->state) == (SRClose|SLClose)) - tr->state = SClosed; - unlock(&tr->statelk); - alertHand(tr, "close notify"); -} - -/* - * read and process one tls record layer message - * must be called with tr->in.io held - * We can't let Eintrs lose data, since doing so will get - * us out of sync with the sender and break the reliablity - * of the channel. Eintr only happens during the reads in - * consume. Therefore we put back any bytes consumed before - * the last call to ensure. - */ -static void -tlsrecread(TlsRec *tr) -{ - OneWay *volatile in; - Block *volatile b; - uchar *p, seq[8], header[RecHdrLen], hmac[MD5dlen]; - int volatile nconsumed; - int len, type, ver, unpad_len; - - nconsumed = 0; - if(waserror()){ - if(strcmp(up->errstr, Eintr) == 0 && !waserror()){ - regurgitate(tr, header, nconsumed); - poperror(); - }else - tlsError(tr, "channel error"); - nexterror(); - } - ensure(tr, &tr->unprocessed, RecHdrLen); - consume(&tr->unprocessed, header, RecHdrLen); -if(tr->debug)pprint("consumed %d header\n", RecHdrLen); - nconsumed = RecHdrLen; - - if((tr->handin == 0) && (header[0] & 0x80)){ - /* Cope with an SSL3 ClientHello expressed in SSL2 record format. - This is sent by some clients that we must interoperate - with, such as Java's JSSE and Microsoft's Internet Explorer. */ - len = (get16(header) & ~0x8000) - 3; - type = header[2]; - ver = get16(header + 3); - if(type != SSL2ClientHello || len < 22) - rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message"); - }else{ /* normal SSL3 record format */ - type = header[0]; - ver = get16(header+1); - len = get16(header+3); - } - if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion)) - rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'", - tr->version, tr->verset?"/set":"", len, type, ver, (char*)header); - if(len > MaxCipherRecLen || len < 0) - rcvError(tr, ERecordOverflow, "record message too long %d", len); - ensure(tr, &tr->unprocessed, len); - nconsumed = 0; - poperror(); - - /* - * If an Eintr happens after this, we'll get out of sync. - * Make sure nothing we call can sleep. - * Errors are ok, as they kill the connection. - * Luckily, allocb won't sleep, it'll just error out. - */ - b = nil; - if(waserror()){ - if(b != nil) - freeb(b); - tlsError(tr, "channel error"); - nexterror(); - } - b = qgrab(&tr->unprocessed, len); -if(tr->debug) pprint("consumed unprocessed %d\n", len); - - in = &tr->in; - if(waserror()){ - qunlock(&in->seclock); - nexterror(); - } - qlock(&in->seclock); - p = b->rp; - if(in->sec != nil) { - /* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here - should look alike, including timing of the response. */ - unpad_len = (*in->sec->dec)(in->sec, p, len); - if(unpad_len >= in->sec->maclen) - len = unpad_len - in->sec->maclen; -if(tr->debug) pprint("decrypted %d\n", unpad_len); -if(tr->debug) pdump(unpad_len, p, "decrypted:"); - - /* update length */ - put16(header+3, len); - put64(seq, in->seq); - in->seq++; - (*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac); - if(unpad_len < in->sec->maclen) - rcvError(tr, EBadRecordMac, "short record mac"); - if(memcmp(hmac, p+len, in->sec->maclen) != 0) - rcvError(tr, EBadRecordMac, "record mac mismatch"); - b->wp = b->rp + len; - } - qunlock(&in->seclock); - poperror(); - if(len < 0) - rcvError(tr, EDecodeError, "runt record message"); - - switch(type) { - default: - rcvError(tr, EIllegalParameter, "invalid record message 0x%x", type); - break; - case RChangeCipherSpec: - if(len != 1 || p[0] != 1) - rcvError(tr, EDecodeError, "invalid change cipher spec"); - qlock(&in->seclock); - if(in->new == nil){ - qunlock(&in->seclock); - rcvError(tr, EUnexpectedMessage, "unexpected change cipher spec"); - } - freeSec(in->sec); - in->sec = in->new; - in->new = nil; - in->seq = 0; - qunlock(&in->seclock); - break; - case RAlert: - if(len != 2) - rcvError(tr, EDecodeError, "invalid alert"); - if(p[0] == 2) - rcvAlert(tr, p[1]); - if(p[0] != 1) - rcvError(tr, EIllegalParameter, "invalid alert fatal code"); - - /* - * propate non-fatal alerts to handshaker - */ - if(p[1] == ECloseNotify) { - tlsclosed(tr, SRClose); - if(tr->opened) - error("tls hungup"); - error("close notify"); - } - if(p[1] == ENoRenegotiation) - alertHand(tr, "no renegotiation"); - else if(p[1] == EUserCanceled) - alertHand(tr, "handshake canceled by user"); - else - rcvError(tr, EIllegalParameter, "invalid alert code"); - break; - case RHandshake: - /* - * don't worry about dropping the block - * qbwrite always queues even if flow controlled and interrupted. - * - * if there isn't any handshaker, ignore the request, - * but notify the other side we are doing so. - */ - lock(&tr->hqlock); - if(tr->handq != nil){ - tr->hqref++; - unlock(&tr->hqlock); - if(waserror()){ - dechandq(tr); - nexterror(); - } - b = padblock(b, 1); - *b->rp = RHandshake; - qbwrite(tr->handq, b); - b = nil; - poperror(); - dechandq(tr); - }else{ - unlock(&tr->hqlock); - if(tr->verset && tr->version != SSL3Version && !waserror()){ - sendAlert(tr, ENoRenegotiation); - poperror(); - } - } - break; - case SSL2ClientHello: - lock(&tr->hqlock); - if(tr->handq != nil){ - tr->hqref++; - unlock(&tr->hqlock); - if(waserror()){ - dechandq(tr); - nexterror(); - } - /* Pass the SSL2 format data, so that the handshake code can compute - the correct checksums. HSSL2ClientHello = HandshakeType 9 is - unused in RFC2246. */ - b = padblock(b, 8); - b->rp[0] = RHandshake; - b->rp[1] = HSSL2ClientHello; - put24(&b->rp[2], len+3); - b->rp[5] = SSL2ClientHello; - put16(&b->rp[6], ver); - qbwrite(tr->handq, b); - b = nil; - poperror(); - dechandq(tr); - }else{ - unlock(&tr->hqlock); - if(tr->verset && tr->version != SSL3Version && !waserror()){ - sendAlert(tr, ENoRenegotiation); - poperror(); - } - } - break; - case RApplication: - if(!tr->opened) - rcvError(tr, EUnexpectedMessage, "application message received before handshake completed"); - if(BLEN(b) > 0){ - tr->processed = b; - b = nil; - } - break; - } - if(b != nil) - freeb(b); - poperror(); -} - -/* - * got a fatal alert message - */ -static void -rcvAlert(TlsRec *tr, int err) -{ - char *s; - int i; - - s = "unknown error"; - for(i=0; i < nelem(tlserrs); i++){ - if(tlserrs[i].err == err){ - s = tlserrs[i].msg; - break; - } - } -if(tr->debug) pprint("rcvAlert: %s\n", s); - - tlsError(tr, s); - if(!tr->opened) - error(s); - error("tls error"); -} - -/* - * found an error while decoding the input stream - */ -static void -rcvError(TlsRec *tr, int err, char *fmt, ...) -{ - char msg[ERRMAX]; - va_list arg; - - va_start(arg, fmt); - vseprint(msg, msg+sizeof(msg), fmt, arg); - va_end(arg); -if(tr->debug) pprint("rcvError: %s\n", msg); - - sendAlert(tr, err); - - if(!tr->opened) - error(msg); - error("tls error"); -} - -/* - * make sure the next hand operation returns with a 'msg' error - */ -static void -alertHand(TlsRec *tr, char *msg) -{ - Block *b; - int n; - - lock(&tr->hqlock); - if(tr->handq == nil){ - unlock(&tr->hqlock); - return; - } - tr->hqref++; - unlock(&tr->hqlock); - - n = strlen(msg); - if(waserror()){ - dechandq(tr); - nexterror(); - } - b = allocb(n + 2); - *b->wp++ = RAlert; - memmove(b->wp, msg, n + 1); - b->wp += n + 1; - - qbwrite(tr->handq, b); - - poperror(); - dechandq(tr); -} - -static void -checkstate(TlsRec *tr, int ishand, int ok) -{ - int state; - - lock(&tr->statelk); - state = tr->state; - unlock(&tr->statelk); - if(state & ok) - return; - switch(state){ - case SHandshake: - case SOpen: - break; - case SError: - case SAlert: - if(ishand) - error(tr->err); - error("tls error"); - case SRClose: - case SLClose: - case SClosed: - error("tls hungup"); - } - error("tls improperly configured"); -} - -static Block* -tlsbread(Chan *c, long n, ulong offset) -{ - int ty; - Block *b; - TlsRec *volatile tr; - - ty = TYPE(c->qid); - switch(ty) { - default: - return devbread(c, n, offset); - case Qhand: - case Qdata: - break; - } - - tr = tlsdevs[CONV(c->qid)]; - if(tr == nil) - panic("tlsbread"); - - if(waserror()){ - qunlock(&tr->in.io); - nexterror(); - } - qlock(&tr->in.io); - if(ty == Qdata){ - checkstate(tr, 0, SOpen); - while(tr->processed == nil) - tlsrecread(tr); - - /* return at most what was asked for */ - b = qgrab(&tr->processed, n); -if(tr->debug) pprint("consumed processed %d\n", BLEN(b)); -if(tr->debug) pdump(BLEN(b), b->rp, "consumed:"); - qunlock(&tr->in.io); - poperror(); - tr->datain += BLEN(b); - }else{ - checkstate(tr, 1, SOpen|SHandshake|SLClose); - - /* - * it's ok to look at state without the lock - * since it only protects reading records, - * and we have that tr->in.io held. - */ - while(!tr->opened && tr->hprocessed == nil && !qcanread(tr->handq)) - tlsrecread(tr); - - qunlock(&tr->in.io); - poperror(); - - if(waserror()){ - qunlock(&tr->hqread); - nexterror(); - } - qlock(&tr->hqread); - if(tr->hprocessed == nil){ - b = qbread(tr->handq, MaxRecLen + 1); - if(*b->rp++ == RAlert){ - kstrcpy(up->errstr, (char*)b->rp, ERRMAX); - freeb(b); - nexterror(); - } - tr->hprocessed = b; - } - b = qgrab(&tr->hprocessed, n); - poperror(); - qunlock(&tr->hqread); - tr->handin += BLEN(b); - } - - return b; -} - -static long -tlsread(Chan *c, void *a, long n, vlong off) -{ - Block *volatile b; - Block *nb; - uchar *va; - int i, ty; - char *buf, *s, *e; - ulong offset = off; - TlsRec * tr; - - if(c->qid.type & QTDIR) - return devdirread(c, a, n, 0, 0, tlsgen); - - tr = tlsdevs[CONV(c->qid)]; - ty = TYPE(c->qid); - switch(ty) { - default: - error(Ebadusefd); - case Qstatus: - buf = smalloc(Statlen); - qlock(&tr->in.seclock); - qlock(&tr->out.seclock); - s = buf; - e = buf + Statlen; - s = seprint(s, e, "State: %s\n", tlsstate(tr->state)); - s = seprint(s, e, "Version: 0x%x\n", tr->version); - if(tr->in.sec != nil) - s = seprint(s, e, "EncIn: %s\nHashIn: %s\n", tr->in.sec->encalg, tr->in.sec->hashalg); - if(tr->in.new != nil) - s = seprint(s, e, "NewEncIn: %s\nNewHashIn: %s\n", tr->in.new->encalg, tr->in.new->hashalg); - if(tr->out.sec != nil) - s = seprint(s, e, "EncOut: %s\nHashOut: %s\n", tr->out.sec->encalg, tr->out.sec->hashalg); - if(tr->out.new != nil) - seprint(s, e, "NewEncOut: %s\nNewHashOut: %s\n", tr->out.new->encalg, tr->out.new->hashalg); - qunlock(&tr->in.seclock); - qunlock(&tr->out.seclock); - n = readstr(offset, a, n, buf); - free(buf); - return n; - case Qstats: - buf = smalloc(Statlen); - s = buf; - e = buf + Statlen; - s = seprint(s, e, "DataIn: %lld\n", tr->datain); - s = seprint(s, e, "DataOut: %lld\n", tr->dataout); - s = seprint(s, e, "HandIn: %lld\n", tr->handin); - seprint(s, e, "HandOut: %lld\n", tr->handout); - n = readstr(offset, a, n, buf); - free(buf); - return n; - case Qctl: - buf = smalloc(Statlen); - snprint(buf, Statlen, "%llud", CONV(c->qid)); - n = readstr(offset, a, n, buf); - free(buf); - return n; - case Qdata: - case Qhand: - b = tlsbread(c, n, offset); - break; - case Qencalgs: - return readstr(offset, a, n, encalgs); - case Qhashalgs: - return readstr(offset, a, n, hashalgs); - } - - if(waserror()){ - freeblist(b); - nexterror(); - } - - n = 0; - va = a; - for(nb = b; nb; nb = nb->next){ - i = BLEN(nb); - memmove(va+n, nb->rp, i); - n += i; - } - - freeblist(b); - poperror(); - - return n; -} - -/* - * write a block in tls records - */ -static void -tlsrecwrite(TlsRec *tr, int type, Block *b) -{ - Block *volatile bb; - Block *nb; - uchar *p, seq[8]; - OneWay *volatile out; - int n, maclen, pad, ok; - - out = &tr->out; - bb = b; - if(waserror()){ - qunlock(&out->io); - if(bb != nil) - freeb(bb); - nexterror(); - } - qlock(&out->io); -if(tr->debug)pprint("send %d\n", BLEN(b)); -if(tr->debug)pdump(BLEN(b), b->rp, "sent:"); - - - ok = SHandshake|SOpen|SRClose; - if(type == RAlert) - ok |= SAlert; - while(bb != nil){ - checkstate(tr, type != RApplication, ok); - - /* - * get at most one maximal record's input, - * with padding on the front for header and - * back for mac and maximal block padding. - */ - if(waserror()){ - qunlock(&out->seclock); - nexterror(); - } - qlock(&out->seclock); - maclen = 0; - pad = 0; - if(out->sec != nil){ - maclen = out->sec->maclen; - pad = maclen + out->sec->block; - } - n = BLEN(bb); - if(n > MaxRecLen){ - n = MaxRecLen; - nb = allocb(n + pad + RecHdrLen); - memmove(nb->wp + RecHdrLen, bb->rp, n); - bb->rp += n; - }else{ - /* - * carefully reuse bb so it will get freed if we're out of memory - */ - bb = padblock(bb, RecHdrLen); - if(pad) - nb = padblock(bb, -pad); - else - nb = bb; - bb = nil; - } - - p = nb->rp; - p[0] = type; - put16(p+1, tr->version); - put16(p+3, n); - - if(out->sec != nil){ - put64(seq, out->seq); - out->seq++; - (*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n); - n += maclen; - - /* encrypt */ - n = (*out->sec->enc)(out->sec, p + RecHdrLen, n); - nb->wp = p + RecHdrLen + n; - - /* update length */ - put16(p+3, n); - } - if(type == RChangeCipherSpec){ - if(out->new == nil) - error("change cipher without a new cipher"); - freeSec(out->sec); - out->sec = out->new; - out->new = nil; - out->seq = 0; - } - qunlock(&out->seclock); - poperror(); - - /* - * if bwrite error's, we assume the block is queued. - * if not, we're out of sync with the receiver and will not recover. - */ - if(waserror()){ - if(strcmp(up->errstr, "interrupted") != 0) - tlsError(tr, "channel error"); - nexterror(); - } - devtab[tr->c->type]->bwrite(tr->c, nb, 0); - poperror(); - } - qunlock(&out->io); - poperror(); -} - -static long -tlsbwrite(Chan *c, Block *b, ulong offset) -{ - int ty; - ulong n; - TlsRec *tr; - - n = BLEN(b); - - tr = tlsdevs[CONV(c->qid)]; - if(tr == nil) - panic("tlsbread"); - - ty = TYPE(c->qid); - switch(ty) { - default: - return devbwrite(c, b, offset); - case Qhand: - tlsrecwrite(tr, RHandshake, b); - tr->handout += n; - break; - case Qdata: - checkstate(tr, 0, SOpen); - tlsrecwrite(tr, RApplication, b); - tr->dataout += n; - break; - } - - return n; -} - -typedef struct Hashalg Hashalg; -struct Hashalg -{ - char *name; - int maclen; - void (*initkey)(Hashalg *, int, Secret *, uchar*); -}; - -static void -initmd5key(Hashalg *ha, int version, Secret *s, uchar *p) -{ - s->maclen = ha->maclen; - if(version == SSL3Version) - s->mac = sslmac_md5; - else - s->mac = hmac_md5; - memmove(s->mackey, p, ha->maclen); -} - -static void -initclearmac(Hashalg *unused1, int unused2, Secret *s, uchar *unused3) -{ - s->maclen = 0; - s->mac = nomac; -} - -static void -initsha1key(Hashalg *ha, int version, Secret *s, uchar *p) -{ - s->maclen = ha->maclen; - if(version == SSL3Version) - s->mac = sslmac_sha1; - else - s->mac = hmac_sha1; - memmove(s->mackey, p, ha->maclen); -} - -static Hashalg hashtab[] = -{ - { "clear", 0, initclearmac, }, - { "md5", MD5dlen, initmd5key, }, - { "sha1", SHA1dlen, initsha1key, }, - { 0 } -}; - -static Hashalg* -parsehashalg(char *p) -{ - Hashalg *ha; - - for(ha = hashtab; ha->name; ha++) - if(strcmp(p, ha->name) == 0) - return ha; - error("unsupported hash algorithm"); - return nil; -} - -typedef struct Encalg Encalg; -struct Encalg -{ - char *name; - int keylen; - int ivlen; - void (*initkey)(Encalg *ea, Secret *, uchar*, uchar*); -}; - -static void -initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *unused1) -{ - s->enckey = smalloc(sizeof(RC4state)); - s->enc = rc4enc; - s->dec = rc4enc; - s->block = 0; - setupRC4state(s->enckey, p, ea->keylen); -} - -static void -initDES3key(Encalg *unused1, Secret *s, uchar *p, uchar *iv) -{ - s->enckey = smalloc(sizeof(DES3state)); - s->enc = des3enc; - s->dec = des3dec; - s->block = 8; - setupDES3state(s->enckey, (uchar(*)[8])p, iv); -} - -static void -initclearenc(Encalg *unused1, Secret *s, uchar *unused2, uchar *unused3) -{ - s->enc = noenc; - s->dec = noenc; - s->block = 0; -} - -static Encalg encrypttab[] = -{ - { "clear", 0, 0, initclearenc }, - { "rc4_128", 128/8, 0, initRC4key }, - { "3des_ede_cbc", 3 * 8, 8, initDES3key }, - { 0 } -}; - -static Encalg* -parseencalg(char *p) -{ - Encalg *ea; - - for(ea = encrypttab; ea->name; ea++) - if(strcmp(p, ea->name) == 0) - return ea; - error("unsupported encryption algorithm"); - return nil; -} - -static long -tlswrite(Chan *c, void *a, long n, vlong off) -{ - Encalg *ea; - Hashalg *ha; - TlsRec *volatile tr; - Secret *volatile tos, *volatile toc; - Block *volatile b; - Cmdbuf *volatile cb; - int m, ty; - char *p, *e; - uchar *volatile x; - ulong offset = off; - - tr = tlsdevs[CONV(c->qid)]; - if(tr == nil) - panic("tlswrite"); - - ty = TYPE(c->qid); - switch(ty){ - case Qdata: - case Qhand: - p = a; - e = p + n; - do{ - m = e - p; - if(m > MaxRecLen) - m = MaxRecLen; - - b = allocb(m); - if(waserror()){ - freeb(b); - nexterror(); - } - memmove(b->wp, p, m); - poperror(); - b->wp += m; - - tlsbwrite(c, b, offset); - - p += m; - }while(p < e); - return n; - case Qctl: - break; - default: - error(Ebadusefd); - return -1; - } - - cb = parsecmd(a, n); - if(waserror()){ - free(cb); - nexterror(); - } - if(cb->nf < 1) - error("short control request"); - - /* mutex with operations using what we're about to change */ - if(waserror()){ - qunlock(&tr->in.seclock); - qunlock(&tr->out.seclock); - nexterror(); - } - qlock(&tr->in.seclock); - qlock(&tr->out.seclock); - - if(strcmp(cb->f[0], "fd") == 0){ - if(cb->nf != 3) - error("usage: fd open-fd version"); - if(tr->c != nil) - error(Einuse); - m = strtol(cb->f[2], nil, 0); - if(m < MinProtoVersion || m > MaxProtoVersion) - error("unsupported version"); - tr->c = buftochan(cb->f[1]); - tr->version = m; - tlsSetState(tr, SHandshake, SClosed); - }else if(strcmp(cb->f[0], "version") == 0){ - if(cb->nf != 2) - error("usage: version vers"); - if(tr->c == nil) - error("must set fd before version"); - if(tr->verset) - error("version already set"); - m = strtol(cb->f[1], nil, 0); - if(m == SSL3Version) - tr->packMac = sslPackMac; - else if(m == TLSVersion) - tr->packMac = tlsPackMac; - else - error("unsupported version"); - tr->verset = 1; - tr->version = m; - }else if(strcmp(cb->f[0], "secret") == 0){ - if(cb->nf != 5) - error("usage: secret hashalg encalg isclient secretdata"); - if(tr->c == nil || !tr->verset) - error("must set fd and version before secrets"); - - if(tr->in.new != nil){ - freeSec(tr->in.new); - tr->in.new = nil; - } - if(tr->out.new != nil){ - freeSec(tr->out.new); - tr->out.new = nil; - } - - ha = parsehashalg(cb->f[1]); - ea = parseencalg(cb->f[2]); - - p = cb->f[4]; - m = (strlen(p)*3)/2; - x = smalloc(m); - tos = nil; - toc = nil; - if(waserror()){ - freeSec(tos); - freeSec(toc); - free(x); - nexterror(); - } - m = dec64(x, m, p, strlen(p)); - if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen) - error("not enough secret data provided"); - - tos = smalloc(sizeof(Secret)); - toc = smalloc(sizeof(Secret)); - if(!ha->initkey || !ea->initkey) - error("misimplemented secret algorithm"); - (*ha->initkey)(ha, tr->version, tos, &x[0]); - (*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]); - (*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]); - (*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]); - - if(!tos->mac || !tos->enc || !tos->dec - || !toc->mac || !toc->enc || !toc->dec) - error("missing algorithm implementations"); - if(strtol(cb->f[3], nil, 0) == 0){ - tr->in.new = tos; - tr->out.new = toc; - }else{ - tr->in.new = toc; - tr->out.new = tos; - } - if(tr->version == SSL3Version){ - toc->unpad = sslunpad; - tos->unpad = sslunpad; - }else{ - toc->unpad = tlsunpad; - tos->unpad = tlsunpad; - } - toc->encalg = ea->name; - toc->hashalg = ha->name; - tos->encalg = ea->name; - tos->hashalg = ha->name; - - free(x); - poperror(); - }else if(strcmp(cb->f[0], "changecipher") == 0){ - if(cb->nf != 1) - error("usage: changecipher"); - if(tr->out.new == nil) - error("cannot change cipher spec without setting secret"); - - qunlock(&tr->in.seclock); - qunlock(&tr->out.seclock); - poperror(); - free(cb); - poperror(); - - /* - * the real work is done as the message is written - * so the stream is encrypted in sync. - */ - b = allocb(1); - *b->wp++ = 1; - tlsrecwrite(tr, RChangeCipherSpec, b); - return n; - }else if(strcmp(cb->f[0], "opened") == 0){ - if(cb->nf != 1) - error("usage: opened"); - if(tr->in.sec == nil || tr->out.sec == nil) - error("cipher must be configured before enabling data messages"); - lock(&tr->statelk); - if(tr->state != SHandshake && tr->state != SOpen){ - unlock(&tr->statelk); - error("cannot enable data messages"); - } - tr->state = SOpen; - unlock(&tr->statelk); - tr->opened = 1; - }else if(strcmp(cb->f[0], "alert") == 0){ - if(cb->nf != 2) - error("usage: alert n"); - if(tr->c == nil) - error("must set fd before sending alerts"); - m = strtol(cb->f[1], nil, 0); - - qunlock(&tr->in.seclock); - qunlock(&tr->out.seclock); - poperror(); - free(cb); - poperror(); - - sendAlert(tr, m); - - if(m == ECloseNotify) - tlsclosed(tr, SLClose); - - return n; - } else if(strcmp(cb->f[0], "debug") == 0){ - if(cb->nf == 2){ - if(strcmp(cb->f[1], "on") == 0) - tr->debug = 1; - else - tr->debug = 0; - } else - tr->debug = 1; - } else - error(Ebadarg); - - qunlock(&tr->in.seclock); - qunlock(&tr->out.seclock); - poperror(); - free(cb); - poperror(); - - return n; -} - -static void -tlsinit(void) -{ - struct Encalg *e; - struct Hashalg *h; - int n; - char *cp; - static int already; - - if(!already){ - fmtinstall('H', encodefmt); - already = 1; - } - - tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs); - trnames = smalloc((sizeof *trnames) * maxtlsdevs); - - n = 1; - for(e = encrypttab; e->name != nil; e++) - n += strlen(e->name) + 1; - cp = encalgs = smalloc(n); - for(e = encrypttab;;){ - strcpy(cp, e->name); - cp += strlen(e->name); - e++; - if(e->name == nil) - break; - *cp++ = ' '; - } - *cp = 0; - - n = 1; - for(h = hashtab; h->name != nil; h++) - n += strlen(h->name) + 1; - cp = hashalgs = smalloc(n); - for(h = hashtab;;){ - strcpy(cp, h->name); - cp += strlen(h->name); - h++; - if(h->name == nil) - break; - *cp++ = ' '; - } - *cp = 0; -} - -Dev tlsdevtab = { - 'a', - "tls", - - devreset, - tlsinit, - devshutdown, - tlsattach, - tlswalk, - tlsstat, - tlsopen, - devcreate, - tlsclose, - tlsread, - tlsbread, - tlswrite, - tlsbwrite, - devremove, - tlswstat, -}; - -/* get channel associated with an fd */ -static Chan* -buftochan(char *p) -{ - Chan *c; - int fd; - - if(p == 0) - error(Ebadarg); - fd = strtoul(p, 0, 0); - if(fd < 0) - error(Ebadarg); - c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ - return c; -} - -static void -sendAlert(TlsRec *tr, int err) -{ - Block *b; - int i, fatal; - char *msg; - -if(tr->debug)pprint("sendAlert %d\n", err); - fatal = 1; - msg = "tls unknown alert"; - for(i=0; i < nelem(tlserrs); i++) { - if(tlserrs[i].err == err) { - msg = tlserrs[i].msg; - if(tr->version == SSL3Version) - err = tlserrs[i].sslerr; - else - err = tlserrs[i].tlserr; - fatal = tlserrs[i].fatal; - break; - } - } - - if(!waserror()){ - b = allocb(2); - *b->wp++ = fatal + 1; - *b->wp++ = err; - if(fatal) - tlsSetState(tr, SAlert, SOpen|SHandshake|SRClose); - tlsrecwrite(tr, RAlert, b); - poperror(); - } - if(fatal) - tlsError(tr, msg); -} - -static void -tlsError(TlsRec *tr, char *msg) -{ - int s; - -if(tr->debug)pprint("tleError %s\n", msg); - lock(&tr->statelk); - s = tr->state; - tr->state = SError; - if(s != SError){ - strncpy(tr->err, msg, ERRMAX - 1); - tr->err[ERRMAX - 1] = '\0'; - } - unlock(&tr->statelk); - if(s != SError) - alertHand(tr, msg); -} - -static void -tlsSetState(TlsRec *tr, int new, int old) -{ - lock(&tr->statelk); - if(tr->state & old) - tr->state = new; - unlock(&tr->statelk); -} - -/* hand up a digest connection */ -static void -tlshangup(TlsRec *tr) -{ - Block *b; - - qlock(&tr->in.io); - for(b = tr->processed; b; b = tr->processed){ - tr->processed = b->next; - freeb(b); - } - if(tr->unprocessed != nil){ - freeb(tr->unprocessed); - tr->unprocessed = nil; - } - qunlock(&tr->in.io); - - tlsSetState(tr, SClosed, ~0); -} - -static TlsRec* -newtls(Chan *ch) -{ - TlsRec **pp, **ep, **np; - char **nmp; - int t, newmax; - - if(waserror()) { - unlock(&tdlock); - nexterror(); - } - lock(&tdlock); - ep = &tlsdevs[maxtlsdevs]; - for(pp = tlsdevs; pp < ep; pp++) - if(*pp == nil) - break; - if(pp >= ep) { - if(maxtlsdevs >= MaxTlsDevs) { - unlock(&tdlock); - poperror(); - return nil; - } - newmax = 2 * maxtlsdevs; - if(newmax > MaxTlsDevs) - newmax = MaxTlsDevs; - np = smalloc(sizeof(TlsRec*) * newmax); - memmove(np, tlsdevs, sizeof(TlsRec*) * maxtlsdevs); - tlsdevs = np; - pp = &tlsdevs[maxtlsdevs]; - memset(pp, 0, sizeof(TlsRec*)*(newmax - maxtlsdevs)); - - nmp = smalloc(sizeof *nmp * newmax); - memmove(nmp, trnames, sizeof *nmp * maxtlsdevs); - trnames = nmp; - - maxtlsdevs = newmax; - } - *pp = mktlsrec(); - if(pp - tlsdevs >= tdhiwat) - tdhiwat++; - t = TYPE(ch->qid); - if(t == Qclonus) - t = Qctl; - ch->qid.path = QID(pp - tlsdevs, t); - ch->qid.vers = 0; - unlock(&tdlock); - poperror(); - return *pp; -} - -static TlsRec * -mktlsrec(void) -{ - TlsRec *tr; - - tr = mallocz(sizeof(*tr), 1); - if(tr == nil) - error(Enomem); - tr->state = SClosed; - tr->ref = 1; - kstrdup(&tr->user, up->user); - tr->perm = 0660; - return tr; -} - -static char* -tlsstate(int s) -{ - switch(s){ - case SHandshake: - return "Handshaking"; - case SOpen: - return "Established"; - case SRClose: - return "RemoteClosed"; - case SLClose: - return "LocalClosed"; - case SAlert: - return "Alerting"; - case SError: - return "Errored"; - case SClosed: - return "Closed"; - } - return "Unknown"; -} - -static void -freeSec(Secret *s) -{ - if(s != nil){ - free(s->enckey); - free(s); - } -} - -static int -noenc(Secret *unused1, uchar *unused2, int n) -{ - return n; -} - -static int -rc4enc(Secret *sec, uchar *buf, int n) -{ - rc4(sec->enckey, buf, n); - return n; -} - -static int -tlsunpad(uchar *buf, int n, int block) -{ - int pad, nn; - - pad = buf[n - 1]; - nn = n - 1 - pad; - if(nn <= 0 || n % block) - return -1; - while(--n > nn) - if(pad != buf[n - 1]) - return -1; - return nn; -} - -static int -sslunpad(uchar *buf, int n, int block) -{ - int pad, nn; - - pad = buf[n - 1]; - nn = n - 1 - pad; - if(nn <= 0 || n % block) - return -1; - return nn; -} - -static int -blockpad(uchar *buf, int n, int block) -{ - int pad, nn; - - nn = n + block; - nn -= nn % block; - pad = nn - (n + 1); - while(n < nn) - buf[n++] = pad; - return nn; -} - -static int -des3enc(Secret *sec, uchar *buf, int n) -{ - n = blockpad(buf, n, 8); - des3CBCencrypt(buf, n, sec->enckey); - return n; -} - -static int -des3dec(Secret *sec, uchar *buf, int n) -{ - des3CBCdecrypt(buf, n, sec->enckey); - return (*sec->unpad)(buf, n, 8); -} -static DigestState* -nomac(uchar *unused1, ulong unused2, uchar *unused3, ulong unused4, - uchar *unused5, DigestState *unused6) -{ - return nil; -} - -/* - * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac. - */ -static DigestState* -sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s, - DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen) -{ - int i; - uchar pad[48], innerdigest[20]; - - if(xlen > sizeof(innerdigest) - || padlen > sizeof(pad)) - return nil; - - if(klen>64) - return nil; - - /* first time through */ - if(s == nil){ - for(i=0; i<padlen; i++) - pad[i] = 0x36; - s = (*x)(key, klen, nil, nil); - s = (*x)(pad, padlen, nil, s); - if(s == nil) - return nil; - } - - s = (*x)(p, len, nil, s); - if(digest == nil) - return s; - - /* last time through */ - for(i=0; i<padlen; i++) - pad[i] = 0x5c; - (*x)(nil, 0, innerdigest, s); - s = (*x)(key, klen, nil, nil); - s = (*x)(pad, padlen, nil, s); - (*x)(innerdigest, xlen, digest, s); - return nil; -} - -static DigestState* -sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s) -{ - return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40); -} - -static DigestState* -sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s) -{ - return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48); -} - -static void -sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac) -{ - DigestState *s; - uchar buf[11]; - - memmove(buf, seq, 8); - buf[8] = header[0]; - buf[9] = header[3]; - buf[10] = header[4]; - - s = (*sec->mac)(buf, 11, mackey, sec->maclen, 0, 0); - (*sec->mac)(body, len, mackey, sec->maclen, mac, s); -} - -static void -tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac) -{ - DigestState *s; - uchar buf[13]; - - memmove(buf, seq, 8); - memmove(&buf[8], header, 5); - - s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0); - (*sec->mac)(body, len, mackey, sec->maclen, mac, s); -} - -static void -put32(uchar *p, u32int x) -{ - p[0] = x>>24; - p[1] = x>>16; - p[2] = x>>8; - p[3] = x; -} - -static void -put64(uchar *p, vlong x) -{ - put32(p, (u32int)(x >> 32)); - put32(p+4, (u32int)x); -} - -static void -put24(uchar *p, int x) -{ - p[0] = x>>16; - p[1] = x>>8; - p[2] = x; -} - -static void -put16(uchar *p, int x) -{ - p[0] = x>>8; - p[1] = x; -} - -/* -static u32int -get32(uchar *p) -{ - return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; -} -*/ - -static int -get16(uchar *p) -{ - return (p[0]<<8)|p[1]; -} - -static char *charmap = "0123456789abcdef"; - -static void -pdump(int len, void *a, char *tag) -{ - uchar *p; - int i; - char buf[65+32]; - char *q; - - p = a; - strcpy(buf, tag); - while(len > 0){ - q = buf + strlen(tag); - for(i = 0; len > 0 && i < 32; i++){ - if(*p >= ' ' && *p < 0x7f){ - *q++ = ' '; - *q++ = *p; - } else { - *q++ = charmap[*p>>4]; - *q++ = charmap[*p & 0xf]; - } - len--; - p++; - } - *q = 0; - - if(len > 0) - pprint("%s...\n", buf); - else - pprint("%s\n", buf); - } -} diff --git a/sys/src/cmd/unix/drawterm/kern/error.c b/sys/src/cmd/unix/drawterm/kern/error.c deleted file mode 100644 index 465de475a..000000000 --- a/sys/src/cmd/unix/drawterm/kern/error.c +++ /dev/null @@ -1,50 +0,0 @@ -char Enoerror[] = "no error"; -char Emount[] = "inconsistent mount"; -char Eunmount[] = "not mounted"; -char Eunion[] = "not in union"; -char Emountrpc[] = "mount rpc error"; -char Eshutdown[] = "device shut down"; -char Enocreate[] = "mounted directory forbids creation"; -char Enonexist[] = "file does not exist"; -char Eexist[] = "file already exists"; -char Ebadsharp[] = "unknown device in # filename"; -char Enotdir[] = "not a directory"; -char Eisdir[] = "file is a directory"; -char Ebadchar[] = "bad character in file name"; -char Efilename[] = "file name syntax"; -char Eperm[] = "permission denied"; -char Ebadusefd[] = "inappropriate use of fd"; -char Ebadarg[] = "bad arg in system call"; -char Einuse[] = "device or object already in use"; -char Eio[] = "i/o error"; -char Etoobig[] = "read or write too large"; -char Etoosmall[] = "read or write too small"; -char Enoport[] = "network port not available"; -char Ehungup[] = "i/o on hungup channel"; -char Ebadctl[] = "bad process or channel control request"; -char Enodev[] = "no free devices"; -char Eprocdied[] = "process exited"; -char Enochild[] = "no living children"; -char Eioload[] = "i/o error in demand load"; -char Enovmem[] = "virtual memory allocation failed"; -char Ebadfd[] = "fd out of range or not open"; -char Enofd[] = "no free file descriptors"; -char Eisstream[] = "seek on a stream"; -char Ebadexec[] = "exec header invalid"; -char Etimedout[] = "connection timed out"; -char Econrefused[] = "connection refused"; -char Econinuse[] = "connection in use"; -char Eintr[] = "interrupted"; -char Enomem[] = "kernel allocate failed"; -char Enoswap[] = "swap space full"; -char Esoverlap[] = "segments overlap"; -char Emouseset[] = "mouse type already set"; -char Eshort[] = "i/o count too small"; -char Egreg[] = "ken has left the building"; -char Ebadspec[] = "bad attach specifier"; -char Enoreg[] = "process has no saved registers"; -char Enoattach[] = "mount/attach disallowed"; -char Eshortstat[] = "stat buffer too small"; -char Ebadstat[] = "malformed stat buffer"; -char Enegoff[] = "negative i/o offset"; -char Ecmdargs[] = "wrong #args in control message"; diff --git a/sys/src/cmd/unix/drawterm/kern/error.h b/sys/src/cmd/unix/drawterm/kern/error.h deleted file mode 100644 index 6bb87622e..000000000 --- a/sys/src/cmd/unix/drawterm/kern/error.h +++ /dev/null @@ -1,50 +0,0 @@ -extern char Enoerror[]; /* no error */ -extern char Emount[]; /* inconsistent mount */ -extern char Eunmount[]; /* not mounted */ -extern char Eunion[]; /* not in union */ -extern char Emountrpc[]; /* mount rpc error */ -extern char Eshutdown[]; /* device shut down */ -extern char Enocreate[]; /* mounted directory forbids creation */ -extern char Enonexist[]; /* file does not exist */ -extern char Eexist[]; /* file already exists */ -extern char Ebadsharp[]; /* unknown device in # filename */ -extern char Enotdir[]; /* not a directory */ -extern char Eisdir[]; /* file is a directory */ -extern char Ebadchar[]; /* bad character in file name */ -extern char Efilename[]; /* file name syntax */ -extern char Eperm[]; /* permission denied */ -extern char Ebadusefd[]; /* inappropriate use of fd */ -extern char Ebadarg[]; /* bad arg in system call */ -extern char Einuse[]; /* device or object already in use */ -extern char Eio[]; /* i/o error */ -extern char Etoobig[]; /* read or write too large */ -extern char Etoosmall[]; /* read or write too small */ -extern char Enoport[]; /* network port not available */ -extern char Ehungup[]; /* i/o on hungup channel */ -extern char Ebadctl[]; /* bad process or channel control request */ -extern char Enodev[]; /* no free devices */ -extern char Eprocdied[]; /* process exited */ -extern char Enochild[]; /* no living children */ -extern char Eioload[]; /* i/o error in demand load */ -extern char Enovmem[]; /* virtual memory allocation failed */ -extern char Ebadfd[]; /* fd out of range or not open */ -extern char Enofd[]; /* no free file descriptors */ -extern char Eisstream[]; /* seek on a stream */ -extern char Ebadexec[]; /* exec header invalid */ -extern char Etimedout[]; /* connection timed out */ -extern char Econrefused[]; /* connection refused */ -extern char Econinuse[]; /* connection in use */ -extern char Eintr[]; /* interrupted */ -extern char Enomem[]; /* kernel allocate failed */ -extern char Enoswap[]; /* swap space full */ -extern char Esoverlap[]; /* segments overlap */ -extern char Emouseset[]; /* mouse type already set */ -extern char Eshort[]; /* i/o count too small */ -extern char Egreg[]; /* ken has left the building */ -extern char Ebadspec[]; /* bad attach specifier */ -extern char Enoreg[]; /* process has no saved registers */ -extern char Enoattach[]; /* mount/attach disallowed */ -extern char Eshortstat[]; /* stat buffer too small */ -extern char Ebadstat[]; /* malformed stat buffer */ -extern char Enegoff[]; /* negative i/o offset */ -extern char Ecmdargs[]; /* wrong #args in control message */ diff --git a/sys/src/cmd/unix/drawterm/kern/exportfs.c b/sys/src/cmd/unix/drawterm/kern/exportfs.c deleted file mode 100644 index 46cb90d0c..000000000 --- a/sys/src/cmd/unix/drawterm/kern/exportfs.c +++ /dev/null @@ -1,821 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -typedef struct Fid Fid; -typedef struct Export Export; -typedef struct Exq Exq; - -#define nil ((void*)0) - -enum -{ - Nfidhash = 1, - MAXRPC = MAXMSG+MAXFDATA, - MAXDIRREAD = (MAXFDATA/DIRLEN)*DIRLEN -}; - -struct Export -{ - Ref r; - Exq* work; - Lock fidlock; - Fid* fid[Nfidhash]; - Chan* root; - Chan* io; - Pgrp* pgrp; - int npart; - char part[MAXRPC]; -}; - -struct Fid -{ - Fid* next; - Fid** last; - Chan* chan; - long offset; - int fid; - int ref; /* fcalls using the fid; locked by Export.Lock */ - int attached; /* fid attached or cloned but not clunked */ -}; - -struct Exq -{ - Lock lk; - int nointr; - int noresponse; /* don't respond to this one */ - Exq* next; - int shut; /* has been noted for shutdown */ - Export* export; - void* slave; - Fcall rpc; - char buf[MAXRPC]; -}; - -struct -{ - Lock l; - Qlock qwait; - Rendez rwait; - Exq *head; /* work waiting for a slave */ - Exq *tail; -}exq; - -static void exshutdown(Export*); -static void exflush(Export*, int, int); -static void exslave(void*); -static void exfree(Export*); -static void exportproc(Export*); - -static char* Exauth(Export*, Fcall*); -static char* Exattach(Export*, Fcall*); -static char* Exclunk(Export*, Fcall*); -static char* Excreate(Export*, Fcall*); -static char* Exopen(Export*, Fcall*); -static char* Exread(Export*, Fcall*); -static char* Exremove(Export*, Fcall*); -static char* Exstat(Export*, Fcall*); -static char* Exwalk(Export*, Fcall*); -static char* Exwrite(Export*, Fcall*); -static char* Exwstat(Export*, Fcall*); -static char* Exversion(Export*, Fcall*); - -static char *(*fcalls[Tmax])(Export*, Fcall*); - -static char Enofid[] = "no such fid"; -static char Eseekdir[] = "can't seek on a directory"; -static char Ereaddir[] = "unaligned read of a directory"; -static int exdebug = 0; - -int -sysexport(int fd) -{ - Chan *c; - Export *fs; - - if(waserror()) - return -1; - - c = fdtochan(fd, ORDWR, 1, 1); - poperror(); - c->flag |= CMSG; - - fs = mallocz(sizeof(Export)); - fs->r.ref = 1; - fs->pgrp = up->pgrp; - refinc(&fs->pgrp->r); - refinc(&up->slash->r); - fs->root = up->slash; - refinc(&fs->root->r); - fs->root = domount(fs->root); - fs->io = c; - - exportproc(fs); - - return 0; -} - -static void -exportinit(void) -{ - lock(&exq.l); - if(fcalls[Tversion] != nil) { - unlock(&exq.l); - return; - } - - fmtinstall('F', fcallfmt); - fmtinstall('D', dirfmt); - fmtinstall('M', dirmodefmt); - fcalls[Tversion] = Exversion; - fcalls[Tauth] = Exauth; - fcalls[Tattach] = Exattach; - fcalls[Twalk] = Exwalk; - fcalls[Topen] = Exopen; - fcalls[Tcreate] = Excreate; - fcalls[Tread] = Exread; - fcalls[Twrite] = Exwrite; - fcalls[Tclunk] = Exclunk; - fcalls[Tremove] = Exremove; - fcalls[Tstat] = Exstat; - fcalls[Twstat] = Exwstat; - unlock(&exq.l); -} - -void -exportproc(Export *fs) -{ - Exq *q; - char *buf; - int n, cn, len; - - exportinit(); - - for(;;){ - q = mallocz(sizeof(Exq)); - if(q == 0) - panic("no memory"); - - q->rpc.data = q->buf + MAXMSG; - - buf = q->buf; - len = MAXRPC; - if(fs->npart) { - memmove(buf, fs->part, fs->npart); - buf += fs->npart; - len -= fs->npart; - goto chk; - } - for(;;) { - if(waserror()) - goto bad; - - n = (*devtab[fs->io->type].read)(fs->io, buf, len, 0); - poperror(); - - if(n <= 0) - goto bad; - - buf += n; - len -= n; - chk: - n = buf - q->buf; - - /* convM2S returns size of correctly decoded message */ - cn = convM2S(q->buf, &q->rpc, n); - if(cn < 0){ - iprint("bad message type in devmnt\n"); - goto bad; - } - if(cn > 0) { - n -= cn; - if(n < 0){ - iprint("negative size in devmnt"); - goto bad; - } - fs->npart = n; - if(n != 0) - memmove(fs->part, q->buf+cn, n); - break; - } - } - if(exdebug) - iprint("export %d <- %F\n", getpid(), &q->rpc); - - if(q->rpc.type == Tflush){ - exflush(fs, q->rpc.tag, q->rpc.oldtag); - free(q); - continue; - } - - q->export = fs; - refinc(&fs->r); - - lock(&exq.l); - if(exq.head == nil) - exq.head = q; - else - exq.tail->next = q; - q->next = nil; - exq.tail = q; - unlock(&exq.l); - if(exq.qwait.first == nil) { - n = thread("exportfs", exslave, nil); -/* iprint("launch export (pid=%ux)\n", n); */ - } - rendwakeup(&exq.rwait); - } -bad: - free(q); - exshutdown(fs); - exfree(fs); -} - -void -exflush(Export *fs, int flushtag, int tag) -{ - Exq *q, **last; - int n; - Fcall fc; - char buf[MAXMSG]; - - /* hasn't been started? */ - lock(&exq.l); - last = &exq.head; - for(q = exq.head; q != nil; q = q->next){ - if(q->export == fs && q->rpc.tag == tag){ - *last = q->next; - unlock(&exq.l); - exfree(fs); - free(q); - goto Respond; - } - last = &q->next; - } - unlock(&exq.l); - - /* in progress? */ - lock(&fs->r.l); - for(q = fs->work; q != nil; q = q->next){ - if(q->rpc.tag == tag && !q->noresponse){ - lock(&q->lk); - q->noresponse = 1; - if(!q->nointr) - intr(q->slave); - unlock(&q->lk); - unlock(&fs->r.l); - goto Respond; - return; - } - } - unlock(&fs->r.l); - -if(exdebug) iprint("exflush: did not find rpc: %d\n", tag); - -Respond: - fc.type = Rflush; - fc.tag = flushtag; - n = convS2M(&fc, buf); -if(exdebug) iprint("exflush -> %F\n", &fc); - if(!waserror()){ - (*devtab[fs->io->type].write)(fs->io, buf, n, 0); - poperror(); - } -} - -void -exshutdown(Export *fs) -{ - Exq *q, **last; - - lock(&exq.l); - last = &exq.head; - for(q = exq.head; q != nil; q = *last){ - if(q->export == fs){ - *last = q->next; - exfree(fs); - free(q); - continue; - } - last = &q->next; - } - unlock(&exq.l); - - lock(&fs->r.l); - q = fs->work; - while(q != nil){ - if(q->shut){ - q = q->next; - continue; - } - q->shut = 1; - unlock(&fs->r.l); - /* postnote(q->slave, 1, "interrupted", NUser); */ - iprint("postnote 2!\n"); - lock(&fs->r.l); - q = fs->work; - } - unlock(&fs->r.l); -} - -void -exfree(Export *fs) -{ - Fid *f, *n; - int i; - - if(refdec(&fs->r) != 0) - return; - closepgrp(fs->pgrp); - cclose(fs->root); - cclose(fs->io); - for(i = 0; i < Nfidhash; i++){ - for(f = fs->fid[i]; f != nil; f = n){ - if(f->chan != nil) - cclose(f->chan); - n = f->next; - free(f); - } - } - free(fs); -} - -int -exwork(void *a) -{ - return exq.head != nil; -} - -void -exslave(void *a) -{ - Export *fs; - Exq *q, *t, **last; - char *err; - int n; -/* - closepgrp(up->pgrp); - up->pgrp = nil; -*/ - for(;;){ - qlock(&exq.qwait); - rendsleep(&exq.rwait, exwork, nil); - - lock(&exq.l); - q = exq.head; - if(q == nil) { - unlock(&exq.l); - qunlock(&exq.qwait); - continue; - } - exq.head = q->next; - q->slave = curthread(); - unlock(&exq.l); - - qunlock(&exq.qwait); - - q->noresponse = 0; - q->nointr = 0; - fs = q->export; - lock(&fs->r.l); - q->next = fs->work; - fs->work = q; - unlock(&fs->r.l); - - up->pgrp = q->export->pgrp; - - if(exdebug > 1) - iprint("exslave dispatch %d %F\n", getpid(), &q->rpc); - - if(waserror()){ - iprint("exslave err %r\n"); - err = up->errstr; - goto Err; - } - if(q->rpc.type >= Tmax || !fcalls[q->rpc.type]) - err = "bad fcall type"; - else - err = (*fcalls[q->rpc.type])(fs, &q->rpc); - - poperror(); - Err:; - q->rpc.type++; - if(err){ - q->rpc.type = Rerror; - strncpy(q->rpc.ename, err, ERRLEN); - } - n = convS2M(&q->rpc, q->buf); - - if(exdebug) - iprint("exslve %d -> %F\n", getpid(), &q->rpc); - - lock(&q->lk); - if(q->noresponse == 0){ - q->nointr = 1; - clearintr(); - if(!waserror()){ - (*devtab[fs->io->type].write)(fs->io, q->buf, n, 0); - poperror(); - } - } - unlock(&q->lk); - - /* - * exflush might set noresponse at this point, but - * setting noresponse means don't send a response now; - * it's okay that we sent a response already. - */ - if(exdebug > 1) - iprint("exslave %d written %d\n", getpid(), q->rpc.tag); - - lock(&fs->r.l); - last = &fs->work; - for(t = fs->work; t != nil; t = t->next){ - if(t == q){ - *last = q->next; - break; - } - last = &t->next; - } - unlock(&fs->r.l); - - exfree(q->export); - free(q); - } - iprint("exslave shut down"); - threadexit(); -} - -Fid* -Exmkfid(Export *fs, int fid) -{ - ulong h; - Fid *f, *nf; - - nf = mallocz(sizeof(Fid)); - if(nf == nil) - return nil; - lock(&fs->fidlock); - h = fid % Nfidhash; - for(f = fs->fid[h]; f != nil; f = f->next){ - if(f->fid == fid){ - unlock(&fs->fidlock); - free(nf); - return nil; - } - } - - nf->next = fs->fid[h]; - if(nf->next != nil) - nf->next->last = &nf->next; - nf->last = &fs->fid[h]; - fs->fid[h] = nf; - - nf->fid = fid; - nf->ref = 1; - nf->attached = 1; - nf->offset = 0; - nf->chan = nil; - unlock(&fs->fidlock); - return nf; -} - -Fid* -Exgetfid(Export *fs, int fid) -{ - Fid *f; - ulong h; - - lock(&fs->fidlock); - h = fid % Nfidhash; - for(f = fs->fid[h]; f; f = f->next) { - if(f->fid == fid){ - if(f->attached == 0) - break; - f->ref++; - unlock(&fs->fidlock); - return f; - } - } - unlock(&fs->fidlock); - return nil; -} - -void -Exputfid(Export *fs, Fid *f) -{ - lock(&fs->fidlock); - f->ref--; - if(f->ref == 0 && f->attached == 0){ - if(f->chan != nil) - cclose(f->chan); - f->chan = nil; - *f->last = f->next; - if(f->next != nil) - f->next->last = f->last; - unlock(&fs->fidlock); - free(f); - return; - } - unlock(&fs->fidlock); -} - -char* -Exsession(Export *e, Fcall *rpc) -{ - memset(rpc->authid, 0, sizeof(rpc->authid)); - memset(rpc->authdom, 0, sizeof(rpc->authdom)); - memset(rpc->chal, 0, sizeof(rpc->chal)); - return nil; -} - -char* -Exauth(Export *e, Fcall *f) -{ - return "authentication not required"; -} - -char* -Exattach(Export *fs, Fcall *rpc) -{ - Fid *f; - - f = Exmkfid(fs, rpc->fid); - if(f == nil) - return Einuse; - if(waserror()){ - f->attached = 0; - Exputfid(fs, f); - return up->errstr; - } - f->chan = clone(fs->root, nil); - poperror(); - rpc->qid = f->chan->qid; - Exputfid(fs, f); - return nil; -} - -char* -Exclone(Export *fs, Fcall *rpc) -{ - Fid *f, *nf; - - if(rpc->fid == rpc->newfid) - return Einuse; - f = Exgetfid(fs, rpc->fid); - if(f == nil) - return Enofid; - nf = Exmkfid(fs, rpc->newfid); - if(nf == nil){ - Exputfid(fs, f); - return Einuse; - } - if(waserror()){ - Exputfid(fs, f); - Exputfid(fs, nf); - return up->errstr; - } - nf->chan = clone(f->chan, nil); - poperror(); - Exputfid(fs, f); - Exputfid(fs, nf); - return nil; -} - -char* -Exclunk(Export *fs, Fcall *rpc) -{ - Fid *f; - - f = Exgetfid(fs, rpc->fid); - if(f != nil){ - f->attached = 0; - Exputfid(fs, f); - } - return nil; -} - -char* -Exwalk(Export *fs, Fcall *rpc) -{ - Fid *f; - Chan *c; - - f = Exgetfid(fs, rpc->fid); - if(f == nil) - return Enofid; - if(waserror()){ - Exputfid(fs, f); - return up->errstr; - } - c = walk(f->chan, rpc->name, 1); - if(c == nil) - error(Enonexist); - poperror(); - - f->chan = c; - rpc->qid = c->qid; - Exputfid(fs, f); - return nil; -} - -char* -Exopen(Export *fs, Fcall *rpc) -{ - Fid *f; - Chan *c; - - f = Exgetfid(fs, rpc->fid); - if(f == nil) - return Enofid; - if(waserror()){ - Exputfid(fs, f); - return up->errstr; - } - c = f->chan; - c = (*devtab[c->type].open)(c, rpc->mode); - poperror(); - - f->chan = c; - f->offset = 0; - rpc->qid = f->chan->qid; - Exputfid(fs, f); - return nil; -} - -char* -Excreate(Export *fs, Fcall *rpc) -{ - Fid *f; - Chan *c; - - f = Exgetfid(fs, rpc->fid); - if(f == nil) - return Enofid; - if(waserror()){ - Exputfid(fs, f); - return up->errstr; - } - c = f->chan; - if(c->mnt && !(c->flag&CCREATE)) - c = createdir(c); - (*devtab[c->type].create)(c, rpc->name, rpc->mode, rpc->perm); - poperror(); - - f->chan = c; - rpc->qid = f->chan->qid; - Exputfid(fs, f); - return nil; -} - -char* -Exread(Export *fs, Fcall *rpc) -{ - Fid *f; - Chan *c; - long off; - int dir, n, seek; - - f = Exgetfid(fs, rpc->fid); - if(f == nil) - return Enofid; - - c = f->chan; - dir = c->qid.path & CHDIR; - if(dir){ - rpc->count -= rpc->count%DIRLEN; - if(rpc->offset%DIRLEN || rpc->count==0){ - Exputfid(fs, f); - return Ereaddir; - } - if(f->offset > rpc->offset){ - Exputfid(fs, f); - return Eseekdir; - } - } - - if(waserror()) { - Exputfid(fs, f); - return up->errstr; - } - - for(;;){ - n = rpc->count; - seek = 0; - off = rpc->offset; - if(dir && f->offset != off){ - off = f->offset; - n = rpc->offset - off; - if(n > MAXDIRREAD) - n = MAXDIRREAD; - seek = 1; - } - if(dir && c->mnt != nil) - n = unionread(c, rpc->data, n); - else{ - c->offset = off; - n = (*devtab[c->type].read)(c, rpc->data, n, off); - } - if(n == 0 || !seek) - break; - f->offset = off + n; - c->offset += n; - } - rpc->count = n; - poperror(); - Exputfid(fs, f); - return nil; -} - -char* -Exwrite(Export *fs, Fcall *rpc) -{ - Fid *f; - Chan *c; - - f = Exgetfid(fs, rpc->fid); - if(f == nil) - return Enofid; - if(waserror()){ - Exputfid(fs, f); - return up->errstr; - } - c = f->chan; - if(c->qid.path & CHDIR) - error(Eisdir); - rpc->count = (*devtab[c->type].write)(c, rpc->data, rpc->count, rpc->offset); - poperror(); - Exputfid(fs, f); - return nil; -} - -char* -Exstat(Export *fs, Fcall *rpc) -{ - Fid *f; - Chan *c; - - f = Exgetfid(fs, rpc->fid); - if(f == nil) - return Enofid; - if(waserror()){ - Exputfid(fs, f); - return up->errstr; - } - c = f->chan; - (*devtab[c->type].stat)(c, rpc->stat); - poperror(); - Exputfid(fs, f); - return nil; -} - -char* -Exwstat(Export *fs, Fcall *rpc) -{ - Fid *f; - Chan *c; - - f = Exgetfid(fs, rpc->fid); - if(f == nil) - return Enofid; - if(waserror()){ - Exputfid(fs, f); - return up->errstr; - } - c = f->chan; - (*devtab[c->type].wstat)(c, rpc->stat); - poperror(); - Exputfid(fs, f); - return nil; -} - -char* -Exremove(Export *fs, Fcall *rpc) -{ - Fid *f; - Chan *c; - - f = Exgetfid(fs, rpc->fid); - if(f == nil) - return Enofid; - if(waserror()){ - Exputfid(fs, f); - return up->errstr; - } - c = f->chan; - (*devtab[c->type].remove)(c); - poperror(); - - /* - * chan is already clunked by remove. - * however, we need to recover the chan, - * and follow sysremove's lead in making to point to root. - */ - c->type = 0; - - f->attached = 0; - Exputfid(fs, f); - return nil; -} diff --git a/sys/src/cmd/unix/drawterm/kern/fns.h b/sys/src/cmd/unix/drawterm/kern/fns.h deleted file mode 100644 index 97a935941..000000000 --- a/sys/src/cmd/unix/drawterm/kern/fns.h +++ /dev/null @@ -1,392 +0,0 @@ -#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1)) - -void accounttime(void); -void addclock0link(void (*)(void), int); -int addphysseg(Physseg*); -void addbootfile(char*, uchar*, ulong); -Block* adjustblock(Block*, int); -void alarmkproc(void*); -Block* allocb(int); -int anyhigher(void); -int anyready(void); -Page* auxpage(void); -Block* bl2mem(uchar*, Block*, int); -int blocklen(Block*); -void callwithureg(void(*)(Ureg*)); -char* c2name(Chan*); -int cangetc(void*); -int canlock(Lock*); -int canpage(Proc*); -int canputc(void*); -int canqlock(QLock*); -int canrlock(RWlock*); -void chandevinit(void); -void chandevreset(void); -void chandevshutdown(void); -void chanfree(Chan*); -void chanrec(Mnt*); -void checkalarms(void); -void checkb(Block*, char*); -void cinit(void); -Chan* cclone(Chan*); -void cclose(Chan*); -char* clipread(void); -int clipwrite(char*); -void closeegrp(Egrp*); -void closefgrp(Fgrp*); -void closemount(Mount*); -void closepgrp(Pgrp*); -void closergrp(Rgrp*); -long clrfpintr(void); -void cmderror(Cmdbuf*, char*); -int cmount(Chan**, Chan*, int, char*); -void cnameclose(Cname*); -void confinit(void); -void confinit1(int); -int consactive(void); -extern void (*consdebug)(void); -void copen(Chan*); -Block* concatblock(Block*); -Block* copyblock(Block*, int); -void copypage(Page*, Page*); -int cread(Chan*, uchar*, int, vlong); -void cunmount(Chan*, Chan*); -void cupdate(Chan*, uchar*, int, vlong); -void cwrite(Chan*, uchar*, int, vlong); -ulong dbgpc(Proc*); -int decref(Ref*); -int decrypt(void*, void*, int); -void delay(int); -Chan* devattach(int, char*); -Block* devbread(Chan*, long, ulong); -long devbwrite(Chan*, Block*, ulong); -Chan* devclone(Chan*); -int devconfig(int, char *, DevConf *); -void devcreate(Chan*, char*, int, ulong); -void devdir(Chan*, Qid, char*, vlong, char*, long, Dir*); -long devdirread(Chan*, char*, long, Dirtab*, int, Devgen*); -Devgen devgen; -void devinit(void); -int devno(int, int); -Chan* devopen(Chan*, int, Dirtab*, int, Devgen*); -void devpermcheck(char*, ulong, int); -void devpower(int); -void devremove(Chan*); -void devreset(void); -void devshutdown(void); -int devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*); -Walkqid* devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*); -int devwstat(Chan*, uchar*, int); -void drawactive(int); -void drawcmap(void); -int drawcanqlock(void); -void drawqlock(void); -void drawqunlock(void); -void dumpaproc(Proc*); -void dumpqueues(void); -void dumpregs(Ureg*); -void dumpstack(void); -Fgrp* dupfgrp(Fgrp*); -void duppage(Page*); -void dupswap(Page*); -int emptystr(char*); -int encrypt(void*, void*, int); -void envcpy(Egrp*, Egrp*); -int eqchan(Chan*, Chan*, int); -int eqqid(Qid, Qid); -void error(char*); -long execregs(ulong, ulong, ulong); -void exhausted(char*); -void exit(int); -uvlong fastticks(uvlong*); -int fault(ulong, int); -void fdclose(int, int); -Chan* fdtochan(int, int, int, int); -int fixfault(Segment*, ulong, int, int); -void flushmmu(void); -void forkchild(Proc*, Ureg*); -void forkret(void); -void free(void*); -void freeb(Block*); -void freeblist(Block*); -int freebroken(void); -void freepte(Segment*, Pte*); -void freesegs(int); -void freesession(Session*); -ulong getmalloctag(void*); -ulong getrealloctag(void*); -void gotolabel(Label*); -char* getconfenv(void); -int haswaitq(void*); -long hostdomainwrite(char*, int); -long hostownerwrite(char*, int); -void hzsched(void); -void iallocinit(void); -Block* iallocb(int); -void iallocsummary(void); -long ibrk(ulong, int); -void ilock(Lock*); -void iunlock(Lock*); -int incref(Ref*); -void initseg(void); -int iprint(char*, ...); -void isdir(Chan*); -int iseve(void); -#define islo() (0) -Segment* isoverlap(Proc*, ulong, int); -int ispages(void*); -int isphysseg(char*); -void ixsummary(void); -void kbdclock(void); -int kbdcr2nl(Queue*, int); -int kbdputc(Queue*, int); -void kbdrepeat(int); -long keyread(char*, int, long); -void kickpager(void); -void killbig(void); -int kproc(char*, void(*)(void*), void*); -void kprocchild(Proc*, void (*)(void*), void*); -extern void (*kproftimer)(ulong); -void ksetenv(char*, char*, int); -void kstrcpy(char*, char*, int); -void kstrdup(char**, char*); -long latin1(Rune*, int); -void lock(Lock*); -void lockinit(void); -void logopen(Log*); -void logclose(Log*); -char* logctl(Log*, int, char**, Logflag*); -void logn(Log*, int, void*, int); -long logread(Log*, void*, ulong, long); -void log(Log*, int, char*, ...); -Cmdtab* lookupcmd(Cmdbuf*, Cmdtab*, int); -void machinit(void); -void* mallocz(ulong, int); -#define malloc kmalloc -void* malloc(ulong); -void mallocsummary(void); -Block* mem2bl(uchar*, int); -void mfreeseg(Segment*, ulong, int); -void microdelay(int); -void mkqid(Qid*, vlong, ulong, int); -void mmurelease(Proc*); -void mmuswitch(Proc*); -Chan* mntauth(Chan*, char*); -void mntdump(void); -long mntversion(Chan*, char*, int, int); -void mountfree(Mount*); -ulong ms2tk(ulong); -ulong msize(void*); -ulong ms2tk(ulong); -uvlong ms2fastticks(ulong); -void muxclose(Mnt*); -Chan* namec(char*, int, int, ulong); -Chan* newchan(void); -int newfd(Chan*); -Mhead* newmhead(Chan*); -Mount* newmount(Mhead*, Chan*, int, char*); -Page* newpage(int, Segment **, ulong); -Pgrp* newpgrp(void); -Rgrp* newrgrp(void); -Proc* newproc(void); -char* nextelem(char*, char*); -void nexterror(void); -Cname* newcname(char*); -int notify(Ureg*); -int nrand(int); -int okaddr(ulong, ulong, int); -int openmode(ulong); -void oserrstr(void); -void oserror(void); -Block* packblock(Block*); -Block* padblock(Block*, int); -void pagechainhead(Page*); -void pageinit(void); -void pagersummary(void); -void panic(char*, ...); -Cmdbuf* parsecmd(char *a, int n); -ulong perfticks(void); -void pexit(char*, int); -int preempted(void); -void printinit(void); -int procindex(ulong); -void pgrpcpy(Pgrp*, Pgrp*); -void pgrpnote(ulong, char*, long, int); -Pgrp* pgrptab(int); -void pio(Segment *, ulong, ulong, Page **); -#define poperror() up->nerrlab-- -void portclock(Ureg*); -int postnote(Proc*, int, char*, int); -int pprint(char*, ...); -void prflush(void); -ulong procalarm(ulong); -int proccounter(char *name); -void procctl(Proc*); -void procdump(void); -int procfdprint(Chan*, int, int, char*, int); -void procinit0(void); -void procflushseg(Segment*); -void procpriority(Proc*, int, int); -Proc* proctab(int); -void procwired(Proc*, int); -Pte* ptealloc(void); -Pte* ptecpy(Pte*); -int pullblock(Block**, int); -Block* pullupblock(Block*, int); -Block* pullupqueue(Queue*, int); -void putmhead(Mhead*); -void putmmu(ulong, ulong, Page*); -void putpage(Page*); -void putseg(Segment*); -void putstr(char*); -void putstrn(char*, int); -void putswap(Page*); -ulong pwait(Waitmsg*); -Label* pwaserror(void); -void qaddlist(Queue*, Block*); -Block* qbread(Queue*, int); -long qbwrite(Queue*, Block*); -Queue* qbypass(void (*)(void*, Block*), void*); -int qcanread(Queue*); -void qclose(Queue*); -int qconsume(Queue*, void*, int); -Block* qcopy(Queue*, int, ulong); -int qdiscard(Queue*, int); -void qflush(Queue*); -void qfree(Queue*); -int qfull(Queue*); -Block* qget(Queue*); -void qhangup(Queue*, char*); -int qisclosed(Queue*); -void qinit(void); -int qiwrite(Queue*, void*, int); -int qlen(Queue*); -void qlock(QLock*); -Queue* qopen(int, int, void (*)(void*), void*); -int qpass(Queue*, Block*); -int qpassnolim(Queue*, Block*); -int qproduce(Queue*, void*, int); -void qputback(Queue*, Block*); -long qread(Queue*, void*, int); -Block* qremove(Queue*); -void qreopen(Queue*); -void qsetlimit(Queue*, int); -void qunlock(QLock*); -int qwindow(Queue*); -int qwrite(Queue*, void*, int); -void qnoblock(Queue*, int); -int rand(void); -void randominit(void); -ulong randomread(void*, ulong); -void rdb(void); -int readnum(ulong, char*, ulong, ulong, int); -int readstr(ulong, char*, ulong, char*); -void ready(Proc*); -void rebootcmd(int, char**); -void reboot(void*, void*, ulong); -void relocateseg(Segment*, ulong); -void renameuser(char*, char*); -void resched(char*); -void resrcwait(char*); -int return0(void*); -void rlock(RWlock*); -long rtctime(void); -void runlock(RWlock*); -Proc* runproc(void); -void savefpregs(FPsave*); -extern void (*saveintrts)(void); -void sched(void); -void scheddump(void); -void schedinit(void); -extern void (*screenputs)(char*, int); -long seconds(void); -ulong segattach(Proc*, ulong, char *, ulong, ulong); -void segclock(ulong); -void segpage(Segment*, Page*); -void setkernur(Ureg*, Proc*); -int setlabel(Label*); -void setmalloctag(void*, uintptr); -void setrealloctag(void*, ulong); -void setregisters(Ureg*, char*, char*, int); -void setswapchan(Chan*); -long showfilewrite(char*, int); -char* skipslash(char*); -void sleep(Rendez*, int(*)(void*), void*); -void* smalloc(ulong); -int splhi(void); -int spllo(void); -void splx(int); -void splxpc(int); -char* srvname(Chan*); -int swapcount(ulong); -int swapfull(void); -void swapinit(void); -void timeradd(Timer*); -void timerdel(Timer*); -void timersinit(void); -void timerintr(Ureg*, uvlong); -void timerset(uvlong); -ulong tk2ms(ulong); -#define TK2MS(x) ((x)*(1000/HZ)) -vlong todget(vlong*); -void todfix(void); -void todsetfreq(vlong); -void todinit(void); -void todset(vlong, vlong, int); -Block* trimblock(Block*, int, int); -void tsleep(Rendez*, int (*)(void*), void*, int); -int uartctl(Uart*, char*); -int uartgetc(void); -void uartkick(void*); -void uartmouse(Uart*, int (*)(Queue*, int), int); -void uartputc(int); -void uartputs(char*, int); -void uartrecv(Uart*, char); -Uart* uartsetup(Uart*); -int uartstageoutput(Uart*); -void unbreak(Proc*); -void uncachepage(Page*); -long unionread(Chan*, void*, long); -void unlock(Lock*); -Proc** uploc(void); -void userinit(void); -ulong userpc(void); -long userwrite(char*, int); -#define validaddr(a, b, c) -void validname(char*, int); -void validstat(uchar*, int); -void vcacheinval(Page*, ulong); -void* vmemchr(void*, int, int); -Proc* wakeup(Rendez*); -int walk(Chan**, char**, int, int, int*); -#define waserror() (setjmp(pwaserror()->buf)) -void wlock(RWlock*); -void wunlock(RWlock*); -void* xalloc(ulong); -void* xallocz(ulong, int); -void xfree(void*); -void xhole(ulong, ulong); -void xinit(void); -int xmerge(void*, void*); -void* xspanalloc(ulong, int, ulong); -void xsummary(void); -void yield(void); -Segment* data2txt(Segment*); -Segment* dupseg(Segment**, int, int); -Segment* newseg(int, ulong, ulong); -Segment* seg(Proc*, ulong, int); -void hnputv(void*, vlong); -void hnputl(void*, ulong); -void hnputs(void*, ushort); -vlong nhgetv(void*); -ulong nhgetl(void*); -ushort nhgets(void*); -ulong ticks(void); -void osproc(Proc*); -void osnewproc(Proc*); -void procsleep(void); -void procwakeup(Proc*); -void osinit(void); -void screeninit(void); -extern void terminit(void); - diff --git a/sys/src/cmd/unix/drawterm/kern/netif.h b/sys/src/cmd/unix/drawterm/kern/netif.h deleted file mode 100644 index 06c42aec8..000000000 --- a/sys/src/cmd/unix/drawterm/kern/netif.h +++ /dev/null @@ -1,133 +0,0 @@ -typedef struct Etherpkt Etherpkt; -typedef struct Netaddr Netaddr; -typedef struct Netfile Netfile; -typedef struct Netif Netif; - -enum -{ - Nmaxaddr= 64, - Nmhash= 31, - - Ncloneqid= 1, - Naddrqid, - N2ndqid, - N3rdqid, - Ndataqid, - Nctlqid, - Nstatqid, - Ntypeqid, - Nifstatqid, -}; - -/* - * Macros to manage Qid's used for multiplexed devices - */ -#define NETTYPE(x) (((ulong)x)&0x1f) -#define NETID(x) ((((ulong)x))>>5) -#define NETQID(i,t) ((((ulong)i)<<5)|(t)) - -/* - * one per multiplexed connection - */ -struct Netfile -{ - QLock lk; - - int inuse; - ulong mode; - char owner[KNAMELEN]; - - int type; /* multiplexor type */ - int prom; /* promiscuous mode */ - int scan; /* base station scanning interval */ - int bridge; /* bridge mode */ - int headersonly; /* headers only - no data */ - uchar maddr[8]; /* bitmask of multicast addresses requested */ - int nmaddr; /* number of multicast addresses */ - - Queue *in; /* input buffer */ -}; - -/* - * a network address - */ -struct Netaddr -{ - Netaddr *next; /* allocation chain */ - Netaddr *hnext; - uchar addr[Nmaxaddr]; - int ref; -}; - -/* - * a network interface - */ -struct Netif -{ - QLock lk; - - /* multiplexing */ - char name[KNAMELEN]; /* for top level directory */ - int nfile; /* max number of Netfiles */ - Netfile **f; - - /* about net */ - int limit; /* flow control */ - int alen; /* address length */ - int mbps; /* megabits per sec */ - uchar addr[Nmaxaddr]; - uchar bcast[Nmaxaddr]; - Netaddr *maddr; /* known multicast addresses */ - int nmaddr; /* number of known multicast addresses */ - Netaddr *mhash[Nmhash]; /* hash table of multicast addresses */ - int prom; /* number of promiscuous opens */ - int scan; /* number of base station scanners */ - int all; /* number of -1 multiplexors */ - - /* statistics */ - int misses; - int inpackets; - int outpackets; - int crcs; /* input crc errors */ - int oerrs; /* output errors */ - int frames; /* framing errors */ - int overflows; /* packet overflows */ - int buffs; /* buffering errors */ - int soverflows; /* software overflow */ - - /* routines for touching the hardware */ - void *arg; - void (*promiscuous)(void*, int); - void (*multicast)(void*, uchar*, int); - void (*scanbs)(void*, uint); /* scan for base stations */ -}; - -void netifinit(Netif*, char*, int, ulong); -Walkqid* netifwalk(Netif*, Chan*, Chan*, char **, int); -Chan* netifopen(Netif*, Chan*, int); -void netifclose(Netif*, Chan*); -long netifread(Netif*, Chan*, void*, long, ulong); -Block* netifbread(Netif*, Chan*, long, ulong); -long netifwrite(Netif*, Chan*, void*, long); -int netifwstat(Netif*, Chan*, uchar*, int); -int netifstat(Netif*, Chan*, uchar*, int); -int activemulti(Netif*, uchar*, int); - -/* - * Ethernet specific - */ -enum -{ - Eaddrlen= 6, - ETHERMINTU = 60, /* minimum transmit size */ - ETHERMAXTU = 1514, /* maximum transmit size */ - ETHERHDRSIZE = 14, /* size of an ethernet header */ -}; - -struct Etherpkt -{ - uchar d[Eaddrlen]; - uchar s[Eaddrlen]; - uchar type[2]; - uchar data[1500]; -}; diff --git a/sys/src/cmd/unix/drawterm/kern/parse.c b/sys/src/cmd/unix/drawterm/kern/parse.c deleted file mode 100644 index 8c991f8dc..000000000 --- a/sys/src/cmd/unix/drawterm/kern/parse.c +++ /dev/null @@ -1,113 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -/* - * Generous estimate of number of fields, including terminal nil pointer - */ -static int -ncmdfield(char *p, int n) -{ - int white, nwhite; - char *ep; - int nf; - - if(p == nil) - return 1; - - nf = 0; - ep = p+n; - white = 1; /* first text will start field */ - while(p < ep){ - nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0); /* UTF is irrelevant */ - if(white && !nwhite) /* beginning of field */ - nf++; - white = nwhite; - } - return nf+1; /* +1 for nil */ -} - -/* - * parse a command written to a device - */ -Cmdbuf* -parsecmd(char *p, int n) -{ - Cmdbuf *volatile cb; - int nf; - char *sp; - - nf = ncmdfield(p, n); - - /* allocate Cmdbuf plus string pointers plus copy of string including \0 */ - sp = smalloc(sizeof(*cb) + nf * sizeof(char*) + n + 1); - cb = (Cmdbuf*)sp; - cb->f = (char**)(&cb[1]); - cb->buf = (char*)(&cb->f[nf]); - - if(up!=nil && waserror()){ - free(cb); - nexterror(); - } - memmove(cb->buf, p, n); - if(up != nil) - poperror(); - - /* dump new line and null terminate */ - if(n > 0 && cb->buf[n-1] == '\n') - n--; - cb->buf[n] = '\0'; - - cb->nf = tokenize(cb->buf, cb->f, nf-1); - cb->f[cb->nf] = nil; - - return cb; -} - -/* - * Reconstruct original message, for error diagnostic - */ -void -cmderror(Cmdbuf *cb, char *s) -{ - int i; - char *p, *e; - - p = up->genbuf; - e = p+ERRMAX-10; - p = seprint(p, e, "%s \"", s); - for(i=0; i<cb->nf; i++){ - if(i > 0) - p = seprint(p, e, " "); - p = seprint(p, e, "%q", cb->f[i]); - } - strcpy(p, "\""); - error(up->genbuf); -} - -/* - * Look up entry in table - */ -Cmdtab* -lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab) -{ - int i; - Cmdtab *ct; - - if(cb->nf == 0) - error("empty control message"); - - for(ct = ctab, i=0; i<nctab; i++, ct++){ - if(strcmp(ct->cmd, "*") !=0) /* wildcard always matches */ - if(strcmp(ct->cmd, cb->f[0]) != 0) - continue; - if(ct->narg != 0 && ct->narg != cb->nf) - cmderror(cb, Ecmdargs); - return ct; - } - - cmderror(cb, "unknown control message"); - return nil; -} diff --git a/sys/src/cmd/unix/drawterm/kern/pgrp.c b/sys/src/cmd/unix/drawterm/kern/pgrp.c deleted file mode 100644 index 30b1f3e7b..000000000 --- a/sys/src/cmd/unix/drawterm/kern/pgrp.c +++ /dev/null @@ -1,272 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -static Ref pgrpid; -static Ref mountid; - -#ifdef NOTDEF -void -pgrpnote(ulong noteid, char *a, long n, int flag) -{ - Proc *p, *ep; - char buf[ERRMAX]; - - if(n >= ERRMAX-1) - error(Etoobig); - - memmove(buf, a, n); - buf[n] = 0; - p = proctab(0); - ep = p+conf.nproc; - for(; p < ep; p++) { - if(p->state == Dead) - continue; - if(up != p && p->noteid == noteid && p->kp == 0) { - qlock(&p->debug); - if(p->pid == 0 || p->noteid != noteid){ - qunlock(&p->debug); - continue; - } - if(!waserror()) { - postnote(p, 0, buf, flag); - poperror(); - } - qunlock(&p->debug); - } - } -} -#endif - -Pgrp* -newpgrp(void) -{ - Pgrp *p; - - p = smalloc(sizeof(Pgrp)); - p->ref.ref = 1; - p->pgrpid = incref(&pgrpid); - return p; -} - -Rgrp* -newrgrp(void) -{ - Rgrp *r; - - r = smalloc(sizeof(Rgrp)); - r->ref.ref = 1; - return r; -} - -void -closergrp(Rgrp *r) -{ - if(decref(&r->ref) == 0) - free(r); -} - -void -closepgrp(Pgrp *p) -{ - Mhead **h, **e, *f, *next; - - if(decref(&p->ref) != 0) - return; - - qlock(&p->debug); - wlock(&p->ns); - p->pgrpid = -1; - - e = &p->mnthash[MNTHASH]; - for(h = p->mnthash; h < e; h++) { - for(f = *h; f; f = next) { - wlock(&f->lock); - cclose(f->from); - mountfree(f->mount); - f->mount = nil; - next = f->hash; - wunlock(&f->lock); - putmhead(f); - } - } - wunlock(&p->ns); - qunlock(&p->debug); - free(p); -} - -void -pgrpinsert(Mount **order, Mount *m) -{ - Mount *f; - - m->order = 0; - if(*order == 0) { - *order = m; - return; - } - for(f = *order; f; f = f->order) { - if(m->mountid < f->mountid) { - m->order = f; - *order = m; - return; - } - order = &f->order; - } - *order = m; -} - -/* - * pgrpcpy MUST preserve the mountid allocation order of the parent group - */ -void -pgrpcpy(Pgrp *to, Pgrp *from) -{ - int i; - Mount *n, *m, **link, *order; - Mhead *f, **tom, **l, *mh; - - wlock(&from->ns); - order = 0; - tom = to->mnthash; - for(i = 0; i < MNTHASH; i++) { - l = tom++; - for(f = from->mnthash[i]; f; f = f->hash) { - rlock(&f->lock); - mh = newmhead(f->from); - *l = mh; - l = &mh->hash; - link = &mh->mount; - for(m = f->mount; m; m = m->next) { - n = newmount(mh, m->to, m->mflag, m->spec); - m->copy = n; - pgrpinsert(&order, m); - *link = n; - link = &n->next; - } - runlock(&f->lock); - } - } - /* - * Allocate mount ids in the same sequence as the parent group - */ - lock(&mountid.lk); - for(m = order; m; m = m->order) - m->copy->mountid = mountid.ref++; - unlock(&mountid.lk); - wunlock(&from->ns); -} - -Fgrp* -dupfgrp(Fgrp *f) -{ - Fgrp *new; - Chan *c; - int i; - - new = smalloc(sizeof(Fgrp)); - if(f == nil){ - new->fd = smalloc(DELTAFD*sizeof(Chan*)); - new->nfd = DELTAFD; - new->ref.ref = 1; - return new; - } - - lock(&f->ref.lk); - /* Make new fd list shorter if possible, preserving quantization */ - new->nfd = f->maxfd+1; - i = new->nfd%DELTAFD; - if(i != 0) - new->nfd += DELTAFD - i; - new->fd = malloc(new->nfd*sizeof(Chan*)); - if(new->fd == 0){ - unlock(&f->ref.lk); - error("no memory for fgrp"); - } - new->ref.ref = 1; - - new->maxfd = f->maxfd; - for(i = 0; i <= f->maxfd; i++) { - if((c = f->fd[i])){ - incref(&c->ref); - new->fd[i] = c; - } - } - unlock(&f->ref.lk); - - return new; -} - -void -closefgrp(Fgrp *f) -{ - int i; - Chan *c; - - if(f == 0) - return; - - if(decref(&f->ref) != 0) - return; - - for(i = 0; i <= f->maxfd; i++) - if((c = f->fd[i])) - cclose(c); - - free(f->fd); - free(f); -} - -Mount* -newmount(Mhead *mh, Chan *to, int flag, char *spec) -{ - Mount *m; - - m = smalloc(sizeof(Mount)); - m->to = to; - m->head = mh; - incref(&to->ref); - m->mountid = incref(&mountid); - m->mflag = flag; - if(spec != 0) - kstrdup(&m->spec, spec); - - return m; -} - -void -mountfree(Mount *m) -{ - Mount *f; - - while(m) { - f = m->next; - cclose(m->to); - m->mountid = 0; - free(m->spec); - free(m); - m = f; - } -} - -#ifdef NOTDEF -void -resrcwait(char *reason) -{ - char *p; - - if(up == 0) - panic("resrcwait"); - - p = up->psstate; - if(reason) { - up->psstate = reason; - print("%s\n", reason); - } - - tsleep(&up->sleep, return0, 0, 300); - up->psstate = p; -} -#endif diff --git a/sys/src/cmd/unix/drawterm/kern/posix.c b/sys/src/cmd/unix/drawterm/kern/posix.c deleted file mode 100644 index 069d6531f..000000000 --- a/sys/src/cmd/unix/drawterm/kern/posix.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Posix generic OS implementation for drawterm. - */ - -#include "u.h" - -#ifndef _XOPEN_SOURCE /* for Apple and OpenBSD; not sure if needed */ -#define _XOPEN_SOURCE 500 -#endif - -#include <pthread.h> -#include <time.h> -#include <sys/time.h> -#include <sys/select.h> -#include <signal.h> -#include <pwd.h> -#include <errno.h> - -#include "lib.h" -#include "dat.h" -#include "fns.h" - -typedef struct Oproc Oproc; -struct Oproc -{ - int nsleep; - int nwakeup; - pthread_mutex_t mutex; - pthread_cond_t cond; -}; - -static pthread_key_t prdakey; - -Proc* -_getproc(void) -{ - void *v; - - if((v = pthread_getspecific(prdakey)) == nil) - panic("cannot getspecific"); - return v; -} - -void -_setproc(Proc *p) -{ - if(pthread_setspecific(prdakey, p) != 0) - panic("cannot setspecific"); -} - -void -osinit(void) -{ - if(pthread_key_create(&prdakey, 0)) - panic("cannot pthread_key_create"); -} - -#undef pipe -void -osnewproc(Proc *p) -{ - Oproc *op; - pthread_mutexattr_t attr; - - op = (Oproc*)p->oproc; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); - pthread_mutex_init(&op->mutex, &attr); - pthread_mutexattr_destroy(&attr); - pthread_cond_init(&op->cond, 0); -} - -void -osmsleep(int ms) -{ - struct timeval tv; - - tv.tv_sec = ms / 1000; - tv.tv_usec = (ms % 1000) * 1000; /* micro */ - if(select(0, NULL, NULL, NULL, &tv) < 0) - panic("select"); -} - -void -osyield(void) -{ - sched_yield(); -} - -void -oserrstr(void) -{ - char *p; - - if((p = strerror(errno)) != nil) - strecpy(up->errstr, up->errstr+ERRMAX, p); - else - snprint(up->errstr, ERRMAX, "unix error %d", errno); -} - -void -oserror(void) -{ - oserrstr(); - nexterror(); -} - -static void* tramp(void*); - -void -osproc(Proc *p) -{ - pthread_t pid; - - if(pthread_create(&pid, nil, tramp, p)){ - oserrstr(); - panic("osproc: %r"); - } - sched_yield(); -} - -static void* -tramp(void *vp) -{ - Proc *p; - - p = vp; - if(pthread_setspecific(prdakey, p)) - panic("cannot setspecific"); - (*p->fn)(p->arg); - /* BUG: leaks Proc */ - pthread_setspecific(prdakey, 0); - pthread_exit(0); - return 0; -} - -void -procsleep(void) -{ - Proc *p; - Oproc *op; - - p = up; - op = (Oproc*)p->oproc; - pthread_mutex_lock(&op->mutex); - op->nsleep++; - while(op->nsleep > op->nwakeup) - pthread_cond_wait(&op->cond, &op->mutex); - pthread_mutex_unlock(&op->mutex); -} - -void -procwakeup(Proc *p) -{ - Oproc *op; - - op = (Oproc*)p->oproc; - pthread_mutex_lock(&op->mutex); - op->nwakeup++; - if(op->nwakeup == op->nsleep) - pthread_cond_signal(&op->cond); - pthread_mutex_unlock(&op->mutex); -} - -int randfd; -#undef open -void -randominit(void) -{ -#ifdef USE_RANDOM - srandom(getpid()+fastticks(nil)+ticks()); -#else - if((randfd = open("/dev/urandom", OREAD)) < 0) - if((randfd = open("/dev/random", OREAD)) < 0) - panic("open /dev/random: %r"); -#endif -} - -#undef read -ulong -randomread(void *v, ulong n) -{ -#ifdef USE_RANDOM - int i; - - for(i=0; i<n; i++) - ((uchar*)v)[i] = random(); - return n; -#else - int m; - - if((m = read(randfd, v, n)) != n) - panic("short read from /dev/random: %d but %d", n, m); - return m; -#endif -} - -#undef time -long -seconds(void) -{ - return time(0); -} - -ulong -ticks(void) -{ - static long sec0 = 0, usec0; - struct timeval t; - - if(gettimeofday(&t, nil) < 0) - return 0; - if(sec0 == 0){ - sec0 = t.tv_sec; - usec0 = t.tv_usec; - } - return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000; -} - -long -showfilewrite(char *a, int n) -{ - error("not implemented"); - return -1; -} diff --git a/sys/src/cmd/unix/drawterm/kern/procinit.c b/sys/src/cmd/unix/drawterm/kern/procinit.c deleted file mode 100644 index b2299d963..000000000 --- a/sys/src/cmd/unix/drawterm/kern/procinit.c +++ /dev/null @@ -1,67 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -Rgrp *thergrp; - -void -procinit0(void) -{ - Proc *p; - - p = newproc(); - p->fgrp = dupfgrp(nil); - p->rgrp = newrgrp(); - p->pgrp = newpgrp(); - _setproc(p); - - up->slash = namec("#/", Atodir, 0, 0); - cnameclose(up->slash->name); - up->slash->name = newcname("/"); - up->dot = cclone(up->slash); -} - -Ref pidref; - -Proc* -newproc(void) -{ - Proc *p; - - p = mallocz(sizeof(Proc), 1); - p->pid = incref(&pidref); - strcpy(p->user, eve); - p->syserrstr = p->errbuf0; - p->errstr = p->errbuf1; - strcpy(p->text, "drawterm"); - osnewproc(p); - return p; -} - -int -kproc(char *name, void (*fn)(void*), void *arg) -{ - Proc *p; - - p = newproc(); - p->fn = fn; - p->arg = arg; - p->slash = cclone(up->slash); - p->dot = cclone(up->dot); - p->rgrp = up->rgrp; - if(p->rgrp) - incref(&p->rgrp->ref); - p->pgrp = up->pgrp; - if(up->pgrp) - incref(&up->pgrp->ref); - p->fgrp = up->fgrp; - if(p->fgrp) - incref(&p->fgrp->ref); - strecpy(p->text, p->text+sizeof p->text, name); - - osproc(p); - return p->pid; -} - diff --git a/sys/src/cmd/unix/drawterm/kern/qio.c b/sys/src/cmd/unix/drawterm/kern/qio.c deleted file mode 100644 index edee200be..000000000 --- a/sys/src/cmd/unix/drawterm/kern/qio.c +++ /dev/null @@ -1,1524 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -static ulong padblockcnt; -static ulong concatblockcnt; -static ulong pullupblockcnt; -static ulong copyblockcnt; -static ulong consumecnt; -static ulong producecnt; -static ulong qcopycnt; - -static int debugging; - -#define QDEBUG if(0) - -/* - * IO queues - */ -struct Queue -{ - Lock lk; - - Block* bfirst; /* buffer */ - Block* blast; - - int len; /* bytes allocated to queue */ - int dlen; /* data bytes in queue */ - int limit; /* max bytes in queue */ - int inilim; /* initial limit */ - int state; - int noblock; /* true if writes return immediately when q full */ - int eof; /* number of eofs read by user */ - - void (*kick)(void*); /* restart output */ - void (*bypass)(void*, Block*); /* bypass queue altogether */ - void* arg; /* argument to kick */ - - QLock rlock; /* mutex for reading processes */ - Rendez rr; /* process waiting to read */ - QLock wlock; /* mutex for writing processes */ - Rendez wr; /* process waiting to write */ - - char err[ERRMAX]; -}; - -enum -{ - Maxatomic = 64*1024, -}; - -uint qiomaxatomic = Maxatomic; - -void -ixsummary(void) -{ - debugging ^= 1; - iallocsummary(); - print("pad %lud, concat %lud, pullup %lud, copy %lud\n", - padblockcnt, concatblockcnt, pullupblockcnt, copyblockcnt); - print("consume %lud, produce %lud, qcopy %lud\n", - consumecnt, producecnt, qcopycnt); -} - -/* - * free a list of blocks - */ -void -freeblist(Block *b) -{ - Block *next; - - for(; b != 0; b = next){ - next = b->next; - b->next = 0; - freeb(b); - } -} - -/* - * pad a block to the front (or the back if size is negative) - */ -Block* -padblock(Block *bp, int size) -{ - int n; - Block *nbp; - - QDEBUG checkb(bp, "padblock 1"); - if(size >= 0){ - if(bp->rp - bp->base >= size){ - bp->rp -= size; - return bp; - } - - if(bp->next) - panic("padblock 0x%p", getcallerpc(&bp)); - n = BLEN(bp); - padblockcnt++; - nbp = allocb(size+n); - nbp->rp += size; - nbp->wp = nbp->rp; - memmove(nbp->wp, bp->rp, n); - nbp->wp += n; - freeb(bp); - nbp->rp -= size; - } else { - size = -size; - - if(bp->next) - panic("padblock 0x%p", getcallerpc(&bp)); - - if(bp->lim - bp->wp >= size) - return bp; - - n = BLEN(bp); - padblockcnt++; - nbp = allocb(size+n); - memmove(nbp->wp, bp->rp, n); - nbp->wp += n; - freeb(bp); - } - QDEBUG checkb(nbp, "padblock 1"); - return nbp; -} - -/* - * return count of bytes in a string of blocks - */ -int -blocklen(Block *bp) -{ - int len; - - len = 0; - while(bp) { - len += BLEN(bp); - bp = bp->next; - } - return len; -} - -/* - * return count of space in blocks - */ -int -blockalloclen(Block *bp) -{ - int len; - - len = 0; - while(bp) { - len += BALLOC(bp); - bp = bp->next; - } - return len; -} - -/* - * copy the string of blocks into - * a single block and free the string - */ -Block* -concatblock(Block *bp) -{ - int len; - Block *nb, *f; - - if(bp->next == 0) - return bp; - - nb = allocb(blocklen(bp)); - for(f = bp; f; f = f->next) { - len = BLEN(f); - memmove(nb->wp, f->rp, len); - nb->wp += len; - } - concatblockcnt += BLEN(nb); - freeblist(bp); - QDEBUG checkb(nb, "concatblock 1"); - return nb; -} - -/* - * make sure the first block has at least n bytes - */ -Block* -pullupblock(Block *bp, int n) -{ - int i; - Block *nbp; - - /* - * this should almost always be true, it's - * just to avoid every caller checking. - */ - if(BLEN(bp) >= n) - return bp; - - /* - * if not enough room in the first block, - * add another to the front of the list. - */ - if(bp->lim - bp->rp < n){ - nbp = allocb(n); - nbp->next = bp; - bp = nbp; - } - - /* - * copy bytes from the trailing blocks into the first - */ - n -= BLEN(bp); - while((nbp = bp->next)){ - i = BLEN(nbp); - if(i > n) { - memmove(bp->wp, nbp->rp, n); - pullupblockcnt++; - bp->wp += n; - nbp->rp += n; - QDEBUG checkb(bp, "pullupblock 1"); - return bp; - } else { - /* shouldn't happen but why crash if it does */ - if(i < 0){ - print("pullup negative length packet\n"); - i = 0; - } - memmove(bp->wp, nbp->rp, i); - pullupblockcnt++; - bp->wp += i; - bp->next = nbp->next; - nbp->next = 0; - freeb(nbp); - n -= i; - if(n == 0){ - QDEBUG checkb(bp, "pullupblock 2"); - return bp; - } - } - } - freeb(bp); - return 0; -} - -/* - * make sure the first block has at least n bytes - */ -Block* -pullupqueue(Queue *q, int n) -{ - Block *b; - - if(BLEN(q->bfirst) >= n) - return q->bfirst; - q->bfirst = pullupblock(q->bfirst, n); - for(b = q->bfirst; b != nil && b->next != nil; b = b->next) - ; - q->blast = b; - return q->bfirst; -} - -/* - * trim to len bytes starting at offset - */ -Block * -trimblock(Block *bp, int offset, int len) -{ - ulong l; - Block *nb, *startb; - - QDEBUG checkb(bp, "trimblock 1"); - if(blocklen(bp) < offset+len) { - freeblist(bp); - return nil; - } - - while((l = BLEN(bp)) < offset) { - offset -= l; - nb = bp->next; - bp->next = nil; - freeb(bp); - bp = nb; - } - - startb = bp; - bp->rp += offset; - - while((l = BLEN(bp)) < len) { - len -= l; - bp = bp->next; - } - - bp->wp -= (BLEN(bp) - len); - - if(bp->next) { - freeblist(bp->next); - bp->next = nil; - } - - return startb; -} - -/* - * copy 'count' bytes into a new block - */ -Block* -copyblock(Block *bp, int count) -{ - int l; - Block *nbp; - - QDEBUG checkb(bp, "copyblock 0"); - nbp = allocb(count); - for(; count > 0 && bp != 0; bp = bp->next){ - l = BLEN(bp); - if(l > count) - l = count; - memmove(nbp->wp, bp->rp, l); - nbp->wp += l; - count -= l; - } - if(count > 0){ - memset(nbp->wp, 0, count); - nbp->wp += count; - } - copyblockcnt++; - QDEBUG checkb(nbp, "copyblock 1"); - - return nbp; -} - -Block* -adjustblock(Block* bp, int len) -{ - int n; - Block *nbp; - - if(len < 0){ - freeb(bp); - return nil; - } - - if(bp->rp+len > bp->lim){ - nbp = copyblock(bp, len); - freeblist(bp); - QDEBUG checkb(nbp, "adjustblock 1"); - - return nbp; - } - - n = BLEN(bp); - if(len > n) - memset(bp->wp, 0, len-n); - bp->wp = bp->rp+len; - QDEBUG checkb(bp, "adjustblock 2"); - - return bp; -} - - -/* - * throw away up to count bytes from a - * list of blocks. Return count of bytes - * thrown away. - */ -int -pullblock(Block **bph, int count) -{ - Block *bp; - int n, bytes; - - bytes = 0; - if(bph == nil) - return 0; - - while(*bph != nil && count != 0) { - bp = *bph; - n = BLEN(bp); - if(count < n) - n = count; - bytes += n; - count -= n; - bp->rp += n; - QDEBUG checkb(bp, "pullblock "); - if(BLEN(bp) == 0) { - *bph = bp->next; - bp->next = nil; - freeb(bp); - } - } - return bytes; -} - -/* - * get next block from a queue, return null if nothing there - */ -Block* -qget(Queue *q) -{ - int dowakeup; - Block *b; - - /* sync with qwrite */ - ilock(&q->lk); - - b = q->bfirst; - if(b == nil){ - q->state |= Qstarve; - iunlock(&q->lk); - return nil; - } - q->bfirst = b->next; - b->next = 0; - q->len -= BALLOC(b); - q->dlen -= BLEN(b); - QDEBUG checkb(b, "qget"); - - /* if writer flow controlled, restart */ - if((q->state & Qflow) && q->len < q->limit/2){ - q->state &= ~Qflow; - dowakeup = 1; - } else - dowakeup = 0; - - iunlock(&q->lk); - - if(dowakeup) - wakeup(&q->wr); - - return b; -} - -/* - * throw away the next 'len' bytes in the queue - */ -int -qdiscard(Queue *q, int len) -{ - Block *b; - int dowakeup, n, sofar; - - ilock(&q->lk); - for(sofar = 0; sofar < len; sofar += n){ - b = q->bfirst; - if(b == nil) - break; - QDEBUG checkb(b, "qdiscard"); - n = BLEN(b); - if(n <= len - sofar){ - q->bfirst = b->next; - b->next = 0; - q->len -= BALLOC(b); - q->dlen -= BLEN(b); - freeb(b); - } else { - n = len - sofar; - b->rp += n; - q->dlen -= n; - } - } - - /* - * if writer flow controlled, restart - * - * This used to be - * q->len < q->limit/2 - * but it slows down tcp too much for certain write sizes. - * I really don't understand it completely. It may be - * due to the queue draining so fast that the transmission - * stalls waiting for the app to produce more data. - presotto - */ - if((q->state & Qflow) && q->len < q->limit){ - q->state &= ~Qflow; - dowakeup = 1; - } else - dowakeup = 0; - - iunlock(&q->lk); - - if(dowakeup) - wakeup(&q->wr); - - return sofar; -} - -/* - * Interrupt level copy out of a queue, return # bytes copied. - */ -int -qconsume(Queue *q, void *vp, int len) -{ - Block *b; - int n, dowakeup; - uchar *p = vp; - Block *tofree = nil; - - /* sync with qwrite */ - ilock(&q->lk); - - for(;;) { - b = q->bfirst; - if(b == 0){ - q->state |= Qstarve; - iunlock(&q->lk); - return -1; - } - QDEBUG checkb(b, "qconsume 1"); - - n = BLEN(b); - if(n > 0) - break; - q->bfirst = b->next; - q->len -= BALLOC(b); - - /* remember to free this */ - b->next = tofree; - tofree = b; - }; - - if(n < len) - len = n; - memmove(p, b->rp, len); - consumecnt += n; - b->rp += len; - q->dlen -= len; - - /* discard the block if we're done with it */ - if((q->state & Qmsg) || len == n){ - q->bfirst = b->next; - b->next = 0; - q->len -= BALLOC(b); - q->dlen -= BLEN(b); - - /* remember to free this */ - b->next = tofree; - tofree = b; - } - - /* if writer flow controlled, restart */ - if((q->state & Qflow) && q->len < q->limit/2){ - q->state &= ~Qflow; - dowakeup = 1; - } else - dowakeup = 0; - - iunlock(&q->lk); - - if(dowakeup) - wakeup(&q->wr); - - if(tofree != nil) - freeblist(tofree); - - return len; -} - -int -qpass(Queue *q, Block *b) -{ - int dlen, len, dowakeup; - - /* sync with qread */ - dowakeup = 0; - ilock(&q->lk); - if(q->len >= q->limit){ - freeblist(b); - iunlock(&q->lk); - return -1; - } - if(q->state & Qclosed){ - freeblist(b); - iunlock(&q->lk); - return BALLOC(b); - } - - /* add buffer to queue */ - if(q->bfirst) - q->blast->next = b; - else - q->bfirst = b; - len = BALLOC(b); - dlen = BLEN(b); - QDEBUG checkb(b, "qpass"); - while(b->next){ - b = b->next; - QDEBUG checkb(b, "qpass"); - len += BALLOC(b); - dlen += BLEN(b); - } - q->blast = b; - q->len += len; - q->dlen += dlen; - - if(q->len >= q->limit/2) - q->state |= Qflow; - - if(q->state & Qstarve){ - q->state &= ~Qstarve; - dowakeup = 1; - } - iunlock(&q->lk); - - if(dowakeup) - wakeup(&q->rr); - - return len; -} - -int -qpassnolim(Queue *q, Block *b) -{ - int dlen, len, dowakeup; - - /* sync with qread */ - dowakeup = 0; - ilock(&q->lk); - - if(q->state & Qclosed){ - freeblist(b); - iunlock(&q->lk); - return BALLOC(b); - } - - /* add buffer to queue */ - if(q->bfirst) - q->blast->next = b; - else - q->bfirst = b; - len = BALLOC(b); - dlen = BLEN(b); - QDEBUG checkb(b, "qpass"); - while(b->next){ - b = b->next; - QDEBUG checkb(b, "qpass"); - len += BALLOC(b); - dlen += BLEN(b); - } - q->blast = b; - q->len += len; - q->dlen += dlen; - - if(q->len >= q->limit/2) - q->state |= Qflow; - - if(q->state & Qstarve){ - q->state &= ~Qstarve; - dowakeup = 1; - } - iunlock(&q->lk); - - if(dowakeup) - wakeup(&q->rr); - - return len; -} - -/* - * if the allocated space is way out of line with the used - * space, reallocate to a smaller block - */ -Block* -packblock(Block *bp) -{ - Block **l, *nbp; - int n; - - for(l = &bp; *l; l = &(*l)->next){ - nbp = *l; - n = BLEN(nbp); - if((n<<2) < BALLOC(nbp)){ - *l = allocb(n); - memmove((*l)->wp, nbp->rp, n); - (*l)->wp += n; - (*l)->next = nbp->next; - freeb(nbp); - } - } - - return bp; -} - -int -qproduce(Queue *q, void *vp, int len) -{ - Block *b; - int dowakeup; - uchar *p = vp; - - /* sync with qread */ - dowakeup = 0; - ilock(&q->lk); - - /* no waiting receivers, room in buffer? */ - if(q->len >= q->limit){ - q->state |= Qflow; - iunlock(&q->lk); - return -1; - } - - /* save in buffer */ - b = iallocb(len); - if(b == 0){ - iunlock(&q->lk); - return 0; - } - memmove(b->wp, p, len); - producecnt += len; - b->wp += len; - if(q->bfirst) - q->blast->next = b; - else - q->bfirst = b; - q->blast = b; - /* b->next = 0; done by iallocb() */ - q->len += BALLOC(b); - q->dlen += BLEN(b); - QDEBUG checkb(b, "qproduce"); - - if(q->state & Qstarve){ - q->state &= ~Qstarve; - dowakeup = 1; - } - - if(q->len >= q->limit) - q->state |= Qflow; - iunlock(&q->lk); - - if(dowakeup) - wakeup(&q->rr); - - return len; -} - -/* - * copy from offset in the queue - */ -Block* -qcopy(Queue *q, int len, ulong offset) -{ - int sofar; - int n; - Block *b, *nb; - uchar *p; - - nb = allocb(len); - - ilock(&q->lk); - - /* go to offset */ - b = q->bfirst; - for(sofar = 0; ; sofar += n){ - if(b == nil){ - iunlock(&q->lk); - return nb; - } - n = BLEN(b); - if(sofar + n > offset){ - p = b->rp + offset - sofar; - n -= offset - sofar; - break; - } - QDEBUG checkb(b, "qcopy"); - b = b->next; - } - - /* copy bytes from there */ - for(sofar = 0; sofar < len;){ - if(n > len - sofar) - n = len - sofar; - memmove(nb->wp, p, n); - qcopycnt += n; - sofar += n; - nb->wp += n; - b = b->next; - if(b == nil) - break; - n = BLEN(b); - p = b->rp; - } - iunlock(&q->lk); - - return nb; -} - -/* - * called by non-interrupt code - */ -Queue* -qopen(int limit, int msg, void (*kick)(void*), void *arg) -{ - Queue *q; - - q = malloc(sizeof(Queue)); - if(q == 0) - return 0; - - q->limit = q->inilim = limit; - q->kick = kick; - q->arg = arg; - q->state = msg; - - q->state |= Qstarve; - q->eof = 0; - q->noblock = 0; - - return q; -} - -/* open a queue to be bypassed */ -Queue* -qbypass(void (*bypass)(void*, Block*), void *arg) -{ - Queue *q; - - q = malloc(sizeof(Queue)); - if(q == 0) - return 0; - - q->limit = 0; - q->arg = arg; - q->bypass = bypass; - q->state = 0; - - return q; -} - -static int -notempty(void *a) -{ - Queue *q = a; - - return (q->state & Qclosed) || q->bfirst != 0; -} - -/* - * wait for the queue to be non-empty or closed. - * called with q ilocked. - */ -static int -qwait(Queue *q) -{ - /* wait for data */ - for(;;){ - if(q->bfirst != nil) - break; - - if(q->state & Qclosed){ - if(++q->eof > 3) - return -1; - if(*q->err && strcmp(q->err, Ehungup) != 0) - return -1; - return 0; - } - - q->state |= Qstarve; /* flag requesting producer to wake me */ - iunlock(&q->lk); - sleep(&q->rr, notempty, q); - ilock(&q->lk); - } - return 1; -} - -/* - * add a block list to a queue - */ -void -qaddlist(Queue *q, Block *b) -{ - /* queue the block */ - if(q->bfirst) - q->blast->next = b; - else - q->bfirst = b; - q->len += blockalloclen(b); - q->dlen += blocklen(b); - while(b->next) - b = b->next; - q->blast = b; -} - -/* - * called with q ilocked - */ -Block* -qremove(Queue *q) -{ - Block *b; - - b = q->bfirst; - if(b == nil) - return nil; - q->bfirst = b->next; - b->next = nil; - q->dlen -= BLEN(b); - q->len -= BALLOC(b); - QDEBUG checkb(b, "qremove"); - return b; -} - -/* - * copy the contents of a string of blocks into - * memory. emptied blocks are freed. return - * pointer to first unconsumed block. - */ -Block* -bl2mem(uchar *p, Block *b, int n) -{ - int i; - Block *next; - - for(; b != nil; b = next){ - i = BLEN(b); - if(i > n){ - memmove(p, b->rp, n); - b->rp += n; - return b; - } - memmove(p, b->rp, i); - n -= i; - p += i; - b->rp += i; - next = b->next; - freeb(b); - } - return nil; -} - -/* - * copy the contents of memory into a string of blocks. - * return nil on error. - */ -Block* -mem2bl(uchar *p, int len) -{ - int n; - Block *b, *first, **l; - - first = nil; - l = &first; - if(waserror()){ - freeblist(first); - nexterror(); - } - do { - n = len; - if(n > Maxatomic) - n = Maxatomic; - - *l = b = allocb(n); - /* setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]); */ - memmove(b->wp, p, n); - b->wp += n; - p += n; - len -= n; - l = &b->next; - } while(len > 0); - poperror(); - - return first; -} - -/* - * put a block back to the front of the queue - * called with q ilocked - */ -void -qputback(Queue *q, Block *b) -{ - b->next = q->bfirst; - if(q->bfirst == nil) - q->blast = b; - q->bfirst = b; - q->len += BALLOC(b); - q->dlen += BLEN(b); -} - -/* - * flow control, get producer going again - * called with q ilocked - */ -static void -qwakeup_iunlock(Queue *q) -{ - int dowakeup = 0; - - /* if writer flow controlled, restart */ - if((q->state & Qflow) && q->len < q->limit/2){ - q->state &= ~Qflow; - dowakeup = 1; - } - - iunlock(&q->lk); - - /* wakeup flow controlled writers */ - if(dowakeup){ - if(q->kick) - q->kick(q->arg); - wakeup(&q->wr); - } -} - -/* - * get next block from a queue (up to a limit) - */ -Block* -qbread(Queue *q, int len) -{ - Block *b, *nb; - int n; - - qlock(&q->rlock); - if(waserror()){ - qunlock(&q->rlock); - nexterror(); - } - - ilock(&q->lk); - switch(qwait(q)){ - case 0: - /* queue closed */ - iunlock(&q->lk); - qunlock(&q->rlock); - poperror(); - return nil; - case -1: - /* multiple reads on a closed queue */ - iunlock(&q->lk); - error(q->err); - } - - /* if we get here, there's at least one block in the queue */ - b = qremove(q); - n = BLEN(b); - - /* split block if it's too big and this is not a message queue */ - nb = b; - if(n > len){ - if((q->state&Qmsg) == 0){ - n -= len; - b = allocb(n); - memmove(b->wp, nb->rp+len, n); - b->wp += n; - qputback(q, b); - } - nb->wp = nb->rp + len; - } - - /* restart producer */ - qwakeup_iunlock(q); - - poperror(); - qunlock(&q->rlock); - return nb; -} - -/* - * read a queue. if no data is queued, post a Block - * and wait on its Rendez. - */ -long -qread(Queue *q, void *vp, int len) -{ - Block *b, *first, **l; - int m, n; - - qlock(&q->rlock); - if(waserror()){ - qunlock(&q->rlock); - nexterror(); - } - - ilock(&q->lk); -again: - switch(qwait(q)){ - case 0: - /* queue closed */ - iunlock(&q->lk); - qunlock(&q->rlock); - poperror(); - return 0; - case -1: - /* multiple reads on a closed queue */ - iunlock(&q->lk); - error(q->err); - } - - /* if we get here, there's at least one block in the queue */ - if(q->state & Qcoalesce){ - /* when coalescing, 0 length blocks just go away */ - b = q->bfirst; - if(BLEN(b) <= 0){ - freeb(qremove(q)); - goto again; - } - - /* grab the first block plus as many - * following blocks as will completely - * fit in the read. - */ - n = 0; - l = &first; - m = BLEN(b); - for(;;) { - *l = qremove(q); - l = &b->next; - n += m; - - b = q->bfirst; - if(b == nil) - break; - m = BLEN(b); - if(n+m > len) - break; - } - } else { - first = qremove(q); - n = BLEN(first); - } - - /* copy to user space outside of the ilock */ - iunlock(&q->lk); - b = bl2mem(vp, first, len); - ilock(&q->lk); - - /* take care of any left over partial block */ - if(b != nil){ - n -= BLEN(b); - if(q->state & Qmsg) - freeb(b); - else - qputback(q, b); - } - - /* restart producer */ - qwakeup_iunlock(q); - - poperror(); - qunlock(&q->rlock); - return n; -} - -static int -qnotfull(void *a) -{ - Queue *q = a; - - return q->len < q->limit || (q->state & Qclosed); -} - -ulong noblockcnt; - -/* - * add a block to a queue obeying flow control - */ -long -qbwrite(Queue *q, Block *b) -{ - int n, dowakeup; - - n = BLEN(b); - - if(q->bypass){ - (*q->bypass)(q->arg, b); - return n; - } - - dowakeup = 0; - qlock(&q->wlock); - if(waserror()){ - if(b != nil) - freeb(b); - qunlock(&q->wlock); - nexterror(); - } - - ilock(&q->lk); - - /* give up if the queue is closed */ - if(q->state & Qclosed){ - iunlock(&q->lk); - error(q->err); - } - - /* if nonblocking, don't queue over the limit */ - if(q->len >= q->limit){ - if(q->noblock){ - iunlock(&q->lk); - freeb(b); - noblockcnt += n; - qunlock(&q->wlock); - poperror(); - return n; - } - } - - /* queue the block */ - if(q->bfirst) - q->blast->next = b; - else - q->bfirst = b; - q->blast = b; - b->next = 0; - q->len += BALLOC(b); - q->dlen += n; - QDEBUG checkb(b, "qbwrite"); - b = nil; - - /* make sure other end gets awakened */ - if(q->state & Qstarve){ - q->state &= ~Qstarve; - dowakeup = 1; - } - iunlock(&q->lk); - - /* get output going again */ - if(q->kick && (dowakeup || (q->state&Qkick))) - q->kick(q->arg); - - /* wakeup anyone consuming at the other end */ - if(dowakeup){ - wakeup(&q->rr); - - /* if we just wokeup a higher priority process, let it run */ - /* - p = wakeup(&q->rr); - if(p != nil && p->priority > up->priority) - sched(); - */ - } - - /* - * flow control, wait for queue to get below the limit - * before allowing the process to continue and queue - * more. We do this here so that postnote can only - * interrupt us after the data has been queued. This - * means that things like 9p flushes and ssl messages - * will not be disrupted by software interrupts. - * - * Note - this is moderately dangerous since a process - * that keeps getting interrupted and rewriting will - * queue infinite crud. - */ - for(;;){ - if(q->noblock || qnotfull(q)) - break; - - ilock(&q->lk); - q->state |= Qflow; - iunlock(&q->lk); - sleep(&q->wr, qnotfull, q); - } - USED(b); - - qunlock(&q->wlock); - poperror(); - return n; -} - -/* - * write to a queue. only Maxatomic bytes at a time is atomic. - */ -int -qwrite(Queue *q, void *vp, int len) -{ - int n, sofar; - Block *b; - uchar *p = vp; - - QDEBUG if(!islo()) - print("qwrite hi %p\n", getcallerpc(&q)); - - sofar = 0; - do { - n = len-sofar; - if(n > Maxatomic) - n = Maxatomic; - - b = allocb(n); - /* setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]); */ - if(waserror()){ - freeb(b); - nexterror(); - } - memmove(b->wp, p+sofar, n); - poperror(); - b->wp += n; - - qbwrite(q, b); - - sofar += n; - } while(sofar < len && (q->state & Qmsg) == 0); - - return len; -} - -/* - * used by print() to write to a queue. Since we may be splhi or not in - * a process, don't qlock. - */ -int -qiwrite(Queue *q, void *vp, int len) -{ - int n, sofar, dowakeup; - Block *b; - uchar *p = vp; - - dowakeup = 0; - - sofar = 0; - do { - n = len-sofar; - if(n > Maxatomic) - n = Maxatomic; - - b = iallocb(n); - if(b == nil) - break; - memmove(b->wp, p+sofar, n); - b->wp += n; - - ilock(&q->lk); - - QDEBUG checkb(b, "qiwrite"); - if(q->bfirst) - q->blast->next = b; - else - q->bfirst = b; - q->blast = b; - q->len += BALLOC(b); - q->dlen += n; - - if(q->state & Qstarve){ - q->state &= ~Qstarve; - dowakeup = 1; - } - - iunlock(&q->lk); - - if(dowakeup){ - if(q->kick) - q->kick(q->arg); - wakeup(&q->rr); - } - - sofar += n; - } while(sofar < len && (q->state & Qmsg) == 0); - - return sofar; -} - -/* - * be extremely careful when calling this, - * as there is no reference accounting - */ -void -qfree(Queue *q) -{ - qclose(q); - free(q); -} - -/* - * Mark a queue as closed. No further IO is permitted. - * All blocks are released. - */ -void -qclose(Queue *q) -{ - Block *bfirst; - - if(q == nil) - return; - - /* mark it */ - ilock(&q->lk); - q->state |= Qclosed; - q->state &= ~(Qflow|Qstarve); - strcpy(q->err, Ehungup); - bfirst = q->bfirst; - q->bfirst = 0; - q->len = 0; - q->dlen = 0; - q->noblock = 0; - iunlock(&q->lk); - - /* free queued blocks */ - freeblist(bfirst); - - /* wake up readers/writers */ - wakeup(&q->rr); - wakeup(&q->wr); -} - -/* - * Mark a queue as closed. Wakeup any readers. Don't remove queued - * blocks. - */ -void -qhangup(Queue *q, char *msg) -{ - /* mark it */ - ilock(&q->lk); - q->state |= Qclosed; - if(msg == 0 || *msg == 0) - strcpy(q->err, Ehungup); - else - strncpy(q->err, msg, ERRMAX-1); - iunlock(&q->lk); - - /* wake up readers/writers */ - wakeup(&q->rr); - wakeup(&q->wr); -} - -/* - * return non-zero if the q is hungup - */ -int -qisclosed(Queue *q) -{ - return q->state & Qclosed; -} - -/* - * mark a queue as no longer hung up - */ -void -qreopen(Queue *q) -{ - ilock(&q->lk); - q->state &= ~Qclosed; - q->state |= Qstarve; - q->eof = 0; - q->limit = q->inilim; - iunlock(&q->lk); -} - -/* - * return bytes queued - */ -int -qlen(Queue *q) -{ - return q->dlen; -} - -/* - * return space remaining before flow control - */ -int -qwindow(Queue *q) -{ - int l; - - l = q->limit - q->len; - if(l < 0) - l = 0; - return l; -} - -/* - * return true if we can read without blocking - */ -int -qcanread(Queue *q) -{ - return q->bfirst!=0; -} - -/* - * change queue limit - */ -void -qsetlimit(Queue *q, int limit) -{ - q->limit = limit; -} - -/* - * set blocking/nonblocking - */ -void -qnoblock(Queue *q, int onoff) -{ - q->noblock = onoff; -} - -/* - * flush the output queue - */ -void -qflush(Queue *q) -{ - Block *bfirst; - - /* mark it */ - ilock(&q->lk); - bfirst = q->bfirst; - q->bfirst = 0; - q->len = 0; - q->dlen = 0; - iunlock(&q->lk); - - /* free queued blocks */ - freeblist(bfirst); - - /* wake up readers/writers */ - wakeup(&q->wr); -} - -int -qfull(Queue *q) -{ - return q->state & Qflow; -} - -int -qstate(Queue *q) -{ - return q->state; -} diff --git a/sys/src/cmd/unix/drawterm/kern/qlock.c b/sys/src/cmd/unix/drawterm/kern/qlock.c deleted file mode 100644 index fdbeaeac3..000000000 --- a/sys/src/cmd/unix/drawterm/kern/qlock.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" - -static void -queue(Proc **first, Proc **last) -{ - Proc *t; - - t = *last; - if(t == 0) - *first = up; - else - t->qnext = up; - *last = up; - up->qnext = 0; -} - -static Proc* -dequeue(Proc **first, Proc **last) -{ - Proc *t; - - t = *first; - if(t == 0) - return 0; - *first = t->qnext; - if(*first == 0) - *last = 0; - return t; -} - -void -qlock(QLock *q) -{ - lock(&q->lk); - - if(q->hold == 0) { - q->hold = up; - unlock(&q->lk); - return; - } - - /* - * Can't assert this because of RWLock - assert(q->hold != up); - */ - - queue((Proc**)&q->first, (Proc**)&q->last); - unlock(&q->lk); - procsleep(); -} - -int -canqlock(QLock *q) -{ - lock(&q->lk); - if(q->hold == 0) { - q->hold = up; - unlock(&q->lk); - return 1; - } - unlock(&q->lk); - return 0; -} - -void -qunlock(QLock *q) -{ - Proc *p; - - lock(&q->lk); - /* - * Can't assert this because of RWlock - assert(q->hold == CT); - */ - p = dequeue((Proc**)&q->first, (Proc**)&q->last); - if(p) { - q->hold = p; - unlock(&q->lk); - procwakeup(p); - } else { - q->hold = 0; - unlock(&q->lk); - } -} - -int -holdqlock(QLock *q) -{ - return q->hold == up; -} - diff --git a/sys/src/cmd/unix/drawterm/kern/rendez.c b/sys/src/cmd/unix/drawterm/kern/rendez.c deleted file mode 100644 index 6a9ad174e..000000000 --- a/sys/src/cmd/unix/drawterm/kern/rendez.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -void -sleep(Rendez *r, int (*f)(void*), void *arg) -{ - int s; - - s = splhi(); - - lock(&r->lk); - lock(&up->rlock); - if(r->p){ - print("double sleep %lud %lud\n", r->p->pid, up->pid); - dumpstack(); - } - - /* - * Wakeup only knows there may be something to do by testing - * r->p in order to get something to lock on. - * Flush that information out to memory in case the sleep is - * committed. - */ - r->p = up; - - if((*f)(arg) || up->notepending){ - /* - * if condition happened or a note is pending - * never mind - */ - r->p = nil; - unlock(&up->rlock); - unlock(&r->lk); - } else { - /* - * now we are committed to - * change state and call scheduler - */ - up->state = Wakeme; - up->r = r; - - /* statistics */ - /* m->cs++; */ - - unlock(&up->rlock); - unlock(&r->lk); - - procsleep(); - } - - if(up->notepending) { - up->notepending = 0; - splx(s); - error(Eintr); - } - - splx(s); -} - -Proc* -wakeup(Rendez *r) -{ - Proc *p; - int s; - - s = splhi(); - - lock(&r->lk); - p = r->p; - - if(p != nil){ - lock(&p->rlock); - if(p->state != Wakeme || p->r != r) - panic("wakeup: state"); - r->p = nil; - p->r = nil; - p->state = Running; - procwakeup(p); - unlock(&p->rlock); - } - unlock(&r->lk); - - splx(s); - - return p; -} - diff --git a/sys/src/cmd/unix/drawterm/kern/rwlock.c b/sys/src/cmd/unix/drawterm/kern/rwlock.c deleted file mode 100644 index 3381957a3..000000000 --- a/sys/src/cmd/unix/drawterm/kern/rwlock.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -void -rlock(RWlock *l) -{ - qlock(&l->x); /* wait here for writers and exclusion */ - lock(&l->lk); - l->readers++; - canqlock(&l->k); /* block writers if we are the first reader */ - unlock(&l->lk); - qunlock(&l->x); -} - -void -runlock(RWlock *l) -{ - lock(&l->lk); - if(--l->readers == 0) /* last reader out allows writers */ - qunlock(&l->k); - unlock(&l->lk); -} - -void -wlock(RWlock *l) -{ - qlock(&l->x); /* wait here for writers and exclusion */ - qlock(&l->k); /* wait here for last reader */ -} - -void -wunlock(RWlock *l) -{ - qunlock(&l->k); - qunlock(&l->x); -} diff --git a/sys/src/cmd/unix/drawterm/kern/screen.h b/sys/src/cmd/unix/drawterm/kern/screen.h deleted file mode 100644 index dfdc12de5..000000000 --- a/sys/src/cmd/unix/drawterm/kern/screen.h +++ /dev/null @@ -1,63 +0,0 @@ -typedef struct Mouseinfo Mouseinfo; -typedef struct Mousestate Mousestate; -typedef struct Cursorinfo Cursorinfo; -typedef struct Screeninfo Screeninfo; - -#define Mousequeue 16 /* queue can only have Mousequeue-1 elements */ -#define Mousewindow 500 /* mouse event window in millisec */ - -struct Mousestate { - int buttons; - Point xy; - ulong msec; -}; - -struct Mouseinfo { - Lock lk; - Mousestate queue[Mousequeue]; - int ri, wi; - int lastb; - int trans; - int open; - Rendez r; -}; - -struct Cursorinfo { - Lock lk; - Point offset; - uchar clr[2*16]; - uchar set[2*16]; -}; - -struct Screeninfo { - Lock lk; - Memimage *newsoft; - int reshaped; - int depth; - int dibtype; -}; - -extern Memimage *gscreen; -extern Mouseinfo mouse; -extern Cursorinfo cursor; -extern Screeninfo screen; - -void screeninit(void); -void screenload(Rectangle, int, uchar *, Point, int); - -void getcolor(ulong, ulong*, ulong*, ulong*); -void setcolor(ulong, ulong, ulong, ulong); - -void refreshrect(Rectangle); - -void cursorarrow(void); -void setcursor(void); -void mouseset(Point); -void drawflushr(Rectangle); -void flushmemscreen(Rectangle); -uchar *attachscreen(Rectangle*, ulong*, int*, int*, int*, void**); - -void drawqlock(void); -void drawqunlock(void); -int drawcanqlock(void); -void terminit(void); diff --git a/sys/src/cmd/unix/drawterm/kern/sleep.c b/sys/src/cmd/unix/drawterm/kern/sleep.c deleted file mode 100644 index 6a9ad174e..000000000 --- a/sys/src/cmd/unix/drawterm/kern/sleep.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -void -sleep(Rendez *r, int (*f)(void*), void *arg) -{ - int s; - - s = splhi(); - - lock(&r->lk); - lock(&up->rlock); - if(r->p){ - print("double sleep %lud %lud\n", r->p->pid, up->pid); - dumpstack(); - } - - /* - * Wakeup only knows there may be something to do by testing - * r->p in order to get something to lock on. - * Flush that information out to memory in case the sleep is - * committed. - */ - r->p = up; - - if((*f)(arg) || up->notepending){ - /* - * if condition happened or a note is pending - * never mind - */ - r->p = nil; - unlock(&up->rlock); - unlock(&r->lk); - } else { - /* - * now we are committed to - * change state and call scheduler - */ - up->state = Wakeme; - up->r = r; - - /* statistics */ - /* m->cs++; */ - - unlock(&up->rlock); - unlock(&r->lk); - - procsleep(); - } - - if(up->notepending) { - up->notepending = 0; - splx(s); - error(Eintr); - } - - splx(s); -} - -Proc* -wakeup(Rendez *r) -{ - Proc *p; - int s; - - s = splhi(); - - lock(&r->lk); - p = r->p; - - if(p != nil){ - lock(&p->rlock); - if(p->state != Wakeme || p->r != r) - panic("wakeup: state"); - r->p = nil; - p->r = nil; - p->state = Running; - procwakeup(p); - unlock(&p->rlock); - } - unlock(&r->lk); - - splx(s); - - return p; -} - diff --git a/sys/src/cmd/unix/drawterm/kern/smalloc.c b/sys/src/cmd/unix/drawterm/kern/smalloc.c deleted file mode 100644 index 314f3c850..000000000 --- a/sys/src/cmd/unix/drawterm/kern/smalloc.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -void* -smalloc(ulong n) -{ - return mallocz(n, 1); -} - -void* -malloc(ulong n) -{ - return mallocz(n, 1); -} - diff --git a/sys/src/cmd/unix/drawterm/kern/stub.c b/sys/src/cmd/unix/drawterm/kern/stub.c deleted file mode 100644 index d9c690638..000000000 --- a/sys/src/cmd/unix/drawterm/kern/stub.c +++ /dev/null @@ -1,171 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -void -mallocsummary(void) -{ -} - -void -pagersummary(void) -{ -} - -int -iseve(void) -{ - return 1; -} - -void -setswapchan(Chan *c) -{ - USED(c); -} - -void -splx(int x) -{ - USED(x); -} - -int -splhi(void) -{ - return 0; -} - -int -spllo(void) -{ - return 0; -} - -void -procdump(void) -{ -} - -void -scheddump(void) -{ -} - -void -killbig(void) -{ -} - -void -dumpstack(void) -{ -} - -void -xsummary(void) -{ -} - -void -rebootcmd(int argc, char **argv) -{ - USED(argc); - USED(argv); -} - -void -kickpager(void) -{ -} - -int -userwrite(char *a, int n) -{ - error(Eperm); - return 0; -} - -vlong -todget(vlong *p) -{ - if(p) - *p = 0; - return 0; -} - -void -todset(vlong a, vlong b, int c) -{ - USED(a); - USED(b); - USED(c); -} - -void -todsetfreq(vlong a) -{ - USED(a); -} - -long -hostdomainwrite(char *a, int n) -{ - USED(a); - USED(n); - error(Eperm); - return 0; -} - -long -hostownerwrite(char *a, int n) -{ - USED(a); - USED(n); - error(Eperm); - return 0; -} - -void -todinit(void) -{ -} - -void -rdb(void) -{ -} - -void -setmalloctag(void *v, uintptr tag) -{ - USED(v); - USED(tag); -} - -int -postnote(Proc *p, int x, char *msg, int flag) -{ - USED(p); - USED(x); - USED(msg); - USED(flag); - return 0; -} - -void -exhausted(char *s) -{ - panic("out of %s", s); -} - -uvlong -fastticks(uvlong *v) -{ - if(v) - *v = 1; - return 0; -} - diff --git a/sys/src/cmd/unix/drawterm/kern/sysfile.c b/sys/src/cmd/unix/drawterm/kern/sysfile.c deleted file mode 100644 index 18dadbcda..000000000 --- a/sys/src/cmd/unix/drawterm/kern/sysfile.c +++ /dev/null @@ -1,1244 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#include "user.h" -#undef open -#undef mount -#undef read -#undef write -#undef seek -#undef stat -#undef wstat -#undef remove -#undef close -#undef fstat -#undef fwstat - -/* - * The sys*() routines needn't poperror() as they return directly to syscall(). - */ - -static void -unlockfgrp(Fgrp *f) -{ - int ex; - - ex = f->exceed; - f->exceed = 0; - unlock(&f->ref.lk); - if(ex) - pprint("warning: process exceeds %d file descriptors\n", ex); -} - -int -growfd(Fgrp *f, int fd) /* fd is always >= 0 */ -{ - Chan **newfd, **oldfd; - - if(fd < f->nfd) - return 0; - if(fd >= f->nfd+DELTAFD) - return -1; /* out of range */ - /* - * Unbounded allocation is unwise; besides, there are only 16 bits - * of fid in 9P - */ - if(f->nfd >= 5000){ - Exhausted: - print("no free file descriptors\n"); - return -1; - } - newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*)); - if(newfd == 0) - goto Exhausted; - oldfd = f->fd; - memmove(newfd, oldfd, f->nfd*sizeof(Chan*)); - f->fd = newfd; - free(oldfd); - f->nfd += DELTAFD; - if(fd > f->maxfd){ - if(fd/100 > f->maxfd/100) - f->exceed = (fd/100)*100; - f->maxfd = fd; - } - return 1; -} - -/* - * this assumes that the fgrp is locked - */ -int -findfreefd(Fgrp *f, int start) -{ - int fd; - - for(fd=start; fd<f->nfd; fd++) - if(f->fd[fd] == 0) - break; - if(fd >= f->nfd && growfd(f, fd) < 0) - return -1; - return fd; -} - -int -newfd(Chan *c) -{ - int fd; - Fgrp *f; - - f = up->fgrp; - lock(&f->ref.lk); - fd = findfreefd(f, 0); - if(fd < 0){ - unlockfgrp(f); - return -1; - } - if(fd > f->maxfd) - f->maxfd = fd; - f->fd[fd] = c; - unlockfgrp(f); - return fd; -} - -int -newfd2(int fd[2], Chan *c[2]) -{ - Fgrp *f; - - f = up->fgrp; - lock(&f->ref.lk); - fd[0] = findfreefd(f, 0); - if(fd[0] < 0){ - unlockfgrp(f); - return -1; - } - fd[1] = findfreefd(f, fd[0]+1); - if(fd[1] < 0){ - unlockfgrp(f); - return -1; - } - if(fd[1] > f->maxfd) - f->maxfd = fd[1]; - f->fd[fd[0]] = c[0]; - f->fd[fd[1]] = c[1]; - unlockfgrp(f); - - return 0; -} - -Chan* -fdtochan(int fd, int mode, int chkmnt, int iref) -{ - Chan *c; - Fgrp *f; - - c = 0; - f = up->fgrp; - - lock(&f->ref.lk); - if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) { - unlock(&f->ref.lk); - error(Ebadfd); - } - if(iref) - incref(&c->ref); - unlock(&f->ref.lk); - - if(chkmnt && (c->flag&CMSG)) { - if(iref) - cclose(c); - error(Ebadusefd); - } - - if(mode<0 || c->mode==ORDWR) - return c; - - if((mode&OTRUNC) && c->mode==OREAD) { - if(iref) - cclose(c); - error(Ebadusefd); - } - - if((mode&~OTRUNC) != c->mode) { - if(iref) - cclose(c); - error(Ebadusefd); - } - - return c; -} - -int -openmode(ulong o) -{ - o &= ~(OTRUNC|OCEXEC|ORCLOSE); - if(o > OEXEC) - error(Ebadarg); - if(o == OEXEC) - return OREAD; - return o; -} - -long -_sysfd2path(int fd, char *buf, uint nbuf) -{ - Chan *c; - - c = fdtochan(fd, -1, 0, 1); - - if(c->name == nil) - snprint(buf, nbuf, "<null>"); - else - snprint(buf, nbuf, "%s", c->name->s); - cclose(c); - return 0; -} - -long -_syspipe(int fd[2]) -{ - Chan *c[2]; - Dev *d; - static char *datastr[] = {"data", "data1"}; - - d = devtab[devno('|', 0)]; - c[0] = namec("#|", Atodir, 0, 0); - c[1] = 0; - fd[0] = -1; - fd[1] = -1; - - if(waserror()){ - cclose(c[0]); - if(c[1]) - cclose(c[1]); - nexterror(); - } - c[1] = cclone(c[0]); - if(walk(&c[0], datastr+0, 1, 1, nil) < 0) - error(Egreg); - if(walk(&c[1], datastr+1, 1, 1, nil) < 0) - error(Egreg); - c[0] = d->open(c[0], ORDWR); - c[1] = d->open(c[1], ORDWR); - if(newfd2(fd, c) < 0) - error(Enofd); - poperror(); - - return 0; -} - -long -_sysdup(int fd0, int fd1) -{ - int fd; - Chan *c, *oc; - Fgrp *f = up->fgrp; - - /* - * Close after dup'ing, so date > #d/1 works - */ - c = fdtochan(fd0, -1, 0, 1); - fd = fd1; - if(fd != -1){ - lock(&f->ref.lk); - if(fd<0 || growfd(f, fd)<0) { - unlockfgrp(f); - cclose(c); - error(Ebadfd); - } - if(fd > f->maxfd) - f->maxfd = fd; - - oc = f->fd[fd]; - f->fd[fd] = c; - unlockfgrp(f); - if(oc) - cclose(oc); - }else{ - if(waserror()) { - cclose(c); - nexterror(); - } - fd = newfd(c); - if(fd < 0) - error(Enofd); - poperror(); - } - - return fd; -} - -long -_sysopen(char *name, int mode) -{ - int fd; - Chan *c = 0; - - openmode(mode); /* error check only */ - if(waserror()){ - if(c) - cclose(c); - nexterror(); - } - c = namec(name, Aopen, mode, 0); - fd = newfd(c); - if(fd < 0) - error(Enofd); - poperror(); - return fd; -} - -void -fdclose(int fd, int flag) -{ - int i; - Chan *c; - Fgrp *f = up->fgrp; - - lock(&f->ref.lk); - c = f->fd[fd]; - if(c == 0){ - /* can happen for users with shared fd tables */ - unlock(&f->ref.lk); - return; - } - if(flag){ - if(c==0 || !(c->flag&flag)){ - unlock(&f->ref.lk); - return; - } - } - f->fd[fd] = 0; - if(fd == f->maxfd) - for(i=fd; --i>=0 && f->fd[i]==0; ) - f->maxfd = i; - - unlock(&f->ref.lk); - cclose(c); -} - -long -_sysclose(int fd) -{ - fdtochan(fd, -1, 0, 0); - fdclose(fd, 0); - - return 0; -} - -long -unionread(Chan *c, void *va, long n) -{ - int i; - long nr; - Mhead *m; - Mount *mount; - - qlock(&c->umqlock); - m = c->umh; - rlock(&m->lock); - mount = m->mount; - /* bring mount in sync with c->uri and c->umc */ - for(i = 0; mount != nil && i < c->uri; i++) - mount = mount->next; - - nr = 0; - while(mount != nil) { - /* Error causes component of union to be skipped */ - if(mount->to && !waserror()) { - if(c->umc == nil){ - c->umc = cclone(mount->to); - c->umc = devtab[c->umc->type]->open(c->umc, OREAD); - } - - nr = devtab[c->umc->type]->read(c->umc, va, n, c->umc->offset); - c->umc->offset += nr; - poperror(); - } - if(nr > 0) - break; - - /* Advance to next element */ - c->uri++; - if(c->umc) { - cclose(c->umc); - c->umc = nil; - } - mount = mount->next; - } - runlock(&m->lock); - qunlock(&c->umqlock); - return nr; -} - -static long -kread(int fd, void *buf, long n, vlong *offp) -{ - int dir; - Chan *c; - vlong off; - - c = fdtochan(fd, OREAD, 1, 1); - - if(waserror()) { - cclose(c); - nexterror(); - } - - dir = c->qid.type&QTDIR; - /* - * The offset is passed through on directories, normally. sysseek complains but - * pread is used by servers and e.g. exportfs that shouldn't need to worry about this issue. - */ - - if(offp == nil) /* use and maintain channel's offset */ - off = c->offset; - else - off = *offp; - - if(off < 0) - error(Enegoff); - - if(dir && c->umh) - n = unionread(c, buf, n); - else - n = devtab[c->type]->read(c, buf, n, off); - - if(offp == nil){ - lock(&c->ref.lk); - c->offset += n; - unlock(&c->ref.lk); - } - - poperror(); - cclose(c); - - return n; -} - -/* name conflicts with netbsd -long -_sys_read(int fd, void *buf, long n) -{ - return kread(fd, buf, n, nil); -} -*/ - -long -_syspread(int fd, void *buf, long n, vlong off) -{ - if(off == ((uvlong) ~0)) - return kread(fd, buf, n, nil); - return kread(fd, buf, n, &off); -} - -static long -kwrite(int fd, void *buf, long nn, vlong *offp) -{ - Chan *c; - long m, n; - vlong off; - - n = 0; - c = fdtochan(fd, OWRITE, 1, 1); - if(waserror()) { - if(offp == nil){ - lock(&c->ref.lk); - c->offset -= n; - unlock(&c->ref.lk); - } - cclose(c); - nexterror(); - } - - if(c->qid.type & QTDIR) - error(Eisdir); - - n = nn; - - if(offp == nil){ /* use and maintain channel's offset */ - lock(&c->ref.lk); - off = c->offset; - c->offset += n; - unlock(&c->ref.lk); - }else - off = *offp; - - if(off < 0) - error(Enegoff); - - m = devtab[c->type]->write(c, buf, n, off); - - if(offp == nil && m < n){ - lock(&c->ref.lk); - c->offset -= n - m; - unlock(&c->ref.lk); - } - - poperror(); - cclose(c); - - return m; -} - -long -sys_write(int fd, void *buf, long n) -{ - return kwrite(fd, buf, n, nil); -} - -long -_syspwrite(int fd, void *buf, long n, vlong off) -{ - if(off == ((uvlong) ~0)) - return kwrite(fd, buf, n, nil); - return kwrite(fd, buf, n, &off); -} - -static vlong -_sysseek(int fd, vlong off, int whence) -{ - Chan *c; - uchar buf[sizeof(Dir)+100]; - Dir dir; - int n; - - c = fdtochan(fd, -1, 1, 1); - if(waserror()){ - cclose(c); - nexterror(); - } - if(devtab[c->type]->dc == '|') - error(Eisstream); - - switch(whence){ - case 0: - if((c->qid.type & QTDIR) && off != 0) - error(Eisdir); - if(off < 0) - error(Enegoff); - c->offset = off; - break; - - case 1: - if(c->qid.type & QTDIR) - error(Eisdir); - lock(&c->ref.lk); /* lock for read/write update */ - off = off + c->offset; - if(off < 0) - error(Enegoff); - c->offset = off; - unlock(&c->ref.lk); - break; - - case 2: - if(c->qid.type & QTDIR) - error(Eisdir); - n = devtab[c->type]->stat(c, buf, sizeof buf); - if(convM2D(buf, n, &dir, nil) == 0) - error("internal error: stat error in seek"); - off = dir.length + off; - if(off < 0) - error(Enegoff); - c->offset = off; - break; - - default: - error(Ebadarg); - } - c->uri = 0; - c->dri = 0; - cclose(c); - poperror(); - return off; -} - -void -validstat(uchar *s, int n) -{ - int m; - char buf[64]; - - if(statcheck(s, n) < 0) - error(Ebadstat); - /* verify that name entry is acceptable */ - s += STATFIXLEN - 4*BIT16SZ; /* location of first string */ - /* - * s now points at count for first string. - * if it's too long, let the server decide; this is - * only for his protection anyway. otherwise - * we'd have to allocate and waserror. - */ - m = GBIT16(s); - s += BIT16SZ; - if(m+1 > sizeof buf) - return; - memmove(buf, s, m); - buf[m] = '\0'; - /* name could be '/' */ - if(strcmp(buf, "/") != 0) - validname(buf, 0); -} - -long -_sysfstat(int fd, void *buf, long n) -{ - Chan *c; - uint l; - - l = n; - validaddr(buf, l, 1); - c = fdtochan(fd, -1, 0, 1); - if(waserror()) { - cclose(c); - nexterror(); - } - l = devtab[c->type]->stat(c, buf, l); - poperror(); - cclose(c); - return l; -} - -long -_sysstat(char *name, void *buf, long n) -{ - Chan *c; - uint l; - - l = n; - validaddr(buf, l, 1); - validaddr(name, 1, 0); - c = namec(name, Aaccess, 0, 0); - if(waserror()){ - cclose(c); - nexterror(); - } - l = devtab[c->type]->stat(c, buf, l); - poperror(); - cclose(c); - return l; -} - -long -_syschdir(char *name) -{ - Chan *c; - - validaddr(name, 1, 0); - - c = namec(name, Atodir, 0, 0); - cclose(up->dot); - up->dot = c; - return 0; -} - -long -bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, ulong flag, char* spec) -{ - int ret; - Chan *c0, *c1, *ac, *bc; - struct{ - Chan *chan; - Chan *authchan; - char *spec; - int flags; - }bogus; - - if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER)) - error(Ebadarg); - - bogus.flags = flag & MCACHE; - - if(ismount){ - if(up->pgrp->noattach) - error(Enoattach); - - ac = nil; - bc = fdtochan(fd, ORDWR, 0, 1); - if(waserror()) { - if(ac) - cclose(ac); - cclose(bc); - nexterror(); - } - - if(afd >= 0) - ac = fdtochan(afd, ORDWR, 0, 1); - - bogus.chan = bc; - bogus.authchan = ac; - - validaddr((ulong)spec, 1, 0); - bogus.spec = spec; - if(waserror()) - error(Ebadspec); - validname(spec, 1); - poperror(); - - ret = devno('M', 0); - c0 = devtab[ret]->attach((char*)&bogus); - - poperror(); - if(ac) - cclose(ac); - cclose(bc); - }else{ - bogus.spec = 0; - validaddr((ulong)arg0, 1, 0); - c0 = namec(arg0, Abind, 0, 0); - } - - if(waserror()){ - cclose(c0); - nexterror(); - } - - validaddr((ulong)arg1, 1, 0); - c1 = namec(arg1, Amount, 0, 0); - if(waserror()){ - cclose(c1); - nexterror(); - } - - ret = cmount(&c0, c1, flag, bogus.spec); - - poperror(); - cclose(c1); - poperror(); - cclose(c0); - if(ismount) - fdclose(fd, 0); - - return ret; -} - -long -_sysbind(char *old, char *new, int flag) -{ - return bindmount(0, -1, -1, old, new, flag, nil); -} - -long -_sysmount(int fd, int afd, char *new, int flag, char *spec) -{ - return bindmount(1, fd, afd, nil, new, flag, spec); -} - -long -_sysunmount(char *old, char *new) -{ - Chan *cmount, *cmounted; - - cmounted = 0; - - cmount = namec(new, Amount, 0, 0); - - if(old) { - if(waserror()) { - cclose(cmount); - nexterror(); - } - validaddr(old, 1, 0); - /* - * This has to be namec(..., Aopen, ...) because - * if arg[0] is something like /srv/cs or /fd/0, - * opening it is the only way to get at the real - * Chan underneath. - */ - cmounted = namec(old, Aopen, OREAD, 0); - poperror(); - } - - if(waserror()) { - cclose(cmount); - if(cmounted) - cclose(cmounted); - nexterror(); - } - - cunmount(cmount, cmounted); - cclose(cmount); - if(cmounted) - cclose(cmounted); - poperror(); - return 0; -} - -long -_syscreate(char *name, int mode, ulong perm) -{ - int fd; - Chan *c = 0; - - openmode(mode&~OEXCL); /* error check only; OEXCL okay here */ - if(waserror()) { - if(c) - cclose(c); - nexterror(); - } - validaddr(name, 1, 0); - c = namec(name, Acreate, mode, perm); - fd = newfd(c); - if(fd < 0) - error(Enofd); - poperror(); - return fd; -} - -long -_sysremove(char *name) -{ - Chan *c; - - c = namec(name, Aremove, 0, 0); - if(waserror()){ - c->type = 0; /* see below */ - cclose(c); - nexterror(); - } - devtab[c->type]->remove(c); - /* - * Remove clunks the fid, but we need to recover the Chan - * so fake it up. rootclose() is known to be a nop. - */ - c->type = 0; - poperror(); - cclose(c); - return 0; -} - -long -_syswstat(char *name, void *buf, long n) -{ - Chan *c; - uint l; - - l = n; - validstat(buf, l); - validaddr(name, 1, 0); - c = namec(name, Aaccess, 0, 0); - if(waserror()){ - cclose(c); - nexterror(); - } - l = devtab[c->type]->wstat(c, buf, l); - poperror(); - cclose(c); - return l; -} - -long -_sysfwstat(int fd, void *buf, long n) -{ - Chan *c; - uint l; - - l = n; - validaddr(buf, l, 0); - validstat(buf, l); - c = fdtochan(fd, -1, 1, 1); - if(waserror()) { - cclose(c); - nexterror(); - } - l = devtab[c->type]->wstat(c, buf, l); - poperror(); - cclose(c); - return l; -} - - -static void -starterror(void) -{ - assert(up->nerrlab == 0); -} - -static void -_syserror(void) -{ - char *p; - - p = up->syserrstr; - up->syserrstr = up->errstr; - up->errstr = p; -} - -static void -enderror(void) -{ - assert(up->nerrlab == 1); - poperror(); -} - -int -sysbind(char *old, char *new, int flag) -{ - int n; - - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _sysbind(old, new, flag); - enderror(); - return n; -} - -int -syschdir(char *path) -{ - int n; - - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _syschdir(path); - enderror(); - return n; -} - -int -sysclose(int fd) -{ - int n; - - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _sysclose(fd); - enderror(); - return n; -} - -int -syscreate(char *name, int mode, ulong perm) -{ - int n; - - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _syscreate(name, mode, perm); - enderror(); - return n; -} - -int -sysdup(int fd0, int fd1) -{ - int n; - - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _sysdup(fd0, fd1); - enderror(); - return n; -} - -int -sysfstat(int fd, uchar *buf, int n) -{ - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _sysfstat(fd, buf, n); - enderror(); - return n; -} - -int -sysfwstat(int fd, uchar *buf, int n) -{ - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _sysfwstat(fd, buf, n); - enderror(); - return n; -} - -int -sysmount(int fd, int afd, char *new, int flag, char *spec) -{ - int n; - - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _sysmount(fd, afd, new, flag, spec); - enderror(); - return n; -} - -int -sysunmount(char *old, char *new) -{ - int n; - - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _sysunmount(old, new); - enderror(); - return n; -} - -int -sysopen(char *name, int mode) -{ - int n; - - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _sysopen(name, mode); - enderror(); - return n; -} - -int -syspipe(int *fd) -{ - int n; - - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _syspipe(fd); - enderror(); - return n; -} - -long -syspread(int fd, void *buf, long n, vlong off) -{ - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _syspread(fd, buf, n, off); - enderror(); - return n; -} - -long -syspwrite(int fd, void *buf, long n, vlong off) -{ - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _syspwrite(fd, buf, n, off); - enderror(); - return n; -} - -long -sysread(int fd, void *buf, long n) -{ - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _syspread(fd, buf, n, (uvlong) ~0); - enderror(); - return n; -} - -int -sysremove(char *path) -{ - int n; - - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _sysremove(path); - enderror(); - return n; -} - -vlong -sysseek(int fd, vlong off, int whence) -{ - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - off = _sysseek(fd, off, whence); - enderror(); - return off; -} - -int -sysstat(char *name, uchar *buf, int n) -{ - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _sysstat(name, buf, n); - enderror(); - return n; -} - -long -syswrite(int fd, void *buf, long n) -{ - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _syspwrite(fd, buf, n, (uvlong) ~0); - enderror(); - return n; -} - -int -syswstat(char *name, uchar *buf, int n) -{ - starterror(); - if(waserror()){ - _syserror(); - return -1; - } - n = _syswstat(name, buf, n); - enderror(); - return n; -} - -void -werrstr(char *f, ...) -{ - char buf[ERRMAX]; - va_list arg; - - va_start(arg, f); - vsnprint(buf, sizeof buf, f, arg); - va_end(arg); - - if(up->nerrlab) - strecpy(up->errstr, up->errstr+ERRMAX, buf); - else - strecpy(up->syserrstr, up->syserrstr+ERRMAX, buf); -} - -int -__errfmt(Fmt *fmt) -{ - if(up->nerrlab) - return fmtstrcpy(fmt, up->errstr); - else - return fmtstrcpy(fmt, up->syserrstr); -} - -int -errstr(char *buf, uint n) -{ - char tmp[ERRMAX]; - char *p; - - p = up->nerrlab ? up->errstr : up->syserrstr; - memmove(tmp, p, ERRMAX); - utfecpy(p, p+ERRMAX, buf); - utfecpy(buf, buf+n, tmp); - return strlen(buf); -} - -int -rerrstr(char *buf, uint n) -{ - char *p; - - p = up->nerrlab ? up->errstr : up->syserrstr; - utfecpy(buf, buf+n, p); - return strlen(buf); -} - -void* -_sysrendezvous(void* arg0, void* arg1) -{ - void *tag, *val; - Proc *p, **l; - - tag = arg0; - l = &REND(up->rgrp, (uintptr)tag); - up->rendval = (void*)~0; - - lock(&up->rgrp->ref.lk); - for(p = *l; p; p = p->rendhash) { - if(p->rendtag == tag) { - *l = p->rendhash; - val = p->rendval; - p->rendval = arg1; - - while(p->mach != 0) - ; - procwakeup(p); - unlock(&up->rgrp->ref.lk); - return val; - } - l = &p->rendhash; - } - - /* Going to sleep here */ - up->rendtag = tag; - up->rendval = arg1; - up->rendhash = *l; - *l = up; - up->state = Rendezvous; - unlock(&up->rgrp->ref.lk); - - procsleep(); - - return up->rendval; -} - -void* -sysrendezvous(void *tag, void *val) -{ - void *n; - - starterror(); - if(waserror()){ - _syserror(); - return (void*)~0; - } - n = _sysrendezvous(tag, val); - enderror(); - return n; -} diff --git a/sys/src/cmd/unix/drawterm/kern/sysproc.c b/sys/src/cmd/unix/drawterm/kern/sysproc.c deleted file mode 100644 index 11caeb773..000000000 --- a/sys/src/cmd/unix/drawterm/kern/sysproc.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -long -sysexits(ulong *arg) -{ - char *status; - char *inval = "invalid exit string"; - char buf[ERRMAX]; - - status = (char*)arg[0]; - if(status){ - if(waserror()) - status = inval; - else{ - validaddr((ulong)status, 1, 0); - if(vmemchr(status, 0, ERRMAX) == 0){ - memmove(buf, status, ERRMAX); - buf[ERRMAX-1] = 0; - status = buf; - } - } - poperror(); - - } - pexit(status, 1); - return 0; /* not reached */ -} - diff --git a/sys/src/cmd/unix/drawterm/kern/term.c b/sys/src/cmd/unix/drawterm/kern/term.c deleted file mode 100644 index f8fa9cbbf..000000000 --- a/sys/src/cmd/unix/drawterm/kern/term.c +++ /dev/null @@ -1,205 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -#include <draw.h> -#include <memdraw.h> -#include "screen.h" - -#define MINX 8 -#define Backgnd 0xFF /* white */ - - Memsubfont *memdefont; - -struct{ - Point pos; - int bwid; -}out; - -Lock screenlock; - -Memimage *conscol; -Memimage *back; -extern Memimage *gscreen; - -static Rectangle flushr; -static Rectangle window; -static Point curpos; -static int h; -static void termscreenputs(char*, int); - - -static void -screenflush(void) -{ - drawflushr(flushr); - flushr = Rect(10000, 10000, -10000, -10000); -} - -static void -addflush(Rectangle r) -{ - if(flushr.min.x >= flushr.max.x) - flushr = r; - else - combinerect(&flushr, r); -} - -static void -screenwin(void) -{ - Point p; - char *greet; - Memimage *grey; - - drawqlock(); - back = memwhite; - conscol = memblack; - memfillcolor(gscreen, 0x444488FF); - - h = memdefont->height; - - window.min = addpt(gscreen->r.min, Pt(20,20)); - window.max.x = window.min.x + Dx(gscreen->r)*3/4-40; - window.max.y = window.min.y + Dy(gscreen->r)*3/4-100; - - memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); - window = insetrect(window, 4); - memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S); - - /* a lot of work to get a grey color */ - grey = allocmemimage(Rect(0,0,1,1), CMAP8); - grey->flags |= Frepl; - grey->clipr = gscreen->r; - memfillcolor(grey, 0xAAAAAAFF); - memimagedraw(gscreen, Rect(window.min.x, window.min.y, - window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S); - freememimage(grey); - window = insetrect(window, 5); - - greet = " Plan 9 Console "; - p = addpt(window.min, Pt(10, 0)); - memimagestring(gscreen, p, conscol, ZP, memdefont, greet); - window.min.y += h+6; - curpos = window.min; - window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; - flushmemscreen(gscreen->r); - drawqunlock(); -} - -void -terminit(void) -{ - memdefont = getmemdefont(); - out.pos.x = MINX; - out.pos.y = 0; - out.bwid = memdefont->info[' '].width; - screenwin(); - screenputs = termscreenputs; -} - -static void -scroll(void) -{ - int o; - Point p; - Rectangle r; - - o = 8*h; - r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); - p = Pt(window.min.x, window.min.y+o); - memimagedraw(gscreen, r, gscreen, p, nil, p, S); - r = Rpt(Pt(window.min.x, window.max.y-o), window.max); - memimagedraw(gscreen, r, back, ZP, nil, ZP, S); - flushmemscreen(gscreen->r); - curpos.y -= o; -} - -static void -screenputc(char *buf) -{ - Point p; - int w, pos; - Rectangle r; - static int *xp; - static int xbuf[256]; - - if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) - xp = xbuf; - - switch(buf[0]) { - case '\n': - if(curpos.y+h >= window.max.y) - scroll(); - curpos.y += h; - screenputc("\r"); - break; - case '\r': - xp = xbuf; - curpos.x = window.min.x; - break; - case '\t': - p = memsubfontwidth(memdefont, " "); - w = p.x; - *xp++ = curpos.x; - pos = (curpos.x-window.min.x)/w; - pos = 8-(pos%8); - r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h); - memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); - addflush(r); - curpos.x += pos*w; - break; - case '\b': - if(xp <= xbuf) - break; - xp--; - r = Rect(*xp, curpos.y, curpos.x, curpos.y + h); - memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); - addflush(r); - curpos.x = *xp; - break; - default: - p = memsubfontwidth(memdefont, buf); - w = p.x; - - if(curpos.x >= window.max.x-w) - screenputc("\n"); - - *xp++ = curpos.x; - r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h); - memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); - memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf); - addflush(r); - curpos.x += w; - } -} - -static void -termscreenputs(char *s, int n) -{ - int i, locked; - Rune r; - char buf[4]; - - lock(&screenlock); - locked = drawcanqlock(); - while(n > 0){ - i = chartorune(&r, s); - if(i == 0){ - s++; - --n; - continue; - } - memmove(buf, s, i); - buf[i] = 0; - n -= i; - s += i; - screenputc(buf); - } - if(locked) - drawqunlock(); - screenflush(); - unlock(&screenlock); -} diff --git a/sys/src/cmd/unix/drawterm/kern/uart.c b/sys/src/cmd/unix/drawterm/kern/uart.c deleted file mode 100644 index da6d93e3d..000000000 --- a/sys/src/cmd/unix/drawterm/kern/uart.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -extern int panicking; -void -uartputs(char *s, int n) -{ - if(panicking) - write(1, s, n); -} - - diff --git a/sys/src/cmd/unix/drawterm/kern/unused/syscall.c b/sys/src/cmd/unix/drawterm/kern/unused/syscall.c deleted file mode 100644 index 1ae9a7cb2..000000000 --- a/sys/src/cmd/unix/drawterm/kern/unused/syscall.c +++ /dev/null @@ -1,837 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -Chan* -fdtochan(int fd, int mode, int chkmnt, int iref) -{ - Fgrp *f; - Chan *c; - - c = 0; - f = up->fgrp; - - lock(&f->ref.lk); - if(fd<0 || NFD<=fd || (c = f->fd[fd])==0) { - unlock(&f->ref.lk); - error(Ebadfd); - } - if(iref) - refinc(&c->ref); - unlock(&f->ref.lk); - - if(chkmnt && (c->flag&CMSG)) - goto bad; - if(mode<0 || c->mode==ORDWR) - return c; - if((mode&OTRUNC) && c->mode==OREAD) - goto bad; - if((mode&~OTRUNC) != c->mode) - goto bad; - return c; -bad: - if(iref) - cclose(c); - error(Ebadusefd); - return nil; /* shut up compiler */ -} - -static void -fdclose(int fd, int flag) -{ - int i; - Chan *c; - Fgrp *f; - - f = up->fgrp; - - lock(&f->ref.lk); - c = f->fd[fd]; - if(c == 0) { - unlock(&f->ref.lk); - return; - } - if(flag) { - if(c==0 || !(c->flag&flag)) { - unlock(&f->ref.lk); - return; - } - } - f->fd[fd] = 0; - if(fd == f->maxfd) - for(i=fd; --i>=0 && f->fd[i]==0; ) - f->maxfd = i; - - unlock(&f->ref.lk); - cclose(c); -} - -static int -newfd(Chan *c) -{ - int i; - Fgrp *f; - - f = up->fgrp; - lock(&f->ref.lk); - for(i=0; i<NFD; i++) - if(f->fd[i] == 0){ - if(i > f->maxfd) - f->maxfd = i; - f->fd[i] = c; - unlock(&f->ref.lk); - return i; - } - unlock(&f->ref.lk); - error("no file descriptors"); - return 0; -} - -int -sysclose(int fd) -{ - if(waserror()) - return -1; - - fdtochan(fd, -1, 0, 0); - fdclose(fd, 0); - poperror(); - return 0; -} - -int -syscreate(char *path, int mode, ulong perm) -{ - int fd; - Chan *c = 0; - - if(waserror()) { - cclose(c); - return -1; - } - - openmode(mode); /* error check only */ - c = namec(path, Acreate, mode, perm); - fd = newfd((Chan*)c); - poperror(); - return fd; -} - -int -sysdup(int old, int new) -{ - Chan *oc; - Fgrp *f = up->fgrp; - Chan *c = 0; - - if(waserror()) - return -1; - - c = fdtochan(old, -1, 0, 1); - if(new != -1) { - if(new < 0 || NFD <= new) { - cclose(c); - error(Ebadfd); - } - lock(&f->ref.lk); - if(new > f->maxfd) - f->maxfd = new; - oc = f->fd[new]; - f->fd[new] = (Chan*)c; - unlock(&f->ref.lk); - if(oc != 0) - cclose(oc); - } - else { - if(waserror()) { - cclose(c); - nexterror(); - } - new = newfd((Chan*)c); - poperror(); - } - poperror(); - return new; -} - -int -sysfstat(int fd, char *buf) -{ - Chan *c = 0; - - if(waserror()) { - cclose(c); - return -1; - } - c = fdtochan(fd, -1, 0, 1); - devtab[c->type]->stat((Chan*)c, buf); - poperror(); - cclose(c); - return 0; -} - -int -sysfwstat(int fd, char *buf) -{ - Chan *c = 0; - - if(waserror()) { - cclose(c); - return -1; - } - nameok(buf); - c = fdtochan(fd, -1, 1, 1); - devtab[c->type]->wstat((Chan*)c, buf); - poperror(); - cclose(c); - return 0; -} - -int -syschdir(char *dir) -{ - return 0; -} - -long -bindmount(Chan *c0, char *old, int flag, char *spec) -{ - int ret; - Chan *c1 = 0; - - if(flag>MMASK || (flag&MORDER) == (MBEFORE|MAFTER)) - error(Ebadarg); - - c1 = namec(old, Amount, 0, 0); - if(waserror()){ - cclose(c1); - nexterror(); - } - - ret = cmount(c0, c1, flag, spec); - - poperror(); - cclose(c1); - return ret; -} - -int -sysbind(char *new, char *old, int flags) -{ - long r; - Chan *c0 = 0; - - if(waserror()) { - cclose(c0); - return -1; - } - c0 = namec(new, Aaccess, 0, 0); - r = bindmount(c0, old, flags, ""); - poperror(); - cclose(c0); - return 0; -} - -int -sysmount(int fd, char *old, int flags, char *spec) -{ - long r; - Chan *c0 = 0, *bc = 0; - struct { - Chan* chan; - char* spec; - int flags; - } mntparam; - - if(waserror()) { - cclose(bc); - cclose(c0); - return -1; - } - bc = fdtochan(fd, ORDWR, 0, 1); - mntparam.chan = (Chan*)bc; - mntparam.spec = spec; - mntparam.flags = flags; - c0 = (*devtab[devno('M', 0)].attach)(&mntparam); - cclose(bc); - r = bindmount(c0, old, flags, spec); - poperror(); - cclose(c0); - - return r; -} - -int -sysunmount(char *old, char *new) -{ - Chan *cmount = 0, *cmounted = 0; - - if(waserror()) { - cclose(cmount); - cclose(cmounted); - return -1; - } - - cmount = namec(new, Amount, OREAD, 0); - if(old != 0) - cmounted = namec(old, Aopen, OREAD, 0); - - cunmount(cmount, cmounted); - poperror(); - cclose(cmount); - cclose(cmounted); - return 0; -} - -int -sysopen(char *path, int mode) -{ - int fd; - Chan *c = 0; - - if(waserror()){ - cclose(c); - return -1; - } - openmode(mode); /* error check only */ - c = namec(path, Aopen, mode, 0); - fd = newfd((Chan*)c); - poperror(); - return fd; -} - -long -unionread(Chan *c, void *va, long n) -{ - long nr; - Chan *nc = 0; - Pgrp *pg = 0; - - pg = up->pgrp; - rlock(&pg->ns); - - for(;;) { - if(waserror()) { - runlock(&pg->ns); - nexterror(); - } - nc = clone(c->mnt->to, 0); - poperror(); - - if(c->mountid != c->mnt->mountid) { - runlock(&pg->ns); - cclose(nc); - return 0; - } - - /* Error causes component of union to be skipped */ - if(waserror()) { - cclose(nc); - goto next; - } - - nc = (*devtab[nc->type].open)((Chan*)nc, OREAD); - nc->offset = c->offset; - nr = (*devtab[nc->type].read)((Chan*)nc, va, n, nc->offset); - /* devdirread e.g. changes it */ - c->offset = nc->offset; - poperror(); - - cclose(nc); - if(nr > 0) { - runlock(&pg->ns); - return nr; - } - /* Advance to next element */ - next: - c->mnt = c->mnt->next; - if(c->mnt == 0) - break; - c->mountid = c->mnt->mountid; - c->offset = 0; - } - runlock(&pg->ns); - return 0; -} - -long -sysread(int fd, void *va, long n) -{ - int dir; - Lock *cl; - Chan *c = 0; - - if(waserror()) { - cclose(c); - return -1; - } - c = fdtochan(fd, OREAD, 1, 1); - - dir = c->qid.path&CHDIR; - if(dir) { - n -= n%DIRLEN; - if(c->offset%DIRLEN || n==0) - error(Etoosmall); - } - - if(dir && c->mnt) - n = unionread((Chan*)c, va, n); - else - n = (*devtab[c->type].read)((Chan*)c, va, n, c->offset); - - cl = (Lock*)&c->r.l; - lock(cl); - c->offset += n; - unlock(cl); - - poperror(); - cclose(c); - - return n; -} - -int -sysremove(char *path) -{ - Chan *c = 0; - - if(waserror()) { - if(c != 0) - c->type = 0; /* see below */ - cclose(c); - return -1; - } - c = namec(path, Aaccess, 0, 0); - (*devtab[c->type].remove)((Chan*)c); - /* - * Remove clunks the fid, but we need to recover the Chan - * so fake it up. rootclose() is known to be a nop. - */ - c->type = 0; - poperror(); - cclose(c); - return 0; -} - -long -sysseek(int fd, long off, int whence) -{ - Dir dir; - Chan *c; - char buf[DIRLEN]; - - if(waserror()) - return -1; - - c = fdtochan(fd, -1, 1, 0); - if(c->qid.path & CHDIR) - error(Eisdir); - - switch(whence) { - case 0: - c->offset = off; - break; - - case 1: - lock(&c->r.l); /* lock for read/write update */ - c->offset += off; - off = c->offset; - unlock(&c->r.l); - break; - - case 2: - (*devtab[c->type].stat)(c, buf); - convM2D(buf, &dir); - c->offset = dir.length + off; - off = c->offset; - break; - } - poperror(); - return off; -} - -int -sysstat(char *path, char *buf) -{ - Chan *c = 0; - - if(waserror()){ - cclose(c); - return -1; - } - c = namec(path, Aaccess, 0, 0); - (*devtab[c->type].stat)((Chan*)c, buf); - poperror(); - cclose(c); - return 0; -} - -long -syswrite(int fd, void *va, long n) -{ - Lock *cl; - Chan *c = 0; - - if(waserror()) { - cclose(c); - return -1; - } - c = fdtochan(fd, OWRITE, 1, 1); - if(c->qid.path & CHDIR) - error(Eisdir); - - n = (*devtab[c->type].write)((Chan*)c, va, n, c->offset); - - cl = (Lock*)&c->r.l; - lock(cl); - c->offset += n; - unlock(cl); - - poperror(); - cclose(c); - - return n; -} - -int -syswstat(char *path, char *buf) -{ - Chan *c = 0; - - if(waserror()) { - cclose(c); - return -1; - } - - nameok(buf); - c = namec(path, Aaccess, 0, 0); - (*devtab[c->type].wstat)((Chan*)c, buf); - poperror(); - cclose(c); - return 0; -} - -int -sysdirstat(char *name, Dir *dir) -{ - char buf[DIRLEN]; - - if(sysstat(name, buf) == -1) - return -1; - convM2D(buf, dir); - return 0; -} - -int -sysdirfstat(int fd, Dir *dir) -{ - char buf[DIRLEN]; - - if(sysfstat(fd, buf) == -1) - return -1; - - convM2D(buf, dir); - return 0; -} - -int -sysdirwstat(char *name, Dir *dir) -{ - char buf[DIRLEN]; - - convD2M(dir, buf); - return syswstat(name, buf); -} - -int -sysdirfwstat(int fd, Dir *dir) -{ - char buf[DIRLEN]; - - convD2M(dir, buf); - return sysfwstat(fd, buf); -} - -long -sysdirread(int fd, Dir *dbuf, long count) -{ - int c, n, i, r; - char buf[DIRLEN*50]; - - n = 0; - count = (count/sizeof(Dir)) * DIRLEN; - while(n < count) { - c = count - n; - if(c > sizeof(buf)) - c = sizeof(buf); - r = sysread(fd, buf, c); - if(r == 0) - break; - if(r < 0 || r % DIRLEN) - return -1; - for(i=0; i<r; i+=DIRLEN) { - convM2D(buf+i, dbuf); - dbuf++; - } - n += r; - if(r != c) - break; - } - - return (n/DIRLEN) * sizeof(Dir); -} - -static int -call(char *clone, char *dest, int *cfdp, char *dir, char *local) -{ - int fd, cfd, n; - char *p, name[3*NAMELEN+5], data[3*NAMELEN+10]; - - cfd = sysopen(clone, ORDWR); - if(cfd < 0){ - werrstr("%s: %r", clone); - return -1; - } - - /* get directory name */ - n = sysread(cfd, name, sizeof(name)-1); - if(n < 0) { - sysclose(cfd); - return -1; - } - name[n] = 0; - sprint(name, "%d", strtoul(name, 0, 0)); - p = strrchr(clone, '/'); - *p = 0; - if(dir) - snprint(dir, 2*NAMELEN, "%s/%s", clone, name); - snprint(data, sizeof(data), "%s/%s/data", clone, name); - - /* connect */ - /* set local side (port number, for example) if we need to */ - if(local) - snprint(name, sizeof(name), "connect %s %s", dest, local); - else - snprint(name, sizeof(name), "connect %s", dest); - if(syswrite(cfd, name, strlen(name)) < 0){ - werrstr("%s failed: %r", name); - sysclose(cfd); - return -1; - } - - /* open data connection */ - fd = sysopen(data, ORDWR); - if(fd < 0){ - werrstr("can't open %s: %r", data); - sysclose(cfd); - return -1; - } - if(cfdp) - *cfdp = cfd; - else - sysclose(cfd); - return fd; -} - -int -sysdial(char *dest, char *local, char *dir, int *cfdp) -{ - int n, fd, rv; - char *p, net[128], clone[NAMELEN+12]; - - /* go for a standard form net!... */ - p = strchr(dest, '!'); - if(p == 0){ - snprint(net, sizeof(net), "net!%s", dest); - } else { - strncpy(net, dest, sizeof(net)-1); - net[sizeof(net)-1] = 0; - } - - /* call the connection server */ - fd = sysopen("/net/cs", ORDWR); - if(fd < 0){ - /* no connection server, don't translate */ - p = strchr(net, '!'); - *p++ = 0; - snprint(clone, sizeof(clone), "/net/%s/clone", net); - return call(clone, p, cfdp, dir, local); - } - - /* - * send dest to connection to translate - */ - if(syswrite(fd, net, strlen(net)) < 0){ - werrstr("%s: %r", net); - sysclose(fd); - return -1; - } - - /* - * loop through each address from the connection server till - * we get one that works. - */ - rv = -1; - sysseek(fd, 0, 0); - while((n = sysread(fd, net, sizeof(net) - 1)) > 0){ - net[n] = 0; - p = strchr(net, ' '); - if(p == 0) - continue; - *p++ = 0; - rv = call(net, p, cfdp, dir, local); - if(rv >= 0) - break; - } - sysclose(fd); - return rv; -} - -static int -identtrans(char *addr, char *naddr, int na, char *file, int nf) -{ - char *p; - char reply[4*NAMELEN]; - - /* parse the network */ - strncpy(reply, addr, sizeof(reply)); - reply[sizeof(reply)-1] = 0; - p = strchr(reply, '!'); - if(p) - *p++ = 0; - - sprint(file, "/net/%.*s/clone", na - sizeof("/net//clone"), reply); - strncpy(naddr, p, na); - naddr[na-1] = 0; - return 1; -} - -static int -nettrans(char *addr, char *naddr, int na, char *file, int nf) -{ - long n; - int fd; - char *cp; - char reply[4*NAMELEN]; - - /* - * ask the connection server - */ - fd = sysopen("/net/cs", ORDWR); - if(fd < 0) - return identtrans(addr, naddr, na, file, nf); - if(syswrite(fd, addr, strlen(addr)) < 0){ - sysclose(fd); - return -1; - } - sysseek(fd, 0, 0); - n = sysread(fd, reply, sizeof(reply)-1); - sysclose(fd); - if(n <= 0) - return -1; - reply[n] = '\0'; - - /* - * parse the reply - */ - cp = strchr(reply, ' '); - if(cp == 0) - return -1; - *cp++ = 0; - strncpy(naddr, cp, na); - naddr[na-1] = 0; - strncpy(file, reply, nf); - file[nf-1] = 0; - return 0; -} - -int -sysannounce(char *addr, char *dir) -{ - char *cp; - int ctl, n, m; - char buf[3*NAMELEN]; - char buf2[3*NAMELEN]; - char netdir[2*NAMELEN]; - char naddr[3*NAMELEN]; - - /* - * translate the address - */ - if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0){ - werrstr("can't translate address"); - return -1; - } - - /* - * get a control channel - */ - ctl = sysopen(netdir, ORDWR); - if(ctl<0){ - werrstr("can't open control channel"); - return -1; - } - cp = strrchr(netdir, '/'); - *cp = 0; - - /* - * find out which line we have - */ - n = sprint(buf, "%.*s/", 2*NAMELEN+1, netdir); - m = sysread(ctl, &buf[n], sizeof(buf)-n-1); - if(m <= 0) { - sysclose(ctl); - werrstr("can't read control file"); - return -1; - } - buf[n+m] = 0; - - /* - * make the call - */ - n = sprint(buf2, "announce %.*s", 2*NAMELEN, naddr); - if(syswrite(ctl, buf2, n) != n) { - sysclose(ctl); - werrstr("announcement fails"); - return -1; - } - - strcpy(dir, buf); - - return ctl; -} - -int -syslisten(char *dir, char *newdir) -{ - char *cp; - int ctl, n, m; - char buf[3*NAMELEN]; - - /* - * open listen, wait for a call - */ - sprint(buf, "%.*s/listen", 2*NAMELEN+1, dir); - ctl = sysopen(buf, ORDWR); - if(ctl < 0) - return -1; - - /* - * find out which line we have - */ - strcpy(buf, dir); - cp = strrchr(buf, '/'); - *++cp = 0; - n = cp-buf; - m = sysread(ctl, cp, sizeof(buf) - n - 1); - if(n<=0){ - sysclose(ctl); - return -1; - } - buf[n+m] = 0; - - strcpy(newdir, buf); - return ctl; -} diff --git a/sys/src/cmd/unix/drawterm/kern/waserror.c b/sys/src/cmd/unix/drawterm/kern/waserror.c deleted file mode 100644 index 3a07bc928..000000000 --- a/sys/src/cmd/unix/drawterm/kern/waserror.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include "error.h" - -Label* -pwaserror(void) -{ - if(up->nerrlab == NERR) - panic("error stack overflow"); - return &up->errlab[up->nerrlab++]; -} - -void -nexterror(void) -{ - longjmp(up->errlab[--up->nerrlab].buf, 1); -} - -void -error(char *e) -{ - kstrcpy(up->errstr, e, ERRMAX); - setjmp(up->errlab[NERR-1].buf); - nexterror(); -} diff --git a/sys/src/cmd/unix/drawterm/kern/win32.c b/sys/src/cmd/unix/drawterm/kern/win32.c deleted file mode 100644 index fa79c1d54..000000000 --- a/sys/src/cmd/unix/drawterm/kern/win32.c +++ /dev/null @@ -1,470 +0,0 @@ -#include <windows.h> -#include "u.h" -#include "lib.h" -#include "dat.h" -#include "fns.h" -#include <libsec.h> - -typedef struct Oproc Oproc; -struct Oproc { - int tid; - HANDLE *sema; -}; - -static int tlsx = TLS_OUT_OF_INDEXES; - -char *argv0; - -Proc* -_getproc(void) -{ - if(tlsx == TLS_OUT_OF_INDEXES) - return nil; - return TlsGetValue(tlsx); -} - -void -_setproc(Proc *p) -{ - if(tlsx == TLS_OUT_OF_INDEXES){ - tlsx = TlsAlloc(); - if(tlsx == TLS_OUT_OF_INDEXES) - panic("out of indexes"); - } - TlsSetValue(tlsx, p); -} - -void -oserror(void) -{ - oserrstr(); - nexterror(); -} - -void -osinit(void) -{ - Oproc *t; - static Proc firstprocCTstore; - - _setproc(&firstprocCTstore); - t = (Oproc*)firstprocCTstore.oproc; - assert(t != 0); - - t->tid = GetCurrentThreadId(); - t->sema = CreateSemaphore(0, 0, 1000, 0); - if(t->sema == 0) { - oserror(); - panic("could not create semaphore: %r"); - } -} - -void -osnewproc(Proc *p) -{ - Oproc *op; - - op = (Oproc*)p->oproc; - op->sema = CreateSemaphore(0, 0, 1000, 0); - if (op->sema == 0) { - oserror(); - panic("could not create semaphore: %r"); - } -} - -void -osmsleep(int ms) -{ - Sleep((DWORD) ms); -} - -void -osyield(void) -{ - Sleep(0); -} - -static DWORD WINAPI tramp(LPVOID vp); - -void -osproc(Proc *p) -{ - DWORD tid; - - if(CreateThread(0, 0, tramp, p, 0, &tid) == 0) { - oserror(); - panic("osproc: %r"); - } - - Sleep(0); -} - -static DWORD WINAPI -tramp(LPVOID vp) -{ - Proc *p = (Proc *) vp; - Oproc *op = (Oproc*) p->oproc; - - _setproc(p); - op->tid = GetCurrentThreadId(); - op->sema = CreateSemaphore(0, 0, 1000, 0); - if(op->sema == 0) { - oserror(); - panic("could not create semaphore: %r"); - } - - (*p->fn)(p->arg); - ExitThread(0); - return 0; -} - -void -procsleep(void) -{ - Proc *p; - Oproc *op; - - p = up; - op = (Oproc*)p->oproc; - WaitForSingleObject(op->sema, INFINITE);} - -void -procwakeup(Proc *p) -{ - Oproc *op; - - op = (Oproc*)p->oproc; - ReleaseSemaphore(op->sema, 1, 0); -} - -void -random20(uchar *p) -{ - LARGE_INTEGER ti; - int i, j; - FILETIME ft; - DigestState ds; - vlong tsc; - - GetSystemTimeAsFileTime(&ft); - memset(&ds, 0, sizeof ds); - sha1((uchar*)&ft, sizeof(ft), 0, &ds); - for(i=0; i<50; i++) { - for(j=0; j<10; j++) { - QueryPerformanceCounter(&ti); - sha1((uchar*)&ti, sizeof(ti), 0, &ds); - tsc = GetTickCount(); - sha1((uchar*)&tsc, sizeof(tsc), 0, &ds); - } - Sleep(10); - } - sha1(0, 0, p, &ds); -} - -void -randominit(void) -{ -} - -ulong -randomread(void *v, ulong n) -{ - int i; - uchar p[20]; - - for(i=0; i<n; i+=20){ - random20(p); - if(i+20 <= n) - memmove((char*)v+i, p, 20); - else - memmove((char*)v+i, p, n-i); - } - return n; -} - -long -seconds(void) -{ - return time(0); -} - -ulong -ticks(void) -{ - return GetTickCount(); -} - -#if 0 -uvlong -fastticks(uvlong *v) -{ - uvlong n; - - n = GetTickCount() * 1000 * 1000; - if(v) - *v = n; - return n; -} -#endif - -extern int main(int, char*[]); - - -int -wstrutflen(Rune *s) -{ - int n; - - for(n=0; *s; n+=runelen(*s),s++) - ; - return n; -} - -int -wstrtoutf(char *s, Rune *t, int n) -{ - int i; - char *s0; - - s0 = s; - if(n <= 0) - return wstrutflen(t)+1; - while(*t) { - if(n < UTFmax+1 && n < runelen(*t)+1) { - *s = 0; - return s-s0+wstrutflen(t)+1; - } - i = runetochar(s, t); - s += i; - n -= i; - t++; - } - *s = 0; - return s-s0; -} - -int -win_hasunicode(void) -{ - OSVERSIONINFOA osinfo; - int r; - - osinfo.dwOSVersionInfoSize = sizeof(osinfo); - if(!GetVersionExA(&osinfo)) - panic("GetVersionEx failed"); - switch(osinfo.dwPlatformId) { - default: - panic("unknown PlatformId"); - case VER_PLATFORM_WIN32s: - panic("Win32s not supported"); - case VER_PLATFORM_WIN32_WINDOWS: - r = 0; - break; - case VER_PLATFORM_WIN32_NT: - r = 1; - break; - } - - return r; -} - -int -wstrlen(Rune *s) -{ - int n; - - for(n=0; *s; s++,n++) - ; - return n; -} -static int args(char *argv[], int n, char *p); - -int APIENTRY -WinMain(HINSTANCE x, HINSTANCE y, LPSTR z, int w) -{ - int argc, n; - char *arg, *p, **argv; - Rune *warg; - - if(0 && win_hasunicode()){ - warg = GetCommandLineW(); - n = (wstrlen(warg)+1)*UTFmax; - arg = malloc(n); - wstrtoutf(arg, warg, n); - }else - arg = GetCommandLineA(); - - /* conservative guess at the number of args */ - for(argc=4,p=arg; *p; p++) - if(*p == ' ' || *p == '\t') - argc++; - argv = malloc(argc*sizeof(char*)); - argc = args(argv, argc, arg); - - mymain(argc, argv); - ExitThread(0); - return 0; -} - -/* - * Break the command line into arguments - * The rules for this are not documented but appear to be the following - * according to the source for the microsoft C library. - * Words are seperated by space or tab - * Words containing a space or tab can be quoted using " - * 2N backslashes + " ==> N backslashes and end quote - * 2N+1 backslashes + " ==> N backslashes + literal " - * N backslashes not followed by " ==> N backslashes - */ -static int -args(char *argv[], int n, char *p) -{ - char *p2; - int i, j, quote, nbs; - - for(i=0; *p && i<n-1; i++) { - while(*p == ' ' || *p == '\t') - p++; - quote = 0; - argv[i] = p2 = p; - for(;*p; p++) { - if(!quote && (*p == ' ' || *p == '\t')) - break; - for(nbs=0; *p == '\\'; p++,nbs++) - ; - if(*p == '"') { - for(j=0; j<(nbs>>1); j++) - *p2++ = '\\'; - if(nbs&1) - *p2++ = *p; - else - quote = !quote; - } else { - for(j=0; j<nbs; j++) - *p2++ = '\\'; - *p2++ = *p; - } - } - /* move p up one to avoid pointing to null at end of p2 */ - if(*p) - p++; - *p2 = 0; - } - argv[i] = 0; - - return i; -} -/* - * Windows socket error messages - * There must be a way to get these strings out of the library. - * This table is derived from the MSDN online help. - */ -static struct { - int e; - char *s; -} tab[] = { - { 10004, "interrupted function call" }, - { 10013, "permission denied" }, - { 10014, "bad address" }, - { 10022, "invalid argument" }, - { 10024, "too many open files" }, - { 10035, "resource temporarily unavailable" }, - { 10036, "operation now in progress" }, - { 10037, "operation already in progress" }, - { 10038, "socket operation on nonsocket" }, - { 10039, "destination address required" }, - { 10040, "message too long" }, - { 10041, "protocol wrong type for socket" }, - { 10042, "bad protocol option" }, - { 10043, "protocol not supported" }, - { 10044, "socket type not supported" }, - { 10045, "operation not supported" }, - { 10046, "protocol family not supported" }, - { 10047, "address family not supported by protocol family" }, - { 10048, "address already in use" }, - { 10049, "cannot assign requested address" }, - { 10050, "network is down" }, - { 10051, "network is unreachable" }, - { 10052, "network dropped connection on reset" }, - { 10053, "software caused connection abort" }, - { 10054, "connection reset by peer" }, - { 10055, "no buffer space available" }, - { 10056, "socket is already connected" }, - { 10057, "socket is not connected" }, - { 10058, "cannot send after socket shutdown" }, - { 10060, "connection timed out" }, - { 10061, "connection refused" }, - { 10064, "host is down" }, - { 10065, "no route to host" }, - { 10067, "too many processes" }, - { 10091, "network subsystem is unavailable" }, - { 10092, "winsock.dll version out of range" }, - { 10093, "wsastartup not called" }, - { 10101, "graceful shutdown in progress" }, - { 10109, "class type not found" }, - { 11001, "host name not found" }, - { 11002, "host not found (non-authoritative)" }, - { 11003, "nonrecoverable error" }, - { 11004, "valid name, but no data record of requested type" }, -}; - -void -osrerrstr(char *buf, uint nbuf) -{ - char *p, *q; - int e, i, r; - - e = GetLastError(); - r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, - 0, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - buf, nbuf, 0); - if(r == 0){ - for(i=0; i<nelem(tab); i++) - if(tab[i].e == e){ - strecpy(buf, buf+nbuf, tab[i].s); - break; - } - if(i==nelem(tab)) - snprint(buf, nbuf, "windows error %d", e); - } - - for(p=q=buf; *p; p++) { - if(*p == '\r') - continue; - if(*p == '\n') - *q++ = ' '; - else - *q++ = *p; - } - *q = '\0'; -} - -void -oserrstr(void) -{ - osrerrstr(up->errstr, ERRMAX); -} - -long -showfilewrite(char *a, int n) -{ - Rune *action, *arg, *cmd; - static Rune Lopen[] = { 'o', 'p', 'e', 'n', 0 }; - - cmd = runesmprint("%.*s", n, a); - if(cmd == nil) - error("out of memory"); - if(cmd[runestrlen(cmd)-1] == '\n') - cmd[runestrlen(cmd)] = 0; - p = runestrchr(cmd, ' '); - if(p){ - action = cmd; - *p++ = 0; - arg = p; - }else{ - action = Lopen; - arg = cmd; - } - ShellExecute(0, 0, action, arg, 0, SW_SHOWNORMAL); - return n; -} |