shithub: patches

Download patch

ref: 4ac3a0224ed9d54818f858fba69c8e94f38f2c12
author: Romano <me+git@fallglow.com>
date: Tue Aug 13 01:53:34 EDT 2024

9front: add patches, both good and bad

--- /dev/null
+++ b/9front/2235c398fa9e7b48e0c84cda05c6994a14736e55.patch
@@ -1,0 +1,215 @@
+From: Romano <me+git@fallglow.com>
+Date: Tue, 13 Aug 2024 05:33:53 +0000
+Subject: [PATCH] newuser:
+
+* make bin subdirs for all archs, as well as rc
+* make lib/drawterm user dir for drawterm-specific config
+** add lib/drawterm/default for default config
+* change console prompt to con#
+* update man page newuser source to match, and doc changes
+---
+diff c32dabd4853888f62f09a6d3f8e0deed4077b6a7 2235c398fa9e7b48e0c84cda05c6994a14736e55
+--- a/sys/lib/newuser
++++ b/sys/lib/newuser
+@@ -1,5 +1,4 @@
+ #!/bin/rc
+-
+ user=`{cat /dev/user}
+ home=/usr/$user
+ if(test -f $home/lib/profile){
+@@ -8,10 +7,10 @@
+ }
+ cd $home
+ x='$'
+-mkdir bin bin/rc bin/mips bin/386 bin/amd64 bin/power bin/arm bin/arm64 
+-mkdir lib tmp
++mkdir bin/^('' rc spim arm arm64 amd64 386 power power64 mips)
++mkdir lib lib/drawterm tmp
+ chmod +t tmp
+-bind -qc /n/other/usr/$user/tmp $home/tmp
++if(test -d /n/other/usr/$user/tmp) bind -qc /n/other/usr/$user/tmp $home/tmp
+ bind -c $home/tmp /tmp
+ mail -c
+ auth/cron -c
+@@ -22,38 +21,41 @@
+ font=/lib/font/bit/vga/unicode.font
+ switch($x^service){
+ case terminal
+-	webcookies
+-	webfs
+-	plumber
+ 	echo -n accelerated > '#m/mousectl'
+ 	echo -n 'res 3' > '#m/mousectl'
+ 	prompt=('term% ' '	')
+ 	fn term%{ $x^* }
++	webcookies
++	webfs
++	plumber
+ 	rio
+ case cpu
+-	bind /mnt/term/dev/cons /dev/cons
+-	bind -q /mnt/term/dev/consctl /dev/consctl
+-	>[2] /dev/null {
+-		cp /dev/sysname /mnt/term/dev/label
+-		if(wsys=`{cat /mnt/term/env/wsys} && ~ $x^#wsys 1) {
+-			wsys=/mnt/term^$x^wsys
+-		}
+-		if not {
+-			wsys=()
+-		}
+-	} 
+-	bind -a /mnt/term/dev /dev
++	# if rcpu or drawterm:
++	if(test -d /mnt/term/dev){
++		bind /mnt/term/dev/cons /dev/cons
++		bind -q /mnt/term/dev/consctl /dev/consctl
++		>[2] /dev/null {
++			cp /dev/sysname /mnt/term/dev/label
++			if(wsys=`{cat /mnt/term/env/wsys} && ~ $x^#wsys 1)
++				wsys=/mnt/term^$x^wsys
++			if not
++				wsys=()
++		} 
++		bind -a /mnt/term/dev /dev
++	}
+ 	prompt=('cpu% ' '	')
+ 	fn cpu%{ $x^* }
+-	if(! test -e /mnt/term/dev/wsys){
+-		# call from drawterm
+-		if(test -e /mnt/term/dev/secstore){
+-			auth/factotum -n
+-			read -m /mnt/term/dev/secstore >/mnt/factotum/ctl
+-			echo >/mnt/term/dev/secstore
+-		}
+-		if not
+-			auth/factotum
++
++	# if drawterm, load profile based on incoming sysname:
++	if(test -d /mnt/term/cmd){
++		dtsys=`{cat /mnt/term/dev/sysname}
++		if(! test -f $x^home/lib/drawterm/^$x^dtsys)
++			dtsys=default
++		. $x^home/lib/drawterm/^$x^dtsys
++	}
++
++	# otherwise start the typical programs
++	if not if(! test -e /mnt/term/dev/wsys){
+ 		webcookies
+ 		webfs
+ 		plumber
+@@ -60,9 +62,25 @@
+ 		rio
+ 	}
+ case con
+-	prompt=('cpu% ' '	')
++	prompt=('con# ' '	')
+ }
+ !
++
++cat > lib/drawterm/default <<!
++if(test -e /mnt/term/dev/secstore){
++	auth/factotum -n
++	read -m /mnt/term/dev/secstore >/mnt/factotum/ctl
++	echo >/mnt/term/dev/secstore
++}
++if not auth/factotum
++
++webcookies
++webfs
++plumber
++rio
++
++!
++
+ cat > lib/plumbing <<!
+ # to update: cp $$home/lib/plumbing /mnt/plumb/rules
+ 
+--- a/sys/man/8/newuser
++++ b/sys/man/8/newuser
+@@ -63,49 +63,61 @@
+ looks like this:
+ .IP
+ .EX
+-bind -a $home/bin/rc /bin
+-bind -a $home/bin/$cputype /bin
+-bind -c tmp /tmp
+-font = /lib/font/bit/pelm/euro.9.font
++bind -qa $home/bin/rc /bin
++bind -qa $home/bin/$cputype /bin
++font=/lib/font/bit/vga/unicode.font
+ switch($service){
+ case terminal
+-	plumber
+-	upas/fs
+ 	echo -n accelerated > '#m/mousectl'
+ 	echo -n 'res 3' > '#m/mousectl'
+ 	prompt=('term% ' '	')
+ 	fn term%{ $* }
+-	exec rio
++	webcookies
++	webfs
++	plumber
++	rio
+ case cpu
+-	if (test -e /mnt/term/mnt/wsys) {
+-		# rio already running
+-		wsys = /mnt/term^`{cat /mnt/term/env/wsys}
+-		bind -a /mnt/term/mnt/wsys /dev
+-		echo -n $sysname > /dev/label
++	# if rcpu or drawterm:
++	if(test -d /mnt/term/dev){
++		bind /mnt/term/dev/cons /dev/cons
++		bind -q /mnt/term/dev/consctl /dev/consctl
++		>[2] /dev/null {
++			cp /dev/sysname /mnt/term/dev/label
++			if(wsys=`{cat /mnt/term/env/wsys} && ~ $#wsys 1)
++				wsys=/mnt/term^$wsys
++			if not
++				wsys=()
++		} 
++		bind -a /mnt/term/dev /dev
+ 	}
+-	bind /mnt/term/dev/cons /dev/cons
+-	bind /mnt/term/dev/consctl /dev/consctl
+-	bind -a /mnt/term/dev /dev
+ 	prompt=('cpu% ' '	')
+ 	fn cpu%{ $* }
+-	upas/fs
+-	news
+-	if (! test -e /mnt/term/mnt/wsys) {
+-		# cpu call from drawterm
+-		font=/lib/font/bit/pelm/latin1.8.font
+-		auth/factotum
++
++	# if drawterm, load profile based on incoming sysname:
++	if(test -d /mnt/term/cmd){
++		dtsys=`{cat /mnt/term/dev/sysname}
++		if(! test -f $home/lib/drawterm/^$dtsys)
++			dtsys=default
++		. $home/lib/drawterm/^$dtsys
++	}
++
++	# otherwise start the typical programs
++	if not if(! test -e /mnt/term/dev/wsys){
++		webcookies
++		webfs
+ 		plumber
+-		exec rio
++		rio
+ 	}
+ case con
+-	prompt=('cpu% ' '	')
+-	news
++	prompt=('con# ' '	')
+ }
+ .EE
+ .PP
+ Sites may make changes to
+ .B /sys/lib/newuser
+-that reflect the properties of the local environment.
++that reflect the properties of the local environment, as well as drawterm-specific
++loading changes under
++.B /usr/$user/lib/drawterm .
+ .SH "SEE ALSO"
+ .IR passwd (1),
+ .IR rio (1),
--- /dev/null
+++ b/9front/23b40c5aa93bb205423c8c40d02eef825011b215.patch
@@ -1,0 +1,17 @@
+From: Romano <me+git@fallglow.com>
+Date: Thu, 11 Jul 2024 05:53:38 +0000
+Subject: [PATCH] add a couple items
+
+---
+diff c17447a0c0bc8211015c87261abe57ed46ffe0ca 23b40c5aa93bb205423c8c40d02eef825011b215
+--- a/lib/keyboard
++++ b/lib/keyboard
+@@ -548,6 +548,8 @@
+ 22C2  CA          ⋂	n-ary intersection
+ 22C3  CU          ⋃	n-ary union
+ 22C4  lz          ⋄	diamond operator
++22D8  3<          ⋘    very much less than
++22D9  3>          ⋙    very much greater than
+ 22DC  =<          ⋜	equal to or less than
+ 22DD  =>          ⋝	equal to or greater than
+ 22E6  <!~         ⋦	less than but not equivalent to
--- /dev/null
+++ b/9front/4b1f1c6fff2f186fe19bb2199dd963eb30e1ecd3.patch
@@ -1,0 +1,22 @@
+From: Romano <me+git@fallglow.com>
+Date: Mon, 10 Jun 2024 04:42:52 +0000
+Subject: [PATCH] dhcpd(8): typos
+
+---
+diff 79455f36cf2b7fff2d789e014afe1df0e8b871cd 4b1f1c6fff2f186fe19bb2199dd963eb30e1ecd3
+--- a/sys/man/8/dhcpd
++++ b/sys/man/8/dhcpd
+@@ -334,11 +334,11 @@
+ (see
+ .IR regexp (6))
+ that is matched against the requested file name
+-and the second column contains a subsitution.
++and the second column contains a substitution.
+ Lines starting with
+ .B #
+ are ignored.
+-Occurances in the resulting filename of
++Occurrences in the resulting filename of
+ .BR %I ,
+ .B %C
+ or
--- /dev/null
+++ b/9front/559725a4c1048cb88e44cbb7a15d1c7990d2e465.patch
@@ -1,0 +1,180 @@
+From: Romano <me+git@fallglow.com>
+Date: Sun, 30 Jun 2024 06:30:18 +0000
+Subject: [PATCH] merge 9front
+
+---
+diff 2350b084010b853275b822dddc3385d6ea876030 559725a4c1048cb88e44cbb7a15d1c7990d2e465
+--- a/sys/src/cmd/rio/dat.h
++++ b/sys/src/cmd/rio/dat.h
+@@ -46,11 +46,11 @@
+ 
+ enum
+ {
+-	Selborder		= 4,		/* border of selected window */
+-	Unselborder	= 1,		/* border of unselected window */
+-	Scrollwid 		= 12,		/* width of scroll bar */
+-	Scrollgap 		= 4,		/* gap right of scroll bar */
+-	BIG			= 3,		/* factor by which window dimension can exceed screen */
++	Minselborder	= 4,		/* minimum border of selected window */
++	Minunselborder	= 1,		/* minimum border of unselected window */
++	Minscrollwid 	= 12,		/* minimum width of scroll bar */
++	Minscrollgap 	= 4,		/* minimum gap right of scroll bar */
++	BIG		= 3,		/* factor by which window dimension can exceed screen */
+ 	TRUE		= 1,
+ 	FALSE		= 0,
+ };
+@@ -341,3 +341,8 @@
+ int		messagesize;		/* negotiated in 9P version setup */
+ int		shiftdown;
+ int		debug;
++int 		Borderwid;		/* border width of window */
++int 		Selborder;		/* border of selected window */
++int 		Unselborder;		/* border of unselected window */
++int 		Scrollwid;		/* width of scroll bar */
++int 		Scrollgap;		/* gap right of scroll bar */
+--- a/sys/src/cmd/rio/data.c
++++ b/sys/src/cmd/rio/data.c
+@@ -185,6 +185,16 @@
+ };
+ 
+ void
++fontinit(void)
++{
++	Borderwid = ceil(stringwidth(font, "0") / 4) > Borderwidth ? ceil(stringwidth(font, "0") / 4) : Borderwidth;
++	Selborder = ceil(stringwidth(font, "0") / 2) > Minselborder ? ceil(stringwidth(font, "0") / 2) : Minselborder;
++	Unselborder = ceil(stringwidth(font, "0") / 8) > Minunselborder ? ceil(stringwidth(font, "0") / 8) : Minunselborder;
++	Scrollwid = ceil(stringwidth(font, "0") * 1.5) > Minscrollwid ? ceil(stringwidth(font, "0") * 1.5) : Minscrollwid;
++	Scrollgap = ceil(stringwidth(font, "0") / 2) > Minscrollgap ? ceil(stringwidth(font, "0") / 2) : Minscrollgap;
++}
++
++void
+ iconinit(void)
+ {
+ 	background = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x777777FF);
+--- a/sys/src/cmd/rio/fns.h
++++ b/sys/src/cmd/rio/fns.h
+@@ -16,6 +16,7 @@
+ void	error(char*);
+ void	killprocs(void);
+ int	shutdown(void*, char*);
++void	fontinit(void);
+ void	iconinit(void);
+ void	*erealloc(void*, uint);
+ void *emalloc(uint);
+--- a/sys/src/cmd/rio/rio.c
++++ b/sys/src/cmd/rio/rio.c
+@@ -182,6 +182,7 @@
+ 		fprint(2, "rio: can't open display: %r\n");
+ 		exits("display open");
+ 	}
++	fontinit();
+ 	iconinit();
+ 
+ 	exitchan = chancreate(sizeof(int), 0);
+@@ -951,10 +952,10 @@
+ 	}
+ 	if(col != nil){
+ 		r = canonrect(r);
+-		drawedge(&b[0], col, Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y));
+-		drawedge(&b[1], col, Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth));
+-		drawedge(&b[2], col, Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y));
+-		drawedge(&b[3], col, Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y));
++		drawedge(&b[0], col, Rect(r.min.x, r.min.y, r.min.x+Borderwid, r.max.y));
++		drawedge(&b[1], col, Rect(r.min.x+Borderwid, r.min.y, r.max.x-Borderwid, r.min.y+Borderwid));
++		drawedge(&b[2], col, Rect(r.max.x-Borderwid, r.min.y, r.max.x, r.max.y));
++		drawedge(&b[3], col, Rect(r.min.x+Borderwid, r.max.y-Borderwid, r.max.x-Borderwid, r.max.y));
+ 	}
+ 	lastcol = col;
+ }
+--- a/sys/src/cmd/rio/wctl.c
++++ b/sys/src/cmd/rio/wctl.c
+@@ -100,13 +100,13 @@
+ 	 * that includes the border on each side with an extra pixel
+ 	 * so that the text is still drawn
+ 	 */
+-	if(Dx(r) < 100 || Dy(r) < 2*(Borderwidth+1)+font->height)
++	if(Dx(r) < 100 || Dy(r) < 2*(Borderwid+Unselborder)+font->height)
+ 		return 0;
+ 	/* window must be on screen */
+ 	if(!rectXrect(screen->r, r))
+ 		return 0;
+ 	/* must have some screen and border visible so we can move it out of the way */
+-	if(rectinrect(screen->r, insetrect(r, Borderwidth)))
++	if(rectinrect(screen->r, insetrect(r, Borderwid)))
+ 		return 0;
+ 	return 1;
+ }
+@@ -148,8 +148,8 @@
+ 	static int i = 0;
+ 	int minx, miny, dx, dy;
+ 
+-	dx = min(600, Dx(screen->r) - 2*Borderwidth);
+-	dy = min(400, Dy(screen->r) - 2*Borderwidth);
++	dx = min(600, Dx(screen->r) - 2*Borderwid);
++	dy = min(400, Dy(screen->r) - 2*Borderwid);
+ 	minx = 32 + 16*i;
+ 	miny = 32 + 16*i;
+ 	i++;
+--- a/sys/src/cmd/rio/wind.c
++++ b/sys/src/cmd/rio/wind.c
+@@ -353,7 +353,7 @@
+ 
+ 	w->i = i;
+ 	w->mc.image = i;
+-	r = insetrect(i->r, Selborder+1);
++	r = insetrect(i->r, Selborder+Unselborder);
+ 	w->scrollr = r;
+ 	w->scrollr.max.x = r.min.x+Scrollwid;
+ 	w->lastsr = ZR;
+@@ -1249,7 +1249,7 @@
+ 
+ 	w = emalloc(sizeof(Window));
+ 	w->screenr = i->r;
+-	r = insetrect(i->r, Selborder+1);
++	r = insetrect(i->r,Selborder+Unselborder);
+ 	w->i = i;
+ 	w->mc = *mc;
+ 	w->ck = ck;
+--- a/sys/src/cmd/upas/send/message.c
++++ b/sys/src/cmd/upas/send/message.c
+@@ -1,6 +1,7 @@
+ #include "common.h"
+ #include "send.h"
+ #include <regexp.h>
++#include <ctype.h>
+ #include "../smtp/smtp.h"
+ #include "../smtp/rfc822.tab.h"
+ 
+@@ -18,6 +19,23 @@
+ static String*	getstring(Node *p);
+ static String*	getaddr(Node *p);
+ 
++char *
++userfrom(char *cp)
++{
++	char *s;
++	int n;
++
++	if((n = strlen(cp)) > 4 && cp[n-1] == '>'){
++		if((s = strrchr(cp, '<')) != nil && s != cp && isspace(s[-1])) {
++			s++;
++			cp[n-1] = '\0';
++			strcpy(cp, s);
++		}
++	}
++
++	return cp;
++}
++
+ int
+ default_from(message *mp)
+ {
+@@ -32,7 +50,7 @@
+ 		return -1;
+ 	}
+ 	if(cp && *cp)
+-		s_append(mp->sender, cp);
++		s_append(mp->sender, userfrom(cp));
+ 	else
+ 		s_append(mp->sender, lp);
+ 	free(cp);
--- /dev/null
+++ b/9front/675bcd62992e59002c834ef445d515b346f4374d.patch
@@ -1,0 +1,181 @@
+From: Romano <me+git@fallglow.com>
+Date: Fri, 12 Jul 2024 19:24:48 +0000
+Subject: [PATCH] rc: do not share certain special vars; fix $status bug for most cases
+
+
+Certain special vars (namely $*, $pid, $apid, and $status)
+are used internally and should not be set after a child
+returns.
+
+There has been a long-standing bug where checking the value
+of $status with ~ overwrites the value of $status. $status
+is now restored in most cases, other than running it
+as a standalone built-in command.
+
+Man page for rc is updated
+---
+diff 7637f8f5fd6490d07ba64bcf404321028e698ed9 675bcd62992e59002c834ef445d515b346f4374d
+--- a/sys/src/cmd/rc/code.c
++++ b/sys/src/cmd/rc/code.c
+@@ -275,6 +275,8 @@
+ 		codeswitch(t, eflag);
+ 		break;
+ 	case TWIDDLE:
++		if(c0 && c0->type=='$' && c0->child[0] && (c0->child[0]->type==WORD && strcmp(c0->child[0]->str, "status")==0))
++			emitf(Xstashstatus);
+ 		emitf(Xmark);
+ 		noglobs(c1, 1);
+ 		outcode(c1, eflag);
+--- a/sys/src/cmd/rc/exec.c
++++ b/sys/src/cmd/rc/exec.c
+@@ -282,6 +282,16 @@
+ 			dotrap();
+ 	}
+ }
++
++void
++unstashstatus(void)
++{
++	var *oldstatus = vlook("status-");
++	if(oldstatus->val && oldstatus->val->word){
++		setstatus(oldstatus->val->word);
++	}
++}
++
+ /*
+  * Opcode routines
+  * Arguments on stack (...)
+@@ -415,6 +425,7 @@
+ void
+ Xifnot(void)
+ {
++	unstashstatus();
+ 	if(ifnot)
+ 		runq->pc++;
+ 	else
+@@ -597,7 +608,9 @@
+ void
+ Xtrue(void)
+ {
+-	if(truestatus()) runq->pc++;
++	int stat = truestatus();
++	unstashstatus();
++	if(stat) runq->pc++;
+ 	else runq->pc = runq->code[runq->pc].i;
+ }
+ 
+@@ -605,7 +618,9 @@
+ Xif(void)
+ {
+ 	ifnot = 1;
+-	if(truestatus()) runq->pc++;
++	int stat = truestatus();
++	unstashstatus();
++	if(stat) runq->pc++;
+ 	else runq->pc = runq->code[runq->pc].i;
+ }
+ 
+@@ -661,6 +676,12 @@
+ 		}
+ 	poplist();
+ 	poplist();
++}
++
++void
++Xstashstatus(void)
++{
++	setvar("status-", Newword(estrdup(getstatus()), (word *)0));
+ }
+ 
+ void
+--- a/sys/src/cmd/rc/exec.h
++++ b/sys/src/cmd/rc/exec.h
+@@ -4,7 +4,7 @@
+ extern void Xappend(void), Xasync(void), Xbackq(void), Xbang(void), Xclose(void);
+ extern void Xconc(void), Xcount(void), Xdelfn(void), Xdol(void), Xqw(void), Xdup(void);
+ extern void Xexit(void), Xfalse(void), Xfn(void), Xfor(void), Xglob(void);
+-extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(void), Xhere(void), Xhereq(void);
++extern void Xjump(void), Xmark(void), Xmatch(void), Xstashstatus(void), Xpipe(void), Xread(void), Xhere(void), Xhereq(void);
+ extern void Xrdwr(void), Xsrcline(void);
+ extern void Xunredir(void), Xstar(void), Xreturn(void), Xsubshell(void);
+ extern void Xtrue(void), Xword(void), Xwrite(void), Xpipefd(void), Xcase(void);
+--- a/sys/src/cmd/rc/pfnc.c
++++ b/sys/src/cmd/rc/pfnc.c
+@@ -30,6 +30,7 @@
+ 	Xword, "Xword",
+ 	Xwrite, "Xwrite",
+ 	Xmatch, "Xmatch",
++	Xstashstatus, "Xstashstatus",
+ 	Xcase, "Xcase",
+ 	Xconc, "Xconc",
+ 	Xassign, "Xassign",
+--- a/sys/src/cmd/rc/plan9.c
++++ b/sys/src/cmd/rc/plan9.c
+@@ -144,7 +144,12 @@
+ 		if(n <= 0)
+ 			break;
+ 		for(i = 0; i<n; i++){
+-			if(ent[i].length<=0 || strncmp(ent[i].name, "fn#", 3)==0)
++			if(ent[i].length<=0
++				|| strncmp(ent[i].name, "fn#", 3)==0
++				|| strcmp(ent[i].name,"*")==0
++				|| strcmp(ent[i].name,"apid")==0
++				|| strcmp(ent[i].name,"pid")==0
++				|| strcmp(ent[i].name,"status")==0)
+ 				continue;
+ 			if((fd = Open(Env(ent[i].name, 0), 0))>=0){
+ 				io *f = openiofd(fd);
+--- a/sys/src/cmd/rc/test/updenvall.file
++++ b/sys/src/cmd/rc/test/updenvall.file
+@@ -78,3 +78,40 @@
+ 	echo d
+ }
+ ' '/env/fn#a is echo d'
++
++echo testing special vars
++*=b
++echo -n a > /env/'*'
++ok $"* 'b' '* not set'
++echo -n $"pid >/tmp/pid.rc.test
++rc -c ''
++ok $"pid `{cat /tmp/pid.rc.test} 'pid not set'
++rm /tmp/pid.rc.test
++echo -n `{apid=foobar; echo $apid} >/dev/null
++ok $"apid '' 'apid not set'
++echo -n foo > /env/status
++ok $"status '' 'status not set'
++status=foo
++~ $status foo
++ok $"status '' 'naked ~ sets status to '''''
++status=`{echo foo}
++ok $"status foo 'backtick sets status'
++if(~ $status foo)
++	ok $"status foo '$status'
++if(! ~ $status a)
++	ok $"status foo '$status for ! ~'
++if(~ $status a)
++	;
++if not
++	ok $status foo '$status for if not'
++if(~ $"status foo)
++	ok $"status foo '$"status'
++if(echo a | grep -s a || ls)
++	ok $"status foo '||'
++while(! ~ $status foo)
++	status=bar
++ok $status foo 'after while not match'
++while(~ $status foo)
++	status=bar;
++ok $status bar 'after while match'
++status=''
+--- a/sys/src/cmd/rc/test/updenvall.rc
++++ b/sys/src/cmd/rc/test/updenvall.rc
+@@ -9,7 +9,7 @@
+ 	shift
+ 	desc=$1
+ 	if(~ $"actual $"expected)	echo ok $desc
+-	if not echo 'not ok '^$"desc^', got '$"actual
++	if not echo 'NOT OK '^$"desc^', got '$"actual
+ }
+ 
+ # now let's run the test with our build
--- /dev/null
+++ b/9front/7637f8f5fd6490d07ba64bcf404321028e698ed9.patch
@@ -1,0 +1,29 @@
+From: Romano <me+git@fallglow.com>
+Date: Thu, 11 Jul 2024 05:56:24 +0000
+Subject: [PATCH] make "" use a fn that will then work with built-ins
+
+	currently "" does not work with built-ins, so re-running
+	built-ins might not have the desired effect (e.g., setting
+	environment variables, cd). This updates "" to be defined
+	internally as a function, which then update the parent
+	environment after being called.
+---
+diff 23b40c5aa93bb205423c8c40d02eef825011b215 7637f8f5fd6490d07ba64bcf404321028e698ed9
+--- a/rc/bin/""
++++ b/rc/bin/""
+@@ -1,5 +1,5 @@
+-#!/bin/rc
+-
++#!/bin/rc -b
++fn "" {
+ PROMPT='[^ 	]*(%|;)+[ 	]+'
+ 
+ _x = `{" $* | tail -1}
+@@ -10,4 +10,6 @@
+ 
+ echo '	' $_x >[1=2]
+ _x=`{ echo -n 'eval '''; echo $_x | sed 's/^'$PROMPT'//; s/''/''''/g; s/$/''/'}
+-rc -c $"_x
++eval $"_x
++}
++"" $*
--- /dev/null
+++ b/9front/863b4ae53732ddeaf96dc23b0e9924651f2b4090.patch
@@ -1,0 +1,56 @@
+From: Romano <me+git@fallglow.com>
+Date: Fri, 17 May 2024 08:08:34 +0000
+Subject: [PATCH] upas/send: parse e-mail descriptions like marshal
+
+
+/sys/src/cmd/upas/marshal/marshal.c:/^printfrom parses an e-mail with a
+description (e.g., "A Name <a.name@example.com>") and sets the from to
+just the e-mail address portion. This does the same for upas/send so that
+upasname='A name <a.name@example.com>' can be used to both set the From:
+in marshal with a description and to match the correct from in upas/send
+for sending via smtp.
+---
+diff e51d4aa069548de51d0e88a6d621d278e9138cd0 863b4ae53732ddeaf96dc23b0e9924651f2b4090
+--- a/sys/src/cmd/upas/send/message.c
++++ b/sys/src/cmd/upas/send/message.c
+@@ -1,6 +1,7 @@
+ #include "common.h"
+ #include "send.h"
+ #include <regexp.h>
++#include <ctype.h>
+ #include "../smtp/smtp.h"
+ #include "../smtp/rfc822.tab.h"
+ 
+@@ -18,6 +19,23 @@
+ static String*	getstring(Node *p);
+ static String*	getaddr(Node *p);
+ 
++char *
++userfrom(char *cp)
++{
++	char *s;
++	int n;
++
++	if((n = strlen(cp)) > 4 && cp[n-1] == '>'){
++		if((s = strrchr(cp, '<')) != nil && s != cp && isspace(s[-1])) {
++			s++;
++			cp[n-1] = '\0';
++			strcpy(cp, s);
++		}
++	}
++
++	return cp;
++}
++
+ int
+ default_from(message *mp)
+ {
+@@ -32,7 +50,7 @@
+ 		return -1;
+ 	}
+ 	if(cp && *cp)
+-		s_append(mp->sender, cp);
++		s_append(mp->sender, userfrom(cp));
+ 	else
+ 		s_append(mp->sender, lp);
+ 	free(cp);
--- /dev/null
+++ b/9front/8a64e5171aad8bb0201a61e7df3046892ee6617f.patch
@@ -1,0 +1,17 @@
+From: Romano <me+git@fallglow.com>
+Date: Wed, 03 Jul 2024 20:13:04 +0000
+Subject: [PATCH] avl: update example to use correct sig
+
+---
+diff f12775c520326e2c300a3346a7deb1a777a9e4f6 8a64e5171aad8bb0201a61e7df3046892ee6617f
+--- a/sys/man/2/avl
++++ b/sys/man/2/avl
+@@ -113,7 +113,7 @@
+ 	Node *h, n;
+ 
+ 	n.key = key;
+-	h = (Node*)avllookup(t, &n);
++	h = (Node*)avllookup(t, &n, 0);
+ 	return h ? h->val : -1;
+ }
+ \fI\&...\fP
--- /dev/null
+++ b/9front/a94b1f5e58acf73619445c7c4f5eaa8c9e04dda5.patch
@@ -1,0 +1,180 @@
+From: Romano <me+git@fallglow.com>
+Date: Thu, 20 Jun 2024 04:08:13 +0000
+Subject: [PATCH] merge
+
+---
+diff 107a7ba9717429ae34294d9afa804b5271157ab0 a94b1f5e58acf73619445c7c4f5eaa8c9e04dda5
+--- a/sys/src/cmd/rio/dat.h
++++ b/sys/src/cmd/rio/dat.h
+@@ -46,11 +46,11 @@
+ 
+ enum
+ {
+-	Selborder		= 4,		/* border of selected window */
+-	Unselborder	= 1,		/* border of unselected window */
+-	Scrollwid 		= 12,		/* width of scroll bar */
+-	Scrollgap 		= 4,		/* gap right of scroll bar */
+-	BIG			= 3,		/* factor by which window dimension can exceed screen */
++	Minselborder	= 4,		/* minimum border of selected window */
++	Minunselborder	= 1,		/* minimum border of unselected window */
++	Minscrollwid 	= 12,		/* minimum width of scroll bar */
++	Minscrollgap 	= 4,		/* minimum gap right of scroll bar */
++	BIG		= 3,		/* factor by which window dimension can exceed screen */
+ 	TRUE		= 1,
+ 	FALSE		= 0,
+ };
+@@ -341,3 +341,8 @@
+ int		messagesize;		/* negotiated in 9P version setup */
+ int		shiftdown;
+ int		debug;
++int 		Borderwid;		/* border width of window */
++int 		Selborder;		/* border of selected window */
++int 		Unselborder;		/* border of unselected window */
++int 		Scrollwid;		/* width of scroll bar */
++int 		Scrollgap;		/* gap right of scroll bar */
+--- a/sys/src/cmd/rio/data.c
++++ b/sys/src/cmd/rio/data.c
+@@ -185,6 +185,16 @@
+ };
+ 
+ void
++fontinit(void)
++{
++	Borderwid = ceil(stringwidth(font, "0") / 4) > Borderwidth ? ceil(stringwidth(font, "0") / 4) : Borderwidth;
++	Selborder = ceil(stringwidth(font, "0") / 2) > Minselborder ? ceil(stringwidth(font, "0") / 2) : Minselborder;
++	Unselborder = ceil(stringwidth(font, "0") / 8) > Minunselborder ? ceil(stringwidth(font, "0") / 8) : Minunselborder;
++	Scrollwid = ceil(stringwidth(font, "0") * 1.5) > Minscrollwid ? ceil(stringwidth(font, "0") * 1.5) : Minscrollwid;
++	Scrollgap = ceil(stringwidth(font, "0") / 2) > Minscrollgap ? ceil(stringwidth(font, "0") / 2) : Minscrollgap;
++}
++
++void
+ iconinit(void)
+ {
+ 	background = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x777777FF);
+--- a/sys/src/cmd/rio/fns.h
++++ b/sys/src/cmd/rio/fns.h
+@@ -16,6 +16,7 @@
+ void	error(char*);
+ void	killprocs(void);
+ int	shutdown(void*, char*);
++void	fontinit(void);
+ void	iconinit(void);
+ void	*erealloc(void*, uint);
+ void *emalloc(uint);
+--- a/sys/src/cmd/rio/rio.c
++++ b/sys/src/cmd/rio/rio.c
+@@ -182,6 +182,7 @@
+ 		fprint(2, "rio: can't open display: %r\n");
+ 		exits("display open");
+ 	}
++	fontinit();
+ 	iconinit();
+ 
+ 	exitchan = chancreate(sizeof(int), 0);
+@@ -951,10 +952,10 @@
+ 	}
+ 	if(col != nil){
+ 		r = canonrect(r);
+-		drawedge(&b[0], col, Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y));
+-		drawedge(&b[1], col, Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth));
+-		drawedge(&b[2], col, Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y));
+-		drawedge(&b[3], col, Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y));
++		drawedge(&b[0], col, Rect(r.min.x, r.min.y, r.min.x+Borderwid, r.max.y));
++		drawedge(&b[1], col, Rect(r.min.x+Borderwid, r.min.y, r.max.x-Borderwid, r.min.y+Borderwid));
++		drawedge(&b[2], col, Rect(r.max.x-Borderwid, r.min.y, r.max.x, r.max.y));
++		drawedge(&b[3], col, Rect(r.min.x+Borderwid, r.max.y-Borderwid, r.max.x-Borderwid, r.max.y));
+ 	}
+ 	lastcol = col;
+ }
+--- a/sys/src/cmd/rio/wctl.c
++++ b/sys/src/cmd/rio/wctl.c
+@@ -100,13 +100,13 @@
+ 	 * that includes the border on each side with an extra pixel
+ 	 * so that the text is still drawn
+ 	 */
+-	if(Dx(r) < 100 || Dy(r) < 2*(Borderwidth+1)+font->height)
++	if(Dx(r) < 100 || Dy(r) < 2*(Borderwid+Unselborder)+font->height)
+ 		return 0;
+ 	/* window must be on screen */
+ 	if(!rectXrect(screen->r, r))
+ 		return 0;
+ 	/* must have some screen and border visible so we can move it out of the way */
+-	if(rectinrect(screen->r, insetrect(r, Borderwidth)))
++	if(rectinrect(screen->r, insetrect(r, Borderwid)))
+ 		return 0;
+ 	return 1;
+ }
+@@ -148,8 +148,8 @@
+ 	static int i = 0;
+ 	int minx, miny, dx, dy;
+ 
+-	dx = min(600, Dx(screen->r) - 2*Borderwidth);
+-	dy = min(400, Dy(screen->r) - 2*Borderwidth);
++	dx = min(600, Dx(screen->r) - 2*Borderwid);
++	dy = min(400, Dy(screen->r) - 2*Borderwid);
+ 	minx = 32 + 16*i;
+ 	miny = 32 + 16*i;
+ 	i++;
+--- a/sys/src/cmd/rio/wind.c
++++ b/sys/src/cmd/rio/wind.c
+@@ -353,7 +353,7 @@
+ 
+ 	w->i = i;
+ 	w->mc.image = i;
+-	r = insetrect(i->r, Selborder+1);
++	r = insetrect(i->r, Selborder+Unselborder);
+ 	w->scrollr = r;
+ 	w->scrollr.max.x = r.min.x+Scrollwid;
+ 	w->lastsr = ZR;
+@@ -1249,7 +1249,7 @@
+ 
+ 	w = emalloc(sizeof(Window));
+ 	w->screenr = i->r;
+-	r = insetrect(i->r, Selborder+1);
++	r = insetrect(i->r,Selborder+Unselborder);
+ 	w->i = i;
+ 	w->mc = *mc;
+ 	w->ck = ck;
+--- a/sys/src/cmd/upas/send/message.c
++++ b/sys/src/cmd/upas/send/message.c
+@@ -1,6 +1,7 @@
+ #include "common.h"
+ #include "send.h"
+ #include <regexp.h>
++#include <ctype.h>
+ #include "../smtp/smtp.h"
+ #include "../smtp/rfc822.tab.h"
+ 
+@@ -18,6 +19,23 @@
+ static String*	getstring(Node *p);
+ static String*	getaddr(Node *p);
+ 
++char *
++userfrom(char *cp)
++{
++	char *s;
++	int n;
++
++	if((n = strlen(cp)) > 4 && cp[n-1] == '>'){
++		if((s = strrchr(cp, '<')) != nil && s != cp && isspace(s[-1])) {
++			s++;
++			cp[n-1] = '\0';
++			strcpy(cp, s);
++		}
++	}
++
++	return cp;
++}
++
+ int
+ default_from(message *mp)
+ {
+@@ -32,7 +50,7 @@
+ 		return -1;
+ 	}
+ 	if(cp && *cp)
+-		s_append(mp->sender, cp);
++		s_append(mp->sender, userfrom(cp));
+ 	else
+ 		s_append(mp->sender, lp);
+ 	free(cp);
--- /dev/null
+++ b/9front/c17447a0c0bc8211015c87261abe57ed46ffe0ca.patch
@@ -1,0 +1,233 @@
+From: Romano <me+git@fallglow.com>
+Date: Thu, 11 Jul 2024 05:32:38 +0000
+Subject: [PATCH] rc: keep env vars and functions in sync
+
+
+	From env(3):
+	          The env device serves a one-level directory containing files
+	          with arbitrary names and contents.  The intention is that
+	          the file name is the name of an environment variable (see
+	          rc(1)), and the content is the variable's current value.
+
+	And from rc(1):
+        Environment
+          The environment is a list of strings made available to exe-
+          cuting binaries by the env device (see env(3)).
+
+	But currently, the environment variables and functions are not kept
+	in sync with /env . For instance, '>/env/a echo -n b' will not
+	update $a to be 'b'. Also, even when the namespaces are shared
+	between processes, once the child process completes the namespaces
+	are out of sync.
+
+	This patch attempts to address that by updating the environment
+	variables and functions after children processes exit when the
+	children share the same namespace. Tests are added for the
+	functionality as well.
+---
+diff 8a64e5171aad8bb0201a61e7df3046892ee6617f c17447a0c0bc8211015c87261abe57ed46ffe0ca
+--- a/sys/src/cmd/rc/fns.h
++++ b/sys/src/cmd/rc/fns.h
+@@ -27,6 +27,7 @@
+ void	Setstatus(char*);
+ void	Trapinit(void);
+ void	Updenv(void);
++void	Updenvall(void);
+ void	Vinit(void);
+ int	Waitfor(int);
+ long	Write(int, void*, long);
+--- a/sys/src/cmd/rc/havefork.c
++++ b/sys/src/cmd/rc/havefork.c
+@@ -64,6 +64,7 @@
+ 		setvar("apid", newword(npid, (word *)0));
+ 		break;
+ 	}
++	Updenvall();
+ }
+ 
+ void
+@@ -99,6 +100,7 @@
+ 		p->pid = pid;
+ 		break;
+ 	}
++	Updenvall();
+ }
+ 
+ /*
+@@ -128,7 +130,7 @@
+ 		Close(pfd[PRD]);
+ 		start(runq->code, runq->pc+1, runq->local, runq->redir);
+ 		pushredir(ROPEN, pfd[PWR], 1);
+-		return;
++		break;
+ 	default:
+ 		addwaitpid(pid);
+ 		Close(pfd[PWR]);
+@@ -149,8 +151,9 @@
+ 		Waitfor(pid);
+ 
+ 		runq->pc = runq->code[runq->pc].i;
+-		return;
++		break;
+ 	}
++	Updenvall();
+ }
+ 
+ void
+@@ -196,6 +199,7 @@
+ 		p->pc = p->code[pc+1].i;
+ 		break;
+ 	}
++	Updenvall();
+ }
+ 
+ void
+@@ -219,6 +223,7 @@
+ 		runq->pc = runq->code[runq->pc].i;
+ 		break;
+ 	}
++	Updenvall();
+ }
+ 
+ int
+--- a/sys/src/cmd/rc/plan9.c
++++ b/sys/src/cmd/rc/plan9.c
+@@ -259,6 +259,17 @@
+ }
+ 
+ void
++Updenvall(void)
++{
++	Vinit();
++	char *cmds = estrdup("for(fn in /env/fn'#'*) { . -bq $fn }\n");
++	int line = runq->line;
++	execcmds(openiocore(cmds, strlen(cmds)), estrdup(srcfile(runq)), runq->local, runq->redir);
++	runq->lex->line = line;
++	runq->lex->qflag = 1;
++}
++
++void
+ Exec(char **argv)
+ {
+ 	exec(argv[0], argv+1);
+--- a/sys/src/cmd/rc/simple.c
++++ b/sys/src/cmd/rc/simple.c
+@@ -102,6 +102,7 @@
+ 			/* interrupts don't get us out */
+ 			while(Waitfor(pid) < 0)
+ 				;
++			Updenvall();
+ 		}
+ 	}
+ }
+--- /dev/null
++++ b/sys/src/cmd/rc/test/mkfile
+@@ -1,0 +1,6 @@
++</$objtype/mkfile
++
++TEST=\
++	updenvall\
++
++</sys/src/cmd/mktest
+--- /dev/null
++++ b/sys/src/cmd/rc/test/updenvall.file
+@@ -1,0 +1,80 @@
++>/env/var1 echo -n a
++ok `{whatis var1} 'var1=a
++' '$var1 is /env/var1'
++ok $var1 a '$var1 is a'
++ok `{cat /env/var1} a '/env/var1 is a'
++
++echo testing var with rc
++../$O.out -c 'var1=ab'
++ok `{whatis var1} 'var1=ab
++' 'var1 is ab'
++ok $var1 ab '$var1 is ab'
++ok `{cat /env/var1} ab '/env/var1 is ab'
++
++echo testing var with rc -c
++../$O.out -c 'var1=b'
++ok `{whatis var1} 'var1=b
++' 'var1 is b'
++ok $var1 b '$var1 is b'
++ok `{cat /env/var1} b '/env/var1 is b'
++
++echo testing var with subshell
++@{ var1=c }
++ok `{whatis var1} 'var1=c
++' 'var1 is c'
++ok $var1 c '$var1 is c'
++ok `{cat /env/var1} c '/env/var1 is c'
++
++echo testing var with backtick
++echo `{ var1=d } >/dev/null
++ok `{whatis var1} 'var1=d
++' 'var1 is d'
++ok $var1 d '$var1 is d'
++ok `{cat /env/var1} d '/env/var1 is d'
++
++a=()
++> '/env/fn#a' echo -n 'fn a {
++	echo a
++}
++'
++ok `{whatis a} 'fn a {
++	echo a
++}
++' 'fn a is echo a'
++ok `{cat '/env/fn#a'} 'fn a {
++	echo a
++}
++' '/env/fn#a is echo a'
++
++echo testing fn with rc -c
++../$O.out -c 'fn a { echo b }'
++ok `{whatis a} 'fn a {
++	echo b
++}
++' 'fn a is echo b'
++ok `{cat '/env/fn#a'} 'fn a {
++	echo b
++}
++' '/env/fn#a is echo b'
++
++echo testing fn with subshell
++@{ fn a { echo c } }
++ok `{whatis a} 'fn a {
++	echo c
++}
++' 'fn b is echo c'
++ok `{cat '/env/fn#a'} 'fn a {
++	echo c
++}
++' '/env/fn#a is echo c'
++
++echo testing fn with backtick
++echo `{fn a { echo d } } >/dev/null
++ok `{whatis a} 'fn a {
++	echo d
++}
++' 'fn a is echo d'
++ok `{cat '/env/fn#a'} 'fn a {
++	echo d
++}
++' '/env/fn#a is echo d'
+--- /dev/null
++++ b/sys/src/cmd/rc/test/updenvall.rc
+@@ -1,0 +1,16 @@
++#!/bin/rc
++# test that all environment variables and functions
++# are in sync.
++
++fn ok {
++	actual=$1
++	shift
++	expected=$1
++	shift
++	desc=$1
++	if(~ $"actual $"expected)	echo ok $desc
++	if not echo 'not ok '^$"desc^', got '$"actual
++}
++
++# now let's run the test with our build
++../$O.out <updenvall.file
--- /dev/null
+++ b/9front/c32dabd4853888f62f09a6d3f8e0deed4077b6a7.patch
@@ -1,0 +1,42 @@
+From: Romano <me+git@fallglow.com>
+Date: Fri, 12 Jul 2024 20:40:40 +0000
+Subject: [PATCH] rc: updated man page
+
+---
+diff 675bcd62992e59002c834ef445d515b346f4374d c32dabd4853888f62f09a6d3f8e0deed4077b6a7
+--- a/sys/man/1/rc
++++ b/sys/man/1/rc
+@@ -825,7 +825,13 @@
+ When
+ .I rc
+ starts executing it reads variable and function definitions from its
+-environment.
++environment, except for the special variables
++.BR $* ,
++.BR $pid ,
++and
++.BR $apid ,
++and
++.BR $status .
+ .SS Special Variables
+ The following variables are set or used by
+ .IR rc .
+@@ -1019,7 +1025,16 @@
+ .B ~
+ to check the value of
+ .B $status
+-changes
+-.BR $status .
++as a changes
++.BR $status 
++when used alone as a built-in command. E.g.,
++.EX
++cpu% status=b; ~ $status a; echo $status
++no match
++cpu% status=b; if(~ $status a; echo $status) echo $status
++no match
++b
++cpu%
++.EE
+ .PP
+ Free carets don't get inserted next to keywords.
--- /dev/null
+++ b/9front/e51d4aa069548de51d0e88a6d621d278e9138cd0.patch
@@ -1,0 +1,142 @@
+From: Romano <unobe@cpan.org>
+Date: Thu, 09 May 2024 21:04:32 +0000
+Subject: [PATCH] rio: resize border and scrollbar based on font
+
+
+when using large fonts the scroll bar is aberrantly small, as is
+the border size. initialize the border widths and scroll widths
+based on the font size. set a minimum value based on existing
+hard-coded values.
+---
+diff 025a2d172ebfe36bc0da32f5712dd250916c73f1 e51d4aa069548de51d0e88a6d621d278e9138cd0
+--- a/sys/src/cmd/rio/dat.h
++++ b/sys/src/cmd/rio/dat.h
+@@ -46,11 +46,11 @@
+ 
+ enum
+ {
+-	Selborder		= 4,		/* border of selected window */
+-	Unselborder	= 1,		/* border of unselected window */
+-	Scrollwid 		= 12,		/* width of scroll bar */
+-	Scrollgap 		= 4,		/* gap right of scroll bar */
+-	BIG			= 3,		/* factor by which window dimension can exceed screen */
++	Minselborder	= 4,		/* minimum border of selected window */
++	Minunselborder	= 1,		/* minimum border of unselected window */
++	Minscrollwid 	= 12,		/* minimum width of scroll bar */
++	Minscrollgap 	= 4,		/* minimum gap right of scroll bar */
++	BIG		= 3,		/* factor by which window dimension can exceed screen */
+ 	TRUE		= 1,
+ 	FALSE		= 0,
+ };
+@@ -341,3 +341,8 @@
+ int		messagesize;		/* negotiated in 9P version setup */
+ int		shiftdown;
+ int		debug;
++int 		Borderwid;		/* border width of window */
++int 		Selborder;		/* border of selected window */
++int 		Unselborder;		/* border of unselected window */
++int 		Scrollwid;		/* width of scroll bar */
++int 		Scrollgap;		/* gap right of scroll bar */
+--- a/sys/src/cmd/rio/data.c
++++ b/sys/src/cmd/rio/data.c
+@@ -185,6 +185,16 @@
+ };
+ 
+ void
++fontinit(void)
++{
++	Borderwid = ceil(stringwidth(font, "0") / 4) > Borderwidth ? ceil(stringwidth(font, "0") / 4) : Borderwidth;
++	Selborder = ceil(stringwidth(font, "0") / 2) > Minselborder ? ceil(stringwidth(font, "0") / 2) : Minselborder;
++	Unselborder = ceil(stringwidth(font, "0") / 8) > Minunselborder ? ceil(stringwidth(font, "0") / 8) : Minunselborder;
++	Scrollwid = ceil(stringwidth(font, "0") * 1.5) > Minscrollwid ? ceil(stringwidth(font, "0") * 1.5) : Minscrollwid;
++	Scrollgap = ceil(stringwidth(font, "0") / 2) > Minscrollgap ? ceil(stringwidth(font, "0") / 2) : Minscrollgap;
++}
++
++void
+ iconinit(void)
+ {
+ 	background = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x777777FF);
+--- a/sys/src/cmd/rio/fns.h
++++ b/sys/src/cmd/rio/fns.h
+@@ -16,6 +16,7 @@
+ void	error(char*);
+ void	killprocs(void);
+ int	shutdown(void*, char*);
++void	fontinit(void);
+ void	iconinit(void);
+ void	*erealloc(void*, uint);
+ void *emalloc(uint);
+--- a/sys/src/cmd/rio/rio.c
++++ b/sys/src/cmd/rio/rio.c
+@@ -182,6 +182,7 @@
+ 		fprint(2, "rio: can't open display: %r\n");
+ 		exits("display open");
+ 	}
++	fontinit();
+ 	iconinit();
+ 
+ 	exitchan = chancreate(sizeof(int), 0);
+@@ -951,10 +952,10 @@
+ 	}
+ 	if(col != nil){
+ 		r = canonrect(r);
+-		drawedge(&b[0], col, Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y));
+-		drawedge(&b[1], col, Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth));
+-		drawedge(&b[2], col, Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y));
+-		drawedge(&b[3], col, Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y));
++		drawedge(&b[0], col, Rect(r.min.x, r.min.y, r.min.x+Borderwid, r.max.y));
++		drawedge(&b[1], col, Rect(r.min.x+Borderwid, r.min.y, r.max.x-Borderwid, r.min.y+Borderwid));
++		drawedge(&b[2], col, Rect(r.max.x-Borderwid, r.min.y, r.max.x, r.max.y));
++		drawedge(&b[3], col, Rect(r.min.x+Borderwid, r.max.y-Borderwid, r.max.x-Borderwid, r.max.y));
+ 	}
+ 	lastcol = col;
+ }
+--- a/sys/src/cmd/rio/wctl.c
++++ b/sys/src/cmd/rio/wctl.c
+@@ -100,13 +100,13 @@
+ 	 * that includes the border on each side with an extra pixel
+ 	 * so that the text is still drawn
+ 	 */
+-	if(Dx(r) < 100 || Dy(r) < 2*(Borderwidth+1)+font->height)
++	if(Dx(r) < 100 || Dy(r) < 2*(Borderwid+Unselborder)+font->height)
+ 		return 0;
+ 	/* window must be on screen */
+ 	if(!rectXrect(screen->r, r))
+ 		return 0;
+ 	/* must have some screen and border visible so we can move it out of the way */
+-	if(rectinrect(screen->r, insetrect(r, Borderwidth)))
++	if(rectinrect(screen->r, insetrect(r, Borderwid)))
+ 		return 0;
+ 	return 1;
+ }
+@@ -148,8 +148,8 @@
+ 	static int i = 0;
+ 	int minx, miny, dx, dy;
+ 
+-	dx = min(600, Dx(screen->r) - 2*Borderwidth);
+-	dy = min(400, Dy(screen->r) - 2*Borderwidth);
++	dx = min(600, Dx(screen->r) - 2*Borderwid);
++	dy = min(400, Dy(screen->r) - 2*Borderwid);
+ 	minx = 32 + 16*i;
+ 	miny = 32 + 16*i;
+ 	i++;
+--- a/sys/src/cmd/rio/wind.c
++++ b/sys/src/cmd/rio/wind.c
+@@ -353,7 +353,7 @@
+ 
+ 	w->i = i;
+ 	w->mc.image = i;
+-	r = insetrect(i->r, Selborder+1);
++	r = insetrect(i->r, Selborder+Unselborder);
+ 	w->scrollr = r;
+ 	w->scrollr.max.x = r.min.x+Scrollwid;
+ 	w->lastsr = ZR;
+@@ -1249,7 +1249,7 @@
+ 
+ 	w = emalloc(sizeof(Window));
+ 	w->screenr = i->r;
+-	r = insetrect(i->r, Selborder+1);
++	r = insetrect(i->r,Selborder+Unselborder);
+ 	w->i = i;
+ 	w->mc = *mc;
+ 	w->ck = ck;
--- /dev/null
+++ b/9front/f12775c520326e2c300a3346a7deb1a777a9e4f6.patch
@@ -1,0 +1,28 @@
+From: Romano <me+git@fallglow.com>
+Date: Sun, 30 Jun 2024 06:46:33 +0000
+Subject: [PATCH] 9p(2) minor typos
+
+---
+diff 559725a4c1048cb88e44cbb7a15d1c7990d2e465 f12775c520326e2c300a3346a7deb1a777a9e4f6
+--- a/sys/man/2/9p
++++ b/sys/man/2/9p
+@@ -241,8 +241,8 @@
+ .B RFNOTEG
+ and
+ .B RFMEM
+-flags. This isolates the service loop from the callers
+-namespace and from notes posted to the callers note group
++flags. This isolates the service loop from the caller's
++namespace and from notes posted to the caller's note group
+ but shares data and bss segments.
+ .IP
+ The child process then waits for the parent to copy its
+@@ -849,7 +849,7 @@
+ authenticated or will return -1 and
+ call
+ .I respond
+-with an apropiate error.
++with an appropriate error.
+ .I Authread
+ and
+ .I authwrite
--- /dev/null
+++ b/9front/f6228aa02e4fd3f7f5d1d2fa8b3a1e03afd2299a.patch
@@ -1,0 +1,32 @@
+From: Romano <me+git@fallglow.com>
+Date: Tue, 13 Aug 2024 05:36:36 +0000
+Subject: [PATCH] riow: change shift+q → del as hotkey for deleting current window
+
+
+this helps particularly for OS X drawterm, since shift+q is already set for
+logging out. delete also clicked more with me since del is used for
+stopping a process.
+---
+diff 2235c398fa9e7b48e0c84cda05c6994a14736e55 f6228aa02e4fd3f7f5d1d2fa8b3a1e03afd2299a
+--- a/sys/man/1/riow
++++ b/sys/man/1/riow
+@@ -72,7 +72,7 @@
+ Spawn a new
+ .IR window (1).
+ .TP
+-.B Kmod4+shift+q
++.B Kmod4+del
+ Delete the current window.
+ .TP
+ .B Kmod4+h/j/k/l
+--- a/sys/src/cmd/riow.c
++++ b/sys/src/cmd/riow.c
+@@ -368,7 +368,7 @@
+ 			cycleaction(0, -1);
+ 			return 0;
+ 		}
+-		if(r == 'Q' && mod == (Mmod4|Mshift)){
++		if(r == 0x7f && mod == Mmod4){
+ 			delete();
+ 			return 0;
+ 		}