summaryrefslogtreecommitdiff
path: root/sys/src/cmd
diff options
context:
space:
mode:
authorAlex Musolino <alex@musolino.id.au>2020-12-15 20:55:41 +1030
committerAlex Musolino <alex@musolino.id.au>2020-12-15 20:55:41 +1030
commit3749e92cdb88a157f99c0709a264bd508603be9b (patch)
tree49ce703965ba4114490729c5aeabd9ba120d9b78 /sys/src/cmd
parent404c901f299c4d93cb159a3c44c2977a25408319 (diff)
parent32291b52bcbd6976051acff1692b571e321ac859 (diff)
merge
Diffstat (limited to 'sys/src/cmd')
-rw-r--r--sys/src/cmd/aux/kbdfs/kbdfs.c2
-rw-r--r--sys/src/cmd/aux/statusbar.c38
-rw-r--r--sys/src/cmd/aux/statusmsg.c4
-rw-r--r--sys/src/cmd/cpu.c2
-rw-r--r--sys/src/cmd/exportfs/exportfs.c850
-rw-r--r--sys/src/cmd/exportfs/exportfs.h3
-rw-r--r--sys/src/cmd/exportfs/exportsrv.c8
-rw-r--r--sys/src/cmd/exportfs/io.c503
-rw-r--r--sys/src/cmd/exportfs/mkfile6
-rw-r--r--sys/src/cmd/exportfs/oexportfs.c443
-rw-r--r--sys/src/cmd/iostats.c1
-rw-r--r--sys/src/cmd/nusb/kb/kb.c13
-rw-r--r--sys/src/cmd/ptrap.c62
-rw-r--r--sys/src/cmd/rio/fsys.c20
-rw-r--r--sys/src/cmd/rio/rio.c61
-rw-r--r--sys/src/cmd/rio/wctl.c9
-rw-r--r--sys/src/cmd/rio/wind.c6
-rw-r--r--sys/src/cmd/srvfs.c45
-rw-r--r--sys/src/cmd/vmx/dat.h1
-rw-r--r--sys/src/cmd/vmx/exith.c269
-rw-r--r--sys/src/cmd/vmx/fns.h4
-rw-r--r--sys/src/cmd/vmx/ide.c10
-rw-r--r--sys/src/cmd/vmx/io.c14
-rw-r--r--sys/src/cmd/vmx/mkfile5
-rw-r--r--sys/src/cmd/vmx/nanosec.c9
-rw-r--r--sys/src/cmd/vmx/vesa.c3
-rw-r--r--sys/src/cmd/vmx/vga.c18
-rw-r--r--sys/src/cmd/vmx/vmx.c34
-rw-r--r--sys/src/cmd/vmx/x86.h5
29 files changed, 1342 insertions, 1106 deletions
diff --git a/sys/src/cmd/aux/kbdfs/kbdfs.c b/sys/src/cmd/aux/kbdfs/kbdfs.c
index 8a57b52fc..a7a5a6966 100644
--- a/sys/src/cmd/aux/kbdfs/kbdfs.c
+++ b/sys/src/cmd/aux/kbdfs/kbdfs.c
@@ -179,7 +179,7 @@ Rune kbtabesc1[Nscan] =
[0x40] 0, 0, 0, 0, 0, 0, Kbreak, Khome,
[0x48] Kup, Kpgup, 0, Kleft, 0, Kright, 0, Kend,
[0x50] Kdown, Kpgdown,Kins, Kdel, 0, 0, 0, 0,
-[0x58] 0, 0, 0, 0, 0, 0, 0, 0,
+[0x58] 0, 0, 0, Kmod4, 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, 0,
diff --git a/sys/src/cmd/aux/statusbar.c b/sys/src/cmd/aux/statusbar.c
index 02d85176f..6d2db3295 100644
--- a/sys/src/cmd/aux/statusbar.c
+++ b/sys/src/cmd/aux/statusbar.c
@@ -21,10 +21,10 @@ initcolor(void)
text = display->black;
light = allocimagemix(display, DPalegreen, DWhite);
dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen);
+ if(light == nil || dark == nil) sysfatal("initcolor: %r");
}
Rectangle rbar;
-Point ptext;
vlong n, d;
int last;
int lastp = -1;
@@ -75,7 +75,7 @@ drawbar(void)
if(lastp != p){
sprint(buf, "%3d%%", p);
- stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP);
+ stringbg(screen, Pt(screen->r.max.x-4-stringwidth(display->defaultfont, buf), screen->r.min.y+4), text, ZP, display->defaultfont, buf, light, ZP);
lastp = p;
}
@@ -94,24 +94,13 @@ drawbar(void)
void
eresized(int new)
{
- Point p, q;
- Rectangle r;
-
if(new && getwindow(display, Refnone) < 0)
fprint(2,"can't reattach to window");
- r = screen->r;
- draw(screen, r, light, nil, ZP);
- p = string(screen, addpt(r.min, Pt(4,4)), text, ZP,
- display->defaultfont, title);
-
- p.x = r.min.x+4;
- p.y += display->defaultfont->height+4;
-
- q = subpt(r.max, Pt(4,4));
- rbar = Rpt(p, q);
-
- ptext = Pt(r.max.x-4-stringwidth(display->defaultfont, "100%"), r.min.x+4);
+ draw(screen, screen->r, light, nil, ZP);
+ if(title) string(screen, addpt(screen->r.min, Pt(4,4)), text, ZP, font, title);
+ rbar = insetrect(screen->r, 4);
+ rbar.min.y += font->height + 4;
border(screen, rbar, -2, dark, ZP);
last = 0;
lastp = -1;
@@ -163,7 +152,7 @@ bar(Biobuf *b)
void
usage(void)
{
- fprint(2, "usage: aux/statusbar [-kt] [-w minx,miny,maxx,maxy] 'title'\n");
+ fprint(2, "usage: %s [-kt] [-w minx,miny,maxx,maxy] [title]\n", argv0);
exits("usage");
}
@@ -190,11 +179,14 @@ main(int argc, char **argv)
usage();
}ARGEND;
- if(argc != 1)
+ switch(argc){
+ default:
usage();
-
- title = argv[0];
-
+ case 1:
+ title = argv[0];
+ case 0:
+ break;
+ }
lfd = dup(0, -1);
while(q = strchr(p, ','))
@@ -204,7 +196,7 @@ main(int argc, char **argv)
textmode = 1;
rbar = Rect(0, 0, 60, 1);
}else{
- if(initdraw(0, 0, title) < 0)
+ if(initdraw(0, 0, title ? title : argv0) < 0)
exits("initdraw");
initcolor();
einit(Emouse|Ekeyboard);
diff --git a/sys/src/cmd/aux/statusmsg.c b/sys/src/cmd/aux/statusmsg.c
index 1133a090a..fa2f4790b 100644
--- a/sys/src/cmd/aux/statusmsg.c
+++ b/sys/src/cmd/aux/statusmsg.c
@@ -22,6 +22,7 @@ initcolor(void)
{
text = display->black;
light = allocimagemix(display, DPalegreen, DWhite);
+ if(light == nil) sysfatal("initcolor: %r");
}
void
@@ -136,7 +137,6 @@ main(int argc, char **argv)
usage();
case 1:
title = argv[0];
- break;
case 0:
break;
}
@@ -153,7 +153,7 @@ main(int argc, char **argv)
if((bout = Bfdopen(1, OWRITE)) == nil)
sysfatal("Bfdopen: %r");
}else{
- if(initdraw(0, 0, title) < 0)
+ if(initdraw(0, 0, title ? title : argv0) < 0)
sysfatal("initdraw: %r");
initcolor();
einit(Emouse|Ekeyboard);
diff --git a/sys/src/cmd/cpu.c b/sys/src/cmd/cpu.c
index 98080347d..3fb3a6d5e 100644
--- a/sys/src/cmd/cpu.c
+++ b/sys/src/cmd/cpu.c
@@ -37,7 +37,7 @@ char *patternfile;
char *origargs;
char *srvname = "ncpu";
-char *exportfs = "/bin/exportfs";
+char *exportfs = "/bin/oexportfs";
char *ealgs = "rc4_256 sha1";
/* message size for exportfs; may be larger so we can do big graphics in CPU window */
diff --git a/sys/src/cmd/exportfs/exportfs.c b/sys/src/cmd/exportfs/exportfs.c
index 275151a6c..b17cec499 100644
--- a/sys/src/cmd/exportfs/exportfs.c
+++ b/sys/src/cmd/exportfs/exportfs.c
@@ -1,135 +1,44 @@
-/*
- * exportfs - Export a plan 9 name space across a network
- */
#include <u.h>
#include <libc.h>
-#include <auth.h>
#include <fcall.h>
-#include <libsec.h>
#define Extern
#include "exportfs.h"
-#define QIDPATH ((1LL<<48)-1)
-vlong newqid = 0;
-
-enum {
- Encnone,
- Encssl,
- Enctls,
-};
-
-void (*fcalls[])(Fsrpc*) =
-{
- [Tversion] Xversion,
- [Tauth] Xauth,
- [Tflush] Xflush,
- [Tattach] Xattach,
- [Twalk] Xwalk,
- [Topen] slave,
- [Tcreate] Xcreate,
- [Tclunk] Xclunk,
- [Tread] slave,
- [Twrite] slave,
- [Tremove] Xremove,
- [Tstat] Xstat,
- [Twstat] Xwstat,
-};
-
-/* accounting and debugging counters */
-int filecnt;
-int freecnt;
-int qidcnt;
-int qfreecnt;
-int ncollision;
-
int srvfd = -1;
-int nonone = 1;
-char *filterp;
-char *ealgs = "rc4_256 sha1";
-char *aanfilter = "/bin/aan";
-int encproto = Encnone;
int readonly;
-static void mksecret(char *, uchar *);
-static char *anstring = "tcp!*!0";
-
-char *netdir = "", *local = "", *remote = "";
-
-void filter(int, char *, char *);
-
void
usage(void)
{
- fprint(2, "usage: %s [-adnsR] [-f dbgfile] [-m msize] [-r root] "
- "[-S srvfile] [-e 'crypt hash'] [-P exclusion-file] "
- "[-A announce-string] [-B address]\n", argv0);
+ fprint(2, "usage: %s [-dsR] [-f dbgfile] [-m msize] [-r root] "
+ "[-S srvfile] [-P exclusion-file]\n", argv0);
fatal("usage");
}
-static void
-noteconn(int fd)
-{
- NetConnInfo *nci;
-
- nci = getnetconninfo(nil, fd);
- if(nci == nil)
- return;
- netdir = estrdup(nci->dir);
- local = estrdup(nci->lsys);
- remote = estrdup(nci->rsys);
- freenetconninfo(nci);
-}
-
void
main(int argc, char **argv)
{
- char buf[ERRMAX], ebuf[ERRMAX], initial[4], *ini, *srvfdfile;
- char *dbfile, *srv, *na, *nsfile, *keyspec;
- int doauth, n, fd;
- AuthInfo *ai;
- Fsrpc *r;
+ char *dbfile, *srv, *srvfdfile;
+ int n;
dbfile = "/tmp/exportdb";
srv = nil;
srvfd = -1;
srvfdfile = nil;
- na = nil;
- nsfile = nil;
- keyspec = "";
- doauth = 0;
- ai = nil;
ARGBEGIN{
- case 'a':
- doauth = 1;
- break;
-
case 'd':
dbg++;
break;
- case 'e':
- ealgs = EARGF(usage());
- if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
- ealgs = nil;
- break;
-
case 'f':
dbfile = EARGF(usage());
break;
- case 'k':
- keyspec = EARGF(usage());
- break;
-
case 'm':
messagesize = strtoul(EARGF(usage()), nil, 0);
break;
- case 'n':
- nonone = 0;
- break;
-
case 'r':
srv = EARGF(usage());
break;
@@ -138,22 +47,10 @@ main(int argc, char **argv)
srv = "/";
break;
- case 'A':
- anstring = EARGF(usage());
- break;
-
- case 'B':
- na = EARGF(usage());
- break;
-
case 'F':
/* accepted but ignored, for backwards compatibility */
break;
- case 'N':
- nsfile = EARGF(usage());
- break;
-
case 'P':
patternfile = EARGF(usage());
break;
@@ -173,52 +70,15 @@ main(int argc, char **argv)
}ARGEND
USED(argc, argv);
- if(na == nil && doauth){
- /*
- * We use p9any so we don't have to visit this code again, with the
- * cost that this code is incompatible with the old world, which
- * requires p9sk2. (The two differ in who talks first, so compatibility
- * is awkward.)
- */
- ai = auth_proxy(0, auth_getkey, "proto=p9any role=server %s", keyspec);
- if(ai == nil)
- fatal("auth_proxy: %r");
- if(nonone && strcmp(ai->cuid, "none") == 0)
- fatal("exportfs by none disallowed");
- if(auth_chuid(ai, nsfile) < 0)
- fatal("auth_chuid: %r");
- else { /* chown network connection */
- Dir nd;
- nulldir(&nd);
- nd.mode = 0660;
- nd.uid = ai->cuid;
- dirfwstat(0, &nd);
- }
- putenv("service", "exportfs");
- }
-
if(srvfdfile != nil){
+ if(srv != nil){
+ fprint(2, "exportfs: -S cannot be used with -r or -s\n");
+ usage();
+ }
if((srvfd = open(srvfdfile, ORDWR)) < 0)
fatal("open %s: %r", srvfdfile);
- }
-
- if(na != nil){
- if(srv == nil)
- fatal("-B requires -s");
-
- local = "me";
- remote = na;
- if((fd = dial(netmkaddr(na, 0, "importfs"), 0, 0, 0)) < 0)
- fatal("can't dial %s: %r", na);
-
- ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec);
- if(ai == nil)
- fatal("%r: %s", na);
-
- dup(fd, 0);
- dup(fd, 1);
- close(fd);
- }
+ } else if(srv == nil)
+ usage();
exclusions();
@@ -228,11 +88,6 @@ main(int argc, char **argv)
close(n);
}
- if(srvfd >= 0 && srv != nil){
- fprint(2, "exportfs: -S cannot be used with -r or -s\n");
- usage();
- }
-
DEBUG(DFD, "exportfs: started\n");
rfork(RFNOTEG|RFREND);
@@ -246,695 +101,18 @@ main(int argc, char **argv)
fmtinstall('F', fcallfmt);
- /*
- * Get tree to serve from network connection,
- * check we can get there and ack the connection
- */
- if(srvfd != -1) {
- /* do nothing */
- }
- else if(srv != nil) {
+ if(srvfd == -1) {
if(chdir(srv) < 0) {
+ char ebuf[ERRMAX];
ebuf[0] = '\0';
errstr(ebuf, sizeof ebuf);
- r = getsbuf();
- r->work.tag = NOTAG;
- r->work.fid = NOFID;
- r->work.type = Rerror;
- r->work.ename = ebuf;
- n = convS2M(&r->work, r->buf, messagesize);
- write(0, r->buf, n);
DEBUG(DFD, "chdir(\"%s\"): %s\n", srv, ebuf);
- exits(ebuf);
+ mounterror(ebuf);
}
DEBUG(DFD, "invoked as server for %s", srv);
- strncpy(buf, srv, sizeof buf);
- }
- else {
- noteconn(0);
- buf[0] = 0;
- n = read(0, buf, sizeof(buf)-1);
- if(n < 0) {
- errstr(buf, sizeof buf);
- fprint(0, "read(0): %s\n", buf);
- DEBUG(DFD, "read(0): %s\n", buf);
- exits(buf);
- }
- buf[n] = 0;
- if(chdir(buf) < 0) {
- errstr(ebuf, sizeof ebuf);
- fprint(0, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf);
- DEBUG(DFD, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf);
- exits(ebuf);
- }
}
DEBUG(DFD, "\niniting root\n");
initroot();
-
- DEBUG(DFD, "exportfs: %s\n", buf);
-
- if(srv == nil && srvfd == -1 && write(0, "OK", 2) != 2)
- fatal("open ack write");
-
- ini = initial;
- n = readn(0, initial, sizeof(initial));
- if(n == 0)
- fatal(nil); /* port scan or spurious open/close on exported /srv file (unmount) */
- if(n < sizeof(initial))
- fatal("can't read initial string: %r");
-
- if(memcmp(ini, "impo", 4) == 0) {
- char buf[128], *p, *args[3];
-
- ini = nil;
- p = buf;
- for(;;){
- if((n = read(0, p, 1)) < 0)
- fatal("can't read impo arguments: %r");
- if(n == 0)
- fatal("connection closed while reading arguments");
- if(*p == '\n')
- *p = '\0';
- if(*p++ == '\0')
- break;
- if(p >= buf + sizeof(buf))
- fatal("import parameters too long");
- }
-
- if(tokenize(buf, args, nelem(args)) != 2)
- fatal("impo arguments invalid: impo%s...", buf);
-
- if(strcmp(args[0], "aan") == 0)
- filterp = aanfilter;
- else if(strcmp(args[0], "nofilter") != 0)
- fatal("import filter argument unsupported: %s", args[0]);
-
- if(strcmp(args[1], "ssl") == 0)
- encproto = Encssl;
- else if(strcmp(args[1], "tls") == 0)
- encproto = Enctls;
- else if(strcmp(args[1], "clear") != 0)
- fatal("import encryption proto unsupported: %s", args[1]);
-
- if(encproto == Enctls)
- fatal("%s: tls has not yet been implemented", argv[0]);
- }
-
- if(encproto != Encnone && ealgs != nil && ai != nil) {
- uchar key[16], digest[SHA1dlen];
- char fromclientsecret[21];
- char fromserversecret[21];
- int i;
-
- if(ai->nsecret < 8)
- fatal("secret too small for ssl");
- memmove(key+4, ai->secret, 8);
-
- /* exchange random numbers */
- srand(truerand());
- for(i = 0; i < 4; i++)
- key[i+12] = rand();
-
- if(ini != nil)
- fatal("Protocol botch: old import");
- if(readn(0, key, 4) != 4)
- fatal("can't read key part; %r");
-
- if(write(0, key+12, 4) != 4)
- fatal("can't write key part; %r");
-
- /* scramble into two secrets */
- sha1(key, sizeof(key), digest, nil);
- mksecret(fromclientsecret, digest);
- mksecret(fromserversecret, digest+10);
-
- if(filterp != nil)
- filter(0, filterp, na);
-
- switch(encproto) {
- case Encssl:
- fd = pushssl(0, ealgs, fromserversecret, fromclientsecret, nil);
- if(fd < 0)
- fatal("can't establish ssl connection: %r");
- if(fd != 0){
- dup(fd, 0);
- close(fd);
- }
- break;
- case Enctls:
- default:
- fatal("Unsupported encryption protocol");
- }
- }
- else if(filterp != nil) {
- if(ini != nil)
- fatal("Protocol botch: don't know how to deal with this");
- filter(0, filterp, na);
- }
- dup(0, 1);
-
- if(ai != nil)
- auth_freeAI(ai);
-
- if(ini != nil){
- r = getsbuf();
- memmove(r->buf, ini, BIT32SZ);
- n = GBIT32(r->buf);
- if(n <= BIT32SZ || n > messagesize)
- fatal("bad length in 9P2000 message header");
- n -= BIT32SZ;
- if(readn(0, r->buf+BIT32SZ, n) != n)
- fatal(nil);
- n += BIT32SZ;
- goto Message;
- }
-
- /*
- * Start serving file requests from the network
- */
- for(;;) {
- r = getsbuf();
- n = read9pmsg(0, r->buf, messagesize);
- if(n <= 0)
- fatal(nil);
- Message:
- if(convM2S(r->buf, n, &r->work) != n)
- fatal("convM2S format error");
-
- DEBUG(DFD, "%F\n", &r->work);
- (fcalls[r->work.type])(r);
- }
-}
-
-void
-reply(Fcall *r, Fcall *t, char *err)
-{
- uchar *data;
- int n;
-
- t->tag = r->tag;
- t->fid = r->fid;
- if(err != nil) {
- t->type = Rerror;
- t->ename = err;
- }
- else
- t->type = r->type + 1;
-
- DEBUG(DFD, "\t%F\n", t);
-
- data = malloc(messagesize); /* not mallocz; no need to clear */
- if(data == nil)
- fatal(Enomem);
- n = convS2M(t, data, messagesize);
- if(write(0, data, n) != n){
- /* not fatal, might have got a note due to flush */
- fprint(2, "exportfs: short write in reply: %r\n");
- }
- free(data);
-}
-
-Fid *
-getfid(int nr)
-{
- Fid *f;
-
- for(f = fidhash(nr); f != nil; f = f->next)
- if(f->nr == nr)
- return f;
-
- return nil;
-}
-
-int
-freefid(int nr)
-{
- Fid *f, **l;
- char buf[128];
-
- l = &fidhash(nr);
- for(f = *l; f != nil; f = f->next) {
- if(f->nr == nr) {
- if(f->mid) {
- snprint(buf, sizeof(buf), "/mnt/exportfs/%d", f->mid);
- unmount(0, buf);
- psmap[f->mid] = 0;
- }
- if(f->f != nil) {
- freefile(f->f);
- f->f = nil;
- }
- if(f->dir != nil){
- free(f->dir);
- f->dir = nil;
- }
- *l = f->next;
- f->next = fidfree;
- fidfree = f;
- return 1;
- }
- l = &f->next;
- }
-
- return 0;
-}
-
-Fid *
-newfid(int nr)
-{
- Fid *new, **l;
- int i;
-
- l = &fidhash(nr);
- for(new = *l; new != nil; new = new->next)
- if(new->nr == nr)
- return nil;
-
- if(fidfree == nil) {
- fidfree = emallocz(sizeof(Fid) * Fidchunk);
-
- for(i = 0; i < Fidchunk-1; i++)
- fidfree[i].next = &fidfree[i+1];
-
- fidfree[Fidchunk-1].next = nil;
- }
-
- new = fidfree;
- fidfree = new->next;
-
- memset(new, 0, sizeof(Fid));
- new->next = *l;
- *l = new;
- new->nr = nr;
- new->fid = -1;
- new->mid = 0;
-
- return new;
-}
-
-static struct {
- Lock;
- Fsrpc *free;
-
- /* statistics */
- int nalloc;
- int nfree;
-} sbufalloc;
-
-Fsrpc *
-getsbuf(void)
-{
- Fsrpc *w;
-
- lock(&sbufalloc);
- w = sbufalloc.free;
- if(w != nil){
- sbufalloc.free = w->next;
- w->next = nil;
- sbufalloc.nfree--;
- unlock(&sbufalloc);
- } else {
- sbufalloc.nalloc++;
- unlock(&sbufalloc);
- w = emallocz(sizeof(*w) + messagesize);
- }
- w->flushtag = NOTAG;
- return w;
-}
-
-void
-putsbuf(Fsrpc *w)
-{
- w->flushtag = NOTAG;
- lock(&sbufalloc);
- w->next = sbufalloc.free;
- sbufalloc.free = w;
- sbufalloc.nfree++;
- unlock(&sbufalloc);
-}
-
-void
-freefile(File *f)
-{
- File *parent, *child;
-
- while(--f->ref == 0){
- freecnt++;
- DEBUG(DFD, "free %s\n", f->name);
- /* delete from parent */
- parent = f->parent;
- if(parent->child == f)
- parent->child = f->childlist;
- else{
- for(child = parent->child; child->childlist != f; child = child->childlist) {
- if(child->childlist == nil)
- fatal("bad child list");
- }
- child->childlist = f->childlist;
- }
- freeqid(f->qidt);
- free(f->name);
- free(f);
- f = parent;
- }
-}
-
-File *
-file(File *parent, char *name)
-{
- Dir *dir;
- char *path;
- File *f;
-
- DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name);
-
- path = makepath(parent, name);
- if(patternfile != nil && excludefile(path)){
- free(path);
- return nil;
- }
- dir = dirstat(path);
- free(path);
- if(dir == nil)
- return nil;
-
- for(f = parent->child; f != nil; f = f->childlist)
- if(strcmp(name, f->name) == 0)
- break;
-
- if(f == nil){
- f = emallocz(sizeof(File));
- f->name = estrdup(name);
-
- f->parent = parent;
- f->childlist = parent->child;
- parent->child = f;
- parent->ref++;
- f->ref = 0;
- filecnt++;
- }
- f->ref++;
- f->qid.type = dir->qid.type;
- f->qid.vers = dir->qid.vers;
- f->qidt = uniqueqid(dir);
- f->qid.path = f->qidt->uniqpath;
-
- f->inval = 0;
-
- free(dir);
-
- return f;
-}
-
-void
-initroot(void)
-{
- Dir *dir;
-
- root = emallocz(sizeof(File));
- root->name = estrdup(".");
-
- dir = dirstat(root->name);
- if(dir == nil)
- fatal("root stat");
-
- root->ref = 1;
- root->qid.vers = dir->qid.vers;
- root->qidt = uniqueqid(dir);
- root->qid.path = root->qidt->uniqpath;
- root->qid.type = QTDIR;
- free(dir);
-
- psmpt = emallocz(sizeof(File));
- psmpt->name = estrdup("/");
-
- dir = dirstat(psmpt->name);
- if(dir == nil)
- return;
-
- psmpt->ref = 1;
- psmpt->qid.vers = dir->qid.vers;
- psmpt->qidt = uniqueqid(dir);
- psmpt->qid.path = psmpt->qidt->uniqpath;
- free(dir);
-
- psmpt = file(psmpt, "mnt");
- if(psmpt == nil)
- return;
- psmpt = file(psmpt, "exportfs");
-}
-
-char*
-makepath(File *p, char *name)
-{
- int i, n;
- char *c, *s, *path, *seg[256];
-
- seg[0] = name;
- n = strlen(name)+2;
- for(i = 1; i < 256 && p; i++, p = p->parent){
- seg[i] = p->name;
- n += strlen(p->name)+1;
- }
- path = emallocz(n);
- s = path;
-
- while(i--) {
- for(c = seg[i]; *c; c++)
- *s++ = *c;
- *s++ = '/';
- }
- while(s[-1] == '/')
- s--;
- *s = '\0';
-
- return path;
-}
-
-int
-qidhash(vlong path)
-{
- int h, n;
-
- h = 0;
- for(n=0; n<64; n+=Nqidbits){
- h ^= path;
- path >>= Nqidbits;
- }
- return h & (Nqidtab-1);
-}
-
-void
-freeqid(Qidtab *q)
-{
- ulong h;
- Qidtab *l;
-
- if(--q->ref)
- return;
- qfreecnt++;
- h = qidhash(q->path);
- if(qidtab[h] == q)
- qidtab[h] = q->next;
- else{
- for(l=qidtab[h]; l->next!=q; l=l->next)
- if(l->next == nil)
- fatal("bad qid list");
- l->next = q->next;
- }
- free(q);
-}
-
-Qidtab*
-qidlookup(Dir *d)
-{
- ulong h;
- Qidtab *q;
-
- h = qidhash(d->qid.path);
- for(q=qidtab[h]; q!=nil; q=q->next)
- if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path)
- return q;
- return nil;
-}
-
-int
-qidexists(vlong path)
-{
- int h;
- Qidtab *q;
-
- for(h=0; h<Nqidtab; h++)
- for(q=qidtab[h]; q!=nil; q=q->next)
- if(q->uniqpath == path)
- return 1;
- return 0;
-}
-
-Qidtab*
-uniqueqid(Dir *d)
-{
- ulong h;
- vlong path;
- Qidtab *q;
-
- q = qidlookup(d);
- if(q != nil){
- q->ref++;
- return q;
- }
- path = d->qid.path;
- while(qidexists(path)){
- DEBUG(DFD, "collision on %s\n", d->name);
- /* collision: find a new one */
- ncollision++;
- path &= QIDPATH;
- ++newqid;
- if(newqid >= (1<<16)){
- DEBUG(DFD, "collision wraparound\n");
- newqid = 1;
- }
- path |= newqid<<48;
- DEBUG(DFD, "assign qid %.16llux\n", path);
- }
- qidcnt++;
- q = emallocz(sizeof(Qidtab));
- q->ref = 1;
- q->type = d->type;
- q->dev = d->dev;
- q->path = d->qid.path;
- q->uniqpath = path;
- h = qidhash(d->qid.path);
- q->next = qidtab[h];
- qidtab[h] = q;
- return q;
-}
-
-void
-fatal(char *s, ...)
-{
- char buf[ERRMAX];
- va_list arg;
- Proc *m;
-
- if(s != nil) {
- va_start(arg, s);
- vsnprint(buf, ERRMAX, s, arg);
- va_end(arg);
- }
-
- /* Clear away the slave children */
- for(m = Proclist; m != nil; m = m->next)
- postnote(PNPROC, m->pid, "kill");
-
- if(s != nil) {
- DEBUG(DFD, "%s\n", buf);
- sysfatal("%s", buf); /* caution: buf could contain '%' */
- } else
- exits(nil);
-}
-
-void*
-emallocz(uint n)
-{
- void *p;
-
- p = mallocz(n, 1);
- if(p == nil)
- fatal(Enomem);
- setmalloctag(p, getcallerpc(&n));
- return p;
-}
-
-char*
-estrdup(char *s)
-{
- char *t;
-
- t = strdup(s);
- if(t == nil)
- fatal(Enomem);
- setmalloctag(t, getcallerpc(&s));
- return t;
-}
-
-void
-filter(int fd, char *cmd, char *host)
-{
- char addr[128], buf[256], *s, *file, *argv[16];
- int lfd, p[2], len, argc;
-
- if(host == nil){
- /* Get a free port and post it to the client. */
- if (announce(anstring, addr) < 0)
- fatal("filter: Cannot announce %s: %r", anstring);
-
- snprint(buf, sizeof(buf), "%s/local", addr);
- if ((lfd = open(buf, OREAD)) < 0)
- fatal("filter: Cannot open %s: %r", buf);
- if ((len = read(lfd, buf, sizeof buf - 1)) < 0)
- fatal("filter: Cannot read %s: %r", buf);
- close(lfd);
- buf[len] = '\0';
- if ((s = strchr(buf, '\n')) != nil)
- len = s - buf;
- if (write(fd, buf, len) != len)
- fatal("filter: cannot write port; %r");
- } else {
- /* Read address string from connection */
- if ((len = read(fd, buf, sizeof buf - 1)) < 0)
- sysfatal("filter: cannot write port; %r");
- buf[len] = '\0';
-
- if ((s = strrchr(buf, '!')) == nil)
- sysfatal("filter: illegally formatted port %s", buf);
- strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1));
- strecpy(strrchr(addr, '!'), addr+sizeof(addr), s);
- }
-
- DEBUG(DFD, "filter: %s\n", addr);
-
- snprint(buf, sizeof(buf), "%s", cmd);
- argc = tokenize(buf, argv, nelem(argv)-3);
- if (argc == 0)
- sysfatal("filter: empty command");
-
- if(host != nil)
- argv[argc++] = "-c";
- argv[argc++] = addr;
- argv[argc] = nil;
-
- file = argv[0];
- if((s = strrchr(argv[0], '/')) != nil)
- argv[0] = s+1;
-
- if(pipe(p) < 0)
- sysfatal("pipe: %r");
-
- switch(rfork(RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND)) {
- case -1:
- fatal("filter: rfork; %r\n");
- case 0:
- close(fd);
- if (dup(p[0], 1) < 0)
- fatal("filter: Cannot dup to 1; %r");
- if (dup(p[0], 0) < 0)
- fatal("filter: Cannot dup to 0; %r");
- close(p[0]);
- close(p[1]);
- exec(file, argv);
- fatal("filter: exec; %r");
- default:
- dup(p[1], fd);
- close(p[0]);
- close(p[1]);
- }
-}
-
-static void
-mksecret(char *t, uchar *f)
-{
- sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
- f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
+ io();
}
diff --git a/sys/src/cmd/exportfs/exportfs.h b/sys/src/cmd/exportfs/exportfs.h
index b3587fab2..344304b7c 100644
--- a/sys/src/cmd/exportfs/exportfs.h
+++ b/sys/src/cmd/exportfs/exportfs.h
@@ -112,7 +112,10 @@ void Xwalk(Fsrpc*);
void Xwstat(Fsrpc*);
void slave(Fsrpc*);
+void io(void);
void reply(Fcall*, Fcall*, char*);
+void mounterror(char*);
+
Fid *getfid(int);
int freefid(int);
Fid *newfid(int);
diff --git a/sys/src/cmd/exportfs/exportsrv.c b/sys/src/cmd/exportfs/exportsrv.c
index a413ed0dc..b7ddd64b5 100644
--- a/sys/src/cmd/exportfs/exportsrv.c
+++ b/sys/src/cmd/exportfs/exportsrv.c
@@ -5,8 +5,6 @@
#define Extern extern
#include "exportfs.h"
-extern char *netdir, *local, *remote;
-
char Ebadfid[] = "Bad fid";
char Enotdir[] = "Not a directory";
char Edupfid[] = "Fid already in use";
@@ -493,12 +491,6 @@ slave(Fsrpc *f)
return;
case 0:
- if (local[0] != '\0')
- if (netdir[0] != '\0')
- procsetname("%s: %s -> %s", netdir,
- local, remote);
- else
- procsetname("%s -> %s", local, remote);
blockingslave(m);
_exits(0);
diff --git a/sys/src/cmd/exportfs/io.c b/sys/src/cmd/exportfs/io.c
new file mode 100644
index 000000000..ad1d7154b
--- /dev/null
+++ b/sys/src/cmd/exportfs/io.c
@@ -0,0 +1,503 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#define Extern
+#include "exportfs.h"
+
+#define QIDPATH ((1LL<<48)-1)
+vlong newqid = 0;
+
+void (*fcalls[])(Fsrpc*) =
+{
+ [Tversion] Xversion,
+ [Tauth] Xauth,
+ [Tflush] Xflush,
+ [Tattach] Xattach,
+ [Twalk] Xwalk,
+ [Topen] slave,
+ [Tcreate] Xcreate,
+ [Tclunk] Xclunk,
+ [Tread] slave,
+ [Twrite] slave,
+ [Tremove] Xremove,
+ [Tstat] Xstat,
+ [Twstat] Xwstat,
+};
+
+/* accounting and debugging counters */
+int filecnt;
+int freecnt;
+int qidcnt;
+int qfreecnt;
+int ncollision;
+
+
+/*
+ * Start serving file requests from the network
+ */
+void
+io(void)
+{
+ Fsrpc *r;
+ int n;
+
+ for(;;) {
+ r = getsbuf();
+ n = read9pmsg(0, r->buf, messagesize);
+ if(n <= 0)
+ fatal(nil);
+ if(convM2S(r->buf, n, &r->work) != n)
+ fatal("convM2S format error");
+
+ DEBUG(DFD, "%F\n", &r->work);
+ (fcalls[r->work.type])(r);
+ }
+}
+
+void
+reply(Fcall *r, Fcall *t, char *err)
+{
+ uchar *data;
+ int n;
+
+ t->tag = r->tag;
+ t->fid = r->fid;
+ if(err != nil) {
+ t->type = Rerror;
+ t->ename = err;
+ }
+ else
+ t->type = r->type + 1;
+
+ DEBUG(DFD, "\t%F\n", t);
+
+ data = malloc(messagesize); /* not mallocz; no need to clear */
+ if(data == nil)
+ fatal(Enomem);
+ n = convS2M(t, data, messagesize);
+ if(write(1, data, n) != n){
+ /* not fatal, might have got a note due to flush */
+ fprint(2, "exportfs: short write in reply: %r\n");
+ }
+ free(data);
+}
+
+void
+mounterror(char *err)
+{
+ Fsrpc *r;
+ int n;
+
+ r = getsbuf();
+ r->work.tag = NOTAG;
+ r->work.fid = NOFID;
+ r->work.type = Rerror;
+ r->work.ename = err;
+ n = convS2M(&r->work, r->buf, messagesize);
+ write(1, r->buf, n);
+ exits(err);
+}
+
+Fid *
+getfid(int nr)
+{
+ Fid *f;
+
+ for(f = fidhash(nr); f != nil; f = f->next)
+ if(f->nr == nr)
+ return f;
+
+ return nil;
+}
+
+int
+freefid(int nr)
+{
+ Fid *f, **l;
+ char buf[128];
+
+ l = &fidhash(nr);
+ for(f = *l; f != nil; f = f->next) {
+ if(f->nr == nr) {
+ if(f->mid) {
+ snprint(buf, sizeof(buf), "/mnt/exportfs/%d", f->mid);
+ unmount(0, buf);
+ psmap[f->mid] = 0;
+ }
+ if(f->f != nil) {
+ freefile(f->f);
+ f->f = nil;
+ }
+ if(f->dir != nil){
+ free(f->dir);
+ f->dir = nil;
+ }
+ *l = f->next;
+ f->next = fidfree;
+ fidfree = f;
+ return 1;
+ }
+ l = &f->next;
+ }
+
+ return 0;
+}
+
+Fid *
+newfid(int nr)
+{
+ Fid *new, **l;
+ int i;
+
+ l = &fidhash(nr);
+ for(new = *l; new != nil; new = new->next)
+ if(new->nr == nr)
+ return nil;
+
+ if(fidfree == nil) {
+ fidfree = emallocz(sizeof(Fid) * Fidchunk);
+
+ for(i = 0; i < Fidchunk-1; i++)
+ fidfree[i].next = &fidfree[i+1];
+
+ fidfree[Fidchunk-1].next = nil;
+ }
+
+ new = fidfree;
+ fidfree = new->next;
+
+ memset(new, 0, sizeof(Fid));
+ new->next = *l;
+ *l = new;
+ new->nr = nr;
+ new->fid = -1;
+ new->mid = 0;
+
+ return new;
+}
+
+static struct {
+ Lock;
+ Fsrpc *free;
+
+ /* statistics */
+ int nalloc;
+ int nfree;
+} sbufalloc;
+
+Fsrpc *
+getsbuf(void)
+{
+ Fsrpc *w;
+
+ lock(&sbufalloc);
+ w = sbufalloc.free;
+ if(w != nil){
+ sbufalloc.free = w->next;
+ w->next = nil;
+ sbufalloc.nfree--;
+ unlock(&sbufalloc);
+ } else {
+ sbufalloc.nalloc++;
+ unlock(&sbufalloc);
+ w = emallocz(sizeof(*w) + messagesize);
+ }
+ w->flushtag = NOTAG;
+ return w;
+}
+
+void
+putsbuf(Fsrpc *w)
+{
+ w->flushtag = NOTAG;
+ lock(&sbufalloc);
+ w->next = sbufalloc.free;
+ sbufalloc.free = w;
+ sbufalloc.nfree++;
+ unlock(&sbufalloc);
+}
+
+void
+freefile(File *f)
+{
+ File *parent, *child;
+
+ while(--f->ref == 0){
+ freecnt++;
+ DEBUG(DFD, "free %s\n", f->name);
+ /* delete from parent */
+ parent = f->parent;
+ if(parent->child == f)
+ parent->child = f->childlist;
+ else{
+ for(child = parent->child; child->childlist != f; child = child->childlist) {
+ if(child->childlist == nil)
+ fatal("bad child list");
+ }
+ child->childlist = f->childlist;
+ }
+ freeqid(f->qidt);
+ free(f->name);
+ free(f);
+ f = parent;
+ }
+}
+
+File *
+file(File *parent, char *name)
+{
+ Dir *dir;
+ char *path;
+ File *f;
+
+ DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name);
+
+ path = makepath(parent, name);
+ if(patternfile != nil && excludefile(path)){
+ free(path);
+ return nil;
+ }
+ dir = dirstat(path);
+ free(path);
+ if(dir == nil)
+ return nil;
+
+ for(f = parent->child; f != nil; f = f->childlist)
+ if(strcmp(name, f->name) == 0)
+ break;
+
+ if(f == nil){
+ f = emallocz(sizeof(File));
+ f->name = estrdup(name);
+
+ f->parent = parent;
+ f->childlist = parent->child;
+ parent->child = f;
+ parent->ref++;
+ f->ref = 0;
+ filecnt++;
+ }
+ f->ref++;
+ f->qid.type = dir->qid.type;
+ f->qid.vers = dir->qid.vers;
+ f->qidt = uniqueqid(dir);
+ f->qid.path = f->qidt->uniqpath;
+
+ f->inval = 0;
+
+ free(dir);
+
+ return f;
+}
+
+void
+initroot(void)
+{
+ Dir *dir;
+
+ root = emallocz(sizeof(File));
+ root->name = estrdup(".");
+
+ dir = dirstat(root->name);
+ if(dir == nil)
+ fatal("root stat");
+
+ root->ref = 1;
+ root->qid.vers = dir->qid.vers;
+ root->qidt = uniqueqid(dir);
+ root->qid.path = root->qidt->uniqpath;
+ root->qid.type = QTDIR;
+ free(dir);
+
+ psmpt = emallocz(sizeof(File));
+ psmpt->name = estrdup("/");
+
+ dir = dirstat(psmpt->name);
+ if(dir == nil)
+ return;
+
+ psmpt->ref = 1;
+ psmpt->qid.vers = dir->qid.vers;
+ psmpt->qidt = uniqueqid(dir);
+ psmpt->qid.path = psmpt->qidt->uniqpath;
+ free(dir);
+
+ psmpt = file(psmpt, "mnt");
+ if(psmpt == nil)
+ return;
+ psmpt = file(psmpt, "exportfs");
+}
+
+char*
+makepath(File *p, char *name)
+{
+ int i, n;
+ char *c, *s, *path, *seg[256];
+
+ seg[0] = name;
+ n = strlen(name)+2;
+ for(i = 1; i < 256 && p; i++, p = p->parent){
+ seg[i] = p->name;
+ n += strlen(p->name)+1;
+ }
+ path = emallocz(n);
+ s = path;
+
+ while(i--) {
+ for(c = seg[i]; *c; c++)
+ *s++ = *c;
+ *s++ = '/';
+ }
+ while(s[-1] == '/')
+ s--;
+ *s = '\0';
+
+ return path;
+}
+
+int
+qidhash(vlong path)
+{
+ int h, n;
+
+ h = 0;
+ for(n=0; n<64; n+=Nqidbits){
+ h ^= path;
+ path >>= Nqidbits;
+ }
+ return h & (Nqidtab-1);
+}
+
+void
+freeqid(Qidtab *q)
+{
+ ulong h;
+ Qidtab *l;
+
+ if(--q->ref)
+ return;
+ qfreecnt++;
+ h = qidhash(q->path);
+ if(qidtab[h] == q)
+ qidtab[h] = q->next;
+ else{
+ for(l=qidtab[h]; l->next!=q; l=l->next)
+ if(l->next == nil)
+ fatal("bad qid list");
+ l->next = q->next;
+ }
+ free(q);
+}
+
+Qidtab*
+qidlookup(Dir *d)
+{
+ ulong h;
+ Qidtab *q;
+
+ h = qidhash(d->qid.path);
+ for(q=qidtab[h]; q!=nil; q=q->next)
+ if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path)
+ return q;
+ return nil;
+}
+
+int
+qidexists(vlong path)
+{
+ int h;
+ Qidtab *q;
+
+ for(h=0; h<Nqidtab; h++)
+ for(q=qidtab[h]; q!=nil; q=q->next)
+ if(q->uniqpath == path)
+ return 1;
+ return 0;
+}
+
+Qidtab*
+uniqueqid(Dir *d)
+{
+ ulong h;
+ vlong path;
+ Qidtab *q;
+
+ q = qidlookup(d);
+ if(q != nil){
+ q->ref++;
+ return q;
+ }
+ path = d->qid.path;
+ while(qidexists(path)){
+ DEBUG(DFD, "collision on %s\n", d->name);
+ /* collision: find a new one */
+ ncollision++;
+ path &= QIDPATH;
+ ++newqid;
+ if(newqid >= (1<<16)){
+ DEBUG(DFD, "collision wraparound\n");
+ newqid = 1;
+ }
+ path |= newqid<<48;
+ DEBUG(DFD, "assign qid %.16llux\n", path);
+ }
+ qidcnt++;
+ q = emallocz(sizeof(Qidtab));
+ q->ref = 1;
+ q->type = d->type;
+ q->dev = d->dev;
+ q->path = d->qid.path;
+ q->uniqpath = path;
+ h = qidhash(d->qid.path);
+ q->next = qidtab[h];
+ qidtab[h] = q;
+ return q;
+}
+
+void
+fatal(char *s, ...)
+{
+ char buf[ERRMAX];
+ va_list arg;
+ Proc *m;
+
+ if(s != nil) {
+ va_start(arg, s);
+ vsnprint(buf, ERRMAX, s, arg);
+ va_end(arg);
+ }
+
+ /* Clear away the slave children */
+ for(m = Proclist; m != nil; m = m->next)
+ postnote(PNPROC, m->pid, "kill");
+
+ if(s != nil) {
+ DEBUG(DFD, "%s\n", buf);
+ sysfatal("%s", buf); /* caution: buf could contain '%' */
+ } else
+ exits(nil);
+}
+
+void*
+emallocz(uint n)
+{
+ void *p;
+
+ p = mallocz(n, 1);
+ if(p == nil)
+ fatal(Enomem);
+ setmalloctag(p, getcallerpc(&n));
+ return p;
+}
+
+char*
+estrdup(char *s)
+{
+ char *t;
+
+ t = strdup(s);
+ if(t == nil)
+ fatal(Enomem);
+ setmalloctag(t, getcallerpc(&s));
+ return t;
+}
diff --git a/sys/src/cmd/exportfs/mkfile b/sys/src/cmd/exportfs/mkfile
index cf1f51451..df89c4def 100644
--- a/sys/src/cmd/exportfs/mkfile
+++ b/sys/src/cmd/exportfs/mkfile
@@ -1,10 +1,10 @@
</$objtype/mkfile
-TARG=exportfs
+TARG=exportfs oexportfs
OFILES=\
- exportfs.$O\
exportsrv.$O\
pattern.$O\
+ io.$O\
HFILES=exportfs.h\
@@ -15,4 +15,4 @@ UPDATE=\
$HFILES\
${OFILES:%.$O=%.c}\
-</sys/src/cmd/mkone
+</sys/src/cmd/mkmany
diff --git a/sys/src/cmd/exportfs/oexportfs.c b/sys/src/cmd/exportfs/oexportfs.c
new file mode 100644
index 000000000..c6683a174
--- /dev/null
+++ b/sys/src/cmd/exportfs/oexportfs.c
@@ -0,0 +1,443 @@
+/*
+ * oexportfs - legacy exportfs for cpu and import
+ */
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include <libsec.h>
+#define Extern
+#include "exportfs.h"
+
+enum {
+ Encnone,
+ Encssl,
+ Enctls,
+};
+
+int srvfd = -1;
+int nonone = 1;
+char *filterp;
+char *ealgs = "rc4_256 sha1";
+char *aanfilter = "/bin/aan";
+int encproto = Encnone;
+int readonly;
+
+static char *anstring = "tcp!*!0";
+
+static void
+filter(int fd, char *cmd, char *host)
+{
+ char addr[128], buf[256], *s, *file, *argv[16];
+ int lfd, p[2], len, argc;
+
+ if(host == nil){
+ /* Get a free port and post it to the client. */
+ if (announce(anstring, addr) < 0)
+ fatal("filter: Cannot announce %s: %r", anstring);
+
+ snprint(buf, sizeof(buf), "%s/local", addr);
+ if ((lfd = open(buf, OREAD)) < 0)
+ fatal("filter: Cannot open %s: %r", buf);
+ if ((len = read(lfd, buf, sizeof buf - 1)) < 0)
+ fatal("filter: Cannot read %s: %r", buf);
+ close(lfd);
+ buf[len] = '\0';
+ if ((s = strchr(buf, '\n')) != nil)
+ len = s - buf;
+ if (write(fd, buf, len) != len)
+ fatal("filter: cannot write port; %r");
+ } else {
+ /* Read address string from connection */
+ if ((len = read(fd, buf, sizeof buf - 1)) < 0)
+ sysfatal("filter: cannot write port; %r");
+ buf[len] = '\0';
+
+ if ((s = strrchr(buf, '!')) == nil)
+ sysfatal("filter: illegally formatted port %s", buf);
+ strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1));
+ strecpy(strrchr(addr, '!'), addr+sizeof(addr), s);
+ }
+
+ DEBUG(DFD, "filter: %s\n", addr);
+
+ snprint(buf, sizeof(buf), "%s", cmd);
+ argc = tokenize(buf, argv, nelem(argv)-3);
+ if (argc == 0)
+ sysfatal("filter: empty command");
+
+ if(host != nil)
+ argv[argc++] = "-c";
+ argv[argc++] = addr;
+ argv[argc] = nil;
+
+ file = argv[0];
+ if((s = strrchr(argv[0], '/')) != nil)
+ argv[0] = s+1;
+
+ if(pipe(p) < 0)
+ sysfatal("pipe: %r");
+
+ switch(rfork(RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND)) {
+ case -1:
+ fatal("filter: rfork; %r\n");
+ case 0:
+ close(fd);
+ if (dup(p[0], 1) < 0)
+ fatal("filter: Cannot dup to 1; %r");
+ if (dup(p[0], 0) < 0)
+ fatal("filter: Cannot dup to 0; %r");
+ close(p[0]);
+ close(p[1]);
+ exec(file, argv);
+ fatal("filter: exec; %r");
+ default:
+ dup(p[1], fd);
+ close(p[0]);
+ close(p[1]);
+ }
+}
+
+static void
+mksecret(char *t, uchar *f)
+{
+ sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
+ f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [-adnsR] [-f dbgfile] [-m msize] [-r root] "
+ "[-S srvfile] [-e 'crypt hash'] [-P exclusion-file] "
+ "[-A announce-string] [-B address]\n", argv0);
+ fatal("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ char buf[ERRMAX], ebuf[ERRMAX], initial[4], *ini, *srvfdfile;
+ char *dbfile, *srv, *na, *nsfile, *keyspec;
+ int doauth, n, fd;
+ AuthInfo *ai;
+ Fsrpc *r;
+
+ dbfile = "/tmp/exportdb";
+ srv = nil;
+ srvfd = -1;
+ srvfdfile = nil;
+ na = nil;
+ nsfile = nil;
+ keyspec = "";
+ doauth = 0;
+
+ ai = nil;
+ ARGBEGIN{
+ case 'a':
+ doauth = 1;
+ break;
+
+ case 'd':
+ dbg++;
+ break;
+
+ case 'e':
+ ealgs = EARGF(usage());
+ if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
+ ealgs = nil;
+ break;
+
+ case 'f':
+ dbfile = EARGF(usage());
+ break;
+
+ case 'k':
+ keyspec = EARGF(usage());
+ break;
+
+ case 'm':
+ messagesize = strtoul(EARGF(usage()), nil, 0);
+ break;
+
+ case 'n':
+ nonone = 0;
+ break;
+
+ case 'r':
+ srv = EARGF(usage());
+ break;
+
+ case 's':
+ srv = "/";
+ break;
+
+ case 'A':
+ anstring = EARGF(usage());
+ break;
+
+ case 'B':
+ na = EARGF(usage());
+ break;
+
+ case 'F':
+ /* accepted but ignored, for backwards compatibility */
+ break;
+
+ case 'N':
+ nsfile = EARGF(usage());
+ break;
+
+ case 'P':
+ patternfile = EARGF(usage());
+ break;
+
+ case 'R':
+ readonly = 1;
+ break;
+
+ case 'S':
+ if(srvfdfile != nil)
+ usage();
+ srvfdfile = EARGF(usage());
+ break;
+
+ default:
+ usage();
+ }ARGEND
+ USED(argc, argv);
+
+ if(na == nil && doauth){
+ /*
+ * We use p9any so we don't have to visit this code again, with the
+ * cost that this code is incompatible with the old world, which
+ * requires p9sk2. (The two differ in who talks first, so compatibility
+ * is awkward.)
+ */
+ ai = auth_proxy(0, auth_getkey, "proto=p9any role=server %s", keyspec);
+ if(ai == nil)
+ fatal("auth_proxy: %r");
+ if(nonone && strcmp(ai->cuid, "none") == 0)
+ fatal("exportfs by none disallowed");
+ if(auth_chuid(ai, nsfile) < 0)
+ fatal("auth_chuid: %r");
+ else { /* chown network connection */
+ Dir nd;
+ nulldir(&nd);
+ nd.mode = 0660;
+ nd.uid = ai->cuid;
+ dirfwstat(0, &nd);
+ }
+ putenv("service", "exportfs");
+ }
+
+ if(srvfdfile != nil){
+ if((srvfd = open(srvfdfile, ORDWR)) < 0)
+ fatal("open %s: %r", srvfdfile);
+ }
+
+ if(na != nil){
+ if(srv == nil)
+ fatal("-B requires -s");
+
+ if((fd = dial(netmkaddr(na, 0, "importfs"), 0, 0, 0)) < 0)
+ fatal("can't dial %s: %r", na);
+
+ ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec);
+ if(ai == nil)
+ fatal("%r: %s", na);
+
+ dup(fd, 0);
+ dup(fd, 1);
+ close(fd);
+ }
+
+ exclusions();
+
+ if(dbg) {
+ n = create(dbfile, OWRITE|OTRUNC, 0666);
+ dup(n, DFD);
+ close(n);
+ }
+
+ if(srvfd >= 0 && srv != nil){
+ fprint(2, "%s: -S cannot be used with -r or -s\n", argv0);
+ usage();
+ }
+
+ DEBUG(DFD, "%s: started\n", argv0);
+
+ rfork(RFNOTEG|RFREND);
+
+ if(messagesize == 0){
+ messagesize = iounit(0);
+ if(messagesize == 0)
+ messagesize = 8192+IOHDRSZ;
+ }
+ fhash = emallocz(sizeof(Fid*)*FHASHSIZE);
+
+ fmtinstall('F', fcallfmt);
+
+ /*
+ * Get tree to serve from network connection,
+ * check we can get there and ack the connection
+ */
+ if(srvfd != -1) {
+ /* do nothing */
+ }
+ else if(srv != nil) {
+ if(chdir(srv) < 0) {
+ ebuf[0] = '\0';
+ errstr(ebuf, sizeof ebuf);
+ DEBUG(DFD, "chdir(\"%s\"): %s\n", srv, ebuf);
+ mounterror(ebuf);
+ }
+ DEBUG(DFD, "invoked as server for %s", srv);
+ strncpy(buf, srv, sizeof buf);
+ }
+ else {
+ buf[0] = 0;
+ n = read(0, buf, sizeof(buf)-1);
+ if(n < 0) {
+ errstr(buf, sizeof buf);
+ fprint(0, "read(0): %s\n", buf);
+ DEBUG(DFD, "read(0): %s\n", buf);
+ exits(buf);
+ }
+ buf[n] = 0;
+ if(chdir(buf) < 0) {
+ errstr(ebuf, sizeof ebuf);
+ fprint(0, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf);
+ DEBUG(DFD, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf);
+ exits(ebuf);
+ }
+ }
+
+ DEBUG(DFD, "\niniting root\n");
+ initroot();
+
+ DEBUG(DFD, "%s: %s\n", argv0, buf);
+
+ if(srv == nil && srvfd == -1 && write(0, "OK", 2) != 2)
+ fatal("open ack write");
+
+ ini = initial;
+ n = readn(0, initial, sizeof(initial));
+ if(n == 0)
+ fatal(nil); /* port scan or spurious open/close on exported /srv file (unmount) */
+ if(n < sizeof(initial))
+ fatal("can't read initial string: %r");
+
+ if(memcmp(ini, "impo", 4) == 0) {
+ char buf[128], *p, *args[3];
+
+ ini = nil;
+ p = buf;
+ for(;;){
+ if((n = read(0, p, 1)) < 0)
+ fatal("can't read impo arguments: %r");
+ if(n == 0)
+ fatal("connection closed while reading arguments");
+ if(*p == '\n')
+ *p = '\0';
+ if(*p++ == '\0')
+ break;
+ if(p >= buf + sizeof(buf))
+ fatal("import parameters too long");
+ }
+
+ if(tokenize(buf, args, nelem(args)) != 2)
+ fatal("impo arguments invalid: impo%s...", buf);
+
+ if(strcmp(args[0], "aan") == 0)
+ filterp = aanfilter;
+ else if(strcmp(args[0], "nofilter") != 0)
+ fatal("import filter argument unsupported: %s", args[0]);
+
+ if(strcmp(args[1], "ssl") == 0)
+ encproto = Encssl;
+ else if(strcmp(args[1], "tls") == 0)
+ encproto = Enctls;
+ else if(strcmp(args[1], "clear") != 0)
+ fatal("import encryption proto unsupported: %s", args[1]);
+
+ if(encproto == Enctls)
+ fatal("%s: tls has not yet been implemented", argv[0]);
+ }
+
+ if(encproto != Encnone && ealgs != nil && ai != nil) {
+ uchar key[16], digest[SHA1dlen];
+ char fromclientsecret[21];
+ char fromserversecret[21];
+ int i;
+
+ if(ai->nsecret < 8)
+ fatal("secret too small for ssl");
+ memmove(key+4, ai->secret, 8);
+
+ /* exchange random numbers */
+ srand(truerand());
+ for(i = 0; i < 4; i++)
+ key[i+12] = rand();
+
+ if(ini != nil)
+ fatal("Protocol botch: old import");
+ if(readn(0, key, 4) != 4)
+ fatal("can't read key part; %r");
+
+ if(write(0, key+12, 4) != 4)
+ fatal("can't write key part; %r");
+
+ /* scramble into two secrets */
+ sha1(key, sizeof(key), digest, nil);
+ mksecret(fromclientsecret, digest);
+ mksecret(fromserversecret, digest+10);
+
+ if(filterp != nil)
+ filter(0, filterp, na);
+
+ switch(encproto) {
+ case Encssl:
+ fd = pushssl(0, ealgs, fromserversecret, fromclientsecret, nil);
+ if(fd < 0)
+ fatal("can't establish ssl connection: %r");
+ if(fd != 0){
+ dup(fd, 0);
+ close(fd);
+ }
+ break;
+ case Enctls:
+ default:
+ fatal("Unsupported encryption protocol");
+ }
+ }
+ else if(filterp != nil) {
+ if(ini != nil)
+ fatal("Protocol botch: don't know how to deal with this");
+ filter(0, filterp, na);
+ }
+ dup(0, 1);
+
+ if(ai != nil)
+ auth_freeAI(ai);
+
+ if(ini != nil){
+ extern void (*fcalls[])(Fsrpc*);
+
+ r = getsbuf();
+ memmove(r->buf, ini, BIT32SZ);
+ n = GBIT32(r->buf);
+ if(n <= BIT32SZ || n > messagesize)
+ fatal("bad length in 9P2000 message header");
+ n -= BIT32SZ;
+ if(readn(0, r->buf+BIT32SZ, n) != n)
+ fatal(nil);
+ n += BIT32SZ;
+
+ if(convM2S(r->buf, n, &r->work) != n)
+ fatal("convM2S format error");
+ DEBUG(DFD, "%F\n", &r->work);
+ (fcalls[r->work.type])(r);
+ }
+ io();
+}
diff --git a/sys/src/cmd/iostats.c b/sys/src/cmd/iostats.c
index e61a7ff94..421f531a9 100644
--- a/sys/src/cmd/iostats.c
+++ b/sys/src/cmd/iostats.c
@@ -354,6 +354,7 @@ main(int argc, char **argv)
sysfatal("fork: %r");
case 0:
dup(efd[0], 0);
+ dup(efd[0], 1);
close(efd[0]);
close(efd[1]);
close(pfd[1]);
diff --git a/sys/src/cmd/nusb/kb/kb.c b/sys/src/cmd/nusb/kb/kb.c
index 7b9ed9f2c..e00c85b99 100644
--- a/sys/src/cmd/nusb/kb/kb.c
+++ b/sys/src/cmd/nusb/kb/kb.c
@@ -637,7 +637,7 @@ hidparse(int t, int f, int g[], int l[], int, void *a)
s->h = v;
break;
- case 0x0D0051: /* Conteact identifier */
+ case 0x0D0051: /* Contact identifier */
s->id = v;
break;
@@ -684,7 +684,7 @@ readerproc(void* a)
{
char err[ERRMAX], mbuf[80];
uchar lastk[64], uk, dk;
- int i, c, nerrs, lastb, nlastk;
+ int i, c, nerrs, bpress, lastb, nlastk;
int abs, x, y, z, b;
Hidreport p;
Hidslot lasts[nelem(p.s)], *s, *l;
@@ -774,7 +774,7 @@ readerproc(void* a)
continue;
/* combine all the slots */
- abs = x = y = z = b = 0;
+ bpress = abs = x = y = z = b = 0;
for(i=0; i<p.ns; *l = *s, i++){
s = &p.s[i];
@@ -785,7 +785,7 @@ readerproc(void* a)
if(l == &lasts[nelem(lasts)-1] || !l->valid)
*l = *s;
- /* convet absolute z to relative */
+ /* convert absolute z to relative */
z += s->z;
if(s->abs & 4)
z -= l->z;
@@ -808,6 +808,7 @@ readerproc(void* a)
b |= 2;
if(s->b & 2)
b |= 4;
+ bpress |= s->m;
/* X/Y are absolute? */
if((s->abs & 3) == 3){
@@ -825,7 +826,9 @@ readerproc(void* a)
y += s->y;
}
}
-
+
+ if(bpress == 0)
+ b = lastb & 7;
if(z != 0)
b |= z > 0 ? 8 : 16;
diff --git a/sys/src/cmd/ptrap.c b/sys/src/cmd/ptrap.c
index 7cf60f7d4..dae3c088d 100644
--- a/sys/src/cmd/ptrap.c
+++ b/sys/src/cmd/ptrap.c
@@ -8,6 +8,7 @@
typedef struct IOProc IOProc;
typedef struct PFilter PFilter;
+typedef struct FAttr FAttr;
typedef struct PFid PFid;
struct IOProc {
@@ -27,11 +28,19 @@ struct PFid {
};
Qid rootqid = {.type QTDIR};
+struct FAttr {
+ char *name;
+ Reprog *filt;
+ int invert;
+ FAttr *next;
+};
+
struct PFilter {
char *name;
Reprog *filt;
- PFilter *next;
int invert;
+ FAttr *attr;
+ PFilter *next;
};
PFilter *filters;
@@ -162,12 +171,32 @@ ptrapopen(Req *r)
}
static int
+filter(PFilter *f, Plumbmsg *pm)
+{
+ FAttr *a;
+ char *value;
+
+ if(!(regexec(f->filt, pm->data, nil, 0) ^ f->invert))
+ return 0;
+ for(a = f->attr; a; a = a->next){
+ value = plumblookup(pm->attr, a->name);
+ if(value == nil)
+ return 0;
+ if(!(regexec(a->filt, value, nil, 0) ^ f->attr->invert))
+ return 0;
+ }
+ return 1;
+}
+
+static int
filterread(Req *r, PFid *pf)
{
int rc, len, more;
char *buf;
Plumbmsg *pm;
+ PFilter *f;
+ f = pf->filter;
for(;;){
if(pf->msg != nil){
rc = r->ifcall.count;
@@ -194,7 +223,7 @@ filterread(Req *r, PFid *pf)
len += rc;
}
free(buf);
- if(regexec(pf->filter->filt, pm->data, nil, 0) ^ pf->filter->invert){
+ if(filter(f, pm)){
pf->msg = plumbpack(pm, &pf->msgn);
pf->msgp = 0;
}
@@ -341,7 +370,7 @@ Srv ptrapsrv = {
void
usage(void)
{
- fprint(2, "usage: %s port regex [ port regex ... ]\n", argv0);
+ fprint(2, "usage: %s port regex [ +attr regex ... ] ...\n", argv0);
exits("usage");
}
@@ -349,6 +378,7 @@ void
threadmain(int argc, char **argv)
{
PFilter *f;
+ FAttr *fa;
char *p;
int i;
@@ -357,19 +387,33 @@ threadmain(int argc, char **argv)
}ARGEND;
if(argc == 0 || argc % 2) usage();
- for(i = 0; i < argc; i += 2){
+ for(i = 0; i+1 < argc;){
+ p = argv[i];
f = emalloc9p(sizeof(PFilter));
- f->name = strdup(argv[i]);
+ f->name = estrdup9p(p);
p = argv[i+1];
- if(*p == '!'){
+ if(p[0] == '!'){
p++;
f->invert = 1;
}
- f->filt = regcomp(p);
- if(f->filt == nil)
- sysfatal("%r");
+ if((f->filt = regcomp(p)) == nil)
+ sysfatal("regcomp: %r");
f->next = filters;
filters = f;
+ for(i += 2; p = argv[i], i+1 < argc && p[0] == '+'; i += 2){
+ p++;
+ fa = emalloc9p(sizeof(FAttr));
+ fa->name = estrdup9p(p);
+ p = argv[i+1];
+ if(p[0] == '!'){
+ p++;
+ fa->invert = 1;
+ }
+ if((fa->filt = regcomp(p)) == nil)
+ sysfatal("regcomp: %r");
+ fa->next = f->attr;
+ f->attr = fa;
+ }
}
threadpostmountsrv(&ptrapsrv, nil, "/mnt/plumb", MREPL | MCREATE);
diff --git a/sys/src/cmd/rio/fsys.c b/sys/src/cmd/rio/fsys.c
index 1562f71e8..be81a1d57 100644
--- a/sys/src/cmd/rio/fsys.c
+++ b/sys/src/cmd/rio/fsys.c
@@ -118,37 +118,27 @@ cexecpipe(int *p0, int *p1)
Filsys*
filsysinit(Channel *cxfidalloc)
{
- int n, fd, pid, p0;
+ int p0;
Filsys *fs;
Channel *c;
- char buf[128];
fs = emalloc(sizeof(Filsys));
if(cexecpipe(&fs->cfd, &fs->sfd) < 0)
goto Rescue;
fmtinstall('F', fcallfmt);
clockfd = open("/dev/time", OREAD|OCEXEC);
- fd = open("/dev/user", OREAD);
- strcpy(buf, "Jean-Paul_Belmondo");
- if(fd >= 0){
- n = read(fd, buf, sizeof buf-1);
- if(n > 0)
- buf[n] = 0;
- close(fd);
- }
- fs->user = estrdup(buf);
+ fs->user = getuser();
fs->csyncflush = chancreate(sizeof(int), 0);
if(fs->csyncflush == nil)
error("chancreate syncflush");
fs->cxfidalloc = cxfidalloc;
- pid = getpid();
/*
* Create and post wctl pipe
*/
if(cexecpipe(&p0, &wctlfd) < 0)
goto Rescue;
- snprint(srvwctl, sizeof(srvwctl), "/srv/riowctl.%s.%d", fs->user, pid);
+ snprint(srvwctl, sizeof(srvwctl), "/srv/riowctl.%s.%lud", fs->user, (ulong)getpid());
post(srvwctl, "wctl", p0);
close(p0);
@@ -165,7 +155,7 @@ filsysinit(Channel *cxfidalloc)
/*
* Post srv pipe
*/
- snprint(srvpipe, sizeof(srvpipe), "/srv/rio.%s.%d", fs->user, pid);
+ snprint(srvpipe, sizeof(srvpipe), "/srv/rio.%s.%lud", fs->user, (ulong)getpid());
post(srvpipe, "wsys", fs->cfd);
return fs;
@@ -234,7 +224,7 @@ filsysmount(Filsys *fs, int id)
char buf[32];
close(fs->sfd); /* close server end so mount won't hang if exiting */
- sprint(buf, "%d", id);
+ snprint(buf, sizeof buf, "%d", id);
if(mount(fs->cfd, -1, "/mnt/wsys", MREPL, buf) == -1){
fprint(2, "mount failed: %r\n");
return -1;
diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c
index a42721fac..a28fb2ccc 100644
--- a/sys/src/cmd/rio/rio.c
+++ b/sys/src/cmd/rio/rio.c
@@ -244,7 +244,7 @@ putsnarf(void)
if(snarffd<0 || nsnarf==0)
return;
- fd = open("/dev/snarf", OWRITE);
+ fd = open("/dev/snarf", OWRITE|OCEXEC);
if(fd < 0)
return;
/* snarf buffer could be huge, so fprint will truncate; do it in blocks */
@@ -394,12 +394,13 @@ portion(int x, int lo, int hi)
{
x -= lo;
hi -= lo;
- if(hi < 20)
- return x > 0 ? 2 : 0;
- if(x < 20)
- return 0;
- if(x > hi-20)
- return 2;
+ if(x < hi/2){
+ if(x < 20)
+ return 0;
+ } else {
+ if(x > hi-20)
+ return 2;
+ }
return 1;
}
@@ -857,7 +858,7 @@ sweep(void)
}
void
-drawedge(Image **bp, Rectangle r)
+drawedge(Image **bp, Image *col, Rectangle r)
{
Image *b = *bp;
if(b != nil && Dx(b->r) == Dx(r) && Dy(b->r) == Dy(r))
@@ -865,28 +866,30 @@ drawedge(Image **bp, Rectangle r)
else{
freeimage(b);
b = allocwindow(wscreen, r, Refbackup, DNofill);
- if(b != nil) draw(b, r, sizecol, nil, ZP);
+ if(b != nil) draw(b, r, col, nil, ZP);
*bp = b;
}
}
void
-drawborder(Rectangle r, int show)
+drawborder(Rectangle r, Image *col)
{
- static Image *b[4];
- int i;
- if(show == 0){
- for(i = 0; i < 4; i++){
- freeimage(b[i]);
- b[i] = nil;
- }
- }else{
+ static Image *b[4], *lastcol;
+
+ if(col != lastcol){
+ freeimage(b[0]), b[0] = nil;
+ freeimage(b[1]), b[1] = nil;
+ freeimage(b[2]), b[2] = nil;
+ freeimage(b[3]), b[3] = nil;
+ }
+ if(col != nil){
r = canonrect(r);
- drawedge(&b[0], Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y));
- drawedge(&b[1], Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth));
- drawedge(&b[2], Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y));
- drawedge(&b[3], Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y));
+ drawedge(&b[0], col, Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y));
+ drawedge(&b[1], col, Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth));
+ drawedge(&b[2], col, Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y));
+ drawedge(&b[3], col, Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y));
}
+ lastcol = col;
}
Image*
@@ -901,17 +904,17 @@ drag(Window *w)
dm = subpt(om, w->screenr.min);
d = subpt(w->screenr.max, w->screenr.min);
op = subpt(om, dm);
- drawborder(Rect(op.x, op.y, op.x+d.x, op.y+d.y), 1);
+ drawborder(Rect(op.x, op.y, op.x+d.x, op.y+d.y), sizecol);
while(mouse->buttons==4){
p = subpt(mouse->xy, dm);
if(!eqpt(p, op)){
- drawborder(Rect(p.x, p.y, p.x+d.x, p.y+d.y), 1);
+ drawborder(Rect(p.x, p.y, p.x+d.x, p.y+d.y), sizecol);
op = p;
}
readmouse(mousectl);
}
r = Rect(op.x, op.y, op.x+d.x, op.y+d.y);
- drawborder(r, 0);
+ drawborder(r, nil);
p = mouse->xy;
riosetcursor(inborder(r, p) ? corners[whichcorner(r, p)] : nil);
menuing = FALSE;
@@ -935,7 +938,7 @@ bandsize(Window *w)
or = w->screenr;
but = mouse->buttons;
startp = onscreen(mouse->xy);
- drawborder(or, 1);
+ drawborder(or, sizecol);
while(mouse->buttons == but) {
p = onscreen(mouse->xy);
which = whichcorner(or, p);
@@ -945,12 +948,14 @@ bandsize(Window *w)
}
r = whichrect(or, p, owhich);
if(!eqrect(r, or) && goodrect(r)){
+ drawborder(r, sizecol);
or = r;
- drawborder(r, 1);
}
readmouse(mousectl);
}
- drawborder(or, 0);
+ drawborder(or, nil);
+ if(!goodrect(or))
+ riosetcursor(nil);
if(mouse->buttons!=0 || !goodrect(or) || eqrect(or, w->screenr)
|| abs(p.x-startp.x)+abs(p.y-startp.y) <= 1){
flushimage(display, 1);
diff --git a/sys/src/cmd/rio/wctl.c b/sys/src/cmd/rio/wctl.c
index 59c9246c9..bef98fda9 100644
--- a/sys/src/cmd/rio/wctl.c
+++ b/sys/src/cmd/rio/wctl.c
@@ -88,14 +88,19 @@ static char *params[] = {
int
goodrect(Rectangle r)
{
- if(!eqrect(canonrect(r), r))
+ if(badrect(r) || !eqrect(canonrect(r), r))
return 0;
/* reasonable sizes only please */
if(Dx(r) > BIG*Dx(screen->r))
return 0;
if(Dy(r) > BIG*Dy(screen->r))
return 0;
- if(Dx(r) < 100 || Dy(r) < 3*font->height)
+ /*
+ * the height has to be big enough to fit one line of text.
+ * that includes the border on each side with an extra pixel
+ * so that the text is still drawn
+ */
+ if(Dx(r) < 100 || Dy(r) < 2*(Borderwidth+1)+font->height)
return 0;
/* window must be on screen */
if(!rectXrect(screen->r, r))
diff --git a/sys/src/cmd/rio/wind.c b/sys/src/cmd/rio/wind.c
index 9734fd18f..1fd1b671c 100644
--- a/sys/src/cmd/rio/wind.c
+++ b/sys/src/cmd/rio/wind.c
@@ -1420,7 +1420,7 @@ wclosewin(Window *w)
void
wsetpid(Window *w, int pid, int dolabel)
{
- char buf[64];
+ char buf[32];
int ofd;
ofd = w->notefd;
@@ -1428,11 +1428,11 @@ wsetpid(Window *w, int pid, int dolabel)
w->notefd = -1;
else {
if(dolabel){
- snprint(buf, sizeof(buf), "rc %d", pid);
+ snprint(buf, sizeof(buf), "rc %lud", (ulong)pid);
free(w->label);
w->label = estrdup(buf);
}
- snprint(buf, sizeof(buf), "/proc/%d/notepg", pid);
+ snprint(buf, sizeof(buf), "/proc/%lud/notepg", (ulong)pid);
w->notefd = open(buf, OWRITE|OCEXEC);
}
if(ofd >= 0)
diff --git a/sys/src/cmd/srvfs.c b/sys/src/cmd/srvfs.c
index d5c028150..a500c8ed2 100644
--- a/sys/src/cmd/srvfs.c
+++ b/sys/src/cmd/srvfs.c
@@ -12,7 +12,7 @@ void
main(int argc, char **argv)
{
char *ename, *arglist[16], **argp;
- int n, fd, pipefd[2];
+ int fd, pipefd[2];
char buf[64];
int perm = 0600;
@@ -39,14 +39,27 @@ main(int argc, char **argv)
*argp++ = "-R";
break;
}ARGEND
- *argp = 0;
if(argc != 2)
usage();
+ *argp++ = "-r";
+ *argp++ = argv[1];
+ *argp = 0;
if(pipe(pipefd) < 0){
fprint(2, "can't pipe: %r\n");
exits("pipe");
}
+ if(argv[0][0] == '/')
+ strecpy(buf, buf+sizeof buf, argv[0]);
+ else
+ snprint(buf, sizeof buf, "/srv/%s", argv[0]);
+ fd = create(buf, OWRITE|ORCLOSE, perm);
+ if(fd < 0){
+ fprint(2, "can't create %s: %r\n", buf);
+ exits("create");
+ }
+ fprint(fd, "%d", pipefd[1]);
+ close(pipefd[1]);
switch(rfork(RFPROC|RFNOWAIT|RFNOTEG|RFFDG)){
case -1:
@@ -56,39 +69,11 @@ main(int argc, char **argv)
dup(pipefd[0], 0);
dup(pipefd[0], 1);
close(pipefd[0]);
- close(pipefd[1]);
exec(ename, arglist);
fprint(2, "can't exec exportfs: %r\n");
exits("exec");
default:
break;
}
- close(pipefd[0]);
- if(fprint(pipefd[1], "%s", argv[1]) < 0){
- fprint(2, "can't write pipe: %r\n");
- exits("write");
- }
- n = read(pipefd[1], buf, sizeof buf-1);
- if(n < 0){
- fprint(2, "can't read pipe: %r\n");
- exits("read");
- }
- buf[n] = 0;
- if(n != 2 || strcmp(buf, "OK") != 0){
- fprint(2, "not OK (%d): %s\n", n, buf);
- exits("OK");
- }
- if(argv[0][0] == '/')
- strecpy(buf, buf+sizeof buf, argv[0]);
- else
- snprint(buf, sizeof buf, "/srv/%s", argv[0]);
- fd = create(buf, OWRITE, perm);
- if(fd < 0){
- fprint(2, "can't create %s: %r\n", buf);
- exits("create");
- }
- fprint(fd, "%d", pipefd[1]);
- close(fd);
- close(pipefd[1]);
exits(0);
}
diff --git a/sys/src/cmd/vmx/dat.h b/sys/src/cmd/vmx/dat.h
index 25a1898a0..b6e375a8e 100644
--- a/sys/src/cmd/vmx/dat.h
+++ b/sys/src/cmd/vmx/dat.h
@@ -11,6 +11,7 @@ enum {
VMDEAD,
};
extern int state;
+extern int debug;
enum {
BY2PG = 4096
diff --git a/sys/src/cmd/vmx/exith.c b/sys/src/cmd/vmx/exith.c
index 48f054c01..185c22e07 100644
--- a/sys/src/cmd/vmx/exith.c
+++ b/sys/src/cmd/vmx/exith.c
@@ -1,9 +1,8 @@
#include <u.h>
#include <libc.h>
-#include <thread.h>
-#include <bio.h>
#include "dat.h"
#include "fns.h"
+#include "x86.h"
int persist = 1;
@@ -118,109 +117,167 @@ eptfault(ExitInfo *ei)
typedef struct CPUID CPUID;
struct CPUID {
- u32int idx;
u32int ax, bx, cx, dx;
};
-static CPUID *cpuidf;
-static int ncpuidf;
+static u32int cpuidmax;
+static u32int cpuidmaxext;
+static CPUID leaf1;
+static struct {
+ uvlong miscen;
+}msr;
-static void
-auxcpuidproc(void *vpfd)
-{
- int *pfd;
-
- pfd = vpfd;
- close(pfd[1]);
- close(0);
- open("/dev/null", OREAD);
- dup(pfd[0], 1);
- close(pfd[0]);
- procexecl(nil, "/bin/aux/cpuid", "cpuid", "-r", nil);
- threadexits("exec: %r");
-}
+static uchar _cpuid[] = {
+ 0x5E, /* POP SI (PC) */
+ 0x5D, /* POP BP (CPUID&) */
+ 0x58, /* POP AX */
+ 0x59, /* POP CX */
+
+ 0x51, /* PUSH CX */
+ 0x50, /* PUSH AX */
+ 0x55, /* PUSH BP */
+ 0x56, /* PUSH SI */
+
+ 0x31, 0xDB, /* XOR BX, BX */
+ 0x31, 0xD2, /* XOR DX, DX */
+
+ 0x0F, 0xA2, /* CPUID */
+
+ 0x89, 0x45, 0x00, /* MOV AX, 0(BP) */
+ 0x89, 0x5d, 0x04, /* MOV BX, 4(BP) */
+ 0x89, 0x4d, 0x08, /* MOV CX, 8(BP) */
+ 0x89, 0x55, 0x0C, /* MOV DX, 12(BP) */
+ 0xC3, /* RET */
+};
+
+static CPUID (*getcpuid)(ulong ax, ulong cx) = (CPUID(*)(ulong, ulong)) _cpuid;
void
cpuidinit(void)
{
- int pfd[2];
- Biobuf *bp;
- char *l, *f[5];
- CPUID *cp;
-
- pipe(pfd);
- procrfork(auxcpuidproc, pfd, 4096, RFFDG);
- close(pfd[0]);
- bp = Bfdopen(pfd[1], OREAD);
- if(bp == nil) sysfatal("Bopenfd: %r");
- for(; l = Brdstr(bp, '\n', 1), l != nil; free(l)){
- if(tokenize(l, f, 5) < 5) continue;
- cpuidf = realloc(cpuidf, (ncpuidf + 1) * sizeof(CPUID));
- cp = cpuidf + ncpuidf++;
- cp->idx = strtoul(f[0], nil, 16);
- cp->ax = strtoul(f[1], nil, 16);
- cp->bx = strtoul(f[2], nil, 16);
- cp->cx = strtoul(f[3], nil, 16);
- cp->dx = strtoul(f[4], nil, 16);
- }
- Bterm(bp);
- close(pfd[1]);
-}
+ CPUID r;
+ int f;
-CPUID *
-getcpuid(ulong idx)
-{
- CPUID *cp;
-
- for(cp = cpuidf; cp < cpuidf + ncpuidf; cp++)
- if(cp->idx == idx)
- return cp;
- return nil;
+ if(sizeof(uintptr) == 8) /* patch out POP BP -> POP AX */
+ _cpuid[1] = 0x58;
+ segflush(_cpuid, sizeof(_cpuid));
+
+ r = getcpuid(0, 0);
+ cpuidmax = r.ax;
+ r = getcpuid(0x80000000, 0);
+ cpuidmaxext = r.ax;
+ leaf1 = getcpuid(1, 0);
+
+ memset(&msr, 0, sizeof(msr));
+ if((f = open("/dev/msr", OREAD)) >= 0){
+ pread(f, &msr.miscen, 8, 0x1a0);
+ msr.miscen &= 1<<0; /* fast strings */
+ close(f);
+ }
}
-int maxcpuid = 7;
+static int xsavesz[] = {
+ [1] = 512+64,
+ [3] = 512+64,
+ [7] = 512+64+256,
+};
static void
cpuid(ExitInfo *ei)
{
u32int ax, bx, cx, dx;
- CPUID *cp;
- static CPUID def;
-
+ CPUID cp;
+
ax = rget(RAX);
- cp = getcpuid(ax);
- if(cp == nil) cp = &def;
+ cx = rget(RCX);
+ bx = dx = 0;
+ cp = getcpuid(ax, cx);
switch(ax){
- case 0: /* highest register & GenuineIntel */
- ax = maxcpuid;
- bx = cp->bx;
- dx = cp->dx;
- cx = cp->cx;
+ case 0x00: /* highest register & GenuineIntel */
+ ax = MIN(cpuidmax, 0x18);
+ bx = cp.bx;
+ dx = cp.dx;
+ cx = cp.cx;
break;
- case 1: /* features */
- ax = cp->ax;
- bx = cp->bx & 0xffff;
- cx = cp->cx & 0x60de2203;
- dx = cp->dx & 0x0782a179;
+ case 0x01: /* features */
+ ax = cp.ax;
+ bx = cp.bx & 0xffff;
+ /* some features removed, hypervisor added */
+ cx = cp.cx & 0x76de3217 | 0x80000000UL;
+ dx = cp.dx & 0x0f8aa579;
+ if(leaf1.cx & 1<<27){
+ if(rget("cr4real") & Cr4Osxsave)
+ cx |= 1<<27;
+ }else{
+ cx &= ~0x1c000000;
+ }
break;
- case 2: goto literal; /* cache stuff */
- case 3: goto zero; /* processor serial number */
- case 4: goto zero; /* cache stuff */
- case 5: goto zero; /* monitor/mwait */
- case 6: goto zero; /* thermal management */
- case 7: goto zero; /* more features */
- case 10: goto zero; /* performance counters */
+ case 0x02: goto literal; /* cache stuff */
+ case 0x03: goto zero; /* processor serial number */
+ case 0x04: goto literal; /* cache stuff */
+ case 0x05: goto zero; /* monitor/mwait */
+ case 0x06: goto zero; /* thermal management */
+ case 0x07: /* more features */
+ if(cx == 0){
+ ax = 0;
+ bx = cp.bx & 0x2369;
+ cx = 0;
+ if((leaf1.cx & 1<<27) == 0)
+ bx &= ~0xdc230020;
+ }else{
+ goto zero;
+ }
+ break;
+ case 0x08: goto zero;
+ case 0x09: goto literal; /* direct cache access */
+ case 0x0a: goto zero; /* performance counters */
+ case 0x0b: goto zero; /* extended topology */
+ case 0x0c: goto zero;
+ case 0x0d: /* extended state */
+ if((leaf1.cx & 1<<27) == 0)
+ goto zero;
+ if(cx == 0){ /* main leaf */
+ ax = cp.ax & 7; /* x87, sse, avx */
+ bx = xsavesz[rget("xcr0")]; /* current xsave size */
+ cx = xsavesz[ax]; /* max xsave size */
+ }else if(cx == 1){ /* sub leaf */
+ ax = cp.ax & 7; /* xsaveopt, xsavec, xgetbv1 */
+ bx = xsavesz[rget("xcr0")];
+ cx = 0;
+ }else if(cx == 2){
+ ax = xsavesz[7] - xsavesz[3];
+ bx = xsavesz[3];
+ cx = 0;
+ }else{
+ goto zero;
+ }
+ break;
+ case 0x0f: goto zero; /* RDT */
+ case 0x10: goto zero; /* RDT */
+ case 0x12: goto zero; /* SGX */
+ case 0x14: goto zero; /* PT */
+ case 0x15: goto zero; /* TSC */
+ case 0x16: goto zero; /* cpu clock */
+ case 0x17: goto zero; /* SoC */
+ case 0x18: goto literal; /* pages, tlb */
+
+ case 0x40000000: /* hypervisor */
+ ax = 0;
+ bx = 0x4b4d564b; /* act as KVM */
+ cx = 0x564b4d56;
+ dx = 0x4d;
+ break;
+
case 0x80000000: /* highest register */
- ax = 0x80000008;
- bx = cx = dx = 0;
+ ax = MIN(cpuidmaxext, 0x80000008);
+ cx = 0;
break;
case 0x80000001: /* signature & ext features */
- ax = cp->ax;
- bx = 0;
- cx = cp->cx & 0x121;
+ ax = cp.ax;
+ cx = cp.cx & 0x121;
if(sizeof(uintptr) == 8)
- dx = cp->dx & 0x24100800;
+ dx = cp.dx & 0x24100800;
else
- dx = cp->dx & 0x04100000;
+ dx = cp.dx & 0x04100000;
break;
case 0x80000002: goto literal; /* brand string */
case 0x80000003: goto literal; /* brand string */
@@ -230,18 +287,16 @@ cpuid(ExitInfo *ei)
case 0x80000007: goto zero; /* invariant tsc */
case 0x80000008: goto literal; /* address bits */
literal:
- ax = cp->ax;
- bx = cp->bx;
- cx = cp->cx;
- dx = cp->dx;
+ ax = cp.ax;
+ bx = cp.bx;
+ cx = cp.cx;
+ dx = cp.dx;
break;
default:
- vmerror("unknown cpuid field eax=%#ux", ax);
+ if((ax & 0xf0000000) != 0x40000000)
+ vmdebug("unknown cpuid field eax=%#ux", ax);
zero:
- ax = 0;
- bx = 0;
- cx = 0;
- dx = 0;
+ ax = cx = 0;
break;
}
rset(RAX, ax);
@@ -267,12 +322,15 @@ rdwrmsr(ExitInfo *ei)
else rset("pat", val);
break;
case 0x8B: val = 0; break; /* microcode update */
+ case 0x1A0: /* IA32_MISC_ENABLE */
+ if(rd) val = msr.miscen;
+ break;
default:
if(rd){
- vmerror("read from unknown MSR %#ux ignored", cx);
+ vmdebug("read from unknown MSR %#ux ignored", cx);
val = 0;
}else
- vmerror("write to unknown MSR %#ux ignored (val=%#ullx)", cx, val);
+ vmdebug("write to unknown MSR %#ux ignored (val=%#ullx)", cx, val);
break;
}
if(rd){
@@ -310,7 +368,7 @@ movcr(ExitInfo *ei)
case 0:
switch(q >> 4 & 3){
case 0:
- vmdebug("illegal CR0 write, value %#ux", rget(x86reg[q >> 8 & 15]));
+ vmdebug("illegal CR0 write, value %#ux", (u32int)rget(x86reg[q >> 8 & 15]));
rset("cr0real", rget(x86reg[q >> 8 & 15]));
skipinstr(ei);
break;
@@ -332,7 +390,7 @@ movcr(ExitInfo *ei)
case 4:
switch(q >> 4 & 3){
case 0:
- vmdebug("illegal CR4 write, value %#ux", rget(x86reg[q >> 8 & 15]));
+ vmdebug("illegal CR4 write, value %#ux", (u32int)rget(x86reg[q >> 8 & 15]));
rset("cr4real", rget(x86reg[q >> 8 & 15]));
skipinstr(ei);
break;
@@ -347,7 +405,7 @@ movcr(ExitInfo *ei)
}
break;
default:
- vmerror("access to unknown control register CR%d", ei->qual & 15);
+ vmerror("access to unknown control register CR%ud", q & 15);
postexc("#ud", NOERRC);
}
}
@@ -373,6 +431,26 @@ irqackhand(ExitInfo *ei)
irqack(ei->qual);
}
+static void
+xsetbv(ExitInfo *ei)
+{
+ uvlong v;
+
+ /* this should also #ud if LOCK prefix is used */
+
+ v = rget(RAX)&0xffffffff | rget(RDX)<<32;
+ if(rget(RCX) & 0xffffffff)
+ postexc("#gp", 0);
+ else if(v != 1 && v != 3 && v != 7)
+ postexc("#gp", 0);
+ else if((leaf1.cx & 1<<26) == 0 || (rget("cr4real") & Cr4Osxsave) == 0)
+ postexc("#ud", NOERRC);
+ else{
+ rset("xcr0", v);
+ skipinstr(ei);
+ }
+}
+
typedef struct ExitType ExitType;
struct ExitType {
char *name;
@@ -389,6 +467,7 @@ static ExitType etypes[] = {
{".movdr", movdr},
{"#db", dbgexc},
{"movcr", movcr},
+ {".xsetbv", xsetbv},
};
void
diff --git a/sys/src/cmd/vmx/fns.h b/sys/src/cmd/vmx/fns.h
index d73e5fe1d..06643a9aa 100644
--- a/sys/src/cmd/vmx/fns.h
+++ b/sys/src/cmd/vmx/fns.h
@@ -1,3 +1,4 @@
+#define MIN(a,b) ((a)<(b)?(a):(b))
void *emalloc(ulong);
void loadkernel(char *);
uvlong rget(char *);
@@ -10,7 +11,8 @@ void pitadvance(void);
void rtcadvance(void);
void settimer(vlong targ);
void vmerror(char *, ...);
-#define vmdebug vmerror
+#pragma varargck argpos vmerror 1
+#define vmdebug if(!debug) {} else vmerror
int ctl(char *, ...);
void registermmio(uvlong, uvlong, uvlong (*)(int, uvlong, uvlong));
void irqline(int, int);
diff --git a/sys/src/cmd/vmx/ide.c b/sys/src/cmd/vmx/ide.c
index 162cac1c0..1e7cd1a7e 100644
--- a/sys/src/cmd/vmx/ide.c
+++ b/sys/src/cmd/vmx/ide.c
@@ -118,7 +118,7 @@ idegoio(IDE *d, int wr)
addr = getlba(d);
if(addr < 0){
- vmerror("ide%d: access to invalid sector address (access to CHS=(%#.4ux,%#ux,%#.2ux); geometry is (%#.4ux,%#ux,%#.2ux)", d-ide, d->cyl, d->head&0xf, d->sec, d->lcyl, d->lhead, d->lsec);
+ vmerror("ide%zd: access to invalid sector address (access to CHS=(%#.4ux,%#ux,%#.2ux); geometry is (%#.4ux,%#ux,%#.2ux)", d-ide, d->cyl, d->head&0xf, d->sec, d->lcyl, d->lhead, d->lsec);
postexc("#bp", NOERRC);
d->stat = IDEDRDY | IDEDSC | IDEDRQ | IDEERR;
d->err = IDEIDNF;
@@ -325,7 +325,7 @@ ideioproc(void *dp)
qunlock(io);
werrstr("eof");
if(getsector(a+i, p) < 0 && pread(d->fd, p, 512, (a+i)*512) < 512){
- vmerror("ide%d: read: %r", d - ide);
+ vmerror("ide%zd: read: %r", d - ide);
qlock(io);
io->err = IDEUNC;
qunlock(io);
@@ -355,7 +355,7 @@ idecmd(IDE *d, u8int cmd)
break;
default:
if((d->flags & IDEPRESENT) == 0){
- vmerror("ide%d: command %#ux issued to absent drive", d-ide, cmd);
+ vmerror("ide%zd: command %#ux issued to absent drive", d-ide, cmd);
return;
}
}
@@ -435,7 +435,7 @@ idecmd(IDE *d, u8int cmd)
case 0x66: d->flags |= IDEKEEPFEAT; break; /* retain settings */
case 0xcc: d->flags &= ~IDEKEEPFEAT; break; /* revert to default on reset */
default:
- vmerror("ide%d: unknown feature %#ux", d-ide, d->feat);
+ vmerror("ide%zd: unknown feature %#ux", d-ide, d->feat);
d->stat = IDEDRDY|IDEDSC|IDEERR;
d->err = IDEABRT;
return;
@@ -443,7 +443,7 @@ idecmd(IDE *d, u8int cmd)
d->stat = IDEDRDY|IDEDSC;
break;
default:
- vmerror("ide%d: unknown command %#ux", d-ide, cmd);
+ vmerror("ide%zd: unknown command %#ux", d-ide, cmd);
d->stat = IDEDRDY|IDEDSC|IDEERR;
d->err = IDEABRT;
}
diff --git a/sys/src/cmd/vmx/io.c b/sys/src/cmd/vmx/io.c
index 2de8fe605..25244b4e0 100644
--- a/sys/src/cmd/vmx/io.c
+++ b/sys/src/cmd/vmx/io.c
@@ -292,7 +292,7 @@ picio(int isin, u16int port, u32int val, int sz, void *)
p->imr = 0;
p->prio = 7;
p->flags = 0;
- if((val & 0x0b) != 0x01) vmerror("PIC%ld ICW1 with unsupported value %#ux", p-pic, val);
+ if((val & 0x0b) != 0x01) vmerror("PIC%zd ICW1 with unsupported value %#ux", p-pic, (u32int)val);
p->init = 1;
return 0;
}
@@ -347,7 +347,7 @@ picio(int isin, u16int port, u32int val, int sz, void *)
case 0xa1:
switch(p->init){
default:
- vmerror("write to PIC%ld in init=%d state", p-pic, p->init);
+ vmerror("write to PIC%zd in init=%d state", p-pic, p->init);
return 0;
case 1:
p->base = val;
@@ -355,11 +355,11 @@ picio(int isin, u16int port, u32int val, int sz, void *)
return 0;
case 2:
if(p == &pic[0] && val != 4 || p == &pic[1] && val != 2)
- vmerror("PIC%ld ICW3 with unsupported value %#ux", p-pic, val);
+ vmerror("PIC%zd ICW3 with unsupported value %#ux", p-pic, val);
p->init = 3;
return 0;
case 3:
- if((val & 0xfd) != 1) vmerror("PIC%ld ICW4 with unsupported value %#ux", p-pic, val);
+ if((val & 0xfd) != 1) vmerror("PIC%zd ICW4 with unsupported value %#ux", p-pic, val);
if((val & 2) != 0) p->flags |= AEOI;
p->init = 4;
picupdate(p);
@@ -726,7 +726,7 @@ kbdcmd(u8int val)
case 0xf2: keyputc(0xfa); keyputc(0xab); keyputc(0x41); break; /* keyboard id */
case 0xee: keyputc(0xee); break; /* echo */
default:
- vmerror("unknown kbd command %#ux", val);
+ vmdebug("unknown kbd command %#ux", val);
keyputc(0xfe);
}
}
@@ -1203,9 +1203,9 @@ u32int
iowhine(int isin, u16int port, u32int val, int sz, void *mod)
{
if(isin)
- vmerror("%s%sread from unknown i/o port %#ux ignored (sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, sz, rget(RPC));
+ vmdebug("%s%sread from unknown i/o port %#ux ignored (sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, sz, rget(RPC));
else
- vmerror("%s%swrite to unknown i/o port %#ux ignored (val=%#ux, sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, val, sz, rget(RPC));
+ vmdebug("%s%swrite to unknown i/o port %#ux ignored (val=%#ux, sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, val, sz, rget(RPC));
return -1;
}
diff --git a/sys/src/cmd/vmx/mkfile b/sys/src/cmd/vmx/mkfile
index e52b53466..78842c3dc 100644
--- a/sys/src/cmd/vmx/mkfile
+++ b/sys/src/cmd/vmx/mkfile
@@ -2,6 +2,7 @@
BIN=/$objtype/bin
TARG=vmx
+CLEANFILES=$O.vmxgdb
HFILES=dat.h fns.h
OFILES=\
vmx.$O \
@@ -19,6 +20,10 @@ OFILES=\
</sys/src/cmd/mkone
+default:V: all
+
+all:V: $O.out $O.vmxgdb
+
install:V: $BIN/vmxgdb
$BIN/vmxgdb: $O.vmxgdb
diff --git a/sys/src/cmd/vmx/nanosec.c b/sys/src/cmd/vmx/nanosec.c
index ac418483d..1301e9faf 100644
--- a/sys/src/cmd/vmx/nanosec.c
+++ b/sys/src/cmd/vmx/nanosec.c
@@ -17,14 +17,15 @@ nanosec(void)
return nsec() - xstart;
if(fasthz == 0){
- if((fasthz = _tos->cyclefreq) == 0){
- fasthz = ~0ULL;
+ if(_tos->cyclefreq){
+ cycles(&xstart);
+ fasthz = _tos->cyclefreq;
+ } else {
xstart = nsec();
+ fasthz = ~0ULL;
fprint(2, "cyclefreq not available, falling back to nsec()\n");
fprint(2, "you might want to disable aux/timesync\n");
return 0;
- }else{
- cycles(&xstart);
}
}
cycles(&x);
diff --git a/sys/src/cmd/vmx/vesa.c b/sys/src/cmd/vmx/vesa.c
index 35c7a0d38..61eeb5c2c 100644
--- a/sys/src/cmd/vmx/vesa.c
+++ b/sys/src/cmd/vmx/vesa.c
@@ -622,7 +622,8 @@ vesathread(void *)
if(vesaddc(&ur) < 0 || vesasetregs(sp, &ur) < 0) continue;
break;
default:
- vmerror("vesa: unsupported function %#x", ur.ax);
+ vesasetax(sp, 0x0100);
+ vmdebug("vesa: unsupported function %#x", ur.ax);
}
}
}
diff --git a/sys/src/cmd/vmx/vga.c b/sys/src/cmd/vmx/vga.c
index 9fadff15e..b59eb44a1 100644
--- a/sys/src/cmd/vmx/vga.c
+++ b/sys/src/cmd/vmx/vga.c
@@ -178,7 +178,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *)
switch(vga.sidx){
case 0: vga.seq[vga.sidx] = val & 3; return 0;
case 4: vga.seq[vga.sidx] = val & 0xe; return 0;
- default: vmerror("vga: write to unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0;
+ default: vmdebug("vga: write to unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0;
}
case 0x3c6: return 0;
case 0x3c7: vga.rdidx = val << 2; return 0;
@@ -194,7 +194,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *)
case 4: vga.graph[vga.gidx] = val & 3; break;
case 8: vga.graph[vga.gidx] = val; break;
default:
- vmerror("vga: write to unknown graphics register %#ux (val=%#ux)", vga.gidx, val);
+ vmdebug("vga: write to unknown graphics register %#ux (val=%#ux)", vga.gidx, val);
}
return 0;
case 0x3d4: vga.cidx = val; return 0;
@@ -204,7 +204,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *)
vga.crtc[vga.cidx] = val;
return 0;
default:
- vmerror("vga: write to unknown CRTC register %#ux (val=%#ux)", vga.cidx, val);
+ vmdebug("vga: write to unknown CRTC register %#ux (val=%#ux)", vga.cidx, val);
}
return 0;
case 0x103c0: return vga.aidx & 0x3f;
@@ -215,7 +215,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *)
case 0:
case 4:
return vga.seq[vga.sidx];
- default: vmerror("vga: read from unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0;
+ default: vmdebug("vga: read from unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0;
}
case 0x103c6: return 0xff;
case 0x103c7: return vga.rdidx >> 2;
@@ -232,7 +232,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *)
case 8:
return vga.graph[vga.gidx];
default:
- vmerror("vga: read from unknown graphics register %#ux", vga.gidx);
+ vmdebug("vga: read from unknown graphics register %#ux", vga.gidx);
return 0;
}
case 0x103d4: return vga.cidx;
@@ -241,7 +241,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *)
case 10: case 11: case 12: case 13: case 14: case 15:
return vga.crtc[vga.cidx];
default:
- vmerror("vga: read from unknown CRTC register %#ux", vga.cidx);
+ vmdebug("vga: read from unknown CRTC register %#ux", vga.cidx);
return 0;
}
case 0x103ca:
@@ -374,7 +374,7 @@ keyproc(void *)
nkdown[k->code >> 6] |= 1ULL<<(k->code&63);
break;
}
- if(k == nil) vmerror("unknown key %d", r);
+ if(k == nil) vmdebug("unknown key %d", r);
}
if(mousegrab && (nkdown[0]>>29 & 1) != 0 && (nkdown[0]>>56 & 1) != 0){
mousegrab = 0;
@@ -737,7 +737,7 @@ vgafbparse(char *fbstring)
void
-vgainit(void)
+vgainit(int new)
{
char buf[512];
int i;
@@ -760,7 +760,7 @@ vgainit(void)
sysfatal("got nil ptr for framebuffer");
}
snprint(buf, sizeof(buf), "-dx %d -dy %d", maxw+50, maxh+50);
- if(newwindow(buf) < 0 || initdraw(nil, nil, "vmx") < 0)
+ if((new && newwindow(buf) < 0) || initdraw(nil, nil, "vmx") < 0)
sysfatal("failed to initialize graphics: %r");
screeninit(1);
flushimage(display, 1);
diff --git a/sys/src/cmd/vmx/vmx.c b/sys/src/cmd/vmx/vmx.c
index 1a974a042..b3b73d845 100644
--- a/sys/src/cmd/vmx/vmx.c
+++ b/sys/src/cmd/vmx/vmx.c
@@ -11,7 +11,7 @@ Region *mmap;
int ctlfd, regsfd, mapfd, waitfd;
Channel *waitch, *sleepch, *notifch;
enum { MSEC = 1000*1000, MinSleep = MSEC, SleeperPoll = 2000*MSEC } ;
-int getexit, state;
+int getexit, state, debug;
typedef struct VmxNotif VmxNotif;
struct VmxNotif {
void (*f)(void *);
@@ -320,9 +320,6 @@ gend(void *v)
return (u8int *) v + gavail(v);
}
-void *tmp, *vgamem;
-uvlong tmpoff, vgamemoff;
-
static void
mksegment(char *sn)
{
@@ -355,8 +352,9 @@ mksegment(char *sn)
close(fd);
gmem = segattach(0, sn, nil, sz);
if(gmem == (void*)-1) sysfatal("segattach: %r");
+ }else{
+ memset(gmem, 0, sz > 1<<24 ? 1<<24 : sz);
}
- memset(gmem, 0, sz > 1<<24 ? 1<<24 : sz);
p = gmem;
for(r = mmap; r != nil; r = r->next){
if(r->segname == nil) continue;
@@ -365,14 +363,12 @@ mksegment(char *sn)
p += r->end - r->start;
r->ve = p;
}
- vgamem = p;
- vgamemoff = p - gmem;
- regptr(0xa0000)->segoff = vgamemoff;
- regptr(0xa0000)->v = vgamem;
+ /* vga */
+ r = regptr(0xa0000);
+ r->segoff = p - gmem;
+ r->v = p;
p += 256*1024;
- regptr(0xa0000)->ve = p;
- tmp = p;
- tmpoff = p - gmem;
+ r->ve = p;
for(r = mmap; r != nil; r = r->next)
modregion(r);
@@ -504,7 +500,7 @@ sendnotif(void (*f)(void *), void *arg)
send(notifch, &notif);
}
-extern void vgainit(void);
+extern void vgainit(int);
extern void pciinit(void);
extern void pcibusmap(void);
extern void cpuidinit(void);
@@ -574,7 +570,7 @@ usage(void)
for(p = blanks; *p != 0; p++)
*p = ' ';
fprint(2, "usage: %s [ -M mem ] [ -c com1rd[,com1wr] ] [ -C com2rd[,com2r] ] [ -n nic ]\n", argv0);
- fprint(2, " %s [ -d blockfile ] [ -m module ] [ -v vga ] [ -9 srv ] kernel [ args ... ]\n", blanks);
+ fprint(2, " %s [ -d blockfile ] [ -m module ] [ -v|-w vga ] [ -9 srv ] kernel [ args ... ]\n", blanks);
threadexitsall("usage");
}
@@ -590,6 +586,7 @@ threadmain(int argc, char **argv)
static uvlong gmemsz = 64*1024*1024;
static char *srvname;
extern uintptr fbsz, fbaddr;
+ int newwin = 0;
int i;
quotefmtinstall();
@@ -598,7 +595,7 @@ threadmain(int argc, char **argv)
waitch = chancreate(sizeof(char *), 32);
sleepch = chancreate(sizeof(ulong), 32);
notifch = chancreate(sizeof(VmxNotif), 16);
-
+
ARGBEGIN {
case 'm':
bootmod = realloc(bootmod, (bootmodn + 1) * sizeof(char *));
@@ -633,10 +630,15 @@ threadmain(int argc, char **argv)
}
edevn++;
break;
+ case 'D':
+ debug++;
+ break;
case 'M':
gmemsz = siparse(EARGF(usage()));
if(gmemsz != (uintptr) gmemsz) sysfatal("too much memory for address space");
break;
+ case 'w':
+ newwin = 1;
case 'v':
vgafbparse(EARGF(usage()));
break;
@@ -673,7 +675,7 @@ threadmain(int argc, char **argv)
loadkernel(argv[0]);
pciinit();
- vgainit();
+ vgainit(newwin);
for(i = 0; i < edevn; i++)
if(edev[i](edevaux[i]) < 0)
sysfatal("%s: %r", edevt[i]);
diff --git a/sys/src/cmd/vmx/x86.h b/sys/src/cmd/vmx/x86.h
index da2b16847..4fe7947e1 100644
--- a/sys/src/cmd/vmx/x86.h
+++ b/sys/src/cmd/vmx/x86.h
@@ -22,8 +22,9 @@ enum {
enum {
Cr0Pg = 1<<31,
- Cr4Pse = 1<<4,
- Cr4Pae = 1<<5,
+ Cr4Pse = 1<<4,
+ Cr4Pae = 1<<5,
+ Cr4Osxsave = 1<<18,
EferLme = 1<<8,
};