]> git.lizzy.rs Git - plan9front.git/commitdiff
livecd
authorcinap_lenrek <cinap_lenrek@centraldogma>
Mon, 11 Apr 2011 19:47:05 +0000 (19:47 +0000)
committercinap_lenrek <cinap_lenrek@centraldogma>
Mon, 11 Apr 2011 19:47:05 +0000 (19:47 +0000)
196 files changed:
mnt/acme/.dummy [new file with mode: 0644]
mnt/apeselect/.dummy [new file with mode: 0644]
mnt/apm/.dummy [new file with mode: 0644]
mnt/arch/.dummy [new file with mode: 0644]
mnt/cd/.dummy [new file with mode: 0644]
mnt/cons/.dummy [new file with mode: 0644]
mnt/cons/cons/.dummy [new file with mode: 0644]
mnt/cons/consctl/.dummy [new file with mode: 0644]
mnt/consoles/.dummy [new file with mode: 0644]
mnt/doc/.dummy [new file with mode: 0644]
mnt/exportfs/.dummy [new file with mode: 0644]
mnt/exportfs/0/.dummy [new file with mode: 0644]
mnt/exportfs/1/.dummy [new file with mode: 0644]
mnt/exportfs/10/.dummy [new file with mode: 0644]
mnt/exportfs/11/.dummy [new file with mode: 0644]
mnt/exportfs/12/.dummy [new file with mode: 0644]
mnt/exportfs/13/.dummy [new file with mode: 0644]
mnt/exportfs/14/.dummy [new file with mode: 0644]
mnt/exportfs/15/.dummy [new file with mode: 0644]
mnt/exportfs/16/.dummy [new file with mode: 0644]
mnt/exportfs/2/.dummy [new file with mode: 0644]
mnt/exportfs/3/.dummy [new file with mode: 0644]
mnt/exportfs/4/.dummy [new file with mode: 0644]
mnt/exportfs/5/.dummy [new file with mode: 0644]
mnt/exportfs/6/.dummy [new file with mode: 0644]
mnt/exportfs/7/.dummy [new file with mode: 0644]
mnt/exportfs/8/.dummy [new file with mode: 0644]
mnt/exportfs/9/.dummy [new file with mode: 0644]
mnt/keys/.dummy [new file with mode: 0644]
mnt/lp/.dummy [new file with mode: 0644]
mnt/netkeys/.dummy [new file with mode: 0644]
mnt/news/.dummy [new file with mode: 0644]
mnt/plumb/.dummy [new file with mode: 0644]
mnt/rdb/.dummy [new file with mode: 0644]
mnt/temp/.dummy [new file with mode: 0644]
mnt/term/.dummy [new file with mode: 0644]
mnt/ums/.dummy [new file with mode: 0644]
mnt/vmware/.dummy [new file with mode: 0644]
mnt/web/.dummy [new file with mode: 0644]
mnt/webcookies/.dummy [new file with mode: 0644]
mnt/wiki/.dummy [new file with mode: 0644]
mnt/wrap/.dummy [new file with mode: 0644]
mnt/wsys/.dummy [new file with mode: 0644]
n/.dummy [new file with mode: 0644]
sys/lib/dist.old/cdstub/.dummy [new file with mode: 0644]
sys/lib/dist.old/cmd/bargraph.c [new file with mode: 0644]
sys/lib/dist.old/cmd/bflz.c [new file with mode: 0644]
sys/lib/dist.old/cmd/bzfs/bzfs.h [new file with mode: 0644]
sys/lib/dist.old/cmd/bzfs/mkext.c [new file with mode: 0644]
sys/lib/dist.old/cmd/bzfs/mkfile [new file with mode: 0644]
sys/lib/dist.old/cmd/bzfs/oramfs.c [new file with mode: 0644]
sys/lib/dist.old/cmd/bzfs/unbflz.c [new file with mode: 0644]
sys/lib/dist.old/cmd/bzfs/unbzip.c [new file with mode: 0644]
sys/lib/dist.old/cmd/cdsh.c [new file with mode: 0644]
sys/lib/dist.old/cmd/clog.c [new file with mode: 0644]
sys/lib/dist.old/cmd/mkfile [new file with mode: 0644]
sys/lib/dist.old/cmd/multi/mkfile [new file with mode: 0644]
sys/lib/dist.old/cmd/multi/mkmulti [new file with mode: 0644]
sys/lib/dist.old/cmd/multi/multi.c [new file with mode: 0644]
sys/lib/dist.old/cmd/tailfsrv.c [new file with mode: 0644]
sys/lib/dist.old/cmd/touchfs.c [new file with mode: 0644]
sys/lib/dist.old/cmd/unbflz.c [new file with mode: 0644]
sys/lib/dist.old/logcompress.awk [new file with mode: 0755]
sys/lib/dist.old/logtime.awk [new file with mode: 0755]
sys/lib/dist.old/mkfile [new file with mode: 0644]
sys/lib/dist.old/pc/cd0.proto [new file with mode: 0644]
sys/lib/dist.old/pc/emptyfile [new file with mode: 0644]
sys/lib/dist.old/pc/glenda/bin/rc/riostart [new file with mode: 0755]
sys/lib/dist.old/pc/glenda/lib/first.window [new file with mode: 0644]
sys/lib/dist.old/pc/glenda/lib/profile [new file with mode: 0644]
sys/lib/dist.old/pc/inst/bootfloppy [new file with mode: 0755]
sys/lib/dist.old/pc/inst/bootplan9 [new file with mode: 0755]
sys/lib/dist.old/pc/inst/bootsetup [new file with mode: 0755]
sys/lib/dist.old/pc/inst/bootwin9x [new file with mode: 0755]
sys/lib/dist.old/pc/inst/bootwinnt [new file with mode: 0755]
sys/lib/dist.old/pc/inst/configarch [new file with mode: 0755]
sys/lib/dist.old/pc/inst/configdist [new file with mode: 0755]
sys/lib/dist.old/pc/inst/configether [new file with mode: 0755]
sys/lib/dist.old/pc/inst/configfs [new file with mode: 0755]
sys/lib/dist.old/pc/inst/configip [new file with mode: 0755]
sys/lib/dist.old/pc/inst/confignet [new file with mode: 0755]
sys/lib/dist.old/pc/inst/configppp [new file with mode: 0755]
sys/lib/dist.old/pc/inst/copydist [new file with mode: 0755]
sys/lib/dist.old/pc/inst/defs [new file with mode: 0755]
sys/lib/dist.old/pc/inst/download [new file with mode: 0755]
sys/lib/dist.old/pc/inst/finish [new file with mode: 0755]
sys/lib/dist.old/pc/inst/fmtfossil [new file with mode: 0755]
sys/lib/dist.old/pc/inst/fmtventi [new file with mode: 0755]
sys/lib/dist.old/pc/inst/gui [new file with mode: 0755]
sys/lib/dist.old/pc/inst/halt [new file with mode: 0755]
sys/lib/dist.old/pc/inst/hasmbr [new file with mode: 0755]
sys/lib/dist.old/pc/inst/hdrs [new file with mode: 0755]
sys/lib/dist.old/pc/inst/is9660 [new file with mode: 0755]
sys/lib/dist.old/pc/inst/isext2 [new file with mode: 0755]
sys/lib/dist.old/pc/inst/isfat [new file with mode: 0755]
sys/lib/dist.old/pc/inst/isfossil [new file with mode: 0755]
sys/lib/dist.old/pc/inst/isventi [new file with mode: 0755]
sys/lib/dist.old/pc/inst/isventiarenas [new file with mode: 0755]
sys/lib/dist.old/pc/inst/isventiisect [new file with mode: 0755]
sys/lib/dist.old/pc/inst/main [new file with mode: 0755]
sys/lib/dist.old/pc/inst/mainloop [new file with mode: 0755]
sys/lib/dist.old/pc/inst/mkini.awk [new file with mode: 0755]
sys/lib/dist.old/pc/inst/mountdist [new file with mode: 0755]
sys/lib/dist.old/pc/inst/mountfossil [new file with mode: 0755]
sys/lib/dist.old/pc/inst/mountfs [new file with mode: 0755]
sys/lib/dist.old/pc/inst/moveoldfs [new file with mode: 0755]
sys/lib/dist.old/pc/inst/partdisk [new file with mode: 0755]
sys/lib/dist.old/pc/inst/prepdisk [new file with mode: 0755]
sys/lib/dist.old/pc/inst/replcfg [new file with mode: 0755]
sys/lib/dist.old/pc/inst/startether [new file with mode: 0755]
sys/lib/dist.old/pc/inst/startppp [new file with mode: 0755]
sys/lib/dist.old/pc/inst/startwin [new file with mode: 0755]
sys/lib/dist.old/pc/inst/stop [new file with mode: 0755]
sys/lib/dist.old/pc/inst/stopether [new file with mode: 0755]
sys/lib/dist.old/pc/inst/stopppp [new file with mode: 0755]
sys/lib/dist.old/pc/inst/textonly [new file with mode: 0755]
sys/lib/dist.old/pc/inst/watchfd [new file with mode: 0755]
sys/lib/dist.old/pc/inst/xxx [new file with mode: 0755]
sys/lib/dist.old/pc/mkfile [new file with mode: 0644]
sys/lib/dist.old/pc/plan9.ini [new file with mode: 0644]
sys/lib/dist.old/pc/plan9.ini.blank [new file with mode: 0644]
sys/lib/dist.old/pc/plan9.ini.cd [new file with mode: 0644]
sys/lib/dist.old/pc/plan9.ini.vmware [new file with mode: 0644]
sys/lib/dist.old/pc/proto [new file with mode: 0644]
sys/lib/dist.old/pc/sub/D003753 [new file with mode: 0755]
sys/lib/dist.old/pc/sub/F004116 [new file with mode: 0755]
sys/lib/dist.old/pc/sub/bind [new file with mode: 0755]
sys/lib/dist.old/pc/sub/bunzip2 [new file with mode: 0755]
sys/lib/dist.old/pc/sub/common [new file with mode: 0755]
sys/lib/dist.old/pc/sub/compactdb [new file with mode: 0755]
sys/lib/dist.old/pc/sub/local [new file with mode: 0755]
sys/lib/dist.old/pc/sub/mkdir [new file with mode: 0755]
sys/lib/dist.old/pc/sub/ndist [new file with mode: 0755]
sys/lib/dist.old/pc/sub/pci [new file with mode: 0755]
sys/lib/dist.old/pc/sub/pwd [new file with mode: 0755]
sys/lib/dist.old/pc/sub/ramfs [new file with mode: 0755]
sys/lib/dist.old/pc/sub/sleep [new file with mode: 0755]
sys/lib/dist.old/pc/sub/termrc [new file with mode: 0755]
sys/lib/dist.old/pc/sub/unmount [new file with mode: 0755]
sys/lib/dist.old/pc/sub/users [new file with mode: 0755]
sys/lib/dist.old/pc/sub/vmware [new file with mode: 0755]
sys/lib/dist.old/pc/subst/plan9.ini [new file with mode: 0644]
sys/lib/dist.old/setup [new file with mode: 0755]
sys/lib/dist/cdstub/.dummy [deleted file]
sys/lib/dist/cdstub/bootdisk.img [deleted file]
sys/lib/dist/cmd/bargraph.c [deleted file]
sys/lib/dist/cmd/bflz.c [deleted file]
sys/lib/dist/cmd/bzfs/bzfs.h [deleted file]
sys/lib/dist/cmd/bzfs/mkext.c [deleted file]
sys/lib/dist/cmd/bzfs/mkfile [deleted file]
sys/lib/dist/cmd/bzfs/oramfs.c [deleted file]
sys/lib/dist/cmd/bzfs/unbflz.c [deleted file]
sys/lib/dist/cmd/bzfs/unbzip.c [deleted file]
sys/lib/dist/cmd/cdsh.c [deleted file]
sys/lib/dist/cmd/clog.c [deleted file]
sys/lib/dist/cmd/mkfile [deleted file]
sys/lib/dist/cmd/multi/mkfile [deleted file]
sys/lib/dist/cmd/multi/mkmulti [deleted file]
sys/lib/dist/cmd/multi/multi.c [deleted file]
sys/lib/dist/cmd/tailfsrv.c [deleted file]
sys/lib/dist/cmd/touchfs.c [deleted file]
sys/lib/dist/cmd/unbflz.c [deleted file]
sys/lib/dist/logcompress.awk [deleted file]
sys/lib/dist/logtime.awk [deleted file]
sys/lib/dist/mkfile
sys/lib/dist/pc/cd0.proto [deleted file]
sys/lib/dist/pc/plan9.ini
sys/lib/dist/pc/plan9.ini.cd
sys/lib/dist/setup [deleted file]
sys/src/boot/pc/iso.c
sys/src/cmd/aux/mkfile
sys/src/cmd/aux/realemu/arg.c [new file with mode: 0644]
sys/src/cmd/aux/realemu/dat.h [new file with mode: 0644]
sys/src/cmd/aux/realemu/decode.c [new file with mode: 0644]
sys/src/cmd/aux/realemu/fmt.c [new file with mode: 0644]
sys/src/cmd/aux/realemu/fns.h [new file with mode: 0644]
sys/src/cmd/aux/realemu/loadcom.c [new file with mode: 0644]
sys/src/cmd/aux/realemu/main.c [new file with mode: 0644]
sys/src/cmd/aux/realemu/mkfile [new file with mode: 0644]
sys/src/cmd/aux/realemu/notes [new file with mode: 0644]
sys/src/cmd/aux/realemu/pit.c [new file with mode: 0644]
sys/src/cmd/aux/realemu/realemu.man [new file with mode: 0644]
sys/src/cmd/aux/realemu/vgalist [new file with mode: 0644]
sys/src/cmd/aux/realemu/xec.c [new file with mode: 0644]
tmp/.dummy [new file with mode: 0644]
usr/glenda/bin/rc/pull [new file with mode: 0755]
usr/glenda/bin/rc/riostart [new file with mode: 0755]
usr/glenda/bin/rc/screensize [new file with mode: 0755]
usr/glenda/lib/acme.dump [new file with mode: 0644]
usr/glenda/lib/acme.dump.small [new file with mode: 0644]
usr/glenda/lib/first.window [new file with mode: 0755]
usr/glenda/lib/newstime [new file with mode: 0644]
usr/glenda/lib/plumbing [new file with mode: 0644]
usr/glenda/lib/profile [new file with mode: 0644]
usr/glenda/readme.acme [new file with mode: 0644]
usr/glenda/readme.rio [new file with mode: 0644]

diff --git a/mnt/acme/.dummy b/mnt/acme/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/apeselect/.dummy b/mnt/apeselect/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/apm/.dummy b/mnt/apm/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/arch/.dummy b/mnt/arch/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/cd/.dummy b/mnt/cd/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/cons/.dummy b/mnt/cons/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/cons/cons/.dummy b/mnt/cons/cons/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/cons/consctl/.dummy b/mnt/cons/consctl/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/consoles/.dummy b/mnt/consoles/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/doc/.dummy b/mnt/doc/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/.dummy b/mnt/exportfs/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/0/.dummy b/mnt/exportfs/0/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/1/.dummy b/mnt/exportfs/1/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/10/.dummy b/mnt/exportfs/10/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/11/.dummy b/mnt/exportfs/11/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/12/.dummy b/mnt/exportfs/12/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/13/.dummy b/mnt/exportfs/13/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/14/.dummy b/mnt/exportfs/14/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/15/.dummy b/mnt/exportfs/15/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/16/.dummy b/mnt/exportfs/16/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/2/.dummy b/mnt/exportfs/2/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/3/.dummy b/mnt/exportfs/3/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/4/.dummy b/mnt/exportfs/4/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/5/.dummy b/mnt/exportfs/5/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/6/.dummy b/mnt/exportfs/6/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/7/.dummy b/mnt/exportfs/7/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/8/.dummy b/mnt/exportfs/8/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/exportfs/9/.dummy b/mnt/exportfs/9/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/keys/.dummy b/mnt/keys/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/lp/.dummy b/mnt/lp/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/netkeys/.dummy b/mnt/netkeys/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/news/.dummy b/mnt/news/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/plumb/.dummy b/mnt/plumb/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/rdb/.dummy b/mnt/rdb/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/temp/.dummy b/mnt/temp/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/term/.dummy b/mnt/term/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/ums/.dummy b/mnt/ums/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/vmware/.dummy b/mnt/vmware/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/web/.dummy b/mnt/web/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/webcookies/.dummy b/mnt/webcookies/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/wiki/.dummy b/mnt/wiki/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/wrap/.dummy b/mnt/wrap/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mnt/wsys/.dummy b/mnt/wsys/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/n/.dummy b/n/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/sys/lib/dist.old/cdstub/.dummy b/sys/lib/dist.old/cdstub/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/sys/lib/dist.old/cmd/bargraph.c b/sys/lib/dist.old/cmd/bargraph.c
new file mode 100644 (file)
index 0000000..f7a142e
--- /dev/null
@@ -0,0 +1,346 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <bio.h>
+#include <event.h>
+
+enum {PNCTL=3};
+
+static char* rdenv(char*);
+int newwin(char*);
+Rectangle screenrect(void);
+
+int nokill;
+int textmode;
+char *title;
+
+Image *light;
+Image *dark;
+Image *text;
+
+void
+initcolor(void)
+{
+       text = display->black;
+       light = allocimagemix(display, DPalegreen, DWhite);
+       dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen);
+}
+
+Rectangle rbar;
+Point ptext;
+vlong n, d;
+int last;
+int lastp = -1;
+int first = 1;
+
+char backup[80];
+
+void
+drawbar(void)
+{
+       int i, j;
+       int p;
+       char buf[200], bar[100], *s;
+       static char lastbar[100];
+
+       if(n > d || n < 0 || d <= 0)
+               return;
+
+       i = (Dx(rbar)*n)/d;
+       p = (n*100LL)/d;
+
+       if(textmode){
+               bar[0] = '|';
+               for(j=0; j<i; j++)
+                       bar[j+1] = '#';
+               for(; j<60; j++)
+                       bar[j+1] = '-';
+               bar[61] = '|';
+               bar[62] = ' ';
+               sprint(bar+63, "%3d%% ", p);
+               for(i=0; bar[i]==lastbar[i] && bar[i]; i++)
+                       ;
+               memset(buf, '\b', strlen(lastbar)-i);
+               strcpy(buf+strlen(lastbar)-i, bar+i);
+               if(buf[0])
+                       write(1, buf, strlen(buf));
+               strcpy(lastbar, bar);
+               return;
+       }
+       
+       if(lastp == p && last == i)
+               return;
+
+       if(lastp != p){
+               sprint(buf, "%d%%", p);
+               
+               stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP);
+               lastp = p;
+       }
+
+       if(last != i){
+               draw(screen, Rect(rbar.min.x+last, rbar.min.y, rbar.min.x+i, rbar.max.y),
+                       dark, nil, ZP);
+               last = i;
+       }
+       flushimage(display, 1);
+}
+
+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);
+       border(screen, rbar, -2, dark, ZP);
+       last = 0;
+       lastp = -1;
+
+       drawbar();
+}
+
+void
+bar(Biobuf *b)
+{
+       char *p, *f[2];
+       Event e;
+       int k, die, parent, child;
+
+       parent = getpid();
+
+       die = 0;
+       if(textmode)
+               child = -1;
+       else
+       switch(child = rfork(RFMEM|RFPROC)) {
+       case 0:
+               sleep(1000);
+               while(!die && (k = eread(Ekeyboard|Emouse, &e))) {
+                       if(nokill==0 && k == Ekeyboard && (e.kbdc == 0x7F || e.kbdc == 0x03)) { /* del, ctl-c */
+                               die = 1;
+                               postnote(PNPROC, parent, "interrupt");
+                               _exits("interrupt");
+                       }
+               }
+               _exits(0);
+       }
+
+       while(!die && (p = Brdline(b, '\n'))) {
+               p[Blinelen(b)-1] = '\0';
+               if(tokenize(p, f, 2) != 2)
+                       continue;
+               n = strtoll(f[0], 0, 0);
+               d = strtoll(f[1], 0, 0);
+               drawbar();
+       }
+       postnote(PNCTL, child, "kill");
+}
+
+
+void
+usage(void)
+{
+       fprint(2, "usage: bargraph [-kt] [-w minx,miny,maxx,maxy] 'title'\n");
+       exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+       Biobuf b;
+       char *p, *q;
+       int lfd;
+
+       p = "0,0,200,60";
+       
+       ARGBEGIN{
+       case 'w':
+               p = ARGF();
+               break;
+       case 't':
+               textmode = 1;
+               break;
+       case 'k':
+               nokill = 1;
+               break;
+       default:
+               usage();
+       }ARGEND;
+
+       if(argc != 1)
+               usage();
+
+       title = argv[0];
+
+       lfd = dup(0, -1);
+
+       while(q = strchr(p, ','))
+               *q = ' ';
+       Binit(&b, lfd, OREAD);
+       if(textmode || newwin(p) < 0){
+               textmode = 1;
+               rbar = Rect(0, 0, 60, 1);
+       }else{
+               initdraw(0, 0, "bar");
+               initcolor();
+               einit(Emouse|Ekeyboard);
+               eresized(0);
+       }
+       bar(&b);
+}
+
+
+/* all code below this line should be in the library, but is stolen from colors instead */
+static char*
+rdenv(char *name)
+{
+       char *v;
+       int fd, size;
+
+       fd = open(name, OREAD);
+       if(fd < 0)
+               return 0;
+       size = seek(fd, 0, 2);
+       v = malloc(size+1);
+       if(v == 0){
+               fprint(2, "%s: can't malloc: %r\n", argv0);
+               exits("no mem");
+       }
+       seek(fd, 0, 0);
+       read(fd, v, size);
+       v[size] = 0;
+       close(fd);
+       return v;
+}
+
+int
+newwin(char *win)
+{
+       char *srv, *mntsrv;
+       char spec[100];
+       int srvfd, cons, pid;
+
+       switch(rfork(RFFDG|RFPROC|RFNAMEG|RFENVG|RFNOTEG|RFNOWAIT)){
+       case -1:
+               fprint(2, "bargraph: can't fork: %r\n");
+               return -1;
+       case 0:
+               break;
+       default:
+               exits(0);
+       }
+
+       srv = rdenv("/env/wsys");
+       if(srv == 0){
+               mntsrv = rdenv("/mnt/term/env/wsys");
+               if(mntsrv == 0){
+                       fprint(2, "bargraph: can't find $wsys\n");
+                       return -1;
+               }
+               srv = malloc(strlen(mntsrv)+10);
+               sprint(srv, "/mnt/term%s", mntsrv);
+               free(mntsrv);
+               pid  = 0;                       /* can't send notes to remote processes! */
+       }else
+               pid = getpid();
+       USED(pid);
+       srvfd = open(srv, ORDWR);
+       free(srv);
+       if(srvfd == -1){
+               fprint(2, "bargraph: can't open %s: %r\n", srv);
+               return -1;
+       }
+       sprint(spec, "new -r %s", win);
+       if(mount(srvfd, -1, "/mnt/wsys", 0, spec) == -1){
+               fprint(2, "bargraph: can't mount /mnt/wsys: %r (spec=%s)\n", spec);
+               return -1;
+       }
+       close(srvfd);
+       unmount("/mnt/acme", "/dev");
+       bind("/mnt/wsys", "/dev", MBEFORE);
+       cons = open("/dev/cons", OREAD);
+       if(cons==-1){
+       NoCons:
+               fprint(2, "bargraph: can't open /dev/cons: %r");
+               return -1;
+       }
+       dup(cons, 0);
+       close(cons);
+       cons = open("/dev/cons", OWRITE);
+       if(cons==-1)
+               goto NoCons;
+       dup(cons, 1);
+       dup(cons, 2);
+       close(cons);
+//     wctlfd = open("/dev/wctl", OWRITE);
+       return 0;
+}
+
+Rectangle
+screenrect(void)
+{
+       int fd;
+       char buf[12*5];
+
+       fd = open("/dev/screen", OREAD);
+       if(fd == -1)
+               fd=open("/mnt/term/dev/screen", OREAD);
+       if(fd == -1){
+               fprint(2, "%s: can't open /dev/screen: %r\n", argv0);
+               exits("window read");
+       }
+       if(read(fd, buf, sizeof buf) != sizeof buf){
+               fprint(2, "%s: can't read /dev/screen: %r\n", argv0);
+               exits("screen read");
+       }
+       close(fd);
+       return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48));
+}
+
+int
+postnote(int group, int pid, char *note)
+{
+       char file[128];
+       int f, r;
+
+       switch(group) {
+       case PNPROC:
+               sprint(file, "/proc/%d/note", pid);
+               break;
+       case PNGROUP:
+               sprint(file, "/proc/%d/notepg", pid);
+               break;
+       case PNCTL:
+               sprint(file, "/proc/%d/ctl", pid);
+               break;
+       default:
+               return -1;
+       }
+
+       f = open(file, OWRITE);
+       if(f < 0)
+               return -1;
+
+       r = strlen(note);
+       if(write(f, note, r) != r) {
+               close(f);
+               return -1;
+       }
+       close(f);
+       return 0;
+}
diff --git a/sys/lib/dist.old/cmd/bflz.c b/sys/lib/dist.old/cmd/bflz.c
new file mode 100644 (file)
index 0000000..89cb361
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * Extraordinarily brute force Lempel & Ziv-like
+ * compressor.  The input file must fit in memory
+ * during compression, and the output file will
+ * be reconstructed in memory during decompression.
+ * We search for large common sequences and use a
+ * greedy algorithm to choose which sequence gets
+ * compressed first.
+ *
+ * Files begin with "BLZ\n" and a 32-bit uncompressed file length.
+ *
+ * Output format is a series of blocks followed by
+ * a raw data section.  Each block begins with a 32-bit big-endian
+ * number.  The top bit is type and the next 31 bits
+ * are uncompressed size.  Type is one of
+ *     0 - use raw data for this length
+ *     1 - a 32-bit offset follows
+ * After the blocks come the raw data.  (The end of the blocks can be
+ * noted by summing block lengths until you reach the file length.)
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#define malloc sbrk
+
+int minrun = 16;
+int win = 16;
+ulong outn;
+int verbose;
+int mindist;
+
+enum { Prime = 16777213 };     /* smallest prime < 2^24 (so p*256+256 < 2^32) */
+enum { NOFF = 3 };
+
+Biobuf bout;
+ulong length;
+uchar *data;
+ulong sum32(ulong, void*, long);
+uchar *odat;
+int nodat;
+int nraw;
+int rawstart;
+int acct;
+int zlength;
+int maxchain;
+int maxrle[256];
+int nnew;
+
+typedef struct Node Node;
+struct Node {
+       Node *link;
+       ulong key;
+       ulong offset[NOFF];
+};
+
+Node *nodepool;
+int nnodepool;
+
+Node **hash;
+uint nhash;
+
+uint maxlen;
+uint maxsame;
+uint replacesame = 8*1024*1024;
+
+Node *freelist, **freeend;
+uint nalloc;
+
+Node*
+allocnode(void)
+{
+       int i;
+       Node *n;
+
+       if(nnodepool == 0){
+               nnodepool = 256*1024;
+               nodepool = malloc(sizeof(Node)*nnodepool);
+       }
+       if(freelist){
+               n = freelist;
+               freelist = n->link;
+               return n;
+       }
+       assert(nnodepool > 0);
+       nalloc++;
+       n = &nodepool[--nnodepool];
+       for(i=0; i<NOFF; i++)
+               n->offset[i] = -1;
+
+       return n;
+}
+
+void
+freenode(Node *n)
+{
+       if(freelist == nil)
+               freelist = n;
+       else
+               *freeend = n;
+       freeend = &n->link;
+       n->link = nil;
+}
+
+Node**
+llookup(ulong key)
+{
+       uint c;
+       Node **l, **top, *n;
+       
+       if(nhash == 0){
+               uint x;
+
+               x = length/8;
+               for(nhash=1; nhash<x; nhash<<=1)
+                       ;
+               hash = sbrk(sizeof(Node*)*nhash);
+       }
+
+       top = &hash[key&(nhash-1)];
+       c = 0;
+       for(l=top; *l; l=&(*l)->link){
+               c++;
+               if((*l)->key == key){
+                       /* move to front */
+                       n = *l;
+                       *l = n->link;
+                       n->link = *top;
+                       *top = n;
+                       return top;
+               }
+       }
+       if(c > maxlen)
+               maxlen = c;
+       return l;
+}
+
+Node*
+lookup(ulong key)
+{
+       return *llookup(key);
+}
+
+void
+insertnode(ulong key, ulong offset)
+{
+       int i;
+       Node *n, **l;
+
+       l = llookup(key);
+       if(*l == nil){
+               if(l==&hash[key&(nhash-1)])
+                       nnew++;
+               *l = allocnode();
+               (*l)->key = key;
+       }
+       n = *l;
+
+       /* add or replace last */
+       for(i=0; i<NOFF-1 && n->offset[i]!=-1; i++)
+               ;
+       n->offset[i] = offset;
+}
+
+void
+Bputint(Biobufhdr *b, int n)
+{
+       uchar p[4];
+
+       p[0] = n>>24;
+       p[1] = n>>16;
+       p[2] = n>>8;
+       p[3] = n;
+       Bwrite(b, p, 4);
+}
+
+void
+flushraw(void)
+{
+       if(nraw){
+               if(verbose)
+                       fprint(2, "Raw %d+%d\n", rawstart, nraw);
+               zlength += 4+nraw;
+               Bputint(&bout, (1<<31)|nraw);
+               memmove(odat+nodat, data+rawstart, nraw);
+               nodat += nraw;
+               nraw = 0;
+       }
+}
+
+int
+rawbyte(int i)
+{
+       assert(acct == i);
+       if(nraw == 0)
+               rawstart = i;
+       acct++;
+       nraw++;
+       return 1;
+}
+
+int
+refblock(int i, int len, int off)
+{
+       assert(acct == i);
+       acct += len;
+       if(nraw)
+               flushraw();
+       if(verbose)
+               fprint(2, "Copy %d+%d from %d\n", i, len, off);
+       Bputint(&bout, len);
+       Bputint(&bout, off);
+       zlength += 4+4;
+       return len;
+}
+
+int
+cmprun(uchar *a, uchar *b, int len)
+{
+       int i;
+
+       if(a==b)
+               return 0;
+       for(i=0; i<len && a[i]==b[i]; i++)
+               ;
+       return i;
+}
+
+int
+countrle(uchar *a)
+{
+       int i;
+
+       for(i=0; a[i]==a[0]; i++)
+               ;
+       return i;
+}
+
+void
+compress(void)
+{
+       int best, i, j, o, rle, run, maxrun, maxoff;
+       ulong sum;
+       Node *n;
+
+       sum = 0;
+       for(i=0; i<win && i<length; i++)
+               sum = (sum*256+data[i])%Prime;
+       for(i=0; i<length-win; ){
+               maxrun = 0;
+               maxoff = 0;
+               if(verbose)
+                       fprint(2, "look %.6lux\n", sum);
+               n = lookup(sum);
+               if(n){
+                       best = -1;
+                       for(o=0; o<NOFF; o++){
+                               if(n->offset[o] == -1)
+                                       break;
+                               run = cmprun(data+i, data+n->offset[o], length-i);
+                               if(run > maxrun && n->offset[o]+mindist < i){
+                                       maxrun = run;
+                                       maxoff = n->offset[o];
+                                       best = o;
+                               }
+                       }
+                       if(best > 0){
+                               o = n->offset[best];
+                               for(j=best; j>0; j--)
+                                       n->offset[j] = n->offset[j-1];
+                               n->offset[0] = o;
+                       }
+               }
+                               
+               if(maxrun >= minrun)
+                       j = i+refblock(i, maxrun, maxoff);
+               else
+                       j = i+rawbyte(i);
+               for(; i<j; i++){
+                       /* avoid huge chains from large runs of same byte */
+                       rle = countrle(data+i);
+                       if(rle<4)
+                               insertnode(sum, i);
+                       else if(rle>maxrle[data[i]]){
+                               maxrle[data[i]] = rle;
+                               insertnode(sum, i);
+                       }
+                       sum = (sum*256+data[i+win]) % Prime;
+                       sum = (sum + data[i]*outn) % Prime;
+               }
+       }
+       /* could do better here */
+       for(; i<length; i++)
+               rawbyte(i);
+       flushraw();
+}
+
+void
+usage(void)
+{
+       fprint(2, "usage: bflz [-n winsize] [file]\n");
+       exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+       int fd, i, n;
+       char buf[10485760];
+
+       ARGBEGIN{
+       case 'd':
+               verbose = 1;
+               break;
+       case 's':
+               replacesame = atoi(EARGF(usage()));
+               break;
+       case 'm':
+               mindist = atoi(EARGF(usage()));
+               break;
+       case 'n':
+               win = atoi(EARGF(usage()));
+               minrun = win;
+               break;
+       default:
+               usage();
+       }ARGEND
+
+       switch(argc){
+       default:
+               usage();
+       case 0:
+               fd = 0;
+               break;
+       case 1:
+               if((fd = open(argv[0], OREAD)) < 0)
+                       sysfatal("open %s: %r", argv[0]);
+               break;
+       }
+
+       while((n = readn(fd, buf, sizeof buf)) > 0){
+               data = realloc(data, length+n);
+               if(data == nil)
+                       sysfatal("realloc: %r");
+               memmove(data+length, buf, n);
+               length += n;
+               if(n < sizeof buf)
+                       break;
+       }
+       odat = malloc(length);
+       if(odat == nil)
+               sysfatal("malloc: %r");
+
+       Binit(&bout, 1, OWRITE);
+       Bprint(&bout, "BLZ\n");
+       Bputint(&bout, length);
+       outn = 1;
+       for(i=0; i<win; i++)
+               outn = (outn * 256) % Prime;
+
+       if(verbose)
+               fprint(2, "256^%d = %.6lux\n", win, outn);
+       outn = Prime - outn;
+       if(verbose)
+               fprint(2, "outn = %.6lux\n", outn);
+
+       compress();
+       Bwrite(&bout, odat, nodat);
+       Bterm(&bout);
+       fprint(2, "brk %p\n", sbrk(1));
+       fprint(2, "%d nodes used; %d of %d hash slots used\n", nalloc, nnew, nhash);
+       exits(nil);     
+}
diff --git a/sys/lib/dist.old/cmd/bzfs/bzfs.h b/sys/lib/dist.old/cmd/bzfs/bzfs.h
new file mode 100644 (file)
index 0000000..1de291a
--- /dev/null
@@ -0,0 +1,11 @@
+int unbzip(int);
+void _unbzip(int, int);
+int unbflz(int);
+int xexpand(int);
+void *emalloc(ulong);
+void *erealloc(void*, ulong);
+char *estrdup(char*);
+
+void ramfsmain(int, char**);
+extern int chatty;
+void error(char*, ...);
diff --git a/sys/lib/dist.old/cmd/bzfs/mkext.c b/sys/lib/dist.old/cmd/bzfs/mkext.c
new file mode 100644 (file)
index 0000000..1fedd62
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * bzip2-based file system.
+ * the file system itself is just a bzipped2 xzipped mkfs archive
+ * prefixed with "bzfilesystem\n" and suffixed with
+ * a kilobyte of zeros.
+ *
+ * changes to the file system are only kept in 
+ * memory, not written back to the disk.
+ *
+ * this is intended for use on a floppy boot disk.
+ * we assume the file is in the dos file system and
+ * contiguous on the disk: finding it amounts to
+ * looking at the beginning of each sector for 
+ * "bzfilesystem\n".  then we pipe it through 
+ * bunzip2 and store the files in a file tree in memory.
+ * things are slightly complicated by the fact that
+ * devfloppy requires reads to be on a 512-byte
+ * boundary and be a multiple of 512 bytes; we
+ * fork a process to relieve bunzip2 of this restriction.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <auth.h>
+#include <fcall.h>
+#include "bzfs.h"
+
+enum{
+       LEN     = 8*1024,
+       NFLDS   = 6,            /* filename, modes, uid, gid, mtime, bytes */
+};
+
+void   mkdirs(char*, char*);
+void   mkdir(char*, ulong, ulong, char*, char*);
+void   extract(char*, ulong, ulong, char*, char*, ulong);
+void   seekpast(ulong);
+void   error(char*, ...);
+void   warn(char*, ...);
+void   usage(void);
+char *mtpt;
+Biobufhdr bin;
+uchar  binbuf[2*LEN];
+
+void
+usage(void)
+{
+       fprint(2, "usage: bzfs [-m mtpt] [-s] [-f file] [-h]\n");
+       exits("usage");
+}
+
+/*
+ * floppy disks can only be read on 512-byte 
+ * boundaries and in 512 byte multiples.
+ * feed one over a pipe to allow arbitrary reading.
+ */
+char zero[512];
+int
+blockread(int in, char *first, int nfirst)
+{
+       int p[2], out, n, rv;
+       char blk[512];
+
+       if(pipe(p) < 0)
+               sysfatal("pipe: %r");
+       rv = p[0];
+       out = p[1];
+       switch(rfork(RFPROC|RFNOTEG|RFFDG)){
+       case -1:
+               sysfatal("fork: %r");
+       case 0:
+               close(rv);
+               break;
+       default:
+               close(in);
+               close(out);
+               return rv;
+       }
+
+       write(out, first, nfirst);
+       
+       while((n=read(in, blk, sizeof blk)) > 0){
+               if(write(out, blk, n) != n)
+                       break;
+               if(n == sizeof(blk) && memcmp(zero, blk, n) == n)
+                       break;
+       }
+       _exits(0);
+       return -1;
+}
+
+enum { NAMELEN = 28 };
+
+void
+main(int argc, char **argv)
+{
+       char *rargv[10];
+       int rargc;
+       char *fields[NFLDS], name[2*LEN], *p, *namep;
+       char uid[NAMELEN], gid[NAMELEN];
+       ulong mode, bytes, mtime;
+       char *file;
+       int i, n, stdin, fd, chatty;
+       char blk[512];
+
+       if(argc>1 && strcmp(argv[1], "RAMFS") == 0){
+               argv[1] = argv[0];
+               ramfsmain(argc-1, argv+1);
+               exits(nil);
+       }
+       if(argc>1 && strcmp(argv[1], "BUNZIP") == 0){
+               _unbzip(0, 1);
+               exits(nil);
+       }
+
+       rfork(RFNOTEG);
+       stdin = 0;
+       file = nil;
+       namep = name;
+       mtpt = "/root";
+       chatty = 0;
+       ARGBEGIN{
+       case 'd':
+               chatty = !chatty;
+               break;
+       case 'f':
+               file = ARGF();
+               break;
+       case 's':
+               stdin++;
+               break;
+       case 'm':
+               mtpt = ARGF();
+               break;
+       default:
+               usage();
+       }ARGEND
+
+       if(argc != 0)
+               usage();
+
+       if(file == nil) {
+               fprint(2, "must specify -f file\n");
+               usage();
+       }
+
+       if((fd = open(file, OREAD)) < 0) {
+               fprint(2, "cannot open \"%s\": %r\n", file);
+               exits("open");
+       }
+
+       rargv[0] = "ramfs";
+       rargc = 1;
+       if(stdin)
+               rargv[rargc++] = "-i";
+       rargv[rargc++] = "-m";
+       rargv[rargc++] = mtpt;
+       rargv[rargc] = nil;
+       ramfsmain(rargc, rargv);
+
+       if(1 || strstr(file, "disk")) { /* search for archive on block boundary */
+if(chatty) fprint(2, "searching for bz\n");
+               for(i=0;; i++){
+                       if((n = readn(fd, blk, sizeof blk)) != sizeof blk)
+                               sysfatal("read %d gets %d: %r\n", i, n);
+                       if(strncmp(blk, "bzfilesystem\n", 13) == 0)
+                               break;
+               }
+if(chatty) fprint(2, "found at %d\n", i);
+       }
+
+       if(chdir(mtpt) < 0)
+               error("chdir %s: %r", mtpt);
+
+       fd = unbflz(unbzip(blockread(fd, blk+13, sizeof(blk)-13)));
+
+       Binits(&bin, fd, OREAD, binbuf, sizeof binbuf);
+       while(p = Brdline(&bin, '\n')){
+               p[Blinelen(&bin)-1] = '\0';
+if(chatty) fprint(2, "%s\n", p);
+               if(strcmp(p, "end of archive") == 0){
+                       _exits(0);
+               }
+               if(getfields(p, fields, NFLDS, 0, " \t") != NFLDS){
+                       warn("too few fields in file header");
+                       continue;
+               }
+               strcpy(namep, fields[0]);
+               mode = strtoul(fields[1], 0, 8);
+               mtime = strtoul(fields[4], 0, 10);
+               bytes = strtoul(fields[5], 0, 10);
+               strncpy(uid, fields[2], NAMELEN);
+               strncpy(gid, fields[3], NAMELEN);
+               if(mode & DMDIR)
+                       mkdir(name, mode, mtime, uid, gid);
+               else
+                       extract(name, mode, mtime, uid, gid, bytes);
+       }
+       fprint(2, "premature end of archive\n");
+       exits("premature end of archive");
+}
+
+char buf[8192];
+
+int
+ffcreate(char *name, ulong mode, char *uid, char *gid, ulong mtime, int length)
+{
+       int fd, om;
+       Dir nd;
+
+       sprint(buf, "%s/%s", mtpt, name);
+       om = ORDWR;
+       if(mode&DMDIR)
+               om = OREAD;
+       if((fd = create(buf, om, (mode&DMDIR)|0666)) < 0)
+               error("create %s: %r", buf);
+
+       nulldir(&nd);
+       nd.mode = mode;
+       nd.uid = uid;
+       nd.gid = gid;
+       nd.mtime = mtime;
+       if(length)
+               nd.length = length;
+       if(dirfwstat(fd, &nd) < 0)      
+               error("fwstat %s: %r", buf);
+
+       return fd;
+}
+
+void
+mkdir(char *name, ulong mode, ulong mtime, char *uid, char *gid)
+{
+       close(ffcreate(name, mode, uid, gid, mtime, 0));
+}
+
+void
+extract(char *name, ulong mode, ulong mtime, char *uid, char *gid, ulong bytes)
+{
+       int fd, tot, n;
+
+       fd = ffcreate(name, mode, uid, gid, mtime, bytes);
+
+       for(tot = 0; tot < bytes; tot += n){
+               n = sizeof buf;
+               if(tot + n > bytes)
+                       n = bytes - tot;
+               n = Bread(&bin, buf, n);
+               if(n <= 0)
+                       error("premature eof reading %s", name);
+               if(write(fd, buf, n) != n)
+                       error("short write writing %s", name);
+       }
+       close(fd);
+}
+
+void
+error(char *fmt, ...)
+{
+       char buf[1024];
+       va_list arg;
+
+       sprint(buf, "%s: ", argv0);
+       va_start(arg, fmt);
+       vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
+       va_end(arg);
+       fprint(2, "%s\n", buf);
+       exits(0);
+}
+
+void
+warn(char *fmt, ...)
+{
+       char buf[1024];
+       va_list arg;
+
+       sprint(buf, "%s: ", argv0);
+       va_start(arg, fmt);
+       vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
+       va_end(arg);
+       fprint(2, "%s\n", buf);
+}
+
+int
+_efgfmt(Fmt*)
+{
+       return -1;
+}
diff --git a/sys/lib/dist.old/cmd/bzfs/mkfile b/sys/lib/dist.old/cmd/bzfs/mkfile
new file mode 100644 (file)
index 0000000..df81b56
--- /dev/null
@@ -0,0 +1,20 @@
+</$objtype/mkfile
+
+TARG=bzfs
+
+OFILES=\
+       mkext.$O\
+       oramfs.$O\
+       unbflz.$O\
+       unbzip.$O\
+
+HFILES=bzfs.h
+
+BIN=/sys/lib/dist/bin/$objtype
+LIB=/sys/src/cmd/bzip2/lib/libbzip2.a$O
+</sys/src/cmd/mkone
+
+CFLAGS=$CFLAGS -p -I/sys/src/cmd/bzip2/lib
+
+/sys/src/cmd/bzip2/lib/libbzip2.a$O:
+       @{cd /sys/src/cmd/bzip2/lib && mk}
diff --git a/sys/lib/dist.old/cmd/bzfs/oramfs.c b/sys/lib/dist.old/cmd/bzfs/oramfs.c
new file mode 100644 (file)
index 0000000..cba0272
--- /dev/null
@@ -0,0 +1,927 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include "bzfs.h"
+
+/*
+ * Rather than reading /adm/users, which is a lot of work for
+ * a toy program, we assume all groups have the form
+ *     NNN:user:user:
+ * meaning that each user is the leader of his own group.
+ */
+
+enum
+{
+       OPERM   = 0x3,          /* mask of all permission types in open mode */
+       Nram    = 512,
+       Maxsize = 512*1024*1024,
+       Maxfdata        = 8192,
+};
+
+typedef struct Fid Fid;
+typedef struct Ram Ram;
+
+struct Fid
+{
+       short   busy;
+       short   open;
+       short   rclose;
+       int     fid;
+       Fid     *next;
+       char    *user;
+       Ram     *ram;
+};
+
+struct Ram
+{
+       short   busy;
+       short   open;
+       long    parent;         /* index in Ram array */
+       Qid     qid;
+       long    perm;
+       char    *name;
+       ulong   atime;
+       ulong   mtime;
+       char    *user;
+       char    *group;
+       char    *muid;
+       char    *data;
+       long    ndata;
+};
+
+enum
+{
+       Pexec =         1,
+       Pwrite =        2,
+       Pread =         4,
+       Pother =        1,
+       Pgroup =        8,
+       Powner =        64,
+};
+
+ulong  path;           /* incremented for each new file */
+Fid    *fids;
+Ram    ram[Nram];
+int    nram;
+int    mfd[2];
+char   *user;
+uchar  mdata[IOHDRSZ+Maxfdata];
+uchar  rdata[Maxfdata];        /* buffer for data in reply */
+uchar statbuf[STATMAX];
+Fcall thdr;
+Fcall  rhdr;
+int    messagesize = sizeof mdata;
+
+Fid *  newfid(int);
+uint   ramstat(Ram*, uchar*, uint);
+void   io(void);
+void   *erealloc(void*, ulong);
+void   *emalloc(ulong);
+char   *estrdup(char*);
+void   ramfsusage(void);
+int    perm(Fid*, Ram*, int);
+char *atom(char*);
+
+char   *rflush(Fid*), *rversion(Fid*), *rauth(Fid*),
+       *rattach(Fid*), *rwalk(Fid*),
+       *ropen(Fid*), *rcreate(Fid*),
+       *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
+       *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
+
+char   *(*fcalls[])(Fid*) = {
+       [Tversion]      rversion,
+       [Tflush]        rflush,
+       [Tauth] rauth,
+       [Tattach]       rattach,
+       [Twalk]         rwalk,
+       [Topen]         ropen,
+       [Tcreate]       rcreate,
+       [Tread]         rread,
+       [Twrite]        rwrite,
+       [Tclunk]        rclunk,
+       [Tremove]       rremove,
+       [Tstat]         rstat,
+       [Twstat]        rwstat,
+};
+
+char   Eperm[] =       "permission denied";
+char   Enotdir[] =     "not a directory";
+char   Enoauth[] =     "no authentication in ramfs";
+char   Enotexist[] =   "file does not exist";
+char   Einuse[] =      "file in use";
+char   Eexist[] =      "file exists";
+char   Eisdir[] =      "file is a directory";
+char   Enotowner[] =   "not owner";
+char   Eisopen[] =     "file already open for I/O";
+char   Excl[] =        "exclusive use file already open";
+char   Ename[] =       "illegal name";
+char   Eversion[] =    "unknown 9P version";
+
+int debug;
+
+void
+notifyf(void *a, char *s)
+{
+       USED(a);
+       if(strncmp(s, "interrupt", 9) == 0)
+               noted(NCONT);
+       noted(NDFLT);
+}
+
+void
+ramfsmain(int argc, char *argv[])
+{
+       Ram *r;
+       char *defmnt;
+       int p[2];
+       char buf[32];
+       int fd, srvfd;
+       int stdio = 0;
+
+       srvfd = -1;
+       defmnt = "/tmp";
+       ARGBEGIN{
+       case 'D':
+               debug = 1;
+               break;
+       case 'i':               /* this is DIFFERENT from normal ramfs; use 1 for both for kernel */
+               defmnt = 0;
+               stdio = 1;
+               srvfd = 0;
+               mfd[0] = 1;
+               mfd[1] = 1;
+               break;
+       case 's':
+               defmnt = 0;
+               break;
+       case 'm':
+               defmnt = ARGF();
+               break;
+       default:
+               ramfsusage();
+       }ARGEND
+
+       if(!stdio){
+               if(pipe(p) < 0)
+                       error("pipe failed");
+               srvfd = p[1];
+               mfd[0] = p[0];
+               mfd[1] = p[0];
+               if(defmnt == 0){
+                       fd = create("#s/ramfs", OWRITE, 0666);
+                       if(fd < 0)
+                               error("create of /srv/ramfs failed");
+                       sprint(buf, "%d", p[1]);
+                       if(write(fd, buf, strlen(buf)) < 0)
+                               error("writing /srv/ramfs");
+               }
+       }
+
+       user = atom(getuser());
+       notify(notifyf);
+       nram = 1;
+       r = &ram[0];
+       r->busy = 1;
+       r->data = 0;
+       r->ndata = 0;
+       r->perm = DMDIR | 0775;
+       r->qid.type = QTDIR;
+       r->qid.path = 0LL;
+       r->qid.vers = 0;
+       r->parent = 0;
+       r->user = user;
+       r->group = user;
+       r->muid = user;
+       r->atime = time(0);
+       r->mtime = r->atime;
+       r->name = estrdup(".");
+
+       if(debug)
+               fmtinstall('F', fcallfmt);
+       switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
+       case -1:
+               error("fork");
+       case 0:
+               close(srvfd);
+               io();
+               break;
+       default:
+               close(mfd[0]);  /* don't deadlock if child fails */
+               if(defmnt && mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0)
+                       error("mount failed: %r");
+       }
+}
+
+char*
+rversion(Fid*)
+{
+       Fid *f;
+
+       for(f = fids; f; f = f->next)
+               if(f->busy)
+                       rclunk(f);
+       if(thdr.msize > sizeof mdata)
+               rhdr.msize = sizeof mdata;
+       else
+               rhdr.msize = thdr.msize;
+       messagesize = rhdr.msize;
+       if(strncmp(thdr.version, "9P2000", 6) != 0)
+               return Eversion;
+       rhdr.version = "9P2000";
+       return 0;
+}
+
+char*
+rauth(Fid*)
+{
+       return "ramfs: no authentication required";
+}
+
+char*
+rflush(Fid *f)
+{
+       USED(f);
+       return 0;
+}
+
+char*
+rattach(Fid *f)
+{
+       /* no authentication! */
+       f->busy = 1;
+       f->rclose = 0;
+       f->ram = &ram[0];
+       rhdr.qid = f->ram->qid;
+       if(thdr.uname[0])
+               f->user = atom(thdr.uname);
+       else
+               f->user = atom("none");
+       if(strcmp(user, "none") == 0)
+               user = f->user;
+       return 0;
+}
+
+char*
+clone(Fid *f, Fid **nf)
+{
+       if(f->open)
+               return Eisopen;
+       if(f->ram->busy == 0)
+               return Enotexist;
+       *nf = newfid(thdr.newfid);
+       (*nf)->busy = 1;
+       (*nf)->open = 0;
+       (*nf)->rclose = 0;
+       (*nf)->ram = f->ram;
+       (*nf)->user = f->user;  /* no ref count; the leakage is minor */
+       return 0;
+}
+
+char*
+rwalk(Fid *f)
+{
+       Ram *r, *fram;
+       char *name;
+       Ram *parent;
+       Fid *nf;
+       char *err;
+       ulong t;
+       int i;
+
+       err = nil;
+       nf = nil;
+       rhdr.nwqid = 0;
+       if(rhdr.newfid != rhdr.fid){
+               err = clone(f, &nf);
+               if(err)
+                       return err;
+               f = nf; /* walk the new fid */
+       }
+       fram = f->ram;
+       if(thdr.nwname > 0){
+               t = time(0);
+               for(i=0; i<thdr.nwname && i<MAXWELEM; i++){
+                       if((fram->qid.type & QTDIR) == 0){
+                               err = Enotdir;
+                               break;
+                       }
+                       if(fram->busy == 0){
+                               err = Enotexist;
+                               break;
+                       }
+                       fram->atime = t;
+                       name = thdr.wname[i];
+                       if(strcmp(name, ".") == 0){
+    Found:
+                               rhdr.nwqid++;
+                               rhdr.wqid[i] = fram->qid;
+                               continue;
+                       }
+                       parent = &ram[fram->parent];
+#ifdef CHECKS
+                       if(!perm(f, parent, Pexec)){
+                               err = Eperm;
+                               break;
+                       }
+#endif
+                       if(strcmp(name, "..") == 0){
+                               fram = parent;
+                               goto Found;
+                       }
+                       for(r=ram; r < &ram[nram]; r++)
+                               if(r->busy && r->parent==fram-ram && strcmp(name, r->name)==0){
+                                       fram = r;
+                                       goto Found;
+                               }
+                       break;
+               }
+               if(i==0 && err == nil)
+                       err = Enotexist;
+       }
+       if(nf != nil && (err!=nil || rhdr.nwqid<thdr.nwname)){
+               /* clunk the new fid, which is the one we walked */
+               f->busy = 0;
+               f->ram = nil;
+       }
+       if(rhdr.nwqid == thdr.nwname)   /* update the fid after a successful walk */
+               f->ram = fram;
+       return err;
+}
+
+char *
+ropen(Fid *f)
+{
+       Ram *r;
+       int mode, trunc;
+
+       if(f->open)
+               return Eisopen;
+       r = f->ram;
+       if(r->busy == 0)
+               return Enotexist;
+       if(r->perm & DMEXCL)
+               if(r->open)
+                       return Excl;
+       mode = thdr.mode;
+       if(r->qid.type & QTDIR){
+               if(mode != OREAD)
+                       return Eperm;
+               rhdr.qid = r->qid;
+               return 0;
+       }
+       if(mode & ORCLOSE){
+               /* can't remove root; must be able to write parent */
+               if(r->qid.path==0 || !perm(f, &ram[r->parent], Pwrite))
+                       return Eperm;
+               f->rclose = 1;
+       }
+       trunc = mode & OTRUNC;
+       mode &= OPERM;
+       if(mode==OWRITE || mode==ORDWR || trunc)
+               if(!perm(f, r, Pwrite))
+                       return Eperm;
+       if(mode==OREAD || mode==ORDWR)
+               if(!perm(f, r, Pread))
+                       return Eperm;
+       if(mode==OEXEC)
+               if(!perm(f, r, Pexec))
+                       return Eperm;
+       if(trunc && (r->perm&DMAPPEND)==0){
+               r->ndata = 0;
+               if(r->data)
+                       free(r->data);
+               r->data = 0;
+               r->qid.vers++;
+       }
+       rhdr.qid = r->qid;
+       rhdr.iounit = messagesize-IOHDRSZ;
+       f->open = 1;
+       r->open++;
+       return 0;
+}
+
+char *
+rcreate(Fid *f)
+{
+       Ram *r;
+       char *name;
+       long parent, prm;
+
+       if(f->open)
+               return Eisopen;
+       if(f->ram->busy == 0)
+               return Enotexist;
+       parent = f->ram - ram;
+       if((f->ram->qid.type&QTDIR) == 0)
+               return Enotdir;
+       /* must be able to write parent */
+#ifdef CHECKS
+       if(!perm(f, f->ram, Pwrite))
+               return Eperm;
+#endif
+       prm = thdr.perm;
+       name = thdr.name;
+       if(strcmp(name, ".")==0 || strcmp(name, "..")==0)
+               return Ename;
+       for(r=ram; r<&ram[nram]; r++)
+               if(r->busy && parent==r->parent)
+               if(strcmp((char*)name, r->name)==0)
+                       return Einuse;
+       for(r=ram; r->busy; r++)
+               if(r == &ram[Nram-1])
+                       return "no free ram resources";
+       r->busy = 1;
+       r->qid.path = ++path;
+       r->qid.vers = 0;
+       if(prm & DMDIR)
+               r->qid.type |= QTDIR;
+       r->parent = parent;
+       free(r->name);
+       r->name = estrdup(name);
+       r->user = f->user;
+       r->group = f->ram->group;
+       r->muid = f->ram->muid;
+       if(prm & DMDIR)
+               prm = (prm&~0777) | (f->ram->perm&prm&0777);
+       else
+               prm = (prm&(~0777|0111)) | (f->ram->perm&prm&0666);
+       r->perm = prm;
+       r->ndata = 0;
+       if(r-ram >= nram)
+               nram = r - ram + 1;
+       r->atime = time(0);
+       r->mtime = r->atime;
+       f->ram->mtime = r->atime;
+       f->ram = r;
+       rhdr.qid = r->qid;
+       rhdr.iounit = messagesize-IOHDRSZ;
+       f->open = 1;
+       if(thdr.mode & ORCLOSE)
+               f->rclose = 1;
+       r->open++;
+       return 0;
+}
+
+char*
+rread(Fid *f)
+{
+       Ram *r;
+       uchar *buf;
+       long off;
+       int n, m, cnt;
+
+       if(f->ram->busy == 0)
+               return Enotexist;
+       n = 0;
+       rhdr.count = 0;
+       off = thdr.offset;
+       buf = rdata;
+       cnt = thdr.count;
+       if(cnt > messagesize)   /* shouldn't happen, anyway */
+               cnt = messagesize;
+       if(f->ram->qid.type & QTDIR){
+               for(r=ram+1; off > 0; r++){
+                       if(r->busy && r->parent==f->ram-ram)
+                               off -= ramstat(r, statbuf, sizeof statbuf);
+                       if(r == &ram[nram-1])
+                               return 0;
+               }
+               for(; r<&ram[nram] && n < cnt; r++){
+                       if(!r->busy || r->parent!=f->ram-ram)
+                               continue;
+                       m = ramstat(r, buf+n, cnt-n);
+                       if(m == 0)
+                               break;
+                       n += m;
+               }
+               rhdr.data = (char*)rdata;
+               rhdr.count = n;
+               return 0;
+       }
+       r = f->ram;
+       if(off >= r->ndata)
+               return 0;
+       r->atime = time(0);
+       n = cnt;
+       if(off+n > r->ndata)
+               n = r->ndata - off;
+       rhdr.data = r->data+off;
+       rhdr.count = n;
+       return 0;
+}
+
+char*
+rwrite(Fid *f)
+{
+       Ram *r;
+       ulong off;
+       int cnt;
+
+       r = f->ram;
+       if(r->busy == 0)
+               return Enotexist;
+       off = thdr.offset;
+       if(r->perm & DMAPPEND)
+               off = r->ndata;
+       cnt = thdr.count;
+       if(r->qid.type & QTDIR)
+               return Eisdir;
+       if(off+cnt >= Maxsize)          /* sanity check */
+               return "write too big";
+       if(off+cnt > r->ndata)
+               r->data = erealloc(r->data, off+cnt);
+       if(off > r->ndata)
+               memset(r->data+r->ndata, 0, off-r->ndata);
+       if(off+cnt > r->ndata)
+               r->ndata = off+cnt;
+       memmove(r->data+off, thdr.data, cnt);
+       r->qid.vers++;
+       r->mtime = time(0);
+       rhdr.count = cnt;
+       return 0;
+}
+
+void
+realremove(Ram *r)
+{
+       r->ndata = 0;
+       if(r->data)
+               free(r->data);
+       r->data = 0;
+       r->parent = 0;
+       memset(&r->qid, 0, sizeof r->qid);
+       free(r->name);
+       r->name = nil;
+       r->busy = 0;
+}
+
+char *
+rclunk(Fid *f)
+{
+       if(f->open)
+               f->ram->open--;
+       if(f->rclose)
+               realremove(f->ram);
+       f->busy = 0;
+       f->open = 0;
+       f->ram = 0;
+       return 0;
+}
+
+char *
+rremove(Fid *f)
+{
+       Ram *r;
+
+       if(f->open)
+               f->ram->open--;
+       f->busy = 0;
+       f->open = 0;
+       r = f->ram;
+       f->ram = 0;
+#ifdef CHECKS
+       if(r->qid.path == 0 || !perm(f, &ram[r->parent], Pwrite))
+               return Eperm;
+#endif
+       ram[r->parent].mtime = time(0);
+       realremove(r);
+       return 0;
+}
+
+char *
+rstat(Fid *f)
+{
+       if(f->ram->busy == 0)
+               return Enotexist;
+       rhdr.nstat = ramstat(f->ram, statbuf, sizeof statbuf);
+       rhdr.stat = statbuf;
+       return 0;
+}
+
+char *
+rwstat(Fid *f)
+{
+       Ram *r, *s;
+       Dir dir;
+
+       if(f->ram->busy == 0)
+               return Enotexist;
+       convM2D(thdr.stat, thdr.nstat, &dir, (char*)statbuf);
+       r = f->ram;
+
+       /*
+        * To change length, must have write permission on file.
+        */
+#ifdef CHECKS
+       if(dir.length!=~0 && dir.length!=r->ndata){
+               if(!perm(f, r, Pwrite))
+                       return Eperm;
+       }
+#endif
+
+       /*
+        * To change name, must have write permission in parent
+        * and name must be unique.
+        */
+       if(dir.name[0]!='\0' && strcmp(dir.name, r->name)!=0){
+#ifdef CHECKS
+               if(!perm(f, &ram[r->parent], Pwrite))
+                       return Eperm;
+#endif
+               for(s=ram; s<&ram[nram]; s++)
+                       if(s->busy && s->parent==r->parent)
+                       if(strcmp(dir.name, s->name)==0)
+                               return Eexist;
+       }
+
+#ifdef OWNERS
+       /*
+        * To change mode, must be owner or group leader.
+        * Because of lack of users file, leader=>group itself.
+        */
+       if(dir.mode!=~0 && r->perm!=dir.mode){
+               if(strcmp(f->user, r->user) != 0)
+               if(strcmp(f->user, r->group) != 0)
+                       return Enotowner;
+       }
+
+       /*
+        * To change group, must be owner and member of new group,
+        * or leader of current group and leader of new group.
+        * Second case cannot happen, but we check anyway.
+        */
+       if(dir.gid[0]!='\0' && strcmp(r->group, dir.gid)!=0){
+               if(strcmp(f->user, r->user) == 0)
+               if(strcmp(f->user, dir.gid) == 0)
+                       goto ok;
+               if(strcmp(f->user, r->group) == 0)
+               if(strcmp(f->user, dir.gid) == 0)
+                       goto ok;
+               return Enotowner;
+               ok:;
+       }
+#endif
+
+       /* all ok; do it */
+       if(dir.mode != ~0){
+               dir.mode &= ~DMDIR;     /* cannot change dir bit */
+               dir.mode |= r->perm&DMDIR;
+               r->perm = dir.mode;
+       }
+       if(dir.name[0] != '\0'){
+               free(r->name);
+               r->name = estrdup(dir.name);
+       }
+       if(dir.gid[0] != '\0')
+               r->group = atom(dir.gid);
+
+       if(dir.uid[0] != '\0')
+               r->user = atom(dir.uid);
+
+       if(dir.length!=~0 && dir.length!=r->ndata){
+               r->data = erealloc(r->data, dir.length);
+               if(r->ndata < dir.length)
+                       memset(r->data+r->ndata, 0, dir.length-r->ndata);
+               r->ndata = dir.length;
+       }
+
+       if(dir.mtime != ~0)
+               r->mtime = dir.mtime;
+
+       ram[r->parent].mtime = time(0);
+       return 0;
+}
+
+uint
+ramstat(Ram *r, uchar *buf, uint nbuf)
+{
+       Dir dir;
+
+       dir.name = r->name;
+       dir.qid = r->qid;
+       dir.mode = r->perm;
+       dir.length = r->ndata;
+       dir.uid = r->user;
+       dir.gid = r->group;
+       dir.muid = r->muid;
+       dir.atime = r->atime;
+       dir.mtime = r->mtime;
+       return convD2M(&dir, buf, nbuf);
+}
+
+Fid *
+newfid(int fid)
+{
+       Fid *f, *ff;
+
+       ff = 0;
+       for(f = fids; f; f = f->next)
+               if(f->fid == fid)
+                       return f;
+               else if(!ff && !f->busy)
+                       ff = f;
+       if(ff){
+               ff->fid = fid;
+               return ff;
+       }
+       f = emalloc(sizeof *f);
+       f->ram = nil;
+       f->fid = fid;
+       f->next = fids;
+       fids = f;
+       return f;
+}
+
+void
+io(void)
+{
+       char *err;
+       int n, pid;
+
+       pid = getpid();
+
+       for(;;){
+               /*
+                * reading from a pipe or a network device
+                * will give an error after a few eof reads.
+                * however, we cannot tell the difference
+                * between a zero-length read and an interrupt
+                * on the processes writing to us,
+                * so we wait for the error.
+                */
+               n = read9pmsg(mfd[0], mdata, messagesize);
+               if(n < 0)
+                       error("mount read: %r");
+               if(n == 0)
+                       continue;
+               if(convM2S(mdata, n, &thdr) == 0)
+                       continue;
+
+               if(debug)
+                       fprint(2, "ramfs %d:<-%F\n", pid, &thdr);
+
+               if(!fcalls[thdr.type])
+                       err = "bad fcall type";
+               else
+                       err = (*fcalls[thdr.type])(newfid(thdr.fid));
+               if(err){
+                       rhdr.type = Rerror;
+                       rhdr.ename = err;
+               }else{
+                       rhdr.type = thdr.type + 1;
+                       rhdr.fid = thdr.fid;
+               }
+               rhdr.tag = thdr.tag;
+               if(debug)
+                       fprint(2, "ramfs %d:->%F\n", pid, &rhdr);/**/
+               n = convS2M(&rhdr, mdata, messagesize);
+               if(n == 0)
+                       error("convS2M error on write");
+               if(write(mfd[1], mdata, n) != n)
+                       error("mount write");
+       }
+}
+
+int
+perm(Fid *f, Ram *r, int p)
+{
+       if((p*Pother) & r->perm)
+               return 1;
+       if(strcmp(f->user, r->group)==0 && ((p*Pgroup) & r->perm))
+               return 1;
+       if(strcmp(f->user, r->user)==0 && ((p*Powner) & r->perm))
+               return 1;
+       return 0;
+}
+
+void *
+emalloc(ulong n)
+{
+       void *p;
+
+       p = malloc(n);
+       if(!p)
+               error("out of memory");
+       memset(p, 0, n);
+       return p;
+}
+
+void *
+erealloc(void *p, ulong n)
+{
+       p = realloc(p, n);
+       if(!p)
+               error("out of memory");
+       return p;
+}
+
+char *
+estrdup(char *q)
+{
+       char *p;
+       int n;
+
+       n = strlen(q)+1;
+       p = malloc(n);
+       if(!p)
+               error("out of memory");
+       memmove(p, q, n);
+       return p;
+}
+
+void
+ramfsusage(void)
+{
+       fprint(2, "usage: %s [-is] [-m mountpoint]\n", argv0);
+       exits("usage");
+}
+
+/*
+ *     Custom allocators to avoid malloc overheads on small objects.
+ *     We never free these.  (See below.)
+ */
+typedef struct Stringtab       Stringtab;
+struct Stringtab {
+       Stringtab *link;
+       char *str;
+};
+static Stringtab*
+taballoc(void)
+{
+       static Stringtab *t;
+       static uint nt;
+
+       if(nt == 0){
+               t = malloc(64*sizeof(Stringtab));
+               if(t == 0)
+                       sysfatal("out of memory");
+               nt = 64;
+       }
+       nt--;
+       return t++;
+}
+
+static char*
+xstrdup(char *s)
+{
+       char *r;
+       int len;
+       static char *t;
+       static int nt;
+
+       len = strlen(s)+1;
+       if(len >= 8192)
+               sysfatal("strdup big string");
+
+       if(nt < len){
+               t = malloc(8192);
+               if(t == 0)
+                       sysfatal("out of memory");
+               nt = 8192;
+       }
+       r = t;
+       t += len;
+       nt -= len;
+       strcpy(r, s);
+       return r;
+}
+
+/*
+ *     Return a uniquely allocated copy of a string.
+ *     Don't free these -- they stay in the table for the 
+ *     next caller who wants that particular string.
+ *     String comparison can be done with pointer comparison 
+ *     if you know both strings are atoms.
+ */
+static Stringtab *stab[1024];
+
+static uint
+hash(char *s)
+{
+       uint h;
+       uchar *p;
+
+       h = 0;
+       for(p=(uchar*)s; *p; p++)
+               h = h*37 + *p;
+       return h;
+}
+
+char*
+atom(char *str)
+{
+       uint h;
+       Stringtab *tab;
+       
+       h = hash(str) % nelem(stab);
+       for(tab=stab[h]; tab; tab=tab->link)
+               if(strcmp(str, tab->str) == 0)
+                       return tab->str;
+
+       tab = taballoc();
+       tab->str = xstrdup(str);
+       tab->link = stab[h];
+       stab[h] = tab;
+       return tab->str;
+}
diff --git a/sys/lib/dist.old/cmd/bzfs/unbflz.c b/sys/lib/dist.old/cmd/bzfs/unbflz.c
new file mode 100644 (file)
index 0000000..661d65e
--- /dev/null
@@ -0,0 +1,108 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "bzfs.h"
+
+int
+Bgetint(Biobuf *b)
+{
+       uchar p[4];
+
+       if(Bread(b, p, 4) != 4)
+               sysfatal("short read");
+       return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+}
+
+/*
+ * memmove but make sure overlap works properly.
+ */
+void
+copy(uchar *dst, uchar *src, int n)
+{
+       while(n-- > 0)
+               *dst++ = *src++;
+}
+
+int
+unbflz(int in)
+{
+       int rv, out, p[2];
+       Biobuf *b, bin;
+       char buf[5];
+       uchar *data;
+       int i, j, length, n, m, o, sum;
+       ulong *blk;
+       int nblk, mblk;
+
+       if(pipe(p) < 0)
+               sysfatal("pipe: %r");
+
+       rv = p[0];
+       out = p[1];
+       switch(rfork(RFPROC|RFFDG|RFNOTEG|RFMEM)){
+       case -1:
+               sysfatal("fork: %r");
+       case 0:
+               close(rv);
+               break;
+       default:
+               close(in);
+               close(out);
+               return rv;
+       }
+
+       Binit(&bin, in, OREAD);
+       b = &bin;
+
+       if(Bread(b, buf, 4) != 4)
+               sysfatal("short read");
+
+       if(memcmp(buf, "BLZ\n", 4) != 0)
+               sysfatal("bad header");
+
+       length = Bgetint(b);
+       data = malloc(length);
+       if(data == nil)
+               sysfatal("out of memory");
+       sum = 0;
+       nblk = 0;
+       mblk = 0;
+       blk = nil;
+       while(sum < length){
+               if(nblk>=mblk){
+                       mblk += 16384;
+                       blk = realloc(blk, (mblk+1)*sizeof(blk[0]));
+                       if(blk == nil)
+                               sysfatal("out of memory");
+               }
+               n = Bgetint(b);
+               blk[nblk++] = n;
+               if(n&(1<<31))
+                       n &= ~(1<<31);
+               else
+                       blk[nblk++] = Bgetint(b);
+               sum += n;
+       }
+       if(sum != length)
+               sysfatal("bad compressed data %d %d", sum, length);
+       i = 0;
+       j = 0;
+       while(i < length){
+               assert(j < nblk);
+               n = blk[j++];
+               if(n&(1<<31)){
+                       n &= ~(1<<31);
+                       if((m=Bread(b, data+i, n)) != n)
+                               sysfatal("short read %d %d", n, m);
+               }else{
+                       o = blk[j++];
+                       copy(data+i, data+o, n);
+               }
+               i += n;
+       }
+       write(out, data, length);
+       close(in);
+       close(out);
+       _exits(0);
+       return -1;
+}
diff --git a/sys/lib/dist.old/cmd/bzfs/unbzip.c b/sys/lib/dist.old/cmd/bzfs/unbzip.c
new file mode 100644 (file)
index 0000000..070e7ba
--- /dev/null
@@ -0,0 +1,861 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "bzfs.h"
+
+/*
+ * THIS FILE IS NOT IDENTICAL TO THE ORIGINAL
+ * FROM THE BZIP2 DISTRIBUTION.
+ *
+ * It has been modified, mainly to break the library
+ * into smaller pieces.
+ *
+ * Russ Cox
+ * rsc@plan9.bell-labs.com
+ * July 2000
+ */
+
+/*---------------------------------------------*/
+/*--
+  Place a 1 beside your platform, and 0 elsewhere.
+  Attempts to autosniff this even if you don't.
+--*/
+
+
+/*--
+  Plan 9 from Bell Labs
+--*/
+#define BZ_PLAN9     1
+#define BZ_UNIX 0
+
+#define exit(x) exits((x) ? "whoops" : nil)
+#define size_t ulong
+
+#ifdef __GNUC__
+#   define NORETURN __attribute__ ((noreturn))
+#else
+#   define NORETURN /**/
+#endif
+
+/*--
+  Some more stuff for all platforms :-)
+  This might have to get moved into the platform-specific
+  header files if we encounter a machine with different sizes.
+--*/
+
+typedef char            Char;
+typedef unsigned char   Bool;
+typedef unsigned char   UChar;
+typedef int             Int32;
+typedef unsigned int    UInt32;
+typedef short           Int16;
+typedef unsigned short  UInt16;
+                                       
+#define True  ((Bool)1)
+#define False ((Bool)0)
+
+/*--
+  IntNative is your platform's `native' int size.
+  Only here to avoid probs with 64-bit platforms.
+--*/
+typedef int IntNative;
+
+#include "bzfs.h"
+#include "bzlib.h"
+#include "bzlib_private.h"
+
+static int
+bunzip(int ofd, char *ofile, Biobuf *bin)
+{
+       int e, n, done, onemore;
+       char buf[8192];
+       char obuf[8192];
+       Biobuf bout;
+       bz_stream strm;
+
+       USED(ofile);
+
+       memset(&strm, 0, sizeof strm);
+       BZ2_bzDecompressInit(&strm, 0, 0);
+
+       strm.next_in = buf;
+       strm.avail_in = 0;
+       strm.next_out = obuf;
+       strm.avail_out = sizeof obuf;
+
+       done = 0;
+       Binit(&bout, ofd, OWRITE);
+
+       /*
+        * onemore is a crummy hack to go 'round the loop
+        * once after we finish, to flush the output buffer.
+        */
+       onemore = 1;
+       SET(e);
+       do {
+               if(!done && strm.avail_in < sizeof buf) {
+                       if(strm.avail_in)
+                               memmove(buf, strm.next_in, strm.avail_in);
+                       
+                       n = Bread(bin, buf+strm.avail_in, sizeof(buf)-strm.avail_in);
+                       if(n <= 0)
+                               done = 1;
+                       else
+                               strm.avail_in += n;
+                       strm.next_in = buf;
+               }
+               if(strm.avail_out < sizeof obuf) {
+                       Bwrite(&bout, obuf, sizeof(obuf)-strm.avail_out);
+                       strm.next_out = obuf;
+                       strm.avail_out = sizeof obuf;
+               }
+
+               if(onemore == 0)
+                       break;
+       } while((e=BZ2_bzDecompress(&strm)) == BZ_OK || onemore--);
+
+       if(e != BZ_STREAM_END) {
+               fprint(2, "bunzip2: decompress failed\n");
+               return 0;
+       }
+
+       if(BZ2_bzDecompressEnd(&strm) != BZ_OK) {
+               fprint(2, "bunzip2: decompress end failed (can't happen)\n");
+               return 0;
+       }
+
+       Bterm(&bout);
+
+       return 1;
+}
+
+void
+_unbzip(int in, int out)
+{
+       Biobuf bin;
+
+       Binit(&bin, in, OREAD);
+       if(bunzip(out, nil, &bin) != 1) {
+               fprint(2, "bunzip2 failed\n");
+               _exits("bunzip2");
+       }
+}
+
+int
+unbzip(int in)
+{
+       int rv, out, p[2];
+
+       if(pipe(p) < 0)
+               sysfatal("pipe: %r");
+
+       rv = p[0];
+       out = p[1];
+       switch(rfork(RFPROC|RFFDG|RFNOTEG|RFMEM)){
+       case -1:
+               sysfatal("fork: %r");
+       case 0:
+               close(rv);
+               break;
+       default:
+               close(in);
+               close(out);
+               return rv;
+       }
+
+       _unbzip(in, out);
+       _exits(0);
+       return -1;      /* not reached */
+}
+
+int bz_config_ok ( void )
+{
+   if (sizeof(int)   != 4) return 0;
+   if (sizeof(short) != 2) return 0;
+   if (sizeof(char)  != 1) return 0;
+   return 1;
+}
+
+void* default_bzalloc(void *o, int items, int size)
+{
+       USED(o);
+       return sbrk(items*size);
+}
+
+void default_bzfree(void*, void*)
+{
+}
+
+void
+bz_internal_error(int)
+{
+       abort();
+}
+
+/*-------------------------------------------------------------*/
+/*--- Decompression machinery                               ---*/
+/*---                                          decompress.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+  This file is a part of bzip2 and/or libbzip2, a program and
+  library for lossless, block-sorting data compression.
+
+  Copyright (C) 1996-2000 Julian R Seward.  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+  2. The origin of this software must not be misrepresented; you must 
+     not claim that you wrote the original software.  If you use this 
+     software in a product, an acknowledgment in the product 
+     documentation would be appreciated but is not required.
+
+  3. Altered source versions must be plainly marked as such, and must
+     not be misrepresented as being the original software.
+
+  4. The name of the author may not be used to endorse or promote 
+     products derived from this software without specific prior written 
+     permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Julian Seward, Cambridge, UK.
+  jseward@acm.org
+  bzip2/libbzip2 version 1.0 of 21 March 2000
+
+  This program is based on (at least) the work of:
+     Mike Burrows
+     David Wheeler
+     Peter Fenwick
+     Alistair Moffat
+     Radford Neal
+     Ian H. Witten
+     Robert Sedgewick
+     Jon L. Bentley
+
+  For more information on these sources, see the manual.
+--*/
+
+
+
+/*---------------------------------------------------*/
+static
+void makeMaps_d ( DState* s )
+{
+   Int32 i;
+   s->nInUse = 0;
+   for (i = 0; i < 256; i++)
+      if (s->inUse[i]) {
+         s->seqToUnseq[s->nInUse] = i;
+         s->nInUse++;
+      }
+}
+
+
+/*---------------------------------------------------*/
+#define RETURN(rrr)                               \
+   { retVal = rrr; goto save_state_and_return; };
+
+#define GET_BITS(lll,vvv,nnn)                     \
+       case lll: \
+               { int x; if((retVal = getbits(s, lll, &x, nnn)) != 99) \
+                       goto save_state_and_return; vvv=x; }\
+
+int
+getbits(DState *s, int lll, int *vvv, int nnn)
+{
+       s->state = lll;
+       
+       for(;;) {
+               if (s->bsLive >= nnn) {
+                       UInt32 v;
+                       v = (s->bsBuff >>
+                                (s->bsLive-nnn)) & ((1 << nnn)-1);
+                       s->bsLive -= nnn;
+                       *vvv = v;
+                       return 99;
+               }
+               if (s->strm->avail_in == 0) return BZ_OK;
+               s->bsBuff
+                       = (s->bsBuff << 8) |
+                         ((UInt32)
+                                 (*((UChar*)(s->strm->next_in))));
+               s->bsLive += 8;
+               s->strm->next_in++;
+               s->strm->avail_in--;
+               s->strm->total_in_lo32++;
+               if (s->strm->total_in_lo32 == 0)
+                       s->strm->total_in_hi32++;
+       }
+       return -1;      /* KEN */
+}
+
+#define GET_UCHAR(lll,uuu)                        \
+   GET_BITS(lll,uuu,8)
+
+#define GET_BIT(lll,uuu)                          \
+   GET_BITS(lll,uuu,1)
+
+/*---------------------------------------------------*/
+#define GET_MTF_VAL(label1,label2,lval)           \
+{                                                 \
+   if (groupPos == 0) {                           \
+      groupNo++;                                  \
+      if (groupNo >= nSelectors)                  \
+         RETURN(BZ_DATA_ERROR);                   \
+      groupPos = BZ_G_SIZE;                       \
+      gSel = s->selector[groupNo];                \
+      gMinlen = s->minLens[gSel];                 \
+      gLimit = &(s->limit[gSel][0]);              \
+      gPerm = &(s->perm[gSel][0]);                \
+      gBase = &(s->base[gSel][0]);                \
+   }                                              \
+   groupPos--;                                    \
+   zn = gMinlen;                                  \
+   GET_BITS(label1, zvec, zn);                    \
+   while (1) {                                    \
+      if (zn > 20 /* the longest code */)         \
+         RETURN(BZ_DATA_ERROR);                   \
+      if (zvec <= gLimit[zn]) break;              \
+      zn++;                                       \
+      GET_BIT(label2, zj);                        \
+      zvec = (zvec << 1) | zj;                    \
+   };                                             \
+   if (zvec - gBase[zn] < 0                       \
+       || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE)  \
+      RETURN(BZ_DATA_ERROR);                      \
+   lval = gPerm[zvec - gBase[zn]];                \
+}
+
+
+/*---------------------------------------------------*/
+Int32 BZ2_decompress ( DState* s )
+{
+   UChar      uc;
+   Int32      retVal;
+   Int32      minLen, maxLen;
+   bz_stream* strm = s->strm;
+
+   /* stuff that needs to be saved/restored */
+   Int32  i;
+   Int32  j;
+   Int32  t;
+   Int32  alphaSize;
+   Int32  nGroups;
+   Int32  nSelectors;
+   Int32  EOB;
+   Int32  groupNo;
+   Int32  groupPos;
+   Int32  nextSym;
+   Int32  nblockMAX;
+   Int32  nblock;
+   Int32  es;
+   Int32  N;
+   Int32  curr;
+   Int32  zt;
+   Int32  zn; 
+   Int32  zvec;
+   Int32  zj;
+   Int32  gSel;
+   Int32  gMinlen;
+   Int32* gLimit;
+   Int32* gBase;
+   Int32* gPerm;
+
+   if (s->state == BZ_X_MAGIC_1) {
+      /*initialise the save area*/
+      s->save_i           = 0;
+      s->save_j           = 0;
+      s->save_t           = 0;
+      s->save_alphaSize   = 0;
+      s->save_nGroups     = 0;
+      s->save_nSelectors  = 0;
+      s->save_EOB         = 0;
+      s->save_groupNo     = 0;
+      s->save_groupPos    = 0;
+      s->save_nextSym     = 0;
+      s->save_nblockMAX   = 0;
+      s->save_nblock      = 0;
+      s->save_es          = 0;
+      s->save_N           = 0;
+      s->save_curr        = 0;
+      s->save_zt          = 0;
+      s->save_zn          = 0;
+      s->save_zvec        = 0;
+      s->save_zj          = 0;
+      s->save_gSel        = 0;
+      s->save_gMinlen     = 0;
+      s->save_gLimit      = NULL;
+      s->save_gBase       = NULL;
+      s->save_gPerm       = NULL;
+   }
+
+   /*restore from the save area*/
+   i           = s->save_i;
+   j           = s->save_j;
+   t           = s->save_t;
+   alphaSize   = s->save_alphaSize;
+   nGroups     = s->save_nGroups;
+   nSelectors  = s->save_nSelectors;
+   EOB         = s->save_EOB;
+   groupNo     = s->save_groupNo;
+   groupPos    = s->save_groupPos;
+   nextSym     = s->save_nextSym;
+   nblockMAX   = s->save_nblockMAX;
+   nblock      = s->save_nblock;
+   es          = s->save_es;
+   N           = s->save_N;
+   curr        = s->save_curr;
+   zt          = s->save_zt;
+   zn          = s->save_zn; 
+   zvec        = s->save_zvec;
+   zj          = s->save_zj;
+   gSel        = s->save_gSel;
+   gMinlen     = s->save_gMinlen;
+   gLimit      = s->save_gLimit;
+   gBase       = s->save_gBase;
+   gPerm       = s->save_gPerm;
+
+   retVal = BZ_OK;
+
+   switch (s->state) {
+
+      GET_UCHAR(BZ_X_MAGIC_1, uc);
+      if (uc != 'B') RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_UCHAR(BZ_X_MAGIC_2, uc);
+      if (uc != 'Z') RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_UCHAR(BZ_X_MAGIC_3, uc)
+      if (uc != 'h') RETURN(BZ_DATA_ERROR_MAGIC);
+
+      GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
+      if (s->blockSize100k < '1' || 
+          s->blockSize100k > '9') RETURN(BZ_DATA_ERROR_MAGIC);
+      s->blockSize100k -= '0';
+
+      if (0 && s->smallDecompress) {
+         s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
+         s->ll4  = BZALLOC( 
+                      ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) 
+                   );
+         if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
+      } else {
+         s->tt  = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
+         if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
+      }
+
+      GET_UCHAR(BZ_X_BLKHDR_1, uc);
+
+      if (uc == 0x17) goto endhdr_2;
+      if (uc != 0x31) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_2, uc);
+      if (uc != 0x41) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_3, uc);
+      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_4, uc);
+      if (uc != 0x26) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_5, uc);
+      if (uc != 0x53) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_BLKHDR_6, uc);
+      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+
+      s->currBlockNo++;
+    //  if (s->verbosity >= 2)
+    //     VPrintf1 ( "\n    [%d: huff+mtf ", s->currBlockNo );
+      s->storedBlockCRC = 0;
+      GET_UCHAR(BZ_X_BCRC_1, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_2, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_3, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_BCRC_4, uc);
+      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+
+      GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
+
+      s->origPtr = 0;
+      GET_UCHAR(BZ_X_ORIGPTR_1, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+      GET_UCHAR(BZ_X_ORIGPTR_2, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+      GET_UCHAR(BZ_X_ORIGPTR_3, uc);
+      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+
+      if (s->origPtr < 0)
+         RETURN(BZ_DATA_ERROR);
+      if (s->origPtr > 10 + 100000*s->blockSize100k) 
+         RETURN(BZ_DATA_ERROR);
+
+      /*--- Receive the mapping table ---*/
+      for (i = 0; i < 16; i++) {
+         GET_BIT(BZ_X_MAPPING_1, uc);
+         if (uc == 1) 
+            s->inUse16[i] = True; else 
+            s->inUse16[i] = False;
+      }
+
+      for (i = 0; i < 256; i++) s->inUse[i] = False;
+
+      for (i = 0; i < 16; i++)
+         if (s->inUse16[i])
+            for (j = 0; j < 16; j++) {
+               GET_BIT(BZ_X_MAPPING_2, uc);
+               if (uc == 1) s->inUse[i * 16 + j] = True;
+            }
+      makeMaps_d ( s );
+      if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
+      alphaSize = s->nInUse+2;
+
+      /*--- Now the selectors ---*/
+      GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
+      if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
+      GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
+      if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
+      for (i = 0; i < nSelectors; i++) {
+         j = 0;
+         while (True) {
+            GET_BIT(BZ_X_SELECTOR_3, uc);
+            if (uc == 0) break;
+            j++;
+            if (j >= nGroups) RETURN(BZ_DATA_ERROR);
+         }
+         s->selectorMtf[i] = j;
+      }
+
+      /*--- Undo the MTF values for the selectors. ---*/
+      {
+         UChar pos[BZ_N_GROUPS], tmp, v;
+         for (v = 0; v < nGroups; v++) pos[v] = v;
+   
+         for (i = 0; i < nSelectors; i++) {
+            v = s->selectorMtf[i];
+            tmp = pos[v];
+            while (v > 0) { pos[v] = pos[v-1]; v--; }
+            pos[0] = tmp;
+            s->selector[i] = tmp;
+         }
+      }
+
+      /*--- Now the coding tables ---*/
+      for (t = 0; t < nGroups; t++) {
+         GET_BITS(BZ_X_CODING_1, curr, 5);
+         for (i = 0; i < alphaSize; i++) {
+            while (True) {
+               if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
+               GET_BIT(BZ_X_CODING_2, uc);
+               if (uc == 0) break;
+               GET_BIT(BZ_X_CODING_3, uc);
+               if (uc == 0) curr++; else curr--;
+            }
+            s->len[t][i] = curr;
+         }
+      }
+
+      /*--- Create the Huffman decoding tables ---*/
+      for (t = 0; t < nGroups; t++) {
+         minLen = 32;
+         maxLen = 0;
+         for (i = 0; i < alphaSize; i++) {
+            if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+            if (s->len[t][i] < minLen) minLen = s->len[t][i];
+         }
+         BZ2_hbCreateDecodeTables ( 
+            &(s->limit[t][0]), 
+            &(s->base[t][0]), 
+            &(s->perm[t][0]), 
+            &(s->len[t][0]),
+            minLen, maxLen, alphaSize
+         );
+         s->minLens[t] = minLen;
+      }
+
+      /*--- Now the MTF values ---*/
+
+      EOB      = s->nInUse+1;
+      nblockMAX = 100000 * s->blockSize100k;
+      groupNo  = -1;
+      groupPos = 0;
+
+      for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
+
+      /*-- MTF init --*/
+      {
+         Int32 ii, jj, kk;
+         kk = MTFA_SIZE-1;
+         for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
+            for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+               s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
+               kk--;
+            }
+            s->mtfbase[ii] = kk + 1;
+         }
+      }
+      /*-- end MTF init --*/
+
+      nblock = 0;
+      GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
+
+      while (True) {
+
+         if (nextSym == EOB) break;
+
+         if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
+
+            es = -1;
+            N = 1;
+            do {
+               if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
+               if (nextSym == BZ_RUNB) es = es + (1+1) * N;
+               N = N * 2;
+               GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
+            }
+               while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
+
+            es++;
+            uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
+            s->unzftab[uc] += es;
+
+            if (0 && s->smallDecompress)
+               while (es > 0) {
+                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+                  s->ll16[nblock] = (UInt16)uc;
+                  nblock++;
+                  es--;
+               }
+            else
+               while (es > 0) {
+                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+                  s->tt[nblock] = (UInt32)uc;
+                  nblock++;
+                  es--;
+               };
+
+            continue;
+
+         } else {
+
+            if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+
+            /*-- uc = MTF ( nextSym-1 ) --*/
+            {
+               Int32 ii, jj, kk, pp, lno, off;
+               UInt32 nn;
+               nn = (UInt32)(nextSym - 1);
+
+               if (nn < MTFL_SIZE) {
+                  /* avoid general-case expense */
+                  pp = s->mtfbase[0];
+                  uc = s->mtfa[pp+nn];
+                  while (nn > 3) {
+                     Int32 z = pp+nn;
+                     s->mtfa[(z)  ] = s->mtfa[(z)-1];
+                     s->mtfa[(z)-1] = s->mtfa[(z)-2];
+                     s->mtfa[(z)-2] = s->mtfa[(z)-3];
+                     s->mtfa[(z)-3] = s->mtfa[(z)-4];
+                     nn -= 4;
+                  }
+                  while (nn > 0) { 
+                     s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; 
+                  };
+                  s->mtfa[pp] = uc;
+               } else { 
+                  /* general case */
+                  lno = nn / MTFL_SIZE;
+                  off = nn % MTFL_SIZE;
+                  pp = s->mtfbase[lno] + off;
+                  uc = s->mtfa[pp];
+                  while (pp > s->mtfbase[lno]) { 
+                     s->mtfa[pp] = s->mtfa[pp-1]; pp--; 
+                  };
+                  s->mtfbase[lno]++;
+                  while (lno > 0) {
+                     s->mtfbase[lno]--;
+                     s->mtfa[s->mtfbase[lno]] 
+                        = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
+                     lno--;
+                  }
+                  s->mtfbase[0]--;
+                  s->mtfa[s->mtfbase[0]] = uc;
+                  if (s->mtfbase[0] == 0) {
+                     kk = MTFA_SIZE-1;
+                     for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
+                        for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+                           s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
+                           kk--;
+                        }
+                        s->mtfbase[ii] = kk + 1;
+                     }
+                  }
+               }
+            }
+            /*-- end uc = MTF ( nextSym-1 ) --*/
+
+            s->unzftab[s->seqToUnseq[uc]]++;
+            if (0 && s->smallDecompress)
+               s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
+               s->tt[nblock]   = (UInt32)(s->seqToUnseq[uc]);
+            nblock++;
+
+            GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
+            continue;
+         }
+      }
+
+      /* Now we know what nblock is, we can do a better sanity
+         check on s->origPtr.
+      */
+      if (s->origPtr < 0 || s->origPtr >= nblock)
+         RETURN(BZ_DATA_ERROR);
+
+      s->state_out_len = 0;
+      s->state_out_ch  = 0;
+      BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
+      s->state = BZ_X_OUTPUT;
+    //  if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
+
+      /*-- Set up cftab to facilitate generation of T^(-1) --*/
+      s->cftab[0] = 0;
+      for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
+      for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
+
+      if (0 && s->smallDecompress) {
+
+         /*-- Make a copy of cftab, used in generation of T --*/
+         for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
+
+         /*-- compute the T vector --*/
+         for (i = 0; i < nblock; i++) {
+            uc = (UChar)(s->ll16[i]);
+            SET_LL(i, s->cftabCopy[uc]);
+            s->cftabCopy[uc]++;
+         }
+
+         /*-- Compute T^(-1) by pointer reversal on T --*/
+         i = s->origPtr;
+         j = GET_LL(i);
+         do {
+            Int32 tmp = GET_LL(j);
+            SET_LL(j, i);
+            i = j;
+            j = tmp;
+         }
+            while (i != s->origPtr);
+
+         s->tPos = s->origPtr;
+         s->nblock_used = 0;
+         if (s->blockRandomised) {
+            BZ_RAND_INIT_MASK;
+            BZ_GET_SMALL(s->k0); s->nblock_used++;
+            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
+         } else {
+            BZ_GET_SMALL(s->k0); s->nblock_used++;
+         }
+
+      } else {
+
+         /*-- compute the T^(-1) vector --*/
+         for (i = 0; i < nblock; i++) {
+            uc = (UChar)(s->tt[i] & 0xff);
+            s->tt[s->cftab[uc]] |= (i << 8);
+            s->cftab[uc]++;
+         }
+
+         s->tPos = s->tt[s->origPtr] >> 8;
+         s->nblock_used = 0;
+         if (s->blockRandomised) {
+            BZ_RAND_INIT_MASK;
+            BZ_GET_FAST(s->k0); s->nblock_used++;
+            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
+         } else {
+            BZ_GET_FAST(s->k0); s->nblock_used++;
+         }
+
+      }
+
+      RETURN(BZ_OK);
+
+
+
+    endhdr_2:
+
+      GET_UCHAR(BZ_X_ENDHDR_2, uc);
+      if (uc != 0x72) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_3, uc);
+      if (uc != 0x45) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_4, uc);
+      if (uc != 0x38) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_5, uc);
+      if (uc != 0x50) RETURN(BZ_DATA_ERROR);
+      GET_UCHAR(BZ_X_ENDHDR_6, uc);
+      if (uc != 0x90) RETURN(BZ_DATA_ERROR);
+
+      s->storedCombinedCRC = 0;
+      GET_UCHAR(BZ_X_CCRC_1, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_2, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_3, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+      GET_UCHAR(BZ_X_CCRC_4, uc);
+      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+
+      s->state = BZ_X_IDLE;
+      RETURN(BZ_STREAM_END);
+
+      default: AssertH ( False, 4001 );
+   }
+
+   AssertH ( False, 4002 );
+
+   save_state_and_return:
+
+   s->save_i           = i;
+   s->save_j           = j;
+   s->save_t           = t;
+   s->save_alphaSize   = alphaSize;
+   s->save_nGroups     = nGroups;
+   s->save_nSelectors  = nSelectors;
+   s->save_EOB         = EOB;
+   s->save_groupNo     = groupNo;
+   s->save_groupPos    = groupPos;
+   s->save_nextSym     = nextSym;
+   s->save_nblockMAX   = nblockMAX;
+   s->save_nblock      = nblock;
+   s->save_es          = es;
+   s->save_N           = N;
+   s->save_curr        = curr;
+   s->save_zt          = zt;
+   s->save_zn          = zn;
+   s->save_zvec        = zvec;
+   s->save_zj          = zj;
+   s->save_gSel        = gSel;
+   s->save_gMinlen     = gMinlen;
+   s->save_gLimit      = gLimit;
+   s->save_gBase       = gBase;
+   s->save_gPerm       = gPerm;
+
+   return retVal;   
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end                                      decompress.c ---*/
+/*-------------------------------------------------------------*/
diff --git a/sys/lib/dist.old/cmd/cdsh.c b/sys/lib/dist.old/cmd/cdsh.c
new file mode 100644 (file)
index 0000000..2162350
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * The `cd' shell.  
+ * Just has cd and lc.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+char *pwd;
+char *root = "/";
+
+void
+usage(void)
+{
+       fprint(2, "usage: cdsh [-r root]\n");
+       exits("usage");
+}
+
+int
+system(char *cmd)
+{
+       int pid;
+       if((pid = fork()) < 0)
+               return -1;
+
+       if(pid == 0) {
+               dup(2, 1);
+               execl("/bin/rc", "rc", "-c", cmd, nil);
+               exits("exec");
+       }
+       waitpid();
+       return 0;
+}
+
+int
+cd(char *s)
+{
+       char *newpwd;
+       int l;
+
+       if(s[0] == '/') {
+               cleanname(s);
+               newpwd = strdup(s);
+       } else {
+               l = strlen(pwd)+1+strlen(s)+1+50;       /* 50 = crud for unicode mistakes */
+               newpwd = malloc(l);
+               snprint(newpwd, l, "%s/%s", pwd, s);
+               cleanname(newpwd);
+               assert(newpwd[0] == '/');
+       }
+
+       if(chdir(root) < 0 || (newpwd[1] != '\0' && chdir(newpwd+1) < 0)) {
+               chdir(root);
+               chdir(pwd+1);
+               free(newpwd);
+               return -1;
+       } else {
+               free(pwd);
+               pwd = newpwd;
+               return 0;
+       }
+}
+
+void
+main(int argc, char **argv)
+{
+       char *p;
+       Biobuf bin;
+       char *f[2];
+       int nf;
+
+       ARGBEGIN{
+       case 'r':
+               root = ARGF();
+               if(root == nil)
+                       usage();
+               if(root[0] != '/') {
+                       fprint(2, "root must be rooted\n");
+                       exits("root");
+               }
+               break;
+       default:
+               usage();
+       }ARGEND;
+
+       if(argc != 0)
+               usage();
+
+       cleanname(root);
+       if(cd("/") < 0) {
+               fprint(2, "cannot cd %s: %r\n", root);
+               exits("root");
+       }
+
+       Binit(&bin, 0, OREAD);
+       while(fprint(2, "%s%% ", pwd), (p = Brdline(&bin, '\n'))) {
+               p[Blinelen(&bin)-1] = '\0';
+               nf = tokenize(p, f, nelem(f));
+               if(nf < 1)
+                       continue;
+               if(strcmp(f[0], "exit") == 0)
+                       break;
+               if(strcmp(f[0], "lc") == 0) {
+                       if(nf == 1) {
+                               if(system("/bin/lc") < 0)
+                                       fprint(2, "lc: %r\n");
+                       } else if(nf == 2) {
+                               if(strpbrk(p, "'`{}^@$#&()|\\;><"))
+                                       fprint(2, "no shell characters allowed\n");
+                               else {
+                                       p = f[1];
+                                       *--p = ' ';
+                                       *--p = 'c';
+                                       *--p = 'l';
+                                       if(system(p) < 0)
+                                               fprint(2, "lc: %r\n");
+                               }
+                       }
+                       continue;
+               }
+               if(strcmp(f[0], "cd") == 0) {
+                       if(nf < 2)
+                               fprint(2, "usage: cd dir\n");
+                       else if(cd(f[1]) < 0)
+                               fprint(2, "cd: %r\n");
+                       continue;
+               }
+               fprint(2, "commands are cd, lc, and exit\n");
+       }
+
+       print("%s\n", pwd);
+}
diff --git a/sys/lib/dist.old/cmd/clog.c b/sys/lib/dist.old/cmd/clog.c
new file mode 100644 (file)
index 0000000..98d1cf5
--- /dev/null
@@ -0,0 +1,59 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+char *argv0;
+
+int
+openlog(char *name)
+{
+       int fd;
+
+       fd = open(name, OWRITE);
+       if(fd < 0){
+               fprint(2, "%s: can't open %s: %r\n", argv0, name);
+               return -1;
+       }
+       seek(fd, 0, 2);
+       return fd;
+}
+
+void
+main(int argc, char **argv)
+{
+       Biobuf in;
+       int fd;
+       char *p, *t;
+       char buf[8192];
+
+       argv0 = argv[0];
+       if(argc != 4){
+               fprint(2, "usage: %s console logfile prefix\n", argv0);
+               exits("usage");
+       }
+
+       fd = open(argv[1], OREAD);
+       if(fd < 0){
+               fprint(2, "%s: can't open %s: %r\n", argv0, argv[1]);
+               exits("open");
+       }
+       Binit(&in, fd, OREAD);
+
+       fd = openlog(argv[2]);
+
+       for(;;){
+               if(p = Brdline(&in, '\n')){
+                       p[Blinelen(&in)-1] = 0;
+                       if(fprint(fd, "%s: %s\n", argv[3], p) < 0){
+                               close(fd);
+                               fd = openlog(argv[2]);
+                               fprint(fd, "%s: %s\n", t, p);
+                       }
+               } else if(Blinelen(&in) == 0)   // true eof
+                       break;
+               else {
+                       Bread(&in, buf, sizeof buf);
+               }
+       }
+       exits(0);
+}
diff --git a/sys/lib/dist.old/cmd/mkfile b/sys/lib/dist.old/cmd/mkfile
new file mode 100644 (file)
index 0000000..bbcd135
--- /dev/null
@@ -0,0 +1,24 @@
+</$objtype/mkfile
+CPUS=386
+
+TARG=\
+       bargraph\
+       bflz\
+       cdsh\
+       tailfsrv\
+       touchfs\
+       unbflz\
+
+OFILES=
+HFILES=
+
+BIN=/sys/lib/dist/bin/$objtype
+</sys/src/cmd/mkmany
+
+all:V: bzfs!all
+install:V:     bzfs!install
+clean:V:       bzfs!clean
+
+bzfs!%:V:
+       cd bzfs; mk $stem; cd ..
+
diff --git a/sys/lib/dist.old/cmd/multi/mkfile b/sys/lib/dist.old/cmd/multi/mkfile
new file mode 100644 (file)
index 0000000..a3acc36
--- /dev/null
@@ -0,0 +1,76 @@
+objtype=386
+</$objtype/mkfile
+
+TARG=multi
+
+PIECES=\
+       aux/mouse\
+       aux/pcmcia\
+       aux/vga\
+       aux/zerotrunc\
+       disk/fdisk\
+       disk/format\
+       disk/mbr\
+       disk/prep\
+#      fossil/fossil\
+#      fossil/flfmt\
+       ip/ipconfig\
+       ip/ppp\
+       ndb/cs\
+       ndb/dns\
+#      replica/applylog\
+       9660srv\
+#      awk\
+       basename\
+       cat\
+       chgrp\
+       chmod\
+       cleanname\
+       cmp\
+       cp\
+       date\
+       dd\
+       dossrv\
+       echo\
+       ed\
+       ext2srv\
+#      fcp\
+       grep\
+       hget\
+       hoc\
+       ls\
+       mc\
+       mount\
+       mv\
+       ps\
+       read\
+#      rio\
+       rm\
+       sed\
+       sort\
+       srv\
+#      stats\
+       syscall\
+       tail\
+       tee\
+       test\
+       wc\
+       xd\
+
+8.multi:V: mkmulti mkfile
+       mkmulti $PIECES 
+       ls -l 8.multi
+       ls -l /386/bin/$PIECES | awk '{s += $6} END{print s}'
+
+scripts:V:
+       rm -rf ../../pc/multi
+       mkdir ../../pc/multi
+       for(i in $PIECES){
+               b=`{basename $i}
+               echo '#!/bin/multi' >>../../pc/multi/$b
+               chmod +x ../../pc/multi/$b
+       }
+
+BIN=/sys/lib/dist/bin/$objtype
+</sys/src/cmd/mkmany
+
diff --git a/sys/lib/dist.old/cmd/multi/mkmulti b/sys/lib/dist.old/cmd/multi/mkmulti
new file mode 100644 (file)
index 0000000..2317e51
--- /dev/null
@@ -0,0 +1,70 @@
+#!/bin/rc
+
+targ=multi
+
+n=0
+dir=`{pwd}
+
+fn grab {
+       echo using $*
+       for(i){
+               n=`{echo 1+$n|hoc}
+               mv $i $dir/a.$n.8
+       }
+}
+
+fn getfiles {
+       sed -n 's/^(pcc|8\^l|8l) +(-o [^ ]* +)?([^\-].*)/ \3/p' | sed 's/ -[^ ]*//g' |
+               sed 's/ [^ ]*\.a//g'
+}
+
+rm a.*.8
+>multi.h
+>multiproto.h
+
+for(i){
+echo $i...
+       b=`{basename $i}
+       p=$b
+       if(~ $b [0-9]*)
+               p=_$b
+       echo void $p^_main'(int, char**);' >>$dir/multiproto.h
+       echo "$b", $p^_main, >>$dir/multi.h
+       d=`{basename -d $i}
+       if(~ $i disk/prep disk/fdisk){
+               cd /sys/src/cmd/disk/prep
+               rm 8.$b
+               files=`{mk 8.$b | getfiles}
+       }
+       if not if(test -d /sys/src/cmd/$i && @{cd /sys/src/cmd/$i && mk 8.out}){
+               cd /sys/src/cmd/$i
+               rm 8.out
+               files=`{mk 8.out | getfiles}
+       }
+       if not if(test -d /sys/src/cmd/$i && @{cd /sys/src/cmd/$i && mk 8.$b}){
+               cd /sys/src/cmd/$i
+               rm 8.out
+               files=`{mk 8.$b | getfiles}
+       }
+       if not if(test -d /sys/src/cmd/$d && @{cd /sys/src/cmd/$d && mk 8.$b}){
+               cd /sys/src/cmd/$d
+               rm 8.$b
+               files=`{mk 8.$b | getfiles}
+       }
+       if not{
+               echo do not know how to make $i
+               exit oops
+       }
+       aux/8prefix $p^_ $files
+       grab $files
+       switch(`{pwd}){
+       case /sys/src/cmd /sys/src/cmd/aux /sys/src/cmd/ip
+               rm 8.$b
+       case *
+               mk clean
+       }
+}
+cd $dir
+8c -FVw multi.c
+8l -o 8.$targ multi.8 a.*.8
+# rm a.*.8
diff --git a/sys/lib/dist.old/cmd/multi/multi.c b/sys/lib/dist.old/cmd/multi/multi.c
new file mode 100644 (file)
index 0000000..a2e3035
--- /dev/null
@@ -0,0 +1,38 @@
+#include <u.h>
+#include <libc.h>
+
+#include "multiproto.h"
+struct {
+       char *name; 
+       void (*fn)(int, char**);
+} mains[] =
+{
+#include "multi.h"
+};
+
+void
+main(int argc, char **argv)
+{
+       int i;
+       char *cmd, *p;
+       
+       if(argc == 1){
+               fprint(2, "usage: multi cmd args...\n");
+               exits("usage");
+       }
+       
+       cmd = argv[1];
+       if(p = strrchr(cmd, '/'))
+               cmd = p+1;
+       argv++;
+       argc--;
+
+       for(i=0; i<nelem(mains); i++){
+               if(strcmp(cmd, mains[i].name) == 0){
+                       mains[i].fn(argc, argv);
+                       return;
+               }
+       }
+       fprint(2, "multi: no such cmd %s\n", cmd);
+       exits("no cmd");
+}
diff --git a/sys/lib/dist.old/cmd/tailfsrv.c b/sys/lib/dist.old/cmd/tailfsrv.c
new file mode 100644 (file)
index 0000000..fc41f42
--- /dev/null
@@ -0,0 +1,17 @@
+#include <u.h>
+#include <libc.h>
+
+void
+main(void)
+{
+       int fd, p[2];
+       char buf[8192], n;
+
+       pipe(p);
+       fd = create("/srv/log", OWRITE, 0666);
+       fprint(fd, "%d", p[0]);
+       close(fd);
+       close(p[0]);
+       while((n = read(p[1], buf, sizeof buf)) >= 0)
+               write(1, buf, n);
+}
diff --git a/sys/lib/dist.old/cmd/touchfs.c b/sys/lib/dist.old/cmd/touchfs.c
new file mode 100644 (file)
index 0000000..00fadf3
--- /dev/null
@@ -0,0 +1,66 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+void
+Bpass(Biobuf *bin, Biobuf *bout, int n)
+{
+       char buf[8192];
+       int m;
+
+       while(n > 0) {
+               m = sizeof buf;
+               if(m > n)
+                       m = n;
+               m = Bread(bin, buf, m);
+               if(m <= 0) {
+                       fprint(2, "corrupt archive\n");
+                       exits("notdone");
+               }
+               Bwrite(bout, buf, m);
+               n -= m;
+       }
+       assert(n == 0);
+}
+
+void
+main(int argc, char **argv)
+{
+       char *p, *f[10];
+       Biobuf bin, bout;
+       int nf;
+       ulong d, size;
+
+       if(argc != 2) {
+               fprint(2, "usage: cat mkfs-archive | touchfs date (in seconds)\n");
+               exits("usage");
+       }
+
+       d = strtoul(argv[1], 0, 0);
+
+       quotefmtinstall();
+       Binit(&bin, 0, OREAD);
+       Binit(&bout, 1, OWRITE);
+
+       while(p = Brdline(&bin, '\n')) {
+               p[Blinelen(&bin)-1] = '\0';
+               if(strcmp(p, "end of archive") == 0) {
+                       Bprint(&bout, "end of archive\n");
+                       exits(0);
+               }
+
+               nf = tokenize(p, f, nelem(f));
+               if(nf != 6) {
+                       fprint(2, "corrupt archive\n");
+                       exits("notdone");
+               }
+
+               Bprint(&bout, "%q %q %q %q %lud %q\n",
+                       f[0], f[1], f[2], f[3], d, f[5]);
+
+               size = strtoul(f[5], 0, 0);
+               Bpass(&bin, &bout, size);
+       }
+       fprint(2, "premature end of archive\n");
+       exits("notdone");
+}
diff --git a/sys/lib/dist.old/cmd/unbflz.c b/sys/lib/dist.old/cmd/unbflz.c
new file mode 100644 (file)
index 0000000..5ddb821
--- /dev/null
@@ -0,0 +1,109 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+void
+usage(void)
+{
+       fprint(2, "usage: unbflz [file]\n");
+       exits("usage");
+}
+
+int
+Bgetint(Biobuf *b)
+{
+       uchar p[4];
+
+       if(Bread(b, p, 4) != 4)
+               sysfatal("short read");
+       return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+}
+
+/*
+ * memmove but make sure overlap works properly.
+ */
+void
+copy(uchar *dst, uchar *src, int n)
+{
+       while(n-- > 0)
+               *dst++ = *src++;
+}
+
+void
+main(int argc, char **argv)
+{
+       Biobuf *b, bin;
+       char buf[5];
+       uchar *data;
+       ulong *blk, l;
+       int nblk, mblk;
+       int sum;
+       int i, j, length, m, n, o;
+
+       ARGBEGIN{
+       default:
+               usage();
+       }ARGEND
+
+       switch(argc){
+       default:
+               usage();
+       case 0:
+               Binit(&bin, 0, OREAD);
+               b = &bin;
+               break;
+       case 1:
+               if((b = Bopen(argv[0], OREAD)) == nil)
+                       sysfatal("open %s: %r", argv[0]);
+               break;
+       }
+
+       if(Bread(b, buf, 4) != 4)
+               sysfatal("short read");
+
+       if(memcmp(buf, "BLZ\n", 4) != 0)
+               sysfatal("bad header");
+
+       length = Bgetint(b);
+       data = malloc(length);
+       if(data == nil)
+               sysfatal("out of memory");
+       sum = 0;
+       nblk = 0;
+       mblk = 0;
+       blk = nil;
+       while(sum < length){
+               if(nblk>=mblk){
+                       mblk += 16384;
+                       blk = realloc(blk, (mblk+1)*sizeof(blk[0]));
+                       if(blk == nil)
+                               sysfatal("out of memory");
+               }
+               l = Bgetint(b);
+               blk[nblk++] = l;
+               if(l&(1<<31))
+                       l &= ~(1<<31);
+               else
+                       blk[nblk++] = Bgetint(b);
+               sum += l;
+       }
+       if(sum != length)
+               sysfatal("bad compressed data %d %d", sum, length);
+       i = 0;
+       j = 0;
+       while(i < length){
+               assert(j < nblk);
+               n = blk[j++];
+               if(n&(1<<31)){
+                       n &= ~(1<<31);
+                       if((m=Bread(b, data+i, n)) != n)
+                               sysfatal("short read %d %d", n, m);
+               }else{
+                       o = blk[j++];
+                       copy(data+i, data+o, n);
+               }
+               i += n;
+       }
+       write(1, data, length);
+       exits(nil);
+}
diff --git a/sys/lib/dist.old/logcompress.awk b/sys/lib/dist.old/logcompress.awk
new file mode 100755 (executable)
index 0000000..3267a48
--- /dev/null
@@ -0,0 +1,15 @@
+{
+       verb[$4] = $3
+       data[$4] = sprintf("%s %s %s %s %s %s", $5, $6, $7, $8, $9, $10)
+}
+
+END{
+       for(i in verb)
+               if(verb[i] != "d")
+                       printf("a %s %s\n", i, data[i]) |"sort +1"
+       close("sort +1")
+       for(i in verb)
+               if(verb[i] == "d")
+                       printf("d %s %s\n", i, data[i]) |"sort -r +1"
+       close("sort -r +1")
+}
diff --git a/sys/lib/dist.old/logtime.awk b/sys/lib/dist.old/logtime.awk
new file mode 100755 (executable)
index 0000000..f974f8d
--- /dev/null
@@ -0,0 +1,3 @@
+{
+       printf("%s %d %s\n", t, NR, $0);
+}
diff --git a/sys/lib/dist.old/mkfile b/sys/lib/dist.old/mkfile
new file mode 100644 (file)
index 0000000..f9739e4
--- /dev/null
@@ -0,0 +1,221 @@
+# /sys/lib/dist/mkfile
+src9=/n/sources/plan9          # what to export
+dist=/sys/lib/dist.old         # where this machinery lives
+scr=/n/other/dist              # scratch space before copying to web.protect
+# import /sys/lib/dist/web.protect from the outside
+x=`{setup}
+
+cd:V: $scr/plan9.iso
+
+ncd:V: $scr/plan9-new.iso.bz2
+
+ncd-dist:V: $scr/plan9-new.iso.bz2
+       mk $dist/web.protect/plan9-new.iso.bz2
+
+cd-dist:V: $scr/plan9.iso.bz2
+       mk $dist/web.protect/plan9.iso.bz2
+
+contrib-cd:V: $scr/contrib.iso.bz2
+       mk $dist/web.protect/contrib.iso.bz2
+
+$scr/%.iso:D: $src9/dist/replica/plan9.log
+       @ { cd pc; mk cddisk }
+       rm -f $target
+       bind pc/cddisk cdstub/bootdisk.img
+       if(! test -f $src9/bootdisk.img)
+               bind -a cdstub $src9
+       title=`{date | sed 's/(...) (...) (..) (..:..):.. (...) (....)/Plan 9 - \2 \3 \6 \4/'}
+       title=$"title
+       echo 'CD:' $title
+       disk/mk9660 -9cj -v $title -s $src9 -b bootdisk.img $target
+
+# copy compressed file from scratch space to the distribution, carefully
+$dist/web.protect/%.iso.bz2:   $scr/%.iso.bz2
+       >>$target.new
+       chmod +t $target.new            # waste write buf, not venti store
+       cp $prereq $target.new
+       # replace previous version with a flash cut
+       if (test -e $target)
+               mv $target $target.old # try to not clobber downloads in progress
+       mv $target.new $target
+
+cd-cleanup:V:
+       rm -f $dist/web.protect/*.iso.bz2.old # remove old versions after a delay
+
+# generate replica log & db for $src9 only
+scan:V:
+       test -d $scr            # make sure other was mounted above
+       test -d $src9
+       test -d $dist/web.protect
+       lock scan.lock replica/scan $dist/sources.replica
+       chmod +t $src9/dist/replica/*.^(db log)
+
+# generate replica log & db for all of /n/sources
+scanall:V:
+       @ {
+               rfork ne
+               d=/n/sources
+               test -d $src9
+               lock scanall.lock replica/scan $dist/sourcesall.replica
+               chmod +t $src9/dist/replica/*.^(db log)
+       }
+
+compresslog:V:
+       {
+       awk -f logcompress.awk $src9/dist/replica/plan9.log |
+               awk -f logtime.awk -v 't='^`{date -n} >/tmp/plan9.log
+       rm -f $src9/dist/replica/plan9.new.log
+       cp /tmp/plan9.log $src9/dist/replica/plan9.new.log &&
+               mv $src9/dist/replica/plan9.new.log $src9/dist/replica/plan9.log
+       } <scan.lock
+
+#restart:V:
+#      rm -f $src9/dist/replica/plan9.db
+#      rm -f $src9/dist/replica/plan9.log
+#      chmod 664 $src9/dist/replica/plan9.db >$src9/dist/replica/plan9.db
+#      chmod 664 $src9/dist/replica/plan9.log >$src9/dist/replica/plan9.log
+#      chmod +a $src9/dist/replica/plan9.log
+#      mk scan
+
+odump:V:
+       disk/dump9660 -9cj -v 'Plan 9 4e Dumps' -s $src9 \
+               -p /sys/lib/sysconfig/proto/allproto $scr/distdump.iso
+
+cd.install:V:
+#      if(~ $sysname achille){
+#              echo; echo; echo '*** run this on a real machine, like chips.'
+#              exit bad
+#      }
+       bzip2 -9 <$scr/plan9.iso >web.protect/nplan9.iso.bz2
+
+D.install:V:
+       D=/n/roro/usr/rob/testplan9
+       9fs roro
+       test -d $D
+       cp $D$dist/pc/ndisk $dist/web.protect/ndisk
+       cp $D$dist/pc/9loaddebug $dist/web.protect/n9loaddebug
+
+reallyinstall:V:
+       if(! ~ $sysname achille){
+               echo; echo; echo '*** this needs to run on achille.'
+               exit bad
+       }
+       cd web.protect
+       for (i in plan9.iso.bz2 disk 9loaddebug vmware.zip)
+               if(test -f n$i){
+                       mv $i _$i && { mv n$i $i || mv _$i $i }
+               }
+       rm /srv/ramfs.9down4e
+       $dist/startcache
+
+dump:V:
+       rm -f /srv/9660.xxx
+       9660srv 9660.xxx
+       mount /srv/9660.xxx /n/kremvax $scr/plan9.iso
+       now=`{mtime $dist/web.protect/plan9.iso.bz2 | awk '{print $1}'}
+       ls -l /rls/plan9/4e.iso
+       disk/dump9660 -9cj -s /n/kremvax -n $now /rls/plan9/4e.iso
+       ls -l /rls/plan9/4e.iso
+       rm /srv/9660.xxx
+
+reencode:V:
+       rm -f $scr/nplan9.iso
+       rm -f /srv/9660.xxx
+       9660srv 9660.xxx
+       mount /srv/9660.xxx /n/kremvax $scr/plan9.iso
+       disk/mk9660 -9cj -v 'Plan 9 4th Edition' -s /n/kremvax \
+               -b bootdisk.img $scr/nplan9.iso
+       rm /srv/9660.xxx
+
+# compress a cd image in scratch space
+$scr/%.iso.bz2:D: $scr/%.iso
+       @ {
+               cd $scr
+               bzip2 -9 <$stem.iso >n$stem.iso.bz2 &&
+               {
+                       if (test -e $stem.iso.bz2)
+                               mv  $stem.iso.bz2 _$stem.iso.bz2
+                       mv n$stem.iso.bz2 $stem.iso.bz2
+               }
+               echo `{date} md5 `{md5sum <$stem.iso.bz2} \
+                       sha1 `{sha1sum <$stem.iso.bz2} \
+                       $stem.iso.bz2 >>/usr/web/plan9checksums.txt
+       }
+
+$scr/contrib.iso:DV:
+       rm -f $target
+       disk/mk9660 -9cj -v 'Plan 9 Extras' -s /n/sources \
+               -p ./contrib.proto $target
+
+rebuild:V:
+       chmod +l build.lock >>build.lock
+       rebuild <build.lock
+
+rebuild-mail:V:
+       chmod +l build.lock >>build.lock
+       rebuild <build.lock
+       datemail 'nightly build errors' 9trouble <buildit.out
+       datemail 'nightly build differences' 9trouble <checkbuild.out
+       status=''
+
+scansources-mail:V:
+       scansources | datemail 'nightly fs vs. sources scan' 9trouble
+
+worldwritable-mail:V:
+       test -e $src9
+       @ {cd /n/sources; /usr/rsc/bin/$cputype/lsr -t -d} |
+               awk '$2 ~ /[2367]$/' | grep -vf ok-writable |
+               datemail 'WRITABLE FILES ON SOURCES' 9trouble || status=''
+       status=''
+       @ {
+               cd $src9
+               /usr/rsc/bin/$cputype/lsr -t -d $src9
+       } |
+               awk '$2 ~ /[2367][^2367].$/' |
+               datemail 'non-group-writable files on sources' 9trouble
+       status=''
+       # use /n/boot to avoid walking the archives mounted under
+       # /lib/vac, or other mounts or binds.
+       rfork n
+       9fs boot
+       test -e /n/boot/sys
+       /usr/rsc/bin/$cputype/lsr -t -d /n/boot/sys /n/boot/lib |
+               grep -v '/lib/audio/|/sys/src/cmd/vac/test/' | # give us a break
+               awk '$2 ~ /[2367][^2367].$/' |
+               datemail 'non-group-writable files on fs' 9trouble
+       status=''
+
+9.tar.gz:V:
+       @{
+               rfork n
+               9fs sources
+               test -e $src9
+               bind -a $src9 $src9/sys/src
+               cd $src9/sys/src
+               tar c LICENSE NOTICE 9
+       } | gzip >$target
+
+9-export:V: 9.tar.gz
+       9fs sources
+       cp 9.tar.gz /n/sources/extra/9.tgz
+       chmod +t    /n/sources/extra/9.tgz
+
+plan9.tar.bz2:V:
+       @{
+               rfork n
+               9fs sources
+               cd /n/sources
+               test -e $src9
+               bind /n/empty $src9/lib/font
+               bind /n/empty $src9/sys/lib/postscript/font
+               bind /n/empty $src9/sys/lib/ghostscript
+               bind /n/empty $src9/sys/src/cmd/gs
+               tar c plan9/LICENSE* plan9/NOTICE plan9/*/mkfile plan9/*/include \
+                       plan9/acme/*/src plan9/acme/bin/source \
+                       plan9/^(adm cron lib lp mail rc sys tmp usr)
+       } | bzip2 >$target
+
+plan9-export:V: plan9.tar.bz2
+       9fs sources
+       chmod +t plan9.tar.bz2
+       mv plan9.tar.bz2 /n/sources/extra/plan9.tar.bz2
diff --git a/sys/lib/dist.old/pc/cd0.proto b/sys/lib/dist.old/pc/cd0.proto
new file mode 100644 (file)
index 0000000..62bdb1b
--- /dev/null
@@ -0,0 +1 @@
+cddisk
diff --git a/sys/lib/dist.old/pc/emptyfile b/sys/lib/dist.old/pc/emptyfile
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/sys/lib/dist.old/pc/glenda/bin/rc/riostart b/sys/lib/dist.old/pc/glenda/bin/rc/riostart
new file mode 100755 (executable)
index 0000000..cc5dfa8
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/rc
+
+window '0 0 100 100' games/clock
+window '80 80 610 360' /usr/glenda/lib/first.window
diff --git a/sys/lib/dist.old/pc/glenda/lib/first.window b/sys/lib/dist.old/pc/glenda/lib/first.window
new file mode 100644 (file)
index 0000000..c4f264e
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/rc
+echo -n readme > /dev/label
+echo 'You have completed the Installation Process.'
+
+cat<<'!'
+
+Welcome to Plan 9.
+This is rc.
+!
+
+exec rc
diff --git a/sys/lib/dist.old/pc/glenda/lib/profile b/sys/lib/dist.old/pc/glenda/lib/profile
new file mode 100644 (file)
index 0000000..7767e8a
--- /dev/null
@@ -0,0 +1,16 @@
+if(test -f '#m/mousectl') {
+       echo -n accelerated > '#m/mousectl'
+       echo -n 'res 3' > '#m/mousectl'
+}
+user=`{cat /dev/user}
+home=/usr/$user
+bind -a $home/bin/rc /bin
+bind -a $home/bin/$cputype /bin
+bind -c $home/tmp /tmp
+rio -si inst/gui
+echo 
+echo
+echo 'failed to start rio.  you can start a text-based installation by running'
+echo
+echo ' inst/textonly'
+echo
diff --git a/sys/lib/dist.old/pc/inst/bootfloppy b/sys/lib/dist.old/pc/inst/bootfloppy
new file mode 100755 (executable)
index 0000000..c9aebbc
--- /dev/null
@@ -0,0 +1,47 @@
+#!/bin/rc
+
+rfork e
+
+echo
+echo 'Insert a disk other than your installation boot disk'
+echo 'into your floppy drive; it will be erased to create'
+echo 'the boot floppy.'
+echo
+echo -n 'Press enter when ready.'
+read >/dev/null >[2]/dev/null
+
+if(~ $#adisk 1)
+       ;       # do nothing
+if not if(~ $#bootfile 0)
+       adisk=/dev/fd0disk
+if not {
+       switch($bootfile) {
+       case sd*
+               adisk=`{echo $bootfile | sed 's#(sd..).*#/dev/\1/data#'}
+       case fd*
+               adisk=`{echo $bootfile | sed 's#(fd.).*#/dev/\1disk#'}
+       case *
+               echo 'unknown bootfile '^$bootfile^'; mail 9trouble@plan9.bell-labs.com'
+               exit oops
+       }
+}
+
+if(! ~ `{ls -l $adisk | awk '{print $6}'} 1474560){
+       echo 'Will not format non-floppy disk '^$"adisk. >[1=2]
+       exit 'bad adisk'
+}
+
+log Formatting boot floppy
+if (test -e  /n/newfs/386/9loadnousb)
+       bind /n/newfs/386/9loadnousb /n/newfs/386/9load # cater to old bioses
+disk/format -b /386/pbs \
+       -fd $adisk /n/newfs/386/9load /n/newfs/386/9pcdisk.gz \
+       /tmp/plan9ini.bak
+x=$status
+
+if(~ $x ''){
+       echo 
+       echo 'Done!'
+       echo
+}
+exit $x
diff --git a/sys/lib/dist.old/pc/inst/bootplan9 b/sys/lib/dist.old/pc/inst/bootplan9
new file mode 100755 (executable)
index 0000000..942c043
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/rc
+
+first=`{ls -p '#S' | sed 1q}
+if(! ~ $first $disk) {
+       echo 'warning: The plan 9 partition is not on the boot disk,'
+       echo 'so making it the active partition will have no effect.'
+}
+
+p9offset=`{grep '^part 9fat ' /dev/$disk/ctl |awk '{print $3}'}
+if(! ~ $#p9offset 1) {
+       echo 'could not find plan 9 partition.'
+       echo 'cannot happen'
+       exit bad
+}
+
+if(test $p9offset -gt 4128695) {       # 65536 * 63 - 10
+       echo 
+       echo 'Your Plan 9 partition is more than 2GB into your disk,'
+       echo 'and the master boot records used by Windows 9x/ME'
+       echo 'cannot access it (and thus cannot boot it).'
+       echo
+       echo 'You can install the Plan 9 master boot record, which can load'
+       echo 'partitions far into the disk.'
+       echo 
+}
+
+echo 'If you use the Windows NT/2000/XP master boot record'
+echo 'or a master boot record from a Unix clone (e.g., LILO or'
+echo 'FreeBSD bootmgr), it is probably safe to continue using'
+echo 'that boot record rather than install the Plan 9 boot record.'
+echo
+prompt 'Install the Plan 9 master boot record' y n 
+switch($rd) {
+case n
+       ;
+case y
+       disk/mbr -m /386/mbr /dev/$disk/data
+}
+
+log Setting Plan 9 partition active.
+p9part=`{disk/fdisk /dev/$disk/data >[2]/dev/null </dev/null | 
+               grep PLAN9 | sed 1q | sed 's/ *(p.) .*/\1/'}
+if(~ $#p9part 0){
+       echo 'You have no Plan 9 partitions (How could this happen?)' >[1=2]
+       exit 'no plan 9 partition found'
+}
+p9part=$p9part(1)
+{ echo 'A '^$p9part; echo w } | disk/fdisk /dev/$disk/data >[2]/dev/null >/dev/null
+x=$status
+if(~ $x '' '|'){
+       echo
+       echo 'The Plan 9 partition is now marked as active.'
+       exit ''
+}
+exit $x
diff --git a/sys/lib/dist.old/pc/inst/bootsetup b/sys/lib/dist.old/pc/inst/bootsetup
new file mode 100755 (executable)
index 0000000..cc22fe6
--- /dev/null
@@ -0,0 +1,125 @@
+#!/bin/rc
+
+# desc: create a boot floppy or configure hard disk to boot plan 9
+# prereq: copydist
+
+switch($1) {
+case go
+       echo
+       echo 'Initializing Plan 9 FAT configuration partition (9fat)'
+       echo
+       
+       fat=(/dev/sd*/9fat)
+       fat=$fat(1)
+       disk=`{echo $fat | sed 's:/dev/::;s:/9fat::'}
+       bootfs=`{echo $fs | sed 's:/dev/(sd..)/(.*):\1!\2:'}
+       bootfat=`{echo $fs | sed 's:/dev/(sd..)/(.*):\1!9fat:'}
+       if(! test -f /dev/$disk/9fat) {
+               echo 'You have no 9fat partition.  Can''t setup booting.'
+               exit
+       }
+
+       if(! test -f /tmp/plan9.ini) {
+               {
+                       sfs=`{echo $fs | sed 's;/dev;#S;'}
+                       if(~ $fstype fossil fossil+venti){
+                               echo bootfile'='$bootfat!9pcf
+                               echo 'bootargs=local!'^$sfs
+                               echo 'bootdisk=local!'^$sfs
+                       }
+                       if not {
+                               echo bootfile'='$bootfs!/386/9pcdisk
+                               echo 'bootdisk=local!'^$sfs
+                       }
+                       if(~ $fstype fossil+venti){
+                               venti=`{echo $ventiarena | sed 's;/dev;#S;'}
+                               echo venti'='^$venti
+                       }
+                       # sort -u avoids dups which could otherwise trigger
+                       # pointless boot menus.
+                       grep -v '(^\[)|menuitem|adisk|bootfile|bootdisk|bootargs|nobootprompt|mouseport|vgasize|monitor|cdboot' /tmp/plan9.orig |
+                               sort -u
+                       echo 'mouseport='^$mouseport
+                       echo 'monitor='^$monitor
+                       echo 'vgasize='^$vgasize
+               } >/tmp/plan9.ini
+       }
+       if(! test -f /tmp/plan9ini.bak)
+               cp /tmp/plan9.ini /tmp/plan9ini.bak
+
+       need9fatformat=no
+       if(! isfat /dev/$disk/9fat)
+               need9fatformat=yes
+       if not if(! mount -c /srv/dos /n/9fat /dev/$disk/9fat >[2]/dev/null)
+               need9fatformat=yes
+       if not if(! test -f /n/9fat/plan9.ini)
+               need9fatformat=yes
+
+       if (test -e  /n/newfs/386/9loadnousb)
+               bind /n/newfs/386/9loadnousb /n/newfs/386/9load # cater to old bioses
+       if(~ $need9fatformat yes){
+               log Initializing Plan 9 FAT partition.
+               disk/format -r 2 -d -b /386/pbs \
+                       /dev/$disk/9fat /n/newfs/386/9load
+               # silently install pbslba if the partition is way into the disk.
+               # it''s our only hope.  only need this for >8.5GB into the disk.
+               # but...
+               # there are so few non-LBA bioses out
+               # there anymore that we'll do this even if we're only 2GB into
+               # the disk.  it's just not worth the headaches of dealing with
+               # crappy bioses that don't address the whole 8.5GB properly
+
+               9fatoffset=`{grep '^part 9fat ' /dev/$disk/ctl | awk '{print $4}'}
+               if(! ~ $#9fatoffset 1) {
+                       echo 'could not find plan 9 partition.'
+                       echo 'cannot happen'
+                       exit bad
+               }
+               if(test $9fatoffset -gt 2097152)        # 2GB
+                       disk/format -b /386/pbslba /dev/$disk/9fat
+
+               mount -c /srv/dos /n/9fat /dev/$disk/9fat
+       }
+
+       if(! test -f /n/9fat/4e){
+               logprog cp /n/newfs/386/9load /n/9fat/9load
+               logprog cp /n/newfs/386/9pcf /n/9fat/9pcf
+               if(test -f /n/9fat/plan9.ini && ! test -f /n/9fat/plan9-3e.ini)
+                       logprog mv /n/9fat/plan9.ini /n/9fat/plan9-3e.ini
+               if(test -f /n/9fat/9pcdisk && ! test -f /n/9fat/9pc3e)
+                       logprog mv /n/9fat/9pcdisk /n/9fat/9pc3e
+
+               awk -f /bin/inst/mkini.awk >/n/9fat/plan9.ini
+               >/n/9fat/4e
+       }
+
+       echo
+       echo 'There are myriad ways to boot a Plan 9 system.'
+       echo 'You can use any of the following.'
+       echo
+       echo '  floppy - create a boot floppy'
+       echo '  plan9  - make the plan 9 disk partition the default for booting'
+       echo '  win9x  - add a plan 9 option to windows 9x boot menu'
+       echo '  winnt  - add a plan 9 option to windows nt/2000/xp boot manager'
+       echo
+       echo 'If you are upgrading an extant third edition installation and booting'
+       echo 'from something other than a floppy, you needn''t run anything here.'
+       echo 'Just type ctl-d.'
+
+       oldbootsetup=$didbootsetup
+       didbootsetup=1
+       export didbootsetup
+       prompt 'Enable boot method' floppy plan9 win9x winnt
+       
+       if(! boot$rd){
+               didbootsetup=$oldbootsetup
+               export didbootsetup
+       }
+
+case checkdone
+       xxxfat=(/dev/sd*/9fat)
+       if(! isfat $xxxfat(1) || ! ~ $didbootsetup 1){
+               bootsetup=ready
+               export bootsetup
+       }
+}
diff --git a/sys/lib/dist.old/pc/inst/bootwin9x b/sys/lib/dist.old/pc/inst/bootwin9x
new file mode 100755 (executable)
index 0000000..68c2d19
--- /dev/null
@@ -0,0 +1,117 @@
+#!/bin/rc
+
+dosdisk=`{ls /dev/sd??/dos >[2]/dev/null | sed 1q | sed 's!.*/(.*)/dos!\1!'}
+if(~ $#dosdisk 0 || ! c: || ! test -f /n/c:/autoexec.bat || ! test -f /n/c:/config.sys) {
+       echo 'Could not find autoexec.bat or config.sys on the first FAT disk.'
+       exit bad
+}
+
+for (i in autoexec config msdos)
+       if(test -f /n/c:/$i.p9) {
+               echo 'A Plan 9 backup already exists; will not edit system files again.'
+               exit bad
+       }
+
+for (i in autoexec.bat config.sys msdos.sys)
+       if(! cp /n/c:/$i /n/c:/^`{echo $i | sed 's/\.(bat|sys)$/.p9/'}) {
+               echo 'Could not back up '^$i^'; will not continue.'
+               exit bad
+       }
+
+if(! test -d /n/c:/plan9 && ! mkdir /n/c:/plan9) {
+       echo 'Could not create directory /n/c:/plan9.'
+       exit bad
+}
+
+if(! cp /n/newfs/386/^(9load ld.com 9pcdisk) /tmp/plan9ini.bak /n/c:/plan9) {
+       echo 'Could not copy Plan 9 boot files into /n/c:/plan9.'
+       exit bad
+}
+
+chmod +w /n/c:/autoexec.bat /n/c:/config.sys /n/c:/msdos.sys
+
+if(grep -si 'Plan ?9' /n/c:/config.sys || grep -si 'Plan ?9' /n/c:/autoexec.bat) {
+       echo 'Plan 9 entries already in config.sys or autoexec.bat.'
+       echo 'Not changing them; refer to Plan 9 install documentation'
+       echo 'to configure manually.'
+       exit bad
+}
+
+if(! grep -si '\[menu\]' /n/c:/config.sys) {
+       {
+               echo 1
+               echo i
+               echo '[menu]\r'
+               echo 'menuitem=windows, Windows\r'
+               echo 'menudefault=windows\r'
+               echo '\r'
+               echo '[common]\r'
+               echo '\r'
+               echo '[windows]\r'
+               echo .
+               echo w
+               echo q
+       } | ed /n/c:/config.sys >/dev/null >[2]/dev/null
+}
+
+{
+       echo 1
+       echo '/\[[Mm][Ee][Nn][Uu]\]'
+       echo '?^[Mm][Ee][Nn][Uu][Ii][Tt][Ee][Mm]='
+       echo a
+       echo 'menuitem=plan9, Plan 9 from Bell Labs\r'
+       echo .
+       echo '$'
+       echo a
+       echo '\r'
+       echo '[plan9]\r'
+       echo '\r'
+       echo .
+       echo w
+       echo q
+} | ed /n/c:/config.sys >/dev/null>[2]/dev/null
+
+{
+       echo 1
+       echo i
+       echo '@echo off\r'
+       echo 'if %config%==plan9 goto plan9\r'
+       echo 'goto notplan9\r'
+       echo ':plan9\r'
+       echo 'plan9\ld '^$dosdisk^'!dos!plan9/9load\r'
+       echo ':notplan9\r'
+       echo .
+       echo w
+       echo q
+} | ed /n/c:/autoexec.bat >/dev/null>[2]/dev/null
+
+fn zeroopt {
+       if(grep -s '^'^$1^'=1' /n/c:/msdos.sys) {
+               {
+                       echo '/^'^$1^'=1/s/=1/=0/'
+                       echo w
+                       echo q
+               } | ed /n/c:/msdos.sys>/dev/null>[2]/dev/null
+       }
+       if not if (grep -s '^'^$1^'=0' /n/c:/msdos.sys)
+               ;
+       if not {
+               {
+                       echo 1
+                       echo i
+                       echo '[Options]\r'
+                       echo 'Logo=0\r'
+                       echo .
+                       echo w
+                       echo q
+               } | ed /n/c:/msdos.sys>/dev/null>[2]/dev/null
+       }
+}
+
+if(grep -si '^\[paths\]' /n/c:/msdos.sys){     # Windows 9x rather than DOS
+       zeroopt Logo
+#      zeroopt BootGUI
+}
+               
+echo 'Plan 9 added to Windows 9X boot menu.'
+exit ''
diff --git a/sys/lib/dist.old/pc/inst/bootwinnt b/sys/lib/dist.old/pc/inst/bootwinnt
new file mode 100755 (executable)
index 0000000..ee92f5d
--- /dev/null
@@ -0,0 +1,47 @@
+#!/bin/rc
+
+if(! c: || ! test -f /n/c:/boot.ini) {
+       echo 'Could not find NT''s boot.ini on the first FAT disk.'
+       exit bad
+}
+
+if(test -f /n/c:/boot.p9) {
+       echo 'A Plan 9 backup already exists; will not edit boot.ini again.'
+       exit bad
+}
+
+if(! cp /n/c:/boot.ini /n/c:/boot.p9) {
+       echo 'Could not back up boot.ini; will not continue.'
+       exit bad
+}
+
+chmod +w /n/c:/boot.ini
+
+if(! grep -si '\[operating systems\]' /n/c:/boot.ini) {
+       echo 'Could not parse boot.ini.'
+       exit bad
+}
+
+if(grep -si 'Plan 9' /n/c:/boot.ini) {
+       p9file=`{grep 'Plan 9' /n/c:/boot.ini | sed 1q | sed 's/=.*//'}
+       if(! ~ $p9file [Cc]:'\'*) {
+               echo 'Unexpected Plan 9 entry in boot.ini already; not continuing.'
+               exit bad
+       }
+}
+
+if not {
+       p9file='c:\bootsect.p9'
+       echo 'c:\bootsect.p9 = "Plan 9 from Bell Labs"\r' >>/n/c:/boot.ini
+}
+
+p9file=/n/^`{echo $p9file | sed 's!\\!/!g'}
+
+
+if(dd -if /dev/$disk/plan9 -bs 512 -count 1 -of $p9file >/dev/null >[2]/dev/null) {
+       echo 'Plan 9 added to Windows NT boot menu.'
+       exit ''
+}
+
+echo 'Error copying Plan 9 boot sector to file.'
+exit bad
diff --git a/sys/lib/dist.old/pc/inst/configarch b/sys/lib/dist.old/pc/inst/configarch
new file mode 100755 (executable)
index 0000000..61912bf
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/rc
+
+# desc: set source of distribution archives
+# prereq: mountfs
+
+switch($1) {
+case go
+       echo
+       echo 'Will you be using a distribution archive on local media or the internet?'
+       echo
+
+       prompt 'Distribution is from' local internet
+       archmedium=$rd
+       export archmedium
+
+       switch($archmedium) {
+       case local
+               exec configlocal go
+       case internet
+               exec configip go
+       }
+
+case checkdone
+       switch($#archmedium) {
+       case 1
+               switch($archmedium) {
+               case local
+                       exec configlocal checkdone
+               case internet
+                       exec configip checkdone
+               case *
+                       configarch=notdone
+                       export configarch
+               }
+       case *
+               configarch=notdone
+               export configarch
+       }
+}
+               
diff --git a/sys/lib/dist.old/pc/inst/configdist b/sys/lib/dist.old/pc/inst/configdist
new file mode 100755 (executable)
index 0000000..3e99bea
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/rc
+
+# prereq: mountfs
+# desc: choose the source of the distribution archive
+
+switch($1){
+case checkdone
+       if(! ~ $distisfrom net local){
+               configdist=ready
+               export configdist
+       }
+
+case go
+       echo 'Are you going to download the distribution'
+       echo 'from the internet or do you have it on local media?'
+       echo
+       prompt -d local 'Distribution is from' local net
+       distisfrom=$rd
+       export distisfrom
+}
+
+
diff --git a/sys/lib/dist.old/pc/inst/configether b/sys/lib/dist.old/pc/inst/configether
new file mode 100755 (executable)
index 0000000..0922ea3
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/rc
+
+# desc: configure your internet connection via an ethernet card
+
+switch($1) {
+case go
+       echo
+       echo 'Please choose a method for configuring your ethernet connection.'
+       echo
+       echo '  manual - specify IP address, network mask, gateway IP address'
+       echo '  dhcp - use DHCP to automatically configure'
+       echo
+       
+       prompt 'Configuration method' manual dhcp
+       ethermethod=$rd
+       gwaddr=xxx
+       ipaddr=xxx
+       ipmask=xxx
+       switch($ethermethod){
+       case dhcp
+               echo
+               echo 'Some ISPs, notably @HOME, require a host name passed with DHCP'
+               echo 'requests.  An example for @HOME would be "cc1018221-a".  If your'
+               echo 'ISP supplied you such a name, enter it.'
+               echo
+               prompt -d none 'host name'; dhcphost=$rd
+               switch($dhcphost){
+               case none
+                       dhcphost=();
+               case *
+                       dhcphost=(-h $dhcphost)
+               }
+               export dhcphost
+       case manual
+               prompt 'ip address'; ipaddr=$rd
+               prompt 'network mask'; ipmask=$rd
+               prompt 'gateway address'; gwaddr=$rd
+               export ipaddr ipmask gwaddr
+       }
+       
+       export ethermethod gwaddr ipaddr ipmask dhcphost
+       exec startether go
+
+case checkdone
+       if(! ~ $ethermethod manual dhcp) {
+               configether=notdone
+               export configether
+       }
+       if(~ $ethermethod manual && ~ 0 $#ipaddr $#ipmask $#gwaddr) {
+               configether=notdone
+               export configether
+       }
+}
diff --git a/sys/lib/dist.old/pc/inst/configfs b/sys/lib/dist.old/pc/inst/configfs
new file mode 100755 (executable)
index 0000000..81f8289
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/rc
+
+# desc: choose the type of file system to install
+
+switch($1){
+case checkdone
+       if(! ~ $fstype fossil fossil+venti){
+               configfs=ready
+               export configfs
+       }
+
+case go
+       echo 'You can install the following types of file systems:'
+       echo
+       echo '  fossil                  the new Plan9 fileserver'
+       echo '  fossil+venti    fossil + a archival dump server'
+       echo
+       prompt -d fossil 'File system' fossil fossil+venti
+       fstype=$rd
+       export fstype
+}
+
+
diff --git a/sys/lib/dist.old/pc/inst/configip b/sys/lib/dist.old/pc/inst/configip
new file mode 100755 (executable)
index 0000000..a7873c9
--- /dev/null
@@ -0,0 +1,64 @@
+#!/bin/rc
+
+switch($1) {
+case go
+
+       devs=''
+       if(test -d '#l/ether0' >[2]/dev/null)
+               devs=$devs^ether
+       if(test -f '#t'/eia? >[2]/dev/null)
+               devs=$devs^ppp
+       
+       switch($devs){
+       case ''
+               echo
+               echo 'Could not find ethernet card nor serial port nor modem.'
+               echo 'Please use a local copy of the distribution archive.'
+               echo
+               ifc=none
+       
+       case ppp
+               echo
+               echo 'No ethernet card was detected, but there is a serial port or modem.'
+               echo 'We will configure PPP.'
+               echo
+               ifc=ppp
+       
+       case ether
+               echo
+               echo 'No serial port or modem detected, but there is an ethernet card.'
+               echo 'We will configure the ethernet.'
+               echo
+               ifc=ether
+       
+       case etherppp
+               echo
+               echo 'You can connect to the internet via'
+               echo 'a local ethernet or a dial-up PPP connection.'
+               echo
+               prompt 'Interface to use' ether ppp
+               ifc=$rd
+       }
+       
+       ipinterface=$ifc
+       export ipinterface
+       
+       switch($ifc) {
+       case ether
+               exec configether go
+       case ppp
+               exec configppp go
+       }
+
+case checkdone
+       if(~ $#ipinterface 1)
+               switch($ipinterface) {
+               case ether
+                       exec configether checkdone
+               case ppp
+                       exec configppp checkdone
+               }
+       configarch=notdone
+       export configarch
+
+}
diff --git a/sys/lib/dist.old/pc/inst/confignet b/sys/lib/dist.old/pc/inst/confignet
new file mode 100755 (executable)
index 0000000..182ed40
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/rc
+
+# prereq: configdist
+# desc: configure the network to download the distribution
+
+switch($1){
+case checkready checkdone
+       if(! ~ $distisfrom net){
+               confignet=notdone
+               export confignet
+               exit
+       }
+       if(~ $distisfrom net && ~ $netisfrom ppp ether){
+               x=config$netisfrom
+               $x=done
+               config$netisfrom checkdone
+               confignet=$$x
+               export confignet
+               exit
+       }
+       confignet=ready
+       export confignet
+       exit
+
+case go
+       devs=''
+       if(test -d '#l/ether0' >[2]/dev/null)
+               devs=$devs^ether
+       if(test -f '#t'/eia? >[2]/dev/null)
+               devs=$devs^ppp
+       
+       switch($devs){
+       case ''
+               echo
+               echo 'Could not find ethernet card nor serial port nor modem.'
+               echo 'Please use a local copy of the distribution archive.'
+               echo
+               netisfrom=none
+       
+       case ppp
+               echo
+               echo 'No ethernet card was detected, but there is a serial port or modem.'
+               echo 'We will configure PPP.'
+               echo
+               netisfrom=ppp
+       
+       case ether
+               echo
+               echo 'No serial port or modem detected, but there is an ethernet card.'
+               echo 'We will configure the ethernet.'
+               echo
+               netisfrom=ether
+       
+       case etherppp
+               echo
+               echo 'You can connect to the internet via'
+               echo 'a local ethernet or a dial-up PPP connection.'
+               echo
+               prompt 'Interface to use' ether ppp
+               netisfrom=$rd
+       }
+       
+       export netisfrom
+       if(~ $netisfrom ether ppp)
+               exec config$netisfrom go
+}
+
diff --git a/sys/lib/dist.old/pc/inst/configppp b/sys/lib/dist.old/pc/inst/configppp
new file mode 100755 (executable)
index 0000000..6bbffc4
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/rc
+
+# desc: configure your internet connection via ppp over a modem
+
+switch($1) {
+case go
+       devs=`{ls -p '#t/'eia? >[2]/dev/null}
+       if(~ $#devs 0) {
+               echo 'No serial port found; this can''t happen.'        # because configip checks
+               exit
+       }
+       
+       # not going to use the mouse for PPP
+       if(~ eia^$mouseport $devs)
+               devs=`{echo $devs | sed 's/eia'^$mouseport^'//'}
+       
+       if(~ $#devs 0) {
+               echo 'The only serial port you have is your mouse.'
+               echo 'Cannot configure PPP.'
+               exit
+       }
+       
+       echo
+       echo 'Please choose the serial port or modem to use to connect to your ISP.'
+       echo
+       for(i in $devs) {
+               n=`{echo $i | sed 's/eia//'}
+               n=`{hoc -e 1+$n}
+               echo '  '^$i^'(Windows'' COM'^$n^')'
+       }
+       echo
+       prompt 'Serial device' $devs
+       pppdev=$rd
+       
+       echo
+       echo 'Pick a baud rate for the PPP connection.'
+       echo
+       prompt -d 115200 'Baud rate'
+       pppbaud=$rd
+       
+       echo
+       echo 'You can specify your dialup phone number, username, and password,'
+       echo 'or you can log in manually by typing the modem commands yourself.'
+       echo
+       prompt 'Dialing method' auto manual
+       pppmethod=$rd
+       
+       switch($pppmethod){
+       case auto
+               prompt 'PPP phone number'; pppphone=$rd
+               prompt 'PPP phone username'; pppuser=$rd
+               prompt 'PPP phone password'; ppppasswd=$rd
+       }
+       
+       export pppdev pppmethod pppphone ppppasswd pppuser pppbaud
+       exec startppp go
+
+case checkdone
+       if(! ~ $#pppmethod 1 || ! test -f /dev/$pppdev){
+               configppp=notdone
+               export configppp
+       }
+}
diff --git a/sys/lib/dist.old/pc/inst/copydist b/sys/lib/dist.old/pc/inst/copydist
new file mode 100755 (executable)
index 0000000..507d560
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/rc
+
+# prereq: mountdist
+# desc: copy the distribution into the file system
+
+switch($1){
+case checkready
+       if(! test -d /n/dist/dist/replica){
+               copydist=notdone
+               export copydist
+               exit
+       }
+       if(test -f /n/newfs/dist/replica/didplan9){
+               copydist=done
+               export copydist
+               exit
+       }
+case go
+       inst/watchfd applylog 0 `{ls -l /n/dist/dist/replica/plan9.log | awk '{print $6}'} 'Installing file system' &
+       replica/pull -c / /rc/bin/inst/replcfg
+       if(~ $status '' *conflicts || test -f /n/newfs/dist/replica/didplan9witherrors)
+               >/n/newfs/dist/replica/didplan9
+       if not
+               >/n/newfs/dist/replica/didplan9witherrors
+
+case checkdone
+       if(! test -f /n/newfs/dist/replica/didplan9){
+               copydist=notdone
+               export copydist
+       }
+}
diff --git a/sys/lib/dist.old/pc/inst/defs b/sys/lib/dist.old/pc/inst/defs
new file mode 100755 (executable)
index 0000000..f9c9454
--- /dev/null
@@ -0,0 +1,162 @@
+nl='
+'
+tab='  '
+if(~ $#distname 0)
+       distname=plan9
+
+wctl=/dev/null
+if(test -w /dev/wctl)
+       wctl=/dev/wctl
+
+fn log {
+       echo $* >>/srv/log
+}
+
+fn logprog {
+       echo '% '^$"* >>/srv/log
+       $* >[2=1] >>/srv/log
+}
+
+fn sigint {
+       # nothing happens
+}
+
+fn prompt {
+       def=()
+       what=()
+       if(~ $1 -d && ! ~ $#* 1){
+               def=$2
+               shift
+               shift
+       }
+
+       optstr=()
+       if(~ $1 -w && ! ~ $#* 1){
+               optstr=$2
+               shift
+               shift
+       }
+
+       pr=$1
+       shift
+
+       opts=($*)
+       if(~ $#opts 0) {
+               suf=' '
+       }
+       if not if(! ~ $#optstr 0) {
+               if(~ $optstr '') 
+                       suf=' '
+               if not {
+                       pr=$pr^' ('^$"optstr^')'
+                       suf=''
+               }
+       }
+       if not {
+               pr=$pr^' ('^$1
+               shift
+               for(i)
+                       pr=$pr^', '^$i
+               pr=$pr^')'
+               suf=''
+       }
+
+       if(~ $#def 1)
+               pr=$pr^$suf^'['^$def^']'
+       if not
+               pr=$pr^$suf^'[no default]'
+
+       pr=$pr^': '
+
+
+       okay=no
+       while(~ $okay no) {
+               echo -n current >$wctl
+               echo -n top >$wctl
+               echo -n $pr >[1=2]
+               ifs='' {rd=`{read}}
+               if(~ $#rd 0)
+                       exit notdone
+               if(~ $rd !*){
+                       ifs='' {rd=`{echo $rd | sed 's/!//'}}
+                       echo $rd
+                       rc -c $rd
+                       echo !$status
+               }
+               if not{
+                       rd=`{echo $rd}
+                       if(~ $#rd 0 || ~ $rd '')
+                               rd=$def
+       
+                       switch($#opts){
+                       case 0
+                               if(! ~ $rd '')
+                                       okay=yes
+                       case *
+                               if(~ $rd $opts)
+                                       okay=yes
+                       }
+               }
+       }
+       echo -n $rd >/env/rd    # just in case
+}
+
+fn desc {
+       echo -n '       '^$1^'  - '
+       grep '^# desc: ' $1 | sed 's/# desc: //'
+}
+
+fn prereq {
+       grep '^# prereq:' $1 | sed 's/# prereq://'
+}
+
+fn mustdo {
+       echo You must `{grep '^# mustdo:' $1 | sed 's/# mustdo://'}
+}
+
+# there's no easy way to pass shell variables
+# up from children to parents; the parents have
+# to be coerced into noticing that the environment
+# changed, even when in the same environment group.
+#
+# instead, we explicitly export the variables we want
+# to percolate, and the parent calls coherence to reread
+# the variables.
+#
+# we just append to the vars file, so that later exports
+# override earlier ones; when we call coherence, 
+# the duplicates are thrown out.
+
+fn export {
+       null=()
+       nonnull=()
+       for(i in $*){
+               if(~ $#$i 0)
+                       null=($null $i)
+               if not
+                       nonnull=($nonnull $i)
+       }
+       if(! ~ $#nonnull 0)
+               whatis $nonnull |grep -v '^\./' >>/tmp/vars >[2]/dev/null
+       for(i in $null)
+               echo $i^'=()' >>/tmp/vars
+}
+
+fn coherence {
+       if(test -f /tmp/vars) {
+               grep '^[a-z]*=' /tmp/vars >/tmp/vars2
+               v=`{sed 's/^([a-z]*)=.*/\1/' /tmp/vars2 | sort -u}
+               . /tmp/vars2
+               rm /tmp/vars2
+               rm /tmp/vars
+               export $v
+       }
+}
+
+# ip device stats
+
+fn isipdevup {
+       grep -s $1 /net/ipifc/*/status >[2]/dev/null 
+}
+
+
diff --git a/sys/lib/dist.old/pc/inst/download b/sys/lib/dist.old/pc/inst/download
new file mode 100755 (executable)
index 0000000..70d7f5b
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/rc
+
+# prereq: mountfs
+# desc: download or continue to download the distribution archives
+
+switch($1) {
+case checkready
+       devs=(`{cat /net/ipifc/*/status >[2]/dev/null |
+               grep -v '127\.0\.0\.1' |
+               sed 's/ .*//'})
+       if(~ $#devs 0) {
+               download=notdone
+               export download
+       }
+       if(~ $mountdist done){
+               download=notdone
+               export download
+       }
+
+case go
+       if(! test -f /srv/cs) {
+               log starting cs, dns
+               logprog ndb/cs >>/srv/log >[2=1]
+               logprog ndb/dns -r >>/srv/log >[2=1]
+       }
+       if(! test -f /net/cs) {
+               logprog mount -a /srv/cs /net
+               logprog mount -a /srv/dns /net
+       }
+
+       # BUG make restartable
+       echo 'Downloading distribution package...'
+       baropt='-w 145,129,445,168'
+       if(~ $textinst 1)
+               baropt=-t
+       if(! hget -vo /n/newfs/dist/_plan9.iso.bz2 $installurl/plan9.iso.bz2 |[2] bargraph $baropt 'downloading '^plan9.iso.bz2)
+                       exit
+       mv /n/newfs/dist/_plan9.iso.bz2 /n/newfs/dist/plan9.iso.bz2
+       if(~ $fstype fossil){
+               echo fsys main sync >>/srv/fscons
+       }
+
+       echo 'The distribution is downloaded.'
+
+       srvmedia=()
+       mountmedia=(mount /srv/fossil /n/distmedia)
+       distmediadir=/dist
+       export distmediadir mountmedia distmedia
+       
+case checkdone
+       if(! test -f /n/newfs/dist/plan9.iso.bz2) {
+               download=notdone
+               export download
+       }
+}
+
diff --git a/sys/lib/dist.old/pc/inst/finish b/sys/lib/dist.old/pc/inst/finish
new file mode 100755 (executable)
index 0000000..e616e64
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/rc
+
+# desc: finish the installation and reboot
+# prereq: bootsetup
+# mustdo: 
+
+switch($1) {
+case checkdone
+       finish=ready
+       export finish
+
+case go
+       if(~ $cdboot yes){
+               echo 'Congratulations; you''ve completed the install.'
+               echo
+               halt
+       }
+       stop go finished
+}
diff --git a/sys/lib/dist.old/pc/inst/fmtfossil b/sys/lib/dist.old/pc/inst/fmtfossil
new file mode 100755 (executable)
index 0000000..98bf33f
--- /dev/null
@@ -0,0 +1,91 @@
+#!/bin/rc
+
+# desc: initialize disks for a fossil server
+# prereq: configfs
+
+switch($1){
+case checkready checkdone
+       if(! ~ $fstype fossil+venti fossil){
+               fmtfossil=notdone
+               export fmtfossil
+               exit
+       }
+       ff=`{ls /dev/sd*/fossil* /dev/fs/fossil* >[2]/dev/null}
+       if(~ $#ff 0){
+               fmtfossil=notdone
+               export fmtfossil
+               exit
+       }
+       gg=()
+       for(f in $ff)
+               if(isfossil $f)
+                       gg=($gg $f)
+       if(~ $#gg 0){
+               fmtfossil=ready
+               export fmtfossil
+               exit
+       }
+       fmtfossil=done
+       export fmtfossil
+       exit
+
+case go
+       ff=`{ls /dev/sd*/fossil* /dev/fs/fossil* >[2]/dev/null}
+       if(~ $#ff 0){
+               echo 'You need to create a partition or partitions to hold the Fossil write cache.'
+               echo 'The partition name must begin with "fossil".'
+               echo
+               fmtfossil=notdone
+               export fmtfossil
+               exit
+       }
+       default=()
+       if(~ $#ff 1){
+               default=(-d $ff)
+       }
+       echo You have the following fossil partitions.
+       echo
+       prompt $default 'Fossil partition to format' $ff
+       f=$rd
+
+       do=yes
+       if(isfossil $f){
+               echo $f appears to already be formatted as Fossil file system.
+               echo Do you really want to reformat it?
+               echo
+               prompt -d no 'Reformat '$f yes no
+               do=$rd
+       }
+       if(~ $do yes){
+               fossil/flfmt -y $f
+               n=`{cat /dev/swap | grep ' user' | sed 's/^[0-9]+\/([0-9]+) .*/\1/'}
+               if(test $n -gt 32768)
+                       m=3000  # if have at least 128 user MB, use 24MB for fossil
+               if not if(test $n -gt 16384)
+                       m=1500  # 64 user MB => 12MB for fossil
+               if not if(test $n -gt 8192)
+                       m=750   # 32 user MB => 6MB for fossil
+               if not
+                       m=256   # 2MB for fossil (this will be slow)
+
+               # if we're using a venti in the back, take hourly snapshots
+               # that retire after three days, in addition to the daily dumps at 5am
+               if(~ $fstype fossil+venti){
+                       v=''
+                       snap='fsys main snaptime -s 60 -a 0500 -t 2880'
+               }
+               # otherwise, take the daily dumps but nothing else --
+               # we can't retire snapshots unless dumps are being archived
+               if not{
+                       v='-V'
+                       snap=''
+               }
+               echo \
+'fsys main config '^$f^'
+fsys main open '^$v^' -c '^$m^'
+'^$snap^'
+'              | fossil/conf -w $f
+       }
+       
+       echo Done.
+}
diff --git a/sys/lib/dist.old/pc/inst/fmtventi b/sys/lib/dist.old/pc/inst/fmtventi
new file mode 100755 (executable)
index 0000000..db79440
--- /dev/null
@@ -0,0 +1,190 @@
+#!/bin/rc
+
+# desc: initialize disks for a venti server
+# prereq: mountdist
+
+switch($1){
+case checkready checkdone
+       if(! ~ $fstype fossil+venti){
+               fmtventi=notdone
+               export fmtventi
+               exit
+       }
+       if(! test -e /bin/venti/fmtarenas || ! test -e /bin/venti/fmtisect || ! test -e /bin/venti/fmtindex){
+               bind -a /n/dist/386/bin/venti /bin/venti
+               if(! test -e /bin/venti/fmtarenas || ! test -e /bin/venti/fmtisect || ! test -e /bin/venti/fmtindex){
+                       fmtventi=notdone
+                       export fmtventi
+                       exit
+               }
+       }
+       ff=`{ls /dev/sd*/arenas* /dev/fs/arenas* >[2]/dev/null}
+       if(~ $#ff 0){
+               fmtventi=notdone
+               export fmtventi
+               exit
+       }
+       gg=()
+       for(f in $ff)
+               if(isventi $f)
+                       gg=($gg $f)
+       if(~ $#gg 0){
+               fmtventi=ready
+               export fmtventi
+               exit
+       }
+
+       ventiarena=$gg(1)
+       export ventiarena
+
+       fmtventi=done
+       export fmtventi
+       exit
+
+case go
+       ff=`{ls /dev/sd*/arenas* /dev/fs/arenas* >[2]/dev/null}
+       if(~ $#ff 0){
+               echo 'You need to create a partition or partitions to hold the Venti arenas.'
+               echo 'The arena partition names must begin with "arenas".'
+               echo
+               fmtventi=notdone
+               export fmtventi
+               exit
+       }
+       default=(-d $"ff)
+       if(! ~ $#ventiarena 0){
+               default=(-d $"ventiarena)
+       }
+       echo You have the following Venti arena partitions.
+       ls -l $ff
+       echo
+
+       prompt $default 'Venti arena partitions to use'
+       aa=`{echo $rd}
+       bad=no
+       for(a in $aa){
+               if(! ~ $a $ff){
+                       echo 'Bad venti arena partition' $a
+                       fmtventi=notdone
+                       export fmtventi
+                       exit
+               }
+       }
+       ventiarena=$aa
+       export ventiarena
+
+       gg=`{ls /dev/sd*/isect* /dev/fs/isect* >[2]/dev/null}
+       if(~ $#gg 0){
+               echo 'You need to create a partition or partitions to hold the Venti indices.'
+               echo 'The index partition names must begin with "isect".'
+               echo
+               fmtventi=notdone
+               export fmtventi
+               exit
+       }
+       default=(-d $"gg)
+       if(! ~ $#ventiindex 0){
+               default=(-d $"ventiindex)
+       }
+
+       echo You have the following Venti index partitions.
+       ls -l $gg
+       echo
+
+       prompt $default 'Venti index partitions to use'
+       aa=`{echo $rd}
+       bad=no
+       for(a in $aa){
+               if(! ~ $a $gg){
+                       echo 'Bad venti index partition' $a
+                       fmtventi=notdone
+                       export fmtventi
+                       exit
+               }
+       }
+       ventiindex=$aa
+       export ventiindex
+
+       n=-1
+       fmta=()
+       for(a in $ventiarena){
+               do=yes
+               n=`{hoc -e 1+$n}
+               if(isventiarenas $a){
+                       echo File $a is already formatted as a Venti arenas partition.
+                       prompt -d no 'Reformat '$a yes no
+                       do=$rd
+               }
+               if(~ $do yes)
+                       fmta=($fmta arenas$n:$a)
+       }
+
+       n=-1
+       fmti=()
+       for(a in $ventiindex){
+               do=yes
+               n=`{hoc -e 1+$n}
+               if(isventiisect $a){
+                       echo File $a is already formatted as a Venti index section.
+                       prompt -d no 'Reformat '$a yes no
+                       do=$rd
+               }
+               if(~ $do yes)
+                       fmti=($fmti isect$n:$a)
+       }
+
+       echo Formatting Venti arenas and indices (this takes a while).
+       # do each disk in parallel
+       echo good >/tmp/fmt
+       dd=()
+       for(a in $fmta $fmti){
+               d=`{echo $a | sed 's!.*:(/.*/).*!\1!'}
+               if(! ~ $d $dd)
+                       dd=($dd $d)
+       }
+       for(d in $dd){
+               {
+                       for(a in $fmta){
+                               i=`{echo $a | sed 's!(.*):(/.*/)(.*)!\1 \2 \2\3!'}
+                               if(~ $i(2) $d){
+                                       echo $i(3) ...
+                                       venti/fmtarenas $i(1) $i(3) || echo bad >/tmp/fmt
+                                       echo done with $i(3)
+                               }
+                       }
+                       for(a in $fmti){
+                               i=`{echo $a | sed 's!(.*):(/.*/)(.*)!\1 \2 \2\3!'}
+                               if(~ $i(2) $d){
+                                       echo $i(3) ...
+                                       venti/fmtisect $i(1) $i(3) || echo bad >/tmp/fmt
+                                       echo done with $i(3)
+                               }
+                       }
+               } &
+       }
+       wait
+       if(~ bad `{cat /tmp/fmt}){
+               echo There were errors formatting the indices and arenas.
+               fmtventi=ready
+               export fmtventi
+               exit errors
+       }
+
+       echo Done formatting Venti arenas and indices.
+
+       v=$ventiarena(1)
+       echo Storing Venti config on $v...
+       {
+               echo index main
+               for(i in $ventiindex)
+                       echo isect $i
+               for(a in $ventiarena)
+                       echo arenas $a
+       } | venti/conf -w $v
+
+       echo Initializing index...
+       venti/fmtindex $v
+
+       echo Done with Venti!
+}
+
diff --git a/sys/lib/dist.old/pc/inst/gui b/sys/lib/dist.old/pc/inst/gui
new file mode 100755 (executable)
index 0000000..afb0981
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/rc
+
+cd /bin/inst
+echo blanktime 0 >/dev/vgactl
+. defs
+
+startwin 640 480
diff --git a/sys/lib/dist.old/pc/inst/halt b/sys/lib/dist.old/pc/inst/halt
new file mode 100755 (executable)
index 0000000..4554359
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/rc
+
+echo -n 'Halting file systems...'
+
+if(ps | grep -s ' venti$')
+       venti/sync -h tcp!127.0.0.1!17034
+if(ps | grep -s ' fossil$'){
+       echo fsys all halt >>/srv/fscons
+       slay fossil|rc
+}
+
+echo done
+echo
+echo Remember to take the install disk out of the drive.
+echo Feel free to turn off your computer.
+while()
+       sleep 3600
+
diff --git a/sys/lib/dist.old/pc/inst/hasmbr b/sys/lib/dist.old/pc/inst/hasmbr
new file mode 100755 (executable)
index 0000000..1adaa0a
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/rc
+
+if(! ~ $#* 1) {
+       echo 'usage: hasmbr /dev/sdC0/part' >[1=2]
+       exit usage
+}
+
+x=`{xd -b $1 | sed -n '32p;32q'}
+if(~ $x(16) 55 && ~ $x(17) aa) 
+       exit ''
+exit nope
+
diff --git a/sys/lib/dist.old/pc/inst/hdrs b/sys/lib/dist.old/pc/inst/hdrs
new file mode 100755 (executable)
index 0000000..0b93499
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/rc
+
+if(! ~ $#* 1) {
+       echo 'usage: hdrs file.9gz' >[1=2]
+       exit usage
+}
+gunzip < $1 | disk/mkext -h 
diff --git a/sys/lib/dist.old/pc/inst/is9660 b/sys/lib/dist.old/pc/inst/is9660
new file mode 100755 (executable)
index 0000000..1d138e5
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/rc
+
+# 0000000  01  C  D  0  0  1 01 00  P  L  A  N     9
+   
+if(! ~ $#* 1) {
+       echo 'usage: is9660 /dev/sdC0/part' >[1=2]
+       exit usage
+}
+
+ifs=$nl {id=`{dd -if $1 -bs 2048 -skip 16>[2]/dev/null | xd -c | sed 1q | sed 's/.........(....................).*/\1/'}}
+~ $id '01  C  D  0  0  1 01'
+exit $status
diff --git a/sys/lib/dist.old/pc/inst/isext2 b/sys/lib/dist.old/pc/inst/isext2
new file mode 100755 (executable)
index 0000000..b79265f
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/rc
+
+if(! ~ $#* 1) {
+       echo 'usage: isext2 /dev/sdC0/part' >[1=2]
+       exit usage
+}
+
+cmp -s <{dd -if $1 -bs 1 -count 2 -skip 1080 >[2]/dev/null | xd -b |sed 1q} \
+       <{echo '0000000  53 ef'}
+
+exit $status
diff --git a/sys/lib/dist.old/pc/inst/isfat b/sys/lib/dist.old/pc/inst/isfat
new file mode 100755 (executable)
index 0000000..8602785
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/rc
+
+rfork e
+
+# 0000000  eb 3c 90  P  l  a  n  9  .  0  0 00 02 04 02 00
+# 0000010  02 00 02 02  P f8 14 00  ? 00 ff 00  ~ 04  } 00
+# 0000020  02  P 00 00 80 00  ) a8 04  } 00  C  Y  L  I  N
+# 0000030   D  R  I  C  A  L  F  A  T  1  6          fa 8c
+
+if(! ~ $#* 1) {
+       echo 'usage: isfat /dev/sdC0/part' >[1=2]
+       exit usage
+}
+
+arg=$1
+fn fat {
+       cmp -s <{dd -if $arg -bs 1 -count 3 -skip $1 >[2]/dev/null} <{echo -n FAT}
+}
+
+fat 54 || fat 82
+exit $status
+
diff --git a/sys/lib/dist.old/pc/inst/isfossil b/sys/lib/dist.old/pc/inst/isfossil
new file mode 100755 (executable)
index 0000000..21c7d3e
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/rc
+
+if(! ~ $#* 1){
+       echo 'usage: isfossil /dev/sdC0/part' >[1=2]
+       exit usage
+}
+
+arg=$1
+if(! cmp -s <{dd -quiet 1 -if $arg -bs 1024 -iseek 127 |
+       dd -quiet 1 -bs 14 -count 1} <{echo 'fossil config'})
+       exit noconfig
+if(! cmp -s <{dd -quiet 1 -if $arg -bs 1024 -iseek 128 |
+       dd -quiet 1 -bs 4 -count 1 | xd -b | sed 1q} <{echo '0000000  37 76 ae 89'})
+       exit notwritebuffer
+exit 0
+
diff --git a/sys/lib/dist.old/pc/inst/isventi b/sys/lib/dist.old/pc/inst/isventi
new file mode 100755 (executable)
index 0000000..555c27a
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/rc
+
+if(! ~ $#* 1){
+       echo 'usage: isventi /dev/sdC0/part' >[1=2]
+       exit usage
+}
+
+arg=$1
+if(! cmp -s <{dd -quiet 1 -if $arg -bs 1024 -iseek 248 |
+       dd -quiet 1 -bs 13 -count 1} <{echo 'venti config'})
+       exit noconfig
+exit 0
+
diff --git a/sys/lib/dist.old/pc/inst/isventiarenas b/sys/lib/dist.old/pc/inst/isventiarenas
new file mode 100755 (executable)
index 0000000..dfce274
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/rc
+
+if(! ~ $#* 1){
+       echo 'usage: isventiarenas /dev/sdC0/part' >[1=2]
+       exit usage
+}
+
+arg=$1
+if(! cmp -s <{dd -quiet 1 -if $arg -bs 1024 -iseek 256 |
+       dd -quiet 1 -bs 4 -count 1 | xd -b | sed 1q} <{echo '0000000  a9 e4 a5 e7'})
+       exit notarenas
+exit 0
+
diff --git a/sys/lib/dist.old/pc/inst/isventiisect b/sys/lib/dist.old/pc/inst/isventiisect
new file mode 100755 (executable)
index 0000000..0b11c9c
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/rc
+
+if(! ~ $#* 1){
+       echo 'usage: isventiisect /dev/sdC0/part' >[1=2]
+       exit usage
+}
+
+arg=$1
+if(! cmp -s <{dd -quiet 1 -if $arg -bs 1024 -iseek 256 |
+       dd -quiet 1 -bs 4 -count 1 | xd -b | sed 1q} <{echo '0000000  d1 5c 5e c7'})
+       exit notisect
+exit 0
+
diff --git a/sys/lib/dist.old/pc/inst/main b/sys/lib/dist.old/pc/inst/main
new file mode 100755 (executable)
index 0000000..25ac0d1
--- /dev/null
@@ -0,0 +1,115 @@
+#!/bin/rc
+
+. defs
+
+while()
+{
+div=--------------------------------------
+echo
+echo $div
+echo
+echo -n 'Preparing menu...'
+
+# must be topologically sorted (by prereq)
+tasks=(\
+       configfs\
+       partdisk prepdisk\
+       fmtfossil\
+       mountfs\
+       configdist\
+       confignet\
+       mountdist\
+       fmtventi\
+       download\
+       copydist\
+       bootsetup finish stop\
+       stopether stopppp\
+)
+#      startether startppp stopether stopppp download\
+
+# these don't show up in the menu but still matter
+pseudotasks=(configip havefiles etherup etherdown pppup pppdown)
+
+for(i in $tasks $pseudotasks)
+       $i=notdone
+
+coherence
+
+for(i in $tasks $pseudotasks)
+       if(~ $#$i 0)
+               $i=notdone
+
+#
+# we believe the environment about what is done
+# only if we've confirmed it.  since the tasks list is sorted so that
+# prereqs of xxx come before xxx, it's okay to assume xxx
+# is done until proven otherwise -- either a prereq or checkdone
+# will say so.
+#
+
+done=()
+ready=()
+rm /env/done
+rm /env/ready
+for(i in $tasks) {
+       $i=done
+       for(j in `{prereq $i})
+               if(! ~ $$j done)
+                       $i=notdone
+       if(~ $$i done) {
+               export $i
+               $i checkdone
+               $i=`{grep '^'$i^'=' /tmp/vars | sed -n '$p' | sed 's/.*=//'}
+       }
+
+       if(~ $$i notdone ready) {
+               okay=yes
+               for(j in `{prereq $i}) 
+                       if(! ~ $$j done)
+                               okay=no
+               switch($okay){
+               case yes
+                       $i=ready
+                       export $i
+                       $i checkready
+                       $i=`{grep '^'$i^'=' /tmp/vars | sed -n '$p' | sed 's/.*=//'}
+               case no
+                       $i=notdone
+               }
+       }
+
+       if(~ $$i done ready)
+               $$i=($$$i $i)           # rc can be just as complicated as perl!
+}
+
+export $tasks $pseudotasks done ready
+coherence
+echo
+
+if(! ~ $#done 0) {
+       echo 'The following tasks are done: '
+       for(i in $done)
+               desc $i
+       echo
+}
+
+echo 'The following unfinished tasks are ready to be done:'
+for(i in $ready)
+       desc $i
+echo
+
+if(~ $#ready 0) {
+       echo hey you finished everything!  not supposed to happen.
+       sleep 100
+       exit
+}
+
+prompt -d $ready(1) -w '' 'Task to do' $done $ready
+
+echo
+echo $div
+
+$rd go
+$rd=done               # if it's not, the check will figure that out
+export $rd
+}
diff --git a/sys/lib/dist.old/pc/inst/mainloop b/sys/lib/dist.old/pc/inst/mainloop
new file mode 100755 (executable)
index 0000000..94d58ef
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/rc
+
+sleep 86400 &
+cd /bin/inst
+. defs
+fn sigint { }
+
+coherence
+
+disks=`{ls /dev/sd*/data >[2]/dev/null | sed 's!/dev/(sd..)/data!\1!'}
+for (i in /dev/sd*/data)
+       if(test -f $i)
+               disk/fdisk -p $i>`{basename -d $i}^/ctl >[2]/dev/null
+for(i in /dev/sd*/plan9*)
+       if(test -f $i)
+               disk/prep -p $i >`{basename -d $i}^/ctl >[2]/dev/null
+
+# we run this while() here so that ctl-d won''t exit from us -- it''ll only exit main!
+# main contains a while() loop too, to avoid the hit of 
+# continually reexecing from here.
+
+while()
+       main
diff --git a/sys/lib/dist.old/pc/inst/mkini.awk b/sys/lib/dist.old/pc/inst/mkini.awk
new file mode 100755 (executable)
index 0000000..7ddf6a8
--- /dev/null
@@ -0,0 +1,59 @@
+BEGIN{
+       m = "common"
+       haveold = 0;
+       while(getline <"/n/9fat/plan9-3e.ini" > 0){
+               haveold = 1
+               if($0 ~ /\[.*\]/){
+                       m = substr($0, 2, length($0)-2)
+                       continue
+               }
+               if(m=="menu" && $0 ~ /^menuitem=4e,/)
+                       continue
+               a[m] = a[m] $0 "\n"
+       }
+
+       a["4e"] = ""
+       while(getline <"/tmp/plan9.ini" > 0)
+               a["4e"] = a["4e"] $0 "\n"
+
+       if(a["menu"] == "" && haveold){
+               a["menu"] = "menuitem=3e, Plan 9 Third Edition\n"
+               a["3e"] = ""
+       }
+
+       if(a["common"] != ""){
+               for(i in a)
+                       if(i != "4e" && i != "common" && i != "menu")
+                               a[i] = a["common"] a[i]
+               delete a["common"]
+       }
+
+       bootdisk4e=ENVIRON["fs"]
+       gsub("/dev/", "boot(args|disk|file)=local!#S/", bootdisk4e)
+
+       if(!haveold)
+               print a["4e"]
+       else{
+               print "[menu]"
+               print "menuitem=4e, Plan 9 Fourth Edition"
+               print a["menu"]
+               print ""
+               delete a["menu"]
+       
+               print "[4e]"
+               print a["4e"]
+               print ""
+               delete a["4e"]
+       
+               for(i in a){
+                       # BUG: if rootdir is already there we should rewrite it 
+                       # sometimes into /3e/whatwasthere
+                       if(a[i] ~ bootdisk4e && !(a[i] ~ /rootdir=/))
+                               a[i] = "rootdir=/root/3e\n" a[i]
+                       print "[" i "]"
+                       gsub(/9fat!9pcdisk/, "9fat!9pc3e", a[i])
+                       print a[i]
+                       print ""
+               }
+       }
+}
diff --git a/sys/lib/dist.old/pc/inst/mountdist b/sys/lib/dist.old/pc/inst/mountdist
new file mode 100755 (executable)
index 0000000..8d171a1
--- /dev/null
@@ -0,0 +1,222 @@
+#!/bin/rc
+
+# prereq: mountfs configdist
+# desc: locate and mount the distribution
+
+fn domount{
+       if(! test -e $mountmedia(2))
+               logprog $srvmedia
+       unmount /n/distmedia >[2]/dev/null
+       logprog $mountmedia
+}
+
+fn exitifdone{
+       if(test -f /n/dist/dist/replica/plan9.db)
+               exit
+}
+
+fn trycdimage{
+       if(test -f $1){
+               rm -f /srv/9660.dist
+               unmount /n/dist
+               9660srv 9660.dist >[2]/dev/null
+               logprog mount /srv/9660.dist /n/dist $1
+               exitifdone
+               mountdist=notdone
+               export mountdist
+               exit notdone
+       }
+}
+
+fn trycdimagebz2 {
+       if(test -f $1){
+               echo -n 'bunzip2 < '^$1^' >/n/newfs/dist/plan9.iso'
+               bunzip2 < $1 >/n/newfs/dist/_plan9.iso &&
+               mv /n/newfs/dist/_plan9.iso /n/newfs/dist/plan9.iso
+               echo
+               trycdimage /n/newfs/dist/plan9.iso
+               mountdist=notdone
+               export mountdist
+               exit notdone
+       }
+}
+
+fn havedist {
+       test -f $1/dist/replica/plan9.db ||
+       test -f $1/plan9.iso ||
+       test -f $1/plan9.iso.bz2
+}
+
+switch($1){
+case checkready
+       if(! ~ $distisfrom local && ! ~ $download done){
+               mountdist=notdone
+               export mountdist
+       }
+       if(! ~ $#mountmedia 0 1){
+               if(domount){
+                       mountdist=done
+                       export mountdist
+                       if(mountdist checkdone)
+                               exit
+               }
+               srvmedia=()
+               mountmedia=()
+               mountdist=ready
+               export srvmedia mountmedia mountdist
+       }
+               
+case go
+       fat=()
+       ext2=()
+       x9660=()
+       fossil=()
+
+       echo Please wait... Scanning storage devices...
+
+       parts=`{ls /dev/sd??/* >[2]/dev/null | grep -v '/(plan9.*|ctl|log|raw)$'}
+       for (i in $parts) {
+               echo -n '       '^$i
+               n=`{echo $i | sed 's;/;_;g'}
+               if(! test -f /tmp/localpart.$n)
+                       dd -if $i -bs 2048 -count 32 -of /tmp/localpart.$n >[2]/dev/null
+               if(isfat /tmp/localpart.$n)
+                       fat=($fat $i)
+               if(isext2 /tmp/localpart.$n)
+                       ext2=($ext2 $i)
+               if(is9660 /tmp/localpart.$n)
+                       x9660=($x9660 $i)
+               if(isfossil $i)
+                       fossil=($fossil $i)
+               echo
+       }
+       echo
+       echo The following storage media were detected.
+       echo Choose the one containing the distribution.
+       echo
+       for(i in $parts){
+               switch($i){
+               case $fat
+                       echo    '       '^$i^' (microsoft fat)'
+               case $ext2
+                       echo    '       '^$i^' (linux ext2)'
+               case $x9660
+                       echo    '       '^$i^' (iso9660 cdrom)'
+               case $fossil
+                       echo    '       '^$i^' (plan9 fossil)'
+               }
+       }
+       echo
+
+       mountstatus=x
+       while(! ~ $mountstatus ''){
+               prompt -w '' 'Distribution disk' $fat $x9660 $fossil
+               disk=$rd
+
+               srvmedia=()
+               mountmedia=()
+               switch($disk){
+               case $fs
+                       mountmedia=(bind /n/newfs /n/distmedia)
+               case $fat
+                       srvmedia=(dossrv)
+                       mountmedia=(mount /srv/dos /n/distmedia $disk)
+               case $ext2
+                       srvmedia=(ext2srv -r)
+                       mountmedia=(mount /srv/ext2 /n/distmedia $disk)
+               case $x9660
+                       srvmedia=(9660srv)
+                       mountmedia=(mount /srv/9660 /n/distmedia $disk)
+               case $fossil
+                       echo 'srv fossil.mountdist' > /tmp/fossi.conf
+                       echo 'fsys main config '^$disk >> /tmp/fossil.conf
+                       echo 'fsys main open -AWVP' >> /tmp/fossil.conf
+                       echo 'fsys main' >> /tmp/fossil.conf
+                       srvmedia=(fossil/fossil -c '. /tmp/fossil.conf')
+                       mountmedia=(mount /srv/fossil.mountdist /n/distmedia)
+               case *
+                       echo Unknown disk type '(cannot happen)'
+                       exit oops
+               }
+               export srvmedia mountmedia
+               domount
+               mountstatus=$status
+       }
+
+       first=yes
+       dir=/
+       while(~ $first yes || ! havedist /n/distmedia/$dir){
+               if(~ $first yes){
+                       echo
+                       echo Which directory contains the distribution?
+                       echo 'Any of the following will suffice (in order of preference):'
+                       echo '  - the root directory of the cd image'
+                       echo '  - the directory containing plan9.iso'
+                       echo '  - the directory containing plan9.iso.bz2'
+                       echo 'Typing `browse'' will put you in a shell that you can use to'
+                       echo 'look for the directory.'
+                       echo
+                       first=no
+               }
+
+               prompt -d browse 'Location of archives'
+               dir=$rd
+               if(~ $dir browse){
+                       echo This is a simple shell.  Commands are:
+                       echo '  cd directory    - change to directory'
+                       echo '  lc                              - list contents of current directory'
+                       echo '  exit                    - exit shell'
+                       echo 
+                       echo 'Move to the directory containing the distribution'
+                       echo 'and then exit.'
+                       echo
+                       oifs=$ifs
+                       ifs=$nl
+                       dir=`{cdsh -r /n/distmedia}
+                       ifs=$oifs
+               }
+               if(~ $#dir 0)
+                       dir=safdsfdsfdsf
+               if(! ~ $#dir 1)
+                       dir=$"dir
+               if(! havedist /n/distmedia/$dir)
+                       echo 'No distribution found in '^`{cleanname /$dir}
+       }
+
+       distmediadir=$dir
+       export distmediadir
+
+case checkdone
+       if(! ~ $#distmediadir 1){
+               mountdist=notdone
+               export mountdist
+               exit notdone
+       }
+       if(! havedist /n/distmedia/$distmediadir && ! havedist /n/newfs/dist){
+               mountdist=notdone
+               export mountdist
+               exit notdone
+       }
+
+       exitifdone
+
+       if(test -f /n/distmedia/$distmediadir/dist/replica/plan9.db){
+               bind /n/distmedia/$distmediadir /n/dist
+               bind -a /n/dist/386/bin /bin
+               bind -a /n/dist/rc/bin /bin
+               exitifdone
+               mountdist=notdone
+               export mountdist
+               exit notdone
+       }
+
+       trycdimage /n/distmedia/$distmediadir/plan9.iso
+       trycdimage /n/newfs/dist/plan9.iso
+
+       trycdimagebz2 /n/distmedia/$distmediadir/plan9.iso.bz2
+       trycdimagebz2 /n/newfs/dist/plan9.iso.bz2
+
+       mountdist=notdone
+       export mountdist
+       exit notdone
+}
diff --git a/sys/lib/dist.old/pc/inst/mountfossil b/sys/lib/dist.old/pc/inst/mountfossil
new file mode 100755 (executable)
index 0000000..e98a3f4
--- /dev/null
@@ -0,0 +1,104 @@
+#!/bin/rc
+
+switch($1){
+case checkready checkdone
+       if(! ~ $fmtfossil done){
+               mountfs=notdone
+               export mountfs
+               exit
+       }
+       if(! test -f /dev/sd*/fossil* && ! test -f /dev/fs/fossil*){
+               mountfs=notdone
+               export mountfs
+               exit
+       }
+       if(! ~ $#fossil 1 || ! test -f $fossil){
+               mountfs=ready
+               export mountfs
+               exit
+       }
+       if(! ps | grep -s ' fossil$'){
+               echo 'srv -p fscons' > /env/fossilconf
+               echo 'srv -AP fossil' >> /env/fossilconf
+               fossil/conf $fossil | sed 's/^fsys main open .*/& -AWVP/' |
+                       sed 's/^fsys main snaptime .*//' >> /env/fossilconf
+               if(! logprog fossil/fossil -c .' /env/fossilconf'>>[2]/srv/log){
+                       echo 'fossil: '^$status
+                       mountfs=ready
+                       export mountfs
+                       exit oops
+               }
+               if(! test -f /srv/fossil){
+                       echo 'fossil did not create /srv/fossil'
+                       mountfs=ready
+                       exit oops
+               }
+               cat /srv/fscons >>/srv/log &
+               if(! logprog mount -c /srv/fossil /n/newfs){
+                       echo 'mount: '^$status
+                       mountfs=ready
+                       export mountfs
+                       exit oops
+               }
+               fs=$fossil
+               export fs
+       }
+       if(! test -s /n/newfs/adm/users){
+               echo fsys main create /active/adm adm sys d775 >>/srv/fscons
+               echo fsys main create /active/adm/users adm sys 664 >>/srv/fscons
+               echo uname upas :upas >>/srv/fscons
+               echo users -w >>/srv/fscons
+               sleep 2
+       }
+       if(! test -s /n/newfs/adm/users){
+               echo 'could not create /adm/users'
+               mountfs=ready
+               export mountfs
+               exit oops
+       }
+       for(i in dist dist/replica dist/replica/client){
+               if(! test -d /n/newfs/$i)
+                       echo fsys main create /active/$i sys sys d775 >>/srv/fscons
+               sleep 2
+       }
+       if(! test -d /n/newfs/dist/replica/client){
+               echo 'could not create /dist/replica/client'
+               mountfs=ready
+               export mountfs
+               exit oops
+       }
+       if(! test -e /n/newfs/dist/replica/client/plan9.db){
+               echo fsys main create /active/dist/replica/client/plan9.db sys sys 664 >>/srv/fscons
+               echo fsys main create /active/dist/replica/client/plan9.log sys sys a664 >>/srv/fscons
+       }
+       if(test -d /n/newfs/dist/replica/client && test -f /n/newfs/adm/users){
+               mountfs=done
+               export mountfs
+               exit
+       }
+       mountfs=ready
+       export mountfs
+       exit
+
+case go
+       echo 'The following partitions named fossil* were found.'
+       echo
+       echo 'Please choose one to use as the installation file system'
+       echo 'for your Plan 9 installation.'
+       echo
+       files=(`{ls /dev/sd*/fossil* /dev/fs/fossil* >[2]/dev/null})
+       ls -l $files
+       echo
+       if(~ $#fossil 1 && ~ $fossil $files)
+               default=(-d $fossil)
+       if not if(~ $#files 1)
+               default=(-d $files)
+       if not
+               default=()
+       prompt $default 'Fossil partition' $files
+       slay fossil|rc
+       fossil=$rd
+       export fossil
+}
+
+
diff --git a/sys/lib/dist.old/pc/inst/mountfs b/sys/lib/dist.old/pc/inst/mountfs
new file mode 100755 (executable)
index 0000000..8aa9b16
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/rc
+
+# desc: choose and mount file system partition
+# prereq: configfs
+
+switch($fstype){
+case fossil fossil+venti
+       exec mountfossil $*
+case *
+       mountfs=notdone
+       export mountfs
+       exit
+}
+
diff --git a/sys/lib/dist.old/pc/inst/moveoldfs b/sys/lib/dist.old/pc/inst/moveoldfs
new file mode 100755 (executable)
index 0000000..819beeb
--- /dev/null
@@ -0,0 +1,72 @@
+#!/bin/rc
+
+# desc: move an old third edition plan 9 file system out of the way
+# prereq: mountfs
+
+rootfiles=(\
+       386\
+       68000\
+       68020\
+       LICENSE\
+       NOTICE\
+       acme\
+       adm\
+       alpha\
+       arm\
+       cron\
+       dist\
+       fd\
+       lib\
+       lp\
+       mail\
+       mips\
+       mnt\
+       n\
+       power\
+       rc\
+       sparc\
+       sys\
+       tmp\
+       usr/glenda\
+       wrap\
+)
+
+switch($1){
+case checkready
+       if(! test -d /n/kfs/wrap){
+               moveoldfs=done
+               export moveoldfs
+       }
+
+case go
+       if(test -d /n/kfs/wrap){
+               echo 'You have a Third Edition Plan 9 installation on '^$fs^'.'
+               echo 'We need to move the old file system out of the way (into /3e)'
+               echo 'in order to continue.'
+               echo
+               prompt 'Move old file system' y n
+               switch($rd){
+               case y
+                       kname=`{kfsname $fs}
+                       log Moving old Plan 9 installation into /3e on kfs
+                       logprog disk/kfscmd -n$kname 'create /3e sys sys 555 d' >>[2]/srv/log
+                       logprog disk/kfscmd -n$kname 'create /3e/usr sys sys 555 d' >>[2]/srv/log
+                       for(i in $rootfiles)
+                               if(test -e /n/kfs/$i)
+                                       logprog disk/kfscmd -n$kname 'rename /'^$i^' /3e/'^$i
+                       # copy extant /adm/users in case there have been modifications
+                       logprog disk/kfscmd -n$kname 'create /adm adm adm 555 d' >>[2]/srv/log
+                       logprog cp /n/kfs/3e/adm/users /n/kfs/adm/users >>[2]/srv/log
+
+               case n
+                       echo 'Okay, but we can''t continue.'
+                       echo
+               }
+       }
+
+case checkdone
+       if(test -d /n/kfs/wrap){
+               moveoldfs=notdone
+               export moveoldfs
+       }
+}
diff --git a/sys/lib/dist.old/pc/inst/partdisk b/sys/lib/dist.old/pc/inst/partdisk
new file mode 100755 (executable)
index 0000000..430d45f
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/rc
+
+# desc: edit partition tables (e.g., to create a plan 9 partition)
+# prereq: configfs
+
+switch($1){
+case go
+       disks=`{ls /dev/sd*/data >[2]/dev/null | sed 's!/dev/(sd..)/data!\1!'}
+       if(~ $#disks 0) {
+               echo 'No disk devices were found on your system.'
+               echo 'The installation process cannot continue.'
+               exit giveup
+       }
+       
+       echo 'The following disk devices were found.'
+       echo
+       for(i in $disks) {
+               desc=`{cat /dev/$i/ctl | sed 1q | sed 's/inquiry //'}
+               echo $i '-' $desc
+               echo e | disk/fdisk -r /dev/$i/data >[2]/dev/null | grep -v '^   mbr'
+               echo
+       }
+       
+       okay=no
+       defdisk=$disks(1)
+
+       if(~ $#disks 1)
+               default=(-d $disks)
+       if not
+               default=()
+       prompt $default 'Disk to partition' $disks
+       disk=$rd
+
+       if(! hasmbr /dev/$disk/data) {
+               echo 'The disk you selected HAS NO master boot record on its first sector.'
+               echo '(Perhaps it is a completely blank disk.)'
+               echo 'You need a master boot record to use the disk.'
+               echo 'Should we install a default master boot record?'
+               echo
+               prompt 'Install mbr' y n
+               switch($rd) {
+               case y
+                       disk/mbr -m /386/mbr /dev/$disk/data
+                       pickdisk=done
+               }
+       }
+       echo
+       echo 'This is disk/fdisk; use it to create a Plan 9 partition.'
+       echo 'If there is enough room, a Plan 9 partition will be'
+       echo 'suggested; you can probably just type ''w'' and then ''q''.'
+       echo
+       disk/fdisk -a /dev/$disk/data
+       disk/fdisk -p /dev/$disk/data >/dev/$disk/ctl >[2]/dev/null
+       for(i in /dev/sd*/plan9*){
+               if(test -f $i){
+                       d=`{basename -d $i}
+                       disk/prep -p $i >$d/ctl >[2]/dev/null
+               }
+       }
+
+case checkdone
+       # we want at least one disk with both an mbr and a plan9 partition
+       mbrandplan9=0
+       disks=`{ls /dev/sd*/plan9 >[2]/dev/null | sed 's!/dev/(sd..)/plan9!\1!'}
+       for(disk in $disks) {
+               if(hasmbr /dev/$disk/data)
+                       mbrandplan9=1
+       }
+       if(~ $mbrandplan9 0){
+               partdisk=notdone
+               export partdisk
+       }
+}
diff --git a/sys/lib/dist.old/pc/inst/prepdisk b/sys/lib/dist.old/pc/inst/prepdisk
new file mode 100755 (executable)
index 0000000..6ef4a92
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/rc
+
+# desc: subdivide plan 9 disk partition
+# prereq: partdisk
+
+fn autotype {
+       if(~ $fstype fossil)
+               echo -a 9fat -a nvram -a fossil -a swap
+       if(~ $fstype fossil+venti)
+               echo -a 9fat -a nvram -a arenas -a isect -a fossil -a swap # -a other
+}
+
+switch($1) {
+case checkready
+       if(! test -f /dev/sd*/plan9*){
+               prepdisk=notdone
+               export prepdisk
+       }
+
+case go
+       echo 'The following Plan 9 disk partitions were found.'
+       echo
+       disks=(/dev/sd*/plan9*)
+       for (i in $disks){
+               echo $i
+               echo q | disk/prep -r $i >[2]/dev/null
+               echo
+       }
+       if(~ $#disks 1)
+               default=(-d $disks)
+       if not
+               default=()
+       prompt $default 'Plan 9 partition to subdivide' $disks
+       disk=$rd
+
+       echo 'This is disk/prep; use it to subdivide the Plan 9 partition.'
+       echo 'If it is not yet subdivided, a sensible layout will be suggested;'
+       echo 'you can probably just type ''w'' and then ''q''.'
+       echo
+       disk/prep `{autotype} $disk
+       disk/prep -p $disk >`{basename -d $disk}^/ctl >[2]/dev/null
+
+case checkdone
+       if(! test -f /dev/sd*/9fat)
+               prepdisk=ready
+
+       if(! ~ $prepdisk ready){
+               prepdisk=done
+               switch($fstype){
+               case fossil
+                       if(! test -f /dev/sd*/fossil* && ! test -f /dev/fs/fossil*)
+                               prepdisk=ready
+               case fossil+venti
+                       if(! test -f /dev/sd*/fossil* && ! test -f /dev/fs/fossil*)
+                               prepdisk=ready
+                       if(! test -f /dev/sd*/arenas && ! test -f /dev/fs/arenas*)
+                               prepdisk=ready
+                       if(! test -f /dev/sd*/isect && ! test -f /dev/fs/isect*)
+                               prepdisk=ready
+               }
+       }
+       export prepdisk
+}
diff --git a/sys/lib/dist.old/pc/inst/replcfg b/sys/lib/dist.old/pc/inst/replcfg
new file mode 100755 (executable)
index 0000000..30aed86
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/rc
+
+s=/n/dist/dist/replica
+serverroot=/n/dist
+serverlog=$s/plan9.log
+serverproto=$s/plan9.proto
+fn servermount { status='' } 
+fn serverupdate { status='' }
+
+fn clientmount { status='' }
+c=/n/newfs/dist/replica
+clientroot=/n/newfs
+clientproto=$c/plan9.proto
+clientdb=$c/client/plan9.db
+clientexclude=(dist/replica/client)
+clientlog=$c/client/plan9.log
+
+applyopt=(-t -u -T$c/client/plan9.time)
diff --git a/sys/lib/dist.old/pc/inst/startether b/sys/lib/dist.old/pc/inst/startether
new file mode 100755 (executable)
index 0000000..077504c
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/rc
+
+# desc: activate ethernet card
+# prereq: configether
+
+switch($1) {
+case checkready
+       if(isipdevup /net/ether0) {
+               startether=done
+               export startether
+       }
+
+case go
+       if(isipdevup /net/ether0)
+               exit
+
+       log starting ethernet $ethermethod config
+       switch($ethermethod) {
+       case manual
+               ip/ipconfig -g $gwaddr ether /net/ether0 $ipaddr $ipmask >>[2]/srv/log
+       case dhcp
+               ip/ipconfig $dhcphost -D >>/srv/log >[2=1]
+       }
+
+case checkdone
+       if(! isipdevup /net/ether0) {
+               startether=notdone
+               export startether
+       }
+}
diff --git a/sys/lib/dist.old/pc/inst/startppp b/sys/lib/dist.old/pc/inst/startppp
new file mode 100755 (executable)
index 0000000..02bc090
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/rc
+
+# desc: activate ppp connection
+# prereq: configppp
+
+switch($1) {
+case checkready checkdone
+       if (isipdevup '^pkt[0-9]')
+               startppp=done
+       export startppp
+
+case go
+       if(isipdevup '^pkt[0-9]')
+               exit
+
+       ctl=$pppdev^ctl
+       echo b115200 >$ctl
+
+       switch($pppmethod) {
+       case manual
+               echo 
+               echo 'Please dial the modem, and type ctl-d when PPP has started.'
+               echo 'You may need to type ctl-m to send modem commands.'
+               echo
+               ip/ppp -f -u -b b^$pppbaud -p /dev/^$pppdev
+
+       case auto
+               ip/ppp -f -b b^$pppbaud -p /dev/^$pppdev -s $"pppuser:$"ppppasswd -t 'atdt'^$"pppphone
+       }
+}
diff --git a/sys/lib/dist.old/pc/inst/startwin b/sys/lib/dist.old/pc/inst/startwin
new file mode 100755 (executable)
index 0000000..bcd5428
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/rc
+
+fn time { date | sed 's/.........$//'}
+
+rm -f /srv/log
+
+if(~ $#* 2) {
+       wid=$1
+       ht=$2
+} 
+if not {
+       scr=(`{cat /dev/draw/new >[2]/dev/null || status=''})
+       wid=$scr(7)
+       ht=$scr(8)
+}
+
+if(test $ht -gt 800)
+       ht=800
+
+if(test $wid -gt 800)
+       wid=800
+
+statwid=`{hoc -e $wid^'*.2'}
+if(test $statwid -lt 180)
+       statwid=180
+if(test $statwid -gt 300)
+       statwid=300
+
+logwid=`{hoc -e $wid^-$statwid}
+if(test $logwid -gt 1000)
+       logwid=1000
+
+loght=`{hoc -e $ht^'*.25'}
+if(test $loght -lt 130)
+       loght=130
+
+textht=`{hoc -e $ht^-$loght}
+
+window 0,$textht,$statwid,$ht stats -lmisce
+window $statwid,$textht,^`{hoc -e $logwid+$statwid}^,$ht tailfsrv
+window 0,0,^`{hoc -e $logwid+$statwid}^,$textht inst/mainloop
+
+while(! test -f /srv/log)
+       sleep 1
+
+log `{time} Installation process started
diff --git a/sys/lib/dist.old/pc/inst/stop b/sys/lib/dist.old/pc/inst/stop
new file mode 100755 (executable)
index 0000000..a1d4869
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/rc
+
+# desc: save the current installation state, to be resumed later
+# prereq: 
+# mustdo: 
+
+switch($1) {
+case checkdone
+       stop=notdone
+       export stop
+
+case checkready
+       if(~ $cdboot yes){
+               stop=notdone
+               export stop
+       }
+
+case go
+       coherence
+       switch($2){
+       case finished
+               echo 'We need to write the state of the current installation to the install floppy,'
+               echo 'so that you can pick up from here if, for example, you want to set up'
+               echo 'more boot methods.'
+               echo
+       case *
+               echo 'We need to write the state of the current installation to the install floppy.'
+               echo 'so that you can pick up from here when you wish to continue.'
+               echo
+       }
+       echo -n 'Please make sure the install floppy is in the floppy drive and press enter.'
+       read >/dev/null >[2]/dev/null
+
+       if(! a:) {
+               echo 'Couldn''t mount the floppy disk; sorry.'
+               exit
+       }
+
+       if(cp /tmp/vars /n/a:/9inst.cnf || cp /tmp/vars /n/a:/9inst.cnf) {
+               echo 'Your install state has been saved to the install floppy.'
+               if(~ $2 finished){
+                       echo
+                       echo 'Congratulations; you''ve completed the install.'
+               }
+               echo
+               halt
+       }
+
+       echo 'Couldn''t save the state to your install floppy.  Sorry.'
+}
diff --git a/sys/lib/dist.old/pc/inst/stopether b/sys/lib/dist.old/pc/inst/stopether
new file mode 100755 (executable)
index 0000000..59063f0
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/rc
+
+# desc: shut down the ethernet connection
+# prereq:
+
+
+switch($1) {
+case checkready
+       if(! isipdevup /net/ether0) {
+               stopether=notdone
+               export stopether
+       }
+
+case go
+       ip/ipconfig ether /net/ether0 unbind
+
+case checkdone
+       stopether=notdone
+       export stopether
+}
diff --git a/sys/lib/dist.old/pc/inst/stopppp b/sys/lib/dist.old/pc/inst/stopppp
new file mode 100755 (executable)
index 0000000..70b9ce1
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/rc
+
+# desc: shut down the ppp connection
+# prereq:
+
+switch($1) {
+case checkready
+       if(! ~ $#pppdev 1 || ! isipdevup '^pkt[0-9]') {
+               stopppp=notdone
+               export stopppp
+       }
+
+case go
+       kill ppp | rc
+
+case checkdone
+       stopppp=notdone
+       export stopppp
+}
diff --git a/sys/lib/dist.old/pc/inst/textonly b/sys/lib/dist.old/pc/inst/textonly
new file mode 100755 (executable)
index 0000000..1c3922c
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/rc
+
+# text-only install
+cd /bin/inst
+. defs
+
+textinst=1
+export textinst
+
+tailfsrv &
+while(! test -f /srv/log)
+       sleep 1
+log `{date} Installation process started
+inst/mainloop
+
diff --git a/sys/lib/dist.old/pc/inst/watchfd b/sys/lib/dist.old/pc/inst/watchfd
new file mode 100755 (executable)
index 0000000..ca37294
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/rc
+
+p=`{ps | grep $1 | sed 's/[^ ]* +([^ ]+) .*/\1/' }
+while(! ~ $#p 1) {
+       sleep 1
+       p=`{ps | grep $1 | sed 's/[^ ]* +([^ ]+) .*/\1/'}
+}
+p=$p(1)
+
+baropt='-w 145,129,445,168'
+if(~ $textinst 1)
+       baropt=-t
+
+{
+       while(test -f /proc/$p/fd)
+               grep '^ *'^$2^' ' /proc/$p/fd >[2]/dev/null
+} | awk '{print $9 " '^$3^'"; fflush("/dev/stdout")}' | bargraph $baropt $4
diff --git a/sys/lib/dist.old/pc/inst/xxx b/sys/lib/dist.old/pc/inst/xxx
new file mode 100755 (executable)
index 0000000..56b4eb2
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/rc
+
+ip/ipconfig
+echo ' auth=204.178.31.3
+       authdom=cs.bell-labs.com' >>/net/ndb
+ndb/cs
+auth/factotum
+bind -a /bin/auth /
+cpu -e clear -h tcp!204.178.31.2
diff --git a/sys/lib/dist.old/pc/mkfile b/sys/lib/dist.old/pc/mkfile
new file mode 100644 (file)
index 0000000..43ee0b7
--- /dev/null
@@ -0,0 +1,100 @@
+out=outside                    # outside web server
+s=/sys/lib/dist/pc
+x=`{bind -b /sys/lib/dist/bin/$cputype /bin}
+default:V: ndisk
+       ls -l ndisk
+
+SUB=`{ls sub inst}
+boot.raw:Q: proto $SUB
+       rm -rf boot
+       mkdir boot
+       bind /dev/null /sys/log/timesync
+       # make files writable for now.
+       cat proto | sed 's!d000!d775!;s!000!664!;s!555!775!;s!444!664!' >proto.cp
+       disk/mkfs -a proto.cp | disk/mkext -d boot
+       @{
+               cd boot/386
+               strip init
+               cd bin
+               strip * */* >[2]/dev/null || status=''
+       }
+       cat proto | sed 's!/.*!!' >proto.cp
+       disk/mkfs -a -s boot proto.cp | tee >{wc -c >[1=2]} | 
+               touchfs 1000000000 >boot.raw
+
+boot.bz2:Q: boot.raw
+       ls -l boot.raw
+       bflz -n 32 < boot.raw >boot.bflz
+       ls -l boot.bflz
+       bzip2 -9 < boot.bflz >$target
+       ls -l $target
+
+root.bz2:Q: boot.bz2
+       {
+               echo bzfilesystem
+               cat boot.bz2
+               dd -if /dev/zero -bs 1024 -count 1 >[2]/dev/null
+       } >$target
+       ls -l $target
+
+/sys/src/9/pc/9pcflop.gz: root.bz2
+       @{
+               rfork n
+               cd /sys/src/9/pc
+               mk 'CONF=pcflop' 9pcflop.gz
+       }
+
+/sys/src/9/pc/9pccd.gz:
+       @{
+               cd /sys/src/9/pc
+               mk 'CONF=pccd' 9pccd.gz
+       }
+
+# disk/format apparently uses stat to obtain a file's real name, so
+# binding 9loadusb onto 9load will store the name 9loadusb in the
+# generated fat filesystem.  the same is true for plan9.ini.cd and plan9.ini.
+
+9load: /386/9loadlite
+#      cp $prereq $target
+       if (test -e /386/9loadnousb)
+               cp  /386/9loadnousb $target     # cater to old bioses
+       cp /386/9loadlitedebug 9loaddebug
+
+ndisk: 9load /sys/src/9/pc/9pcflop.gz plan9.ini /lib/vgadb
+       dd -if /dev/zero -of ndisk -bs 1024 -count 1440 >[2]/dev/null
+       disk/format -f -b /386/pbs -d ndisk \
+               9load /sys/src/9/pc/9pcflop.gz plan9.ini /lib/vgadb
+       ls -l ndisk
+
+# cannot list both 9pcflop.gz and 9pccd.gz because they cannot be built 
+# in parallel.  stupid mk
+cddisk:DV: 9load /sys/src/9/pc/9pcflop.gz plan9.ini.cd /lib/vgadb
+       mk -a /sys/src/9/pc/9pccd.gz
+       mk -a /sys/src/9/pc/9pcflop.gz
+       rfork n
+       cp -x plan9.ini.cd subst/plan9.ini
+       dd -if /dev/zero -of cddisk -bs 1024 -count 2880 >[2]/dev/null
+       disk/format -t 3½QD -f -b /386/pbs -d cddisk \
+               9load /sys/src/9/pc/^(9pcflop.gz 9pccd.gz) \
+               subst/plan9.ini /lib/vgadb
+       ls -l cddisk
+
+clean:V:
+       if (! unmount 9load >[2]/dev/null)
+               ;
+       rm -rf boot boot.bz2 boot.bflz boot.raw root.bz2 9pcflop ndisk 9load cddisk proto.cp 9loaddebug
+
+install:V: ndisk 9loaddebug
+       9fs $out
+       dst=/n/$out/sys/lib/dist/web.protect
+       cp 9loaddebug $dst
+       gzip -9 < ndisk > $dst/plan9.flp.gz
+       # mk clean
+
+test:V: ndisk 9loaddebug
+       cp 9loaddebug ../web.protect2/n9loaddebug
+       cp ndisk ../web.protect2/ndisk
+
+cd0:D: cddisk
+       rm -f cd0
+       disk/mk9660 -9cj -v 'Plan 9 4th Edition' -s . -p cd0.proto -b cddisk cd0
diff --git a/sys/lib/dist.old/pc/plan9.ini b/sys/lib/dist.old/pc/plan9.ini
new file mode 100644 (file)
index 0000000..71f98e5
--- /dev/null
@@ -0,0 +1,37 @@
+# config for initial floppy booting
+
+[menu]
+menuitem=boot, Boot Plan 9
+# menuitem=debug, Boot Plan 9 and debug 9load
+menudefault=boot, 10
+
+[common]
+# very cautious settings to get started.
+# will defeat booting from usb devices.
+*nomp=1
+*nobiosload=1
+# *noahciload=1
+# *debugload=1
+*nodumpstack=1
+# this would disable ether and usb probing.
+# *nousbprobe=1
+# *noetherprobe=1
+distname=plan9
+partition=new
+mouseport=ask
+monitor=ask
+vgasize=ask
+dmamode=ask
+nobootprompt=local!/boot/bzroot
+installurl=http://plan9.bell-labs.com/plan9/download/plan9.iso.bz2
+# serial console on COM1
+#console=0
+
+[boot]
+bootargs=local!#S/sdD0/data
+bootfile=sdD0!cdboot!9pccd.gz
+
+# [debug]
+# bootargs=local!#S/sdD0/data
+# bootfile=sdD0!cdboot!9pccd.gz
+# *debugload=1
diff --git a/sys/lib/dist.old/pc/plan9.ini.blank b/sys/lib/dist.old/pc/plan9.ini.blank
new file mode 100644 (file)
index 0000000..be51a5d
--- /dev/null
@@ -0,0 +1,10 @@
+THIS IS A 512 byte BLANK PLAN9.INI
+                                                       
+                                                       
+                                                       
+                                                       
+                                                       
+                                                       
+                                                       
+                                                       
+                            
diff --git a/sys/lib/dist.old/pc/plan9.ini.cd b/sys/lib/dist.old/pc/plan9.ini.cd
new file mode 100644 (file)
index 0000000..11a2435
--- /dev/null
@@ -0,0 +1,40 @@
+# config for initial cd booting
+
+[menu]
+menuitem=install, Install Plan 9 from this CD
+menuitem=cdboot, Boot Plan 9 from this CD
+# menuitem=debug, Boot Plan 9 from this CD and debug 9load
+
+[common]
+# very cautious settings to get started.
+# will defeat booting from usb devices.
+*nomp=1
+*nobiosload=1
+# *noahciload=1
+# *debugload=1
+*nodumpstack=1
+# this would disable ether and usb probing.
+# *nousbprobe=1
+# *noetherprobe=1
+partition=new
+mouseport=ask
+monitor=ask
+vgasize=ask
+dmamode=ask
+adisk=/dev/sdD0/cdboot
+cdboot=yes
+# console=0
+# baud=9600
+
+[install]
+nobootprompt=local!/boot/bzroot
+bootfile=sdD0!cdboot!9pcflop.gz
+
+[cdboot]
+bootargs=local!#S/sdD0/data
+bootfile=sdD0!cdboot!9pccd.gz
+
+# [debug]
+# bootargs=local!#S/sdD0/data
+# bootfile=sdD0!cdboot!9pccd.gz
+# *debugload=1
diff --git a/sys/lib/dist.old/pc/plan9.ini.vmware b/sys/lib/dist.old/pc/plan9.ini.vmware
new file mode 100644 (file)
index 0000000..dfee230
--- /dev/null
@@ -0,0 +1,20 @@
+# config for initial vmware booting
+
+# very cautious settings to get started.
+# will defeat booting from usb devices.
+*nomp=1
+*nobiosload=1
+# *noahciload=1
+# *debugload=1
+# *nodumpstack=1
+
+partition=new
+nobootprompt=local!/boot/bzroot
+bootfile=fd0!9pcflop.gz
+
+mouseport=ps2
+monitor=xga
+vgasize=1024x768x16
+#adisk=/dev/sdD0/cdboot
+console=0
+baud=9600
diff --git a/sys/lib/dist.old/pc/proto b/sys/lib/dist.old/pc/proto
new file mode 100644 (file)
index 0000000..a12695d
--- /dev/null
@@ -0,0 +1,175 @@
+386    d775 sys sys
+#      9load   555 sys sys
+       init    555 sys sys
+#      ld.com  555 sys sys
+       mbr     555 sys sys
+       pbs     555 sys sys
+       pbslba  555 sys sys
+       bin     d775 sys sys
+               auth d555 sys sys
+# i think factotum is only needed if we include cpu
+#                      factotum        555 sys sys
+               aux     d555 sys sys
+                       isvmware        555 sys sys
+                       mouse   555 sys sys /sys/lib/dist/pc/multi/mouse
+                       pcmcia  555 sys sys /sys/lib/dist/pc/multi/pcmcia
+               #       stub    555 sys sys
+                       vga     555 sys sys /sys/lib/dist/pc/multi/vga
+                       vmware  555 sys sys /sys/lib/dist/pc/sub/vmware
+               #       vmware  555 sys sys
+               #       vmwarefs        555 sys sys
+               #       vmmousepoll     555 sys sys
+                       zerotrunc       555 sys sys /sys/lib/dist/pc/multi/zerotrunc
+               disk    d555 sys sys
+                       fdisk   555 sys sys /sys/lib/dist/pc/multi/fdisk
+                       format  555 sys sys /sys/lib/dist/pc/multi/format
+#                      kfs     555 sys sys
+#                      kfscmd  555 sys sys
+                       mbr     555 sys sys /sys/lib/dist/pc/multi/mbr
+                       prep    555 sys sys /sys/lib/dist/pc/multi/prep
+               fossil  d555 sys sys
+                       fossil  555 sys sys
+                       flfmt   555 sys sys
+                       conf            555 sys sys
+               ip      d555 sys sys
+                       ipconfig        555 sys sys /sys/lib/dist/pc/multi/ipconfig
+                       ppp     555 sys sys /sys/lib/dist/pc/multi/ppp
+               ndb     d555 sys sys
+# csquery and dnsquery could go
+                       cs      555 sys sys /sys/lib/dist/pc/multi/cs
+#                      csquery 555 sys sys
+                       dns     555 sys sys /sys/lib/dist/pc/multi/dns
+#                      dnsquery        555 sys sys
+               replica d555 sys sys
+                       applylog        555 sys sys
+                       changes 555 sys sys
+                       compactdb       555 sys sys /sys/lib/dist/pc/sub/compactdb
+                       pull            555 sys sys
+               venti   d555 sys sys
+#                      venti   555 sys sys
+#                      conf            555 sys sys
+#                      fmtarenas       555 sys sys
+#                      fmtindex        555 sys sys
+#                      fmtisect        555 sys sys
+               9660srv 555 sys sys /sys/lib/dist/pc/multi/9660srv
+# acme could go
+#              acme    555 sys sys
+               awk     555 sys sys
+               bargraph        555 sys sys /sys/lib/dist/bin/386/bargraph
+               basename        555 sys sys /sys/lib/dist/pc/multi/basename
+               cat     555 sys sys /sys/lib/dist/pc/multi/cat
+               chgrp   555 sys sys /sys/lib/dist/pc/multi/chgrp
+               chmod   555 sys sys /sys/lib/dist/pc/multi/chmod
+               cleanname       555 sys sys /sys/lib/dist/pc/multi/cleanname
+               cmp     555 sys sys /sys/lib/dist/pc/multi/cmp
+               cdsh    555 sys sys /sys/lib/dist/bin/386/cdsh
+               cp      555 sys sys /sys/lib/dist/pc/multi/cp
+# cpu could go
+#              cpu     555 sys sys
+               date    555 sys sys /sys/lib/dist/pc/multi/date
+               dd      555 sys sys /sys/lib/dist/pc/multi/dd
+               dossrv 555 sys sys /sys/lib/dist/pc/multi/dossrv
+               echo    555 sys sys /sys/lib/dist/pc/multi/echo
+               ed      555 sys sys /sys/lib/dist/pc/multi/ed
+# if cpu goes, exportfs could go
+#              exportfs        555 sys sys
+               ext2srv 555 sys sys /sys/lib/dist/pc/multi/ext2srv
+               fcp             555     sys     sys
+               grep    555 sys sys /sys/lib/dist/pc/multi/grep
+               hget    555 sys sys /sys/lib/dist/pc/multi/hget
+               hoc     555 sys sys /sys/lib/dist/pc/multi/hoc
+               ls      555 sys sys /sys/lib/dist/pc/multi/ls
+               mc      555 sys sys /sys/lib/dist/pc/multi/mc
+               mount   555 sys sys /sys/lib/dist/pc/multi/mount
+               multi   555 sys sys /sys/lib/dist/bin/386/multi
+               mv      555 sys sys /sys/lib/dist/pc/multi/mv
+#              netkey  555 sys sys
+               ps      555 sys sys /sys/lib/dist/pc/multi/ps
+               rc      555 sys sys
+               read    555 sys sys /sys/lib/dist/pc/multi/read
+               rio     555 sys sys
+               rm      555 sys sys /sys/lib/dist/pc/multi/rm
+               sed     555 sys sys /sys/lib/dist/pc/multi/sed
+# snoopy could go
+#              snoopy  555 sys sys
+               sort    555 sys sys /sys/lib/dist/pc/multi/sort
+               srv     555 sys sys /sys/lib/dist/pc/multi/srv
+#              ssh     555 sys sys
+               stats   555 sys sys
+               syscall 555 sys sys /sys/lib/dist/pc/multi/syscall
+               tail    555 sys sys /sys/lib/dist/pc/multi/tail
+               tailfsrv        555 sys sys /sys/lib/dist/bin/386/tailfsrv
+               tee     555 sys sys /sys/lib/dist/pc/multi/tee
+#              telnet  555 sys sys
+               test    555 sys sys /sys/lib/dist/pc/multi/test
+               wc      555 sys sys /sys/lib/dist/pc/multi/wc
+               xd      555 sys sys /sys/lib/dist/pc/multi/xd
+adm    d555 adm adm
+       timezone        d555 sys sys
+               local   555 sys sys
+lib    d777 sys sys
+       font    d555 sys sys
+               bit     d555 sys sys
+                       lucidasans      d555 sys sys
+                               lstr.12 444 sys sys
+                               typelatin1.7.font       444 sys sys
+#                      lucm    d555 sys sys
+#                              latin1.9        444 sys sys
+#                              latin1.9.font   444 sys sys
+       namespace       444 sys sys
+       ndb     d555 sys sys
+               common  444 sys sys /sys/lib/dist/pc/sub/common
+               local   444 sys sys /sys/lib/dist/pc/sub/local
+       vgadb   666 sys sys     /dev/null
+fd     d555 sys sys
+mnt    d777 sys sys
+       arch    d000 sys sys
+       temp d000 sys sys
+       vmware  d000 sys sys
+       wsys    d000 sys sys
+n      d777 sys sys
+       a:      d000 sys sys
+       a       d000 sys sys
+       c:      d000 sys sys
+       c       d000 sys sys
+       9fat    d000 sys sys
+       kremvax d000 sys sys    /sys/lib/dist/pc/empty
+       newfs   d000 sys sys
+       dist    d000 sys sys    /sys/lib/dist/pc/empty
+       distmedia       d000 sys sys    /sys/lib/dist/pc/empty
+rc     d555 sys sys
+       bin     d775 sys sys
+               inst    d775 sys sys /sys/lib/dist/pc/empty
+                       +       - sys sys /sys/lib/dist/pc/inst
+               9fat:   555 sys sys
+               a:      555 sys sys      /sys/lib/dist/pc/sub/a:
+               bind    555 sys sys /sys/lib/dist/pc/sub/bind
+               boota:  555 sys sys     /sys/lib/dist/pc/sub/boota:
+               bunzip2 555 sys sys /sys/lib/dist/pc/sub/bunzip2
+               c:      555 sys sys
+               dosmnt  555 sys sys
+               kill    555 sys sys
+               lc      555 sys sys
+               mkdir   555 sys sys /sys/lib/dist/pc/sub/mkdir
+               pci     555 sys sys
+               pwd     555 sys sys /sys/lib/dist/pc/sub/pwd
+               ramfs   555 sys sys /sys/lib/dist/pc/sub/ramfs
+               replica d555 sys sys
+                       changes 555 sys sys
+                       defs    555 sys sys
+                       pull    555 sys sys
+               slay            555 sys sys
+               sleep   555 sys sys /sys/lib/dist/pc/sub/sleep
+               termrc  555 sys sys /sys/lib/dist/pc/sub/termrc
+               unmount 555 sys sys /sys/lib/dist/pc/sub/unmount
+               window  555 sys sys
+       lib     d555 sys sys
+               rcmain  444 sys sys
+sys    d555 sys sys
+       log     d555 sys sys
+               dns     444 sys sys     /sys/lib/dist/pc/emptyfile
+               timesync        444 sys sys     /sys/lib/dist/pc/emptyfile
+tmp    d555 sys sys
+usr    d555 sys sys
+       glenda  d775 glenda glenda
+               +       - glenda glenda /sys/lib/dist/pc/glenda
diff --git a/sys/lib/dist.old/pc/sub/D003753 b/sys/lib/dist.old/pc/sub/D003753
new file mode 100755 (executable)
index 0000000..8624d6e
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/rc
+if(! test -f /srv/dos)
+       dossrv >/dev/null </dev/null >[2]/dev/null
+unmount /n/a:>[2]/dev/null
+
+if(~ $#adisk 1)
+       ;       # do nothing
+if not if(~ $#bootfile 0)
+       adisk=/dev/fd0disk
+if not {
+       switch($bootfile) {
+       case sd*
+               adisk=`{echo $bootfile | sed 's#(sd..).*#/dev/\1/data#'}
+       case fd*
+               adisk=`{echo $bootfile | sed 's#(fd.).*#/dev/\1disk#'}
+       case *
+               echo 'unknown bootfile '^$bootfile^'; mail 9trouble@plan9.bell-labs.com'
+               exit oops
+       }
+}
+
+mount -c /srv/dos /n/a: $adisk
diff --git a/sys/lib/dist.old/pc/sub/F004116 b/sys/lib/dist.old/pc/sub/F004116
new file mode 100755 (executable)
index 0000000..5f6809b
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/rc
+
+rfork e
+if(! test -f /srv/dos)
+       dossrv >/dev/null </dev/null >[2]/dev/null
+unmount /n/a:>[2]/dev/null
+
+switch($bootfile) {
+case sd*!cdboot!*
+       # just look for the right file.  bootfile isn''t trustworthy
+       adisk=/dev/sd*/cdboot
+       if(! ~ $#adisk 1)
+               adisk=$adisk(1)
+case sd*
+       adisk=`{echo $bootfile | sed 's#(sd..).*#/dev/\1/dos#'}
+case fd*
+       adisk=`{echo $bootfile | sed 's#(fd.).*#/dev/\1disk#'}
+case *
+       echo 'unknown bootfile '^$bootfile^'; mail 9trouble@plan9.bell-labs.com'
+       exit oops
+}
+
+mount -c /srv/dos /n/a: $adisk
+
diff --git a/sys/lib/dist.old/pc/sub/bind b/sys/lib/dist.old/pc/sub/bind
new file mode 100755 (executable)
index 0000000..bc01455
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/rc
+
+rfork e
+flag=0
+while(~ $1 -*){
+       switch($1){
+       case -b
+               flag=1
+       case -a
+               flag=2
+       case -c
+               flag=4
+       case -ac -ca
+               flag=6
+       case -bc -cb
+               flag=5
+       }
+       shift
+}
+
+syscall bind $1 $2 $flag >[2]/dev/null
diff --git a/sys/lib/dist.old/pc/sub/bunzip2 b/sys/lib/dist.old/pc/sub/bunzip2
new file mode 100755 (executable)
index 0000000..0a876c6
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/rc
+
+exec /boot/kfs BUNZIP
+# kfs is bzfs
\ No newline at end of file
diff --git a/sys/lib/dist.old/pc/sub/common b/sys/lib/dist.old/pc/sub/common
new file mode 100755 (executable)
index 0000000..ec3e1bc
--- /dev/null
@@ -0,0 +1,123 @@
+#
+#  services
+#
+tcp=cs port=1
+tcp=echo port=7
+tcp=discard port=9
+tcp=systat port=11
+tcp=daytime port=13
+tcp=netstat port=15
+tcp=chargen port=19
+tcp=ftp-data port=20
+tcp=ftp port=21
+tcp=ssh port=22
+tcp=telnet port=23
+tcp=smtp port=25
+tcp=time port=37
+tcp=whois port=43
+tcp=domain port=53
+tcp=uucp port=64
+tcp=gopher port=70
+tcp=rje port=77
+tcp=finger port=79
+tcp=http port=80
+tcp=link port=87
+tcp=supdup port=95
+tcp=hostnames port=101
+tcp=iso-tsap port=102
+tcp=x400 port=103
+tcp=x400-snd port=104
+tcp=csnet-ns port=105
+tcp=pop-2 port=109
+tcp=pop3 port=110
+tcp=sunrpc port=111
+tcp=uucp-path port=117
+tcp=nntp port=119
+tcp=netbios port=139
+tcp=NeWS port=144
+tcp=print-srv port=170
+tcp=z39.50 port=210
+tcp=fsb port=400
+tcp=sysmon port=401
+tcp=proxy port=402
+tcp=proxyd port=404
+tcp=https port=443
+tcp=ssmtp port=465
+tcp=snntp port=563
+tcp=rexec port=512 restricted=
+tcp=login port=513 restricted=
+tcp=shell port=514 restricted=
+tcp=printer port=515
+tcp=courier port=530
+tcp=cscan port=531
+tcp=uucp port=540
+tcp=9fs port=564
+tcp=whoami port=565
+tcp=guard port=566
+tcp=ticket port=567
+tcp=fmclient port=729
+tcp=ingreslock port=1524
+tcp=webster port=2627
+tcp=weather port=3000
+tcp=Xdisplay port=6000
+tcp=styx port=6666
+tcp=mpeg port=6667
+tcp=rstyx port=6668
+tcp=infdb port=6669
+tcp=infsigner port=6671
+tcp=infcsigner port=6672
+tcp=inflogin port=6673
+tcp=bandt port=7330
+tcp=face port=32000
+tcp=ocpu port=17005
+tcp=ocpunote port=17006
+tcp=exportfs port=17007
+tcp=rexexec port=17009
+tcp=ncpu port=17010
+tcp=ncpunote port=17011
+tcp=cpu port=17013
+tcp=video port=17028
+tcp=vgen port=17029
+tcp=alefnslook port=17030
+tcp=411 port=17031
+tcp=flyboy port=17032
+
+il=echo port=7
+il=discard port=9
+il=chargen port=19
+il=whoami port=565
+il=ticket port=566
+il=challbox port=567
+il=ocpu port=17005
+il=ocpunote port=17006
+il=exportfs port=17007
+il=9fs port=17008
+il=rexexec port=17009
+il=ncpu port=17010
+il=ncpunote port=17011
+il=tcpu port=17012
+il=cpu port=17013
+il=fsauth port=17020
+il=rexauth port=17021
+il=changekey port=17022
+il=chal port=17023
+il=check port=17024
+il=juke port=17026
+il=video port=17028
+il=vgen port=17029
+il=alefnslook port=17030
+il=ramfs port=17031
+
+udp=echo port=7
+udp=tacacs port=49
+udp=tftp port=69
+udp=bootpc port=68
+udp=bootp port=67
+udp=dns port=53
+udp=ntp port=123
+udp=rip port=520
+udp=bfs port=2201
+udp=virgil port=2202
+udp=bandt2 port=7331
+
+gre=ppp port=34827
diff --git a/sys/lib/dist.old/pc/sub/compactdb b/sys/lib/dist.old/pc/sub/compactdb
new file mode 100755 (executable)
index 0000000..6033f7a
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/rc
+
+exec cat $*
+
diff --git a/sys/lib/dist.old/pc/sub/local b/sys/lib/dist.old/pc/sub/local
new file mode 100755 (executable)
index 0000000..ec278a4
--- /dev/null
@@ -0,0 +1,8 @@
+
+#
+#  files comprising the database, use as many as you like
+#
+database=
+       file=/lib/ndb/local
+       file=/lib/ndb/common
+
diff --git a/sys/lib/dist.old/pc/sub/mkdir b/sys/lib/dist.old/pc/sub/mkdir
new file mode 100755 (executable)
index 0000000..b4452b9
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/rc
+
+syscall create $1 0 020000000775 >[2]/dev/null
diff --git a/sys/lib/dist.old/pc/sub/ndist b/sys/lib/dist.old/pc/sub/ndist
new file mode 100755 (executable)
index 0000000..2916986
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/rc
+
+s=/n/dist/dist/replica
+serverroot=/n/dist
+serverlog=$s/plan9.log
+serverproto=$s/plan9.proto
+fn servermount { status='' } 
+fn serverupdate { status='' }
+
+fn clientmount { status='' }
+c=/n/kfs/dist/replica
+clientroot=/n/kfs
+clientproto=$c/plan9.proto
+clientdb=$c/client/plan9.db
+clientexclude=(dist/replica/client)
+clientlog=$c/client/plan9.log
diff --git a/sys/lib/dist.old/pc/sub/pci b/sys/lib/dist.old/pc/sub/pci
new file mode 100755 (executable)
index 0000000..c55d4b3
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/rc
+
+rfork n
+bind '#$' /mnt
+cat /mnt/pci/*ctl
diff --git a/sys/lib/dist.old/pc/sub/pwd b/sys/lib/dist.old/pc/sub/pwd
new file mode 100755 (executable)
index 0000000..f75568e
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/rc
+
+syscall -o fd2path 0 buf 1024 < . >[2]/dev/null
diff --git a/sys/lib/dist.old/pc/sub/ramfs b/sys/lib/dist.old/pc/sub/ramfs
new file mode 100755 (executable)
index 0000000..285cd87
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/rc
+
+exec boot/kfs RAMFS $*
+# kfs is bzfs
diff --git a/sys/lib/dist.old/pc/sub/sleep b/sys/lib/dist.old/pc/sub/sleep
new file mode 100755 (executable)
index 0000000..07e6bb8
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/rc
+
+if(! ~ $#* 1) {
+       echo 'usage: sleep n' >[1=2]
+       exit usage
+}
+
+syscall sleep $1^000 >/dev/null >[2]/dev/null
diff --git a/sys/lib/dist.old/pc/sub/termrc b/sys/lib/dist.old/pc/sub/termrc
new file mode 100755 (executable)
index 0000000..a194ee9
--- /dev/null
@@ -0,0 +1,121 @@
+#!/bin/rc
+
+if(~ $#debug 1 && ~ $debug yes)
+       flag x +
+if not
+       debug=0
+
+if(~ $debug yes) echo env...
+sysname=gnot
+font=/lib/font/bit/lucidasans/typelatin1.7.font
+
+for (i in '#P' '#f' '#m' '#t' '#v') {
+       if(~ $debug yes) echo bind $i
+       bind -a $i /dev >/dev/null >[2=1]
+}
+if(~ $debug yes) echo binddev done
+
+for(disk in /dev/sd??) {
+       if(test -f $disk/data && test -f $disk/ctl){
+               disk/fdisk -p $disk/data >$disk/ctl >[2]/dev/null
+#              if(~ $#nosddma 0)
+#                      echo dma on >$disk/ctl
+#              if(~ $#nosdrwm 0)
+#                      echo rwm on >$disk/ctl
+       }
+}
+
+for (i in /sys/log/*) {
+       if(~ $debug yes) echo bind $i
+       bind /dev/null $i
+}
+
+if(~ $debug yes) echo bindlog done
+
+bind -a '#l' /net >/dev/null >[2=1]
+
+dossrv
+boota:
+boota: # again, just in case a timeout made the earlier one fail
+cp /n/a:/plan9.ini /tmp/plan9.orig
+if(! ~ $cdboot yes){
+       pci >/n/a:/pci.txt >[2]/dev/null
+       cp /dev/kmesg /n/a:/boot.txt >[2]/dev/null
+}
+
+# restore a partial install
+if(test -f /n/a:/9inst.cnf)
+       cp /n/a:/9inst.cnf /tmp/vars
+
+# make vgadb easier to edit
+if(test -f /n/a:/vgadb)
+       cp /n/a:/vgadb /lib/vgadb
+
+aux/vmware
+
+# configure loopback device without touching /net/ndb
+{
+       echo bind loopback /dev/null
+       echo add 127.0.0.1 255.255.255.0 
+} >/net/ipifc/clone
+
+if(~ $#dmamode 0)
+       dmamode=ask
+if(~ $dmamode ask){
+       echo -n 'use DMA for ide drives[yes]: '
+       dmamode=`{read}
+       if(~ $#dmamode 0)
+               dmamode=yes
+}
+if(~ $dmamode yes)
+       for(i in /dev/sd*/ctl)
+               if(test -f $i)
+                       {echo dma on; echo rwm on >[2]/dev/null} >$i
+
+if(~ $installmode ask){
+       echo -n 'install mode is (text, graphics)[graphics]: '
+       installmode=`{read}
+       if(~ $#installmode 0)
+               installmode=graphics
+}
+if(~ $installmode text){
+       mouseport=()
+       vgasize=()
+       monitor=()
+}
+if not
+       installmode=graphics
+       
+if(~ $mouseport ask){
+       echo -n 'mouseport is (ps2, ps2intellimouse, 0, 1, 2)[ps2]: '
+       mouseport=`{read}
+       if(~ $#mouseport 0)
+               mouseport=ps2
+}
+if(~ $vgasize ask){
+       echo -n 'vgasize [640x480x8]: '
+       vgasize=`{read}
+       if(~ $#vgasize 0)
+               vgasize=640x480x8
+}
+if(~ $monitor ask){
+       echo -n 'monitor is [xga]: '
+       monitor=`{read}
+       if(~ $#monitor 0)
+               monitor=xga
+}
+if(~ $#mouseport 1) {
+       aux/mouse $mouseport
+       if(~ $#vgasize 1 && ! ~ $vgasize '') {
+               vgasize=`{echo $vgasize}
+               if(! ~ $cdboot yes)
+                       aux/vga -vip $vgasize >/n/a:/vgainfo.txt
+               sleep 2 # wait for floppy to finish
+               aux/vga -l $vgasize
+               if(! ~ $#novgaaccel 0)
+                       echo -n 'hwaccel off' >'#v/vgactl' >[2]/dev/null
+               if(! ~ $#novgablank 0)
+                       echo -n 'hwblank off' >'#v/vgactl' >[2]/dev/null
+       }
+}
+
diff --git a/sys/lib/dist.old/pc/sub/unmount b/sys/lib/dist.old/pc/sub/unmount
new file mode 100755 (executable)
index 0000000..0c736af
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/rc
+
+syscall unmount 0 $1 >[2]/dev/null
diff --git a/sys/lib/dist.old/pc/sub/users b/sys/lib/dist.old/pc/sub/users
new file mode 100755 (executable)
index 0000000..fd2edbe
--- /dev/null
@@ -0,0 +1,7 @@
+-1:adm:adm:
+0:none:none:
+1:tor:tor:
+2:glenda:glenda:
+10000:sys::
+10001:upas:upas:
+10002:bootes:bootes:
diff --git a/sys/lib/dist.old/pc/sub/vmware b/sys/lib/dist.old/pc/sub/vmware
new file mode 100755 (executable)
index 0000000..8b398c9
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/rc
+# vmware - if we're running in a vmware virtual machine, tweak set up
+if(aux/isvmware -s){
+       echo hwaccel off >'#v/vgactl'
+       echo -n off >'#P/i8253timerset'
+       for (ctl in '#S'/sd[C-H]?/ctl)
+               if (test -e $ctl && grep -s '^config .* dma ' $ctl &&
+                   ! grep -s '^config (848A|.* dma 00000000 )' $ctl)
+                       echo 'dma on' >$ctl
+}
diff --git a/sys/lib/dist.old/pc/subst/plan9.ini b/sys/lib/dist.old/pc/subst/plan9.ini
new file mode 100644 (file)
index 0000000..11a2435
--- /dev/null
@@ -0,0 +1,40 @@
+# config for initial cd booting
+
+[menu]
+menuitem=install, Install Plan 9 from this CD
+menuitem=cdboot, Boot Plan 9 from this CD
+# menuitem=debug, Boot Plan 9 from this CD and debug 9load
+
+[common]
+# very cautious settings to get started.
+# will defeat booting from usb devices.
+*nomp=1
+*nobiosload=1
+# *noahciload=1
+# *debugload=1
+*nodumpstack=1
+# this would disable ether and usb probing.
+# *nousbprobe=1
+# *noetherprobe=1
+partition=new
+mouseport=ask
+monitor=ask
+vgasize=ask
+dmamode=ask
+adisk=/dev/sdD0/cdboot
+cdboot=yes
+# console=0
+# baud=9600
+
+[install]
+nobootprompt=local!/boot/bzroot
+bootfile=sdD0!cdboot!9pcflop.gz
+
+[cdboot]
+bootargs=local!#S/sdD0/data
+bootfile=sdD0!cdboot!9pccd.gz
+
+# [debug]
+# bootargs=local!#S/sdD0/data
+# bootfile=sdD0!cdboot!9pccd.gz
+# *debugload=1
diff --git a/sys/lib/dist.old/setup b/sys/lib/dist.old/setup
new file mode 100755 (executable)
index 0000000..a1c381b
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/rc
+# setup - prep for the mkfile
+9fs sources
+9fs other
+9fs outfsother
+if (test -e /cfg/$sysname/config)
+       . /cfg/$sysname/config
+if not
+       outip=204.178.31.2
+import -c tcp!$outip!666 $dist/web.protect
diff --git a/sys/lib/dist/cdstub/.dummy b/sys/lib/dist/cdstub/.dummy
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/sys/lib/dist/cdstub/bootdisk.img b/sys/lib/dist/cdstub/bootdisk.img
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/sys/lib/dist/cmd/bargraph.c b/sys/lib/dist/cmd/bargraph.c
deleted file mode 100644 (file)
index f7a142e..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <bio.h>
-#include <event.h>
-
-enum {PNCTL=3};
-
-static char* rdenv(char*);
-int newwin(char*);
-Rectangle screenrect(void);
-
-int nokill;
-int textmode;
-char *title;
-
-Image *light;
-Image *dark;
-Image *text;
-
-void
-initcolor(void)
-{
-       text = display->black;
-       light = allocimagemix(display, DPalegreen, DWhite);
-       dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen);
-}
-
-Rectangle rbar;
-Point ptext;
-vlong n, d;
-int last;
-int lastp = -1;
-int first = 1;
-
-char backup[80];
-
-void
-drawbar(void)
-{
-       int i, j;
-       int p;
-       char buf[200], bar[100], *s;
-       static char lastbar[100];
-
-       if(n > d || n < 0 || d <= 0)
-               return;
-
-       i = (Dx(rbar)*n)/d;
-       p = (n*100LL)/d;
-
-       if(textmode){
-               bar[0] = '|';
-               for(j=0; j<i; j++)
-                       bar[j+1] = '#';
-               for(; j<60; j++)
-                       bar[j+1] = '-';
-               bar[61] = '|';
-               bar[62] = ' ';
-               sprint(bar+63, "%3d%% ", p);
-               for(i=0; bar[i]==lastbar[i] && bar[i]; i++)
-                       ;
-               memset(buf, '\b', strlen(lastbar)-i);
-               strcpy(buf+strlen(lastbar)-i, bar+i);
-               if(buf[0])
-                       write(1, buf, strlen(buf));
-               strcpy(lastbar, bar);
-               return;
-       }
-       
-       if(lastp == p && last == i)
-               return;
-
-       if(lastp != p){
-               sprint(buf, "%d%%", p);
-               
-               stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP);
-               lastp = p;
-       }
-
-       if(last != i){
-               draw(screen, Rect(rbar.min.x+last, rbar.min.y, rbar.min.x+i, rbar.max.y),
-                       dark, nil, ZP);
-               last = i;
-       }
-       flushimage(display, 1);
-}
-
-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);
-       border(screen, rbar, -2, dark, ZP);
-       last = 0;
-       lastp = -1;
-
-       drawbar();
-}
-
-void
-bar(Biobuf *b)
-{
-       char *p, *f[2];
-       Event e;
-       int k, die, parent, child;
-
-       parent = getpid();
-
-       die = 0;
-       if(textmode)
-               child = -1;
-       else
-       switch(child = rfork(RFMEM|RFPROC)) {
-       case 0:
-               sleep(1000);
-               while(!die && (k = eread(Ekeyboard|Emouse, &e))) {
-                       if(nokill==0 && k == Ekeyboard && (e.kbdc == 0x7F || e.kbdc == 0x03)) { /* del, ctl-c */
-                               die = 1;
-                               postnote(PNPROC, parent, "interrupt");
-                               _exits("interrupt");
-                       }
-               }
-               _exits(0);
-       }
-
-       while(!die && (p = Brdline(b, '\n'))) {
-               p[Blinelen(b)-1] = '\0';
-               if(tokenize(p, f, 2) != 2)
-                       continue;
-               n = strtoll(f[0], 0, 0);
-               d = strtoll(f[1], 0, 0);
-               drawbar();
-       }
-       postnote(PNCTL, child, "kill");
-}
-
-
-void
-usage(void)
-{
-       fprint(2, "usage: bargraph [-kt] [-w minx,miny,maxx,maxy] 'title'\n");
-       exits("usage");
-}
-
-void
-main(int argc, char **argv)
-{
-       Biobuf b;
-       char *p, *q;
-       int lfd;
-
-       p = "0,0,200,60";
-       
-       ARGBEGIN{
-       case 'w':
-               p = ARGF();
-               break;
-       case 't':
-               textmode = 1;
-               break;
-       case 'k':
-               nokill = 1;
-               break;
-       default:
-               usage();
-       }ARGEND;
-
-       if(argc != 1)
-               usage();
-
-       title = argv[0];
-
-       lfd = dup(0, -1);
-
-       while(q = strchr(p, ','))
-               *q = ' ';
-       Binit(&b, lfd, OREAD);
-       if(textmode || newwin(p) < 0){
-               textmode = 1;
-               rbar = Rect(0, 0, 60, 1);
-       }else{
-               initdraw(0, 0, "bar");
-               initcolor();
-               einit(Emouse|Ekeyboard);
-               eresized(0);
-       }
-       bar(&b);
-}
-
-
-/* all code below this line should be in the library, but is stolen from colors instead */
-static char*
-rdenv(char *name)
-{
-       char *v;
-       int fd, size;
-
-       fd = open(name, OREAD);
-       if(fd < 0)
-               return 0;
-       size = seek(fd, 0, 2);
-       v = malloc(size+1);
-       if(v == 0){
-               fprint(2, "%s: can't malloc: %r\n", argv0);
-               exits("no mem");
-       }
-       seek(fd, 0, 0);
-       read(fd, v, size);
-       v[size] = 0;
-       close(fd);
-       return v;
-}
-
-int
-newwin(char *win)
-{
-       char *srv, *mntsrv;
-       char spec[100];
-       int srvfd, cons, pid;
-
-       switch(rfork(RFFDG|RFPROC|RFNAMEG|RFENVG|RFNOTEG|RFNOWAIT)){
-       case -1:
-               fprint(2, "bargraph: can't fork: %r\n");
-               return -1;
-       case 0:
-               break;
-       default:
-               exits(0);
-       }
-
-       srv = rdenv("/env/wsys");
-       if(srv == 0){
-               mntsrv = rdenv("/mnt/term/env/wsys");
-               if(mntsrv == 0){
-                       fprint(2, "bargraph: can't find $wsys\n");
-                       return -1;
-               }
-               srv = malloc(strlen(mntsrv)+10);
-               sprint(srv, "/mnt/term%s", mntsrv);
-               free(mntsrv);
-               pid  = 0;                       /* can't send notes to remote processes! */
-       }else
-               pid = getpid();
-       USED(pid);
-       srvfd = open(srv, ORDWR);
-       free(srv);
-       if(srvfd == -1){
-               fprint(2, "bargraph: can't open %s: %r\n", srv);
-               return -1;
-       }
-       sprint(spec, "new -r %s", win);
-       if(mount(srvfd, -1, "/mnt/wsys", 0, spec) == -1){
-               fprint(2, "bargraph: can't mount /mnt/wsys: %r (spec=%s)\n", spec);
-               return -1;
-       }
-       close(srvfd);
-       unmount("/mnt/acme", "/dev");
-       bind("/mnt/wsys", "/dev", MBEFORE);
-       cons = open("/dev/cons", OREAD);
-       if(cons==-1){
-       NoCons:
-               fprint(2, "bargraph: can't open /dev/cons: %r");
-               return -1;
-       }
-       dup(cons, 0);
-       close(cons);
-       cons = open("/dev/cons", OWRITE);
-       if(cons==-1)
-               goto NoCons;
-       dup(cons, 1);
-       dup(cons, 2);
-       close(cons);
-//     wctlfd = open("/dev/wctl", OWRITE);
-       return 0;
-}
-
-Rectangle
-screenrect(void)
-{
-       int fd;
-       char buf[12*5];
-
-       fd = open("/dev/screen", OREAD);
-       if(fd == -1)
-               fd=open("/mnt/term/dev/screen", OREAD);
-       if(fd == -1){
-               fprint(2, "%s: can't open /dev/screen: %r\n", argv0);
-               exits("window read");
-       }
-       if(read(fd, buf, sizeof buf) != sizeof buf){
-               fprint(2, "%s: can't read /dev/screen: %r\n", argv0);
-               exits("screen read");
-       }
-       close(fd);
-       return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48));
-}
-
-int
-postnote(int group, int pid, char *note)
-{
-       char file[128];
-       int f, r;
-
-       switch(group) {
-       case PNPROC:
-               sprint(file, "/proc/%d/note", pid);
-               break;
-       case PNGROUP:
-               sprint(file, "/proc/%d/notepg", pid);
-               break;
-       case PNCTL:
-               sprint(file, "/proc/%d/ctl", pid);
-               break;
-       default:
-               return -1;
-       }
-
-       f = open(file, OWRITE);
-       if(f < 0)
-               return -1;
-
-       r = strlen(note);
-       if(write(f, note, r) != r) {
-               close(f);
-               return -1;
-       }
-       close(f);
-       return 0;
-}
diff --git a/sys/lib/dist/cmd/bflz.c b/sys/lib/dist/cmd/bflz.c
deleted file mode 100644 (file)
index 89cb361..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Extraordinarily brute force Lempel & Ziv-like
- * compressor.  The input file must fit in memory
- * during compression, and the output file will
- * be reconstructed in memory during decompression.
- * We search for large common sequences and use a
- * greedy algorithm to choose which sequence gets
- * compressed first.
- *
- * Files begin with "BLZ\n" and a 32-bit uncompressed file length.
- *
- * Output format is a series of blocks followed by
- * a raw data section.  Each block begins with a 32-bit big-endian
- * number.  The top bit is type and the next 31 bits
- * are uncompressed size.  Type is one of
- *     0 - use raw data for this length
- *     1 - a 32-bit offset follows
- * After the blocks come the raw data.  (The end of the blocks can be
- * noted by summing block lengths until you reach the file length.)
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-#define malloc sbrk
-
-int minrun = 16;
-int win = 16;
-ulong outn;
-int verbose;
-int mindist;
-
-enum { Prime = 16777213 };     /* smallest prime < 2^24 (so p*256+256 < 2^32) */
-enum { NOFF = 3 };
-
-Biobuf bout;
-ulong length;
-uchar *data;
-ulong sum32(ulong, void*, long);
-uchar *odat;
-int nodat;
-int nraw;
-int rawstart;
-int acct;
-int zlength;
-int maxchain;
-int maxrle[256];
-int nnew;
-
-typedef struct Node Node;
-struct Node {
-       Node *link;
-       ulong key;
-       ulong offset[NOFF];
-};
-
-Node *nodepool;
-int nnodepool;
-
-Node **hash;
-uint nhash;
-
-uint maxlen;
-uint maxsame;
-uint replacesame = 8*1024*1024;
-
-Node *freelist, **freeend;
-uint nalloc;
-
-Node*
-allocnode(void)
-{
-       int i;
-       Node *n;
-
-       if(nnodepool == 0){
-               nnodepool = 256*1024;
-               nodepool = malloc(sizeof(Node)*nnodepool);
-       }
-       if(freelist){
-               n = freelist;
-               freelist = n->link;
-               return n;
-       }
-       assert(nnodepool > 0);
-       nalloc++;
-       n = &nodepool[--nnodepool];
-       for(i=0; i<NOFF; i++)
-               n->offset[i] = -1;
-
-       return n;
-}
-
-void
-freenode(Node *n)
-{
-       if(freelist == nil)
-               freelist = n;
-       else
-               *freeend = n;
-       freeend = &n->link;
-       n->link = nil;
-}
-
-Node**
-llookup(ulong key)
-{
-       uint c;
-       Node **l, **top, *n;
-       
-       if(nhash == 0){
-               uint x;
-
-               x = length/8;
-               for(nhash=1; nhash<x; nhash<<=1)
-                       ;
-               hash = sbrk(sizeof(Node*)*nhash);
-       }
-
-       top = &hash[key&(nhash-1)];
-       c = 0;
-       for(l=top; *l; l=&(*l)->link){
-               c++;
-               if((*l)->key == key){
-                       /* move to front */
-                       n = *l;
-                       *l = n->link;
-                       n->link = *top;
-                       *top = n;
-                       return top;
-               }
-       }
-       if(c > maxlen)
-               maxlen = c;
-       return l;
-}
-
-Node*
-lookup(ulong key)
-{
-       return *llookup(key);
-}
-
-void
-insertnode(ulong key, ulong offset)
-{
-       int i;
-       Node *n, **l;
-
-       l = llookup(key);
-       if(*l == nil){
-               if(l==&hash[key&(nhash-1)])
-                       nnew++;
-               *l = allocnode();
-               (*l)->key = key;
-       }
-       n = *l;
-
-       /* add or replace last */
-       for(i=0; i<NOFF-1 && n->offset[i]!=-1; i++)
-               ;
-       n->offset[i] = offset;
-}
-
-void
-Bputint(Biobufhdr *b, int n)
-{
-       uchar p[4];
-
-       p[0] = n>>24;
-       p[1] = n>>16;
-       p[2] = n>>8;
-       p[3] = n;
-       Bwrite(b, p, 4);
-}
-
-void
-flushraw(void)
-{
-       if(nraw){
-               if(verbose)
-                       fprint(2, "Raw %d+%d\n", rawstart, nraw);
-               zlength += 4+nraw;
-               Bputint(&bout, (1<<31)|nraw);
-               memmove(odat+nodat, data+rawstart, nraw);
-               nodat += nraw;
-               nraw = 0;
-       }
-}
-
-int
-rawbyte(int i)
-{
-       assert(acct == i);
-       if(nraw == 0)
-               rawstart = i;
-       acct++;
-       nraw++;
-       return 1;
-}
-
-int
-refblock(int i, int len, int off)
-{
-       assert(acct == i);
-       acct += len;
-       if(nraw)
-               flushraw();
-       if(verbose)
-               fprint(2, "Copy %d+%d from %d\n", i, len, off);
-       Bputint(&bout, len);
-       Bputint(&bout, off);
-       zlength += 4+4;
-       return len;
-}
-
-int
-cmprun(uchar *a, uchar *b, int len)
-{
-       int i;
-
-       if(a==b)
-               return 0;
-       for(i=0; i<len && a[i]==b[i]; i++)
-               ;
-       return i;
-}
-
-int
-countrle(uchar *a)
-{
-       int i;
-
-       for(i=0; a[i]==a[0]; i++)
-               ;
-       return i;
-}
-
-void
-compress(void)
-{
-       int best, i, j, o, rle, run, maxrun, maxoff;
-       ulong sum;
-       Node *n;
-
-       sum = 0;
-       for(i=0; i<win && i<length; i++)
-               sum = (sum*256+data[i])%Prime;
-       for(i=0; i<length-win; ){
-               maxrun = 0;
-               maxoff = 0;
-               if(verbose)
-                       fprint(2, "look %.6lux\n", sum);
-               n = lookup(sum);
-               if(n){
-                       best = -1;
-                       for(o=0; o<NOFF; o++){
-                               if(n->offset[o] == -1)
-                                       break;
-                               run = cmprun(data+i, data+n->offset[o], length-i);
-                               if(run > maxrun && n->offset[o]+mindist < i){
-                                       maxrun = run;
-                                       maxoff = n->offset[o];
-                                       best = o;
-                               }
-                       }
-                       if(best > 0){
-                               o = n->offset[best];
-                               for(j=best; j>0; j--)
-                                       n->offset[j] = n->offset[j-1];
-                               n->offset[0] = o;
-                       }
-               }
-                               
-               if(maxrun >= minrun)
-                       j = i+refblock(i, maxrun, maxoff);
-               else
-                       j = i+rawbyte(i);
-               for(; i<j; i++){
-                       /* avoid huge chains from large runs of same byte */
-                       rle = countrle(data+i);
-                       if(rle<4)
-                               insertnode(sum, i);
-                       else if(rle>maxrle[data[i]]){
-                               maxrle[data[i]] = rle;
-                               insertnode(sum, i);
-                       }
-                       sum = (sum*256+data[i+win]) % Prime;
-                       sum = (sum + data[i]*outn) % Prime;
-               }
-       }
-       /* could do better here */
-       for(; i<length; i++)
-               rawbyte(i);
-       flushraw();
-}
-
-void
-usage(void)
-{
-       fprint(2, "usage: bflz [-n winsize] [file]\n");
-       exits("usage");
-}
-
-void
-main(int argc, char **argv)
-{
-       int fd, i, n;
-       char buf[10485760];
-
-       ARGBEGIN{
-       case 'd':
-               verbose = 1;
-               break;
-       case 's':
-               replacesame = atoi(EARGF(usage()));
-               break;
-       case 'm':
-               mindist = atoi(EARGF(usage()));
-               break;
-       case 'n':
-               win = atoi(EARGF(usage()));
-               minrun = win;
-               break;
-       default:
-               usage();
-       }ARGEND
-
-       switch(argc){
-       default:
-               usage();
-       case 0:
-               fd = 0;
-               break;
-       case 1:
-               if((fd = open(argv[0], OREAD)) < 0)
-                       sysfatal("open %s: %r", argv[0]);
-               break;
-       }
-
-       while((n = readn(fd, buf, sizeof buf)) > 0){
-               data = realloc(data, length+n);
-               if(data == nil)
-                       sysfatal("realloc: %r");
-               memmove(data+length, buf, n);
-               length += n;
-               if(n < sizeof buf)
-                       break;
-       }
-       odat = malloc(length);
-       if(odat == nil)
-               sysfatal("malloc: %r");
-
-       Binit(&bout, 1, OWRITE);
-       Bprint(&bout, "BLZ\n");
-       Bputint(&bout, length);
-       outn = 1;
-       for(i=0; i<win; i++)
-               outn = (outn * 256) % Prime;
-
-       if(verbose)
-               fprint(2, "256^%d = %.6lux\n", win, outn);
-       outn = Prime - outn;
-       if(verbose)
-               fprint(2, "outn = %.6lux\n", outn);
-
-       compress();
-       Bwrite(&bout, odat, nodat);
-       Bterm(&bout);
-       fprint(2, "brk %p\n", sbrk(1));
-       fprint(2, "%d nodes used; %d of %d hash slots used\n", nalloc, nnew, nhash);
-       exits(nil);     
-}
diff --git a/sys/lib/dist/cmd/bzfs/bzfs.h b/sys/lib/dist/cmd/bzfs/bzfs.h
deleted file mode 100644 (file)
index 1de291a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-int unbzip(int);
-void _unbzip(int, int);
-int unbflz(int);
-int xexpand(int);
-void *emalloc(ulong);
-void *erealloc(void*, ulong);
-char *estrdup(char*);
-
-void ramfsmain(int, char**);
-extern int chatty;
-void error(char*, ...);
diff --git a/sys/lib/dist/cmd/bzfs/mkext.c b/sys/lib/dist/cmd/bzfs/mkext.c
deleted file mode 100644 (file)
index 1fedd62..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * bzip2-based file system.
- * the file system itself is just a bzipped2 xzipped mkfs archive
- * prefixed with "bzfilesystem\n" and suffixed with
- * a kilobyte of zeros.
- *
- * changes to the file system are only kept in 
- * memory, not written back to the disk.
- *
- * this is intended for use on a floppy boot disk.
- * we assume the file is in the dos file system and
- * contiguous on the disk: finding it amounts to
- * looking at the beginning of each sector for 
- * "bzfilesystem\n".  then we pipe it through 
- * bunzip2 and store the files in a file tree in memory.
- * things are slightly complicated by the fact that
- * devfloppy requires reads to be on a 512-byte
- * boundary and be a multiple of 512 bytes; we
- * fork a process to relieve bunzip2 of this restriction.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <auth.h>
-#include <fcall.h>
-#include "bzfs.h"
-
-enum{
-       LEN     = 8*1024,
-       NFLDS   = 6,            /* filename, modes, uid, gid, mtime, bytes */
-};
-
-void   mkdirs(char*, char*);
-void   mkdir(char*, ulong, ulong, char*, char*);
-void   extract(char*, ulong, ulong, char*, char*, ulong);
-void   seekpast(ulong);
-void   error(char*, ...);
-void   warn(char*, ...);
-void   usage(void);
-char *mtpt;
-Biobufhdr bin;
-uchar  binbuf[2*LEN];
-
-void
-usage(void)
-{
-       fprint(2, "usage: bzfs [-m mtpt] [-s] [-f file] [-h]\n");
-       exits("usage");
-}
-
-/*
- * floppy disks can only be read on 512-byte 
- * boundaries and in 512 byte multiples.
- * feed one over a pipe to allow arbitrary reading.
- */
-char zero[512];
-int
-blockread(int in, char *first, int nfirst)
-{
-       int p[2], out, n, rv;
-       char blk[512];
-
-       if(pipe(p) < 0)
-               sysfatal("pipe: %r");
-       rv = p[0];
-       out = p[1];
-       switch(rfork(RFPROC|RFNOTEG|RFFDG)){
-       case -1:
-               sysfatal("fork: %r");
-       case 0:
-               close(rv);
-               break;
-       default:
-               close(in);
-               close(out);
-               return rv;
-       }
-
-       write(out, first, nfirst);
-       
-       while((n=read(in, blk, sizeof blk)) > 0){
-               if(write(out, blk, n) != n)
-                       break;
-               if(n == sizeof(blk) && memcmp(zero, blk, n) == n)
-                       break;
-       }
-       _exits(0);
-       return -1;
-}
-
-enum { NAMELEN = 28 };
-
-void
-main(int argc, char **argv)
-{
-       char *rargv[10];
-       int rargc;
-       char *fields[NFLDS], name[2*LEN], *p, *namep;
-       char uid[NAMELEN], gid[NAMELEN];
-       ulong mode, bytes, mtime;
-       char *file;
-       int i, n, stdin, fd, chatty;
-       char blk[512];
-
-       if(argc>1 && strcmp(argv[1], "RAMFS") == 0){
-               argv[1] = argv[0];
-               ramfsmain(argc-1, argv+1);
-               exits(nil);
-       }
-       if(argc>1 && strcmp(argv[1], "BUNZIP") == 0){
-               _unbzip(0, 1);
-               exits(nil);
-       }
-
-       rfork(RFNOTEG);
-       stdin = 0;
-       file = nil;
-       namep = name;
-       mtpt = "/root";
-       chatty = 0;
-       ARGBEGIN{
-       case 'd':
-               chatty = !chatty;
-               break;
-       case 'f':
-               file = ARGF();
-               break;
-       case 's':
-               stdin++;
-               break;
-       case 'm':
-               mtpt = ARGF();
-               break;
-       default:
-               usage();
-       }ARGEND
-
-       if(argc != 0)
-               usage();
-
-       if(file == nil) {
-               fprint(2, "must specify -f file\n");
-               usage();
-       }
-
-       if((fd = open(file, OREAD)) < 0) {
-               fprint(2, "cannot open \"%s\": %r\n", file);
-               exits("open");
-       }
-
-       rargv[0] = "ramfs";
-       rargc = 1;
-       if(stdin)
-               rargv[rargc++] = "-i";
-       rargv[rargc++] = "-m";
-       rargv[rargc++] = mtpt;
-       rargv[rargc] = nil;
-       ramfsmain(rargc, rargv);
-
-       if(1 || strstr(file, "disk")) { /* search for archive on block boundary */
-if(chatty) fprint(2, "searching for bz\n");
-               for(i=0;; i++){
-                       if((n = readn(fd, blk, sizeof blk)) != sizeof blk)
-                               sysfatal("read %d gets %d: %r\n", i, n);
-                       if(strncmp(blk, "bzfilesystem\n", 13) == 0)
-                               break;
-               }
-if(chatty) fprint(2, "found at %d\n", i);
-       }
-
-       if(chdir(mtpt) < 0)
-               error("chdir %s: %r", mtpt);
-
-       fd = unbflz(unbzip(blockread(fd, blk+13, sizeof(blk)-13)));
-
-       Binits(&bin, fd, OREAD, binbuf, sizeof binbuf);
-       while(p = Brdline(&bin, '\n')){
-               p[Blinelen(&bin)-1] = '\0';
-if(chatty) fprint(2, "%s\n", p);
-               if(strcmp(p, "end of archive") == 0){
-                       _exits(0);
-               }
-               if(getfields(p, fields, NFLDS, 0, " \t") != NFLDS){
-                       warn("too few fields in file header");
-                       continue;
-               }
-               strcpy(namep, fields[0]);
-               mode = strtoul(fields[1], 0, 8);
-               mtime = strtoul(fields[4], 0, 10);
-               bytes = strtoul(fields[5], 0, 10);
-               strncpy(uid, fields[2], NAMELEN);
-               strncpy(gid, fields[3], NAMELEN);
-               if(mode & DMDIR)
-                       mkdir(name, mode, mtime, uid, gid);
-               else
-                       extract(name, mode, mtime, uid, gid, bytes);
-       }
-       fprint(2, "premature end of archive\n");
-       exits("premature end of archive");
-}
-
-char buf[8192];
-
-int
-ffcreate(char *name, ulong mode, char *uid, char *gid, ulong mtime, int length)
-{
-       int fd, om;
-       Dir nd;
-
-       sprint(buf, "%s/%s", mtpt, name);
-       om = ORDWR;
-       if(mode&DMDIR)
-               om = OREAD;
-       if((fd = create(buf, om, (mode&DMDIR)|0666)) < 0)
-               error("create %s: %r", buf);
-
-       nulldir(&nd);
-       nd.mode = mode;
-       nd.uid = uid;
-       nd.gid = gid;
-       nd.mtime = mtime;
-       if(length)
-               nd.length = length;
-       if(dirfwstat(fd, &nd) < 0)      
-               error("fwstat %s: %r", buf);
-
-       return fd;
-}
-
-void
-mkdir(char *name, ulong mode, ulong mtime, char *uid, char *gid)
-{
-       close(ffcreate(name, mode, uid, gid, mtime, 0));
-}
-
-void
-extract(char *name, ulong mode, ulong mtime, char *uid, char *gid, ulong bytes)
-{
-       int fd, tot, n;
-
-       fd = ffcreate(name, mode, uid, gid, mtime, bytes);
-
-       for(tot = 0; tot < bytes; tot += n){
-               n = sizeof buf;
-               if(tot + n > bytes)
-                       n = bytes - tot;
-               n = Bread(&bin, buf, n);
-               if(n <= 0)
-                       error("premature eof reading %s", name);
-               if(write(fd, buf, n) != n)
-                       error("short write writing %s", name);
-       }
-       close(fd);
-}
-
-void
-error(char *fmt, ...)
-{
-       char buf[1024];
-       va_list arg;
-
-       sprint(buf, "%s: ", argv0);
-       va_start(arg, fmt);
-       vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
-       va_end(arg);
-       fprint(2, "%s\n", buf);
-       exits(0);
-}
-
-void
-warn(char *fmt, ...)
-{
-       char buf[1024];
-       va_list arg;
-
-       sprint(buf, "%s: ", argv0);
-       va_start(arg, fmt);
-       vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
-       va_end(arg);
-       fprint(2, "%s\n", buf);
-}
-
-int
-_efgfmt(Fmt*)
-{
-       return -1;
-}
diff --git a/sys/lib/dist/cmd/bzfs/mkfile b/sys/lib/dist/cmd/bzfs/mkfile
deleted file mode 100644 (file)
index df81b56..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-</$objtype/mkfile
-
-TARG=bzfs
-
-OFILES=\
-       mkext.$O\
-       oramfs.$O\
-       unbflz.$O\
-       unbzip.$O\
-
-HFILES=bzfs.h
-
-BIN=/sys/lib/dist/bin/$objtype
-LIB=/sys/src/cmd/bzip2/lib/libbzip2.a$O
-</sys/src/cmd/mkone
-
-CFLAGS=$CFLAGS -p -I/sys/src/cmd/bzip2/lib
-
-/sys/src/cmd/bzip2/lib/libbzip2.a$O:
-       @{cd /sys/src/cmd/bzip2/lib && mk}
diff --git a/sys/lib/dist/cmd/bzfs/oramfs.c b/sys/lib/dist/cmd/bzfs/oramfs.c
deleted file mode 100644 (file)
index cba0272..0000000
+++ /dev/null
@@ -1,927 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include "bzfs.h"
-
-/*
- * Rather than reading /adm/users, which is a lot of work for
- * a toy program, we assume all groups have the form
- *     NNN:user:user:
- * meaning that each user is the leader of his own group.
- */
-
-enum
-{
-       OPERM   = 0x3,          /* mask of all permission types in open mode */
-       Nram    = 512,
-       Maxsize = 512*1024*1024,
-       Maxfdata        = 8192,
-};
-
-typedef struct Fid Fid;
-typedef struct Ram Ram;
-
-struct Fid
-{
-       short   busy;
-       short   open;
-       short   rclose;
-       int     fid;
-       Fid     *next;
-       char    *user;
-       Ram     *ram;
-};
-
-struct Ram
-{
-       short   busy;
-       short   open;
-       long    parent;         /* index in Ram array */
-       Qid     qid;
-       long    perm;
-       char    *name;
-       ulong   atime;
-       ulong   mtime;
-       char    *user;
-       char    *group;
-       char    *muid;
-       char    *data;
-       long    ndata;
-};
-
-enum
-{
-       Pexec =         1,
-       Pwrite =        2,
-       Pread =         4,
-       Pother =        1,
-       Pgroup =        8,
-       Powner =        64,
-};
-
-ulong  path;           /* incremented for each new file */
-Fid    *fids;
-Ram    ram[Nram];
-int    nram;
-int    mfd[2];
-char   *user;
-uchar  mdata[IOHDRSZ+Maxfdata];
-uchar  rdata[Maxfdata];        /* buffer for data in reply */
-uchar statbuf[STATMAX];
-Fcall thdr;
-Fcall  rhdr;
-int    messagesize = sizeof mdata;
-
-Fid *  newfid(int);
-uint   ramstat(Ram*, uchar*, uint);
-void   io(void);
-void   *erealloc(void*, ulong);
-void   *emalloc(ulong);
-char   *estrdup(char*);
-void   ramfsusage(void);
-int    perm(Fid*, Ram*, int);
-char *atom(char*);
-
-char   *rflush(Fid*), *rversion(Fid*), *rauth(Fid*),
-       *rattach(Fid*), *rwalk(Fid*),
-       *ropen(Fid*), *rcreate(Fid*),
-       *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
-       *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
-
-char   *(*fcalls[])(Fid*) = {
-       [Tversion]      rversion,
-       [Tflush]        rflush,
-       [Tauth] rauth,
-       [Tattach]       rattach,
-       [Twalk]         rwalk,
-       [Topen]         ropen,
-       [Tcreate]       rcreate,
-       [Tread]         rread,
-       [Twrite]        rwrite,
-       [Tclunk]        rclunk,
-       [Tremove]       rremove,
-       [Tstat]         rstat,
-       [Twstat]        rwstat,
-};
-
-char   Eperm[] =       "permission denied";
-char   Enotdir[] =     "not a directory";
-char   Enoauth[] =     "no authentication in ramfs";
-char   Enotexist[] =   "file does not exist";
-char   Einuse[] =      "file in use";
-char   Eexist[] =      "file exists";
-char   Eisdir[] =      "file is a directory";
-char   Enotowner[] =   "not owner";
-char   Eisopen[] =     "file already open for I/O";
-char   Excl[] =        "exclusive use file already open";
-char   Ename[] =       "illegal name";
-char   Eversion[] =    "unknown 9P version";
-
-int debug;
-
-void
-notifyf(void *a, char *s)
-{
-       USED(a);
-       if(strncmp(s, "interrupt", 9) == 0)
-               noted(NCONT);
-       noted(NDFLT);
-}
-
-void
-ramfsmain(int argc, char *argv[])
-{
-       Ram *r;
-       char *defmnt;
-       int p[2];
-       char buf[32];
-       int fd, srvfd;
-       int stdio = 0;
-
-       srvfd = -1;
-       defmnt = "/tmp";
-       ARGBEGIN{
-       case 'D':
-               debug = 1;
-               break;
-       case 'i':               /* this is DIFFERENT from normal ramfs; use 1 for both for kernel */
-               defmnt = 0;
-               stdio = 1;
-               srvfd = 0;
-               mfd[0] = 1;
-               mfd[1] = 1;
-               break;
-       case 's':
-               defmnt = 0;
-               break;
-       case 'm':
-               defmnt = ARGF();
-               break;
-       default:
-               ramfsusage();
-       }ARGEND
-
-       if(!stdio){
-               if(pipe(p) < 0)
-                       error("pipe failed");
-               srvfd = p[1];
-               mfd[0] = p[0];
-               mfd[1] = p[0];
-               if(defmnt == 0){
-                       fd = create("#s/ramfs", OWRITE, 0666);
-                       if(fd < 0)
-                               error("create of /srv/ramfs failed");
-                       sprint(buf, "%d", p[1]);
-                       if(write(fd, buf, strlen(buf)) < 0)
-                               error("writing /srv/ramfs");
-               }
-       }
-
-       user = atom(getuser());
-       notify(notifyf);
-       nram = 1;
-       r = &ram[0];
-       r->busy = 1;
-       r->data = 0;
-       r->ndata = 0;
-       r->perm = DMDIR | 0775;
-       r->qid.type = QTDIR;
-       r->qid.path = 0LL;
-       r->qid.vers = 0;
-       r->parent = 0;
-       r->user = user;
-       r->group = user;
-       r->muid = user;
-       r->atime = time(0);
-       r->mtime = r->atime;
-       r->name = estrdup(".");
-
-       if(debug)
-               fmtinstall('F', fcallfmt);
-       switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
-       case -1:
-               error("fork");
-       case 0:
-               close(srvfd);
-               io();
-               break;
-       default:
-               close(mfd[0]);  /* don't deadlock if child fails */
-               if(defmnt && mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0)
-                       error("mount failed: %r");
-       }
-}
-
-char*
-rversion(Fid*)
-{
-       Fid *f;
-
-       for(f = fids; f; f = f->next)
-               if(f->busy)
-                       rclunk(f);
-       if(thdr.msize > sizeof mdata)
-               rhdr.msize = sizeof mdata;
-       else
-               rhdr.msize = thdr.msize;
-       messagesize = rhdr.msize;
-       if(strncmp(thdr.version, "9P2000", 6) != 0)
-               return Eversion;
-       rhdr.version = "9P2000";
-       return 0;
-}
-
-char*
-rauth(Fid*)
-{
-       return "ramfs: no authentication required";
-}
-
-char*
-rflush(Fid *f)
-{
-       USED(f);
-       return 0;
-}
-
-char*
-rattach(Fid *f)
-{
-       /* no authentication! */
-       f->busy = 1;
-       f->rclose = 0;
-       f->ram = &ram[0];
-       rhdr.qid = f->ram->qid;
-       if(thdr.uname[0])
-               f->user = atom(thdr.uname);
-       else
-               f->user = atom("none");
-       if(strcmp(user, "none") == 0)
-               user = f->user;
-       return 0;
-}
-
-char*
-clone(Fid *f, Fid **nf)
-{
-       if(f->open)
-               return Eisopen;
-       if(f->ram->busy == 0)
-               return Enotexist;
-       *nf = newfid(thdr.newfid);
-       (*nf)->busy = 1;
-       (*nf)->open = 0;
-       (*nf)->rclose = 0;
-       (*nf)->ram = f->ram;
-       (*nf)->user = f->user;  /* no ref count; the leakage is minor */
-       return 0;
-}
-
-char*
-rwalk(Fid *f)
-{
-       Ram *r, *fram;
-       char *name;
-       Ram *parent;
-       Fid *nf;
-       char *err;
-       ulong t;
-       int i;
-
-       err = nil;
-       nf = nil;
-       rhdr.nwqid = 0;
-       if(rhdr.newfid != rhdr.fid){
-               err = clone(f, &nf);
-               if(err)
-                       return err;
-               f = nf; /* walk the new fid */
-       }
-       fram = f->ram;
-       if(thdr.nwname > 0){
-               t = time(0);
-               for(i=0; i<thdr.nwname && i<MAXWELEM; i++){
-                       if((fram->qid.type & QTDIR) == 0){
-                               err = Enotdir;
-                               break;
-                       }
-                       if(fram->busy == 0){
-                               err = Enotexist;
-                               break;
-                       }
-                       fram->atime = t;
-                       name = thdr.wname[i];
-                       if(strcmp(name, ".") == 0){
-    Found:
-                               rhdr.nwqid++;
-                               rhdr.wqid[i] = fram->qid;
-                               continue;
-                       }
-                       parent = &ram[fram->parent];
-#ifdef CHECKS
-                       if(!perm(f, parent, Pexec)){
-                               err = Eperm;
-                               break;
-                       }
-#endif
-                       if(strcmp(name, "..") == 0){
-                               fram = parent;
-                               goto Found;
-                       }
-                       for(r=ram; r < &ram[nram]; r++)
-                               if(r->busy && r->parent==fram-ram && strcmp(name, r->name)==0){
-                                       fram = r;
-                                       goto Found;
-                               }
-                       break;
-               }
-               if(i==0 && err == nil)
-                       err = Enotexist;
-       }
-       if(nf != nil && (err!=nil || rhdr.nwqid<thdr.nwname)){
-               /* clunk the new fid, which is the one we walked */
-               f->busy = 0;
-               f->ram = nil;
-       }
-       if(rhdr.nwqid == thdr.nwname)   /* update the fid after a successful walk */
-               f->ram = fram;
-       return err;
-}
-
-char *
-ropen(Fid *f)
-{
-       Ram *r;
-       int mode, trunc;
-
-       if(f->open)
-               return Eisopen;
-       r = f->ram;
-       if(r->busy == 0)
-               return Enotexist;
-       if(r->perm & DMEXCL)
-               if(r->open)
-                       return Excl;
-       mode = thdr.mode;
-       if(r->qid.type & QTDIR){
-               if(mode != OREAD)
-                       return Eperm;
-               rhdr.qid = r->qid;
-               return 0;
-       }
-       if(mode & ORCLOSE){
-               /* can't remove root; must be able to write parent */
-               if(r->qid.path==0 || !perm(f, &ram[r->parent], Pwrite))
-                       return Eperm;
-               f->rclose = 1;
-       }
-       trunc = mode & OTRUNC;
-       mode &= OPERM;
-       if(mode==OWRITE || mode==ORDWR || trunc)
-               if(!perm(f, r, Pwrite))
-                       return Eperm;
-       if(mode==OREAD || mode==ORDWR)
-               if(!perm(f, r, Pread))
-                       return Eperm;
-       if(mode==OEXEC)
-               if(!perm(f, r, Pexec))
-                       return Eperm;
-       if(trunc && (r->perm&DMAPPEND)==0){
-               r->ndata = 0;
-               if(r->data)
-                       free(r->data);
-               r->data = 0;
-               r->qid.vers++;
-       }
-       rhdr.qid = r->qid;
-       rhdr.iounit = messagesize-IOHDRSZ;
-       f->open = 1;
-       r->open++;
-       return 0;
-}
-
-char *
-rcreate(Fid *f)
-{
-       Ram *r;
-       char *name;
-       long parent, prm;
-
-       if(f->open)
-               return Eisopen;
-       if(f->ram->busy == 0)
-               return Enotexist;
-       parent = f->ram - ram;
-       if((f->ram->qid.type&QTDIR) == 0)
-               return Enotdir;
-       /* must be able to write parent */
-#ifdef CHECKS
-       if(!perm(f, f->ram, Pwrite))
-               return Eperm;
-#endif
-       prm = thdr.perm;
-       name = thdr.name;
-       if(strcmp(name, ".")==0 || strcmp(name, "..")==0)
-               return Ename;
-       for(r=ram; r<&ram[nram]; r++)
-               if(r->busy && parent==r->parent)
-               if(strcmp((char*)name, r->name)==0)
-                       return Einuse;
-       for(r=ram; r->busy; r++)
-               if(r == &ram[Nram-1])
-                       return "no free ram resources";
-       r->busy = 1;
-       r->qid.path = ++path;
-       r->qid.vers = 0;
-       if(prm & DMDIR)
-               r->qid.type |= QTDIR;
-       r->parent = parent;
-       free(r->name);
-       r->name = estrdup(name);
-       r->user = f->user;
-       r->group = f->ram->group;
-       r->muid = f->ram->muid;
-       if(prm & DMDIR)
-               prm = (prm&~0777) | (f->ram->perm&prm&0777);
-       else
-               prm = (prm&(~0777|0111)) | (f->ram->perm&prm&0666);
-       r->perm = prm;
-       r->ndata = 0;
-       if(r-ram >= nram)
-               nram = r - ram + 1;
-       r->atime = time(0);
-       r->mtime = r->atime;
-       f->ram->mtime = r->atime;
-       f->ram = r;
-       rhdr.qid = r->qid;
-       rhdr.iounit = messagesize-IOHDRSZ;
-       f->open = 1;
-       if(thdr.mode & ORCLOSE)
-               f->rclose = 1;
-       r->open++;
-       return 0;
-}
-
-char*
-rread(Fid *f)
-{
-       Ram *r;
-       uchar *buf;
-       long off;
-       int n, m, cnt;
-
-       if(f->ram->busy == 0)
-               return Enotexist;
-       n = 0;
-       rhdr.count = 0;
-       off = thdr.offset;
-       buf = rdata;
-       cnt = thdr.count;
-       if(cnt > messagesize)   /* shouldn't happen, anyway */
-               cnt = messagesize;
-       if(f->ram->qid.type & QTDIR){
-               for(r=ram+1; off > 0; r++){
-                       if(r->busy && r->parent==f->ram-ram)
-                               off -= ramstat(r, statbuf, sizeof statbuf);
-                       if(r == &ram[nram-1])
-                               return 0;
-               }
-               for(; r<&ram[nram] && n < cnt; r++){
-                       if(!r->busy || r->parent!=f->ram-ram)
-                               continue;
-                       m = ramstat(r, buf+n, cnt-n);
-                       if(m == 0)
-                               break;
-                       n += m;
-               }
-               rhdr.data = (char*)rdata;
-               rhdr.count = n;
-               return 0;
-       }
-       r = f->ram;
-       if(off >= r->ndata)
-               return 0;
-       r->atime = time(0);
-       n = cnt;
-       if(off+n > r->ndata)
-               n = r->ndata - off;
-       rhdr.data = r->data+off;
-       rhdr.count = n;
-       return 0;
-}
-
-char*
-rwrite(Fid *f)
-{
-       Ram *r;
-       ulong off;
-       int cnt;
-
-       r = f->ram;
-       if(r->busy == 0)
-               return Enotexist;
-       off = thdr.offset;
-       if(r->perm & DMAPPEND)
-               off = r->ndata;
-       cnt = thdr.count;
-       if(r->qid.type & QTDIR)
-               return Eisdir;
-       if(off+cnt >= Maxsize)          /* sanity check */
-               return "write too big";
-       if(off+cnt > r->ndata)
-               r->data = erealloc(r->data, off+cnt);
-       if(off > r->ndata)
-               memset(r->data+r->ndata, 0, off-r->ndata);
-       if(off+cnt > r->ndata)
-               r->ndata = off+cnt;
-       memmove(r->data+off, thdr.data, cnt);
-       r->qid.vers++;
-       r->mtime = time(0);
-       rhdr.count = cnt;
-       return 0;
-}
-
-void
-realremove(Ram *r)
-{
-       r->ndata = 0;
-       if(r->data)
-               free(r->data);
-       r->data = 0;
-       r->parent = 0;
-       memset(&r->qid, 0, sizeof r->qid);
-       free(r->name);
-       r->name = nil;
-       r->busy = 0;
-}
-
-char *
-rclunk(Fid *f)
-{
-       if(f->open)
-               f->ram->open--;
-       if(f->rclose)
-               realremove(f->ram);
-       f->busy = 0;
-       f->open = 0;
-       f->ram = 0;
-       return 0;
-}
-
-char *
-rremove(Fid *f)
-{
-       Ram *r;
-
-       if(f->open)
-               f->ram->open--;
-       f->busy = 0;
-       f->open = 0;
-       r = f->ram;
-       f->ram = 0;
-#ifdef CHECKS
-       if(r->qid.path == 0 || !perm(f, &ram[r->parent], Pwrite))
-               return Eperm;
-#endif
-       ram[r->parent].mtime = time(0);
-       realremove(r);
-       return 0;
-}
-
-char *
-rstat(Fid *f)
-{
-       if(f->ram->busy == 0)
-               return Enotexist;
-       rhdr.nstat = ramstat(f->ram, statbuf, sizeof statbuf);
-       rhdr.stat = statbuf;
-       return 0;
-}
-
-char *
-rwstat(Fid *f)
-{
-       Ram *r, *s;
-       Dir dir;
-
-       if(f->ram->busy == 0)
-               return Enotexist;
-       convM2D(thdr.stat, thdr.nstat, &dir, (char*)statbuf);
-       r = f->ram;
-
-       /*
-        * To change length, must have write permission on file.
-        */
-#ifdef CHECKS
-       if(dir.length!=~0 && dir.length!=r->ndata){
-               if(!perm(f, r, Pwrite))
-                       return Eperm;
-       }
-#endif
-
-       /*
-        * To change name, must have write permission in parent
-        * and name must be unique.
-        */
-       if(dir.name[0]!='\0' && strcmp(dir.name, r->name)!=0){
-#ifdef CHECKS
-               if(!perm(f, &ram[r->parent], Pwrite))
-                       return Eperm;
-#endif
-               for(s=ram; s<&ram[nram]; s++)
-                       if(s->busy && s->parent==r->parent)
-                       if(strcmp(dir.name, s->name)==0)
-                               return Eexist;
-       }
-
-#ifdef OWNERS
-       /*
-        * To change mode, must be owner or group leader.
-        * Because of lack of users file, leader=>group itself.
-        */
-       if(dir.mode!=~0 && r->perm!=dir.mode){
-               if(strcmp(f->user, r->user) != 0)
-               if(strcmp(f->user, r->group) != 0)
-                       return Enotowner;
-       }
-
-       /*
-        * To change group, must be owner and member of new group,
-        * or leader of current group and leader of new group.
-        * Second case cannot happen, but we check anyway.
-        */
-       if(dir.gid[0]!='\0' && strcmp(r->group, dir.gid)!=0){
-               if(strcmp(f->user, r->user) == 0)
-               if(strcmp(f->user, dir.gid) == 0)
-                       goto ok;
-               if(strcmp(f->user, r->group) == 0)
-               if(strcmp(f->user, dir.gid) == 0)
-                       goto ok;
-               return Enotowner;
-               ok:;
-       }
-#endif
-
-       /* all ok; do it */
-       if(dir.mode != ~0){
-               dir.mode &= ~DMDIR;     /* cannot change dir bit */
-               dir.mode |= r->perm&DMDIR;
-               r->perm = dir.mode;
-       }
-       if(dir.name[0] != '\0'){
-               free(r->name);
-               r->name = estrdup(dir.name);
-       }
-       if(dir.gid[0] != '\0')
-               r->group = atom(dir.gid);
-
-       if(dir.uid[0] != '\0')
-               r->user = atom(dir.uid);
-
-       if(dir.length!=~0 && dir.length!=r->ndata){
-               r->data = erealloc(r->data, dir.length);
-               if(r->ndata < dir.length)
-                       memset(r->data+r->ndata, 0, dir.length-r->ndata);
-               r->ndata = dir.length;
-       }
-
-       if(dir.mtime != ~0)
-               r->mtime = dir.mtime;
-
-       ram[r->parent].mtime = time(0);
-       return 0;
-}
-
-uint
-ramstat(Ram *r, uchar *buf, uint nbuf)
-{
-       Dir dir;
-
-       dir.name = r->name;
-       dir.qid = r->qid;
-       dir.mode = r->perm;
-       dir.length = r->ndata;
-       dir.uid = r->user;
-       dir.gid = r->group;
-       dir.muid = r->muid;
-       dir.atime = r->atime;
-       dir.mtime = r->mtime;
-       return convD2M(&dir, buf, nbuf);
-}
-
-Fid *
-newfid(int fid)
-{
-       Fid *f, *ff;
-
-       ff = 0;
-       for(f = fids; f; f = f->next)
-               if(f->fid == fid)
-                       return f;
-               else if(!ff && !f->busy)
-                       ff = f;
-       if(ff){
-               ff->fid = fid;
-               return ff;
-       }
-       f = emalloc(sizeof *f);
-       f->ram = nil;
-       f->fid = fid;
-       f->next = fids;
-       fids = f;
-       return f;
-}
-
-void
-io(void)
-{
-       char *err;
-       int n, pid;
-
-       pid = getpid();
-
-       for(;;){
-               /*
-                * reading from a pipe or a network device
-                * will give an error after a few eof reads.
-                * however, we cannot tell the difference
-                * between a zero-length read and an interrupt
-                * on the processes writing to us,
-                * so we wait for the error.
-                */
-               n = read9pmsg(mfd[0], mdata, messagesize);
-               if(n < 0)
-                       error("mount read: %r");
-               if(n == 0)
-                       continue;
-               if(convM2S(mdata, n, &thdr) == 0)
-                       continue;
-
-               if(debug)
-                       fprint(2, "ramfs %d:<-%F\n", pid, &thdr);
-
-               if(!fcalls[thdr.type])
-                       err = "bad fcall type";
-               else
-                       err = (*fcalls[thdr.type])(newfid(thdr.fid));
-               if(err){
-                       rhdr.type = Rerror;
-                       rhdr.ename = err;
-               }else{
-                       rhdr.type = thdr.type + 1;
-                       rhdr.fid = thdr.fid;
-               }
-               rhdr.tag = thdr.tag;
-               if(debug)
-                       fprint(2, "ramfs %d:->%F\n", pid, &rhdr);/**/
-               n = convS2M(&rhdr, mdata, messagesize);
-               if(n == 0)
-                       error("convS2M error on write");
-               if(write(mfd[1], mdata, n) != n)
-                       error("mount write");
-       }
-}
-
-int
-perm(Fid *f, Ram *r, int p)
-{
-       if((p*Pother) & r->perm)
-               return 1;
-       if(strcmp(f->user, r->group)==0 && ((p*Pgroup) & r->perm))
-               return 1;
-       if(strcmp(f->user, r->user)==0 && ((p*Powner) & r->perm))
-               return 1;
-       return 0;
-}
-
-void *
-emalloc(ulong n)
-{
-       void *p;
-
-       p = malloc(n);
-       if(!p)
-               error("out of memory");
-       memset(p, 0, n);
-       return p;
-}
-
-void *
-erealloc(void *p, ulong n)
-{
-       p = realloc(p, n);
-       if(!p)
-               error("out of memory");
-       return p;
-}
-
-char *
-estrdup(char *q)
-{
-       char *p;
-       int n;
-
-       n = strlen(q)+1;
-       p = malloc(n);
-       if(!p)
-               error("out of memory");
-       memmove(p, q, n);
-       return p;
-}
-
-void
-ramfsusage(void)
-{
-       fprint(2, "usage: %s [-is] [-m mountpoint]\n", argv0);
-       exits("usage");
-}
-
-/*
- *     Custom allocators to avoid malloc overheads on small objects.
- *     We never free these.  (See below.)
- */
-typedef struct Stringtab       Stringtab;
-struct Stringtab {
-       Stringtab *link;
-       char *str;
-};
-static Stringtab*
-taballoc(void)
-{
-       static Stringtab *t;
-       static uint nt;
-
-       if(nt == 0){
-               t = malloc(64*sizeof(Stringtab));
-               if(t == 0)
-                       sysfatal("out of memory");
-               nt = 64;
-       }
-       nt--;
-       return t++;
-}
-
-static char*
-xstrdup(char *s)
-{
-       char *r;
-       int len;
-       static char *t;
-       static int nt;
-
-       len = strlen(s)+1;
-       if(len >= 8192)
-               sysfatal("strdup big string");
-
-       if(nt < len){
-               t = malloc(8192);
-               if(t == 0)
-                       sysfatal("out of memory");
-               nt = 8192;
-       }
-       r = t;
-       t += len;
-       nt -= len;
-       strcpy(r, s);
-       return r;
-}
-
-/*
- *     Return a uniquely allocated copy of a string.
- *     Don't free these -- they stay in the table for the 
- *     next caller who wants that particular string.
- *     String comparison can be done with pointer comparison 
- *     if you know both strings are atoms.
- */
-static Stringtab *stab[1024];
-
-static uint
-hash(char *s)
-{
-       uint h;
-       uchar *p;
-
-       h = 0;
-       for(p=(uchar*)s; *p; p++)
-               h = h*37 + *p;
-       return h;
-}
-
-char*
-atom(char *str)
-{
-       uint h;
-       Stringtab *tab;
-       
-       h = hash(str) % nelem(stab);
-       for(tab=stab[h]; tab; tab=tab->link)
-               if(strcmp(str, tab->str) == 0)
-                       return tab->str;
-
-       tab = taballoc();
-       tab->str = xstrdup(str);
-       tab->link = stab[h];
-       stab[h] = tab;
-       return tab->str;
-}
diff --git a/sys/lib/dist/cmd/bzfs/unbflz.c b/sys/lib/dist/cmd/bzfs/unbflz.c
deleted file mode 100644 (file)
index 661d65e..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include "bzfs.h"
-
-int
-Bgetint(Biobuf *b)
-{
-       uchar p[4];
-
-       if(Bread(b, p, 4) != 4)
-               sysfatal("short read");
-       return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
-}
-
-/*
- * memmove but make sure overlap works properly.
- */
-void
-copy(uchar *dst, uchar *src, int n)
-{
-       while(n-- > 0)
-               *dst++ = *src++;
-}
-
-int
-unbflz(int in)
-{
-       int rv, out, p[2];
-       Biobuf *b, bin;
-       char buf[5];
-       uchar *data;
-       int i, j, length, n, m, o, sum;
-       ulong *blk;
-       int nblk, mblk;
-
-       if(pipe(p) < 0)
-               sysfatal("pipe: %r");
-
-       rv = p[0];
-       out = p[1];
-       switch(rfork(RFPROC|RFFDG|RFNOTEG|RFMEM)){
-       case -1:
-               sysfatal("fork: %r");
-       case 0:
-               close(rv);
-               break;
-       default:
-               close(in);
-               close(out);
-               return rv;
-       }
-
-       Binit(&bin, in, OREAD);
-       b = &bin;
-
-       if(Bread(b, buf, 4) != 4)
-               sysfatal("short read");
-
-       if(memcmp(buf, "BLZ\n", 4) != 0)
-               sysfatal("bad header");
-
-       length = Bgetint(b);
-       data = malloc(length);
-       if(data == nil)
-               sysfatal("out of memory");
-       sum = 0;
-       nblk = 0;
-       mblk = 0;
-       blk = nil;
-       while(sum < length){
-               if(nblk>=mblk){
-                       mblk += 16384;
-                       blk = realloc(blk, (mblk+1)*sizeof(blk[0]));
-                       if(blk == nil)
-                               sysfatal("out of memory");
-               }
-               n = Bgetint(b);
-               blk[nblk++] = n;
-               if(n&(1<<31))
-                       n &= ~(1<<31);
-               else
-                       blk[nblk++] = Bgetint(b);
-               sum += n;
-       }
-       if(sum != length)
-               sysfatal("bad compressed data %d %d", sum, length);
-       i = 0;
-       j = 0;
-       while(i < length){
-               assert(j < nblk);
-               n = blk[j++];
-               if(n&(1<<31)){
-                       n &= ~(1<<31);
-                       if((m=Bread(b, data+i, n)) != n)
-                               sysfatal("short read %d %d", n, m);
-               }else{
-                       o = blk[j++];
-                       copy(data+i, data+o, n);
-               }
-               i += n;
-       }
-       write(out, data, length);
-       close(in);
-       close(out);
-       _exits(0);
-       return -1;
-}
diff --git a/sys/lib/dist/cmd/bzfs/unbzip.c b/sys/lib/dist/cmd/bzfs/unbzip.c
deleted file mode 100644 (file)
index 070e7ba..0000000
+++ /dev/null
@@ -1,861 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include "bzfs.h"
-
-/*
- * THIS FILE IS NOT IDENTICAL TO THE ORIGINAL
- * FROM THE BZIP2 DISTRIBUTION.
- *
- * It has been modified, mainly to break the library
- * into smaller pieces.
- *
- * Russ Cox
- * rsc@plan9.bell-labs.com
- * July 2000
- */
-
-/*---------------------------------------------*/
-/*--
-  Place a 1 beside your platform, and 0 elsewhere.
-  Attempts to autosniff this even if you don't.
---*/
-
-
-/*--
-  Plan 9 from Bell Labs
---*/
-#define BZ_PLAN9     1
-#define BZ_UNIX 0
-
-#define exit(x) exits((x) ? "whoops" : nil)
-#define size_t ulong
-
-#ifdef __GNUC__
-#   define NORETURN __attribute__ ((noreturn))
-#else
-#   define NORETURN /**/
-#endif
-
-/*--
-  Some more stuff for all platforms :-)
-  This might have to get moved into the platform-specific
-  header files if we encounter a machine with different sizes.
---*/
-
-typedef char            Char;
-typedef unsigned char   Bool;
-typedef unsigned char   UChar;
-typedef int             Int32;
-typedef unsigned int    UInt32;
-typedef short           Int16;
-typedef unsigned short  UInt16;
-                                       
-#define True  ((Bool)1)
-#define False ((Bool)0)
-
-/*--
-  IntNative is your platform's `native' int size.
-  Only here to avoid probs with 64-bit platforms.
---*/
-typedef int IntNative;
-
-#include "bzfs.h"
-#include "bzlib.h"
-#include "bzlib_private.h"
-
-static int
-bunzip(int ofd, char *ofile, Biobuf *bin)
-{
-       int e, n, done, onemore;
-       char buf[8192];
-       char obuf[8192];
-       Biobuf bout;
-       bz_stream strm;
-
-       USED(ofile);
-
-       memset(&strm, 0, sizeof strm);
-       BZ2_bzDecompressInit(&strm, 0, 0);
-
-       strm.next_in = buf;
-       strm.avail_in = 0;
-       strm.next_out = obuf;
-       strm.avail_out = sizeof obuf;
-
-       done = 0;
-       Binit(&bout, ofd, OWRITE);
-
-       /*
-        * onemore is a crummy hack to go 'round the loop
-        * once after we finish, to flush the output buffer.
-        */
-       onemore = 1;
-       SET(e);
-       do {
-               if(!done && strm.avail_in < sizeof buf) {
-                       if(strm.avail_in)
-                               memmove(buf, strm.next_in, strm.avail_in);
-                       
-                       n = Bread(bin, buf+strm.avail_in, sizeof(buf)-strm.avail_in);
-                       if(n <= 0)
-                               done = 1;
-                       else
-                               strm.avail_in += n;
-                       strm.next_in = buf;
-               }
-               if(strm.avail_out < sizeof obuf) {
-                       Bwrite(&bout, obuf, sizeof(obuf)-strm.avail_out);
-                       strm.next_out = obuf;
-                       strm.avail_out = sizeof obuf;
-               }
-
-               if(onemore == 0)
-                       break;
-       } while((e=BZ2_bzDecompress(&strm)) == BZ_OK || onemore--);
-
-       if(e != BZ_STREAM_END) {
-               fprint(2, "bunzip2: decompress failed\n");
-               return 0;
-       }
-
-       if(BZ2_bzDecompressEnd(&strm) != BZ_OK) {
-               fprint(2, "bunzip2: decompress end failed (can't happen)\n");
-               return 0;
-       }
-
-       Bterm(&bout);
-
-       return 1;
-}
-
-void
-_unbzip(int in, int out)
-{
-       Biobuf bin;
-
-       Binit(&bin, in, OREAD);
-       if(bunzip(out, nil, &bin) != 1) {
-               fprint(2, "bunzip2 failed\n");
-               _exits("bunzip2");
-       }
-}
-
-int
-unbzip(int in)
-{
-       int rv, out, p[2];
-
-       if(pipe(p) < 0)
-               sysfatal("pipe: %r");
-
-       rv = p[0];
-       out = p[1];
-       switch(rfork(RFPROC|RFFDG|RFNOTEG|RFMEM)){
-       case -1:
-               sysfatal("fork: %r");
-       case 0:
-               close(rv);
-               break;
-       default:
-               close(in);
-               close(out);
-               return rv;
-       }
-
-       _unbzip(in, out);
-       _exits(0);
-       return -1;      /* not reached */
-}
-
-int bz_config_ok ( void )
-{
-   if (sizeof(int)   != 4) return 0;
-   if (sizeof(short) != 2) return 0;
-   if (sizeof(char)  != 1) return 0;
-   return 1;
-}
-
-void* default_bzalloc(void *o, int items, int size)
-{
-       USED(o);
-       return sbrk(items*size);
-}
-
-void default_bzfree(void*, void*)
-{
-}
-
-void
-bz_internal_error(int)
-{
-       abort();
-}
-
-/*-------------------------------------------------------------*/
-/*--- Decompression machinery                               ---*/
-/*---                                          decompress.c ---*/
-/*-------------------------------------------------------------*/
-
-/*--
-  This file is a part of bzip2 and/or libbzip2, a program and
-  library for lossless, block-sorting data compression.
-
-  Copyright (C) 1996-2000 Julian R Seward.  All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  1. Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-
-  2. The origin of this software must not be misrepresented; you must 
-     not claim that you wrote the original software.  If you use this 
-     software in a product, an acknowledgment in the product 
-     documentation would be appreciated but is not required.
-
-  3. Altered source versions must be plainly marked as such, and must
-     not be misrepresented as being the original software.
-
-  4. The name of the author may not be used to endorse or promote 
-     products derived from this software without specific prior written 
-     permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
-  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-  Julian Seward, Cambridge, UK.
-  jseward@acm.org
-  bzip2/libbzip2 version 1.0 of 21 March 2000
-
-  This program is based on (at least) the work of:
-     Mike Burrows
-     David Wheeler
-     Peter Fenwick
-     Alistair Moffat
-     Radford Neal
-     Ian H. Witten
-     Robert Sedgewick
-     Jon L. Bentley
-
-  For more information on these sources, see the manual.
---*/
-
-
-
-/*---------------------------------------------------*/
-static
-void makeMaps_d ( DState* s )
-{
-   Int32 i;
-   s->nInUse = 0;
-   for (i = 0; i < 256; i++)
-      if (s->inUse[i]) {
-         s->seqToUnseq[s->nInUse] = i;
-         s->nInUse++;
-      }
-}
-
-
-/*---------------------------------------------------*/
-#define RETURN(rrr)                               \
-   { retVal = rrr; goto save_state_and_return; };
-
-#define GET_BITS(lll,vvv,nnn)                     \
-       case lll: \
-               { int x; if((retVal = getbits(s, lll, &x, nnn)) != 99) \
-                       goto save_state_and_return; vvv=x; }\
-
-int
-getbits(DState *s, int lll, int *vvv, int nnn)
-{
-       s->state = lll;
-       
-       for(;;) {
-               if (s->bsLive >= nnn) {
-                       UInt32 v;
-                       v = (s->bsBuff >>
-                                (s->bsLive-nnn)) & ((1 << nnn)-1);
-                       s->bsLive -= nnn;
-                       *vvv = v;
-                       return 99;
-               }
-               if (s->strm->avail_in == 0) return BZ_OK;
-               s->bsBuff
-                       = (s->bsBuff << 8) |
-                         ((UInt32)
-                                 (*((UChar*)(s->strm->next_in))));
-               s->bsLive += 8;
-               s->strm->next_in++;
-               s->strm->avail_in--;
-               s->strm->total_in_lo32++;
-               if (s->strm->total_in_lo32 == 0)
-                       s->strm->total_in_hi32++;
-       }
-       return -1;      /* KEN */
-}
-
-#define GET_UCHAR(lll,uuu)                        \
-   GET_BITS(lll,uuu,8)
-
-#define GET_BIT(lll,uuu)                          \
-   GET_BITS(lll,uuu,1)
-
-/*---------------------------------------------------*/
-#define GET_MTF_VAL(label1,label2,lval)           \
-{                                                 \
-   if (groupPos == 0) {                           \
-      groupNo++;                                  \
-      if (groupNo >= nSelectors)                  \
-         RETURN(BZ_DATA_ERROR);                   \
-      groupPos = BZ_G_SIZE;                       \
-      gSel = s->selector[groupNo];                \
-      gMinlen = s->minLens[gSel];                 \
-      gLimit = &(s->limit[gSel][0]);              \
-      gPerm = &(s->perm[gSel][0]);                \
-      gBase = &(s->base[gSel][0]);                \
-   }                                              \
-   groupPos--;                                    \
-   zn = gMinlen;                                  \
-   GET_BITS(label1, zvec, zn);                    \
-   while (1) {                                    \
-      if (zn > 20 /* the longest code */)         \
-         RETURN(BZ_DATA_ERROR);                   \
-      if (zvec <= gLimit[zn]) break;              \
-      zn++;                                       \
-      GET_BIT(label2, zj);                        \
-      zvec = (zvec << 1) | zj;                    \
-   };                                             \
-   if (zvec - gBase[zn] < 0                       \
-       || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE)  \
-      RETURN(BZ_DATA_ERROR);                      \
-   lval = gPerm[zvec - gBase[zn]];                \
-}
-
-
-/*---------------------------------------------------*/
-Int32 BZ2_decompress ( DState* s )
-{
-   UChar      uc;
-   Int32      retVal;
-   Int32      minLen, maxLen;
-   bz_stream* strm = s->strm;
-
-   /* stuff that needs to be saved/restored */
-   Int32  i;
-   Int32  j;
-   Int32  t;
-   Int32  alphaSize;
-   Int32  nGroups;
-   Int32  nSelectors;
-   Int32  EOB;
-   Int32  groupNo;
-   Int32  groupPos;
-   Int32  nextSym;
-   Int32  nblockMAX;
-   Int32  nblock;
-   Int32  es;
-   Int32  N;
-   Int32  curr;
-   Int32  zt;
-   Int32  zn; 
-   Int32  zvec;
-   Int32  zj;
-   Int32  gSel;
-   Int32  gMinlen;
-   Int32* gLimit;
-   Int32* gBase;
-   Int32* gPerm;
-
-   if (s->state == BZ_X_MAGIC_1) {
-      /*initialise the save area*/
-      s->save_i           = 0;
-      s->save_j           = 0;
-      s->save_t           = 0;
-      s->save_alphaSize   = 0;
-      s->save_nGroups     = 0;
-      s->save_nSelectors  = 0;
-      s->save_EOB         = 0;
-      s->save_groupNo     = 0;
-      s->save_groupPos    = 0;
-      s->save_nextSym     = 0;
-      s->save_nblockMAX   = 0;
-      s->save_nblock      = 0;
-      s->save_es          = 0;
-      s->save_N           = 0;
-      s->save_curr        = 0;
-      s->save_zt          = 0;
-      s->save_zn          = 0;
-      s->save_zvec        = 0;
-      s->save_zj          = 0;
-      s->save_gSel        = 0;
-      s->save_gMinlen     = 0;
-      s->save_gLimit      = NULL;
-      s->save_gBase       = NULL;
-      s->save_gPerm       = NULL;
-   }
-
-   /*restore from the save area*/
-   i           = s->save_i;
-   j           = s->save_j;
-   t           = s->save_t;
-   alphaSize   = s->save_alphaSize;
-   nGroups     = s->save_nGroups;
-   nSelectors  = s->save_nSelectors;
-   EOB         = s->save_EOB;
-   groupNo     = s->save_groupNo;
-   groupPos    = s->save_groupPos;
-   nextSym     = s->save_nextSym;
-   nblockMAX   = s->save_nblockMAX;
-   nblock      = s->save_nblock;
-   es          = s->save_es;
-   N           = s->save_N;
-   curr        = s->save_curr;
-   zt          = s->save_zt;
-   zn          = s->save_zn; 
-   zvec        = s->save_zvec;
-   zj          = s->save_zj;
-   gSel        = s->save_gSel;
-   gMinlen     = s->save_gMinlen;
-   gLimit      = s->save_gLimit;
-   gBase       = s->save_gBase;
-   gPerm       = s->save_gPerm;
-
-   retVal = BZ_OK;
-
-   switch (s->state) {
-
-      GET_UCHAR(BZ_X_MAGIC_1, uc);
-      if (uc != 'B') RETURN(BZ_DATA_ERROR_MAGIC);
-
-      GET_UCHAR(BZ_X_MAGIC_2, uc);
-      if (uc != 'Z') RETURN(BZ_DATA_ERROR_MAGIC);
-
-      GET_UCHAR(BZ_X_MAGIC_3, uc)
-      if (uc != 'h') RETURN(BZ_DATA_ERROR_MAGIC);
-
-      GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
-      if (s->blockSize100k < '1' || 
-          s->blockSize100k > '9') RETURN(BZ_DATA_ERROR_MAGIC);
-      s->blockSize100k -= '0';
-
-      if (0 && s->smallDecompress) {
-         s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
-         s->ll4  = BZALLOC( 
-                      ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) 
-                   );
-         if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
-      } else {
-         s->tt  = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
-         if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
-      }
-
-      GET_UCHAR(BZ_X_BLKHDR_1, uc);
-
-      if (uc == 0x17) goto endhdr_2;
-      if (uc != 0x31) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_BLKHDR_2, uc);
-      if (uc != 0x41) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_BLKHDR_3, uc);
-      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_BLKHDR_4, uc);
-      if (uc != 0x26) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_BLKHDR_5, uc);
-      if (uc != 0x53) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_BLKHDR_6, uc);
-      if (uc != 0x59) RETURN(BZ_DATA_ERROR);
-
-      s->currBlockNo++;
-    //  if (s->verbosity >= 2)
-    //     VPrintf1 ( "\n    [%d: huff+mtf ", s->currBlockNo );
-      s->storedBlockCRC = 0;
-      GET_UCHAR(BZ_X_BCRC_1, uc);
-      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_BCRC_2, uc);
-      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_BCRC_3, uc);
-      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_BCRC_4, uc);
-      s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
-
-      GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
-
-      s->origPtr = 0;
-      GET_UCHAR(BZ_X_ORIGPTR_1, uc);
-      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
-      GET_UCHAR(BZ_X_ORIGPTR_2, uc);
-      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
-      GET_UCHAR(BZ_X_ORIGPTR_3, uc);
-      s->origPtr = (s->origPtr << 8) | ((Int32)uc);
-
-      if (s->origPtr < 0)
-         RETURN(BZ_DATA_ERROR);
-      if (s->origPtr > 10 + 100000*s->blockSize100k) 
-         RETURN(BZ_DATA_ERROR);
-
-      /*--- Receive the mapping table ---*/
-      for (i = 0; i < 16; i++) {
-         GET_BIT(BZ_X_MAPPING_1, uc);
-         if (uc == 1) 
-            s->inUse16[i] = True; else 
-            s->inUse16[i] = False;
-      }
-
-      for (i = 0; i < 256; i++) s->inUse[i] = False;
-
-      for (i = 0; i < 16; i++)
-         if (s->inUse16[i])
-            for (j = 0; j < 16; j++) {
-               GET_BIT(BZ_X_MAPPING_2, uc);
-               if (uc == 1) s->inUse[i * 16 + j] = True;
-            }
-      makeMaps_d ( s );
-      if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
-      alphaSize = s->nInUse+2;
-
-      /*--- Now the selectors ---*/
-      GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
-      if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
-      GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
-      if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
-      for (i = 0; i < nSelectors; i++) {
-         j = 0;
-         while (True) {
-            GET_BIT(BZ_X_SELECTOR_3, uc);
-            if (uc == 0) break;
-            j++;
-            if (j >= nGroups) RETURN(BZ_DATA_ERROR);
-         }
-         s->selectorMtf[i] = j;
-      }
-
-      /*--- Undo the MTF values for the selectors. ---*/
-      {
-         UChar pos[BZ_N_GROUPS], tmp, v;
-         for (v = 0; v < nGroups; v++) pos[v] = v;
-   
-         for (i = 0; i < nSelectors; i++) {
-            v = s->selectorMtf[i];
-            tmp = pos[v];
-            while (v > 0) { pos[v] = pos[v-1]; v--; }
-            pos[0] = tmp;
-            s->selector[i] = tmp;
-         }
-      }
-
-      /*--- Now the coding tables ---*/
-      for (t = 0; t < nGroups; t++) {
-         GET_BITS(BZ_X_CODING_1, curr, 5);
-         for (i = 0; i < alphaSize; i++) {
-            while (True) {
-               if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
-               GET_BIT(BZ_X_CODING_2, uc);
-               if (uc == 0) break;
-               GET_BIT(BZ_X_CODING_3, uc);
-               if (uc == 0) curr++; else curr--;
-            }
-            s->len[t][i] = curr;
-         }
-      }
-
-      /*--- Create the Huffman decoding tables ---*/
-      for (t = 0; t < nGroups; t++) {
-         minLen = 32;
-         maxLen = 0;
-         for (i = 0; i < alphaSize; i++) {
-            if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
-            if (s->len[t][i] < minLen) minLen = s->len[t][i];
-         }
-         BZ2_hbCreateDecodeTables ( 
-            &(s->limit[t][0]), 
-            &(s->base[t][0]), 
-            &(s->perm[t][0]), 
-            &(s->len[t][0]),
-            minLen, maxLen, alphaSize
-         );
-         s->minLens[t] = minLen;
-      }
-
-      /*--- Now the MTF values ---*/
-
-      EOB      = s->nInUse+1;
-      nblockMAX = 100000 * s->blockSize100k;
-      groupNo  = -1;
-      groupPos = 0;
-
-      for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
-
-      /*-- MTF init --*/
-      {
-         Int32 ii, jj, kk;
-         kk = MTFA_SIZE-1;
-         for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
-            for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
-               s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
-               kk--;
-            }
-            s->mtfbase[ii] = kk + 1;
-         }
-      }
-      /*-- end MTF init --*/
-
-      nblock = 0;
-      GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
-
-      while (True) {
-
-         if (nextSym == EOB) break;
-
-         if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
-
-            es = -1;
-            N = 1;
-            do {
-               if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
-               if (nextSym == BZ_RUNB) es = es + (1+1) * N;
-               N = N * 2;
-               GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
-            }
-               while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
-
-            es++;
-            uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
-            s->unzftab[uc] += es;
-
-            if (0 && s->smallDecompress)
-               while (es > 0) {
-                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
-                  s->ll16[nblock] = (UInt16)uc;
-                  nblock++;
-                  es--;
-               }
-            else
-               while (es > 0) {
-                  if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
-                  s->tt[nblock] = (UInt32)uc;
-                  nblock++;
-                  es--;
-               };
-
-            continue;
-
-         } else {
-
-            if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
-
-            /*-- uc = MTF ( nextSym-1 ) --*/
-            {
-               Int32 ii, jj, kk, pp, lno, off;
-               UInt32 nn;
-               nn = (UInt32)(nextSym - 1);
-
-               if (nn < MTFL_SIZE) {
-                  /* avoid general-case expense */
-                  pp = s->mtfbase[0];
-                  uc = s->mtfa[pp+nn];
-                  while (nn > 3) {
-                     Int32 z = pp+nn;
-                     s->mtfa[(z)  ] = s->mtfa[(z)-1];
-                     s->mtfa[(z)-1] = s->mtfa[(z)-2];
-                     s->mtfa[(z)-2] = s->mtfa[(z)-3];
-                     s->mtfa[(z)-3] = s->mtfa[(z)-4];
-                     nn -= 4;
-                  }
-                  while (nn > 0) { 
-                     s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; 
-                  };
-                  s->mtfa[pp] = uc;
-               } else { 
-                  /* general case */
-                  lno = nn / MTFL_SIZE;
-                  off = nn % MTFL_SIZE;
-                  pp = s->mtfbase[lno] + off;
-                  uc = s->mtfa[pp];
-                  while (pp > s->mtfbase[lno]) { 
-                     s->mtfa[pp] = s->mtfa[pp-1]; pp--; 
-                  };
-                  s->mtfbase[lno]++;
-                  while (lno > 0) {
-                     s->mtfbase[lno]--;
-                     s->mtfa[s->mtfbase[lno]] 
-                        = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
-                     lno--;
-                  }
-                  s->mtfbase[0]--;
-                  s->mtfa[s->mtfbase[0]] = uc;
-                  if (s->mtfbase[0] == 0) {
-                     kk = MTFA_SIZE-1;
-                     for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
-                        for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
-                           s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
-                           kk--;
-                        }
-                        s->mtfbase[ii] = kk + 1;
-                     }
-                  }
-               }
-            }
-            /*-- end uc = MTF ( nextSym-1 ) --*/
-
-            s->unzftab[s->seqToUnseq[uc]]++;
-            if (0 && s->smallDecompress)
-               s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
-               s->tt[nblock]   = (UInt32)(s->seqToUnseq[uc]);
-            nblock++;
-
-            GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
-            continue;
-         }
-      }
-
-      /* Now we know what nblock is, we can do a better sanity
-         check on s->origPtr.
-      */
-      if (s->origPtr < 0 || s->origPtr >= nblock)
-         RETURN(BZ_DATA_ERROR);
-
-      s->state_out_len = 0;
-      s->state_out_ch  = 0;
-      BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
-      s->state = BZ_X_OUTPUT;
-    //  if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
-
-      /*-- Set up cftab to facilitate generation of T^(-1) --*/
-      s->cftab[0] = 0;
-      for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
-      for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
-
-      if (0 && s->smallDecompress) {
-
-         /*-- Make a copy of cftab, used in generation of T --*/
-         for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
-
-         /*-- compute the T vector --*/
-         for (i = 0; i < nblock; i++) {
-            uc = (UChar)(s->ll16[i]);
-            SET_LL(i, s->cftabCopy[uc]);
-            s->cftabCopy[uc]++;
-         }
-
-         /*-- Compute T^(-1) by pointer reversal on T --*/
-         i = s->origPtr;
-         j = GET_LL(i);
-         do {
-            Int32 tmp = GET_LL(j);
-            SET_LL(j, i);
-            i = j;
-            j = tmp;
-         }
-            while (i != s->origPtr);
-
-         s->tPos = s->origPtr;
-         s->nblock_used = 0;
-         if (s->blockRandomised) {
-            BZ_RAND_INIT_MASK;
-            BZ_GET_SMALL(s->k0); s->nblock_used++;
-            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
-         } else {
-            BZ_GET_SMALL(s->k0); s->nblock_used++;
-         }
-
-      } else {
-
-         /*-- compute the T^(-1) vector --*/
-         for (i = 0; i < nblock; i++) {
-            uc = (UChar)(s->tt[i] & 0xff);
-            s->tt[s->cftab[uc]] |= (i << 8);
-            s->cftab[uc]++;
-         }
-
-         s->tPos = s->tt[s->origPtr] >> 8;
-         s->nblock_used = 0;
-         if (s->blockRandomised) {
-            BZ_RAND_INIT_MASK;
-            BZ_GET_FAST(s->k0); s->nblock_used++;
-            BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
-         } else {
-            BZ_GET_FAST(s->k0); s->nblock_used++;
-         }
-
-      }
-
-      RETURN(BZ_OK);
-
-
-
-    endhdr_2:
-
-      GET_UCHAR(BZ_X_ENDHDR_2, uc);
-      if (uc != 0x72) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_ENDHDR_3, uc);
-      if (uc != 0x45) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_ENDHDR_4, uc);
-      if (uc != 0x38) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_ENDHDR_5, uc);
-      if (uc != 0x50) RETURN(BZ_DATA_ERROR);
-      GET_UCHAR(BZ_X_ENDHDR_6, uc);
-      if (uc != 0x90) RETURN(BZ_DATA_ERROR);
-
-      s->storedCombinedCRC = 0;
-      GET_UCHAR(BZ_X_CCRC_1, uc);
-      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_CCRC_2, uc);
-      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_CCRC_3, uc);
-      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
-      GET_UCHAR(BZ_X_CCRC_4, uc);
-      s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
-
-      s->state = BZ_X_IDLE;
-      RETURN(BZ_STREAM_END);
-
-      default: AssertH ( False, 4001 );
-   }
-
-   AssertH ( False, 4002 );
-
-   save_state_and_return:
-
-   s->save_i           = i;
-   s->save_j           = j;
-   s->save_t           = t;
-   s->save_alphaSize   = alphaSize;
-   s->save_nGroups     = nGroups;
-   s->save_nSelectors  = nSelectors;
-   s->save_EOB         = EOB;
-   s->save_groupNo     = groupNo;
-   s->save_groupPos    = groupPos;
-   s->save_nextSym     = nextSym;
-   s->save_nblockMAX   = nblockMAX;
-   s->save_nblock      = nblock;
-   s->save_es          = es;
-   s->save_N           = N;
-   s->save_curr        = curr;
-   s->save_zt          = zt;
-   s->save_zn          = zn;
-   s->save_zvec        = zvec;
-   s->save_zj          = zj;
-   s->save_gSel        = gSel;
-   s->save_gMinlen     = gMinlen;
-   s->save_gLimit      = gLimit;
-   s->save_gBase       = gBase;
-   s->save_gPerm       = gPerm;
-
-   return retVal;   
-}
-
-
-/*-------------------------------------------------------------*/
-/*--- end                                      decompress.c ---*/
-/*-------------------------------------------------------------*/
diff --git a/sys/lib/dist/cmd/cdsh.c b/sys/lib/dist/cmd/cdsh.c
deleted file mode 100644 (file)
index 2162350..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * The `cd' shell.  
- * Just has cd and lc.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-char *pwd;
-char *root = "/";
-
-void
-usage(void)
-{
-       fprint(2, "usage: cdsh [-r root]\n");
-       exits("usage");
-}
-
-int
-system(char *cmd)
-{
-       int pid;
-       if((pid = fork()) < 0)
-               return -1;
-
-       if(pid == 0) {
-               dup(2, 1);
-               execl("/bin/rc", "rc", "-c", cmd, nil);
-               exits("exec");
-       }
-       waitpid();
-       return 0;
-}
-
-int
-cd(char *s)
-{
-       char *newpwd;
-       int l;
-
-       if(s[0] == '/') {
-               cleanname(s);
-               newpwd = strdup(s);
-       } else {
-               l = strlen(pwd)+1+strlen(s)+1+50;       /* 50 = crud for unicode mistakes */
-               newpwd = malloc(l);
-               snprint(newpwd, l, "%s/%s", pwd, s);
-               cleanname(newpwd);
-               assert(newpwd[0] == '/');
-       }
-
-       if(chdir(root) < 0 || (newpwd[1] != '\0' && chdir(newpwd+1) < 0)) {
-               chdir(root);
-               chdir(pwd+1);
-               free(newpwd);
-               return -1;
-       } else {
-               free(pwd);
-               pwd = newpwd;
-               return 0;
-       }
-}
-
-void
-main(int argc, char **argv)
-{
-       char *p;
-       Biobuf bin;
-       char *f[2];
-       int nf;
-
-       ARGBEGIN{
-       case 'r':
-               root = ARGF();
-               if(root == nil)
-                       usage();
-               if(root[0] != '/') {
-                       fprint(2, "root must be rooted\n");
-                       exits("root");
-               }
-               break;
-       default:
-               usage();
-       }ARGEND;
-
-       if(argc != 0)
-               usage();
-
-       cleanname(root);
-       if(cd("/") < 0) {
-               fprint(2, "cannot cd %s: %r\n", root);
-               exits("root");
-       }
-
-       Binit(&bin, 0, OREAD);
-       while(fprint(2, "%s%% ", pwd), (p = Brdline(&bin, '\n'))) {
-               p[Blinelen(&bin)-1] = '\0';
-               nf = tokenize(p, f, nelem(f));
-               if(nf < 1)
-                       continue;
-               if(strcmp(f[0], "exit") == 0)
-                       break;
-               if(strcmp(f[0], "lc") == 0) {
-                       if(nf == 1) {
-                               if(system("/bin/lc") < 0)
-                                       fprint(2, "lc: %r\n");
-                       } else if(nf == 2) {
-                               if(strpbrk(p, "'`{}^@$#&()|\\;><"))
-                                       fprint(2, "no shell characters allowed\n");
-                               else {
-                                       p = f[1];
-                                       *--p = ' ';
-                                       *--p = 'c';
-                                       *--p = 'l';
-                                       if(system(p) < 0)
-                                               fprint(2, "lc: %r\n");
-                               }
-                       }
-                       continue;
-               }
-               if(strcmp(f[0], "cd") == 0) {
-                       if(nf < 2)
-                               fprint(2, "usage: cd dir\n");
-                       else if(cd(f[1]) < 0)
-                               fprint(2, "cd: %r\n");
-                       continue;
-               }
-               fprint(2, "commands are cd, lc, and exit\n");
-       }
-
-       print("%s\n", pwd);
-}
diff --git a/sys/lib/dist/cmd/clog.c b/sys/lib/dist/cmd/clog.c
deleted file mode 100644 (file)
index 98d1cf5..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-char *argv0;
-
-int
-openlog(char *name)
-{
-       int fd;
-
-       fd = open(name, OWRITE);
-       if(fd < 0){
-               fprint(2, "%s: can't open %s: %r\n", argv0, name);
-               return -1;
-       }
-       seek(fd, 0, 2);
-       return fd;
-}
-
-void
-main(int argc, char **argv)
-{
-       Biobuf in;
-       int fd;
-       char *p, *t;
-       char buf[8192];
-
-       argv0 = argv[0];
-       if(argc != 4){
-               fprint(2, "usage: %s console logfile prefix\n", argv0);
-               exits("usage");
-       }
-
-       fd = open(argv[1], OREAD);
-       if(fd < 0){
-               fprint(2, "%s: can't open %s: %r\n", argv0, argv[1]);
-               exits("open");
-       }
-       Binit(&in, fd, OREAD);
-
-       fd = openlog(argv[2]);
-
-       for(;;){
-               if(p = Brdline(&in, '\n')){
-                       p[Blinelen(&in)-1] = 0;
-                       if(fprint(fd, "%s: %s\n", argv[3], p) < 0){
-                               close(fd);
-                               fd = openlog(argv[2]);
-                               fprint(fd, "%s: %s\n", t, p);
-                       }
-               } else if(Blinelen(&in) == 0)   // true eof
-                       break;
-               else {
-                       Bread(&in, buf, sizeof buf);
-               }
-       }
-       exits(0);
-}
diff --git a/sys/lib/dist/cmd/mkfile b/sys/lib/dist/cmd/mkfile
deleted file mode 100644 (file)
index bbcd135..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-</$objtype/mkfile
-CPUS=386
-
-TARG=\
-       bargraph\
-       bflz\
-       cdsh\
-       tailfsrv\
-       touchfs\
-       unbflz\
-
-OFILES=
-HFILES=
-
-BIN=/sys/lib/dist/bin/$objtype
-</sys/src/cmd/mkmany
-
-all:V: bzfs!all
-install:V:     bzfs!install
-clean:V:       bzfs!clean
-
-bzfs!%:V:
-       cd bzfs; mk $stem; cd ..
-
diff --git a/sys/lib/dist/cmd/multi/mkfile b/sys/lib/dist/cmd/multi/mkfile
deleted file mode 100644 (file)
index a3acc36..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-objtype=386
-</$objtype/mkfile
-
-TARG=multi
-
-PIECES=\
-       aux/mouse\
-       aux/pcmcia\
-       aux/vga\
-       aux/zerotrunc\
-       disk/fdisk\
-       disk/format\
-       disk/mbr\
-       disk/prep\
-#      fossil/fossil\
-#      fossil/flfmt\
-       ip/ipconfig\
-       ip/ppp\
-       ndb/cs\
-       ndb/dns\
-#      replica/applylog\
-       9660srv\
-#      awk\
-       basename\
-       cat\
-       chgrp\
-       chmod\
-       cleanname\
-       cmp\
-       cp\
-       date\
-       dd\
-       dossrv\
-       echo\
-       ed\
-       ext2srv\
-#      fcp\
-       grep\
-       hget\
-       hoc\
-       ls\
-       mc\
-       mount\
-       mv\
-       ps\
-       read\
-#      rio\
-       rm\
-       sed\
-       sort\
-       srv\
-#      stats\
-       syscall\
-       tail\
-       tee\
-       test\
-       wc\
-       xd\
-
-8.multi:V: mkmulti mkfile
-       mkmulti $PIECES 
-       ls -l 8.multi
-       ls -l /386/bin/$PIECES | awk '{s += $6} END{print s}'
-
-scripts:V:
-       rm -rf ../../pc/multi
-       mkdir ../../pc/multi
-       for(i in $PIECES){
-               b=`{basename $i}
-               echo '#!/bin/multi' >>../../pc/multi/$b
-               chmod +x ../../pc/multi/$b
-       }
-
-BIN=/sys/lib/dist/bin/$objtype
-</sys/src/cmd/mkmany
-
diff --git a/sys/lib/dist/cmd/multi/mkmulti b/sys/lib/dist/cmd/multi/mkmulti
deleted file mode 100644 (file)
index 2317e51..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/rc
-
-targ=multi
-
-n=0
-dir=`{pwd}
-
-fn grab {
-       echo using $*
-       for(i){
-               n=`{echo 1+$n|hoc}
-               mv $i $dir/a.$n.8
-       }
-}
-
-fn getfiles {
-       sed -n 's/^(pcc|8\^l|8l) +(-o [^ ]* +)?([^\-].*)/ \3/p' | sed 's/ -[^ ]*//g' |
-               sed 's/ [^ ]*\.a//g'
-}
-
-rm a.*.8
->multi.h
->multiproto.h
-
-for(i){
-echo $i...
-       b=`{basename $i}
-       p=$b
-       if(~ $b [0-9]*)
-               p=_$b
-       echo void $p^_main'(int, char**);' >>$dir/multiproto.h
-       echo "$b", $p^_main, >>$dir/multi.h
-       d=`{basename -d $i}
-       if(~ $i disk/prep disk/fdisk){
-               cd /sys/src/cmd/disk/prep
-               rm 8.$b
-               files=`{mk 8.$b | getfiles}
-       }
-       if not if(test -d /sys/src/cmd/$i && @{cd /sys/src/cmd/$i && mk 8.out}){
-               cd /sys/src/cmd/$i
-               rm 8.out
-               files=`{mk 8.out | getfiles}
-       }
-       if not if(test -d /sys/src/cmd/$i && @{cd /sys/src/cmd/$i && mk 8.$b}){
-               cd /sys/src/cmd/$i
-               rm 8.out
-               files=`{mk 8.$b | getfiles}
-       }
-       if not if(test -d /sys/src/cmd/$d && @{cd /sys/src/cmd/$d && mk 8.$b}){
-               cd /sys/src/cmd/$d
-               rm 8.$b
-               files=`{mk 8.$b | getfiles}
-       }
-       if not{
-               echo do not know how to make $i
-               exit oops
-       }
-       aux/8prefix $p^_ $files
-       grab $files
-       switch(`{pwd}){
-       case /sys/src/cmd /sys/src/cmd/aux /sys/src/cmd/ip
-               rm 8.$b
-       case *
-               mk clean
-       }
-}
-cd $dir
-8c -FVw multi.c
-8l -o 8.$targ multi.8 a.*.8
-# rm a.*.8
diff --git a/sys/lib/dist/cmd/multi/multi.c b/sys/lib/dist/cmd/multi/multi.c
deleted file mode 100644 (file)
index a2e3035..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <u.h>
-#include <libc.h>
-
-#include "multiproto.h"
-struct {
-       char *name; 
-       void (*fn)(int, char**);
-} mains[] =
-{
-#include "multi.h"
-};
-
-void
-main(int argc, char **argv)
-{
-       int i;
-       char *cmd, *p;
-       
-       if(argc == 1){
-               fprint(2, "usage: multi cmd args...\n");
-               exits("usage");
-       }
-       
-       cmd = argv[1];
-       if(p = strrchr(cmd, '/'))
-               cmd = p+1;
-       argv++;
-       argc--;
-
-       for(i=0; i<nelem(mains); i++){
-               if(strcmp(cmd, mains[i].name) == 0){
-                       mains[i].fn(argc, argv);
-                       return;
-               }
-       }
-       fprint(2, "multi: no such cmd %s\n", cmd);
-       exits("no cmd");
-}
diff --git a/sys/lib/dist/cmd/tailfsrv.c b/sys/lib/dist/cmd/tailfsrv.c
deleted file mode 100644 (file)
index fc41f42..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <u.h>
-#include <libc.h>
-
-void
-main(void)
-{
-       int fd, p[2];
-       char buf[8192], n;
-
-       pipe(p);
-       fd = create("/srv/log", OWRITE, 0666);
-       fprint(fd, "%d", p[0]);
-       close(fd);
-       close(p[0]);
-       while((n = read(p[1], buf, sizeof buf)) >= 0)
-               write(1, buf, n);
-}
diff --git a/sys/lib/dist/cmd/touchfs.c b/sys/lib/dist/cmd/touchfs.c
deleted file mode 100644 (file)
index 00fadf3..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-void
-Bpass(Biobuf *bin, Biobuf *bout, int n)
-{
-       char buf[8192];
-       int m;
-
-       while(n > 0) {
-               m = sizeof buf;
-               if(m > n)
-                       m = n;
-               m = Bread(bin, buf, m);
-               if(m <= 0) {
-                       fprint(2, "corrupt archive\n");
-                       exits("notdone");
-               }
-               Bwrite(bout, buf, m);
-               n -= m;
-       }
-       assert(n == 0);
-}
-
-void
-main(int argc, char **argv)
-{
-       char *p, *f[10];
-       Biobuf bin, bout;
-       int nf;
-       ulong d, size;
-
-       if(argc != 2) {
-               fprint(2, "usage: cat mkfs-archive | touchfs date (in seconds)\n");
-               exits("usage");
-       }
-
-       d = strtoul(argv[1], 0, 0);
-
-       quotefmtinstall();
-       Binit(&bin, 0, OREAD);
-       Binit(&bout, 1, OWRITE);
-
-       while(p = Brdline(&bin, '\n')) {
-               p[Blinelen(&bin)-1] = '\0';
-               if(strcmp(p, "end of archive") == 0) {
-                       Bprint(&bout, "end of archive\n");
-                       exits(0);
-               }
-
-               nf = tokenize(p, f, nelem(f));
-               if(nf != 6) {
-                       fprint(2, "corrupt archive\n");
-                       exits("notdone");
-               }
-
-               Bprint(&bout, "%q %q %q %q %lud %q\n",
-                       f[0], f[1], f[2], f[3], d, f[5]);
-
-               size = strtoul(f[5], 0, 0);
-               Bpass(&bin, &bout, size);
-       }
-       fprint(2, "premature end of archive\n");
-       exits("notdone");
-}
diff --git a/sys/lib/dist/cmd/unbflz.c b/sys/lib/dist/cmd/unbflz.c
deleted file mode 100644 (file)
index 5ddb821..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-void
-usage(void)
-{
-       fprint(2, "usage: unbflz [file]\n");
-       exits("usage");
-}
-
-int
-Bgetint(Biobuf *b)
-{
-       uchar p[4];
-
-       if(Bread(b, p, 4) != 4)
-               sysfatal("short read");
-       return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
-}
-
-/*
- * memmove but make sure overlap works properly.
- */
-void
-copy(uchar *dst, uchar *src, int n)
-{
-       while(n-- > 0)
-               *dst++ = *src++;
-}
-
-void
-main(int argc, char **argv)
-{
-       Biobuf *b, bin;
-       char buf[5];
-       uchar *data;
-       ulong *blk, l;
-       int nblk, mblk;
-       int sum;
-       int i, j, length, m, n, o;
-
-       ARGBEGIN{
-       default:
-               usage();
-       }ARGEND
-
-       switch(argc){
-       default:
-               usage();
-       case 0:
-               Binit(&bin, 0, OREAD);
-               b = &bin;
-               break;
-       case 1:
-               if((b = Bopen(argv[0], OREAD)) == nil)
-                       sysfatal("open %s: %r", argv[0]);
-               break;
-       }
-
-       if(Bread(b, buf, 4) != 4)
-               sysfatal("short read");
-
-       if(memcmp(buf, "BLZ\n", 4) != 0)
-               sysfatal("bad header");
-
-       length = Bgetint(b);
-       data = malloc(length);
-       if(data == nil)
-               sysfatal("out of memory");
-       sum = 0;
-       nblk = 0;
-       mblk = 0;
-       blk = nil;
-       while(sum < length){
-               if(nblk>=mblk){
-                       mblk += 16384;
-                       blk = realloc(blk, (mblk+1)*sizeof(blk[0]));
-                       if(blk == nil)
-                               sysfatal("out of memory");
-               }
-               l = Bgetint(b);
-               blk[nblk++] = l;
-               if(l&(1<<31))
-                       l &= ~(1<<31);
-               else
-                       blk[nblk++] = Bgetint(b);
-               sum += l;
-       }
-       if(sum != length)
-               sysfatal("bad compressed data %d %d", sum, length);
-       i = 0;
-       j = 0;
-       while(i < length){
-               assert(j < nblk);
-               n = blk[j++];
-               if(n&(1<<31)){
-                       n &= ~(1<<31);
-                       if((m=Bread(b, data+i, n)) != n)
-                               sysfatal("short read %d %d", n, m);
-               }else{
-                       o = blk[j++];
-                       copy(data+i, data+o, n);
-               }
-               i += n;
-       }
-       write(1, data, length);
-       exits(nil);
-}
diff --git a/sys/lib/dist/logcompress.awk b/sys/lib/dist/logcompress.awk
deleted file mode 100644 (file)
index 3267a48..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-       verb[$4] = $3
-       data[$4] = sprintf("%s %s %s %s %s %s", $5, $6, $7, $8, $9, $10)
-}
-
-END{
-       for(i in verb)
-               if(verb[i] != "d")
-                       printf("a %s %s\n", i, data[i]) |"sort +1"
-       close("sort +1")
-       for(i in verb)
-               if(verb[i] == "d")
-                       printf("d %s %s\n", i, data[i]) |"sort -r +1"
-       close("sort -r +1")
-}
diff --git a/sys/lib/dist/logtime.awk b/sys/lib/dist/logtime.awk
deleted file mode 100644 (file)
index f974f8d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-       printf("%s %d %s\n", t, NR, $0);
-}
index 98dcd8fee7c620226c9a098146ebb79d0a975af0..9fa156194b82d363b61aee4d4ee206b62b821df6 100644 (file)
-# /sys/lib/dist/mkfile
-src9=/n/sources/plan9          # what to export
-dist=/sys/lib/dist             # where this machinery lives
-scr=/n/other/dist              # scratch space before copying to web.protect
-# import /sys/lib/dist/web.protect from the outside
-x=`{setup}
+src9=/n/src9
+scr=/tmp/dist
 
-cd:V: $scr/plan9.iso
-
-ncd:V: $scr/plan9-new.iso.bz2
-
-ncd-dist:V: $scr/plan9-new.iso.bz2
-       mk $dist/web.protect/plan9-new.iso.bz2
-
-cd-dist:V: $scr/plan9.iso.bz2
-       mk $dist/web.protect/plan9.iso.bz2
-
-contrib-cd:V: $scr/contrib.iso.bz2
-       mk $dist/web.protect/contrib.iso.bz2
-
-$scr/%.iso:D: $src9/dist/replica/plan9.log
-       @ { cd pc; mk cddisk }
-       rm -f $target
-       bind pc/cddisk cdstub/bootdisk.img
-       if(! test -f $src9/bootdisk.img)
-               bind -a cdstub $src9
-       title=`{date | sed 's/(...) (...) (..) (..:..):.. (...) (....)/Plan 9 - \2 \3 \6 \4/'}
-       title=$"title
-       echo 'CD:' $title
-       disk/mk9660 -9cj -v $title -s $src9 -b bootdisk.img $target
-
-# copy compressed file from scratch space to the distribution, carefully
-$dist/web.protect/%.iso.bz2:   $scr/%.iso.bz2
-       >>$target.new
-       chmod +t $target.new            # waste write buf, not venti store
-       cp $prereq $target.new
-       # replace previous version with a flash cut
-       if (test -e $target)
-               mv $target $target.old # try to not clobber downloads in progress
-       mv $target.new $target
-
-cd-cleanup:V:
-       rm -f $dist/web.protect/*.iso.bz2.old # remove old versions after a delay
-
-# generate replica log & db for $src9 only
-scan:V:
-       test -d $scr            # make sure other was mounted above
-       test -d $src9
-       test -d $dist/web.protect
-       lock scan.lock replica/scan $dist/sources.replica
-       chmod +t $src9/dist/replica/*.^(db log)
-
-# generate replica log & db for all of /n/sources
-scanall:V:
-       @ {
-               rfork ne
-               d=/n/sources
-               test -d $src9
-               lock scanall.lock replica/scan $dist/sourcesall.replica
-               chmod +t $src9/dist/replica/*.^(db log)
-       }
-
-compresslog:V:
-       {
-       awk -f logcompress.awk $src9/dist/replica/plan9.log |
-               awk -f logtime.awk -v 't='^`{date -n} >/tmp/plan9.log
-       rm -f $src9/dist/replica/plan9.new.log
-       cp /tmp/plan9.log $src9/dist/replica/plan9.new.log &&
-               mv $src9/dist/replica/plan9.new.log $src9/dist/replica/plan9.log
-       } <scan.lock
-
-#restart:V:
-#      rm -f $src9/dist/replica/plan9.db
-#      rm -f $src9/dist/replica/plan9.log
-#      chmod 664 $src9/dist/replica/plan9.db >$src9/dist/replica/plan9.db
-#      chmod 664 $src9/dist/replica/plan9.log >$src9/dist/replica/plan9.log
-#      chmod +a $src9/dist/replica/plan9.log
-#      mk scan
-
-odump:V:
-       disk/dump9660 -9cj -v 'Plan 9 4e Dumps' -s $src9 \
-               -p /sys/lib/sysconfig/proto/allproto $scr/distdump.iso
-
-cd.install:V:
-#      if(~ $sysname achille){
-#              echo; echo; echo '*** run this on a real machine, like chips.'
-#              exit bad
-#      }
-       bzip2 -9 <$scr/plan9.iso >web.protect/nplan9.iso.bz2
+x=`{mkdir -p $scr}
 
-D.install:V:
-       D=/n/roro/usr/rob/testplan9
-       9fs roro
-       test -d $D
-       cp $D$dist/pc/ndisk $dist/web.protect/ndisk
-       cp $D$dist/pc/9loaddebug $dist/web.protect/n9loaddebug
-
-reallyinstall:V:
-       if(! ~ $sysname achille){
-               echo; echo; echo '*** this needs to run on achille.'
-               exit bad
-       }
-       cd web.protect
-       for (i in plan9.iso.bz2 disk 9loaddebug vmware.zip)
-               if(test -f n$i){
-                       mv $i _$i && { mv n$i $i || mv _$i $i }
-               }
-       rm /srv/ramfs.9down4e
-       $dist/startcache
-
-dump:V:
-       rm -f /srv/9660.xxx
-       9660srv 9660.xxx
-       mount /srv/9660.xxx /n/kremvax $scr/plan9.iso
-       now=`{mtime $dist/web.protect/plan9.iso.bz2 | awk '{print $1}'}
-       ls -l /rls/plan9/4e.iso
-       disk/dump9660 -9cj -s /n/kremvax -n $now /rls/plan9/4e.iso
-       ls -l /rls/plan9/4e.iso
-       rm /srv/9660.xxx
-
-reencode:V:
-       rm -f $scr/nplan9.iso
-       rm -f /srv/9660.xxx
-       9660srv 9660.xxx
-       mount /srv/9660.xxx /n/kremvax $scr/plan9.iso
-       disk/mk9660 -9cj -v 'Plan 9 4th Edition' -s /n/kremvax \
-               -b bootdisk.img $scr/nplan9.iso
-       rm /srv/9660.xxx
-
-# compress a cd image in scratch space
-$scr/%.iso.bz2:D: $scr/%.iso
-       @ {
-               cd $scr
-               bzip2 -9 <$stem.iso >n$stem.iso.bz2 &&
-               {
-                       if (test -e $stem.iso.bz2)
-                               mv  $stem.iso.bz2 _$stem.iso.bz2
-                       mv n$stem.iso.bz2 $stem.iso.bz2
-               }
-               echo `{date} md5 `{md5sum <$stem.iso.bz2} \
-                       sha1 `{sha1sum <$stem.iso.bz2} \
-                       $stem.iso.bz2 >>/usr/web/plan9checksums.txt
-       }
-
-$scr/contrib.iso:DV:
-       rm -f $target
-       disk/mk9660 -9cj -v 'Plan 9 Extras' -s /n/sources \
-               -p ./contrib.proto $target
-
-rebuild:V:
-       chmod +l build.lock >>build.lock
-       rebuild <build.lock
-
-rebuild-mail:V:
-       chmod +l build.lock >>build.lock
-       rebuild <build.lock
-       datemail 'nightly build errors' 9trouble <buildit.out
-       datemail 'nightly build differences' 9trouble <checkbuild.out
-       status=''
-
-scansources-mail:V:
-       scansources | datemail 'nightly fs vs. sources scan' 9trouble
-
-worldwritable-mail:V:
-       test -e $src9
-       @ {cd /n/sources; /usr/rsc/bin/$cputype/lsr -t -d} |
-               awk '$2 ~ /[2367]$/' | grep -vf ok-writable |
-               datemail 'WRITABLE FILES ON SOURCES' 9trouble || status=''
-       status=''
-       @ {
-               cd $src9
-               /usr/rsc/bin/$cputype/lsr -t -d $src9
-       } |
-               awk '$2 ~ /[2367][^2367].$/' |
-               datemail 'non-group-writable files on sources' 9trouble
-       status=''
-       # use /n/boot to avoid walking the archives mounted under
-       # /lib/vac, or other mounts or binds.
-       rfork n
-       9fs boot
-       test -e /n/boot/sys
-       /usr/rsc/bin/$cputype/lsr -t -d /n/boot/sys /n/boot/lib |
-               grep -v '/lib/audio/|/sys/src/cmd/vac/test/' | # give us a break
-               awk '$2 ~ /[2367][^2367].$/' |
-               datemail 'non-group-writable files on fs' 9trouble
-       status=''
-
-9.tar.gz:V:
-       @{
-               rfork n
-               9fs sources
-               test -e $src9
-               bind -a $src9 $src9/sys/src
-               cd $src9/sys/src
-               tar c LICENSE NOTICE 9
-       } | gzip >$target
-
-9-export:V: 9.tar.gz
-       9fs sources
-       cp 9.tar.gz /n/sources/extra/9.tgz
-       chmod +t    /n/sources/extra/9.tgz
-
-plan9.tar.bz2:V:
-       @{
-               rfork n
-               9fs sources
-               cd /n/sources
-               test -e $src9
-               bind /n/empty $src9/lib/font
-               bind /n/empty $src9/sys/lib/postscript/font
-               bind /n/empty $src9/sys/lib/ghostscript
-               bind /n/empty $src9/sys/src/cmd/gs
-               tar c plan9/LICENSE* plan9/NOTICE plan9/*/mkfile plan9/*/include \
-                       plan9/acme/*/src plan9/acme/bin/source \
-                       plan9/^(adm cron lib lp mail rc sys tmp usr)
-       } | bzip2 >$target
-
-plan9-export:V: plan9.tar.bz2
-       9fs sources
-       chmod +t plan9.tar.bz2
-       mv plan9.tar.bz2 /n/sources/extra/plan9.tar.bz2
+cd:V: $scr/plan9.iso
+       
+clean:V:
+       rm -rf $scr
+
+$scr/cdstub:D: $src9/386/9bootiso
+       mkdir -p $target
+       cp $prereq $target
+       cp pc/plan9.ini.cd $target/plan9.ini
+
+$scr/plan9.iso: $scr/cdstub
+       bind -a $src9 $scr/cdstub 
+       bind /n/empty $scr/cdstub/.hg
+       disk/mk9660 -9cj -s $scr/cdstub -B 9bootiso $target
+       unmount $scr/cdstub/.hg
+       unmount $scr/cdstub
diff --git a/sys/lib/dist/pc/cd0.proto b/sys/lib/dist/pc/cd0.proto
deleted file mode 100644 (file)
index 62bdb1b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-cddisk
index 71f98e5e14615b2d6237c386e170174759e3c1b6..c28f1ce43ff02f8f954abc4fee0453b4b6e36ce5 100644 (file)
@@ -1,15 +1,6 @@
-# config for initial floppy booting
-
-[menu]
-menuitem=boot, Boot Plan 9
-# menuitem=debug, Boot Plan 9 and debug 9load
-menudefault=boot, 10
-
-[common]
 # very cautious settings to get started.
 # will defeat booting from usb devices.
 *nomp=1
-*nobiosload=1
 # *noahciload=1
 # *debugload=1
 *nodumpstack=1
@@ -22,16 +13,7 @@ mouseport=ask
 monitor=ask
 vgasize=ask
 dmamode=ask
-nobootprompt=local!/boot/bzroot
-installurl=http://plan9.bell-labs.com/plan9/download/plan9.iso.bz2
 # serial console on COM1
 #console=0
-
-[boot]
 bootargs=local!#S/sdD0/data
-bootfile=sdD0!cdboot!9pccd.gz
-
-# [debug]
-# bootargs=local!#S/sdD0/data
-# bootfile=sdD0!cdboot!9pccd.gz
-# *debugload=1
+bootfile=/386/9pccd
index 11a2435cab32f1543e3ef494f347b1ce5529e9e5..de8c1352fd5665a4eeec2b70e124519b098da2f2 100644 (file)
@@ -1,15 +1,7 @@
 # config for initial cd booting
-
-[menu]
-menuitem=install, Install Plan 9 from this CD
-menuitem=cdboot, Boot Plan 9 from this CD
-# menuitem=debug, Boot Plan 9 from this CD and debug 9load
-
-[common]
 # very cautious settings to get started.
 # will defeat booting from usb devices.
 *nomp=1
-*nobiosload=1
 # *noahciload=1
 # *debugload=1
 *nodumpstack=1
@@ -21,20 +13,9 @@ mouseport=ask
 monitor=ask
 vgasize=ask
 dmamode=ask
-adisk=/dev/sdD0/cdboot
+adisk=/dev/sdD0/data
 cdboot=yes
 # console=0
 # baud=9600
-
-[install]
-nobootprompt=local!/boot/bzroot
-bootfile=sdD0!cdboot!9pcflop.gz
-
-[cdboot]
 bootargs=local!#S/sdD0/data
-bootfile=sdD0!cdboot!9pccd.gz
-
-# [debug]
-# bootargs=local!#S/sdD0/data
-# bootfile=sdD0!cdboot!9pccd.gz
-# *debugload=1
+bootfile=/386/9pccd
diff --git a/sys/lib/dist/setup b/sys/lib/dist/setup
deleted file mode 100644 (file)
index a1c381b..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/rc
-# setup - prep for the mkfile
-9fs sources
-9fs other
-9fs outfsother
-if (test -e /cfg/$sysname/config)
-       . /cfg/$sysname/config
-if not
-       outip=204.178.31.2
-import -c tcp!$outip!666 $dist/web.protect
index 9f0d010aa1f073f964a14c2bd6f0fac350c99bfc..1d6bea2b7777ddc18fc71a059f6d18470b178612 100644 (file)
@@ -71,7 +71,7 @@ close(void *f)
 static int
 isowalk(Extend *ex, int drive, char *path)
 {
-       char name[Maxpath], pad, *end;
+       char name[Maxpath], c, *end;
        int i;
        Dir d;
 
@@ -97,8 +97,16 @@ isowalk(Extend *ex, int drive, char *path)
                        break;
                i = d.dirlen - (Dirsz + d.namelen);
                while(i-- > 0)
-                       read(ex, &pad, 1);
-               name[d.namelen] = 0;
+                       read(ex, &c, 1);
+               for(i=0; i<d.namelen; i++){
+                       c = name[i];
+                       if(c >= 'A' && c <= 'Z'){
+                               c -= 'A';
+                               c += 'a';
+                       }
+                       name[i] = c;
+               }
+               name[i] = 0;
                while(*path == '/')
                        path++;
                if((end = strchr(path, '/')) == 0)
index daf2213f681ca54650a6f8c07bcd0fe99363d36d..471e26a927f9cc2031f38351792cd649e540331f 100644 (file)
@@ -51,7 +51,8 @@ DIRS=mnihongo\
        flashfs\
        gps\
        na\
-       vga
+       vga\
+       realemu
 
 all:V: $DIRS
 
diff --git a/sys/src/cmd/aux/realemu/arg.c b/sys/src/cmd/aux/realemu/arg.c
new file mode 100644 (file)
index 0000000..4a67e86
--- /dev/null
@@ -0,0 +1,163 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+#define ause(cpu) (cpu->abuf + (cpu->iabuf++ % nelem(cpu->abuf)))
+
+Iarg*
+adup(Iarg *x)
+{
+       Iarg *a;
+
+       a = ause(x->cpu);
+       *a = *x;
+       return a;
+}
+
+Iarg*
+areg(Cpu *cpu, uchar len, uchar reg)
+{
+       Iarg *a;
+
+       a = ause(cpu);
+       a->cpu = cpu;
+       a->tag = TREG;
+       a->len = len;
+       a->reg = reg;
+       return a;
+}
+
+Iarg*
+amem(Cpu *cpu, uchar len, uchar sreg, ulong off)
+{
+       Iarg *a;
+
+       a = ause(cpu);
+       a->cpu = cpu;
+       a->tag = TMEM;
+       a->len = len;
+       a->sreg = sreg;
+       a->seg = cpu->reg[sreg];
+       a->off = off;
+       return a;
+}
+
+Iarg*
+afar(Iarg *mem, uchar len, uchar alen)
+{
+       Iarg *a, *p;
+
+       p = adup(mem);
+       p->len = alen;
+       a = amem(mem->cpu, len, R0S, ar(p));
+       p->off += alen;
+       p->len = 2;
+       a->seg = ar(p);
+       return a;
+}
+
+Iarg*
+acon(Cpu *cpu, uchar len, ulong val)
+{
+       Iarg *a;
+
+       a = ause(cpu);
+       a->cpu = cpu;
+       a->tag = TCON;
+       a->len = len;
+       a->val = val;
+       return a;
+}
+
+ulong
+ar(Iarg *a)
+{
+       ulong w, o;
+       Bus *io;
+
+       switch(a->tag){
+       default:
+               abort();
+       case TMEM:
+               o = ((a->seg<<4) + (a->off & 0xFFFF)) & 0xFFFFF;
+               io = a->cpu->mem + (o>>16);
+               w = io->r(io->aux, o, a->len);
+               break;
+       case TREG:
+               w = a->cpu->reg[a->reg];
+               break;
+       case TREG|TH:
+               w = a->cpu->reg[a->reg] >> 8;
+               break;
+       case TCON:
+               w = a->val;
+               break;
+       }
+       switch(a->len){
+       default:
+               abort();
+       case 1:
+               w &= 0xFF;
+               break;
+       case 2:
+               w &= 0xFFFF;
+               break;
+       case 4:
+               break;
+       }
+       return w;
+}
+
+long
+ars(Iarg *a)
+{
+       ulong w = ar(a);
+       switch(a->len){
+       default:
+               abort();
+       case 1:
+               return (char)w;
+       case 2:
+               return (short)w;
+       case 4:
+               return (long)w;
+       }
+}
+
+void
+aw(Iarg *a, ulong w)
+{
+       ulong *p, o;
+       Cpu *cpu;
+       Bus *io;
+
+       cpu = a->cpu;
+       switch(a->tag){
+       default:
+               abort();
+       case TMEM:
+               o = ((a->seg<<4) + (a->off & 0xFFFF)) & 0xFFFFF;
+               io = cpu->mem + (o>>16);
+               io->w(io->aux, o, w, a->len);
+               break;
+       case TREG:
+               p = cpu->reg + a->reg;
+               switch(a->len){
+               case 4:
+                       *p = w;
+                       break;
+               case 2:
+                       *p = (*p & ~0xFFFF) | (w & 0xFFFF);
+                       break;
+               case 1:
+                       *p = (*p & ~0xFF) | (w & 0xFF);
+                       break;
+               }
+               break;
+       case TREG|TH:
+               p = cpu->reg + a->reg;
+               *p = (*p & ~0xFF00) | (w & 0xFF)<<8;
+               break;
+       }
+}
diff --git a/sys/src/cmd/aux/realemu/dat.h b/sys/src/cmd/aux/realemu/dat.h
new file mode 100644 (file)
index 0000000..9c8ece2
--- /dev/null
@@ -0,0 +1,362 @@
+typedef struct Iarg Iarg;
+typedef struct Inst Inst;
+typedef struct Bus Bus;
+typedef struct Cpu Cpu;
+typedef struct Pit Pit;
+
+enum {
+       RAX,
+       RCX,
+       RDX,
+       RBX,
+       RSP,
+       RBP,
+       RSI,
+       RDI,
+
+       RES,
+       RCS,
+       RSS,
+       RDS,
+       RFS,
+       RGS,
+
+       R0S,    /* 0 segment */
+
+       RIP,
+       RFL,
+
+       NREG,
+};
+
+struct Iarg
+{
+       Cpu *cpu;
+
+       uchar tag;
+       uchar len;
+       uchar atype;
+
+       union {
+               uchar reg;
+               struct {
+                       uchar sreg;
+                       ulong seg, off;
+               };
+               ulong val;
+       };
+};
+
+struct Inst
+{
+       uchar op;
+       uchar code;
+       uchar olen;
+       uchar alen;
+
+       Iarg *a1, *a2, *a3;
+
+       uchar rep;
+
+       uchar mod;
+       uchar reg;
+       uchar rm;
+
+       uchar scale;
+       uchar index;
+       uchar base;
+
+       uchar sreg;
+       uchar dsreg;
+
+       ulong off;
+       long disp;
+};
+
+struct Bus
+{
+       void *aux;
+       ulong (*r)(void *aux, ulong off, int len);
+       void (*w)(void *aux, ulong off, ulong data, int len);
+};
+
+struct Cpu
+{
+       ulong reg[NREG];
+
+       /* instruction counter */
+       ulong ic;
+
+       /* mem[16], one entry for each 64k block */
+       Bus *mem;
+
+       /* port[1], in/out */
+       Bus *port;
+
+       int trap;
+       ulong oldip;
+       jmp_buf jmp;
+
+       /* default operand, address and stack pointer length */
+       uchar olen, alen, slen;
+
+       /* argument buffers */
+       ulong iabuf;
+       Iarg abuf[0x80];
+};
+
+struct Pit
+{
+       ulong   count;
+
+       /* set by setgate(), cleared by clockpit() */
+       uchar   gateraised;
+
+       /* signals */
+       uchar   gate;
+       uchar   out;
+
+       /* mode and flags */
+       uchar   count0;
+
+       uchar   bcd;
+       uchar   amode;
+       uchar   omode;
+
+       /* latch for wpit initial count */
+       uchar   wcount;
+       uchar   wlatched;
+       uchar   wlatch[2];
+
+       /* latch for rpit status/count */
+       uchar   rcount;
+       uchar   rlatched;
+       uchar   rlatch[2];
+};
+
+/* processor flags */
+enum {
+       CF = 1<<0,      /* carry flag */
+       PF = 1<<2,      /* parity flag */
+       AF = 1<<4,      /* aux carry flag */
+       ZF = 1<<6,      /* zero flag */
+       SF = 1<<7,      /* sign flag */
+       TF = 1<<8,      /* trap flag */
+       IF = 1<<9,      /* interrupts enabled flag */
+       DF = 1<<10,     /* direction flag */
+       OF = 1<<11,     /* overflow flag */
+       IOPL= 3<<12,    /* I/O privelege level */
+       NT = 1<<14,     /* nested task */
+       RF = 1<<16,     /* resume flag */
+       VM = 1<<17,     /* virtual-8086 mode */
+       AC = 1<<18,     /* alignment check */
+       VIF = 1<<19,    /* virtual interrupt flag */
+       VIP = 1<<20,    /* virtual interrupt pending */
+       ID = 1<<21,     /* ID flag */
+};
+
+/* interrupts/traps */
+enum {
+       EDIV0,
+       EDEBUG,
+       ENMI,
+       EBRK,
+       EINTO,
+       EBOUND,
+       EBADOP,
+       ENOFPU,
+       EDBLF,
+       EFPUSEG,
+       EBADTSS,
+       ENP,
+       ESTACK,
+       EGPF,
+       EPF,
+
+       EHALT = 256,    /* pseudo-interrupts */
+       EMEM,
+       EIO,
+};
+
+/* argument tags */
+enum {
+       TREG,
+       TMEM,
+       TCON,
+
+       TH = 0x80,      /* special flag for AH,BH,CH,DH */
+};
+
+/* argument types */
+enum {
+       ANONE,  /* no argument */
+       A0,             /* constant 0 */
+       A1,             /* constant 1 */
+       A2,             /* constant 2 */
+       A3,             /* constant 3 */
+       A4,             /* constant 4 */
+       AAp,    /* 32-bit or 48-bit direct address */
+       AEb,    /* r/m8 from modrm byte */
+       AEv,    /* r/m16 or r/m32 from modrm byte */
+       AEw,    /* r/m16 */
+       AFv,    /* flag word */
+       AGb,    /* r8 from modrm byte */
+       AGv,    /* r16 or r32 from modrm byte */
+       AGw, /* r/m16 */
+       AIb,    /* immediate byte */
+       AIc,    /* immediate byte sign-extended */
+       AIw,    /* immediate 16-bit word */
+       AIv,    /* immediate 16-bit or 32-bit word */
+       AJb,    /* relative offset byte */
+       AJv,    /* relative offset 16-bit or 32-bit word */
+       AJr,    /* r/m16 or r/m32 register */
+       AM,             /* memory address from modrm */
+       AMa,    /* something for bound */
+       AMa2,
+       AMp,    /* 32-bit or 48-bit memory address */
+       AOb,    /* immediate word-sized offset to a byte */
+       AOv,    /* immediate word-size offset to a word */
+       ASw,    /* segment register selected by r field of modrm */
+       AXb,    /* byte at DS:SI */
+       AXv,    /* word at DS:SI */
+       AYb,    /* byte at ES:DI */
+       AYv,    /* word at ES:DI */
+
+       AAL,
+       ACL,
+       ADL,
+       ABL,
+       AAH,
+       ACH,
+       ADH,
+       ABH,
+
+       AAX,
+       ACX,
+       ADX,
+       ABX,
+       ASP,
+       ABP,
+       ASI,
+       ADI,
+
+       AES,
+       ACS,
+       ASS,
+       ADS,
+       AFS,
+       AGS,
+
+       NATYPE,
+};
+
+/* operators */
+enum {
+       OBAD,
+       O0F,
+       OAAA,
+       OAAD,
+       OAAM,
+       OAAS,
+       OADC,
+       OADD,
+       OAND,
+       OARPL,
+       OASIZE,
+       OBOUND,
+       OBT,
+       OBTS,
+       OBTR,
+       OBTC,
+       OBSF,
+       OBSR,
+       OCALL,
+       OCBW,
+       OCLC,
+       OCLD,
+       OCLI,
+       OCMC,
+       OCMOV,
+       OCMP,
+       OCMPS,
+       OCPUID,
+       OCWD,
+       ODAA,
+       ODAS,
+       ODEC,
+       ODIV,
+       OENTER,
+       OGP1,
+       OGP2,
+       OGP3b,
+       OGP3v,
+       OGP4,
+       OGP5,
+       OGP10,
+       OGP12,
+       OHLT,
+       OIDIV,
+       OIMUL,
+       OIN,
+       OINC,
+       OINS,
+       OINT,
+       OIRET,
+       OJUMP,
+       OLAHF,
+       OLEA,
+       OLEAVE,
+       OLFP,
+       OLOCK,
+       OLODS,
+       OLOOP,
+       OLOOPNZ,
+       OLOOPZ,
+       OMOV,
+       OMOVS,
+       OMOVZX,
+       OMOVSX,
+       OMUL,
+       ONEG,
+       ONOP,
+       ONOT,
+       OOR,
+       OOSIZE,
+       OOUT,
+       OOUTS,
+       OPOP,
+       OPOPA,
+       OPOPF,
+       OPUSH,
+       OPUSHA,
+       OPUSHF,
+       ORCL,
+       ORCR,
+       OREPE,
+       OREPNE,
+       ORET,
+       ORETF,
+       OROL,
+       OROR,
+       OSAHF,
+       OSAR,
+       OSBB,
+       OSCAS,
+       OSEG,
+       OSET,
+       OSHL,
+       OSHLD,
+       OSHR,
+       OSHRD,
+       OSTC,
+       OSTD,
+       OSTI,
+       OSTOS,
+       OSUB,
+       OTEST,
+       OWAIT,
+       OXCHG,
+       OXLAT,
+       OXOR,
+       NUMOP,
+};
diff --git a/sys/src/cmd/aux/realemu/decode.c b/sys/src/cmd/aux/realemu/decode.c
new file mode 100644 (file)
index 0000000..e2022a2
--- /dev/null
@@ -0,0 +1,619 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+typedef struct Optab Optab;
+struct Optab {
+       uchar op;
+       uchar a1, a2, a3;
+};
+
+static Optab optab[256] = {
+//00
+  {OADD,  AEb, AGb}, {OADD,  AEv, AGv}, {OADD,  AGb, AEb}, {OADD,  AGv, AEv},
+  {OADD,  AAL, AIb}, {OADD,  AAX, AIv}, {OPUSH, AES,    }, {OPOP,  AES     },
+  {OOR,   AEb, AGb}, {OOR,   AEv, AGv}, {OOR,   AGb, AEb}, {OOR,   AGv, AEv},
+  {OOR,   AAL, AIb}, {OOR,   AAX, AIv}, {OPUSH, ACS,    }, {O0F,           },
+//10
+  {OADC,  AEb, AGb}, {OADC,  AEv, AGv}, {OADC,  AGb, AEb}, {OADC,  AGv, AEv},
+  {OADC,  AAL, AIb}, {OADC,  AAX, AIv}, {OPUSH, ASS,    }, {OPOP,  ASS,    },
+  {OSBB,  AEb, AGb}, {OSBB,  AEv, AGv}, {OSBB,  AGb, AEb}, {OSBB,  AGv, AEv},
+  {OSBB,  AAL, AIb}, {OSBB,  AAX, AIv}, {OPUSH, ADS,    }, {OPOP,  ADS,    },
+//20
+  {OAND,  AEb, AGb}, {OAND,  AEv, AGv}, {OAND,  AGb, AEb}, {OAND,  AGv, AEv},
+  {OAND,  AAL, AIb}, {OAND,  AAX, AIv}, {OSEG,  AES,    }, {ODAA,          },
+  {OSUB,  AEb, AGb}, {OSUB,  AEv, AGv}, {OSUB,  AGb, AEb}, {OSUB,  AGv, AEv},
+  {OSUB,  AAL, AIb}, {OSUB,  AAX, AIv}, {OSEG,  ACS,    }, {ODAS,          },
+//30
+  {OXOR,  AEb, AGb}, {OXOR,  AEv, AGv}, {OXOR,  AGb, AEb}, {OXOR,  AGv, AEv},
+  {OXOR,  AAL, AIb}, {OXOR,  AAX, AIv}, {OSEG,  ASS,    }, {OAAA,          },
+  {OCMP,  AEb, AGb}, {OCMP,  AEv, AGv}, {OCMP,  AGb, AEb}, {OCMP,  AGv, AEv},
+  {OCMP,  AAL, AIb}, {OCMP,  AAX, AIv}, {OSEG,  ADS,    }, {OAAS,          },
+//40
+  {OINC,  AAX,    }, {OINC,  ACX,    }, {OINC,  ADX,    }, {OINC,  ABX,    },
+  {OINC,  ASP,    }, {OINC,  ABP,    }, {OINC,  ASI,    }, {OINC,  ADI,    },
+  {ODEC,  AAX,    }, {ODEC,  ACX,    }, {ODEC,  ADX,    }, {ODEC,  ABX,    },
+  {ODEC,  ASP,    }, {ODEC,  ABP,    }, {ODEC,  ASI,    }, {ODEC,  ADI,    },
+//50
+  {OPUSH, AAX,    }, {OPUSH, ACX,    }, {OPUSH, ADX,    }, {OPUSH, ABX,    },
+  {OPUSH, ASP,    }, {OPUSH, ABP,    }, {OPUSH, ASI,    }, {OPUSH, ADI,    },
+  {OPOP,  AAX,    }, {OPOP,  ACX,    }, {OPOP,  ADX,    }, {OPOP,  ABX,    },
+  {OPOP,  ASP,    }, {OPOP,  ABP,    }, {OPOP,  ASI,    }, {OPOP,  ADI,    },
+//60
+  {OPUSHA,        }, {OPOPA,         }, {OBOUND,AGv,AMa,AMa2}, {OARPL, AEw, AGw},
+  {OSEG,  AFS,    }, {OSEG,  AGS,    }, {OOSIZE,        }, {OASIZE,        },
+  {OPUSH, AIv,    }, {OIMUL,AGv,AEv,AIv},{OPUSH, AIb,   }, {OIMUL,AGv,AEv,AIb},
+  {OINS,  AYb, ADX}, {OINS,  AYv, ADX}, {OOUTS, ADX, AXb}, {OOUTS, ADX, AXv},
+//70
+  {OJUMP, AJb,    }, {OJUMP, AJb,    }, {OJUMP, AJb,    }, {OJUMP, AJb,    },
+  {OJUMP, AJb,    }, {OJUMP, AJb,    }, {OJUMP, AJb,    }, {OJUMP, AJb,    },
+  {OJUMP, AJb,    }, {OJUMP, AJb,    }, {OJUMP, AJb,    }, {OJUMP, AJb,    },
+  {OJUMP, AJb,    }, {OJUMP, AJb,    }, {OJUMP, AJb,    }, {OJUMP, AJb,    },
+//80
+  {OGP1,  AEb, AIb}, {OGP1,  AEv, AIv}, {OGP1,  AEb, AIb}, {OGP1,  AEv, AIc},
+  {OTEST, AEb, AGb}, {OTEST, AEv, AGv}, {OXCHG, AEb, AGb}, {OXCHG, AEv, AGv},
+  {OMOV,  AEb, AGb}, {OMOV,  AEv, AGv}, {OMOV,  AGb, AEb}, {OMOV,  AGv, AEv},
+  {OMOV,  AEw, ASw}, {OLEA,  AGv, AM }, {OMOV,  ASw, AEw}, {OGP10,    },
+//90
+  {ONOP,          }, {OXCHG, ACX, AAX}, {OXCHG, ADX, AAX}, {OXCHG, ABX, AAX},
+  {OXCHG, ASP, AAX}, {OXCHG, ABP, AAX}, {OXCHG, ASI, AAX}, {OXCHG, ADI, AAX},
+  {OCBW,          }, {OCWD,          }, {OCALL, AAp,    }, {OWAIT,         },
+  {OPUSHF,AFv,    }, {OPOPF, AFv,    }, {OSAHF, AAH,    }, {OLAHF, AAH,    },
+//A0
+  {OMOV,  AAL, AOb}, {OMOV,  AAX, AOv}, {OMOV,  AOb, AAL}, {OMOV,  AOv, AAX},
+  {OMOVS, AYb, AXb}, {OMOVS, AYv, AXv}, {OCMPS, AYb, AXb}, {OCMPS, AYv, AXv},
+  {OTEST, AAL, AIb}, {OTEST, AAX, AIv}, {OSTOS, AYb, AAL}, {OSTOS, AYv, AAX},
+  {OLODS, AAL, AXb}, {OLODS, AAX, AXv}, {OSCAS, AYb, AAL}, {OSCAS, AYv, AAX},
+//B0
+  {OMOV,  AAL, AIb}, {OMOV,  ACL, AIb}, {OMOV,  ADL, AIb}, {OMOV,  ABL, AIb},
+  {OMOV,  AAH, AIb}, {OMOV,  ACH, AIb}, {OMOV,  ADH, AIb}, {OMOV,  ABH, AIb},
+  {OMOV,  AAX, AIv}, {OMOV,  ACX, AIv}, {OMOV,  ADX, AIv}, {OMOV,  ABX, AIv},
+  {OMOV,  ASP, AIv}, {OMOV,  ABP, AIv}, {OMOV,  ASI, AIv}, {OMOV,  ADI, AIv},
+//C0
+  {OGP2,  AEb, AIb}, {OGP2,  AEv, AIb}, {ORET,  AIw,    }, {ORET,  A0,     },
+  {OLFP,AES,AGv,AMp},{OLFP,ADS,AGv,AMp},{OGP12, AEb, AIb}, {OGP12, AEv, AIv},
+  {OENTER,AIw, AIb}, {OLEAVE,        }, {ORETF, AIw,    }, {ORETF, A0,     },
+  {OINT,  A3,     }, {OINT,  AIb,    }, {OINT,  A4,     }, {OIRET,         },
+//D0
+  {OGP2,  AEb, A1 }, {OGP2,  AEv, A1 }, {OGP2,  AEb, ACL}, {OGP2,  AEv, ACL},
+  {OAAM,  AIb,    }, {OAAD,  AIb,    }, {OBAD,          }, {OXLAT, AAL, ABX},
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//E0
+  {OLOOPNZ,AJb,   }, {OLOOPZ,AJb,    }, {OLOOP, AJb,    }, {OJUMP, AJb,    },
+  {OIN,   AAL, AIb}, {OIN,   AAX, AIb}, {OOUT,  AIb, AAL}, {OOUT,  AIb, AAX},
+  {OCALL, AJv,    }, {OJUMP, AJv,    }, {OJUMP, AAp,    }, {OJUMP, AJb,    },
+  {OIN,   AAL, ADX}, {OIN,   AAX, ADX}, {OOUT,  ADX, AAL}, {OOUT,  ADX, AAX},
+//F0
+  {OLOCK,         }, {OBAD,          }, {OREPNE,        }, {OREPE,         },
+  {OHLT,          }, {OCMC,          }, {OGP3b,         }, {OGP3v,         },
+  {OCLC,          }, {OSTC,          }, {OCLI,          }, {OSTI,          },
+  {OCLD,          }, {OSTD,          }, {OGP4,          }, {OGP5,          },
+};
+
+static Optab optab0F[256] = {
+//00
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//10 - mostly floating point and quadword moves
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//20 - doubleword <-> control register moves, other arcana
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//30 - wrmsr, rdtsc, rdmsr, rdpmc, sysenter, sysexit
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//40 - conditional moves
+  {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv},
+  {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv},
+  {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv},
+  {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv}, {OCMOV, AGv, AEv},
+//50 - floating point, mmx stuff
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//60 - floating point, mmx stuff
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//70 - floating point, mmx stuff
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//80 - long-displacement jumps
+  {OJUMP, AJv,    }, {OJUMP, AJv,    }, {OJUMP, AJv,    }, {OJUMP, AJv,    },
+  {OJUMP, AJv,    }, {OJUMP, AJv,    }, {OJUMP, AJv,    }, {OJUMP, AJv,    },
+  {OJUMP, AJv,    }, {OJUMP, AJv,    }, {OJUMP, AJv,    }, {OJUMP, AJv,    },
+  {OJUMP, AJv,    }, {OJUMP, AJv,    }, {OJUMP, AJv,    }, {OJUMP, AJv,    },
+//90 - conditional byte set
+  {OSET,  AEb,    }, {OSET,  AEb,    }, {OSET,  AEb,    }, {OSET,  AEb,    },
+  {OSET,  AEb,    }, {OSET,  AEb,    }, {OSET,  AEb,    }, {OSET,  AEb,    },
+  {OSET,  AEb,    }, {OSET,  AEb,    }, {OSET,  AEb,    }, {OSET,  AEb,    },
+  {OSET,  AEb,    }, {OSET,  AEb,    }, {OSET,  AEb,    }, {OSET,  AEb,    },
+//A0
+  {OPUSH, AFS,    }, {OPOP,  AFS,    }, {OCPUID,        }, {OBT,   AEv, AGv},
+  {OSHLD,AEv,AGv,AIb}, {OSHLD,AEv,AGv,ACL}, {OBAD,      }, {OBAD,          },
+  {OPUSH, AGS,    }, {OPOP,  AGS,    }, {OBAD,          }, {OBTS,  AEv, AGv},
+  {OSHRD,AEv,AGv,AIb}, {OSHRD,AEv,AGv,ACL}, {OBAD,      }, {OIMUL, AGv,AGv,AEv},
+//B0 - mostly arcana
+  {OBAD,          }, {OBAD,          }, {OLFP,ASS,AGv,AMp},{OBTR,AEv,AGv   },
+  {OLFP,AFS,AGv,AMp},{OLFP,AGS,AGv,AMp},{OMOVZX,AGv,AEb }, {OMOVZX,AGv,AEw },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBSF,AGv,AEv   }, {OBSR,AGv,AEv   }, {OMOVSX,AGv,AEb }, {OMOVSX,AGv,AEw },
+//C0 - more arcana
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//D0 - mmx
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//E0 - mmx
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+//F0 - mmx
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+};
+
+/* some operands map to whole groups; group numbers from intel opcode map */
+/* args filled in already (in OGP1 entries) */
+static Optab optabgp1[8] = {
+  {OADD,          }, {OOR,           }, {OADC,          }, {OSBB,          },
+  {OAND,          }, {OSUB,          }, {OXOR,          }, {OCMP,          },
+};
+
+/* args filled in already (in OGP2 entries) */
+static Optab optabgp2[8] = {
+  {OROL,          }, {OROR,          }, {ORCL,          }, {ORCR,          },
+  {OSHL,          }, {OSHR,          }, {OBAD,          }, {OSAR,          },
+};
+
+static Optab optabgp3b[8] = {
+  {OTEST, AEb, AIb}, {OBAD,          }, {ONOT,  AEb,    }, {ONEG,  AEb,    },
+  {OMUL,AAX,AAL,AEb},{OIMUL,AAX,AAL,AEb},{ODIV, AEb,    }, {OIDIV, AEb,    },
+};
+
+static Optab optabgp3v[8] = {
+  {OTEST, AEv, AIv}, {OBAD,          }, {ONOT,  AEv,    }, {ONEG,  AEv,    },
+  {OMUL,AAX,AAX,AEv},{OIMUL,AAX,AAX,AEv},{ODIV, AEv,    }, {OIDIV, AEv,    },
+};
+
+static Optab optabgp4[8] = {
+  {OINC,  AEb,    }, {ODEC,  AEb,    }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+};
+
+static Optab optabgp5[8] = {
+  {OINC,  AEv,    }, {ODEC,  AEv,    }, {OCALL,  AEv,   }, {OCALL,  AMp    },
+  {OJUMP, AEv,    }, {OJUMP, AMp,    }, {OPUSH,  AEv,   }, {OBAD,          },
+};
+
+static Optab optabgp10[8] = {
+  {OPOP, AEv,     }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+};
+
+static Optab optabgp12[8] = {
+  {OMOV,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+  {OBAD,          }, {OBAD,          }, {OBAD,          }, {OBAD,          },
+};
+
+/* optabg6  unimplemented - mostly segment manipulation */
+/* optabg7 unimplemented - more segment manipulation */
+/* optabg8 unimplemented - bit tests */
+
+/*
+ * most of optabg9 - optabg16 decode differently depending on the mod value of
+ * the modrm byte.  they're mostly arcane instructions so they're not
+ * implemented.
+ */
+
+static Optab *optabgp[NUMOP] = {
+       [OGP1]  optabgp1,
+       [OGP2]  optabgp2,
+       [OGP3b] optabgp3b,
+       [OGP3v] optabgp3v,
+       [OGP4]  optabgp4,
+       [OGP5]  optabgp5,
+       [OGP10] optabgp10,
+       [OGP12] optabgp12,
+};
+
+static uchar modrmarg[NATYPE] = {
+       [AEb] 1,
+       [AEw] 1,
+       [AEv] 1,
+       [AGb] 1,
+       [AGw] 1,
+       [AGv] 1,
+       [AM]  1,
+       [AMp] 1,
+       [AMa] 1,
+       [AMa2] 1,
+       [ASw] 1,
+       [AJr] 1,
+};
+
+static void
+getmodrm16(Iarg *ip, Inst *i)
+{
+       Iarg *p;
+       uchar b;
+
+       b = ar(ip); ip->off++;
+
+       i->mod = b>>6;
+       i->reg = (b>>3)&7;
+       i->rm = b&7;
+
+       if(i->mod == 3)
+               return;
+
+       switch(i->rm){
+       case 0:
+               i->off = ar(areg(ip->cpu, 2, RBX)) + ar(areg(ip->cpu, 2, RSI));
+               i->off &= 0xFFFF;
+               break;
+       case 1:
+               i->off = ar(areg(ip->cpu, 2, RBX)) + ar(areg(ip->cpu, 2, RDI));
+               i->off &= 0xFFFF;
+               break;
+       case 2:
+               i->dsreg = RSS;
+               i->off = ar(areg(ip->cpu, 2, RBP)) + ar(areg(ip->cpu, 2, RSI));
+               i->off &= 0xFFFF;
+               break;
+       case 3:
+               i->dsreg = RSS;
+               i->off = ar(areg(ip->cpu, 2, RBP)) + ar(areg(ip->cpu, 2, RDI));
+               i->off &= 0xFFFF;
+               break;
+       case 4:
+               i->off = ar(areg(ip->cpu, 2, RSI));
+               break;
+       case 5:
+               i->off = ar(areg(ip->cpu, 2, RDI));
+               break;
+       case 6:
+               if(i->mod == 0){
+                       p = adup(ip); ip->off += 2;
+                       p->len = 2;
+                       i->off = ar(p);
+                       return;
+               }
+               i->dsreg = RSS;
+               i->off = ar(areg(ip->cpu, 2, RBP));
+               break;
+       case 7:
+               i->off = ar(areg(ip->cpu, 2, RBX));
+               break;
+       }
+       switch(i->mod){
+       case 1:
+               i->off += (i->disp = ars(ip)); ip->off++;
+               i->off &= 0xFFFF;
+               break;
+       case 2:
+               p = adup(ip); ip->off += 2;
+               p->len = 2;
+               i->off += (i->disp = ars(p));
+               i->off &= 0xFFFF;
+               break;
+       }
+}
+
+static void
+getmodrm32(Iarg *ip, Inst *i)
+{
+       static uchar scaler[] = {1, 2, 4, 8};
+       Iarg *p;
+       uchar b;
+
+       b = ar(ip); ip->off++;
+
+       i->mod = b>>6;
+       i->reg = (b>>3)&7;
+       i->rm = b&7;
+
+       if(i->mod == 3)
+               return;
+
+       switch(i->rm){
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 6:
+       case 7:
+               i->off = ar(areg(ip->cpu, 4, i->rm + RAX));
+               break;
+       case 4:
+               b = ar(ip); i->off++;
+               i->scale = b>>6;
+               i->index = (b>>3)&7;
+               i->base = b&7;
+
+               if(i->base != 5){
+                       i->off = ar(areg(ip->cpu, 4, i->base + RAX));
+                       break;
+               }
+       case 5:
+               if(i->mod == 0){
+                       p = adup(ip); ip->off += 4;
+                       p->len = 4;
+                       i->off = ar(p);
+               } else {
+                       i->dsreg = RSS;
+                       i->off = ar(areg(ip->cpu, 4, RBP));
+               }
+               break;
+       }
+
+       if(i->rm == 4 && i->index != 4)
+               i->off += ar(areg(ip->cpu, 4, i->index + RAX)) * scaler[i->scale];
+
+       switch(i->mod){
+       case 1:
+               i->off += (i->disp = ars(ip)); ip->off++;
+               break;
+       case 2:
+               p = adup(ip); ip->off += 4;
+               p->len = 4;
+               i->off += (i->disp = ars(p));
+               break;
+       }
+}
+
+static Iarg*
+getarg(Iarg *ip, Inst *i, uchar atype)
+{
+       Iarg *a;
+       uchar len, reg;
+
+       len = i->olen;
+       switch(atype){
+       default:
+               abort();
+
+       case A0:
+       case A1:
+       case A2:
+       case A3:
+       case A4:
+               a = acon(ip->cpu, len, atype - A0);
+               break;
+
+       case AEb:
+               len = 1;
+               if(0){
+       case AEw:
+               len = 2;
+               }
+       case AEv:
+               if(i->mod == 3){
+                       reg = i->rm;
+                       goto REG;
+               }
+               goto MEM;
+
+       case AM:
+       case AMp:
+       case AMa:
+       case AMa2:
+               if(i->mod == 3)
+                       trap(ip->cpu, EBADOP);
+       MEM:
+               a = amem(ip->cpu, len, i->sreg, i->off);
+               if(atype == AMa2)
+                       a->off += i->olen;
+               break;
+
+       case AGb:
+               len = 1;
+               if(0){
+       case AGw:
+               len = 2;
+               }
+       case AGv:
+               reg = i->reg;
+       REG:
+               a = areg(ip->cpu, len, reg + RAX);
+               if(len == 1 && reg >= 4){
+                       a->reg -= 4;
+                       a->tag |= TH;
+               }
+               break;
+
+       case AIb:
+       case AIc:
+               len = 1;
+               if(0){
+       case AIw:
+               len = 2;
+               }
+       case AIv:
+               a = adup(ip); ip->off += len;
+               a->len = len;
+               break;
+
+       case AJb:
+               len = 1;
+       case AJv:
+               a = adup(ip); ip->off += len;
+               a->len = len;
+               a->off = ip->off + ars(a);
+               break;
+
+       case AJr:
+               if(i->mod != 3)
+                       trap(ip->cpu, EBADOP);
+               a = adup(ip);
+               a->off = ar(areg(ip->cpu, i->olen, i->rm + RAX));
+               break;
+
+       case AAp:
+               a = afar(ip, ip->len, len); ip->off += 2+len;
+               break;
+
+       case AOb:
+               len = 1;
+       case AOv:
+               a = adup(ip); ip->off += i->alen;
+               a->len = i->alen;
+               a = amem(ip->cpu, len, i->sreg, ar(a));
+               break;
+
+       case ASw:
+               reg = i->reg;
+       SREG:
+               a = areg(ip->cpu, 2, reg + RES);
+               break;
+
+       case AXb:
+               len = 1;
+       case AXv:
+               a = amem(ip->cpu, len, i->sreg, ar(areg(ip->cpu, i->alen, RSI)));
+               break;
+
+       case AYb:
+               len = 1;
+       case AYv:
+               a = amem(ip->cpu, len, RES, ar(areg(ip->cpu, i->alen, RDI)));
+               break;
+
+       case AFv:
+               a = areg(ip->cpu, len, RFL);
+               break;
+
+       case AAL:
+       case ACL:
+       case ADL:
+       case ABL:
+       case AAH:
+       case ACH:
+       case ADH:
+       case ABH:
+               len = 1;
+               reg = atype - AAL;
+               goto REG;
+
+       case AAX:
+       case ACX:
+       case ADX:
+       case ABX:
+       case ASP:
+       case ABP:
+       case ASI:
+       case ADI:
+               reg = atype - AAX;
+               goto REG;
+
+       case AES:
+       case ACS:
+       case ASS:
+       case ADS:
+       case AFS:
+       case AGS:
+               reg = atype - AES;
+               goto SREG;
+       }
+       a->atype = atype;
+       return a;
+}
+
+static int
+otherlen(int a)
+{
+       if(a == 2)
+               return 4;
+       else if(a == 4)
+               return 2;
+       abort();
+       return 0;
+}
+
+void
+decode(Iarg *ip, Inst *i)
+{
+       Optab *t, *t2;
+       Cpu *cpu;
+
+       cpu = ip->cpu;
+
+       i->op = 0;
+       i->rep = 0;
+       i->sreg = 0;
+       i->dsreg = RDS;
+       i->olen = cpu->olen;
+       i->alen = cpu->alen;
+
+       for(;;){
+               i->code = ar(ip); ip->off++;
+               t = optab + i->code;
+               switch(t->op){
+               case OOSIZE:
+                       i->olen = otherlen(cpu->olen);
+                       continue;
+               case OASIZE:
+                       i->alen = otherlen(cpu->alen);
+                       continue;
+               case OREPE:
+               case OREPNE:
+                       i->rep = t->op;
+                       continue;
+               case OLOCK:
+                       continue;
+               case OSEG:
+                       i->sreg = t->a1-AES+RES;
+                       continue;
+               case O0F:
+                       i->code = ar(ip); ip->off++;
+                       t = optab0F + i->code;
+                       break;
+               }
+               break;
+       }
+       t2 = optabgp[t->op];
+       if(t2 || modrmarg[t->a1] || modrmarg[t->a2] || modrmarg[t->a3])
+               if(i->alen == 2)
+                       getmodrm16(ip, i);
+               else
+                       getmodrm32(ip, i);
+       if(i->sreg == 0)
+               i->sreg = i->dsreg;
+
+       i->a1 = i->a2 = i->a3 = nil;
+       for(;;){
+               if(t->a1)
+                       i->a1 = getarg(ip, i, t->a1);
+               if(t->a2)
+                       i->a2 = getarg(ip, i, t->a2);
+               if(t->a3)
+                       i->a3 = getarg(ip, i, t->a3);
+               if(t2 == nil)
+                       break;
+               t = t2 + i->reg;
+               t2 = nil;
+       }
+       i->op = t->op;
+}
diff --git a/sys/src/cmd/aux/realemu/fmt.c b/sys/src/cmd/aux/realemu/fmt.c
new file mode 100644 (file)
index 0000000..8d65fe9
--- /dev/null
@@ -0,0 +1,385 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+static char *opstr[] = {       /* Edit s/O(.*),/[O\1]= "\1",/g */
+       [OBAD]= "BAD",
+       [O0F]=  "0F",
+       [OAAA]= "AAA",
+       [OAAD]= "AAD",
+       [OAAM]= "AAM",
+       [OAAS]= "AAS",
+       [OADC]= "ADC",
+       [OADD]= "ADD",
+       [OAND]= "AND",
+       [OARPL]=        "ARPL",
+       [OASIZE]=       "ASIZE",
+       [OBOUND]=       "BOUND",
+       [OBT]=  "BT",
+       [OBTC]= "BTC",
+       [OBTR]= "BTR",
+       [OBTS]= "BTS",
+       [OBSF]= "BSF",
+       [OBSR]= "BSR",
+       [OCALL]=        "CALL",
+       [OCBW]= "CBW",
+       [OCLC]= "CLC",
+       [OCLD]= "CLD",
+       [OCLI]= "CLI",
+       [OCMC]= "CMC",
+       [OCMOV]=        "CMOV",
+       [OCMP]= "CMP",
+       [OCMPS]=        "CMPS",
+       [OCWD]= "CWD",
+       [ODAA]= "DAA",
+       [ODAS]= "DAS",
+       [ODEC]= "DEC",
+       [ODIV]= "DIV",
+       [OENTER]=       "ENTER",
+       [OGP1]= "GP1",
+       [OGP2]= "GP2",
+       [OGP3b]=        "GP3b",
+       [OGP3v]=        "GP3v",
+       [OGP4]= "GP4",
+       [OGP5]= "GP5",
+       [OHLT]= "HLT",
+       [OIDIV]=        "IDIV",
+       [OIMUL]=        "IMUL",
+       [OIN]=  "IN",
+       [OINC]= "INC",
+       [OINS]= "INS",
+       [OINT]= "INT",
+       [OIRET]=        "IRET",
+       [OJUMP]=        "JUMP",
+       [OLAHF]=        "LAHF",
+       [OLFP]= "LFP",
+       [OLEA]= "LEA",
+       [OLEAVE]=       "LEAVE",
+       [OLOCK]=        "LOCK",
+       [OLODS]=        "LODS",
+       [OLOOP]=        "LOOP",
+       [OLOOPNZ]=      "LOOPNZ",
+       [OLOOPZ]=       "LOOPZ",
+       [OMOV]= "MOV",
+       [OMOVS]=        "MOVS",
+       [OMOVZX]=       "MOVZX",
+       [OMOVSX]=       "MOVSX",
+       [OMUL]= "MUL",
+       [ONEG]= "NEG",
+       [ONOP]= "NOP",
+       [ONOT]= "NOT",
+       [OOR]=  "OR",
+       [OOSIZE]=       "OSIZE",
+       [OOUT]= "OUT",
+       [OOUTS]=        "OUTS",
+       [OPOP]= "POP",
+       [OPOPA]=        "POPA",
+       [OPOPF]=        "POPF",
+       [OPUSH]=        "PUSH",
+       [OPUSHA]=       "PUSHA",
+       [OPUSHF]=       "PUSHF",
+       [ORCL]= "RCL",
+       [ORCR]= "RCR",
+       [OREPE]=        "REPE",
+       [OREPNE]=       "REPNE",
+       [ORET]= "RET",
+       [ORETF]=        "RETF",
+       [OROL]= "ROL",
+       [OROR]= "ROR",
+       [OSAHF]=        "SAHF",
+       [OSAR]= "SAR",
+       [OSBB]= "SBB",
+       [OSCAS]=        "SCAS",
+       [OSEG]= "SEG",
+       [OSET]= "SET",
+       [OSHL]= "SHL",
+       [OSHLD]=        "SHLD",
+       [OSHR]= "SHR",
+       [OSHRD]=        "SHRD",
+       [OSTC]= "STC",
+       [OSTD]= "STD",
+       [OSTI]= "STI",
+       [OSTOS]=        "STOS",
+       [OSUB]= "SUB",
+       [OTEST]=        "TEST",
+       [OWAIT]=        "WAIT",
+       [OXCHG]=        "XCHG",
+       [OXLAT]=        "XLAT",
+       [OXOR]= "XOR",
+};
+
+static char *memstr16[] = {
+       "BX+SI",
+       "BX+DI",
+       "BP+SI",
+       "BP+DI",
+       "SI",
+       "DI",
+       "BP",
+       "BX",
+};
+
+static char *memstr32[] = {
+       "EAX",
+       "ECX",
+       "EDX",
+       "EBX",
+       "0",
+       "EBP",
+       "ESI",
+       "EDI",
+};
+
+static int
+argconv(char *p, Inst *i, Iarg *a)
+{
+       jmp_buf jmp;
+       char *s;
+
+       s = p;
+       switch(a->tag){
+       default:
+               abort();
+
+       case TCON:
+               return sprint(p, "%lud", a->val);
+       case TREG:
+       case TREG|TH:
+               switch(a->len){
+               case 1:
+                       return sprint(p, "%c%c", "ACDB"[a->reg], "LH"[(a->tag & TH) != 0]);
+               case 4:
+                       *p++ = 'E';
+               case 2:
+                       p += sprint(p, "%c%c", 
+                               "ACDBSBSDECSDFGIF"[a->reg],
+                               "XXXXPPIISSSSSSPL"[a->reg]);
+                       return p - s;
+               }
+       case TMEM:
+               break;
+       }
+
+       /* setup trap jump in case we dereference bad memory */
+       memmove(jmp, a->cpu->jmp, sizeof jmp);
+       if(setjmp(a->cpu->jmp)){
+               p += sprint(p, "<%.4lux:%.4lux>", a->seg, a->off);
+               goto out;
+       }
+
+       switch(a->atype){
+       default:
+               abort();
+
+       case AAp:
+               p += sprint(p, "[%.4lux:%.4lux]", a->seg, a->off);
+               break;
+
+       case AJb:
+       case AJv:
+               p += sprint(p, "[%.4lux]", a->off);
+               break;
+
+       case AIc:
+               p += sprint(p, "$%.2lx", ars(a));
+               break;
+       case AIb:
+       case AIw:
+       case AIv:
+               p += sprint(p, "$%.*lux", (int)a->len*2, ar(a));
+               break;
+
+       case AMp:
+               *p++ = '*';
+       case AEb:
+       case AEw:
+       case AEv:
+       case AM:
+       case AMa:
+       case AMa2:
+       case AOb:
+       case AOv:
+               if(i->sreg != RDS)
+                       p += sprint(p, "%cS:", "ECSDFG"[i->sreg - RES]);
+               if(a->atype == AOb || a->atype == AOv || (i->mod == 0 &&
+                       (i->alen == 2 && i->rm == 6) ||
+                       (i->alen == 4 && ((i->rm == 5) ||
+                       (i->rm == 4 && i->index == 4 && i->base == 5))))){
+                       p += sprint(p, "[%.*lux]", (int)i->alen*2, a->off);
+                       break;
+               }
+               *p++ = '[';
+               if(i->alen == 2)
+                       p += sprint(p, "%s", memstr16[i->rm]);
+               else{
+                       if(i->rm == 4){
+                               if(i->index != 4)
+                                       p += sprint(p, "%c*%s+", "1248"[i->scale], memstr32[i->index]);
+                               if(i->base != 5)
+                                       p += sprint(p, "%s", memstr32[i->base]);
+                               else{
+                                       if(i->mod == 0)
+                                               p += sprint(p, "%.4lux", i->off);
+                                       else
+                                               p += sprint(p, "EBP");
+                               }
+                       } else
+                               p += sprint(p, "%s", memstr32[i->rm]);
+               }                       
+               if(i->mod != 0)
+                       p += sprint(p, "%+lx", i->disp);
+               *p++ = ']';
+               break;
+
+       case AXb:
+       case AXv:
+               if(a->sreg != RDS)
+                       p += sprint(p, "%cS:", "ECSDFG"[a->sreg - RES]);
+               p += sprint(p, "[SI]");
+               break;
+       case AYb:
+       case AYv:
+               if(a->sreg != RDS)
+                       p += sprint(p, "%cS:", "ECSDFG"[a->sreg - RES]);
+               p += sprint(p, "[DI]");
+               break;
+       }
+
+out:
+       memmove(a->cpu->jmp, jmp, sizeof jmp);
+       *p = 0;
+       return p - s;
+}
+
+static char *jmpstr[] = {
+       "JO", "JNO", "JC", "JNC", "JZ", "JNZ", "JBE", "JA",
+       "JS", "JNS", "JP", "JNP", "JL", "JGE", "JLE", "JG",
+};
+
+int
+instfmt(Fmt *fmt)
+{
+       Inst *i;
+       char *p, buf[256];
+
+       i = va_arg(fmt->args, Inst*);
+       p = buf;
+
+       if(i->olen == 4)
+               p += sprint(p, "O32: ");
+       if(i->alen == 4)
+               p += sprint(p, "A32: ");
+       if(i->rep)
+               p += sprint(p, "%s: ", opstr[i->rep]);
+       
+       if(i->op == OXLAT && i->sreg != RDS)
+               p += sprint(p, "%cS:", "ECSDFG"[i->sreg - RES]);
+
+       if(i->op == OJUMP){
+               switch(i->code){
+               case 0xE3:
+                       p += sprint(p, "%s ", "JCXZ");
+                       break;
+               case 0xEB:
+               case 0xE9:
+               case 0xEA:
+               case 0xFF:
+                       p += sprint(p, "%s ", "JMP");
+                       break;
+               default:
+                       p += sprint(p, "%s ", jmpstr[i->code&0xF]);
+                       break;
+               }
+       } else
+               p += sprint(p, "%s ", opstr[i->op]);
+
+
+       for(;;){
+               if(i->a1 == nil)
+                       break;
+               p += argconv(p, i, i->a1);
+               if(i->a2 == nil)
+                       break;
+               *p++ = ',';
+               *p++ = ' ';
+               p += argconv(p, i, i->a2);
+               if(i->a3 == nil)
+                       break;
+               *p++ = ',';
+               *p++ = ' ';
+               p += argconv(p, i, i->a3);
+               break;
+       }
+       *p = 0;
+       fmtstrcpy(fmt, buf);
+       return 0;
+}
+
+int
+flagfmt(Fmt *fmt)
+{
+       char buf[16];
+       ulong f;
+
+       f = va_arg(fmt->args, ulong);
+       sprint(buf, "%c%c%c%c%c%c%c",
+               (f & CF) ? 'C' : 'c',
+               (f & SF) ? 'S' : 's',
+               (f & ZF) ? 'Z' : 'z',
+               (f & OF) ? 'O' : 'o',
+               (f & PF) ? 'P' : 'p',
+               (f & DF) ? 'D' : 'd',
+               (f & IF) ? 'I' : 'i');
+       fmtstrcpy(fmt, buf);
+       return 0;
+}
+
+int
+cpufmt(Fmt *fmt)
+{
+       char buf[512];
+       jmp_buf jmp;
+       Cpu *cpu;
+       Inst i;
+
+       cpu = va_arg(fmt->args, Cpu*);
+
+       memmove(jmp, cpu->jmp, sizeof jmp);
+       if(setjmp(cpu->jmp) == 0)
+               decode(amem(cpu, 1, RCS, cpu->reg[RIP]), &i);
+       memmove(cpu->jmp, jmp, sizeof jmp);
+
+       snprint(buf, sizeof(buf), 
+               "%.6lux "
+               "%.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux "
+               "%.4lux %.4lux %.4lux %.4lux "
+               "%J %.4lux %.2ux %I",
+
+               cpu->ic,
+
+               cpu->reg[RAX],
+               cpu->reg[RBX],
+               cpu->reg[RCX],
+               cpu->reg[RDX],
+
+               cpu->reg[RDI],
+               cpu->reg[RSI],
+
+               cpu->reg[RBP],
+               cpu->reg[RSP],
+
+               cpu->reg[RDS],
+               cpu->reg[RES],
+               cpu->reg[RSS],
+               cpu->reg[RCS],
+
+               cpu->reg[RFL],
+               cpu->reg[RIP],
+
+               i.code,
+               &i);
+
+       fmtstrcpy(fmt, buf);
+       return 0;
+}
diff --git a/sys/src/cmd/aux/realemu/fns.h b/sys/src/cmd/aux/realemu/fns.h
new file mode 100644 (file)
index 0000000..a25f695
--- /dev/null
@@ -0,0 +1,31 @@
+/* arg */
+Iarg *adup(Iarg *x);
+Iarg *areg(Cpu *cpu, uchar len, uchar reg);
+Iarg *amem(Cpu *cpu, uchar len, uchar sreg, ulong off);
+Iarg *afar(Iarg *mem, uchar len, uchar alen);
+Iarg *acon(Cpu *cpu, uchar len, ulong val);
+ulong ar(Iarg *a);
+long ars(Iarg *a);
+void aw(Iarg *a, ulong w);
+
+/* decode */
+void decode(Iarg *ip, Inst *i);
+
+/* xec */
+void trap(Cpu *cpu, int e);
+int intr(Cpu *cpu, int v);
+int xec(Cpu *cpu, int n);
+
+#pragma varargck type "I" Inst*
+#pragma varargck type "J" ulong
+#pragma varargck type "C" Cpu*
+
+int instfmt(Fmt *fmt);
+int flagfmt(Fmt *fmt);
+int cpufmt(Fmt *fmt);
+
+/* pit */
+void clockpit(Pit *pit, vlong cycles);
+void setgate(Pit *ch, uchar gate);
+uchar rpit(Pit *pit, uchar addr);
+void wpit(Pit *pit, uchar addr, uchar data);
diff --git a/sys/src/cmd/aux/realemu/loadcom.c b/sys/src/cmd/aux/realemu/loadcom.c
new file mode 100644 (file)
index 0000000..28c5bf6
--- /dev/null
@@ -0,0 +1,43 @@
+#include <u.h>
+#include <libc.h>
+
+#include "/386/include/ureg.h"
+
+static uchar buf[0xFF01];
+
+void
+main(int argc, char *argv[])
+{
+       struct Ureg u;
+       int fd, rreg, rmem, len;
+
+       ARGBEGIN {
+       } ARGEND;
+
+       if(argc == 0){
+               fprint(2, "usage:\t%s file.com\n", argv0);
+               exits("usage");
+       }
+       if((fd = open(*argv, OREAD)) < 0)
+               sysfatal("open: %r");
+
+       if((rreg = open("/dev/realmode", OWRITE)) < 0)
+               sysfatal("open realmode: %r");
+       if((rmem = open("/dev/realmodemem", OWRITE)) < 0)
+               sysfatal("open realmodemem: %r");
+       if((len = readn(fd, buf, sizeof buf)) < 2)
+               sysfatal("file too small");
+
+       memset(&u, 0, sizeof u);
+       u.cs = u.ds = u.es = u.fs = u.gs = 0x1000;
+       u.ss = 0x0000;
+       u.sp = 0xfffe;
+       u.pc = 0x0100;
+
+       seek(rmem, (u.cs<<4) + u.pc, 0);
+       if(write(rmem, buf, len) != len)
+               sysfatal("write mem: %r");
+
+       if(write(rreg, &u, sizeof u) != sizeof u)
+               sysfatal("write reg: %r");
+}
diff --git a/sys/src/cmd/aux/realemu/main.c b/sys/src/cmd/aux/realemu/main.c
new file mode 100644 (file)
index 0000000..997e751
--- /dev/null
@@ -0,0 +1,784 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+/* for fs */
+#include <auth.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
+#include "/386/include/ureg.h"
+
+enum {
+       MEMSIZE = 0x100000,
+
+       RMBUF = 0x9000,
+       RMCODE = 0x8000,
+
+       PITHZ = 1193182,
+       PITNS = 1000000000/PITHZ,
+};
+
+static Cpu cpu;
+static uchar memory[MEMSIZE+4];
+static uchar pageregtmp[0x10];
+static int portfd[5];
+static int realmemfd;
+static int cputrace;
+static int porttrace;
+static Pit pit[3];
+
+static vlong pitclock;
+
+static void
+startclock(void)
+{
+       pitclock = nsec();
+}
+
+static void
+runclock(void)
+{
+       vlong now, dt;
+
+       now = nsec();
+       dt = now - pitclock;
+       if(dt >= PITNS){
+               clockpit(pit, dt/PITNS);
+               pitclock = now;
+       }
+}
+
+static ulong
+gw1(uchar *p)
+{
+       return p[0];
+}
+static ulong
+gw2(uchar *p)
+{
+       return (ulong)p[0] | (ulong)p[1]<<8;
+}
+static ulong
+gw4(uchar *p)
+{
+       return (ulong)p[0] | (ulong)p[1]<<8 | (ulong)p[2]<<16 | (ulong)p[3]<<24;
+}
+static ulong (*gw[5])(uchar *p) = {
+       [1] gw1,
+       [2] gw2,
+       [4] gw4,
+};
+
+static void
+pw1(uchar *p, ulong w)
+{
+       p[0] = w & 0xFF;
+}
+static void
+pw2(uchar *p, ulong w)
+{
+       p[0] = w & 0xFF;
+       p[1] = (w>>8) & 0xFF;
+}
+static void
+pw4(uchar *p, ulong w)
+{
+       p[0] = w & 0xFF;
+       p[1] = (w>>8) & 0xFF;
+       p[2] = (w>>16) & 0xFF;
+       p[3] = (w>>24) & 0xFF;
+}
+static void (*pw[5])(uchar *p, ulong w) = {
+       [1] pw1,
+       [2] pw2,
+       [4] pw4,
+};
+
+static ulong
+rbad(void *, ulong off, int)
+{
+       fprint(2, "bad mem read %.5lux\n", off);
+       trap(&cpu, EMEM);
+
+       /* not reached */
+       return 0;
+}
+
+static void
+wbad(void *, ulong off, ulong, int)
+{
+       fprint(2, "bad mem write %.5lux\n", off);
+       trap(&cpu, EMEM);
+}
+
+static ulong
+rmem(void *, ulong off, int len)
+{
+       return gw[len](memory + off);
+}
+
+static void
+wmem(void *, ulong off, ulong w, int len)
+{
+       pw[len](memory + off, w);
+}
+
+static ulong
+rrealmem(void *, ulong off, int len)
+{
+       uchar data[4];
+
+       if(pread(realmemfd, data, len, off) != len){
+               fprint(2, "bad real mem read %.5lux: %r\n", off);
+               trap(&cpu, EMEM);
+       }
+       return gw[len](data);
+}
+
+static void
+wrealmem(void *, ulong off, ulong w, int len)
+{
+       uchar data[4];
+
+       pw[len](data, w);
+       if(pwrite(realmemfd, data, len, off) != len){
+               fprint(2, "bad real mem write %.5lux: %r\n", off);
+               trap(&cpu, EMEM);
+       }
+}
+
+
+static ulong
+rport(void *, ulong p, int len)
+{
+       uchar data[4];
+       ulong w;
+
+       switch(p){
+       case 0x20:      /* PIC 1 */
+       case 0x21:
+               w = 0;
+               break;
+       case 0x40:
+       case 0x41:
+       case 0x42:
+       case 0x43:
+               runclock();
+               w = rpit(pit, p - 0x40);
+               break;
+       case 0x60:      /* keyboard data output buffer */
+               w = 0;
+               break;
+       case 0x61:      /* keyboard controller port b */
+               runclock();
+               w = pit[2].out<<5 | pit[2].gate;
+               break;
+       case 0x62:      /* PPI (XT only) */
+               runclock();
+               w = pit[2].out<<5;
+               break;
+       case 0x63:      /* PPI (XT only) read dip switches */
+               w = 0;
+               break;
+       case 0x65:      /* A20 gate */
+               w = 1 << 2;
+               break;
+       case 0x80:      /* extra dma registers (temp) */
+       case 0x84:
+       case 0x85:
+       case 0x86:
+       case 0x88:
+       case 0x8c:
+       case 0x8d:
+       case 0x8e:
+               w = pageregtmp[p-0x80];
+               break;
+       case 0x92:      /* A20 gate (system control port a) */
+               w = 1 << 1;
+               break;
+       case 0xa0:      /* PIC 2 */
+       case 0xa1:
+               w = 0;
+               break;
+       default:
+               if(pread(portfd[len], data, len, p) != len){
+                       fprint(2, "bad %d bit port read %.4lux: %r\n", len*8, p);
+                       trap(&cpu, EIO);
+               }
+               w = gw[len](data);
+       }
+       if(porttrace)
+               fprint(2, "rport %.4lux %.*lux\n", p, len<<1, w);
+       return w;
+}
+
+static void
+wport(void *, ulong p, ulong w, int len)
+{
+       uchar data[4];
+
+       if(porttrace)
+               fprint(2, "wport %.4lux %.*lux\n", p, len<<1, w);
+
+       switch(p){
+       case 0x20:      /* PIC 1 */
+       case 0x21:
+               break;
+       case 0x40:
+       case 0x41:
+       case 0x42:
+       case 0x43:
+               runclock();
+               wpit(pit, p - 0x40, w);
+               break;
+       case 0x60:      /* keyboard controller data port */
+               break;
+       case 0x61:      /* keyboard controller port B */
+               setgate(&pit[2], w & 1);
+               break;
+       case 0x62:      /* PPI (XT only) */
+       case 0x63:
+       case 0x64:      /* KB controller input buffer (ISA, EISA) */
+       case 0x65:      /* A20 gate (bit 2) */
+               break;
+       case 0x80:
+       case 0x84:
+       case 0x85:
+       case 0x86:
+       case 0x88:
+       case 0x8c:
+       case 0x8d:
+       case 0x8e:
+               pageregtmp[p-0x80] = w & 0xFF;
+               break;
+       case 0x92:      /* system control port a */
+       case 0x94:      /* system port enable setup register */
+       case 0x96:
+               break;
+       case 0xA0:      /* PIC 2 */
+       case 0xA1:
+               break;
+       
+       default:
+               pw[len](data, w);
+               if(pwrite(portfd[len], data, len, p) != len){
+                       fprint(2, "bad %d bit port write %.4lux: %r\n", len*8, p);
+                       trap(&cpu, EIO);
+               }
+       }
+}
+
+static Bus memio[] = {
+       /* 0 */ memory, rmem, wmem,     /* RAM: IVT, BIOS data area */
+       /* 1 */ memory, rmem, wmem,     /* custom */
+       /* 2 */ nil,    rbad, wbad,
+       /* 3 */ nil,    rbad, wbad,
+       /* 4 */ nil,    rbad, wbad,
+       /* 5 */ nil,    rbad, wbad,
+       /* 6 */ nil,    rbad, wbad,
+       /* 7 */ nil,    rbad, wbad,
+       /* 8 */ nil,    rbad, wbad,
+       /* 9 */ memory, rmem, wmem,     /* RAM: extended BIOS data area */
+       /* A */ nil,    rrealmem, wrealmem,     /* RAM: VGA framebuffer */
+       /* B */ nil,    rrealmem, wrealmem,     /* RAM: VGA framebuffer */
+       /* C */ memory, rmem, wmem,     /* ROM: VGA BIOS */
+       /* D */ nil,    rbad, wbad,
+       /* E */ memory, rmem, wbad,     /* ROM: BIOS */
+       /* F */ memory, rmem, wbad,     /* ROM: BIOS */
+};
+
+static Bus portio = {
+       nil, rport, wport,
+};
+
+static void
+cpuinit(void)
+{
+       int i;
+
+       fmtinstall('I', instfmt);
+       fmtinstall('J', flagfmt);
+       fmtinstall('C', cpufmt);
+
+       if((portfd[1] = open("#P/iob", ORDWR)) < 0)
+               sysfatal("open iob: %r");
+       if((portfd[2] = open("#P/iow", ORDWR)) < 0)
+               sysfatal("open iow: %r");
+       if((portfd[4] = open("#P/iol", ORDWR)) < 0)
+               sysfatal("open iol: %r");
+
+       if((realmemfd = open("#P/realmodemem", ORDWR)) < 0)
+               sysfatal("open realmodemem: %r");
+
+       for(i=0; i<nelem(memio); i++){
+               ulong off;
+
+               if(memio[i].r != rmem)
+                       continue;
+
+               off = (ulong)i << 16;
+               seek(realmemfd, off, 0);
+               if(readn(realmemfd, memory + off, 0x10000) != 0x10000)
+                       sysfatal("read real mem %lux: %r\n", off);
+       }
+
+       cpu.ic = 0;
+       cpu.mem = memio;
+       cpu.port = &portio;
+       cpu.alen = cpu.olen = cpu.slen = 2;
+}
+
+static char Ebusy[] = "device is busy";
+static char Eintr[] = "interrupted";
+static char Eperm[] = "permission denied";
+static char Eio[] = "i/o error";
+static char Emem[] = "bad memory access";
+static char Enonexist[] = "file does not exist";
+static char Ebadspec[] = "bad attach specifier";
+static char Ewalk[] = "walk in non directory";
+static char Ebadureg[] = "write a Ureg";
+static char Ebadoff[] = "invalid offset";
+static char Ebadtrap[] = "bad trap";
+
+static char *trapstr[] = {
+       [EDIV0] "division by zero",
+       [EDEBUG] "debug exception",
+       [ENMI] "not maskable interrupt",
+       [EBRK] "breakpoint",
+       [EINTO] "into overflow",
+       [EBOUND] "bounds check",
+       [EBADOP] "bad opcode",
+       [ENOFPU] "no fpu installed",
+       [EDBLF] "double fault",
+       [EFPUSEG] "fpu segment overflow",
+       [EBADTSS] "invalid task state segment",
+       [ENP] "segment not present",
+       [ESTACK] "stack fault",
+       [EGPF] "general protection fault",
+       [EPF] "page fault",
+};
+
+static int flushed(void *);
+
+#define GETUREG(x)     gw[sizeof(u->x)]((uchar*)&u->x)
+#define PUTUREG(x,y)   pw[sizeof(u->x)]((uchar*)&u->x,y)
+
+static char*
+realmode(Cpu *cpu, struct Ureg *u, void *r)
+{
+       char *err;
+       int i;
+
+       cpu->reg[RDI] = GETUREG(di);
+       cpu->reg[RSI] = GETUREG(si);
+       cpu->reg[RBP] = GETUREG(bp);
+       cpu->reg[RBX] = GETUREG(bx);
+       cpu->reg[RDX] = GETUREG(dx);
+       cpu->reg[RCX] = GETUREG(cx);
+       cpu->reg[RAX] = GETUREG(ax);
+
+       cpu->reg[RGS] = GETUREG(gs);
+       cpu->reg[RFS] = GETUREG(fs);
+       cpu->reg[RES] = GETUREG(es);
+       cpu->reg[RDS] = GETUREG(ds);
+
+       cpu->reg[RFL] = GETUREG(flags);
+
+       if(i = GETUREG(trap)){
+               cpu->reg[RSS] = 0x0000;
+               cpu->reg[RSP] = 0x7C00;
+               cpu->reg[RCS] = (RMCODE>>4)&0xF000;
+               cpu->reg[RIP] = RMCODE & 0xFFFF;
+               memory[RMCODE] = 0xf4;  /* HLT instruction */
+               if(intr(cpu, i) < 0)
+                       return Ebadtrap;
+       } else {
+               cpu->reg[RSS] = GETUREG(ss);
+               cpu->reg[RSP] = GETUREG(sp);
+               cpu->reg[RCS] = GETUREG(cs);
+               cpu->reg[RIP] = GETUREG(pc);
+       }
+
+       startclock();
+       for(;;){
+               if(cputrace)
+                       fprint(2, "%C\n", cpu);
+               switch(i = xec(cpu, (porttrace | cputrace) ? 1 : 100000)){
+               case -1:
+                       if(flushed(r)){
+                               err = Eintr;
+                               break;
+                       }
+                       runclock();
+                       continue;
+
+               /* normal interrupts */
+               default:
+                       if(intr(cpu, i) < 0){
+                               err = Ebadtrap;
+                               break;
+                       }
+                       continue;
+
+               /* pseudo-interrupts */
+               case EHALT:
+                       err = nil;
+                       break;
+               case EIO:
+                       err = Eio;
+                       break;
+               case EMEM:
+                       err = Emem;
+                       break;
+
+               /* processor traps */
+               case EDIV0:
+               case EDEBUG:
+               case ENMI:
+               case EBRK:
+               case EINTO:
+               case EBOUND:
+               case EBADOP:
+               case ENOFPU:
+               case EDBLF:
+               case EFPUSEG:
+               case EBADTSS:
+               case ENP:
+               case ESTACK:
+               case EGPF:
+               case EPF:
+                       PUTUREG(trap, i);
+                       err = trapstr[i];
+                       break;
+               }
+
+               break;
+       }
+
+       if(err)
+               fprint(2, "%s\n%C\n", err, cpu);
+
+       PUTUREG(di, cpu->reg[RDI]);
+       PUTUREG(si, cpu->reg[RSI]);
+       PUTUREG(bp, cpu->reg[RBP]);
+       PUTUREG(bx, cpu->reg[RBX]);
+       PUTUREG(dx, cpu->reg[RDX]);
+       PUTUREG(cx, cpu->reg[RCX]);
+       PUTUREG(ax, cpu->reg[RAX]);
+
+       PUTUREG(gs, cpu->reg[RGS]);
+       PUTUREG(fs, cpu->reg[RFS]);
+       PUTUREG(es, cpu->reg[RES]);
+       PUTUREG(ds, cpu->reg[RDS]);
+
+       PUTUREG(flags, cpu->reg[RFL]);
+
+       PUTUREG(pc, cpu->reg[RIP]);
+       PUTUREG(cs, cpu->reg[RCS]);
+       PUTUREG(sp, cpu->reg[RSP]);
+       PUTUREG(ss, cpu->reg[RSS]);
+
+       return err;
+}
+
+enum {
+       Qroot,
+       Qcall,
+       Qmem,
+       Nqid,
+};
+
+static struct Qtab {
+       char *name;
+       int mode;
+       int type;
+       int length;
+} qtab[Nqid] = {
+       "/",
+               DMDIR|0555,
+               QTDIR,
+               0,
+
+       "realmode",
+               0666,
+               0,
+               0,
+
+       "realmodemem",
+               0666,   
+               0,
+               MEMSIZE,
+};
+
+static int
+fillstat(ulong qid, Dir *d)
+{
+       struct Qtab *t;
+
+       memset(d, 0, sizeof(Dir));
+       d->uid = "realemu";
+       d->gid = "realemu";
+       d->muid = "";
+       d->qid = (Qid){qid, 0, 0};
+       d->atime = time(0);
+       t = qtab + qid;
+       d->name = t->name;
+       d->qid.type = t->type;
+       d->mode = t->mode;
+       d->length = t->length;
+       return 1;
+}
+
+static void
+fsattach(Req *r)
+{
+       char *spec;
+
+       spec = r->ifcall.aname;
+       if(spec && spec[0]){
+               respond(r, Ebadspec);
+               return;
+       }
+       r->fid->qid = (Qid){Qroot, 0, QTDIR};
+       r->ofcall.qid = r->fid->qid;
+       respond(r, nil);
+}
+
+static void
+fsstat(Req *r)
+{
+       fillstat((ulong)r->fid->qid.path, &r->d);
+       r->d.name = estrdup9p(r->d.name);
+       r->d.uid = estrdup9p(r->d.uid);
+       r->d.gid = estrdup9p(r->d.gid);
+       r->d.muid = estrdup9p(r->d.muid);
+       respond(r, nil);
+}
+
+static char*
+fswalk1(Fid *fid, char *name, Qid *qid)
+{
+       int i;
+       ulong path;
+
+       path = fid->qid.path;
+       switch(path){
+       case Qroot:
+               if (strcmp(name, "..") == 0) {
+                       *qid = (Qid){Qroot, 0, QTDIR};
+                       fid->qid = *qid;
+                       return nil;
+               }
+               for(i = fid->qid.path; i<Nqid; i++){
+                       if(strcmp(name, qtab[i].name) != 0)
+                               continue;
+                       *qid = (Qid){i, 0, 0};
+                       fid->qid = *qid;
+                       return nil;
+               }
+               return Enonexist;
+               
+       default:
+               return Ewalk;
+       }
+}
+
+static void
+fsopen(Req *r)
+{
+       static int need[4] = { 4, 2, 6, 1 };
+       struct Qtab *t;
+       int n;
+
+       t = qtab + r->fid->qid.path;
+       n = need[r->ifcall.mode & 3];
+       if((n & t->mode) != n)
+               respond(r, Eperm);
+       else
+               respond(r, nil);
+}
+
+static int
+readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
+{
+       int i, m, n;
+       long pos;
+       Dir d;
+
+       n = 0;
+       pos = 0;
+       for (i = 1; i < Nqid; i++){
+               fillstat(i, &d);
+               m = convD2M(&d, &buf[n], blen-n);
+               if(off <= pos){
+                       if(m <= BIT16SZ || m > cnt)
+                               break;
+                       n += m;
+                       cnt -= m;
+               }
+               pos += m;
+       }
+       return n;
+}
+
+static Channel *reqchan;
+
+static void
+cpuproc(void *)
+{
+       static struct Ureg rmu;
+       ulong path;
+       vlong o;
+       ulong n;
+       char *p;
+       Req *r;
+
+       threadsetname("cpuproc");
+
+       while(r = recvp(reqchan)){
+               if(flushed(r)){
+                       respond(r, Eintr);
+                       continue;
+               }
+
+               path = r->fid->qid.path;
+
+               p = r->ifcall.data;
+               n = r->ifcall.count;
+               o = r->ifcall.offset;
+
+               switch(((int)r->ifcall.type<<8)|path){
+               case (Tread<<8) | Qmem:
+                       readbuf(r, memory, MEMSIZE);
+                       respond(r, nil);
+                       break;
+
+               case (Tread<<8) | Qcall:
+                       readbuf(r, &rmu, sizeof rmu);
+                       respond(r, nil);
+                       break;
+
+               case (Twrite<<8) | Qmem:
+                       if(o < 0 || o >= MEMSIZE || o+n > MEMSIZE){
+                               respond(r, Ebadoff);
+                               break;
+                       }
+                       memmove(memory + o, p, n);
+                       r->ofcall.count = n;
+                       respond(r, nil);
+                       break;
+
+               case (Twrite<<8) | Qcall:
+                       if(n != sizeof rmu){
+                               respond(r, Ebadureg);
+                               break;
+                       }
+                       memmove(&rmu, p, n);
+                       if(p = realmode(&cpu, &rmu, r)){
+                               respond(r, p);
+                               break;
+                       }
+                       r->ofcall.count = n;
+                       respond(r, nil);
+                       break;
+               }
+       }
+}
+
+static Channel *flushchan;
+
+static int
+flushed(void *r)
+{
+       return nbrecvp(flushchan) == r;
+}
+
+static void
+fsflush(Req *r)
+{
+       nbsendp(flushchan, r->oldreq);
+       respond(r, nil);
+}
+
+static void
+dispatch(Req *r)
+{
+       if(!nbsendp(reqchan, r))
+               respond(r, Ebusy);
+}
+
+static void
+fsread(Req *r)
+{
+       switch((ulong)r->fid->qid.path){
+       case Qroot:
+               r->ofcall.count = readtopdir(r->fid, (void*)r->ofcall.data, r->ifcall.offset,
+                       r->ifcall.count, r->ifcall.count);
+               respond(r, nil);
+               break;
+       default:
+               dispatch(r);
+       }
+}
+
+static void
+fsend(Srv*)
+{
+       threadexitsall(nil);
+}
+
+static Srv fs = {
+       .attach=                fsattach,
+       .walk1=                 fswalk1,
+       .open=                  fsopen,
+       .read=                  fsread,
+       .write=                 dispatch,
+       .stat=                  fsstat,
+       .flush=                 fsflush,
+       .end=                   fsend,
+};
+
+static void
+usage(void)
+{
+       fprint(2, "usgae:\t%s [-Dpt] [-s srvname] [-m mountpoint]\n", argv0);
+       exits("usage");
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+       char *mnt = "/dev";
+       char *srv = nil;
+
+       ARGBEGIN{
+       case 'D':
+               chatty9p++;
+               break;
+       case 'p':
+               porttrace = 1;
+               break;
+       case 't':
+               cputrace = 1;
+               break;
+       case 's':
+               srv = EARGF(usage());
+               mnt = nil;
+               break;
+       case 'm':
+               mnt = EARGF(usage());
+               break;
+       default:
+               usage();
+       }ARGEND
+
+       cpuinit();
+
+       reqchan = chancreate(sizeof(Req*), 8);
+       flushchan = chancreate(sizeof(Req*), 8);
+       procrfork(cpuproc, nil, 16*1024, RFNAMEG|RFNOTEG);
+       threadpostmountsrv(&fs, srv, mnt, MBEFORE);
+}
diff --git a/sys/src/cmd/aux/realemu/mkfile b/sys/src/cmd/aux/realemu/mkfile
new file mode 100644 (file)
index 0000000..47fdf53
--- /dev/null
@@ -0,0 +1,13 @@
+</$objtype/mkfile
+
+BIN=/$objtype/bin/aux
+MAN=/sys/man/8
+
+TARG=realemu
+OFILES=decode.$O arg.$O xec.$O fmt.$O pit.$O main.$O
+HFILES=dat.h fns.h
+
+</sys/src/cmd/mkone
+
+install:V:
+       cp $TARG.man $MAN/$TARG
diff --git a/sys/src/cmd/aux/realemu/notes b/sys/src/cmd/aux/realemu/notes
new file mode 100644 (file)
index 0000000..8702703
--- /dev/null
@@ -0,0 +1,22 @@
+realmode emulator. binds itself over /dev and provides /dev/realmode
+and /dev/realmodemem to be used with aux/vga -m vesa ...
+
+the command option -t enables instruction tracing to stderr.
+
+requires a updated vgavesa driver to use /dev/realmode instead of
+a direct realmode() call.
+
+patch can be found at: /n/sources/patch/vesa-softscreen-resize
+
+a list with graphics cards that have been successfully enabled
+with the aux/vga and realemu can be found in the vgalist file.
+
+bug reports / suggestions or failed attempts email to:
+
+cinap_lenrek AT gmx DOT de
+
+contributors:
+
+i stole some code from rsc's 8i /n/sources/contrib/rsc/8i, so thanks russ! :)
+
+patient testers from irc: sl, Fish-
diff --git a/sys/src/cmd/aux/realemu/pit.c b/sys/src/cmd/aux/realemu/pit.c
new file mode 100644 (file)
index 0000000..206b935
--- /dev/null
@@ -0,0 +1,357 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+enum {
+       AC0 = 0,
+       AC1,
+       AC2,
+       Actl,
+
+       Readback = 3,
+
+       RBC0 = 1<<1,
+       RBC1 = 1<<2,
+       RBC2 = 1<<3,
+       RBlatchstatus = 1<<4,
+       RBlatchcount = 1<<5,
+
+       AMlatchcount = 0,
+       AMloonly,
+       AMhionly,
+       AMlohi,
+
+       OM0 = 0,
+       OM1,
+       OM2,
+       OM3,
+       OM4,
+       OM5,
+       OM2b,
+       OM3b,
+};
+
+static void
+latchstatus(Pit *ch)
+{
+       if(ch->rlatched)
+               return;
+       ch->rlatch[0] = ch->bcd | ch->omode<<1 | ch->amode<<4 | ch->count0<<6 | ch->out<<7;
+       ch->rcount = 0;
+       ch->rlatched = 1;
+}
+
+static void
+latchcount(Pit *ch)
+{
+       ulong w;
+
+       if(ch->rlatched)
+               return;
+       w = ch->count & 0xFFFF;
+       if(ch->bcd)
+               w = (w % 10) + ((w/10) % 10)<<4 + ((w/100) % 10)<<8 + ((w/1000) % 10)<<12;
+       ch->rlatch[0] = w & 0xFF;
+       ch->rlatch[1] = (w >> 8) & 0xFF;
+       ch->rcount = 0;
+       ch->rlatched = 1;
+       switch(ch->amode){
+       case AMhionly:
+               ch->rcount++;
+               break;
+       case AMlohi:
+               ch->rlatched++;
+               break;
+       }
+}
+
+static void
+setcount(Pit *ch)
+{
+       ulong w;
+
+       w = (ulong)ch->wlatch[0] | (ulong)ch->wlatch[1] << 8;
+       if(ch->bcd)
+               w = (w & 0xF) + 10*((w >> 4)&0xF) + 100*((w >> 8)&0xF) + 1000*((w >> 12)&0xF);
+       ch->count = w;
+       ch->count0 = 0;
+}
+
+static int
+deccount(Pit *ch, vlong *cycles)
+{
+       if(ch->count0){
+               *cycles = 0;
+               return 0;
+       } else {
+               vlong passed, remain;
+
+               passed = *cycles;
+               if(ch->count == 0){
+                       ch->count = ch->bcd ? 9999 : 0xFFFF;
+                       passed--;
+               }
+               if(passed <= ch->count){
+                       remain = 0;
+                       ch->count -= passed;
+               } else {
+                       remain = passed - ch->count;
+                       ch->count = 0;
+               }
+               *cycles = remain;
+               return ch->count == 0;
+       }
+}
+
+void
+setgate(Pit *ch, uchar gate)
+{
+       if(ch->gate == 0 && gate)
+               ch->gateraised = 1;
+       ch->gate = gate;
+}
+
+static void
+clockpit1(Pit *ch, vlong *cycles)
+{
+       switch(ch->omode){
+       case OM0:       /* Interrupt On Terminal Count */
+               if(ch->count0){
+                       setcount(ch);
+                       ch->out = 0;
+               Next:
+                       --*cycles;
+                       return;
+               }
+               if(ch->gate && deccount(ch, cycles)){
+                       ch->out = 1;
+                       return;
+               }
+               break;
+
+       case OM1:       /* Hardware Re-triggerable One-shot */
+               if(ch->gateraised){
+                       ch->gateraised = 0;
+                       setcount(ch);
+                       ch->out = 0;
+                       goto Next;
+               }
+               if(deccount(ch, cycles) && ch->out == 0){
+                       ch->out = 1;
+                       return;
+               }
+               break;
+
+       case OM2:       /* Rate Generator */
+       case OM2b:
+               ch->out = 1;
+               if(ch->count0){
+                       setcount(ch);
+                       goto Next;
+               }
+               if(ch->gate == 0)
+                       break;
+               if(ch->gateraised){
+                       ch->gateraised = 0;
+                       setcount(ch);
+                       goto Next;
+               }
+               if(deccount(ch, cycles)){
+                       setcount(ch);
+                       ch->out = 0;
+                       return;
+               }
+               break;
+
+       case OM3:       /* Square Wave Generator */
+       case OM3b:
+               if(ch->count0){
+                       setcount(ch);
+                       goto Next;
+               }
+               if(ch->gate == 0)
+                       break;
+               if(ch->gateraised){
+                       ch->gateraised = 0;
+                       setcount(ch);
+                       goto Next;
+               }
+               if(deccount(ch, cycles)){
+                       setcount(ch);
+                       ch->out ^= 1;
+                       return;
+               }
+               break;
+
+       case OM4:       /* Software Triggered Strobe */
+               ch->out = 1;
+               if(ch->count0){
+                       setcount(ch);
+                       goto Next;
+               }
+               if(ch->gate && deccount(ch, cycles)){
+                       ch->out = 0;
+                       return;
+               }
+               break;
+
+       case OM5:       /* Hardware Triggered Strobe */
+               ch->out = 1;
+               if(ch->gateraised){
+                       ch->gateraised = 0;
+                       setcount(ch);
+                       goto Next;
+               }
+               if(deccount(ch, cycles)){
+                       ch->out = 0;
+                       return;
+               }
+               break;
+       }
+       *cycles = 0;
+}
+
+void
+clockpit(Pit *pit, vlong cycles)
+{
+       Pit *ch;
+       int i;
+
+       if(cycles <= 0)
+               return;
+       for(i = 0; i<Actl; i++){
+               ch = pit + i;
+               if(ch->wlatched){
+                       vlong c;
+
+                       switch(ch->omode){
+                       case OM3:
+                       case OM3b:
+                               c = cycles * 2;
+                               break;
+                       default:
+                               c = cycles;
+                       }
+                       while(c > 0)
+                               clockpit1(ch, &c);
+               }
+               ch->gateraised = 0;
+       }
+}
+
+uchar
+rpit(Pit *pit, uchar addr)
+{
+       Pit *ch;
+       uchar data;
+
+       if(addr >= Actl)
+               return 0;
+       ch = pit + addr;
+       if(ch->rlatched){
+               data = ch->rlatch[ch->rcount & 1];
+               ch->rlatched--;
+       } else {
+               data = 0;
+               switch(ch->amode){
+               case AMloonly:
+                       data = ch->count & 0xFF;
+                       break;
+               case AMhionly:
+                       data = (ch->count >> 8) & 0xFF;
+                       break;
+               case AMlohi:
+                       data = (ch->count >> ((ch->rcount & 1)<<3)) & 0xFF;
+                       break;
+               }
+       }
+       ch->rcount++;
+       if(0) fprint(2, "rpit %p: %.2x %.2x\n", pit, (int)addr, (int)data);
+       return data;
+}
+
+void
+wpit(Pit *pit, uchar addr, uchar data)
+{
+       Pit *ch;
+
+       if(0) fprint(2, "wpit %p: %.2x %.2x\n", pit, (int)addr, (int)data);
+       if(addr > Actl)
+               return;
+       if(addr == Actl){
+               uchar sc, amode, omode, bcd;
+
+               bcd = (data & 1);
+               omode = (data >> 1) & 7;
+               amode = (data >> 4) & 3;
+               sc = (data >> 6) & 3;
+       
+               if(sc == Readback){
+                       ch = nil;
+                       for(;;){
+                               if(data & RBC0){
+                                       ch = pit;
+                                       break;
+                               }
+                               if(data & RBC1){
+                                       ch = pit + 1;
+                                       break;
+                               }
+                               if(data & RBC2){
+                                       ch = pit + 2;
+                                       break;
+                               }
+                               break;
+                       }
+                       if(ch == nil)
+                               return;
+                       if((data & RBlatchcount) == 0)
+                               latchcount(ch);
+                       if((data & RBlatchstatus) == 0)
+                               latchstatus(ch);
+                       return;
+               }
+
+               ch = pit + sc;
+               if(amode == AMlatchcount){
+                       latchcount(ch);
+                       return;
+               }
+               ch->bcd = bcd;
+               
+               ch->amode = amode;
+               ch->omode = omode;
+
+               ch->rlatched = 0;
+               ch->rcount = 0;
+               ch->rlatch[0] = 0;
+               ch->rlatch[1] = 0;
+
+               ch->wlatched = 0;
+               ch->wcount = 0;
+               ch->wlatch[0] = 0;
+               ch->wlatch[1] = 0;
+
+               ch->count0 = 1;
+               ch->out = !!omode;
+               return;
+       }
+
+       ch = pit + addr;
+       switch(ch->amode){
+       case AMloonly:
+       case AMhionly:
+               ch->wlatch[ch->amode - AMloonly] = data;
+               ch->wcount++;
+               break;
+       case AMlohi:
+               ch->wlatch[ch->wcount++ & 1] = data;
+               if(ch->wcount < 2)
+                       return;
+               break;
+       }
+       ch->wlatched = ch->wcount;
+       ch->wcount = 0;
+       ch->count0 = 1;
+}
diff --git a/sys/src/cmd/aux/realemu/realemu.man b/sys/src/cmd/aux/realemu/realemu.man
new file mode 100644 (file)
index 0000000..60763b3
--- /dev/null
@@ -0,0 +1,104 @@
+.TH realemu 8
+.SH NAME
+realemu \- software emulation of /dev/realmode
+.SH SYNOPSIS
+.B aux/realemu
+[
+.B -Dpt
+] [
+.B -s
+.I srvname
+] [
+.B -m
+.I mountpoint
+]
+.SH DESCRIPTION
+.PP
+Originally, kernel provided 
+.B /dev/realmode
+files with the
+.IR arch (3)
+device to access and call the
+.SM BIOS.
+.PP
+Interrupts had to be disabled and the processor was switched in the
+legacy 16-bit
+.SM realmode
+with memory protection disabled to execute
+.SM BIOS
+code.
+.PP
+This is problematic in case the
+.SM BIOS
+reprograms hardware currently
+used by the operating system or when it reenables interrupts or just
+crashes. This will freeze or reboot the machine with no way to
+recover or diagnose the problem.
+.PP
+To avoid this,
+.I realemu
+is used to emulate the execution of the
+.SM BIOS
+routines by interpreting the machine instructions and intercepting
+dangerous actions that would compromise the systems stability.
+.PP
+Running
+.I realemu
+with no arguments, it mounts itself before
+.B /dev
+and
+replaces the original
+.B /dev/realmode
+file in the current namespace.
+.PP
+Then programs like
+.IR vga (8)
+can use it to make ther
+.SM BIOS
+calls.
+.PP
+The
+.B D
+flag will enable debug messages for 9P.  The
+.B p
+and
+.B t
+flags
+control tracing of i/o port access and cpu instructions to
+stderr (fd 2).
+.PP
+When a
+.I srvname
+is given with the
+.B s
+argument, the default
+.I mountpoint
+is ignored and a
+.SM 9P
+channel is created in
+.B /srv
+that can be used to mount
+the filesystem from another namespace. If a
+.I mountpoint
+is given before
+the
+.I srvname
+argument then it is ignored, otherwise it will be used.
+.SH EXAMPLES
+The
+.I realemu
+process is only needed when accessing
+.B /dev/realmode.
+To invoke a subshell so that
+.I realemu
+exits normally after
+.B aux/vga
+completes:
+.IP
+.EX
+% @{rfork n; aux/realemu; aux/vga -m vesa -l $vgasize}
+.SH SOURCE
+.B /sys/src/cmd/aux/realemu
+.SH "SEE ALSO"
+.IR vga (8),
+.IR arch (3)
diff --git a/sys/src/cmd/aux/realemu/vgalist b/sys/src/cmd/aux/realemu/vgalist
new file mode 100644 (file)
index 0000000..3a05305
--- /dev/null
@@ -0,0 +1,9 @@
+#vid   did     bios    wired   product name
+100b   0030    5.30    STI     NSC Geode GX2
+5533   8c2e    1.0     -       T23 / S3 savage
+1002   791e    01.00   -       ATI RS690
+10de   002c    B1      STI     NVidia RivaTNT
+15ad   0405    2.0     -       VMware
+-      -       1.26    -       Bochs
+102b   0519    00      STI     Matrox MILLENNIUM
+5333   8901    Rev E   -       S3 Trio64V2/DX/GX
diff --git a/sys/src/cmd/aux/realemu/xec.c b/sys/src/cmd/aux/realemu/xec.c
new file mode 100644 (file)
index 0000000..8d63e61
--- /dev/null
@@ -0,0 +1,1224 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+#define sign(s)        (1UL<<((s)-1))
+#define mask(s) (sign(s)|(sign(s)-1))
+
+int cputrace;
+
+static void
+push(Iarg *sp, Iarg *a)
+{
+       Iarg *p;
+
+       p = amem(sp->cpu, a->len, RSS, ar(sp));
+       p->off -= a->len;
+       aw(p, ar(a));
+       aw(sp, p->off);
+}
+
+static void
+pop(Iarg *sp, Iarg *a)
+{
+       Iarg *p;
+
+       p = amem(sp->cpu, a->len, RSS, ar(sp));
+       aw(a, ar(p));
+       aw(sp, p->off + a->len);
+}
+
+static void
+jump(Iarg *to)
+{
+       Cpu *cpu;
+
+       cpu = to->cpu;
+       switch(to->atype){
+       default:
+               abort();
+       case AMp:
+               to = afar(to, 1, to->len);
+       case AAp:
+               cpu->reg[RCS] = to->seg;
+       case AJb:
+       case AJv:
+               cpu->reg[RIP] = to->off;
+               break;
+       case AEv:
+               cpu->reg[RIP] = ar(to);
+               break;
+       }
+}
+
+static void
+opcall(Cpu *cpu, Inst *i)
+{
+       Iarg *sp;
+
+       sp = areg(cpu, cpu->slen, RSP);
+       switch(i->a1->atype){
+       default:
+               abort();
+       case AAp:
+       case AMp:
+               push(sp, areg(cpu, i->olen, RCS));
+       case AJv:
+       case AEv:
+               push(sp, areg(cpu, i->olen, RIP));
+               break;
+       }
+       jump(i->a1);
+}
+
+static void
+opint(Cpu *cpu, Inst *i)
+{
+       cpu->trap = ar(i->a1);
+       longjmp(cpu->jmp, 1);
+}
+
+static void
+opiret(Cpu *cpu, Inst *i)
+{
+       Iarg *sp;
+
+       if(i->olen != 2)
+               trap(cpu, EBADOP);
+       sp = areg(cpu, cpu->slen, RSP);
+       pop(sp, areg(cpu, 2, RIP));
+       pop(sp, areg(cpu, 2, RCS));
+       pop(sp, areg(cpu, 2, RFL));
+}
+
+static void
+opret(Cpu *cpu, Inst *i)
+{
+       Iarg *sp;
+       ulong c;
+
+       sp = areg(cpu, cpu->slen, RSP);
+       pop(sp, areg(cpu, i->olen, RIP));
+       if(c = ar(i->a1))
+               aw(sp, ar(sp) + c);
+}
+
+static void
+opretf(Cpu *cpu, Inst *i)
+{
+       Iarg *sp;
+       ulong c;
+
+       sp = areg(cpu, cpu->slen, RSP);
+       pop(sp, areg(cpu, i->olen, RIP));
+       pop(sp, areg(cpu, i->olen, RCS));
+       if(c = ar(i->a1))
+               aw(sp, ar(sp) + c);
+}
+
+static void
+openter(Cpu *cpu, Inst *i)
+{
+       Iarg *sp, *bp;
+       ulong oframe, nframe;
+       int j, n;
+
+       sp = areg(cpu, cpu->slen, RSP);
+       bp = areg(cpu, cpu->slen, RBP);
+       push(sp, bp);
+       oframe = ar(bp);
+       nframe = ar(sp);
+       n = ar(i->a2) % 32;
+       if(n > 0){
+               for(j=1; j<n; j++){
+                       aw(bp, oframe - i->olen*j);
+                       push(sp, bp);
+               }
+               push(sp, acon(cpu, i->olen, nframe));
+       }
+       aw(bp, nframe);
+       aw(sp, nframe - ar(i->a1));
+}
+
+static void
+opleave(Cpu *cpu, Inst *i)
+{
+       Iarg *sp;
+
+       sp = areg(cpu, cpu->slen, RSP);
+       aw(sp, ar(areg(cpu, cpu->slen, RBP)));
+       pop(sp, areg(cpu, i->olen, RBP));
+}
+
+static void
+oppush(Cpu *cpu, Inst *i)
+{
+       Iarg *sp;
+
+       sp = areg(cpu, cpu->slen, RSP);
+       if(i->a1->len == 1)     /* 0x6A push imm8 */
+               push(sp, acon(cpu, i->olen, ar(i->a1)));
+       else
+               push(sp, i->a1);
+}
+
+static void
+oppop(Cpu *cpu, Inst *i)
+{
+       pop(areg(cpu, cpu->slen, RSP), i->a1);
+}
+
+static void
+oppusha(Cpu *cpu, Inst *i)
+{
+       Iarg *sp, *osp;
+
+       sp = areg(cpu, cpu->slen, RSP);
+       osp = acon(cpu, i->olen, ar(sp));
+       push(sp, areg(cpu, i->olen, RAX));
+       push(sp, areg(cpu, i->olen, RCX));
+       push(sp, areg(cpu, i->olen, RDX));
+       push(sp, areg(cpu, i->olen, RBX));
+       push(sp, osp);
+       push(sp, areg(cpu, i->olen, RBP));
+       push(sp, areg(cpu, i->olen, RSI));
+       push(sp, areg(cpu, i->olen, RDI));
+}
+
+static void
+oppopa(Cpu *cpu, Inst *i)
+{
+       Iarg *sp;
+
+       sp = areg(cpu, cpu->slen, RSP);
+       pop(sp, areg(cpu, i->olen, RDI));
+       pop(sp, areg(cpu, i->olen, RSI));
+       pop(sp, areg(cpu, i->olen, RBP));
+       pop(sp, areg(cpu, i->olen, RBX));       // RSP
+       pop(sp, areg(cpu, i->olen, RBX));
+       pop(sp, areg(cpu, i->olen, RDX));
+       pop(sp, areg(cpu, i->olen, RCX));
+       pop(sp, areg(cpu, i->olen, RAX));
+}
+
+static void
+oppushf(Cpu *cpu, Inst *i)
+{
+       push(areg(cpu, cpu->slen, RSP), areg(cpu, i->olen, RFL));
+}
+
+static void
+oppopf(Cpu *cpu, Inst *i)
+{
+       ulong *f, o;
+
+       f = cpu->reg + RFL;
+       o = *f;
+       pop(areg(cpu, cpu->slen, RSP), areg(cpu, i->olen, RFL));
+       *f &= ~(VM|RF);
+       *f |= (o & (VM|RF));
+}
+
+static void
+oplahf(Cpu *cpu, Inst *i)
+{
+       aw(i->a1, cpu->reg[RFL]);
+}
+
+static void
+opsahf(Cpu *cpu, Inst *i)
+{
+       enum { MASK = SF|ZF|AF|PF|CF };
+       ulong *f;
+
+       f = cpu->reg + RFL;
+       *f &= ~MASK;
+       *f |= (ar(i->a1) & MASK);
+}
+
+static void
+opcli(Cpu *cpu, Inst *)
+{
+       cpu->reg[RFL] &= ~IF;
+}
+
+static void
+opsti(Cpu *cpu, Inst *)
+{
+       cpu->reg[RFL] |= IF;
+}
+
+static void
+opcld(Cpu *cpu, Inst *)
+{
+       cpu->reg[RFL] &= ~DF;
+}
+
+static void
+opstd(Cpu *cpu, Inst *)
+{
+       cpu->reg[RFL] |= DF;
+}
+
+static void
+opclc(Cpu *cpu, Inst *)
+{
+       cpu->reg[RFL] &= ~CF;
+}
+
+static void
+opstc(Cpu *cpu, Inst *)
+{
+       cpu->reg[RFL] |= CF;
+}
+
+static void
+opcmc(Cpu *cpu, Inst *)
+{
+       cpu->reg[RFL] ^= CF;
+}
+
+static void
+parity(ulong *f, ulong r)
+{
+       static ulong tab[8] = {
+               0x96696996,
+               0x69969669,
+               0x69969669,
+               0x96696996,
+               0x69969669,
+               0x96696996,
+               0x96696996,
+               0x69969669,
+       };
+       r &= 0xFF;
+       if((tab[r/32] >> (r%32)) & 1)
+               *f &= ~PF;
+       else
+               *f |= PF;
+}
+
+static ulong
+test(ulong *f, long r, int s)
+{
+       *f &= ~(CF|SF|ZF|OF|PF);
+       r &= mask(s);
+       if(r == 0)
+               *f |= ZF;
+       if(r & sign(s))
+               *f |= SF;
+       parity(f, r);
+       return r;
+}
+
+static void
+opshl(Cpu *cpu, Inst *i)
+{
+       ulong *f, r, a, h;
+       int s, n;
+
+       if((n = ar(i->a2) & 31) == 0)
+               return;
+       s = i->a1->len*8;
+       a = ar(i->a1);
+       f = cpu->reg + RFL;
+       r = test(f, a<<n, s);
+       h = sign(s);
+       aw(i->a1, r);
+       if((a<<(n-1)) & h)
+               *f |= CF;
+       if(n == 1 && ((a^r) & h))
+               *f |= OF;
+}
+
+static void
+opshr(Cpu *cpu, Inst *i)
+{
+       ulong *f, a;
+       int s, n;
+
+       if((n = ar(i->a2) & 31) == 0)
+               return;
+       s = i->a1->len*8;
+       a = ar(i->a1);
+       f = cpu->reg + RFL;
+       aw(i->a1, test(f, a>>n, s));
+       if(a & sign(n))
+               *f |= CF;
+       if(n == 1 && (a & sign(s)))
+               *f |= OF;
+}
+
+static void
+opsar(Cpu *cpu, Inst *i)
+{
+       ulong *f;
+       long a;
+       int n;
+
+       if((n = ar(i->a2) & 31) == 0)
+               return;
+       a = ars(i->a1);
+       f = cpu->reg + RFL;
+       aw(i->a1, test(f, a>>n, i->a1->len*8));
+       if(a & sign(n))
+               *f |= CF;
+}
+
+static void
+opshld(Cpu *cpu, Inst *i)
+{
+       ulong *f, a;
+       int s, n;
+
+       if((n = ar(i->a3) & 31) == 0)
+               return;
+       s = i->a1->len*8;
+       a = ar(i->a1);
+       f = cpu->reg + RFL;
+       aw(i->a1, test(f, (a<<n)|(ar(i->a2)>>(s-n)), s));
+       if((a<<(n-1)) & sign(s))
+               *f |= CF;
+}
+
+static void
+opshrd(Cpu *cpu, Inst *i)
+{
+       ulong *f, a;
+       int s, n;
+
+       if((n = ar(i->a3) & 31) == 0)
+               return;
+       s = i->a1->len*8;
+       a = ar(i->a1);
+       f = cpu->reg + RFL;
+       aw(i->a1, test(f, (a>>n)|(ar(i->a2)<<(s-n)), s));
+       if(a & sign(n))
+               *f |= CF;
+}
+
+
+static void
+oprcl(Cpu *cpu, Inst *i)
+{
+       ulong *f, a, r;
+       int s, n;
+
+       s = i->a1->len*8;
+       n = ar(i->a2) % (s+1);
+       a = ar(i->a1);
+       r = (a<<n) | ((a>>(s-n))>>1);
+       f = cpu->reg + RFL;
+       if(*f & CF)
+               r |= sign(n);
+       aw(i->a1, r);
+       *f &= ~(CF|OF);
+       if((a>>(s-n)) & 1)
+               *f |= CF;
+       if((a ^ r) & sign(s))
+               *f |= OF;
+       parity(f, r);
+}
+
+static void
+oprcr(Cpu *cpu, Inst *i)
+{
+       ulong *f, a, r, h;
+       int s, n;
+
+       s = i->a1->len*8;
+       n = ar(i->a2) % (s+1);
+       a = ar(i->a1);
+       h = a<<(s-n);
+       r = (a>>n) | (h<<1);
+       f = cpu->reg + RFL;
+       if(*f & CF)
+               r |= 1<<(s-n);
+       aw(i->a1, r);
+       *f &= ~(CF|OF);
+       if(h & sign(s))
+               *f |= CF;
+       if((a ^ r) & sign(s))
+               *f |= OF;
+       parity(f, r);
+}
+
+static void
+oprol(Cpu *cpu, Inst *i)
+{
+       ulong *f, a, r;
+       int s, n;
+
+       s = i->a1->len*8;
+       n = ar(i->a2) & (s-1);
+       a = ar(i->a1);
+       r = (a<<n) | (a>>(s-n));
+       f = cpu->reg + RFL;
+       aw(i->a1, r);
+       *f &= ~(CF|OF);
+       if(r & 1)
+               *f |= CF;
+       if((a ^ r) & sign(s))
+               *f |= OF;
+       parity(f, r);
+}
+
+static void
+opror(Cpu *cpu, Inst *i)
+{
+       ulong *f, a, r;
+       int s, n;
+
+       s = i->a1->len*8;
+       n = ar(i->a2) & (s-1);
+       a = ar(i->a1);
+       r = (a>>n) | (a<<(s-n));
+       aw(i->a1, r);
+       f = cpu->reg + RFL;
+       *f &= ~(CF|OF);
+       if(r & sign(s))
+               *f |= CF;
+       if((a ^ r) & sign(s))
+               *f |= OF;
+       parity(f, r);
+}
+
+static void
+opbts(Cpu *cpu, Inst *i)
+{
+       ulong a, m;
+       int n;
+
+       a = ar(i->a1);
+       n = ar(i->a2) & 31;
+       m = 1<<n;
+       if(a & m)
+               cpu->reg[RFL] |= CF;
+       else {
+               cpu->reg[RFL] &= ~CF;
+               aw(i->a1, a | m);
+       }
+}
+
+static void
+opbtr(Cpu *cpu, Inst *i)
+{
+       ulong a, m;
+       int n;
+
+       a = ar(i->a1);
+       n = ar(i->a2) & 31;
+       m = 1<<n;
+       if(a & m){
+               cpu->reg[RFL] |= CF;
+               aw(i->a1, a & ~m);
+       } else
+               cpu->reg[RFL] &= ~CF;
+}
+
+static void
+opbitscan(Cpu *cpu, Inst *i)
+{
+       ulong a;
+
+       if((a = ar(i->a2)) == 0)
+               cpu->reg[RFL] |= ZF;
+       else {
+               int j;
+
+               if(i->op == OBSF){
+                       for(j = 0; (a & (1<<j)) == 0; j++)
+                               ;
+               } else {
+                       for(j = i->a2->len*8-1; (a & (1<<j)) == 0; j--)
+                               ;
+               }
+               aw(i->a1, j);
+               cpu->reg[RFL] &= ~ZF;
+       }
+}
+
+static void
+opand(Cpu *cpu, Inst *i)
+{
+       aw(i->a1, test(cpu->reg + RFL, ars(i->a1) & ars(i->a2), i->a1->len*8));
+}
+
+static void
+opor(Cpu *cpu, Inst *i)
+{
+       aw(i->a1, test(cpu->reg + RFL, ars(i->a1) | ars(i->a2), i->a1->len*8));
+}
+
+static void
+opxor(Cpu *cpu, Inst *i)
+{
+       aw(i->a1, test(cpu->reg + RFL, ars(i->a1) ^ ars(i->a2), i->a1->len*8));
+}
+
+static void
+opnot(Cpu *, Inst *i)
+{
+       aw(i->a1, ~ar(i->a1));
+}
+
+static void
+optest(Cpu *cpu, Inst *i)
+{
+       test(cpu->reg + RFL, ars(i->a1) & ars(i->a2), i->a1->len*8);
+}
+
+static ulong
+add(ulong *f, long a, long b, int c, int s)
+{
+       ulong r, cc, m, n;
+
+       *f &= ~(AF|CF|SF|ZF|OF|PF);
+
+       n = sign(s);
+       m = mask(s);
+       r = a + b + c;
+       r &= m;
+       if(r == 0)
+               *f |= ZF;
+       if(r & n)
+               *f |= SF;
+       cc = (a & b) | (~r & (a | b));
+       if(cc & n)
+               *f |= CF;
+       if((cc ^ (cc >> 1)) & (n>>1))
+               *f |= OF;
+       parity(f, r);
+       return r;
+}
+
+static ulong
+sub(ulong *f, long a, long b, int c, int s)
+{
+       ulong r, bc, n;
+
+       *f &= ~(AF|CF|SF|ZF|OF|PF);
+
+       r = a - b - c;
+       n = sign(s);
+       r &= mask(s);
+       if(r == 0)
+               *f |= ZF;
+       if(r & n)
+               *f |= SF;
+       a = ~a;
+       bc = (a & b) | (r & (a | b));
+       if(bc & n)
+               *f |= CF;
+       if((bc ^ (bc >> 1)) & (n>>1))
+               *f |= OF;
+       parity(f, r);
+       return r;
+}
+
+static void
+opadd(Cpu *cpu, Inst *i)
+{
+       aw(i->a1, add(cpu->reg + RFL, ars(i->a1), ars(i->a2), 0, i->a1->len*8));
+}
+
+static void
+opadc(Cpu *cpu, Inst *i)
+{
+       ulong *f = cpu->reg + RFL;
+
+       aw(i->a1, add(f, ars(i->a1), ars(i->a2), (*f & CF) != 0, i->a1->len*8));
+}
+
+static void
+opsub(Cpu *cpu, Inst *i)
+{
+       aw(i->a1, sub(cpu->reg + RFL, ars(i->a1), ars(i->a2), 0, i->a1->len*8));
+}
+
+static void
+opsbb(Cpu *cpu, Inst *i)
+{
+       ulong *f = cpu->reg + RFL;
+
+       aw(i->a1, sub(f, ars(i->a1), ars(i->a2), (*f & CF) != 0, i->a1->len*8));
+}
+
+static void
+opneg(Cpu *cpu, Inst *i)
+{
+       aw(i->a1, sub(cpu->reg + RFL, 0, ars(i->a1), 0, i->a1->len*8));
+}
+
+static void
+opcmp(Cpu *cpu, Inst *i)
+{
+       sub(cpu->reg + RFL, ars(i->a1), ars(i->a2), 0, i->a1->len*8);
+}
+
+static void
+opinc(Cpu *cpu, Inst *i)
+{
+       ulong *f, o;
+
+       f = cpu->reg + RFL;
+       o = *f;
+       aw(i->a1, add(f, ars(i->a1), 1, 0, i->a1->len*8));
+       *f = (*f & ~CF) | (o & CF);
+}
+
+static void
+opdec(Cpu *cpu, Inst *i)
+{
+       ulong *f, o;
+
+       f = cpu->reg + RFL;
+       o = *f;
+       aw(i->a1, sub(f, ars(i->a1), 1, 0, i->a1->len*8));
+       *f = (*f & ~CF) | (o & CF);
+}
+
+static void
+opmul(Cpu *cpu, Inst *i)
+{
+       Iarg *la, *ha;
+       ulong l, h, m;
+       uvlong r;
+       int s;
+
+       s = i->a2->len*8;
+       m = mask(s);
+       r = ar(i->a2) * ar(i->a3);
+       l = r & m;
+       h = (r >> s) & m;
+       if(i->a1->atype != AAX)
+               abort();
+       la = areg(cpu, i->a2->len, RAX);
+       if(s == 8){
+               ha = adup(la);
+               ha->tag |= TH;
+       } else
+               ha = areg(cpu, i->a2->len, RDX);
+       aw(la, l);
+       aw(ha, h);
+       if(h)
+               cpu->reg[RFL] |= (CF|OF);
+       else
+               cpu->reg[RFL] &= ~(CF|OF);
+}
+
+static void
+opimul(Cpu *cpu, Inst *i)
+{
+       ulong l, h, m, n;
+       vlong r;
+       int s;
+
+       s = i->a2->len*8;
+       m = mask(s);
+       n = sign(s);
+       r = ars(i->a2) * ars(i->a3);
+       h = (r >> s) & m;
+       l = r & m;
+       if(i->a1->atype == AAX){
+               Iarg *la, *ha;
+
+               la = areg(cpu, i->a2->len, RAX);
+               if(s == 8){
+                       ha = adup(la);
+                       ha->tag |= TH;
+               }else
+                       ha = areg(cpu, i->a2->len, RDX);
+               aw(la, l);
+               aw(ha, h);
+       } else
+               aw(i->a1, l);
+       if((r > (vlong)n-1) || (r < -(vlong)n))
+               cpu->reg[RFL] |= (CF|OF);
+       else
+               cpu->reg[RFL] &= ~(CF|OF);
+}
+
+static void
+opdiv(Cpu *cpu, Inst *i)
+{
+       Iarg *qa, *ra;
+       uvlong n, q;
+       ulong m, r, d;
+       int s;
+
+       s = i->a1->len*8;
+       m = mask(s);
+       d = ar(i->a1);
+       if(d == 0)
+               trap(cpu, EDIV0);
+       if(s == 8){
+               qa = areg(cpu, 1, RAX);
+               ra = adup(qa);
+               ra->tag |= TH;
+       } else {
+               qa = areg(cpu, i->olen, RAX);
+               ra = areg(cpu, i->olen, RDX);
+       }
+       n = (uvlong)ar(ra)<<s | (uvlong)ar(qa);
+       q = n/d;
+       if(q > m)
+               trap(cpu, EGPF);
+       r = n%d;
+       aw(ra, r);
+       aw(qa, q);
+}
+       
+
+static int
+cctrue(Cpu *cpu, Inst *i)
+{
+       enum { SO = 1<<16,      /* pseudo-flag SF != OF */ };
+       static ulong test[] = {
+               OF,     /* JO, JNO */
+               CF,     /* JC, JNC */
+               ZF,     /* JZ, JNZ */
+               CF|ZF,  /* JBE,JA  */
+               SF,     /* JS, JNS */
+               PF,     /* JP, JNP */
+               SO,     /* JL, JGE */
+               SO|ZF,  /* JLE,JG  */
+       };
+       ulong f, t;
+       uchar c;
+
+       c = i->code;
+       switch(c){
+       case 0xE3:      /* JCXZ */
+               return ar(areg(cpu, i->alen, RCX)) == 0;
+       case 0xEB:      /* JMP */
+       case 0xE9:
+       case 0xEA:
+       case 0xFF:
+               return 1;
+       default:
+               f = cpu->reg[RFL];
+               if(((f&SF)!=0) ^ ((f&OF)!=0))
+                       f |= SO;
+               t = test[(c>>1)&7];
+               return ((t&f) != 0) ^ (c&1);
+       }
+}
+
+static void
+opjump(Cpu *cpu, Inst *i)
+{
+       if(cctrue(cpu, i))
+               jump(i->a1);
+}
+
+static void
+oploop(Cpu *cpu, Inst *i)
+{
+       Iarg *cx;
+       ulong c;
+
+       switch(i->op){
+       default:
+               abort();
+       case OLOOPNZ:
+               if(cpu->reg[RFL] & ZF)
+                       return;
+               break;
+       case OLOOPZ:
+               if((cpu->reg[RFL] & ZF) == 0)
+                       return;
+               break;
+       case OLOOP:
+               break;
+       }
+       cx = areg(cpu, i->alen, RCX);
+       c = ar(cx) - 1;
+       aw(cx, c);
+       if(c)
+               jump(i->a1);
+}
+
+static void
+oplea(Cpu *, Inst *i)
+{
+       aw(i->a1, i->a2->off);
+}
+
+static void
+opmov(Cpu *, Inst *i)
+{
+       aw(i->a1, ar(i->a2));
+}
+
+static void
+opcbw(Cpu *cpu, Inst *i)
+{
+       aw(areg(cpu, i->olen, RAX), ars(areg(cpu, i->olen>>1, RAX)));
+}
+
+static void
+opcwd(Cpu *cpu, Inst *i)
+{
+       aw(areg(cpu, i->olen, RDX), ars(areg(cpu, i->olen, RAX))>>(i->olen*8-1));
+}
+
+static void
+opmovsx(Cpu *, Inst *i)
+{
+       aw(i->a1, ars(i->a2));
+}
+
+static void
+opxchg(Cpu *, Inst *i)
+{
+       ulong x;
+
+       x = ar(i->a1);
+       aw(i->a1, ar(i->a2));
+       aw(i->a2, x);
+}
+
+static void
+oplfp(Cpu *, Inst *i)
+{
+       Iarg *p;
+
+       p = afar(i->a3, i->olen, i->olen);
+       aw(i->a1, p->seg);
+       aw(i->a2, p->off);
+}
+
+static void
+opbound(Cpu *cpu, Inst *i)
+{
+       ulong p, s, e;
+
+       p = ar(i->a1);
+       s = ar(i->a2);
+       e = ar(i->a3);
+       if((p < s) || (p >= e))
+               trap(cpu, EBOUND);
+}
+
+static void
+opxlat(Cpu *cpu, Inst *i)
+{
+       aw(i->a1, ar(amem(cpu, i->a1->len, i->sreg, ar(areg(cpu, i->alen, i->a2->reg)) + ar(i->a1))));
+}
+
+static void
+opcpuid(Cpu *cpu, Inst *)
+{
+       static struct {
+               ulong level;
+
+               ulong ax;
+               ulong bx;
+               ulong cx;
+               ulong dx;
+       } tab[] = {
+               0,
+                       5,
+                       0x756e6547,
+                       0x49656e69,
+                       0x6c65746e,
+               1,
+                       4<<8,
+                       0x00000000,
+                       0x00000000,
+                       0x00000000,
+               2,
+                       0x00000000,
+                       0x00000000,
+                       0x00000000,
+                       0x00000000,
+               3,
+                       0x00000000,
+                       0x00000000,
+                       0x00000000,
+                       0x00000000,
+       };
+
+       int i;
+
+       for(i=0; i<nelem(tab); i++){
+               if(tab[i].level == cpu->reg[RAX]){
+                       cpu->reg[RAX] = tab[i].ax;
+                       cpu->reg[RBX] = tab[i].bx;
+                       cpu->reg[RCX] = tab[i].cx;
+                       cpu->reg[RDX] = tab[i].dx;
+                       return;
+               }
+       }
+       trap(cpu, EBADOP);
+}
+
+static void
+opmovs(Cpu *cpu, Inst *i)
+{
+       Iarg *cx, *d, *s;
+       ulong c;
+       int n;
+
+       d = adup(i->a1);
+       s = adup(i->a2);
+       n = s->len;
+       if(cpu->reg[RFL] & DF)
+               n = -n;
+       if(i->rep){
+               cx = areg(cpu, i->alen, RCX);
+               c = ar(cx);
+       } else {
+               cx = nil;
+               c = 1;
+       }
+       while(c){
+               aw(d, ar(s));
+               d->off += n;
+               s->off += n;
+               c--;
+       }
+       aw(areg(cpu, i->alen, RDI), d->off);
+       aw(areg(cpu, i->alen, RSI), s->off);
+       if(cx)
+               aw(cx, 0);
+}
+
+static void
+oplods(Cpu *cpu, Inst *i)
+{
+       Iarg *cx, *s;
+       ulong c;
+       int n;
+
+       s = adup(i->a2);
+       n = s->len;
+       if(cpu->reg[RFL] & DF)
+               n = -n;
+       if(i->rep){
+               cx = areg(cpu, i->alen, RCX);
+               c = ar(cx);
+       } else {
+               cx = nil;
+               c = 1;
+       }
+       if(c){
+               s->off += n*(c-1);
+               aw(i->a1, ar(s));
+               s->off += n;
+       }
+       aw(areg(cpu, i->alen, RSI), s->off);
+       if(cx)
+               aw(cx, 0);
+}
+
+static void
+opstos(Cpu *cpu, Inst *i)
+{
+       Iarg *cx, *d;
+       ulong c, a;
+       int n;
+
+       d = adup(i->a1);
+       n = d->len;
+       if(cpu->reg[RFL] & DF)
+               n = -n;
+       if(i->rep){
+               cx = areg(cpu, i->alen, RCX);
+               c = ar(cx);
+       } else {
+               cx = nil;
+               c = 1;
+       }
+       a = ar(i->a2);
+       while(c){
+               aw(d, a);
+               d->off += n;
+               c--;
+       }
+       aw(areg(cpu, i->alen, RDI), d->off);
+       if(cx)
+               aw(cx, 0);
+}
+
+static void
+opin(Cpu *cpu, Inst *i)
+{
+       Bus *io;
+
+       io = cpu->port;
+       aw(i->a1, io->r(io->aux, ar(i->a2) & 0xFFFF, i->a1->len));
+}
+
+static void
+opout(Cpu *cpu, Inst *i)
+{
+       Bus *io;
+
+       io = cpu->port;
+       io->w(io->aux, ar(i->a1) & 0xFFFF, ar(i->a2), i->a2->len);
+}
+
+static void
+opnop(Cpu *, Inst *)
+{
+}
+
+static void
+ophlt(Cpu *cpu, Inst *)
+{
+       trap(cpu, EHALT);
+}
+
+static void (*exctab[NUMOP])(Cpu *cpu, Inst*) = {
+       [OINT] = opint,
+       [OIRET] = opiret,
+
+       [OCALL] = opcall,
+       [OJUMP] = opjump,
+
+       [OLOOP] = oploop,
+       [OLOOPZ] = oploop,
+       [OLOOPNZ] = oploop,
+
+       [ORET] = opret,
+       [ORETF] = opretf,
+
+       [OENTER] = openter,
+       [OLEAVE] = opleave,
+
+       [OPUSH] = oppush,
+       [OPOP] = oppop,
+
+       [OPUSHF] = oppushf,
+       [OPOPF] = oppopf,
+       [OLAHF] = oplahf,
+       [OSAHF] = opsahf,
+
+       [OPUSHA] = oppusha,
+       [OPOPA] = oppopa,
+
+       [OCLI] = opcli,
+       [OSTI] = opsti,
+       [OCLC] = opclc,
+       [OSTC] = opstc,
+       [OCMC] = opcmc,
+       [OCLD] = opcld,
+       [OSTD] = opstd,
+
+       [OSHL] = opshl,
+       [OSHR] = opshr,
+       [OSAR] = opsar,
+
+       [OSHLD] = opshld,
+       [OSHRD] = opshrd,
+
+       [ORCL] = oprcl,
+       [ORCR] = oprcr,
+       [OROL] = oprol,
+       [OROR] = opror,
+
+       [OBTS] = opbts,
+       [OBTR] = opbtr,
+       [OBSF] = opbitscan,
+       [OBSR] = opbitscan,
+
+       [OAND] = opand,
+       [OOR] = opor,
+       [OXOR] = opxor,
+       [ONOT] = opnot,
+       [OTEST] = optest,
+
+       [OADD] = opadd,
+       [OADC] = opadc,
+       [OSUB] = opsub,
+       [OSBB] = opsbb,
+       [ONEG] = opneg,
+       [OCMP] = opcmp,
+
+       [OINC] = opinc,
+       [ODEC] = opdec,
+
+       [OMUL] = opmul,
+       [OIMUL] = opimul,
+       [ODIV] = opdiv,
+
+       [OLEA] = oplea,
+       [OMOV] = opmov,
+       [OCBW] = opcbw,
+       [OCWD] = opcwd,
+       [OMOVZX] = opmov,
+       [OMOVSX] = opmovsx,
+       [OXCHG] = opxchg,
+       [OLFP] = oplfp,
+       [OBOUND] = opbound,
+       [OXLAT] = opxlat,
+
+       [OCPUID] = opcpuid,
+
+       [OMOVS] = opmovs,
+       [OSTOS] = opstos,
+       [OLODS] = oplods,
+
+       [OIN] = opin,
+       [OOUT] = opout,
+
+       [ONOP] = opnop,
+       [OHLT] = ophlt,
+};
+
+void
+trap(Cpu *cpu, int e)
+{
+       cpu->reg[RIP] = cpu->oldip;
+       cpu->trap = e;
+       longjmp(cpu->jmp, 1);
+}
+
+int
+intr(Cpu *cpu, int v)
+{
+       Iarg *sp, *ip, *cs, *iv;
+
+       if(v < 0 || v > 0xff || cpu->olen != 2)
+               return -1;
+
+       sp = areg(cpu, cpu->slen, RSP);
+       cs = areg(cpu, 2, RCS);
+       ip = areg(cpu, 2, RIP);
+
+       iv = amem(cpu, 2, R0S, v * 4);
+
+       push(sp, areg(cpu, 2, RFL));
+       push(sp, cs);
+       push(sp, ip);
+
+       cpu->reg[RIP] = ar(iv);
+       iv->off += 2;
+       cpu->reg[RCS] = ar(iv);
+       return 0;
+}
+
+int
+xec(Cpu *cpu, int n)
+{
+       if(setjmp(cpu->jmp))
+               return cpu->trap;
+       while(n--){
+               void (*f)(Cpu *, Inst *);
+               Iarg *ip;
+               Inst i;
+
+               cpu->ic++;
+
+               ip = amem(cpu, 1, RCS, cpu->oldip = cpu->reg[RIP]);
+               decode(ip, &i);
+               cpu->reg[RIP] = ip->off;
+               if((f = exctab[i.op]) == nil)
+                       trap(cpu, EBADOP);
+               f(cpu, &i);
+       }
+       return n;
+}
diff --git a/tmp/.dummy b/tmp/.dummy
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/usr/glenda/bin/rc/pull b/usr/glenda/bin/rc/pull
new file mode 100755 (executable)
index 0000000..42b5ecc
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/rc
+
+rfork e
+flags=()
+while(! ~ $#* 0 && ~ $1 -*){
+       if(~ $1 -c -s){
+               flags=($flags $1)
+               shift
+       }
+       flags=($flags $1)
+       shift
+}
+if(test -f /srv/kfs.cmd)
+       disk/kfscmd allow
+replica/pull -v $flags /dist/replica/network $*
+if(test -f /srv/kfs.cmd)
+       disk/kfscmd disallow
diff --git a/usr/glenda/bin/rc/riostart b/usr/glenda/bin/rc/riostart
new file mode 100755 (executable)
index 0000000..c8515d0
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/rc
+
+scr=(`{cat /dev/draw/new >[2]/dev/null || status=''})
+wid=$scr(11)
+ht=$scr(12)
+
+window 0,0,161,117 stats -lmisce
+window 161,0,560,117 faces -i
+
+if(~ `{screensize} small)
+       dump=acme.dump.small
+if not
+       dump=acme.dump
+
+a=`{echo $wid-35 | hoc }
+window 60,90,$a,$ht acme -l lib/$dump
+window 20,140,610,450 /usr/glenda/lib/first.window
diff --git a/usr/glenda/bin/rc/screensize b/usr/glenda/bin/rc/screensize
new file mode 100755 (executable)
index 0000000..e38ed4d
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/rc
+
+scr=(`{cat /dev/draw/new >[2]/dev/null || status=''})
+wid=$scr(11)
+ht=$scr(12)
+if(test $wid -le 1024)
+       echo small
+if not
+       echo normal
diff --git a/usr/glenda/lib/acme.dump b/usr/glenda/lib/acme.dump
new file mode 100644 (file)
index 0000000..1be4a18
--- /dev/null
@@ -0,0 +1,12 @@
+/usr/glenda
+/lib/font/bit/lucidasans/unicode.8.font
+/lib/font/bit/lucm/unicode.9.font
+          0          20          75
+f          0          24           0           0           1 
+         24          34          16           1           0 /usr/glenda/ Del Snarf Get | Look 
+f          1          25         567         567           1 
+         25          34         567           0           0 readme.acme Del Snarf Undo | Look 
+e          2           0           0           0           1 
+         23          49          52           0           0 /mail/fs/mbox/ Del Snarf | Look Put Mail Delmesg 
+/acme/mail
+Mail mbox
diff --git a/usr/glenda/lib/acme.dump.small b/usr/glenda/lib/acme.dump.small
new file mode 100644 (file)
index 0000000..518a483
--- /dev/null
@@ -0,0 +1,16 @@
+/usr/glenda
+/lib/font/bit/lucidasans/unicode.7.font
+/lib/font/bit/lucidasans/typelatin1.7.font
+          0          20          75
+f          0          24           0           0           1 
+         24          34          16           1           0 /usr/glenda/ Del Snarf Get | Look 
+e          0           0           0           0           8 
+         28          51           6           0           1 /usr/glenda/-serzone Del Snarf | Look Send Noscroll
+/usr/glenda
+win
+f          1          25         567         567           1 
+         25          34         567           0           0 readme.acme Del Snarf Undo | Look 
+e          2           0           0           0           1 
+         23          49          52           0           0 /mail/fs/mbox/ Del Snarf | Look Put Mail Delmesg 
+/acme/mail
+Mail mbox
diff --git a/usr/glenda/lib/first.window b/usr/glenda/lib/first.window
new file mode 100755 (executable)
index 0000000..cf9544e
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/rc
+echo -n readme > /dev/label
+cat readme.rio
+exec rc -i
+
diff --git a/usr/glenda/lib/newstime b/usr/glenda/lib/newstime
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/usr/glenda/lib/plumbing b/usr/glenda/lib/plumbing
new file mode 100644 (file)
index 0000000..b209d2d
--- /dev/null
@@ -0,0 +1,6 @@
+# to update: cp /usr/glenda/lib/plumbing /mnt/plumb/rules
+
+editor = acme
+
+include basic
+
diff --git a/usr/glenda/lib/profile b/usr/glenda/lib/profile
new file mode 100644 (file)
index 0000000..fe27289
--- /dev/null
@@ -0,0 +1,36 @@
+bind -a $home/bin/rc /bin
+bind -a $home/bin/$cputype /bin
+bind -c tmp /tmp
+if(! syscall create /tmp/xxx 1 0666 >[2]/dev/null)
+       ramfs   # in case we're running off a cd
+font = /lib/font/bit/pelm/euro.9.font
+upas/fs
+fn cd { builtin cd $* && awd }  # for acme
+switch($service){
+case terminal
+       plumber
+       echo -n accelerated > '#m/mousectl'
+       echo -n 'res 3' > '#m/mousectl'
+       prompt=('term% ' '      ')
+       fn term%{ $* }
+       exec rio -i riostart
+case cpu
+       if (test -e /mnt/term/mnt/wsys) { # rio already running
+               bind -a /mnt/term/mnt/wsys /dev
+               if(test -w /dev/label)
+                       echo -n $sysname > /dev/label
+       }
+       bind /mnt/term/dev/cons /dev/cons
+       bind /mnt/term/dev/consctl /dev/consctl
+       bind -a /mnt/term/dev /dev
+       prompt=('cpu% ' '       ')
+       fn cpu%{ $* }
+       news
+       if (! test -e /mnt/term/mnt/wsys) {     # cpu call from drawterm
+               font=/lib/font/bit/pelm/latin1.8.font
+               exec rio
+       }
+case con
+       prompt=('cpu% ' '       ')
+       news
+}
diff --git a/usr/glenda/readme.acme b/usr/glenda/readme.acme
new file mode 100644 (file)
index 0000000..18cc16a
--- /dev/null
@@ -0,0 +1,102 @@
+Welcome to acme, the editor/shell/window system hybrid.  Acme is a
+complete environment you can use to edit, run programs, browse the
+file system, etc.
+
+You can scroll the text this window by moving the mouse into
+the window (no clicking necessary) and typing the up and down
+arrows.
+
+When you start Acme, you see several windows layered into two
+columns. Above each window, you can see a ``tag line'' (in blue). The
+first thing to notice is that all the text you see is just that:
+text. You can edit anything at will.
+
+For example, in the left column is a directory window.
+If you look at the window's tag line, you will see that it contains
+
+       /usr/glenda/ Del Snarf Get | Look 
+
+(This might be truncated if the column is narrow.)
+That is just text.
+
+Each mouse button (1, 2, 3, from left to right) does a different
+thing in Acme:
+
+ *     Button 1 can be used to select text (press it, sweep, release it),
+       and also to select the point where text would be inserted in the
+       window. Use it now in your /usr/glenda window.
+ *     Button 2 can be used to execute things.  For example, use button 1
+       to type "ls -l" before "lib/" in the window showing
+       /usr/glenda.  Now use button 2 to select "ls -l lib/" (press
+       it, select, release it).  As you can see, button 2 means
+       "execute this".
+ *     Button 3 can be used to get things. For example, click button 3 on
+       "lib/" within the "/usr/glenda" window. Can you see how a new window
+       shows the contents of "/usr/glenda/lib"? Button 3 can also be used
+       to search within the body of a window. Just click button 3 on the
+       thing you want to search. Again, you can select something with
+       button 1 and then use button 3 on the selection.
+
+You can double-click with button 1 to select words; a double click at
+the end or beginning of a line selects the whole line.  Once you have
+text selected, you can click on it with button 2 to execute the
+selected text.  A single click of button 2 would execute the word
+clicked as a command.
+
+Now let's pay attention to the tag line once more. As you can see,
+the left part has a path. That is the name for the window and shows
+also the directory for the thing shown (file/directory/program
+output). When you execute something using button 2, the current
+directory for the command is the directory shown in the left part of
+the tag (if the thing shown is a file, its directory is used).
+
+As you saw before in the example, there are windows labeled
+"/dir/+Errors", that is where Acme shows the output of a command
+executed in "/dir".
+
+Another thing you can see is that tag lines contain words like "New",
+"Del", "Snarf", etc. Those are commands understood (implemented) by
+Acme. When you request execution of one of them, Acme does the job.
+For example, click with button 2 on "Del" in the
+"/usr/glenda/+Errors" window: it's gone.
+
+The commands shown by Acme are just text and by no means special. Try
+to type "Del" within the body of the window "/usr/glenda", and then
+click (button-2) on it.
+
+These are some commands understood by Acme:
+ *     Newcol: create a new column of windows
+ *     Delcol: delete a column
+ *     New: create a new window (edit it's tag to be a file name and you
+       would be creating a new file; you would need to click on "Put" to
+       put the file in the file system).
+ *     Put: write the body to disk. The file is the one named in the tag.
+ *     Get: refresh the body (e.g. if it's a directory, reread it and
+       show it).
+ *     Snarf: What other window systems call "Copy".
+ *     Paste: Can you guess it?
+ *     Exit: exit acme
+
+Acme likes to place new windows itself. If you prefer to change the
+layout of a window, you only need to drag the layout box at the left
+of the tag line and drop it somewhere else. The point where you drop
+it selects the column where the window is to be placed now, as well
+as the line where the window should start. You can also click the
+layout box to enlarge its window a small amount (button 1), as much
+as possible without obscuring other tag lines in the column (button
+2), and to fill the whole column (button 3). You can get your other
+windows back by button-1- or button-2-clicking the layout box.
+
+This is mostly what you need to get started with Acme. You are
+missing a very useful feature: using combinations (chords) of mouse
+buttons to do things. You can cut, paste, snarf, and pass arguments
+to programs using these mouse chords. You can read this in the
+acme(1) manual page, but it's actually extremely simple: Select a
+region with button 1 but don't release the button. Now clicking
+button 2 deletes the selected text (putting it into the snarf
+buffer); clicking button 3 replaces the selected text with the snarf
+buffer. That's it!
+
+For more information, read /sys/doc/acme/acme.ps (you can just
+button-3 click on that string to view the file).
+
diff --git a/usr/glenda/readme.rio b/usr/glenda/readme.rio
new file mode 100644 (file)
index 0000000..0eb0e44
--- /dev/null
@@ -0,0 +1,178 @@
+Rio is the Plan 9 window system.
+
+To read more of this window, the up and down arrows
+scroll the text up and down half screens.
+
+To effectively use rio, you need at least a three
+button mouse.  If you only have a two button mouse you
+can emulate the middle button by holding down shift key
+whilst pressing the right button.
+
+Button 1, 2, and 3 are used to refer to the left,
+middle, and right buttons respectively.
+
+THE POP-UP MENU
+
+Pressing and holding down button 3 on the desktop or
+shell window will give you a menu with the following
+options:
+
+ * New - create a new window 
+ * Resize - reshape a window 
+ * Move - move a window without reshaping it 
+ * Delete - close a window
+ * Hide - hides a window from display (it will appear
+   in this menu)
+ * <label> - the label of a hidden window,
+   selecting it unhides it
+
+You select an item by releasing the button over the
+menu item.  rio uses the same button that started an
+action throughout that operation.  If you press another
+button during the action the operation is aborted and
+any intermediate changes are reversed.
+
+The menu acts as a action verb selector which then
+requires an object (i.e.  window) to be picked to
+indicate which window the verb is to act on.  A further
+mouse action may then be required.
+
+EXAMPLES
+
+After selecting New, the cursor will change into a
+cross.  Using button 3 again, you should then drag out
+a rectangle to indicate the size and location of the
+new window.  When you release the button a new window
+will be created.
+
+New windows will contain the rc shell.  Invoking a rio
+program from the shell will allow that program to take
+over the window.  As there is no job control in the
+shell (e.g.  &, fg, bg), you just create another window
+if you want to run another program concurrently.
+
+To Resize a window, you select Resize, then click
+(remember using the same button that started the
+action, i.e.  button 3) on the window you want to
+resize.  The cursor will change to a cross-hair theat
+will allow you to drag out the desired shape of the
+window.
+
+After selecting Move, click and keep the button
+depressed over the window you want to move, then move
+the mouse to move the red rectangle that represents the
+new location you want.  Release the button to finish
+the action.
+
+Delete and Hide both operate by requiring you to click
+on the window you wish to respectively Delete or Hide.
+
+WINDOW CONTROL TIPS
+
+Clicking on a window brings it to the front.
+
+You can directly change the shape of a window by
+clicking and dragging on the edge or corner of the
+window border.  Button 1 or 2 will allow you to drag
+the edge or corner to a new size, and Button 3 will
+allow you to move the window.
+
+The pop-up menu remembers the last command chosen, so
+as a short cut you can just press and release button 3
+without moving the mouse between pressing and releasing
+to select the previous command again.
+
+BASIC TEXT CONTROL
+
+Unlike in other systems, the text cursor can only be
+controlled by the mouse or the side-effects of certain
+commands.
+
+Clicking with button 1 will move the text insertion
+point (indicated by an I-beam) to just before the
+character closest to the mouse pointer.  Dragging
+across a section of text will select that portion of
+text.  It may be useful to know that the insertion
+I-beam represents an empty selection (between two
+characters).  In text editors, the current selection is
+known as "dot".
+
+In the shell window button 2 will invoke a pop-up menu.
+Most of it's commands operate on dot.
+
+ * cut - moves the contents of the dot to the clipboard
+   if dot is non-empty 
+ * paste - replaces dot with the contents of the clipboard
+ * snarf - copies dot to the clipboard
+ * plumb - sends dot (or text surrounding dot, if dot is
+   empty)to the plumber.
+ * send - completes the current input line with the dot,
+   if it is non-empty, or the contents of the clipboard.
+   If the dot is non-empty it does a snarf at the same time.
+ * scroll - toggles the automatic scrolling of the window
+   on output.
+
+Double-clicking will allow you to automatically select
+a section of text surrounding that point.  The
+selection is made by an analysis of appropriate
+delimeters.  A whole line is selected by
+double-clicking at either end of the line.  A quoted or
+bracketed selection is made by double-clicking just
+inside of the quote or bracket.
+
+SCROLLING
+
+The arrow keys will let you scroll up or down by half a
+page at a time.
+
+Clicking button 1 on the scrollbar scrolls up by half a
+page.  Button 3 scrolls down by half a page.  Button 2
+jumps to position in the document relative to the
+position on the scrollbar clicked.  Holding a button on
+the scrollbar will have the effect of invoking the
+clicking action continuously.
+
+The white elevator box on the scrollbar is sized
+proportionally to the proportion of the document that
+is currently visible.
+
+Scrolling does not affect the text cursor.
+
+RIO AND THE RC SHELL WINDOW
+
+Rc is a command interpreter for Plan 9 that provides
+similar facilities to UNIX's Bourne shell.  See the
+additional references at the end of this document for
+information specifically about rc.
+
+Rio provides some additional features that enhance the
+interface to programs that use the text console.  The
+rc shell command interpreter is one such program.
+
+Rc commands are typed after the prompt on the last line
+of the text buffer.  The commands are sent to rc only
+after each newline so line editing may be performed if
+desired.  You can move the cursor and edit the previous
+lines of commands and program output but none of this
+will be interpreted by rc shell.
+
+The interpretation of commands is supressed altogether
+when ESC is pressed to put the window in hold mode.
+The window border and text will change to dark blue to
+indicate the hold mode is active.  In this mode you can
+type multiple lines of commands and edit them.
+Pressing ESC again will release the hold and send the
+lines of text to the rc command interpreter.
+
+The DEL key sends an 'interrupt' note to all processes
+in the window's process group.  The usual intent is to
+terminate the execution of the current command.  It is
+also a convenient short cut for ensuring you have a
+fresh command prompt.
+
+FURTHER INFORMATION
+
+For further information, try the rio(1) manual page.
+Type "man rio" or click on rio(1) in either of these
+sentences and select plumb from the button 2 menu.
+