shithub: riscv

Download patch

ref: 2959e1ede0ebc6fdffd7b8660f43c2ce14c9696f
parent: e463eb40363ff4c68b1d903f4e0cdd0ac1c5977f
author: Taru Karttunen <[email protected]>
date: Wed Mar 30 13:14:36 EDT 2011

Import sources from 2011-03-30 iso image - rc

--- /dev/null
+++ b/rc/bin/0a
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec va -L $*
--- /dev/null
+++ b/rc/bin/0c
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec vc -l $*
--- /dev/null
+++ b/rc/bin/0l
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec vl -L $*
--- /dev/null
+++ b/rc/bin/9fs
@@ -1,0 +1,55 @@
+#!/bin/rc
+# 9fs filesystem [mountpoint] - srv & mount filesystem, usually from plan 9
+
+rfork e
+switch($1){
+case ''
+	echo usage: 9fs service '[mountpoint]' >[1=2]
+	exit usage
+case kfs
+	if(! test -f /srv/kfs)
+		disk/kfs
+	mount -c /srv/kfs /n/kfs
+case dump
+	mount /srv/boot /n/dump dump >[2]/dev/null ||
+		mount /srv/boot /n/dump main/archive ||
+		mount /srv/boot /n/dump dump	# again to print error
+case snap
+	mount /srv/boot /n/snap main/snapshot
+case other
+	mount -C /srv/boot /n/other other
+case juke					# ye olde file server
+	srv -q il!jukefs && mount /srv/il!jukefs /n/juke
+case sources
+	srv -nq tcp!sources.cs.bell-labs.com sources /n/sources
+case sourcesdump
+	9fs sources
+	mount -n /srv/sources /n/sourcesdump main/archive
+case sourcessnap
+	9fs sources
+	mount -n /srv/sources /n/sourcessnap main/snapshot
+# arbitrary venti archives
+case vac:*
+	vacfs <{echo $1}
+case *.vac
+	if (test -e $1)
+		score=$1
+	if not if (! ~ $1 /* && test -e $home/lib/vac/$1)
+		score=$home/lib/vac/$1
+	if not if (! ~ $1 /* && test -e /lib/vac/$1)
+		score=/lib/vac/$1
+	if not {
+		echo $0: $1: no such score file >[1=2]
+		exit 'no score file'
+	}
+	vacfs -m /n/`{basename $1 .vac} `{cat $score}
+case wiki
+	srv -m 'net!plan9.bell-labs.com!wiki' wiki /mnt/wiki
+case *
+	switch($#*){
+	case 1
+		srv -m $1
+	case *
+		srv -m $1 $1 $2
+	}
+}
--- /dev/null
+++ b/rc/bin/B
@@ -1,0 +1,40 @@
+#!/bin/rc
+
+files=()
+dest=()
+
+if(~ $#* 0){
+	echo usage: B file ... >[1=2]
+	exit usage
+}
+
+for(i)
+	switch($i){
+	case /*
+		files = ( $files $i )
+	case *
+		files = ( $files `{cleanname `{pwd}^/$i} )
+	}
+
+
+if(test -f /mnt/plumb/edit || test -f /mnt/term/mnt/plumb/edit){
+	plumb -s B -d edit $files
+	exit
+}
+
+# using sam srv file
+
+if(test -f /mnt/term/srv/sam.$user) dest = /mnt/term/srv/sam.$user
+if not if(test -f /srv/sam.$user) dest = /srv/sam.$user
+if not {
+	echo B: can''''t find sam server file >[1=2]
+	exit open
+}
+
+switch($files){
+case *:*
+	for(i in $files)
+		echo $i | sed 's/^/B /;s/:([0-9]+)$/\n\1/g' >> $dest
+case *
+	echo B $files >> $dest
+}
--- /dev/null
+++ b/rc/bin/C
@@ -1,0 +1,66 @@
+#!/bin/rc
+# C system - connect to system's console
+rfork en
+oflag=()
+opt=-r
+while(~ $1 -*)
+	switch($1){
+	case -r
+		shift
+		opt=''
+	case -O -o
+		oflag=-O
+		shift
+	case *
+		opt=-r
+		shift
+	}
+
+switch($1){
+case ella
+	exec C office0
+	exit
+case erika
+	exec C office1
+	exit
+case *
+	# look for server in /lib/ndb
+	server=`{ndb/query sys $1 console}
+	switch($server){
+	case ''
+		echo C: unknown console server for $1
+		exit 1
+	}
+}
+
+# can't cpu to old servers any more
+switch($server){
+case dinar bones
+	ssh $server C $1
+	exit 0
+}
+
+if(! test -e /mnt/consoles/$1){
+	switch($sysname){
+	case $server
+		mount /srv/consoles /mnt/consoles
+	case *
+		import $oflag $server /mnt/consoles
+	}
+}
+
+if(! test -e /mnt/consoles/$1 && test -e /srv/consoles)
+	mount /srv/consoles /mnt/consoles
+
+if(! test -e /mnt/consoles/$1){
+	echo console not found
+	exit 'console not found'
+}
+
+if (test -w /dev/label) {
+	olab=`{cat /dev/label}
+	label $1
+}
+con -l $opt /mnt/consoles/$1
+if (test -w /dev/label)
+	label $olab
--- /dev/null
+++ b/rc/bin/D003753
@@ -1,0 +1,11 @@
+#!/bin/rc
+rfork e
+flop=/dev/fd0disk
+if(! test -r $flop)
+	flop='#f'/fd0disk
+if(! test -f /srv/dos)
+	dossrv >/dev/null </dev/null >[2]/dev/null
+unmount /n/a:>[2]/dev/null
+mount -c /srv/dos /n/a: $flop
+unmount /n/a >[2]/dev/null
+mount -c /srv/dos /n/a $flop
--- /dev/null
+++ b/rc/bin/D003754
@@ -1,0 +1,9 @@
+#!/bin/rc
+
+rfork e
+
+if(test -f /dev/sd*/dos*){
+	dosmnt 1 /n/c:
+	dosmnt 1 /n/c
+	exit
+}
--- /dev/null
+++ b/rc/bin/F000050
@@ -1,0 +1,68 @@
+#!/bin/rc
+# usbfat: [disk [mtpt]] - mount a USB disk's MS FAT file system,
+#	which might be the only thing on the disk, or might be
+#	a partition within the disk.
+rfork e
+disk = ()
+mtpt = /n/usb
+
+test -e /dev/usb || bind -a '#u' /dev || {
+	echo no '#u/usb' >[1=2]
+	exit nousb
+}
+test -e /dev/usbdctl || mount -a /srv/usb /dev || {
+	echo cannot mount /srv/usb >[1=2]
+	exit nousbd
+}
+
+disks=()
+mtpt=()
+switch ($#*) {
+case 0
+	;
+case 1
+	disks = $1
+case 2
+	disks = $1
+	mtpt = $2
+case *
+	echo usage: $0 ' [disk [mtpt]]' >[1=2]
+	exit usage
+}
+
+if(~ `{ls /n/usb >[2]/dev/null | wc -l} 0)
+	mount /srv/usb /n/usb >[2]/dev/null
+if (~ $#disks 0){
+	disks = /dev/sdU*/data
+	if(! test -e $disks(1)){
+		echo no usb disks >[1=2]
+		exit nodisk
+	}
+	disks = (/dev/sdU*/9fat /dev/sdXX/9fat /dev/sdU*/data /dev/sdXX/data)
+}
+for(d in $disks){
+	if(! ~ $done yes) {
+		if(~ $d sdU*.[0-9]* sdXX*)
+			d=/dev/$d/data
+		if(test -e $d){
+			name=`{echo $d | sed 's/.*(sd(XX|U[0-9]+\.[0-9]+)).*/\1/'}
+			if(~ $#mtpt 0)
+				mnt=/n/$name
+			if not
+				mnt=$mtpt
+			# don't mount it if it seems to be already mounted.
+			# if(! test -e $mnt/* && grep -s geometry /dev/$name/ctl)
+			{
+				blk = `{disk/fdisk -p $d |
+					awk '/^part dos / {print $3}'}
+				if (! ~ $#blk 0 &&  ~ $blk [0-9]*)
+					d=$d:$blk
+				if (mount -c <{dossrv -sf $d >[2]/dev/null} $mnt) {
+					echo $mnt
+					done = yes
+				}
+			}
+		}
+	}
+}
+exit ''
--- /dev/null
+++ b/rc/bin/F003758
@@ -1,0 +1,18 @@
+#!/bin/rc
+
+rfork e
+part=`{ls /dev/fs/9fat /dev/sd*/9fat >[2]/dev/null}
+if(~ $#part 0) {
+	echo 'no 9fat partition found' >[1=2]
+	exit no.9fat
+}
+
+part=$part(1)
+
+if(! test -f /srv/dos)
+	dossrv >/dev/null </dev/null >[2]/dev/null
+
+unmount /n/9fat >/dev/null >[2]/dev/null
+mount -c /srv/dos /n/9fat $part
+unmount /n/9 >/dev/null >[2]/dev/null
+mount -c /srv/dos /n/9 $part
--- /dev/null
+++ b/rc/bin/F003763
@@ -1,0 +1,7 @@
+#!/bin/rc
+if(! test -f /srv/dos)
+	dossrv >/dev/null </dev/null >[2]/dev/null
+unmount /n/b:>[2]/dev/null
+mount -c /srv/dos /n/b: /dev/fd1disk
+unmount /n/b >[2]/dev/null
+mount -c /srv/dos /n/b /dev/fd1disk
--- /dev/null
+++ b/rc/bin/Kill
@@ -1,0 +1,4 @@
+#!/bin/rc
+for(i){
+	ps | sed -n '/ '^$i^'$/s%^[^ ]* *([^ ]*).*%chmod 666 /proc/\1/ctl;echo kill > /proc/\1/ctl%p'
+}
--- /dev/null
+++ b/rc/bin/addaoe
@@ -1,0 +1,8 @@
+#!/bin/rc
+# addaoe let unit - add an AoE logical unit as sd$let
+if (! ~ $#* 2 || ! ~ $1 ? || ! ~ $2 *.*) {
+	echo usage: $0 letter aoe-lun >[1=2]
+	exit usage
+}
+if (test -e /dev/aoe/$2 && ! test -e /dev/sd^$1^0)
+	echo config switch on spec $1 type aoe//dev/aoe/$2 >/dev/sdctl
--- /dev/null
+++ b/rc/bin/addpsfonts
@@ -1,0 +1,5 @@
+#!/bin/rc
+# addpsfonts [file]... - add postscript fonts named in %%DocumentFonts comments
+#	of postscript input
+echo %!PS-Adobe-2.0
+exec aux/download -f -mfontmap -plw+ -r/sys/lib/postscript/font/lw+ $*
--- /dev/null
+++ b/rc/bin/ap
@@ -1,0 +1,36 @@
+#!/bin/rc
+#
+#	get AP news headline list or the given story
+#
+
+wire='http://www.newsday.com/news/nationworld/wire'
+if ( ~ $#* 0 )
+	hget $wire | #tee /tmp/ap.$pid |
+		sed -n '/<h1>AP Top News/,/AP News Wire/p' |
+		htmlfmt -a -w 100 |
+		sed -n '
+			/^• / {
+				N
+				s/^• / /g
+				s/\n/ /g
+				s/\[\/news\/nationworld\/wire\//|/
+				s/sns-ap-//
+				s/\.story.*$//
+				p
+		}' |
+		awk -F '|' '
+			{
+			s = "";
+			for (i = 1; i < NF; i++)
+				s = s " " $i;
+			printf("ap %-40s # %s\n", $NF, s);
+		}'
+
+if not
+	hget $wire/sns-ap-^$1^.story |
+		htmlfmt |
+		sed '
+			1,/^AP Top News$/d
+			/^\* __$/,$d
+			/^Subscribe to Newsday home delivery/,$d
+		' 
--- /dev/null
+++ b/rc/bin/ape/ar89
@@ -1,0 +1,15 @@
+#!/bin/rc
+
+flagfmt='c,d,p,r,t,u,v,x'
+args='archive [files ...]'
+
+if(! ifs=() eval `{aux/getflags $*} || ~ $#* 0) {
+	aux/usage
+	exit usage
+}
+
+key=''
+for(i in c d p r t x u v)
+	if(f=flag$i ~ $#$f 1)
+		key=$key$i
+exec /$cputype/bin/ar $key $*
--- /dev/null
+++ b/rc/bin/ape/c89
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec /$cputype/bin/ape/cc $*
--- /dev/null
+++ b/rc/bin/ape/cat
@@ -1,0 +1,18 @@
+#!/bin/rc
+
+rfork e
+
+files=()
+while(! ~ $#* 0){
+	switch($1){
+	case -
+		files=($files /fd/0)
+	case -*
+		;
+	case *
+		files=($files $1)
+	}
+	shift
+}
+
+exec /$cputype/bin/cat $files
--- /dev/null
+++ b/rc/bin/ape/chown
@@ -1,0 +1,4 @@
+#!/bin/rc
+
+echo 'Permission denied'
+exit 1
--- /dev/null
+++ b/rc/bin/ape/dircp
@@ -1,0 +1,9 @@
+#!/bin/rc
+# dircp src dest - copy a tree with ape's tar
+switch($#*){
+case 2
+	@{cd $1 && tar cf /fd/1 .} | @{cd $2 && tar xf /fd/0}
+case *
+	echo usage: dircp from to >[1=2]
+	exit usage
+}
--- /dev/null
+++ b/rc/bin/ape/egrep
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec /rc/bin/ape/grep $*
--- /dev/null
+++ b/rc/bin/ape/false
@@ -1,0 +1,2 @@
+#!/bin/rc
+exit 1
--- /dev/null
+++ b/rc/bin/ape/fgrep
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec /rc/bin/ape/grep $*
--- /dev/null
+++ b/rc/bin/ape/grep
@@ -1,0 +1,22 @@
+#!/bin/rc
+
+rfork e
+
+opts=()
+files=()
+argv0=$0
+while(! ~ $#* 0){
+	switch($1){
+	case -[cefinsv]
+		opts=($opts $1)
+	case -q
+		opts=($opts -s)
+	case -*
+		echo $argv0 $1 not supported >[2=1]
+		exit 'not supported'
+	case *
+		files=($files $1)
+	}
+	shift
+}
+exec /$cputype/bin/grep $opts $files
--- /dev/null
+++ b/rc/bin/ape/install
@@ -1,0 +1,40 @@
+#!/bin/rc
+# Usage: install [options] srcfile dstfile
+# Usage: install srcfile dstfile owner group mode
+
+fn usage {
+	echo 'usage: install [-c|-m mode] srcfile dstfile' >[1=2]
+	exit 1
+}
+
+mode=775
+while(! ~ $#* 0){
+	switch($1){
+	case -c
+		;
+	case -m
+		mode=$2
+		shift
+	case -*
+		usage
+	case *
+		switch($#*) {
+		case 2
+			;
+		case 5
+			mode=$5	# backward compatibility
+		case *
+			usage
+		}
+		srcfile=$1
+		dstfile=$2
+		if (! test -f $dstfile || ! cmp -s $srcfile $dstfile) {
+			cp $srcfile $dstfile
+			chmod $mode $dstfile
+			chmod g+w $dstfile
+		}
+		exit 0
+	}
+	shift
+}
+usage
--- /dev/null
+++ b/rc/bin/ape/ld
@@ -1,0 +1,6 @@
+#!/bin/rc
+# ld for ape, to keep configure happy
+
+O=`{sed -n 's/^O=//p' /$cputype/mkfile}
+
+$O^l $*
--- /dev/null
+++ b/rc/bin/ape/ln
@@ -1,0 +1,23 @@
+#!/bin/rc
+
+argv0=$0
+force=n
+while(! ~ $#* 0 && ~ $1 -*){
+	switch($1){
+	case -f
+		force=y
+	case -s
+		;
+	case *
+		echo 'usage: ln [-s] [-f] source destination' >[2=1]
+		exit 'usage'
+	}
+	shift
+}
+
+if(~ $force n && test -e $2){
+	echo ln: $2 destination exists >[2=1]
+	exit 'usage'
+}
+
+exec cp -gux $1 $2
--- /dev/null
+++ b/rc/bin/ape/ls
@@ -1,0 +1,59 @@
+#!/bin/rc
+
+# flags common to GNU and BSD ls
+
+# -A	all except . and ..
+# -C	force mc
+# -F	usual
+# -H	follow symlinks
+# -L	follow symlinks
+# -R	recursive list
+# -U	unsorted (gnu)
+# 
+# -a	include .files
+# -c	show ctime
+# -d	dirs
+# -f	no sorting
+# -l	long
+# -p	put slash after dir (-F)
+# -r	reverse
+# -s	sizes
+# -t	time sort
+# -u	utime
+# -1	single-column
+
+
+flagfmt='A,C,F,H,L,R,U,a,c,d,f,l,p,r,s,t,u,1'
+args='[file ...]'
+
+if(! ifs=() eval `{aux/getflags $*}){
+	aux/usage
+	exit usage
+}
+
+fn fixlong {
+	echo total 1000
+	/$cputype/bin/sed 's/^(.).(.........) . [0-9]+ /\1\2 1 /'
+}
+
+post=cat
+
+all=()
+# ignore -A
+if(~ $flagC 1) post=mc
+if(~ $flagF 1) all=($all -F)
+# ignore -H, -L
+# save -R for later
+if(~ $flagU 1) all=($all -n)
+# ignore -a, -c
+if(~ $flagd 1) all=($all -d)
+if(~ $flagf 1) all=($all -n)
+if(~ $flagl 1) { all=($all -l); post=fixlong }
+if(~ $flagp 1) all=($all -F)
+if(~ $flagr 1) all=($all -r)
+if(~ $flags 1) all=($all -s)
+if(~ $flagt 1) all=($all -t)
+if(~ $flagu 1) all=($all -u)
+# ignore -1
+
+/$cputype/bin/ls $all $* | $post
--- /dev/null
+++ b/rc/bin/ape/printf
@@ -1,0 +1,4 @@
+#!/bin/rc
+
+# Here only for autoconf and friends.
+echo -n $1
--- /dev/null
+++ b/rc/bin/ape/psh
@@ -1,0 +1,10 @@
+#!/bin/rc
+# set up a shell running in an approximate POSIX 1003.2 environment
+rfork en
+fn sigterm{}
+HOME=$home
+bind -b /rc/bin/ape /bin
+bind -b /$cputype/bin/ape /bin
+if(test -d /$cputype/bin/pub)
+	bind -a /$cputype/bin/pub /bin
+/bin/sh $*
--- /dev/null
+++ b/rc/bin/ape/ranlib
@@ -1,0 +1,3 @@
+#!/bin/rc
+
+exit 0
--- /dev/null
+++ b/rc/bin/ape/rmdir
@@ -1,0 +1,2 @@
+#!/bin/rc
+rm $*
--- /dev/null
+++ b/rc/bin/ape/true
@@ -1,0 +1,2 @@
+#!/bin/rc
+exit 0
--- /dev/null
+++ b/rc/bin/ape/umask
@@ -1,0 +1,2 @@
+#!/bin/rc
+echo no umask in Plan 9
--- /dev/null
+++ b/rc/bin/ape/yacc
@@ -1,0 +1,16 @@
+#!/bin/rc
+
+flagfmt='d,l,t,v,b stem'
+args='grammar'
+
+if(! ifs=() eval `{aux/getflags $*} || ! ~ $#* 1){
+	aux/usage
+	exit usage
+}
+
+y=-S
+if (~ $#flagb 1) y=($y -s $flagb)
+if (~ $#flagd 1) y=($y -d)
+if (~ $#flagt 1) y=($y -D2)
+if (~ $#flagv 1) y=($y -v)
+exec /$cputype/bin/yacc $y $*
--- /dev/null
+++ b/rc/bin/broke
@@ -1,0 +1,8 @@
+#!/bin/rc
+U=`{cat /dev/user}
+if(~ $#* 1){
+	U=$1
+}
+ps | sed -n '/^'$U' .* Broken/s%[^ ]*  *%~>/proc/%
+s%  *.* (.*)%/ctl # \1%
+s%~%echo kill%p'
--- /dev/null
+++ b/rc/bin/bundle
@@ -1,0 +1,8 @@
+#!/bin/rc
+echo '# To unbundle, run this file'
+for(i in $*){
+	echo 'echo '$i
+	echo 'sed ''s/.//'' >'$i' <<''//GO.SYSIN DD '$i''''
+	sed 's/^/-/' $i
+	echo '//GO.SYSIN DD '$i
+}
--- /dev/null
+++ b/rc/bin/cpurc
@@ -1,0 +1,77 @@
+#!/bin/rc
+# cpu server start up
+date > /env/boottime
+
+# mount points
+mntgen -s slashn && chmod 666 /srv/slashn
+
+# name translation, cs sets /dev/sysname
+ndb/cs
+sysname=`{cat /dev/sysname}
+
+# parallelism for mk
+NPROC = `{wc -l </dev/sysstat}
+
+# site-specific startup
+if(test -e /rc/bin/cpurc.local)
+	. /rc/bin/cpurc.local
+
+if (~ $#sysname 0 || ~ $sysname '') {
+	sysname = helix			# default
+	echo -n $sysname >/dev/sysname
+}
+prompt=($sysname^'# ' '	')
+
+# cpu-specific startup
+if(test -e /cfg/$sysname/cpurc)
+	. /cfg/$sysname/cpurc
+
+# start up internet if we don't already have an address
+if(! grep u /net/ipselftab | grep -sv 127.0.0.1)
+	ip/ipconfig
+if(! grep -s 127.0.0.1 /net/ipselftab)
+	ip/ipconfig loopback /dev/null 127.1
+
+# if we're not a server, start a dns resolver
+if(! test -e /srv/dns)
+	ndb/dns -r
+
+# If you are on an auth server, start these before listening:
+#
+# auth/keyfs -wp -m /mnt/keys /adm/keys >/dev/null >[2=1]
+# auth/cron >>/sys/log/cron >[2=1] &
+#
+# also rename some files:
+#
+# if(! test -e /rc/bin/service.auth/tcp567){
+#	mv /rc/bin/service.auth/authsrv.il566 /rc/bin/service.auth/il566
+#	mv /rc/bin/service.auth/authsrv.tcp567 /rc/bin/service.auth/tcp567
+#	mv /rc/bin/service/il566 /rc/bin/service/_il566
+#	mv /rc/bin/service/tcp567 /rc/bin/service/_tcp567
+# }
+
+# start listeners if it hasn't already been done (dicey check)
+if(! netstat -n | grep -s 'tcp.*Listen.* (7|9|21|22|23|25|110|113|565|993|17007|17009|17010) .*')
+	aux/listen -q tcp
+# we don't use IL, maybe you do
+if(! netstat -n | grep -v 17008 | grep -s il.*Listen)
+	aux/listen -q il
+
+if(! ps|grep -s timesync) {
+	aux/timesync -n pool.ntp.org
+	if (test -e '#r/rtc') @ {
+		sleep 10			# let timesync correct the time
+		awk '{print $1}' /dev/time >'#r/rtc'	# fix hw clock
+	} &
+}
+
+# cpu-specific late startup
+if(test -e /cfg/$sysname/cpustart)
+	. /cfg/$sysname/cpustart
+
+# mode of /proc/*/ctl is inherited across rfork, and sets modes on
+# other /proc files, such as note, so let listen be killed.
+dontkill '^(ipconfig|factotum|mntgen|venti|fossil|cs|dns|reboot)$'
+
+# echo `{date} $sysname >>/sys/log/boot
+exit ''
--- /dev/null
+++ b/rc/bin/cpurc.local
@@ -1,0 +1,11 @@
+#!/bin/rc
+# local cpu startup
+
+# used only by upas, as default return domain appended to all unqualified
+# return addresses, even local ones
+site=EXAMPLE
+# replace FILESERVER with the name of your file server
+# here we start with kfs, your local disk file system
+fileserver=kfs
+# replace FACEDOM with the local domain to be used in the faces database
+facedom=FACEDOM
--- /dev/null
+++ b/rc/bin/delkey
@@ -1,0 +1,52 @@
+#!/bin/rc
+
+rfork e
+
+ctl = /mnt/factotum/ctl
+if(test -r /mnt/term/mnt/factotum/ctl)
+	ctl = /mnt/term/mnt/factotum/ctl
+
+fn forceit {
+	switch($force){
+	case no
+		echo -n $* '? [y/n]' > /dev/cons
+		ok = `{read}
+		switch($ok){
+		case y* Y*
+			echo yes
+		case q* Q*
+			exit ''
+		case *
+			echo no
+		}
+	case *
+		echo yes
+	}
+}
+
+fn deleteit {
+	key = `{echo $* | sed 's/ ![0-9a-zA-Z_]+\??/ /g' | sed 's/ +$//'}
+	if(~ `{forceit del$key} yes)
+		if(! echo del$key > $ctl)
+			exit bad
+}
+
+force = no
+
+if(~ $1 '-f'){
+	force = yes
+	shift
+}
+
+ifs='
+'
+
+if(~ $#* 0){
+	for(i in `{cat $ctl})
+		deleteit $i
+	exit ''
+}
+
+for(i in `{grep $"* $ctl})
+	deleteit $i
+exit ''
--- /dev/null
+++ b/rc/bin/diffy
@@ -1,0 +1,14 @@
+#!/bin/rc
+# diffy [diff-opts] file... - diff file against yesterday's version(s)
+rfork e
+diffopts=()
+while(! ~ $#* 0 && ~ $1 -* && ! ~ $1 --){
+	diffopts=($diffopts $1)
+	shift
+}
+if(~ $1 --)
+	shift
+if(! ~ $#* 1)
+	diffopts=($diffopts -m)
+for(f)
+	diff $diffopts `{yesterday $f} $f
--- /dev/null
+++ b/rc/bin/dircp
@@ -1,0 +1,9 @@
+#!/bin/rc
+# dircp src dest - copy a tree with tar
+switch($#*){
+case 2
+	@ {builtin cd $1 && tar cif /fd/1 .} | @ {builtin cd $2 && tar xTf /fd/0}
+case *
+	echo usage: dircp from to >[1=2]
+	exit usage
+}
--- /dev/null
+++ b/rc/bin/diskparts
@@ -1,0 +1,34 @@
+#!/bin/rc
+# set up any disk partitions
+rfork e
+if (! test -e /dev/sdctl)
+	bind -b '#S' /dev
+
+# set up any /dev/sd partitions.
+# note that really big disks (e.g., aoe devices) may have no mbr
+# partition table because the mbr partition table can't cope with large
+# block numbers, so we may have to examine the data file with prep if
+# there's no plan9 file.  beware that `disk/prep -p data' on a disk with
+# no plan 9 partition table will delete all extant partitions.
+for(disk in /dev/sd*) {
+	if(test -f $disk/data && test -f $disk/ctl)
+		{ disk/fdisk -p $disk/data |
+			grep -v '^delpart ' >$disk/ctl } >[2]/dev/null
+	if(test -f $disk/plan9)
+		parts=($disk/plan9*)
+	if not
+		parts=($disk/data)
+	for(part in $parts)
+		if(test -f $part)
+			 { disk/prep -p $part |
+				grep -v '^delpart ' >$disk/ctl } >[2]/dev/null
+}
+
+sysname=`{cat /dev/sysname}
+
+# set up any fs(3) partitions
+if (! test -e /dev/fs/ctl && test -e '#k/fs')
+	bind -b '#k' /dev
+if (~ $#sysname 1 && ! ~ $sysname '' &&
+    test -r /cfg/$sysname/fsconfig && test -w /dev/fs/ctl)
+	read -m /cfg/$sysname/fsconfig >/dev/fs/ctl
--- /dev/null
+++ b/rc/bin/dmaon
@@ -1,0 +1,7 @@
+#!/bin/rc
+# dmaon - turn on ide dma, if possible
+rfork e
+for (ctl in /dev/sd[C-H]?/ctl)
+	if (test -e $ctl && grep -s '^config .* dma ' $ctl &&
+	    ! grep -s '^config (848A|.* dma 00000000 )' $ctl)
+		echo 'dma on' >$ctl
--- /dev/null
+++ b/rc/bin/doc2ps
@@ -1,0 +1,21 @@
+#!/bin/rc
+# doc2ps [file.doc] - convert ms word document to postscript
+rfork e
+fn usage {
+	echo usage: doc2ps '[file.doc]' >[1=2]
+	exit usage
+}
+switch ($#*) {
+case 0
+	file=/tmp/antiword.doc.$pid
+	fn sigexit { rm $file; exit $s }
+	cat >$file
+case 1
+	if(~ $1 -*)
+		usage
+	file=$1
+case *
+	usage
+}
+aux/antiword -i0 -p letter $file 
+s=$status
--- /dev/null
+++ b/rc/bin/doc2txt
@@ -1,0 +1,31 @@
+#!/bin/rc
+
+rfork en
+
+if(! ~ $#* 0 1) {
+	echo 'Usage: doc2txt [file.doc]' >[1=2]
+	exit usage
+}
+
+switch($#*){
+case 0
+	cat >/tmp/doc2txt.$pid
+	file=/tmp/doc2txt.$pid
+case 1
+	file=$1
+}
+aux/olefs $file || { 
+	echo 'doc2txt: couldn''t mount word document' >[1=2]
+	rm -f /tmp/doc2txt.$pid
+	exit word
+}
+
+if(! test -f /mnt/doc/WordDocument) {
+	echo 'doc2txt: is an msoffice doc but not a word document' >[1=2]
+	rm -f /tmp/doc2txt.$pid
+	exit worddoc
+}
+
+aux/mswordstrings /mnt/doc/WordDocument | tcs -f microsoft -t utf |fmt  | uniq
+unmount /mnt/doc
+rm -f /tmp/doc2txt.$pid
--- /dev/null
+++ b/rc/bin/doctype
@@ -1,0 +1,76 @@
+#!/bin/rc
+# doctype:  synthesize proper command line for troff
+
+troff=troff
+eqn=eqn
+prefer=prefer
+opt=''
+dev=''
+while(~ $1 -*){
+	switch($1){
+	case -n;
+		troff=nroff
+		eqn=neqn
+		prefer='prefer -n'
+	case -T
+		dev=$1
+	case -*
+		opt=$opt' $1'
+	}
+	shift
+}
+ifs='
+'{
+	files=`{echo $*}
+}
+grep -h '\$LIST|\|reference|Jp|^\.(EQ|TS|\[|PS|IS|GS|G1|GD|PP|BM|LP|BP|PI|cstart|begin|TH...)|^\.P$' $* |
+sort -u |
+awk '
+BEGIN	{ files = "'$files'" }
+/\$LIST/ { e++ }
+/^\.PP/	{ ms++ }
+/^\.LP/	{ ms++ }
+/^\.EQ/	{ eqn++ }
+/^\.TS/	{ tbl++ }
+/^\.PS/	{ pic++ }
+/^\.IS/	{ ideal++ }
+/^\.GS/ { tped++ }
+/^\.G1/ { grap++; pic++ }
+/^\.GD/ { dag++; pic++ }
+/^\.\[/	{ refer++ }
+/\|reference/ { prefer++ }
+/^\.cstart/ { chem++; pic++ }
+/^\.begin +dformat/ { dformat++; pic++ }
+/^\.TH.../ { man++ }
+/^\.BM/ { lbits++ }
+/^\.P$/	{ mm++ }
+/^\.BP/	{ pictures++ }
+/^\.PI/	{ pictures++ }
+/^\.ft *Jp|\\f\(Jp/ { nihongo++ }
+END {
+	x = ""
+	if (refer) {
+		if (e)	x = "refer/refer -e " files " | "
+		else	x =  "refer/refer " files "| "
+		files = ""
+	}
+	else if (prefer) { x = "cat " files "| '$prefer'| "; files = "" }
+	if (tped)  { x = x "tped " files " | "; files = "" }
+	if (dag)  { x = x "dag " files " | "; files = "" }
+	if (ideal) { x = x "ideal -q " files " | "; files = "" }
+	if (grap)  { x = x "grap " files " | "; files = "" }
+	if (chem)  { x = x "chem " files " | "; files = "" }
+	if (dformat)  { x = x "dformat " files " | "; files = "" }
+	if (pic)   { x = x "pic " files " | "; files = "" }
+	if (tbl)   { x = x "tbl " files " | "; files = "" }
+	if (eqn)   { x = x "'$eqn' '$dev' " files " | "; files = "" }
+	x = x "'$troff' "
+	if (man) x = x "-man"
+	else if (ms) x = x "-ms"
+	else if (mm) x = x "-mm"
+	if (lbits) x = x " -mbits"
+	if (pictures) x = x " -mpictures"
+	if (nihongo) x = x " -mnihongo"
+	x = x " '$opt' '$dev' " files
+	print x
+}'
--- /dev/null
+++ b/rc/bin/dontkill
@@ -1,0 +1,10 @@
+#!/bin/rc
+# dontkill regexp - mark invoker's processes with names matching regexp
+#	as not killable when the kernel runs out of memory
+if (! ~ $#* 1) {
+	echo $0 regexp >[1=2]
+	exit usage
+}
+# see /sys/src/9/port/proc.c:/^killbig
+pids=`{psu | awk '$NF ~ /'$1'/ {print $2}'}
+~ $#pids 0 || chmod -w /proc/^$pids^/ctl
--- /dev/null
+++ b/rc/bin/dosmnt
@@ -1,0 +1,18 @@
+#!/bin/rc
+
+rfork e
+if(! ~ $#* 2){ 
+	echo 'usage: dosmnt N mntpt' >[1=2]
+	exit usage
+}
+
+x=(`{ls /dev/sd??/dos* >[2]/dev/null |uniq})
+if(test $#x -lt $1){
+	echo 'not that many dos disks' >[1=2]
+	exit usage
+}
+
+if(! test -f /srv/dos)
+	dossrv >/dev/null </dev/null >[2]/dev/null
+
+mount -c /srv/dos $2 $x($1)
--- /dev/null
+++ b/rc/bin/dpost
@@ -1,0 +1,10 @@
+#!/bin/rc
+# dpost [-f] [file...] - convert troff output to postscript,
+#	optionally include font def'ns
+# exec lp -dstdout $*
+if (! ~ $#* 0 && ~ $1 -f) {
+	shift
+	aux/tr2post $* | addpsfonts
+}
+if not
+	exec aux/tr2post $*
--- /dev/null
+++ b/rc/bin/eject
@@ -1,0 +1,9 @@
+#!/bin/rc
+switch($1){
+case 0
+	echo eject > /dev/fd0ctl
+case 1
+	echo eject > /dev/fd1ctl
+case *
+	echo eject > /dev/fd0ctl
+}
--- /dev/null
+++ b/rc/bin/fax
@@ -1,0 +1,126 @@
+#!/bin/rc
+# fax [-v] telephone-number recipient [file ...] - send files via fax
+rfork e
+view=no
+stdin=no
+
+fn usage {
+	echo 'usage: fax [-v] telephone-number recipient [file ...]' >[1=2]
+	exit usage
+}
+
+switch($1){
+case -v
+	view=yes
+	shift
+}
+
+switch ($#*) {
+case 0 1
+	usage
+case 2
+	stdin=yes
+}
+telno=`{echo $1|sed 's/[ \-]//g'}
+shift
+
+if (! ~ $telno [0-9]* +[0-9]*)
+	usage
+
+# our old phone system needed *9 to get outside; the new one just needs 9
+switch($telno){
+case ???????
+	telno='9,'^$telno
+case ??????????
+	telno='9,1'^$telno
+case 1??????????
+	telno='9,'^$telno
+case 011*
+	telno='9,'^$telno
+case +*
+	telno=`{echo $telno | sed 's/\+/9,011/'}
+}
+
+recip=$1
+shift
+
+script=/tmp/fax.$pid
+header=/tmp/faxh.$pid
+user=`{cat /dev/user}
+tmp=/tmp/fax.g3.$pid
+tmpin=/tmp/fax.in.$pid
+tmpps=/tmp/fax.ps.$pid
+tel=`{grep '\) '$user /lib/tel}
+myname=`{echo $tel | sed 's/ \(.*//'}
+if (~ $#myname 0)
+	myname=''
+ext=`{echo $tel | sed 's/.*\) [^ ]* [^ ]* ([^ ]*).*/\1/'}
+
+fn sigexit {
+	rm -f $tmp.* $script $header $header.* $tmpin $tmpps
+}
+fn sigint {
+	sigexit
+	exit interrupt
+}
+
+# gather input into a file
+switch($stdin){
+case yes
+	cat >$tmpin
+	infiles=$tmpin
+case *
+	infiles=($*)
+}
+
+# convert to g3
+g3files=()
+a=1
+for(i in $infiles){
+	switch(`{file $i}){
+	case *:*g3* *:*fax*
+		g3files=($g3files $i)
+	case *:*postscript
+		gs -dSAFER '-sDEVICE=dfaxlow' '-sOUTPUTFILE='$tmp'.'$#a'.%03d' \
+			-dNOPAUSE -dQUIET $i quit.ps
+		g3files=($g3files $tmp.$#a.*)
+	case *
+		lp -dstdout $i >$tmpps
+		gs -dSAFER '-sDEVICE=dfaxlow' '-sOUTPUTFILE='$tmp'.'$#a'.%03d' \
+			-dNOPAUSE -dQUIET $tmpps quit.ps
+		g3files=($g3files $tmp.$#a.*)
+	}
+	a=($a 1)		# count by increasing list length
+}
+
+pages=`{echo $g3files|wc -w}
+
+# use delimiters that are unlikely to be supplied in arguments
+{
+	echo -n s∮FAXddd∮
+	echo -n `{date}		# treat `{} output list specially
+	echo ∮
+	echo s∮FAXFFF∮$"myname^∮
+	echo s∮FAXEEE∮$"user^∮
+	echo s∮FAXVVV∮$"ext^∮
+	echo s∮FAXTTT∮$"recip^∮
+	echo s∮FAXfff∮$"telno^∮
+	echo s∮FAXPPP∮$"pages^∮
+} >>$script
+sed -f $script /sys/lib/fax/h.ps >$header
+
+gs -dSAFER '-sDEVICE=dfaxlow' '-sOUTPUTFILE='$header'.%03d' \
+	-dNOPAUSE -dQUIET $header quit.ps
+
+files=()
+for(i in $header.* $g3files){
+	files=($files -f $i)
+}
+
+switch($view){
+case yes
+	page $header.* $g3files
+case *
+	upas/qer $files /mail/faxoutqueue fax $user $telno	</dev/null
+	rx fax /sys/lib/fax/faxgoose				</dev/null
+}
--- /dev/null
+++ b/rc/bin/fedex
@@ -1,0 +1,62 @@
+#!/bin/rc
+
+if(! ~ $#* 1) {
+	echo usage: fedex 123456789012 >[1=2]
+	exit usage
+}
+
+rfork e
+
+fn bgrep{
+pattern=`{echo $1 | sed 's;/;\\&;'}
+shift
+
+@{ echo 'X {
+$
+a
+
+.
+}
+X ,x/(.+\n)+\n/ g/'$pattern'/p' |
+sam -d $* >[2]/dev/null
+}
+}
+
+fn awk2 {
+	awk 'NR%2==1 { a=$0; } 
+		NR%2==0 { b=$0; printf("%-30s %s\n", a, b); }
+	' $*
+}
+
+fn awk3 {
+	awk '{line[NR] = $0}
+	END{
+		i = 4;
+		while(i < NR){
+			what=line[i++];
+			when=line[i];
+			comment="";
+			if(!(when ~ /..\/..\/.... ..:../)){
+				# out of sync
+				printf("%s\n", what);
+				continue;
+			}
+			i++;
+			if(!(line[i+1] ~ /..\/..\/.... ..:../) &&
+				(i+2 > NR || line[i+2] ~ /..\/..\/.... ..:../)){
+				what = what ", " line[i++];
+			}
+			printf("%s  %s\n", when, what);
+		}
+	}' $*
+}
+
+# hget 'http://www.fedex.com/cgi-bin/track_it?airbill_list='$1'&kurrent_airbill='$1'&language=english&cntry_code=us&state=0' |
+hget 'http://www.fedex.com/Tracking?action=track&language=english&cntry_code=us&initial=x&mps=y&tracknumbers='$1 |
+	htmlfmt >/tmp/fedex.$pid
+sed -n '/Tracking number/,/^$/p' /tmp/fedex.$pid | awk2
+echo
+sed -n '/Reference number/,/^$/p' /tmp/fedex.$pid | awk2
+echo
+sed -n '/Date.time/,/^$/p' /tmp/fedex.$pid | sed 1,4d | fmt -l 4000 | sed 's/ [A-Z][A-Z] /&\n/g'
+rm /tmp/fedex.$pid
--- /dev/null
+++ b/rc/bin/fshalt
@@ -1,0 +1,108 @@
+#!/bin/rc
+# fshalt [-r] - sync (flush) and, if possible, halt all file servers
+#	and optionally reboot
+rfork e
+reboot=no
+switch ($#*) {
+case 0
+case 1
+	reboot=yes
+case *
+	echo usage: $0 '[-r]' >[1=2]
+	exit usage
+}
+
+path=(/bin)
+builtin cd /
+
+setrtc
+
+# start venti flushing
+venti/sync -h localhost >[2]/dev/null &
+venti/sync  >[2]/dev/null &
+
+unmount /mnt/consoles >[2]/dev/null
+kill consolefs | rc			# don't compete with /mnt/consoles
+sleep 1
+
+f=`{ls /srv/fscons*>[2]/dev/null}
+k=`{ls /srv/kfs*cmd >[2]/dev/null|sort -r}
+
+echo -n syncing...
+for(i in $f) @ {
+	echo -n $i...
+	{
+		echo
+		dial/drain &
+		sleep 2
+		echo fsys all sync
+		if(! dial/expect -t 120 ': ')
+			echo -n 'not synced...' > /dev/cons
+	} < $i >> $i
+}
+
+# flush the last bit of possible fossil traffic
+echo -n venti...
+venti/sync -h localhost >[2]/dev/null &
+venti/sync  >[2]/dev/null &
+sleep 5
+
+for (i in $k){
+	echo -n $i... 
+	switch($i){
+	case /srv/kfs.cmd
+		disk/kfscmd sync
+	case *
+		disk/kfscmd -n `{echo $i | sed -n 's%/srv/kfs.(.*).cmd%\1%p'} sync
+	}
+	sleep 2
+}
+
+# halting (binaries we run can't be on the fs we're halting)
+ramfs
+builtin cd /tmp
+cp /bin/dial/expect /tmp
+cp /bin/echo /tmp
+cp /bin/disk/kfscmd /tmp
+cp /bin/rc /tmp
+cp /bin/sed /tmp
+cp /bin/ns /tmp
+cp /bin/iostats /tmp
+mkdir /tmp/lib
+cp /rc/lib/rcmain /tmp/lib
+bind /tmp /rc
+bind /tmp /bin
+
+# put this in a shell function so this rc script doesn't get read
+# when it's no longer accessible
+fn x {
+	echo
+	echo -n halting...
+	for(i in $f) @ {
+		echo -n $i...
+		{
+			echo fsys all halt
+			if(! expect -t 60 ': ')
+				echo -n 'not halted...' > /dev/cons
+		} < $i >> $i
+	}
+	
+	for (i in $k){
+		echo -n $i... 
+		switch($i){
+		case /srv/kfs.cmd
+			kfscmd halt
+		case *
+			kfscmd -n `{echo $i | sed -n 's%/srv/kfs.(.*).cmd%\1%p'} halt
+		}
+	}
+	echo
+	echo done halting
+
+	if (~ $reboot yes) {
+		echo rebooting...
+		echo reboot >'#c/reboot'
+	}
+}
+
+x
--- /dev/null
+++ b/rc/bin/go.fishing
@@ -1,0 +1,15 @@
+#!/bin/rc
+# go.fishing - set up vacation responder
+rfork e
+
+cd /mail/box/$user
+if (test -e gone.fishing) {
+	echo $0: /mail/box/$user/gone.fishing already exists >[1=2]
+	exit 'already fishing'
+}
+
+>gone.addrs
+chmod -a gone.addrs
+>gone.addrs
+chmod +arw gone.addrs
+>>gone.fishing
--- /dev/null
+++ b/rc/bin/homespool
@@ -1,0 +1,17 @@
+#!/bin/rc
+
+echo creating spool directory
+mkdir $home/spool
+chmod 777 $home/spool
+echo creating ctrl directory
+mkdir $home/spool/ctrl
+chmod 775 $home/spool/ctrl
+echo creating seqno file
+touch $home/spool/ctrl/seqno
+echo creating options file
+chmod 222 $home/spool/ctrl/seqno
+cat >$home/spool/ctrl/options <<EOF
+facedown
+nobanner
+	$user
+EOF
--- /dev/null
+++ b/rc/bin/ipconf/inside
@@ -1,0 +1,19 @@
+#!/bin/rc
+
+ip/ipconfig
+
+# supply unknowns with inside addresses
+if( ! grep -s 'auth=' /net/ndb){
+	echo '	auth=135.104.9.7'>>/net/ndb
+	echo '	authdom=cs.bell-labs.com'>>/net/ndb
+}
+if( ! grep -s 'ntp=' /net/ndb)
+	echo '	ntp=135.104.9.2'>>/net/ndb
+if( ! grep -s 'dns=' /net/ndb){
+	echo '	dns=135.104.8.38'>>/net/ndb
+	echo '	dns=135.104.70.11'>>/net/ndb
+}
+
+# start dns if it isn't already going
+if(! test -e /srv/dns )
+	ndb/dns -r
--- /dev/null
+++ b/rc/bin/ipconf/lra
@@ -1,0 +1,92 @@
+#!/bin/rc
+
+# on hook and initialize
+fn initfn {
+	dial/drain
+	dial/at -q -t 5 zh0
+}
+
+# dial telephone number
+fn dialfn {
+	dial/drain
+	dial/at -q -t 60 dt^$1
+}
+
+# process options
+for(i in $*){
+	switch($i){
+	case '-P'
+		primary=-P
+	}
+}
+
+# the following can be inherited
+switch($dev){
+case ''
+	dev=/dev/eia1
+}
+switch($telno){
+case ''
+	telno=18009878722
+}
+switch($baud){
+case ''
+	baud=115200
+}
+
+{
+	# set up uart
+	if( test -e $dev^ctl ){
+		echo -n b^$baud	# baud rate
+		echo -n m1	# cts/rts flow control
+		echo -n q64000	# big buffer
+		echo -n n1	# nonblocking writes
+		echo -n r1	# rts on
+		echo -n d1	# dtr on
+		echo -n c1	# handup wen we lose dcd
+	} > $dev^ctl
+
+	# get the modem's attention
+	while( ! initfn )
+		sleep 1
+
+	# dial
+	while( ! dialfn $telno )
+		sleep 30
+		
+	if( ! dial/expect -it 60 'username:' ){
+		echo lra: can''t connect >[1=2]
+		exit connect
+	}
+	dial/pass
+	if( ! dial/expect -it 60 'password:' ){
+		echo lra: can''t connect >[1=2]
+		exit connect
+	}
+	dial/pass
+	if( ! dial/expect -t 60 'telnet:' ){
+		echo lra: can''t connect >[1=2]
+		exit connect
+	}
+	echo ppp
+	echo connected to lra >[1=2]
+
+	# start ppp
+	ip/ppp $primary -f
+} < $dev > $dev
+
+# supply unknowns with inside addresses
+if( ! grep -s 'auth=' /net/ndb){
+	echo '	auth=135.104.9.7'>>/net/ndb
+	echo '	authdom=cs.bell-labs.com'>>/net/ndb
+}
+if( ! grep -s 'ntp=' /net/ndb)
+	echo '	ntp=135.104.9.2'>>/net/ndb
+if( ! grep -s 'dns=' /net/ndb){
+	echo '	dns=135.104.8.38'>>/net/ndb
+	echo '	dns=135.104.70.11'>>/net/ndb
+}
+
+# start dns if it isn't already going
+if(! test -e /srv/dns )
+	ndb/dns -r
--- /dev/null
+++ b/rc/bin/ipconf/outside
@@ -1,0 +1,24 @@
+#!/bin/rc
+ip/ipconfig -dDG
+
+# supply unknowns with outside addresses
+if( ! grep -s 'auth=' /net/ndb){
+	echo '	auth=204.178.31.3'>>/net/ndb
+	echo '	authdom=cs.bell-labs.com'>>/net/ndb
+}
+if( ! grep -s 'ntp=' /net/ndb)
+	echo '	ntp=204.178.31.2'>>/net/ndb
+if( ! grep -s 'dns=' /net/ndb){
+	echo '	dns=204.178.31.3'>>/net/ndb
+	echo '	dns=204.178.31.4'>>/net/ndb
+}
+
+# set ndbfile for termrc touse
+NDBFILE=/lib/ndb/external
+
+# start dns if it isn't already going
+if(! test -e /srv/dns )
+	ndb/dns -r
+
+# just in case we can't find achille
+cpu=tcp!204.178.31.2
--- /dev/null
+++ b/rc/bin/ipconf/theworld
@@ -1,0 +1,76 @@
+#!/bin/rc
+
+fn initfn {
+	dial/flush
+	echo +++
+	echo -n atzh0
+	dial/expect -q -t 5 OK
+}
+
+fn dialfn {
+	dial/flush
+	echo -n atdt^$telno^
+	dial/expect -q -t 60 CONNECT
+}
+
+# process options
+for(i in $*){
+	switch($i){
+	case '-P'
+		primary=-P
+	}
+}
+
+switch($dev){
+case ''
+	dev=/dev/eia1
+}
+switch($telno){
+case ''
+	telno=18009878722
+}
+switch($baud){
+case ''
+	baud=115200
+}
+
+{
+	# set up uart
+	if( test -e $dev^ctl ){
+		echo -n b^$baud
+		echo -n m1	# cts/rts flow control
+		echo -n q64000	# big buffer
+		echo -n n1	# nonblocking writes
+		echo -n r1	# rts on
+		echo -n d1	# dtr on
+		echo -n c1	# handup wen we lose dcd
+	} > $dev^ctl
+
+	# get the modem's attention
+	while( ! initfn )
+		sleep 1
+
+	# dial
+	while( ! dialfn )
+		sleep 30
+	echo connected to the world >[1=2]
+
+	# start ppp
+	ip/ppp $primary -f
+} < $dev > $dev
+
+# supply unknowns with outside addresses
+if( ! grep -s 'auth=' /net/ndb){
+	echo '	auth=204.178.31.3'>>/net/ndb
+	echo '	authdom=cs.bell-labs.com'>>/net/ndb
+}
+if( ! grep -s 'ntp=' /net/ndb)
+	echo '	ntp=204.178.31.2'>>/net/ndb
+if( ! grep -s 'dns=' /net/ndb){
+	echo '	dns=204.178.31.3'>>/net/ndb
+	echo '	dns=204.178.31.4'>>/net/ndb
+}
+
+# start dns if it isn't already going
+if(! test -e /srv/dns )
+	ndb/dns -r
--- /dev/null
+++ b/rc/bin/ipso
@@ -1,0 +1,163 @@
+#!/bin/rc
+# ipso - edit secstore files, reload factotum keys
+if(! ~ $service terminal &&
+    ! ~ $user `{ ls -ld /mnt/factotum/ctl | awk '{print $4}' }){
+	echo >[1=2] ipso should be run only on the terminal
+	exit terminal
+}
+
+rfork e
+path=(/bin)
+home=(/tmp)
+editor = (acme -c1)
+name = secstore
+get = secstoreget
+put = secstoreput
+edit = no
+load = no
+flush = no
+
+fn secstoreget{
+	auth/secstore -i -g $1 <_password
+}
+
+fn secstoreput{
+	auth/secstore -i -p $1 <_password
+}
+
+fn aesget{
+	if(! ~ $1 /*){
+		echo >[1=2] ipso: aescbc requires fully qualified pathname
+		exit usage
+	}
+	auth/aescbc -i -d < $1 > `{basename $1} <[3] _password
+}
+
+fn aesput{
+	auth/aescbc -i -e > $1 < `{basename $1} <[3] _password
+}
+
+fn editedfiles{
+	if(~ $get aesget){
+		for(i in $files)
+			if(ls -tr | sed '1,/^_timestamp$/d' | grep -s '^'^`{basename $i}^'$')
+				echo $i
+	}
+	if not
+		ls -tr | sed '1,/^_timestamp$/d'
+}
+
+edexp=`{grep '^editor=' /mnt/plumb/rules >[2]/dev/null}
+if(~ $#edexp 1)
+	eval $edexp
+
+while(~ $1 -*){
+	switch($1){
+	case -s
+		editor = sam
+	case -a
+		name = aescbc
+		get = aesget
+		put = aesput
+	case -f
+		flush = yes
+	case -e
+		edit = yes
+	case -l
+		load = yes
+	case *
+		echo >[2=1] 'usage: ipso [-a -f -e -l] [-s] [file ...]'
+		exit usage
+	}
+	shift
+}
+
+if(~ $flush no && ~ $edit no && ~ $load no){
+	load = yes
+	edit = yes
+	flush = yes
+}
+
+if(~ $flush yes && ~ $edit no && ~ $load no){
+	echo flushing old keys
+	echo delkey > /mnt/factotum/ctl
+	exit 0
+}
+
+if(~ $get aesget && ~ $#* 0){
+	echo >[2=1] ipso: must specify a fully qualified file name for aescbc '(-a)'
+	exit usage
+}
+
+rfork ne
+ramfs -p >[2] /dev/null # silence 'i/o on hungup channel' message at exit
+unmount /mnt/plumb
+bind -c /tmp /srv
+builtin cd /tmp
+
+if ( ~ $edit yes ) echo '
+	Warning: The editor will display the secret contents of
+	your '$name' files in the clear.
+'
+# get password and remember it
+{
+	echo rawon
+	echo -n $name password: >/dev/cons
+	read > _password
+	echo > /dev/cons
+}</dev/cons > /dev/consctl
+
+# get list of files
+if(~ $#* 0){
+	if(! auth/secstore -G . -i < _password > _listing){
+		echo 'secstore read failed - bad password?'
+		sleep 2
+		exit password
+	}
+	files=`{sed 's/[ 	]+.*//' _listing}
+}
+if not
+	files = $*
+
+# copy the files to local ramfs
+for(i in $files){
+	if(! $get $i){
+		echo $name ' read failed - bad password?'
+		sleep 2
+		exit password
+	}
+}
+sleep 2; date > _timestamp	# so we can find which files have been edited.
+
+# edit the files
+if(~ $edit yes) $editor `{for(i in $files) basename $i}
+if(~ $flush yes ){
+	echo flushing old keys
+	echo delkey > /mnt/factotum/ctl
+}
+if(~ $load yes){
+	echo loading factotum keys
+	if (~ factotum $files) read -m < factotum > /mnt/factotum/ctl
+}
+
+# copy the files back
+for(i in `{editedfiles}){
+	echo -n copy ''''`{basename $i}^'''' back?' [y/n/x]'
+	switch(`{read}){
+	case [yY]*
+		if(! $put $i){
+			echo $name ' read failed - bad password?'
+			sleep 2
+			exit password
+		}
+		echo ''''$i'''' copied to $name
+		if(~ $i factotum)
+			read -m < $i > /mnt/factotum/ctl
+	case [xXqQ]*
+		exit
+	case [nN]* *
+		echo ''''$i'''' skipped
+	}
+}
+
+exit ''
--- /dev/null
+++ b/rc/bin/ipv6on
@@ -1,0 +1,94 @@
+#!/bin/rc
+# ipv6on [netdir ndbfile [gwv4]] - configure an interface for ipv6,
+#	once ipv4 is configured.
+if (! ~ $#* 0 2 3) {
+	echo usage: $0 '[netdir ndbfile [gw-v4-name]]' >[1=2]
+	exit usage
+}
+rfork e
+if (~ $#* 0) {
+	netdir=/net
+	ndbf=/lib/ndb/local
+	gw=`{ndb/ipquery sys $sysname ipgw | sed 's/ipgw=//'}
+}
+if not {
+	netdir=$1
+	ndbf=$2
+	if (~ $#* 2)
+		# gw=()
+		gw=`{ndb/ipquery sys $sysname ipgw | sed 's/ipgw=//'}
+	if not
+		gw=$3
+}
+if (~ $netdir /net) {
+	xsfx=()
+	xdir=()
+}
+if not {
+	xsfx=(-x `{echo $netdir | sed 's;^/net;;'})
+	xdir=(-x $netdir)
+}
+
+fn nonnil {		# variable
+	if (~ $#$1 0) {
+		echo no ip for $1
+		exit no-ip
+	}
+	if (! ~ $#$1 1) {
+		echo multiple ips for $1
+		exit multiple-ips
+	}
+}
+
+#
+# configure v6 for link-local addresses (fe80::) & multicast (ff02::)
+#
+if (! ip/ipconfig -6 $xdir ether $netdir/ether?)
+	exit 'ipconfig -6 failed'
+ip/ipconfig $xdir ether $netdir/ether? ra6 recvra 1
+
+mev6=`{ndb/query -f $ndbf sys $sysname ipv6}
+if (~ $#sysname 0 || ~ $sysname '')
+	mev6=`{ndb/query -f $ndbf sys $sysname ip | grep :}
+# mev4=`{ndb/query -f $ndbf sys $sysname ip | grep -v :}
+
+# for testing
+mylnk=`{ip/linklocal `{cat $netdir/ether?/addr}}
+nonnil mylnk
+
+if (~ $#gw 1) {
+	if (~ $gw [0-9]*.[0-9]*.[0-9]*.[0-9]*)
+		gwv4 = $gw
+	if (~ $#gwv4 0 || ~ $gwv4 '')		# assume namev6 and name
+		gwv4=`{ndb/query -f $ndbf sys $gw ip}
+	gwv6=`{ndb/query -f $ndbf sys $gw ipv6}
+
+	if (! ~ $#gwv4 0) {
+		# echo ping gw $gwv4...
+		# load arp cache with gw mac
+		ip/ping -qn 3 $netdir/icmp!$gwv4 >/dev/null >[2=1] &
+		sleep 1					# wait for ping
+
+		gweth=`{grep '* '^$gwv4^' ' $netdir/arp | awk '{print $4}' }
+		nonnil gweth
+		gwlnk=`{ip/linklocal $gweth}
+		nonnil gwlnk
+	}
+}
+nonnil mev6
+#
+# configure my global v6 addresses
+#
+ip/ipconfig $xdir ether $netdir/ether?	add $mev6 /64
+ip/ipconfig $xdir loopback /dev/null	add $mev6 /128
+
+if (~ $#gw 1) {
+	if (~ $#gwv6 0 || ~ $gwv6 '')
+		gwv6=`{ip/linklocal $gweth}
+	nonnil gwv6
+	#
+	# add default v6 route to v6 addr of v4 gw
+	#
+	echo add :: /0 $gwv6 >$netdir/iproute	# need not be link-local
+}
+exit ''
--- /dev/null
+++ b/rc/bin/iwhois
@@ -1,0 +1,87 @@
+#!/bin/rc
+# iwhois [-n] domain - print registration data for domain
+rfork e
+if (~ $#* 1 && ~ $1 -n)
+	noboiler=yes
+person=`{echo $1|sed s/@.*//}
+fn boilerplate { sed -n '/^[	 ]*[A-Za-z][A-Za-z]*:$/,$p' $* }
+
+switch($1){
+case *@*
+	machine=`{echo $1|sed s/.*@//}
+case *.ca
+	machine=whois.cira.ca
+	fn boilerplate { grep -v ':[	 ]*$' $* }
+case *.us
+	machine=whois.nic.us
+	fn boilerplate { sed '/^>* Whois database was last updated on/,$d' $* }
+case *.co.uk *.net.uk *.org.uk
+	machine=whois.nic.uk
+	fn boilerplate { sed '/^ +WHOIS database last updated at/,$d' $* }
+case *.ac.uk
+	machine=whois.ja.net
+case *.au
+	machine=whois.aunic.net
+	fn boilerplate { grep -v ':[	 ]*$' $* }
+case *.be
+	machine=whois.dns.be
+	person='-T dn '^$person
+	fn boilerplate { cat $* }
+case *.cn
+	machine=whois.cnnic.net.cn
+	fn boilerplate { cat $* }
+case *.de
+	machine=whois.denic.de
+	person='-T dn '^$person
+	fn boilerplate { cat $* }
+case *.dk
+	machine=whois.dk-hostmaster.dk
+	fn boilerplate { grep -v '^#' $* }
+case *.es
+	echo no known whois server for .es
+	exit
+case *.fr
+	machine=whois.nic.fr
+	fn boilerplate { grep -v '^%%' $* }
+case *.in
+	machine=whois.inregistry.net
+	fn boilerplate { cat $* }
+case *.jp
+	machine=whois.jprs.jp
+	person=$person^'/e'
+	fn boilerplate { cat $* }
+case *.se
+	machine=whois.nic-se.se
+	fn boilerplate { grep -v '^#' $* | uniq }
+case [0-9]*.[0-9]*.[0-9]*.[0-9]*
+	machine=whois.arin.net
+	fn boilerplate { cat $* }
+case *
+	machine=whois.internic.net	# alternate: whois.networksolutions.com
+	fn boilerplate { cat $* }
+}
+if (~ $noboiler yes)
+	fn boilerplate { cat $* }
+file=/tmp/iwhois$pid
+fn sigexit {
+	rm -f $file
+}
+echo $person | telnet -nr tcp!$machine!whois > $file
+x=`{ sed -n -e 's/.*Whois Server: (.*)/\1/p' \
+	-e 's;.*ReferralServer: whois://(.*)(:43)?;\1;p' $file }
+switch($#x){
+case 0
+	;			# e.g., for .ca
+case 1
+	# chase the referral chain
+	echo $person | telnet -nr tcp!$x!whois > $file
+case *
+#	echo $0: buggery: `{echo $x | tr ' ' '\12' | sort -u} >[1=2]
+	echo $person | telnet -nr tcp!^$x(1)^!whois > $file
+}
+if (test ! -s $file) {
+	echo $0: broken whois server tcp!$x!whois returned no data >[1=2]
+	exit broken
+}
+boilerplate $file
+rm $file
--- /dev/null
+++ b/rc/bin/juke
@@ -1,0 +1,60 @@
+#!/bin/rc
+
+wide=`{echo $vgasize | sed 's/(.*)x.*x.*/\1 > 240/' | hoc}
+
+debug=0
+tflag=''
+wflag=''
+host=''
+kb=4096
+flags=()
+sname=$user
+if (! ~ $wide 1) {
+	flags=($flags -t)
+	kb=1024
+}
+while(! ~ $#* 0) {
+	switch ($1) {
+	case -d
+		debug=$2
+		shift
+	case -t
+		tflag='-t'
+	case -h
+		host=$2
+		shift
+	case -w
+		wflags='-w'
+	case -s
+		sname=$2
+		shift
+	case -*
+		echo Usage: classical [-d level] [-t] [-h srvhost]
+		exit usage
+	}
+	shift
+}
+if (! test -e /mnt/playlist){
+	if (! ~ $debug '0') echo mounting playlistfs
+	if (! test -e /srv/playlist.$sname && ! ~ $host ''){
+		import -a $host /srv /srv
+	}
+	if (! mount -b /srv/playlist.$sname /mnt >/dev/null >[2]/dev/null){
+		rm -f /srv/playlist.$sname
+		if (! ~ $debug '0') echo starting playlistfs
+		games/playlistfs -s $sname -d $debug
+	}
+}
+if (! test -w /mnt/juke) {
+	if (! test -e /srv/jukefs.$sname && ! ~ $host ''){
+		import -a $host /srv /srv
+	}
+	if (! mount -b /srv/jukefs.$sname /mnt >/dev/null >[2]/dev/null){
+		if (! ~ $debug '0') echo games/jukefs
+		games/jukefs -s $sname
+	}
+}
+if (~ $wflags '-w') {
+	exec games/jukebox -w -d $debug $tflag &
+}
+exec games/jukebox -d $debug $tflag
--- /dev/null
+++ b/rc/bin/kill
@@ -1,0 +1,4 @@
+#!/bin/rc
+for(i){
+	ps | sed -n '/ '^$i^'$/s%^[^ ]* *([^ ]*).*%chmod 666 /proc/\1/ctl;echo kill > /proc/\1/ctl%p'
+}
--- /dev/null
+++ b/rc/bin/kmem
@@ -1,0 +1,31 @@
+#!/bin/rc
+# kmem [kernel] - print summary of allocate blocks in running kernel
+rfork e
+if(! ~ $#* 0 1){
+	echo 'usage: kmem [kernel]' >[1=2]
+	exit usage
+}
+
+if(~ $#* 1)
+	binary=$1
+
+echo 'kinit(); blocksummary()' | acid -k -lkernel -lpool -lleak $pid $binary | awk '
+	$1 == "block" {
+		addr=$6
+		size=$3
+		alloc=$4
+		total[alloc] += size
+		count[alloc]++
+	}
+	$1 == "summary" { 
+		alloc=$2
+		cnt=$3
+		size=$4
+		total[alloc] += size
+		count[alloc] += cnt
+	}
+	END{
+		for(i in count)
+			printf("%6d %11d %s\n", count[i], total[i], i);
+	}
+' | sort -nr
--- /dev/null
+++ b/rc/bin/label
@@ -1,0 +1,6 @@
+#!/bin/rc
+# label word ... - write words into our label, if any
+if (test -w /dev/label)
+	echo -n $* > /dev/label
+if not if (test -w   /mnt/term/dev/label)
+	echo -n $* > /mnt/term/dev/label
--- /dev/null
+++ b/rc/bin/lc
@@ -1,0 +1,2 @@
+#!/bin/rc
+ls -p $* | mc
--- /dev/null
+++ b/rc/bin/leak
@@ -1,0 +1,95 @@
+#!/bin/rc
+
+rfork e
+
+flagfmt='a,b,c,d,s,f binary,r res,x width'
+args='name | pid list'
+if(! ifs=() eval `{aux/getflags $*} || ~ $#* 0){
+	aux/usage
+	exit usage
+}
+
+conflicting=($flagb $flagc $flags)
+if(~ $#conflicting 2 || ~ $#conflicting 3){
+	echo 'can only use one of -b, -c or -s' >[1=2]
+	exit usage
+}
+
+leakflags=()
+if(~ $#flags 1)
+	leakflags=($leakflags -s)
+if(~ $#flaga 1)
+	leakflags=($leakflags -a)
+if(~ $#flagc 1)
+	leakflags=($leakflags -c)
+if(~ $#flagd 1)
+	leakflags=($leakflags -d)
+if(~ $#flagf 1)
+	leakflags=($leakflags -f $flagf)
+
+acidleakflags=()
+if(~ $#flagb 1)
+	acidleakflags=($acidleakflags -b)
+if(~ $#flagr 1)
+	acidleakflags=($acidleakflags -r $flagr)
+if(~ $#flagx 1)
+	acidleakflags=($acidleakflags -x $flagx)
+
+if(! test -d /proc/$1) {
+	# x=`{psu | awk '$NF=="'$1'" {print $2}'}
+	x=`{psu | grep ' '$1'$' | sed 's/^[^ ]+ +([0-9]+).*/\1/'}
+	if(~ $#x 0) {
+		echo 'no processes named '$1 >[1=2]
+		exit usage
+	}
+	echo leak $leakflags $acidleakflags $x
+	exit
+}
+
+pidlist=`{echo $"* | tr ' ' ,}
+
+echo 'leakdump({'$pidlist'})' | acid -lpool -lleak $1 $flagf | 
+{
+	if(~ $#flaga 1 && ~ $#flagd 1)
+		grep 'block|free'
+	if not
+	if(~ $#flaga 1)
+		grep block
+	if not
+	if(~ $#flagd 1)
+		grep free 
+	if not
+		aux/acidleak $acidleakflags $flagf
+} |
+{
+	if(~ $#flags 1)
+		awk '{print $4}' |
+			sort | uniq -c | sort -nr |
+			sed 's! *(.*) (0x.*)!src(\2); // \1!'
+	if not
+	if(~ $#flagc 1)
+		awk 'BEGIN {
+				for(i=0; i<16; i++)
+					_unhex[sprintf("%x", i)] = _unhex[sprintf("%X", i)] = i
+			}
+			function unhex(s, i, v) {
+				sub("^0[xX]0*","",s)
+				for (i=1; i<=length(s); i++)
+					v = v*16 + _unhex[substr(s,i,1)]
+				return v
+			}
+			{	sum[$4] += unhex($3);
+				count[$4]++;
+				alloc[$4] = $6;
+			}
+			END {
+				for (v in sum) {
+					printf("src(%s);\t// %d\t%d\t%d\t%s\n", v, sum[v], count[v], sum[v] / count[v], alloc[v])
+					total += sum[v]
+				}
+				printf("// %d\n", total);
+			}
+		'  | sort -nr +2
+	if not
+		cat
+}	
--- /dev/null
+++ b/rc/bin/lookman
@@ -1,0 +1,36 @@
+#!/bin/rc
+# Usage: lookman key ...
+#	prints out the names of all manual pages containing all the given keywords
+rfork e
+index=/sys/lib/man/lookman/index
+t1=/tmp/look1.$pid
+t2=/tmp/look2.$pid
+fn sigexit {
+	rm -f $t1 $t2
+	exit
+}
+fn sigint sighup sigterm {
+	rm -f $t1 $t2
+	exit note
+}
+
+*=`{echo $*|tr A-Z a-z|tr -dc 'a-z0-9_. \012'}	# fold case, delete funny chars
+if(~ $#* 0){
+	echo Usage: lookman key ... >/fd/2
+	exit usage
+}
+look $1 $index | sed 's/.*	//' | sort -u >$t1
+shift
+for(i in $*){
+	look $i $index | sed 's/.*	//' | sort -u |
+		awk 'BEGIN {
+			while (getline < "'$t1'" > 0)
+				table[$0] = 1
+			}
+			{ if (table[$0]) print }
+		' > $t2
+	mv $t2 $t1
+}
+sort $t1 | sed 's;/sys/man/;;
+	s;(.*)/(.*);man \1 \2 # \2(\1);'
+exit ''
--- /dev/null
+++ b/rc/bin/lp
@@ -1,0 +1,212 @@
+#!/bin/rc
+# lp - enqueues the file to be printed and starts the daemon, when necessary.
+# Make changes to /sys/src/cmd/lp/lp.rc;
+# changes made directly to /rc/bin/lp will be lost.
+
+rfork en	# so that environment and name space are not polluted
+# 
+# put 'fn sigexit { rm /tmp/lpcrap; exit interrupted }' into processes that create /tmp/lpcrap.
+
+ifs=' 	
+'		# set ifs in case it is munged in user's environment
+
+LPLIB=/sys/lib/lp		# lp scripts directories and configuration file are here
+LPBIN=/$cputype/bin/aux		# lp specific binaries are here
+LPSPOOL=$LPLIB/queue		# lp queues
+LPLOGDIR=$LPLIB/log		# lp logs
+
+$LPLIB/bin/lpscratch
+x=$status
+if(! ~ $x '') exit $x
+
+# build /bin from the ground up
+bind /$cputype/bin /bin			# general compiled binaries
+bind -a /rc/bin /bin			# general rc scripts
+# This needs to be fixed for the real thing
+bind -a $LPLIB/bin /bin			# lp specific rc scripts
+bind -a $LPBIN /bin				# lp specific compiled binaries
+path=(/bin)
+
+if (! test -w /tmp) bind -bc $LPLIB/tmp /tmp
+
+USAGE='usage:	lp [-d printer] [-p process] [options] [files]
+		lp [-d printer] -q
+		lp [-d printer] -k jobnos
+
+		options include:
+		-D			turn on debugging output
+		-H			no header
+		-L			landscape mode
+		-M<mach>	print on machine <mach>
+		-Q			put task only into the queue
+		-R			restart printer daemon
+		-c<n>		make <n> copies
+		-f<font.size>	specify font and size
+		-i<src>		take media from <src> input bin
+		-l<n>		print <n> lines per logical page
+		-m<n>		magnify <n> times
+		-n<n>		print <n> logical pages per physical page
+		-o<i-j,k>	print only pages i-j and k
+		-r			reverse pages
+		-u<userid>	print as <userid>
+		-x<n>		x page offset in inches
+		-y<n>		y page offset in inches
+'
+
+# umask 000	# this doesn't work in plan 9
+if (~ $#sysname 0)
+	THIS_HOST=plan9
+if not {
+	THIS_HOST=`{ndb/query sys $sysname dom}
+	if(~ $#THIS_HOST 0)
+		THIS_HOST=$sysname
+}
+
+LPMACHID=$THIS_HOST
+THIS_USERID=$user
+LPUSERID=$THIS_USERID
+LPLOC=''
+
+# Set default printer to be output device
+if (~ $#LPDEST 0 && test -f $LPLIB/defdevice) LPDEST=`{cat $LPLIB/defdevice}
+
+# option parameters
+COPIES=1
+FONT=''
+IBIN=''
+KILLFLAG=0
+LAND=''
+LINES=''
+LPQ=0
+MAG=''
+NOHEAD=''
+NPAG=''
+OLIST=''
+POINT=''
+RESET=''
+REVERSE=''
+QONLY=''
+TRAY=''
+XOFF=''
+YOFF=''
+
+# Process options
+flagfmt='D,H,L,Q,R,r,q,M mach,c copies,d printer,f font.size,i src,k jobnos,l lines,m magnify,n lpages,o pages,p proc,u userid,x offset,y offset'
+argv0=lp
+
+if(! ifs=() eval `{aux/getflags $*}) {
+	echo $USAGE
+	exit usage
+}
+if(~ $flagd '?'){
+	awk 'BEGIN {print "device       location  host                   class"}
+/^[^#]/	{ printf "%-12s %-9s %-22s %s\n", $1, $2, $3, $6 }' $LPLIB/devices
+	exit
+}
+if(~ $flagp '?'){
+	ls $LPLIB/process
+	exit
+}
+
+if (! ~ $#flagD 0) { DEBUG=1; flag x + }; if not { DEBUG=''; flag x - }
+if (! ~ $#flagH 0) NOHEAD=1
+if (! ~ $#flagL 0) LAND=1
+if (! ~ $#flagM 0 && ~ $LPUSERID daemon) LPMACHID=$flagM
+if (! ~ $#flagQ 0) QONLY=1
+if (! ~ $#flagR 0) RESET=1
+if (! ~ $#flagc 0) COPIES=$flagc
+if(! ~ $#flagd 0) LPDEST=$flagd
+if (! ~ $#flagf 0) eval `{echo $flagf | sed -e 's/([^.]*)\.([0-9.]*)/FONT=\1;POINT=\2;/'}
+if (! ~ $#flagi 0) IBIN=$flagi
+if (! ~ $#flagk 0) KILLFLAG=1
+if (! ~ $#flagl 0) LINES=$flagl
+if (! ~ $#flagm 0) MAG=$flagm
+if (! ~ $#flagn 0) NPAG=$flagn
+if (! ~ $#flago 0) OLIST=-o^$flago
+if (! ~ $#flagp 0) LPPROC=$flagp
+if (! ~ $#flagq 0) LPQ=1
+if (! ~ $#flagr 0) REVERSE=1
+if (! ~ $#flagu 0) LPUSERID=$flagu
+if (! ~ $#flagx 0) XOFF=$flagx
+if (! ~ $#flagy 0) YOFF=$flagy
+
+if (~ $#LPDEST 0) {
+	echo 'Set environment variable LPDEST or use the
+''-d printer'' option to set the destination.' >[1=2]
+	exit 'LPDEST not set'
+}
+if (~ $LPDEST */*) {	# handles MHCC destinations like mh/lino
+	LPLOC=`{echo $LPDEST|sed 's/^(.*)\/(.*)/\1/'}
+	LPDEST=`{echo $LPDEST|sed 's/^(.*)\/(.*)/\2/'}
+}
+
+# look up device, get info
+LPDLINE=`{grep '^'$LPDEST'[ 	]' $LPLIB/devices}
+if (! ~ $status '') {
+	echo 'device '$LPDEST' is not in '$LPLIB'/devices' >[1=2]
+	exit 'LPDEST is bad'
+}
+LOC=$LPDLINE(2)
+DEST_HOST=$LPDLINE(3)
+OUTDEV=$LPDLINE(4)
+SPEED=$LPDLINE(5)
+LPCLASS=$LPDLINE(6)
+if (~ $#LPPROC 0) LPPROC=$LPDLINE(7)
+SPOOLER=$LPDLINE(8)
+STAT=$LPDLINE(9)
+KILL=$LPDLINE(10)
+DAEMON=$LPDLINE(11)
+SCHED=$LPDLINE(12)
+
+if (~ $LPCLASS *nohead*)
+	NOHEAD=1
+if (~ $LPCLASS *duplex*)
+	DUPLEX=1
+
+if (~ $#SCHED 0) SCHED=FIFO	# everyone uses FIFO
+if (~ $KILLFLAG 1)
+	switch ($KILL) {
+	case -;	echo kill option not available on $LPDEST >[1=2]
+		exit 'kill n/a'
+	case *;	bind -b $LPLIB/kill /bin
+		exec $KILL $*
+		exit 'kill command '"$KILL"' not found'
+	}
+if (~ $LPQ 1)
+	switch ($STAT) {
+	case -;	echo queue status option not available on $LPDEST >[1=2]
+		exit 'stat option not available'
+	case *;	bind -b $LPLIB/stat /bin
+		exec $STAT $* < /dev/null
+		exit 'stat command '"$STAT"' not found'
+	}
+DATE=`{date}
+LPLOG=$LPLOGDIR/$LPDEST
+if (! test -e $LPLOG) {
+	>$LPLOG
+	chmod +rwa $LPLOG >[2]/dev/null
+}
+
+if (~ $RESET '') {
+	switch ($SPOOLER) {
+	case -;	echo spooler does not exist for $LPDEST >[1=2]
+		exit 'no spooler'
+	case *;	bind -b $LPLIB/spooler /bin
+		if (~ $#* 0) $SPOOLER
+		if not $SPOOLER $*
+	}
+}
+if not {
+	echo restarting daemon for printer $LPDEST >[1=2]
+	UNLOCK $LPSPOOL/$LPDEST
+	sleep 5
+}
+
+# run daemon
+if (~ $QONLY '') {
+	if (! ~ $DAEMON -) {
+		bind -b $LPLIB/daemon /bin
+		$DAEMON $* >>$LPLOG >[2=1] &
+	}
+}
+exit ''
--- /dev/null
+++ b/rc/bin/mail
@@ -1,0 +1,12 @@
+#!/bin/rc
+switch($#*){
+case 0
+	exec upas/nedmail
+}
+
+switch($1){
+case -f* -r* -c* -m*
+	exec upas/nedmail $*
+case *
+	exec upas/marshal $*
+}
--- /dev/null
+++ b/rc/bin/man
@@ -1,0 +1,149 @@
+#!/bin/rc
+# man - print manual pages
+rfork e
+
+. /sys/man/fonts
+
+cmd=n
+sec=()
+S=/sys/man
+d=0
+
+fn roff {
+	preproc=()
+	postproc=cat
+	x=`{doctype $2}
+	if (~ $1 t) {
+		if(~ $x *grap*)
+			preproc=($preproc grap)
+		if(~ $x *pic*)
+			preproc=($preproc pic)
+		Nflag=-Tutf
+	}
+	if not {
+		Nflag='-N'
+		Lflag='-rL1000i'
+		# setting L changes page length to infinity (sed script removes empty lines)
+		if (grep -s '^\.(2C|sp *[0-9]*\.)' $2)
+			postproc=col
+	}
+	if(~ $x *eqn*)
+		preproc=($preproc eqn)
+	if(~ $x *tbl*)
+		preproc=($preproc tbl)
+	{echo -n $FONTS; cat $2 </dev/null} |
+		switch($#preproc) {
+		case 0
+			troff $Nflag $Lflag -$MAN 
+		case 1
+			$preproc | troff $Nflag $Lflag -$MAN
+		case 2
+			$preproc(1) | $preproc(2) | troff $Nflag $Lflag -$MAN
+		case 3
+			$preproc(1) | $preproc(2) | $preproc(3) |
+				troff $Nflag $Lflag -$MAN
+		case *
+			$preproc(1) | $preproc(2) | $preproc(3) |
+				$preproc(4) | troff $Nflag $Lflag -$MAN
+		} | $postproc
+}
+
+fn page {
+	if(test -d /mnt/wsys/acme)
+		/bin/page -w
+	if not
+		/bin/page
+}
+
+
+search=yes
+while(~ $d 0) {
+	if(~ $#* 0) {
+		echo 'Usage: man [-bntpPSw] [0-9] [0-9] ... name1 name2 ...' >[1=2]
+		exit
+	}
+	if(test -d $S/$1){
+		sec=($sec $1)
+		shift
+	}
+	if not
+		switch($1) {
+		case -b ; cmd=b ; shift
+		case -n ; cmd=n ; shift
+		case -P ; cmd=P ; shift
+		case -p ; cmd=p ; shift
+		case -S ; search=no ; shift
+		case -t ; cmd=t ; shift
+		case -w ; cmd=w ; shift
+		case * ; d=1
+		}
+}
+if(~ $#sec 0) {
+	sec=`{ls -pd $S/[0-9]* }
+}
+ix=$S/$sec/INDEX
+if(~ $#* 1) pat='^'^$1^' '
+if not pat='^('^`{echo $* | sed 's/ /|/g'}^') '
+fils=()
+if(~ $search yes)
+for(i in $S/$sec){
+	if(/bin/test -f $i/INDEX){
+		try=`{grep -i $pat $i/INDEX | sed 's/^[^ ]* //' | sort -u}
+		if(! ~ $#try 0)
+			fils=($fils $i/$try)
+	}
+}
+# bug: should also do following loop if not all pages found
+if(~ $#fils 0) {
+	# nothing in INDEX. try for file of given name
+	for(i) {
+		if(~ $i intro) i=0intro
+		for(n in $sec) {
+			try=`{echo $S/$n/$i | tr A-Z a-z}
+			if (/bin/test -f $try)
+				fils=($fils $try)
+		}
+	}
+	if(~ $#fils 0) {
+		echo 'man: no manual page' >[1=2]
+		exit 'no man'
+	}
+}
+for(i in $fils) {
+	if(! /bin/test -f $i)
+		echo need $i >[1=2]
+	if not {
+		switch($cmd) {
+		case w
+			echo $i
+
+		case t
+			roff t $i
+
+		case p
+			roff t $i | grep -v '^x X html' | proof
+
+		case P
+			roff t $i | page
+
+		case n
+			roff n $i | sed '
+				${
+        			       /^$/p
+				}
+				//N
+				/^\n$/D'
+
+		case b
+			x=`{echo $i | sed 's;/sys/man/(.*)/(.*);\1 \2;'}
+			if(~ $x(2) 0intro) x=($x(1) intro)
+			roff n $i | sed '
+				${
+        			       /^$/p
+				}
+				//N
+				/^\n$/D' |
+			plumb -i -d edit -a 'action=showdata filename=/man/'$x(2)^'('$x(1)^')'
+		}
+	}
+}
--- /dev/null
+++ b/rc/bin/map
@@ -1,0 +1,103 @@
+#!/bin/rc
+
+rfork en
+
+# F FEATUREs, M map files, A other arguments
+FEATURE=no
+
+if (~ $MAPPROG '')
+	MAPPROG=/bin/aux/mapd
+
+if (~ $MAPDIR '')
+	MAPDIR=/lib/map
+
+F=(); M=(); A=();
+for (i) {
+	switch ($FEATURE) {
+	case no
+		switch ($i) {
+		case -f
+			FEATURE=yes 
+			F=($F)
+		case *
+			A=($A $i)
+		}
+	case yes
+		switch ($i) {
+		case -f
+		case -*
+			A=($A $i)
+			FEATURE=no
+		case riv*2
+			F=($F 201 202)
+		case riv*3
+			F=($F 201 202 203)
+		case riv*4
+			F=($F 201 202 203 204)
+		case riv*
+			F=($F 201)
+		case iriv*2
+			F=($F 206 207)
+		case iriv*[34]
+			F=($F 206 207 208)
+		case iriv*
+			F=($F 206)
+		case coast*2 shore*2 lake*2
+			F=($F 102)
+		case coast*3 shore*3 lake*3
+			F=($F 102 103)
+		case coast*4 shore*4 lake*4
+			F=($F 102 103 104)
+		case coast* shore* lake*
+		case ilake*[234] ishore*[234]
+			F=($F 106 107)
+		case ilake* ishore*
+			F=($F 106)
+		case reef*
+			F=($F 108)
+		case canal*2
+			F=($F 210 211)
+		case canal*[34]
+			F=($F 210 211 212)
+		case canal*
+			F=($F 210)
+		case glacier*
+			F=($F 115)
+		case state* province*
+			F=($F 401)
+		case countr*2
+			F=($F 301 302)
+		case countr*[34]
+			F=($F 301 302 303)
+		case countr*
+			F=($F 301)
+		case salt*[234]
+			F=($F 109 110)
+		case salt*
+			F=($F 109)
+		case ice*[234] shel*[234]
+			F=($F 113 114)
+		case ice* shel*
+			F=($F 113)
+		case *
+			echo map: unknown feature $i >[1=2]
+			exits "unknown feature"
+		}
+	}
+}
+
+for (j in $F) {
+	if (test -r $MAPDIR/$j)
+		M=($M $MAPDIR/$j)
+}
+
+if (~ $F ?*) {
+	if (test -r $MAPDIR/101)
+		M=(101 $M)
+	M=(-m $M)
+}
+
+if (~ $MAP '')
+	MAP=world
+
+MAP=$MAP MAPDIR=$MAPDIR $MAPPROG $A $M
--- /dev/null
+++ b/rc/bin/mapdemo
@@ -1,0 +1,83 @@
+#!/bin/rc
+
+fn demo {proj=$1;	shift;
+	label=$1;	shift;
+	{	echo 'o'
+		echo 'ra -8192 -8492 8192 8492'
+		echo 'e'
+		echo 'm -8192 8192'
+		echo t $type
+		echo 'm -8192 -8192'
+		echo t $proj - $label
+		MAP=world MAPDIR=/lib/map map $proj $* -s -d 5
+	} 
+	sleep 5
+}
+
+rfork en
+{
+type='Equatorial projections centered on long. 0. Parallels are straight lines.'
+
+demo mercator 'equally spaced straight meridians, conformal, straight compass courses'
+demo sinusoidal 'equally spaced parallels, equal-area, same as bonne(0)'
+demo cylequalarea 'equally spaced straight meridians, equal-area, true scale on Eq' 0
+demo cylindrical 'central projection on tangent cylinder'
+demo rectangular 'equally spaced parallels, equally spaced straight meridians, true scale on Eq' 0
+demo gall 'parallels spaced stereographically on prime meridian, equally spaced straight meridians, true scale on Eq' 0
+demo mollweide '(homalographic) equal-area, hemisphere is a circle'
+demo gilbert 'globe mapped conformally on hemisphere, viewed orthographically'
+
+type='Azimuthal: centered on the North Pole, Parallels are concentric circles, Meridians are equally spaced radial lines'
+
+demo azequidistant 'equally spaced parallels, true distances from pole'
+demo azequalarea 'equal area'
+demo gnomonic 'central projecton on tangent plane, straight great circles'
+demo perspective 'viewed along earth''s axis 2 earth radii from center of earth' 2
+demo orthographic 'viewed from infinity'
+demo stereographic 'conformal, projected from opposite pole'
+demo laue 'radius = tan(2\(mu colatitude ), used in xray crystallography'
+demo fisheye 'fisheye view of stereographic map, index of refraction 2' 2 -o 40.75 74
+demo newyorker 'New Yorker map from viewing pedestal of radius .5' .5 -o 40.75 74
+
+type='Polar conic projections symmetric about the Prime Meridian. Parallels are segments of concentric circles.'
+
+demo conic 'central projection on cone tangent at 40' 40
+demo simpleconic 'equally spaced parallels, true scale on 20 and 50' 20 50
+demo lambert 'conformal, true scale on 20 and 50' 20 50
+demo albers 'equal-area, true scale on 20 and 50' 20 50
+demo bonne 'equally spaced parallels, equal-area, parallel 40 developed from tangent cone' 40
+
+type='Projections with bilateral symmetry about the Prime Meridian and the equator.'
+
+demo polyconic 'parallels developed from tangent cones, equally spaced along Prime Meridian'
+demo aitoff 'equal-area projection of globe onto 2-to-1 ellipse, based on azequalarea'
+demo lagrange 'conformal, maps whole sphere into a circle'
+demo bicentric 'points plotted at true azimuth from two centers on the equator at longitudes +-40, great circles are straight lines' 40
+demo elliptic 'points are plotted at true distance from two centers on the equator at longitudes +-40' 40
+demo globular 'hemisphere is circle, circular meridians and parallels'
+demo vandergrinten 'sphere is circle, meridians as in globular, circular arc parallels resemble mercator'
+
+type='Doubly periodic conformal projections.'
+
+demo guyou 'W and E hemispheres are square'
+demo square 'World is square with Poles at diagonally opposite corners'
+demo tetra 'map on tetrahedron with edge tangent to Prime Meridian at S Pole, unfolded into equilateral triangle'
+demo hex 'world is hexagon centered on N Pole, N and S hemispheres are equilateral
+triangles'
+
+type='Retroazimuthal projections. Directions to center are true.'
+
+demo mecca 'equally spaced vertical meridians' 21.4 -o 90 -39.8
+demo homing 'distances to Mecca are true' 21.4 -o 90 -39.8
+
+type='Miscellaneous projections.'
+
+demo harrison 'oblique perspective from above the North Pole, 2 earth radii from the earth, looking along the Date Line 40 degrees off vertical' 2 40
+demo trapezoidal 'equally spaced parallels, straight meridians equally spaced along parallels, true scale at 20 and 50 on Prime Meridian' 20 50
+demo lune 'conformal, polar cap above Eq is 60-degree lune' 0 60
+
+type='Maps based on the spheroid'
+
+demo sp_mercator 'equally spaced straight meridians, conformal'
+demo sp_albers 'equal-area, true scale on 20 and 50' 20 50
+} | plot
--- /dev/null
+++ b/rc/bin/membername
@@ -1,0 +1,4 @@
+#!/bin/rc
+tr ' ' '\012' <<eof | sed -e 's/[^(]*\(([^)]*)\).*/\1/' | tr '\012' ' '
+$*
+eof
--- /dev/null
+++ b/rc/bin/mousereset
@@ -1,0 +1,3 @@
+#!/bin/rc
+
+echo reset >/dev/mousectl
--- /dev/null
+++ b/rc/bin/nroff
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec troff -N $*
--- /dev/null
+++ b/rc/bin/patch/applied
@@ -1,0 +1,8 @@
+#!/bin/rc
+
+if(~ $#* 0){
+	echo 'usage: patch/applied patch-name...' >[1=2]
+	exit usage
+}
+
+patch/move applied $*
--- /dev/null
+++ b/rc/bin/patch/apply
@@ -1,0 +1,79 @@
+#!/bin/rc
+
+rfork e
+
+if(! ~ $#* 1){
+	echo 'usage: patch/apply patch-name' >[1=2]
+	exit usage
+}
+
+if(! test -d /n/sources/patch){
+	rfork n
+	9fs sources
+}
+
+if(! test -d /n/sources/patch/$1){
+	echo 'no such patch' /n/sources/patch/$1 >[1=2]
+	exit nopatch
+}
+
+builtin cd /n/sources/patch/$1 || exit nopatch
+if(! patch/okay .){
+	echo 'bad patch: '$status >[1=2]
+	exit badpatch
+}
+
+if(! echo >.tmp || ! rm .tmp){
+	echo no write permission >[1=2]
+	exit 'no write permission'
+}
+
+echo -n merge... >[1=2]
+fn xxx {
+	if(! test -f $1)
+		cp $2 $2.new
+	if not
+		ape/diff3 -m $1 $2.orig $2 >$2.new
+	if(grep -s '^<<<<' $2.new){
+		echo conflicts merging $1';' see `{pwd}^/$2.new >[1=2]
+		
+		touch failed
+	}
+}
+rm -f failed
+cat files | sed 's/^/xxx /' | rc
+if(test -f failed){
+	echo exiting without changes >[1=2]
+	exit failed
+}
+
+echo -n backup... >[1=2]
+fn xxx {
+	# echo cp $1 $2.backup
+	cp $1 $2.backup
+}
+cat files | sed 's/^/xxx /' |rc
+
+echo -n copy... >[1=2]
+fn xxx {
+	# echo cp $2.new $1
+	cp $2.new $1 || touch failed
+}
+cat files | sed 's/^/xxx /' | rc
+
+fn xxx {
+	# echo cp $2.backup $1
+	cp $2.backup $1
+}
+
+if(test -f failed){
+	echo copying failed, restoring backups >[1=2]
+	cat files | sed 's/^/xxx /' | rc
+	exit failed
+}
+
+echo >[1=2]
+
+echo to update sources: >[1=2]
+cat files | awk '{print "	update " $1 }' >[1=2]
+
--- /dev/null
+++ b/rc/bin/patch/create
@@ -1,0 +1,85 @@
+#!/bin/rc
+rfork e
+
+fn xchmod { 
+	chmod $* >[2]/dev/null
+}
+
+if(~ $#* 0 1 2){
+	echo 'usage: patch/create name email file... [< description]' >[1=2]
+	exit usage
+}
+
+if(! echo $1 | grep -s '^[a-z_0-9.\-]+$'){
+	echo 'bad name: [a-z0-9._\-]+ only' >[1=2]
+	exit usage
+}
+if(! echo $2 | grep -s '^(-|[A-Za-z0-9.\-+]+@[A-Za-z0-9.\-+]+)$'){
+	echo 'bad email: [a-z0-9.-+] only; use ''-'' to not leave an email address.' >[1=2]
+	exit usage
+}
+
+if(! test -d /n/sources/patch){
+	rfork n
+	9fs sources
+}
+
+patch=$1
+email=$2
+shift
+shift
+d=/n/sources/patch/$patch
+if(! mkdir $d){
+	echo mkdir $d failed >[1=2]
+	exit mkdir
+}
+if(! ~ $email -){
+	echo $email >$d/email
+}
+
+xchmod o-w $d
+>$d/readme
+>$d/files
+>$d/notes
+for(i in $*){
+	i=`{cleanname -d `{pwd} $i}
+	if(! test -f $i){
+		echo error: cannot find $i >[1=2]
+		rm -rf $d
+		exit oops
+	}
+	short=`{basename $i}
+	uniq=$short
+	n=0
+	while(test -f $d/$uniq){
+		uniq=$short.$n
+		n=`{echo 1+$n | hoc}
+	}
+	cp $i $d/$uniq
+	if(test -f /n/sources/plan9/$i){
+		if(cmp -s /n/sources/plan9/$i $i)
+			echo warning: new file $i does not differ from sources >[1=2]
+		cp /n/sources/plan9/$i $d/$uniq.orig
+	}
+	if not
+		echo warning: new file $i not on sources >[1=2]
+	echo $i $uniq >>$d/files
+}
+@{builtin cd $d && xchmod ug+rw * && xchmod a+r *}
+
+if(~ `{cat /proc/$pid/fd | awk 'NR==2{print $NF}'} */dev/cons && test -w /dev/consctl){
+	>/dev/consctl {
+		echo holdon
+		cat >$d/readme
+	}
+}
+if not
+	cat >$d/readme
+
+if(! test -s $d/readme){
+	echo 'no description given; aborting' >[1=2]
+	rm -rf $d
+	exit oops
+}
+
+echo $d
--- /dev/null
+++ b/rc/bin/patch/diff
@@ -1,0 +1,45 @@
+#!/bin/rc
+# patch/diff [-w] patch-name
+rfork e
+fn usage {
+	echo 'usage: patch/diff [-bmnwz] patch-name' >[1=2]
+	exit usage
+}
+
+dopts=(-c)
+while (! ~ $#* 0 && ~ $1 -*) {
+	switch ($1) {
+	case -[bmnw]
+		dopts=($dopts $1)
+	case -z
+		dopts=()
+	case *
+		usage
+	}
+	shift
+}
+if(! ~ $#* 1)
+	usage
+
+if(! test -d /n/sources/patch){
+	rfork n
+	9fs sources
+}
+
+if(! test -d /n/sources/patch/$1){
+	echo 'no such patch' /n/sources/patch/$1 >[1=2]
+	exit nopatch
+}
+
+builtin cd /n/sources/patch/$1 || exit nopatch
+if(! patch/okay .){
+	echo 'bad patch: '$status >[1=2]
+	exit badpatch
+}
+
+d=/n/sources/patch/$1
+fn xxx {
+	echo $1
+	diff $dopts $2.orig $d/$2 | sed 's/^/	/'
+}
+cat files | sed 's/^/xxx /' | rc
--- /dev/null
+++ b/rc/bin/patch/list
@@ -1,0 +1,54 @@
+#!/bin/rc
+
+rfork e
+if(! test -d /n/sources/patch){
+	rfork n
+	9fs sources
+}
+
+pref=''
+builtin cd /n/sources/patch || {
+	echo 'can''t cd /n/sources/patch' >[2=1]
+	exit no-sources
+}
+
+if(~ $1 applied saved sorry maybe){
+	pref=$1^'/'
+	shift
+}
+if(~ $#* 0)
+	*=(`{
+		if(~ $pref *?*)
+			builtin cd $pref
+		ls -t | grep -v '^(applied|saved|sorry|maybe)$'
+	})
+
+trunc=(sed 5q)
+if(~ $#* 1)
+	trunc=cat
+
+{
+for(i in $*){
+	i=$pref^$i
+	if(test -f $i/origls)
+		cat $i/origls | awk '{$NF="'$i'"; print}'
+	if not
+		ls -ld $i
+	if(patch/okay $i){
+		if(test -r $i/email)
+			echo from `{cat $i/email}
+		cat $i/files | awk '{print "	" $1}'
+		cat $i/readme | sed 's/^/	/' | $trunc
+		if(test -f $i/notes){
+			echo
+			cat $i/notes
+		}
+	}
+	if not
+		echo '	'bad patch: $status >[2=1]
+	echo
+}
+} >/tmp/patchtmp.$pid
+
+cat /tmp/patchtmp.$pid
+rm -f /tmp/patchtmp.$pid
--- /dev/null
+++ b/rc/bin/patch/move
@@ -1,0 +1,31 @@
+#!/bin/rc
+# patch/move target patch-tree... - move patch tree(s) to target dir
+rfork e
+pats=/n/sources/patch
+if(~ $#* 0 1){
+	echo 'usage: patch/move dst patch-name...' >[1=2]
+	exit usage
+}
+
+if(! test -d $pats){
+	rfork n
+	9fs sources
+}
+cd $pats
+
+dst=$1
+shift
+for(src){
+	patbase = `{basename $src}
+	patdest = $dst/$patbase
+	if (~ $dst $src $patbase)
+		echo $0: skipping $src >[1=2]
+	if not if(! test -d $src)
+		echo $0: no such patch $pats/$src >[1=2]
+	if not if(test -d $patdest)
+		echo $0: already have $pats/$patdest >[1=2]
+	if not
+		ls -ldp $src >$src/origls &&
+			mkdir $patdest && dircp $src $patdest && rm -rf $src &&
+			test -s $patdest/email && patch/notify $patdest
+}
--- /dev/null
+++ b/rc/bin/patch/note
@@ -1,0 +1,35 @@
+#!/bin/rc
+
+rfork e
+if(! ~ $#* 1){
+	echo 'usage: patch/note patch-name' >[1=2]
+	exit usage
+}
+
+if(! test -d /n/sources/patch){
+	rfork n
+	9fs sources
+}
+
+if(! test -d /n/sources/patch/$1){
+	echo 'no such patch' /n/sources/patch/$1 >[1=2]
+	exit nopatch
+}
+
+builtin cd /n/sources/patch/$1 || exit nopatch
+if(! patch/okay .){
+	echo 'bad patch: '$status >[1=2]
+	exit badpatch
+}
+
+if(~ `{cat /proc/$pid/fd | awk 'NR==2{print $NF}'} */dev/cons && ~ `{ls -l /dev/consctl | awk '{print $1}'} *w*){
+	>/dev/consctl {
+		echo holdon
+		{echo `{date} `{cat /dev/user}
+		cat |sed 's/^/    /'; echo } >>notes
+	}
+}
+if not
+	{echo `{date} `{cat /dev/user}
+	cat |sed 's/^/    /'; echo } >>notes
+
--- /dev/null
+++ b/rc/bin/patch/notify
@@ -1,0 +1,9 @@
+#!/bin/rc
+# patch/notify
+rfork e
+for(i)
+	# don't flood sys when merely shuffling patches around
+	if (~ $i applied/* saved/* sorry/*) {
+		patch/list $i | mail -s 'patch/list '^$i sys \
+			`{cat /n/sources/patch/$i/email}
+	}
--- /dev/null
+++ b/rc/bin/patch/okay
@@ -1,0 +1,14 @@
+#!/bin/rc
+
+rfork e
+if(! ~ $#* 1){
+	echo usage: patch/okay dir >[1=2]
+	exit usage
+}
+
+i=$1
+if(! test -s $i/files || ! test -s $i/readme)
+	exit 'missing files'
+if(grep -v '^/[_a-zA-Z0-9.\-+/:]+ [_a-zA-Z0-9.\-+:]+$' $i/files)
+	exit 'bad file list' 
+exit 0
--- /dev/null
+++ b/rc/bin/patch/remove
@@ -1,0 +1,19 @@
+#!/bin/rc
+
+rfork e
+if(~ $#* 0){
+	echo 'usage: patch/remove patch-name...' >[1=2]
+	exit usage
+}
+
+if(! test -d /n/sources/patch){
+	rfork n
+	9fs sources
+}
+
+for(i){
+	if(! test -d /n/sources/patch/$i)
+		echo 'no such patch' /n/sources/patch/$i >[1=2]
+	if not
+		rm -rf /n/sources/patch/$i
+}
--- /dev/null
+++ b/rc/bin/patch/save
@@ -1,0 +1,8 @@
+#!/bin/rc
+
+if(~ $#* 0){
+	echo 'usage: patch/save patch-name...' >[1=2]
+	exit usage
+}
+
+patch/move saved $*
--- /dev/null
+++ b/rc/bin/patch/sorry
@@ -1,0 +1,8 @@
+#!/bin/rc
+
+if(~ $#* 0){
+	echo 'usage: patch/sorry patch-name...' >[1=2]
+	exit usage
+}
+
+patch/move sorry $*
--- /dev/null
+++ b/rc/bin/patch/undo
@@ -1,0 +1,35 @@
+#!/bin/rc
+
+rfork e
+if(! ~ $#* 1){
+	echo 'usage: patch/undo patch-name' >[1=2]
+	exit usage
+}
+
+if(! test -d /n/sources/patch){
+	rfork n
+	9fs sources
+}
+
+if(! test -d /n/sources/patch/$1){
+	echo 'no such patch' /n/sources/patch/$1 >[1=2]
+	exit nopatch
+}
+
+d=$1
+builtin cd /n/sources/patch/$1 || exit nopatch
+if(! patch/okay .){
+	echo 'bad patch: '$status >[1=2]
+	exit badpatch
+}
+
+fn xxx {
+	if(cmp $2.new $1){
+		echo cp /n/sources/patch/$d/$2.backup $1
+		cp $2.backup $1
+	}
+	if not
+		echo $1 has changed since patch was applied! >[2=1]
+}
+cat files | sed 's/^/xxx /' |rc
+
--- /dev/null
+++ b/rc/bin/pc/bootfloppy
@@ -1,0 +1,22 @@
+#!/bin/rc
+
+if(~ $#* 0 1) {
+	echo 'usage: bootfloppy /dev/fd0disk plan9.ini [files...]'>[1=2]
+	exit usage
+}
+
+if(! test -f $2) {
+	echo $2 does not exist >[1=2]
+	exit noplan9.ini
+}
+
+disk=$1
+ini=$2
+shift 
+shift
+
+mkdir /tmp/bootfloppy.$pid
+cp $ini /tmp/bootfloppy.$pid/plan9.ini
+dd -bs 512 -count 1 < /dev/zero >/tmp/bootfloppy.$pid/plan9.nvr
+disk/format -b /386/pbs -f -d $disk /386/9load /tmp/bootfloppy.$pid/* $*
+rm -rf /tmp/bootfloppy.$pid
--- /dev/null
+++ b/rc/bin/pc/bootplan9
@@ -1,0 +1,72 @@
+#!/bin/rc
+
+rfork e
+
+. /rc/bin/pc/defs
+
+if(! ~ $#* 1) {
+	echo 'usage: bootplan9 /dev/sdC0' >[1=2]
+	echo 'sets active the plan 9 partition on the named disk.' >[1=2]
+	exit usage
+}
+
+disk=$1
+
+fn x {
+	if(! test -f $disk/$1) {
+		echo 'could not find '$disk/$1
+		exit disk
+	}
+}
+
+x plan9
+x data
+x ctl
+
+diskbase=`{basename `{cleanname $disk}}
+
+first=`{ls -p '#S' | sed 1q}
+if(! ~ $first $diskbase) {
+	echo 'warning: The plan 9 partition is not on the boot disk,' >[1=2]
+	echo 'so making it the active partition will have no effect.' >[1=2]
+}
+
+p9offset=`{disk/fdisk -p $disk/data |grep '^part plan9 ' | awk '{print $4}'}
+if(! ~ $#p9offset 1) {
+	echo 'could not find plan 9 partition.' >[1=2]
+	echo 'cannot happen' >[1=2]
+	exit bad
+}
+
+if(test $p9offset -gt 4128705) {	# 65536 * 63
+	echo  >[1=2]
+	echo 'Your Plan 9 partition is more than 2GB into your disk,' >[1=2]
+	echo 'and the master boot records used by most operating systems' >[1=2]
+	echo 'cannot access it (and thus cannot boot it).' >[1=2]
+	echo >[1=2]
+	echo 'Would you like to install a master boot record' >[1=2]
+	echo 'that will be able to access partitions more than 2GB into the disk?' >[1=2]
+	echo >[1=2]
+	prompt 'Install a new mbr' y n 
+	switch($rd) {
+	case n
+		echo >[1=2]
+		echo 'Not setting Plan 9 partition active, then.' >[1=2]
+		echo >[1=2]
+		exit bad
+	case y
+		disk/mbr -m /386/mbr $disk/data
+	}
+}
+
+p9part=`{disk/fdisk $disk/data >[2]/dev/null </dev/null | 
+		grep PLAN9 | sed 1q | sed 's/ *(p.) .*/\1/'}
+if(~ $#p9part 1) {
+	{ echo 'A '^$p9part; echo w } | disk/fdisk $disk/data >[2]/dev/null >/dev/null
+}
+if not {
+	echo 'Could not find Plan 9 partition.'
+	exit notdone
+}
+
+exit
--- /dev/null
+++ b/rc/bin/pc/bootwin9x
@@ -1,0 +1,115 @@
+#!/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.' >[1=2]
+	exit
+}
+
+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.' >[1=2]
+		exit
+	}
+
+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.' >[1=2]
+		exit
+	}
+
+if(! test -d /n/c:/plan9 && ! mkdir /n/c:/plan9) {
+	echo 'Could not create directory /n/c:/plan9.' >[1=2]
+	exit
+}
+
+if(! cp /386/^(9load ld.com) /386/9pcdisk /n/c:/plan9) {
+	echo 'Could not copy Plan 9 boot files into /n/c:/plan9.' >[1=2]
+	exit
+}
+
+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.' >[1=2]
+	echo 'Not changing them; refer to Plan 9 install documentation' >[1=2]
+	echo 'to configure manually.' >[1=2]
+	exit
+}
+
+if(! grep -si '\[menu\]' /n/c:/config.sys) {
+	{
+		echo 1
+		echo i
+		echo '[menu]
'
+		echo 'menuitem=windows, Windows
'
+		echo 'menudefault=windows
'
+		echo '
'
+		echo '[common]
'
+		echo '
'
+		echo '[windows]
'
+		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
'
+	echo .
+	echo '$'
+	echo a
+	echo '
'
+	echo '[plan9]
'
+	echo '
'
+	echo .
+	echo w
+	echo q
+} | ed /n/c:/config.sys >/dev/null >[2]/dev/null
+
+{
+	echo 1
+	echo i
+	echo '@echo off
'
+	echo 'if %config%==plan9 goto plan9
'
+	echo 'goto notplan9
'
+	echo ':plan9
'
+	echo 'plan9\ld '^$dosdisk^'!dos!plan9/9load
'
+	echo ':notplan9
'
+	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]
'
+			echo 'Logo=0
'
+			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
+}
+
+exit
--- /dev/null
+++ b/rc/bin/pc/bootwinnt
@@ -1,0 +1,53 @@
+#!/bin/rc
+
+disk=`{ls /dev/sd??/plan9 >[2]/dev/null | sed 1q | sed 's!.*/(.*)/plan9!\1!'}
+if(! ~ $#disk 1) {
+	echo 'No plan 9 disk found' >[1=2]
+	exit
+}
+
+if(! c: || ! test -f /n/c:/boot.ini) {
+	echo 'Could not find NT''s boot.ini on the first FAT disk.' >[1=2]
+	exit
+}
+
+if(test -f /n/c:/boot.p9) {
+	echo 'A Plan 9 backup already exists; will not edit boot.ini again.' >[1=2]
+	exit
+}
+
+if(! cp /n/c:/boot.ini /n/c:/boot.p9) {
+	echo 'Could not back up boot.ini; will not continue.' >[1=2]
+	exit
+}
+
+chmod +w /n/c:/boot.ini
+
+if(! grep -si '\[operating systems\]' /n/c:/boot.ini) {
+	echo 'Could not parse boot.ini.' >[1=2]
+	exit
+}
+
+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.' >[1=2]
+		exit
+	}
+}
+
+if not {
+	p9file='c:\bootsect.p9'
+	echo 'c:\bootsect.p9 = "Plan 9 from Bell Labs"
' >>/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.' >[1=2]
+	exit
+}
+
+echo 'Error copying Plan 9 boot sector to file.'
+exit
--- /dev/null
+++ b/rc/bin/pc/defs
@@ -1,0 +1,72 @@
+nl='
+'
+tab='	'
+
+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^']'
+	pr=$pr^': '
+
+
+	okay=no
+	while(~ $okay no) {
+# whatis opts
+		echo -n $pr >[1=2]
+		ifs='' {rd=`{read}}
+		if(~ $#rd 0)
+			exit notdone
+		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
+}
+
--- /dev/null
+++ b/rc/bin/pc/isfat
@@ -1,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
+
--- /dev/null
+++ b/rc/bin/pc/personalize
@@ -1,0 +1,7 @@
+#!/bin/rc
+
+switch($#*){
+case 1
+	user=$1
+}
+disk/mkfs -s /n/emelie /sys/lib/sysconfig/proto/usrproto
--- /dev/null
+++ b/rc/bin/pc/setup.9fat
@@ -1,0 +1,33 @@
+#!/bin/rc
+
+rfork e
+if(! ~ $#* 2) {
+	echo 'usage: setup.9fat /dev/sdC0/9fat plan9.ini' >[1=2]
+	exit usage
+}
+
+. /rc/bin/pc/defs
+fat=$1
+ini=$2
+if(! test -f  $fat) {
+	echo fat partition not found >[1=2]
+	exit fat
+}
+if(! test -f $ini) {
+	echo plan9.ini not found >[1=2]
+	exit ini
+}
+
+if(pc/isfat $fat) {
+	echo 'Already a FAT partition in '^$fat^'; ream it?'
+	prompt 'ream 9fat' y n
+	switch($rd) {
+	case n
+		exit
+	}
+}
+
+disk/format -r 2 -d -b /386/pbs $fat /386/9load /386/9pcdisk
+mount -c /srv/dos /n/9fat $fat
+cp $ini /n/9fat/plan9.ini
+unmount /n/9fat
--- /dev/null
+++ b/rc/bin/pc/setup.disk
@@ -1,0 +1,37 @@
+#!/bin/rc
+
+rfork e
+
+if(! ~ $#* 2) {
+	echo 'usage: setup.disk /dev/sdC0 plan9.ini' >[1=2]
+	exit usage
+}
+
+disk=$1
+ini=$2
+if(! test -d  $disk) {
+	echo disk directory not found >[1=2]
+	exit fat
+}
+if(! test -f $ini) {
+	echo plan9.ini not found >[1=2]
+	exit ini
+}
+
+
+disk/fdisk -wa $disk/data
+if(! test -f $disk/plan9) {
+	echo could not create plan 9 partition >[1=2]
+	exit noplan9
+}
+
+disk/prep -cwa $disk/plan9
+if(! test -f $disk/fs) {
+	echo did not create fs partition '(weird)' >[1=2]
+	exit nofs
+}
+
+disk/kfs -rb4096 -f $disk/fs
+pc/setup.9fat $disk/9fat $ini
+pc/update
+pc/personalize
--- /dev/null
+++ b/rc/bin/pc/update
@@ -1,0 +1,20 @@
+#!/bin/rc
+
+if(~ $#fileserver 0) {
+	echo set '$fileserver' >[1=2]	
+	exit no
+}
+if(~ $fileserver kfs) {
+	echo pc/update shouldn''''t be run from kfs >[1=2]
+	echo 'run:' >[1=2]
+	echo '	fileserver=network-server pc/update' >[1=2]
+	exit no
+}
+flag e +
+echo updating files
+9fs $fileserver
+disk/mkfs -s /n/$fileserver /n/$fileserver/sys/lib/sysconfig/proto/portproto
+9fat:
+cp /n/$fileserver/386/9pcdisk /n/9fat/9pcdisk
+cp /n/$fileserver/386/9load /n/9fat/9load
+unmount /n/9fat
--- /dev/null
+++ b/rc/bin/pci
@@ -1,0 +1,95 @@
+#!/bin/rc
+# pci [-bv] - dump pci configuration
+rfork e
+fn verbose {
+	if (! test -f /lib/pci)
+		echo $0: no /lib/pci >[1=2]
+	awk '
+
+	function lower(s) {
+		gsub(/A/, "a", s)
+		gsub(/B/, "b", s)
+		gsub(/C/, "c", s)
+		gsub(/D/, "d", s)
+		gsub(/E/, "e", s)
+		gsub(/F/, "f", s)
+		return s
+	}
+	BEGIN{
+		file="/lib/pci"
+		FS="\t"
+		while(getline <file > 0){
+			if(/^;/) continue
+			if(/^[0-9a-fA-F]/){
+				vid=lower($1)
+				vendor[vid] = $2
+			}
+			if(/^	[0-9a-fA-F]/){
+				did=lower($2)
+				id[vid "/" did] = $3
+			}
+		}
+		FS = " "
+	}
+
+	{
+		print $0
+		vid = $4
+		sub(/\/.*/, "", vid)
+		if(vid in vendor){
+			s = vendor[vid]
+			if($4 in id)
+				s = s " " id[$4]
+			print "\t" s
+		}
+	}
+'
+}
+fn usage {
+	echo usage: $1 '[-bv]' >[1=2]
+	exit usage
+}
+
+filter=cat
+bridges=yes
+done=0
+while (~ $done 0 && ! ~ $#* 0 && ~ $1 -*) {
+	if (~ $1 -*b*)
+		bridges=no
+	if (~ $1 -*v*)
+		filter=verbose
+	switch ($1) {
+	case --
+		done = 1		# no break in rc, alas
+	case -*[~bv]*
+		usage $0
+	}
+	shift
+}
+if (! ~ $#* 0)
+	usage $0
+
+builtin cd '#$/pci' && grep . *ctl | {
+	if (~ $bridges no)
+		sed /:06/d
+	if not
+		cat
+	} |
+	sed '
+	s/ctl:/:	/
+	t noop
+: noop
+	s/:	01/:	disk 01/
+	s/:	02/:	net  02/
+	s/:	03/:	vid  03/
+	s/:	04/:	aud  04/
+	s/:	05/:	mem  05/
+	s/:	06/:	brg  06/
+	s/:	07/:	ser  07/
+	s/:	0c\.03/:	usb  0c.03/
+	s/:	0c\.05/:	smb  0c.05/
+	s/:	0d/:	rad  0d/
+	s/:	10/:	cryp 10/
+	t
+	s/	/	---  /
+' | $filter
--- /dev/null
+++ b/rc/bin/pdf2ps
@@ -1,0 +1,53 @@
+#!/bin/rc
+# pdf2ps [gs-options] [input.pdf] [output.ps] - generate PS from PDF
+rfork e
+
+fn cleanup { }
+fn usage {
+	echo 'usage: pdf2ps [gs-options] [input.pdf] [output.ps]' >[1=2]
+	exit usage
+}
+
+lang=(-'dLanguageLevel=2')
+opt=()
+while(! ~ $#* 0 && ~ $1 -* && ! ~ $1 - --){
+	if(~ $1 '-dLanguageLevel='*)
+		lang=()
+	opt=($opt $1)
+	shift
+}
+if(~ $1 --)
+	shift
+
+switch($#*){
+case 0
+	fin=-
+	fout=-
+case 1
+	fin=$1
+	fout=-
+case 2
+	fin=$1
+	fout=$2
+case *
+	usage
+}
+
+if(~ $fin -){
+	# fin=/tmp/pdf2ps.$pid.^`{date -n}
+	# fn cleanup { rm -f $fin }
+	# cat >$tmp
+	fin=/fd/0
+}
+if(~ $fout -)
+	fout=/fd/1
+
+# Doing an inital `save' helps keep fonts from being flushed between
+# pages.  We have to include the options twice because -I only takes
+# effect if it appears before other options.
+
+gs $opt -dSAFER -dNOPAUSE -dBATCH -q -s'DEVICE=pswrite' \
+	$opt $lang \
+	-s'OutputFile='$fout -c save pop -f $fin
+
+cleanup
--- /dev/null
+++ b/rc/bin/printfont
@@ -1,0 +1,105 @@
+#!/bin/rc
+# Formatted dump of encoded characters in one or more PostScript fonts.
+# Arguments should be PostScript font names or the word all, which dumps
+# all ROM and disk based fonts.
+#
+
+POSTLIB=/sys/lib/postscript/prologues
+PROLOGUE=$POSTLIB/printfont.ps
+
+OPTIONS=''
+COPYFILE=''
+MODE=portrait
+FONTENCODING=Default
+
+NONCONFORMING='%!PS'
+ENDPROLOG='%%EndProlog'
+BEGINSETUP='%%BeginSetup'
+ENDSETUP='%%EndSetup'
+TRAILER='%%Trailer'
+
+SETUP=setup
+
+while (! ~ $#* 0 && ~ $1 -*) {
+	switch ($1) {
+	case -a;  shift; OPTIONS=$OPTIONS' /axescount $1 def'
+	case -a*; OPTIONS=$OPTIONS' /axescount '`{echo $1 | sed s/-a//}' def'
+
+	case -b;  shift; OPTIONS=$OPTIONS' /radix '$1' def'
+	case -b*; OPTIONS=$OPTIONS' /radix '`{echo $1 | sed s/-b//}' def'
+
+	case -c;  shift; OPTIONS=$OPTIONS' /#copies '$1' store'
+	case -c*; OPTIONS=$OPTIONS' /#copies '`{echo $1 | sed s/-c//}' store'
+
+	case -f;  shift; OPTIONS=$OPTIONS' /labelfont /'$1' def'
+	case -f*; OPTIONS=$OPTIONS' /labelfont /'`{echo $1 | sed s/-f//}' def'
+
+	case -g;  shift; OPTIONS=$OPTIONS' /graynotdef '$1' def'
+	case -g*; OPTIONS=$OPTIONS' /graynotdef '`{echo $1 | sed s/-g//}' def'
+
+	case -p;  shift; MODE=$1
+	case -p*; MODE=`{echo $1 | sed s/-p//}
+
+	case -q;  OPTIONS=$OPTIONS' /longnames false def /charwidth false def'
+
+	case -m;  shift; OPTIONS=$OPTIONS' /magnification '$1' def'
+	case -m*; OPTIONS=$OPTIONS' /magnification '`{echo $1 | sed s/-m//}' def'
+
+	case -v;  OPTIONS=$OPTIONS' /longnames true def /charwidth true def'
+
+	case -w;  shift; OPTIONS=$OPTIONS' /linewidth '$1' def'
+	case -w*; OPTIONS=$OPTIONS' /linewidth '`{echo $1 | sed s/-w//}' def'
+
+	case -x;  shift; OPTIONS=$OPTIONS' /xoffset '$1' def'
+	case -x*; OPTIONS=$OPTIONS' /xoffset '`{echo $1 | sed s/-x//}' def'
+
+	case -y;  shift; OPTIONS=$OPTIONS' /yoffset '$1' def'
+	case -y*; OPTIONS=$OPTIONS' /yoffset '`{echo $1 | sed s/-y//}' def'
+
+	case -z;  shift; OPTIONS=$OPTIONS' /zerocell '$1' def'
+	case -z*; OPTIONS=$OPTIONS' /zerocell '`{echo $1 | sed s/-z//}' def'
+
+	case -C;  shift; COPYFILE=$COPYFILE' '$1
+	case -C*; COPYFILE=$COPYFILE' '`{echo $1 | sed s/-C//}
+
+	case -E;  shift; FONTENCODING=$1
+	case -E*; FONTENCODING=`{echo $1 | sed s/-E//}
+
+	case -L;  shift; PROLOGUE=$1
+	case -L*; PROLOGUE=`{echo $1 | sed s/-L//}
+
+	case -*;  echo $0:' illegal option '$1 >[1=2]; exit 1
+	}
+	shift
+}
+
+switch ($MODE) {
+case l*; OPTIONS=$OPTIONS' /landscape true def'
+case *;	OPTIONS=$OPTIONS' /landscape false def'
+}
+
+echo $NONCONFORMING
+cat $PROLOGUE
+echo $ENDPROLOG
+echo $BEGINSETUP
+if (~ $#COPYFILE 0 || ~ $COPYFILE '') COPYFILE=/dev/null
+cat $COPYFILE
+echo $OPTIONS
+
+switch ($FONTENCODING) {
+case /*; cat $FONTENCODING
+case ?*; cat $POSTLIB^/$FONTENCODING^.enc >[2]/dev/null
+}
+
+echo $SETUP
+echo $ENDSETUP
+
+for (i) {
+	switch ($i) {
+	case all; echo AllFonts
+	case /*;  echo $i' PrintFont'
+	case ?*;  echo /$i' PrintFont'
+	}
+}
+
+echo $TRAILER
--- /dev/null
+++ b/rc/bin/ps2gif
@@ -1,0 +1,2 @@
+#!/bin/rc
+cat $1|/bin/gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps| crop | togif
--- /dev/null
+++ b/rc/bin/ps2pdf
@@ -1,0 +1,43 @@
+#!/bin/rc
+# ps2pdf - convert PostScript to PDF
+rfork e
+
+fn usage {
+	echo 'usage: ps2pdf [gs-options] [input.ps [output.pdf]]' >[1=2]
+	exit usage
+}
+
+# gs's pdfwrite sometimes emits bad pdf at level 1.2,
+# but 1.4 seems to work fine.
+compat=(-'dCompatibilityLevel=1.2')
+opt=()
+while(! ~ $#* 0 && ~ $1 -* && ! ~ $1 - --){
+	if(~ $1 '-dCompatibilityLevel='*)
+		compat=()
+	opt=($opt $1)
+	shift
+}
+if(~ $1 --)
+	shift
+
+switch($#*){
+case 0
+	fin='-'
+	fout='-'
+case 1
+	fin=$1
+	fout='-'
+case 2
+	fin=$1
+	fout=$2
+case *
+	usage
+}
+
+# We have to include the options twice because -I only takes effect
+# if it appears before other options.
+
+gscmd=( gs $opt -dSAFER -dNOPAUSE -dBATCH -q -s'DEVICE=pdfwrite' \
+	$opt $compat \
+	-s'OutputFile='$fout -c .setpdfwrite -f $fin)
+exec $gscmd
--- /dev/null
+++ b/rc/bin/psfax
@@ -1,0 +1,90 @@
+#!/bin/rc
+view=no
+stdin=no
+
+switch($1){
+case -v
+	view=yes
+	shift
+}
+
+switch($#*){
+case 0 1
+	echo usage: $0 telephone-number recipient [files]
+	exit 0
+case 2
+	stdin=yes
+}
+
+telno=$1
+shift
+
+recip=$1
+shift
+
+script=/tmp/fax.$pid
+header=/tmp/faxh.$pid
+user=`{cat /dev/user}
+tmp=/tmp/page.$pid
+tmpin=/tmp/page.in.$pid
+tel=`{grep '\) '$user /lib/tel}
+myname=`{echo $tel | sed 's/ \(.*//'}
+ext=`{echo $tel | sed 's/.*\) [^ ]* [^ ]* ([^ ]*).*/\1/'}
+
+fn sigint{
+	#rm -f $tmp.* $tmpin.* $script $header $header.*
+	exit interrupt
+	
+}
+
+# gs insists on reading its standard input, so we read quit.ps to cut it off.
+switch($stdin){
+case yes
+	cat > $tmpin
+	gs -dSAFER '-sDEVICE=dfaxlow' '-sOUTPUTFILE='$tmp'.%.3d' -dNOPAUSE -dQUIET $tmpin quit.ps
+case *
+	gs -dSAFER '-sDEVICE=dfaxlow' '-sOUTPUTFILE='$tmp'.%.3d' -dNOPAUSE -dQUIET $* quit.ps
+}
+
+pages=`{echo $tmp.*|wc -w}
+
+# use delimiters that are unlikely to be supplied in arguments
+echo -n s∮FAXddd∮	 >$script
+echo -n `{date}		>>$script
+echo ∮			>>$script
+echo -n s∮FAXFFF∮	>>$script
+echo -n $myname 	>>$script
+echo ∮			>>$script
+echo -n s∮FAXEEE∮	>>$script
+echo -n $user 		>>$script
+echo ∮			>>$script
+echo -n s∮FAXVVV∮	>>$script
+echo -n $ext 		>>$script
+echo ∮			>>$script
+echo -n s∮FAXTTT∮	>>$script
+echo -n $recip 		>>$script
+echo ∮			>>$script
+echo -n s∮FAXfff∮	>>$script
+echo -n $telno 		>>$script
+echo ∮			>>$script
+echo -n s∮FAXPPP∮	>>$script
+echo -n $pages 		>>$script
+echo ∮			>>$script
+sed -f $script /sys/lib/fax/h.ps > $header
+
+gs -dSAFER '-sDEVICE=dfaxlow' '-sOUTPUTFILE='$header'.%.3d' -dNOPAUSE -dQUIET $header quit.ps
+
+files=()
+for(i in $header.* $tmp.*){
+	files=($files -f $i)
+}
+
+switch($view){
+case no
+	upas/qer $files /mail/faxoutqueue fax $user $telno < /dev/null
+	rx fax /sys/lib/fax/faxgoose
+case yes
+	page $header.* $tmp.*
+}
+
+#rm -f $tmp.* $header $script $header.* $tmpin
--- /dev/null
+++ b/rc/bin/psu
@@ -1,0 +1,20 @@
+#!/bin/rc
+# psu - ps for just one user
+rfork e
+flags=()
+while (! ~ $#* 0 && ~ $1 -*) {
+	flags = ($flags $1)
+	shift
+}
+
+# sed -n p rather than grep so that we get buffered writes.
+# this is a huge difference in drawterm.
+switch($#*){
+case 0
+	ps $flags | sed -n '/^'$user' /p'
+case 1
+	ps $flags | sed -n '/^'$1' /p'
+case *
+	echo Usage: psu '[ps-flags] [ user ]' >[1=2]
+	exit usage
+}
--- /dev/null
+++ b/rc/bin/readweb
@@ -1,0 +1,10 @@
+#!/bin/rc
+# start abaco and its prerequisites
+rfork n
+
+# outside && bind /net.alt /net
+
+webfs
+webcookies
+echo useragent netscape 1.0 >/mnt/web/ctl
+exec /$cputype/bin/abaco $*
--- /dev/null
+++ b/rc/bin/reboot
@@ -1,0 +1,2 @@
+#!/bin/rc
+echo reboot $* > /dev/reboot
--- /dev/null
+++ b/rc/bin/replica/changes
@@ -1,0 +1,15 @@
+#!/bin/rc
+
+rfork en
+
+fn usage {
+	echo 'usage: replica/changes replica-name [paths]' >[1=2]
+	exit usage
+}
+
+. /rc/bin/replica/defs $*
+
+need clientdb clientroot clientproto
+
+must clientmount
+exec replica/updatedb -p $clientproto -l -r $clientroot $clientexclude $clientdb $paths
--- /dev/null
+++ b/rc/bin/replica/defs
@@ -1,0 +1,55 @@
+tmp=()
+
+fn fatal {
+	if(! ~ $#tmp 0)
+		rm -f $tmp
+	echo $* >[1=2]
+	exit $"*
+}
+
+fn must {
+	$* || fatal $"*^': '^$status
+}
+
+fn need {
+	for(i)
+		if(~ $$i UNCONFIGURED)
+			fatal $name^' does not set $'^$i
+}
+
+opt=()
+while(! ~ $#* 0 && ~ $1 -*){
+	if(~ $1 -s -c){	# take one argument 
+		opt=($opt $1)
+		shift
+	}
+	opt=($opt $1)
+	shift
+}
+if(~ $1 --)
+	shift
+if(~ $#* 0)
+	usage
+name=$1
+shift
+paths=($*)
+
+if(! ~ $name /* ./* ../*)
+	name=$home/lib/replica/$name
+
+if(! test -x $name)
+	fatal no such replica $name
+
+cfgopt=()
+applyopt=()
+fn servermount { status='' }
+fn clientmount { status='' }
+fn serverupdate { status='' }
+for (i in clientroot clientproto clientdb clientexclude serverroot serverlog serverproto)
+	$i=UNCONFIGURED
+. $name
+
+if(! ~ $#serverexclude 0)
+	serverexclude=-x^$serverexclude
+if(! ~ $#clientexclude 0)
+	clientexclude=-x^$clientexclude
--- /dev/null
+++ b/rc/bin/replica/pull
@@ -1,0 +1,58 @@
+#!/bin/rc
+
+rfork en
+
+fn usage {
+	echo 'usage: replica/pull [-nv] [-c name] [-s name] replica-name [paths]' >[1=2]
+	exit usage
+}
+
+. /rc/bin/replica/defs $*
+
+need clientlog serverlog clientdb clientroot serverroot
+
+# mount the server file system, update the log
+must servermount
+must serverupdate
+must clientmount
+
+# download the log
+n=`{ls -l $clientlog >[2]/dev/null |awk '{print $6}'}
+s=`{ls -l $serverlog >[2]/dev/null |awk '{print $6}'}
+if(~ $n 0 || ~ $#n 0 || test $s -lt $n){
+	if(test -e $clientlog) must rm $clientlog
+	must fcp $serverlog $clientlog
+}
+if not{
+	m=`{echo $n-1024 | hoc}
+	if(~ $m -*)
+		m=0
+	cmp -s $serverlog $clientlog $m $m
+	x=$status
+	switch($x){
+	case *': EOF'
+		must tail +^$n^c $serverlog >>$clientlog
+	case *': differ'
+		must rm $clientlog
+		must fcp $serverlog $clientlog
+	case ''
+		;
+	case *
+		fatal cmp: $x
+	}
+}
+
+# normally we'd do this after applylog, but we want
+# applylog to be the last thing in this script, so we'll
+# do it here instead, compacting changes from the
+# _last_ applylog.
+
+ndb=`{echo $clientdb | sed 's;(.*)/(.*);\1/_\2;'}
+must replica/compactdb $clientdb >$ndb
+mv $ndb $clientdb
+
+# mount the client file system, apply the log
+# this is the last thing in the script and is execed so that
+# if replica/pull is overwritten nothing bad will happen.
+# applylog takes care of itself as far as protection against being overwritten.
+exec replica/applylog $opt $applyopt $clientdb $clientroot $serverroot $paths <$clientlog
--- /dev/null
+++ b/rc/bin/replica/push
@@ -1,0 +1,18 @@
+#!/bin/rc
+
+rfork en
+
+fn usage {
+	echo 'usage: replica/push [-nv] replica-name [paths]' >[1=2]
+	exit usage
+}
+
+. /rc/bin/replica/defs $*
+
+need clientproto clientexclude cfgopt clientdb clientroot serverroot paths
+
+must servermount
+must clientmount
+exec replica/applychanges -p $clientproto $clientexclude $opt $cfgopt \
+	$clientdb $clientroot $serverroot $paths
+
--- /dev/null
+++ b/rc/bin/replica/scan
@@ -1,0 +1,18 @@
+#!/bin/rc
+
+rfork en
+
+fn usage {
+	echo 'usage: replica/scan replica-name [paths]' >[1=2]
+	exit usage
+}
+
+. /rc/bin/replica/defs $*
+
+need serverroot serverexclude serverproto serverdb serverlog 
+
+must servermount
+replica/updatedb -r^$serverroot $serverexclude -p^$serverproto $serverdb >>$serverlog
+ndb=`{echo $serverdb | sed 's;(.*)/(.*);\1/n\2;'}
+odb=`{echo $serverdb | sed 's;(.*)/(.*);\1/_\2;'}
+replica/compactdb $serverdb >$ndb && mv $serverdb $odb && mv $ndb $serverdb
--- /dev/null
+++ b/rc/bin/replica/setupdirs
@@ -1,0 +1,34 @@
+#!/bin/rc
+
+rfork en
+
+if(! ~ $#libreplica 1)
+	libreplica=$home/lib/replica
+
+fn usage {
+	echo 'usage: replica/setupdirs' >[1=2]
+	exit usage
+}
+
+fn fatal {
+	echo $* >[1=2]
+	exit $"*
+}
+
+fn must {
+	$* || fatal $"*^': '^$status
+}
+
+if(! ~ $#* 0)
+	usage
+
+for (i in \
+	$libreplica\
+	$libreplica/db\
+	$libreplica/db/client\
+	$libreplica/db/server\
+	$libreplica/log\
+	$libreplica/cfg)
+	if(! test -d $i)
+		must mkdir -p $i
+
--- /dev/null
+++ b/rc/bin/rwd
@@ -1,0 +1,23 @@
+#!/bin/rc
+
+rfork e
+if(! ~ $#* 1){
+	echo 'usage: remotesys=xxx rwd dir' >[1=2]
+	exit usage
+}
+
+suf=''
+if(~ $#remotesys 1)
+	suf = @$remotesys
+if not
+	remotesys=''
+
+echo -n $1 >/dev/wdir
+b=`{basename $1}
+if(! ~ $#b 1)
+	b=/
+echo -n $b^$suf >/dev/label
+if(test -f /dev/acme/ctl){
+	echo name $1/-$remotesys >/dev/acme/ctl
+	echo dumpdir $1 >/dev/acme/ctl
+}
--- /dev/null
+++ b/rc/bin/seemail
@@ -1,0 +1,4 @@
+#!/bin/rc
+
+if(~ $1 -i) exec faces -hi
+if not exec faces -h
--- /dev/null
+++ b/rc/bin/service.auth/authsrv.il566
@@ -1,0 +1,2 @@
+#!/bin/rc
+/bin/auth/authsrv -d $3
--- /dev/null
+++ b/rc/bin/service.auth/authsrv.tcp567
@@ -1,0 +1,2 @@
+#!/bin/rc
+/bin/auth/authsrv -d $3
--- /dev/null
+++ b/rc/bin/service/!il17007
@@ -1,0 +1,4 @@
+#!/bin/rc
+
+netdir=`{echo $3 | sed 's;/[0-9]+$;!*!0;'}
+exec exportfs -a -A $netdir
--- /dev/null
+++ b/rc/bin/service/!il17008
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec /bin/exportfs -s
--- /dev/null
+++ b/rc/bin/service/!il17031
@@ -1,0 +1,3 @@
+#!/bin/rc
+exec ramfs -i
+
--- /dev/null
+++ b/rc/bin/service/!tcp515
@@ -1,0 +1,5 @@
+#!/bin/rc
+
+if(/sys/lib/lp/bin/lpscratch){
+	exec /$cputype/bin/aux/lpdaemon >>[2] `{cat /env/LPSCRATCH}^/log/lpdaemonl
+}
--- /dev/null
+++ b/rc/bin/service/!tcp564
@@ -1,0 +1,3 @@
+#!/bin/rc
+mount '#s/boot' /root $rootspec
+exec /bin/exportfs -r /root
--- /dev/null
+++ b/rc/bin/service/startcifs
@@ -1,0 +1,14 @@
+#!/bin/rc
+# startcifs - (re)start cifs (smb) server
+echo killing old cifs server
+Kill aquarela | rc
+
+echo starting new cifs server
+@ {
+	echo 'srv -A local' >>/srv/fscons
+	sleep 2
+	chmod 666 /srv/local
+	9fs local
+	cd /sys/log
+	aquarela
+} &
--- /dev/null
+++ b/rc/bin/service/startnfs
@@ -1,0 +1,9 @@
+#!/bin/rc
+9fs nslocum
+9fs alice
+Kill portmapper|rc
+Kill nfsserver|rc
+rm -f /srv/nfsserver.chat /srv/portmapper.chat
+aux/nfsserver -a il!emelie -a il!choline -c /lib/ndb/nfs >>[2] /sys/log/nfsserver
+aux/portmapper >>[2] /sys/log/portmapper
+aux/portmapper -t >>[2] /sys/log/portmapper
--- /dev/null
+++ b/rc/bin/service/tcp110
@@ -1,0 +1,3 @@
+#!/bin/rc
+
+exec /$cputype/bin/upas/pop3 -t /sys/lib/ssl/cert.pem >>[2] /sys/log/pop3
--- /dev/null
+++ b/rc/bin/service/tcp113
@@ -1,0 +1,4 @@
+#!/bin/rc
+x=`{read|sed 's/
//'}
+y=`{echo -n $x | sed 's/ //g'}
+echo $y^:USERID:UNIX:none
--- /dev/null
+++ b/rc/bin/service/tcp143
@@ -1,0 +1,3 @@
+#!/bin/rc
+
+exec /bin/ip/imap4d >[2]/sys/log/imap4d
--- /dev/null
+++ b/rc/bin/service/tcp17005
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec /bin/ocpu -f -R
--- /dev/null
+++ b/rc/bin/service/tcp17006
@@ -1,0 +1,1 @@
+#!/bin/ocpu -N
--- /dev/null
+++ b/rc/bin/service/tcp17007
@@ -1,0 +1,3 @@
+#!/bin/rc
+netdir=`{echo $3 | sed 's;/[0-9]+$;!*!0;'}
+exec /bin/exportfs -a -A $netdir
--- /dev/null
+++ b/rc/bin/service/tcp17009
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec /bin/ip/rexexec
--- /dev/null
+++ b/rc/bin/service/tcp17010
@@ -1,0 +1,1 @@
+#!/bin/cpu -R
--- /dev/null
+++ b/rc/bin/service/tcp17013
@@ -1,0 +1,1 @@
+#!/bin/cpu -O
--- /dev/null
+++ b/rc/bin/service/tcp19
@@ -1,0 +1,2 @@
+#!/bin/rc
+/bin/aux/write 4096
--- /dev/null
+++ b/rc/bin/service/tcp21
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec /bin/ip/ftpd $*
--- /dev/null
+++ b/rc/bin/service/tcp22
@@ -1,0 +1,3 @@
+#!/bin/rc
+
+exec /bin/aux/sshserve -A 'tis password' `{cat $3/remote} >>[2]/sys/log/ssh
--- /dev/null
+++ b/rc/bin/service/tcp23
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec /bin/ip/telnetd $*
--- /dev/null
+++ b/rc/bin/service/tcp25
@@ -1,0 +1,5 @@
+#!/bin/rc
+#smtp serv net incalldir user
+
+user=`{cat /dev/user}
+exec upas/smtpd -n $3
--- /dev/null
+++ b/rc/bin/service/tcp513
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec /bin/ip/rlogind
--- /dev/null
+++ b/rc/bin/service/tcp53
@@ -1,0 +1,2 @@
+#!/bin/rc
+/bin/ndb/dnstcp $3
--- /dev/null
+++ b/rc/bin/service/tcp565
@@ -1,0 +1,7 @@
+#!/bin/rc
+#whoami service net dir
+loc=`{cat $3/local|sed 's/!.*//'}
+rem=`{cat $3/remote}
+port=`{echo $rem|sed 's/^[^!]*!//'}
+rem=`{echo $rem|sed 's/!.*//'}
+echo i am $loc sysname $sysname you are $rem port $port
--- /dev/null
+++ b/rc/bin/service/tcp7
@@ -1,0 +1,2 @@
+#!/bin/rc
+/bin/cat
--- /dev/null
+++ b/rc/bin/service/tcp9
@@ -1,0 +1,2 @@
+#!/bin/rc
+cat > /dev/null
--- /dev/null
+++ b/rc/bin/service/tcp993
@@ -1,0 +1,3 @@
+#!/bin/rc
+
+exec tlssrv -c/sys/lib/ssl/cert.pem -limap4d -r`{cat $3/remote} /bin/ip/imap4d -pdplan9.bell-labs.com -r`{cat $3/remote}>[2]/sys/log/imap4d
--- /dev/null
+++ b/rc/bin/service/tcp995
@@ -1,0 +1,3 @@
+#!/bin/rc
+
+exec tlssrv -lpop3 -c/sys/lib/ssl/cert.pem -r`{cat $3/remote} /bin/upas/pop3 -p -r`{cat $3/remote} >[2]/sys/log/pop3
--- /dev/null
+++ b/rc/bin/service/telcodata
@@ -1,0 +1,3 @@
+#!/bin/rc
+echo This is the plan 9 incoming fax line.
+echo Please do not make data calls to us.
--- /dev/null
+++ b/rc/bin/service/telcofax
@@ -1,0 +1,4 @@
+#!/bin/rc
+9fs emelie
+bind -c /n/emelie/mail/faxqueue /mail/faxqueue
+exec /bin/aux/faxreceive
--- /dev/null
+++ b/rc/bin/setrtc
@@ -1,0 +1,4 @@
+#!/bin/rc
+# setrtc - set real-time clock to current system time
+if (test -e '#r/rtc')
+	awk '{print $1}' /dev/time >'#r/rtc'
--- /dev/null
+++ b/rc/bin/sig
@@ -1,0 +1,29 @@
+#!/bin/rc
+# Usage: sig key ...
+#	prints out function signatures by grepping the manual
+
+
+*=`{echo $*|tr A-Z a-z|tr -dc 'a-z0-9_ \012'}	# fold case, delete funny chars
+if(~ $#* 0){
+	echo Usage: sig function ... >/fd/2
+	exit 1
+}
+
+for (i) {
+	files=`{grep -il '[ 	]\*?'$i'\(' /sys/man/2/*}
+	for(j in $files) {
+		{echo .nr LL 20i; sed -n '/^.SH SYNOPSIS/,/^.SH.*DESCR/p'  $j } |
+			nroff -man |
+			sed '
+				:a
+				/,$/ {
+					N
+					s/\n//
+				}
+				ta
+				s/[ 	]+/ /g' |
+			grep -i -e '[ 	*]'$i'\(' | sed 's/^[ +]/	/'
+	}
+}
+
+exit 0
--- /dev/null
+++ b/rc/bin/slay
@@ -1,0 +1,7 @@
+#!/bin/rc
+U=`{cat /dev/user}
+for(i){
+	ps | sed -n '/^'$U' .* '$i'$/s%[^ ]*  *%~>/proc/%
+	s%  *.* (.*)%/ctl # \1%
+	s%~%echo kill%p'
+}
--- /dev/null
+++ b/rc/bin/spell
@@ -1,0 +1,21 @@
+#!/bin/rc
+
+spellflags=()
+deroffargs=()
+fflag=''
+for(x){
+	switch($x){
+	case -[abcvx]
+		spellflags=($spellflags $x)
+	case -f
+		fflag=$x
+	case *
+		if(~ $fflag -f)	{
+			spellflags=($spellflags -f $x)
+			fflag=''
+		}
+		if not		deroffargs=($deroffargs $x)
+	}
+}
+
+deroff -w $deroffargs | sort -u | aux/sprog $spellflags
--- /dev/null
+++ b/rc/bin/src
@@ -1,0 +1,55 @@
+#!/bin/rc
+
+rfork e
+path=(/bin/)
+
+sym = 'threadmain?z
+	main?z'
+
+fn dbsrc{
+	echo $sym | db $1 | sed '1d;/symbol not found/d;s/.*\(\) //'
+}
+
+fn go{
+	type=`{file <$1 | sed 's/stdin: //'}
+	switch($type){
+	case 'rc executable file'
+		plumbit $1 '(rc executable)'
+	case *executable* *'plan 9 boot image'*
+		plumbit  `{dbsrc $1} '(executable)'
+	case *
+		echo 'src: can''t find source for '$1 - unrecognized type $type >[1=2]
+	}
+}
+
+fn plumbit{B $1}
+
+fn usage{
+	echo usage: 'src [-n] [-s symbol] executable ...'>[1=2]
+	exit usage
+}
+
+while(~ $1 -*)
+	switch($1){
+	case -n
+		shift
+		fn plumbit {echo $1}
+	case -s
+		shift
+		# add main in case symbol is undefined
+		sym=$1'?z
+			main?z'
+		shift
+	case -*
+		usage
+	}
+
+if(~ $#* 0) usage
+
+for(i){
+	if(test -f $i) go $i
+	if not if(test -f /bin/$i) go /bin/$i
+	if not if(test -f /bin/*/$i) go /bin/*/$i
+	if not if(test -f /bin/*/*/$i) go /bin/*/*/$i
+	if not echo 'src: can''t find '$i
+}
--- /dev/null
+++ b/rc/bin/srvssh
@@ -1,0 +1,101 @@
+#!/bin/rc
+
+# Serve Unix u9fs over SSH
+#
+# Basically, try each of the following until you find one that works:
+#
+#	srvssh unix
+#	srvssh -r unix
+#	srvssh -R unix
+#	srvssh -r -s unix
+#	srvssh -R -s unix
+#
+# and then never look back.  Note that "srvssh unix" should always
+# work.  It's just that if you're talking with certain sshd's, you'll get
+# hit by Nagle's algorithm and need to explore the other flags.
+
+# When using ssh to start u9fs, the only way to turn off
+# Nagle's algorithm (which kills the performance of RPC-based
+# protocols like 9P) is to allocate a pseudo-terminal.  The
+# command ssh -Rmp attempts to allocate a pseudo-terminal and
+# then put it in a transparent mode.  Especially when
+# connected to older SSH daemons, the connection ends up not
+# quite transparent.  To get around this, we explicity set the tty
+# mode on the command line as well.  The hope is that -Rmp makes
+# the connection transparent enough for the Tversion, and the stty
+# command will do the rest.  If -Rmp doesn't make the connection
+# transparent enough for the Tversion (but the stty commands do 
+# make the connection fully transparent) then add "-s 5" to the srv
+# command to tell it to wait 5 seconds before sending the Tversion.
+# That should be enough time for the stty to take effect.
+
+rfork e
+
+fn usage {
+	echo 'usage: srvssh [-R] [-r] [-s] [-u u9fspath] system [srvname [mtpt]]' >[1=2]
+	exit usage
+}
+
+rawhack=''
+sleephack=()
+u9fspath=u9fs
+rawflags=''
+
+while(~ $1 -*){
+	switch($1){
+	case -r
+		rawflags='-Rmp'
+		shift
+	case -R
+		rawflags='-Rmp'
+		rawhack=('stty raw -echo '';''')
+		shift
+	case -s
+		sleephack=(-s 5)
+		shift
+	case -u
+		shift
+		u9fspath=$1
+		shift
+	case -u*
+		u9fspath=`{echo $1 | sed s/-u//}
+		shift
+	case *
+		usage
+	}
+}
+
+if(! ~ $#* 1 2 3)
+	usage
+
+switch($#*){
+case 1
+	srv=$1
+	mtpt=/n/$1
+case 2
+	srv=$2
+	mtpt=/n/$1
+case 3
+	srv=$2
+	mtpt=$3
+}
+
+x=(srv $sleephack -e \
+	'ssh '$rawflags' '$1' '$rawhack' '$u9fspath' -na none -u ''$''USER -l ''$''HOME/u9fs.log' \
+	$srv $mtpt)
+$x
+
+# Sometimes /srv/whatever can be a closed pipe, in which case
+# srv will have been killed for writing to it, without a chance to
+# defend itself.  Rerun it in this case.
+
+ss=$status
+if(~ $ss *'write on closed pipe'*){
+	rm -f /srv/$srv
+	$x
+	ss=$status
+}
+
+if(! ~ $ss '')
+	echo srvssh: $ss >[1=2]
+exit $ss
--- /dev/null
+++ b/rc/bin/start
@@ -1,0 +1,5 @@
+#!/bin/rc
+U=`{cat /dev/user}
+ps | sed -n '/^'$U' .*Stopped.* '$1'$/s%[^ ]*  *%~>/proc/%
+s%  *.*%/ctl%
+s%~%echo start%p'
--- /dev/null
+++ b/rc/bin/startupasfs
@@ -1,0 +1,5 @@
+#!/bin/rc
+# startupasfs - start upas/fs if needed, mainly for lib/profile
+if (! test -e /srv/upasfs.$user)
+	upas/fs -s
+mount -c /srv/upasfs.$user /mail/fs
--- /dev/null
+++ b/rc/bin/stock
@@ -1,0 +1,14 @@
+#!/bin/rc
+
+stock=ALU
+
+if(! ~ $#* 0) stock=`{echo $*|tr a-z A-Z|sed 's/ /+/g'}
+
+hget 'http://download.finance.yahoo.com/d/quotes.csv?s='^$stock^'&f=snl1d1c1v&e=.exe' |
+	sed 's/ +"/"/;s/
//' |
+	switch(`{date}){
+	case *'Apr 1 '*
+		sed 's/("ALU","ALCATEL LUCENT"),([^,]*),(.*)$/\1,72.35,\3/'
+	case *
+		cat
+	}
--- /dev/null
+++ b/rc/bin/stop
@@ -1,0 +1,5 @@
+#!/bin/rc
+U=`{cat /dev/user}
+ps | sed -n '/^'$U' .* '$1'$/s%[^ ]*  *%~>/proc/%
+s%  *.*%/ctl%
+s%~%echo stop%p'
--- /dev/null
+++ b/rc/bin/tel
@@ -1,0 +1,8 @@
+#!/bin/rc
+rfork e
+for(i){
+	if (test -f $home/lib/tel)
+		grep -i $i $home/lib/tel
+	grep -hi $i /lib/tel /lib/areacodes
+}
+exit ''
--- /dev/null
+++ b/rc/bin/termrc
@@ -1,0 +1,106 @@
+#!/bin/rc
+# terminal startup
+TIMESYNCARGS=(-rLa1000000)
+NDBFILE=/lib/ndb/local
+
+mntgen -s slashn && chmod 666 /srv/slashn
+
+# bind all likely devices (#S was bound in boot)
+for(i in f t m v L P u U '$' Σ κ)
+	/bin/bind -a '#'^$i /dev >/dev/null >[2=1]
+
+# set up any partitions
+diskparts
+
+# start up local swapping
+disk=`{ls /dev/sd*/swap >[2]/dev/null}
+if (! ~ $#disk 0)
+	swap $disk(1) >/dev/null >[2=1]
+rm /env/disk
+
+# we do this before we have a name.  we may need to do network
+# setup so that we can get a name.
+if(test -e /rc/bin/termrc.local)
+	. /rc/bin/termrc.local
+
+# cs sets sysname (termrc.local may already have started it so check)
+if(! test -e /srv/cs && ! test -e /net/cs)
+	ndb/cs -f $NDBFILE
+sysname=`{cat /dev/sysname}
+if (~ $#sysname 0 || ~ $sysname '') {
+	sysname = gnot			# default
+	echo -n $sysname >/dev/sysname
+}
+
+# machine specific startup (e.g., for devices not probed)
+if(test -e /cfg/$sysname/termrc)
+	. /cfg/$sysname/termrc
+
+# start IP on the LAN, if not already configured.  diskless terminals
+# are already configured by now.  It's commented out to avoid a long timeout
+# on startup waiting for DHCP.
+#
+# If your site provides DHCP service,
+#
+#if(! test -e /net/ipifc/0/ctl)
+#	ip/ipconfig
+#
+# Otherwise, see /cfg/$sysname/termrc (/cfg/example/termrc is an example).
+
+# start dns if we have an internet
+if(test -e /net/ipifc/0/ctl && ! test -e /srv/dns)
+	ndb/dns -r
+
+if(! ~ $terminal *vx32*){
+	# start timesync if it isn't running and we weren't told not to
+	if(! ps|grep -s timesync)
+		if(! ~ $TIMESYNCARGS '')
+			aux/timesync $TIMESYNCARGS
+
+	# add the loop-back medium
+	if(! grep -s 127.0.0.1 /net/ipselftab)
+		ip/ipconfig loopback /dev/null 127.1
+
+	# set things up for vmware
+	if(! ~ `{cat /dev/user} none)
+		if(test -e /bin/aux/vmware)
+			aux/vmware
+}
+
+# query user if terminal isn't adequately configured yet
+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(test -f /dev/mousectl){
+	switch($mouseport){
+	case ps2 ps2intellimouse 0 1 2
+		aux/mouse $mouseport
+		# parse vgasize into fields
+		vgasize=`{echo $vgasize}
+		if(! ~ $"monitor '' && ! ~ `{cat /dev/user} none)
+			aux/vga -l $vgasize
+		if(~ $accupoint 1)
+			pipefile -dr /bin/aux/accupoint /dev/mouse
+	}
+}
+
+usbstart
+if (test -f /dev/apm)
+	aux/apm
+
+dontkill '^(ipconfig|factotum|mntgen|fossil|cs|dns|listen|reboot)$'
--- /dev/null
+++ b/rc/bin/termrc.local
@@ -1,0 +1,13 @@
+#!/bin/rc
+# local terminal startup
+
+# used only by upas, as default return domain appended to all unqualified
+# return addresses, even local ones
+site=plan9
+# replace FILESERVER with the name of your file server
+# here we start with kfs, your local disk file system
+fileserver=kfs
+# replace FACEDOM with the local domain to be used in the faces database
+facedom=FACEDOM
+# replace CPU with the name of your cpu server
+cpu=CPU
--- /dev/null
+++ b/rc/bin/thesaurus
@@ -1,0 +1,29 @@
+#!/bin/rc
+
+hget 'http://thesaurus.reference.com/search?q='^$1 |
+	htmlfmt -l 1000 |
+	sed -n '/^Main Entry:/,/^Source/ {
+		/^Source/ q
+		/^[A-Z].*:/ {
+			N
+			s/\n/	/g
+		}
+		p
+	}' | awk -F', ' '{
+		if(length($0)<=70){
+			print
+			next
+		}
+		l = 0
+		for(i = 1; i < NF; i++){
+			printf "%s ", $i
+			l += length($i)+1
+			if(l > 70){
+				printf "\n\t\t"
+				l = 2*ENVIRON["tabstop"]
+			}
+		}
+		if(l>0)
+			printf "\n"
+		next
+	}'
--- /dev/null
+++ b/rc/bin/tlsclienttunnel
@@ -1,0 +1,7 @@
+#!/bin/rc
+
+if(! ~ $#* 3){
+	echo 'usage: tlsclienttunnel cryptaddr plainaddr cert.thumb' >[1=2]
+	exit usage
+}
+aux/listen1 -t $2 /bin/tlsclient -t $3 $1 &
--- /dev/null
+++ b/rc/bin/tlssrvtunnel
@@ -1,0 +1,7 @@
+#!/bin/rc
+
+if(! ~ $#* 3){
+	echo 'usage: tlssrvtunnel plainaddr cryptaddr cert.pem' >[1=2]
+	exit usage
+}
+aux/listen1 -tv $2 /bin/tlssrv -c $3 -llisten /bin/aux/trampoline $1 &
--- /dev/null
+++ b/rc/bin/troff2gif
@@ -1,0 +1,2 @@
+#!/bin/rc
+{/bin/troff $*|/bin/lp -dstdout|/bin/gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=plan9bm' - quit.ps| crop -c 255 255 255 | togif}  >[2] /dev/null
--- /dev/null
+++ b/rc/bin/troff2png
@@ -1,0 +1,9 @@
+#!/bin/rc
+
+troff -ms $* | aux/tr2post |
+	gs -g1000x1600 -r100 -dNOPAUSE -dQUIET \
+		'-dGraphicsAlphaBits=4' '-dTextAlphaBits=4' \
+		'-sOUTPUTFILE=-' '-sDEVICE=plan9' - quit.ps |
+	{crop -c 255 255 255; cat >/dev/null} | 
+	topng
+
--- /dev/null
+++ b/rc/bin/umem
@@ -1,0 +1,33 @@
+#!/bin/rc
+# umem pid [binary] - print summary of allocate blocks in a running process
+rfork e
+if(! ~ $#* 1 2){
+	echo 'usage: umem pid [binary]' >[1=2]
+	exit usage
+}
+
+p=$1
+binary=()
+if(~ $#* 2)
+	binary=$2
+
+echo 'blocksummary()' | acid -lpool -lleak $p $binary | awk '
+	$1 == "block" {
+		addr=$6
+		size=$3
+		alloc=$4
+		total[alloc] += size
+		count[alloc]++
+	}
+	$1 == "summary" { 
+		alloc=$2
+		cnt=$3
+		size=$4
+		total[alloc] += size
+		count[alloc] += cnt
+	}
+	END{
+		for(i in count)
+			printf("%6d %11d %s\n", count[i], total[i], i);
+	}
+' | sort -nr
--- /dev/null
+++ b/rc/bin/uncompress
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec compress -d $*
--- /dev/null
+++ b/rc/bin/ups
@@ -1,0 +1,32 @@
+#!/bin/rc
+# ups - look up a UPS tracking number
+rfork en
+
+if(! ~ $#* 1) {
+	echo usage: ups 1ZA41W190338680961 >[1=2]
+	exit usage
+}
+
+hget 'http://wwwapps.ups.com/WebTracking/processInputRequest?tracknum='^$1^ \
+	'&TypeOfInquiryNumber=T' >/tmp/ups.1
+
+sed 's/<[Tt][Dd]>/& «TD»/g; s/<[Tt][Rr]>/&<td> «TR» /g' /tmp/ups.1 |
+	htmlfmt >/tmp/ups.2
+sam -d /tmp/ups.2 >[2] /dev/null <<'!'
+/^Tracking results.*/p
+.,$d
+/Help/d
+1,.d
+$-2,$d
+/Status:/+1
+.,/«TR»/-2d
+,s/\n/ /g
+,s/«TR»/\n/g
+,s/«TD»/	/g
+,s/ *	 */	/g
+,s/^[ 	]*//g
+,s/[ 	]*$//g
+,s/\n\n+/\n\n/g
+,p
+!
+echo
--- /dev/null
+++ b/rc/bin/uptime
@@ -1,0 +1,8 @@
+#!/bin/rc
+clock=`{cat /dev/time}
+xx=`{{echo $clock(3) / $clock(4); echo '_/86400'}|hoc|sed 's/^\./0./g;s/\..*//g'}
+sec=$xx(1)
+days=$xx(2)
+cat /dev/sysname
+echo -n ' up '$days' days, '
+timezone='MDT -21600' date $sec |awk '{print $4}'
--- /dev/null
+++ b/rc/bin/usbeject
@@ -1,0 +1,41 @@
+#!/bin/rc
+# usbeject - unmount usb disks given as arguments
+#	unmount all of them if no arguments given
+rfork e
+disk = ()
+mtpt = /n/usb
+
+test -e /dev/fs/ctl || bind -b '#k' /dev >[2]/dev/null
+
+test -e /dev/usb || bind -a '#u' /dev || {
+	echo $0: no '#u/usb' >[1=2]
+	exit nousb
+}
+test -e /dev/usbdctl || mount -a /srv/usb /dev || {
+	echo $0: cannot mount /srv/usb >[1=2]
+	exit nousbd
+}
+
+disks=()
+mtpt=()
+switch ($#*) {
+case 0
+	disks=`{ls -pd /n/sdU*}
+case *
+	disks=()
+	for (a) {
+		if(~ $a sd??)
+			disk=`{ls -pd /n/^$*^*}
+		if not
+			disk=$a
+		disks=($disks $disk)
+	}
+}
+if (~ $disks '''sdU*''')
+	exit ''
+for (disk in $disks) {
+	unmount /n/$disk >[2]/dev/null && echo $disk unmounted
+	if (test -e /dev/fs/ctl)
+		echo del $disk^parts/^'*' >/dev/fs/ctl >[2]/dev/null
+}
+exit ''
--- /dev/null
+++ b/rc/bin/usbstart
@@ -1,0 +1,24 @@
+#!/bin/rc
+# usbstart - start appropriate usb flavour
+if(test -r '#u'/usb) {
+	if(! test -r /dev/usb)
+		bind -a '#u' /dev
+
+	# /boot/boot may have started usbd, which starts all usb drivers
+	if (! ps | grep -s ' usbd$')
+		usb/usbd
+}
+if not if(test -r '#U'/usb0) {
+	if(! test -r /dev/usb0)
+		bind -a '#U' /dev
+
+	# /boot/boot may have started usbd, usb/kb or usb/disk
+	if (! ps | grep -s ' usbd$')
+		usb/usbd
+	usb/usbmouse -a 2
+	if (! ps | grep -s ' kb$')
+		usb/kb -k
+	usb/usbaudio -s usbaudio.$sysname -V
+	# usb/print
+}
+exit ''
--- /dev/null
+++ b/rc/bin/usps
@@ -1,0 +1,20 @@
+#!/bin/rc
+rfork en
+
+
+if(! ~ $#* 1) {
+	echo usage: usps 01601531218002685498 >[1=2]
+	exit usage
+}
+
+rfork e
+
+hget -p 'origTrackNum='^$1 http://trkcnfrm1.smi.usps.com/PTSInternetWeb/InterLabelInquiry.do |
+	htmlfmt > /tmp/usps.$pid
+
+sam -d /tmp/usps.$pid >[2] /dev/null <<'!'
+0,/Label/-1d
+/^Enter Label/,$d
+,p
+!
+rm /tmp/usps.$pid
--- /dev/null
+++ b/rc/bin/vwhois
@@ -1,0 +1,17 @@
+#!/bin/rc
+
+rfork e
+
+box=mbox
+if(! test -d /mail/fs/$box)
+	box=`{ls -p /mail/fs | grep -v ctl | sed 1q}
+if(~ $#box 0)
+	box=mbox	# we tried
+
+if(~ $#box 1 && test -f /mnt/plumb/seemail || test -f /mnt/term/mnt/plumb/seemail){
+	for(i)
+		plumb -dseemail -a 'filetype=vwhois digest='$i.$pid' mailtype=new sender='$i /mail/fs/$box/XXXvwhois
+}
+if not for (i){
+	echo vwhois: vwhois: vwhois: delivered `{cat /dev/user} From $i '(vwho)' >> /sys/log/mail
+}
--- /dev/null
+++ b/rc/bin/wdoc2txt
@@ -1,0 +1,17 @@
+#!/bin/rc
+
+switch($#*){
+case 0
+	exit
+case 1
+	switch($1){
+	case *.rtf
+		pub/rtf2text $1 >[2]/dev/null | plumb -i -d edit -a 'action=showdata filename='$1
+	case *.doc *
+		doc2txt $1 | plumb -i -d edit -a 'action=showdata filename='$1
+	}
+	exit
+case *
+	for(i in *)
+		wdoc2txt $i
+}
--- /dev/null
+++ b/rc/bin/weather
@@ -1,0 +1,46 @@
+#!/bin/rc
+
+rfork e
+
+DEFAULT=ewr
+
+fn usage{
+	echo 'usage: weather 3-letter-city-code' >[1=2]
+	echo 'for a list of cities in new york, say' >[1=2]
+	echo '	weather ny' >[1=2]
+	exit usage
+}
+
+switch($#*){
+case 0
+	arg=$DEFAULT
+	if(~ $#weather 1)
+		arg=$weather
+case 1
+	arg=$1
+case *
+	usage
+}
+
+switch($arg){
+case [a-zA-Z][a-zA-Z][a-zA-Z]
+	script=('' '' 'C' '4' '1' '1' $arg '' '' '' '' 'X')
+case [a-zA-Z][a-zA-Z]
+	script=('' '' 'C' '4' '1' '3' $arg '' '' '' '' 'X')
+case *
+	usage
+}
+
+{
+	for(i in $script)
+		echo $i
+} |
+con -nrl tcp!rainmaker.wunderground.com!telnet |
+sed -n '/Enter .-letter .* code:/,/CITY FORECAST MENU/p' |
+sed 's/Enter .-letter .* code: //' |
+sed 's/   Press Return to continue, M to return to menu, X to exit: //' |
+grep -v 'CITY FORECAST MENU' |
+tr -d '
' |
+sed 's/ *$//' |
+uniq
+
--- /dev/null
+++ b/rc/bin/who
@@ -1,0 +1,4 @@
+#!/bin/rc
+ps | sed '/Broken/d
+/Exiting/d
+s% .*$%%' | sort -u
--- /dev/null
+++ b/rc/bin/whois
@@ -1,0 +1,9 @@
+#!/bin/rc
+
+for(i in $*)
+	grep '^'$i'	' /adm/whois ||
+	grep -i $i /adm/keys.who ||
+	grep -i $i /adm/netkeys.who ||
+	grep -i $i /adm/whois ||
+	grep -i $i /adm/users ||
+	echo who indeed is $i
--- /dev/null
+++ b/rc/bin/window
@@ -1,0 +1,100 @@
+#!/bin/rc
+# window [many options] cmd [arg...] - create new window and run cmd in it
+rfork e
+fn checkwsys{
+	if(~ $wsys ''){
+		echo  'window: $wsys not defined'
+		exit bad
+	}
+}
+
+# original version used mount to do the work
+fn oldway{
+	switch($#*){
+	case 0 1
+		echo usage: window '''minx miny maxx maxy''' cmd args ...
+		exit usage
+	}
+	
+	checkwsys
+	
+	dir = /mnt/wsys
+	srv = $wsys
+	
+	rfork ne
+	{
+		if(x=`{cat /dev/ppid}; mount $srv $dir N`{{echo $x $1 }| sed 's/^ //g;s/ +/,/g'}){
+			shift
+			bind -b $dir /dev
+			echo -n `{basename $1} > /dev/label >[2] /dev/null
+			exec $* < /dev/cons > /dev/cons >[2] /dev/cons
+		}
+	}&
+}
+
+# if argument is of form '100 100 200 200' or '100,100,200,200' use old way
+if(~ $1 *[0-9][' ,'][0-9]*){
+	oldway $*
+	exit
+}
+
+# geometry parameters are:
+#	-r 0 0 100 100
+#	-dx n
+#	-dy n
+#	-minx n
+#	-miny n
+#	-maxx n
+#	-maxy n
+# where n can be a number, to set the value, or +number or -number to change it
+
+# find wctl file
+fn getwctl{
+	if(~ $wctl ''){
+		if(test -f /dev/wctl) echo /dev/wctl
+		if not if(test -f /mnt/term/dev/wctl) echo /mnt/term/dev/wctl
+		if not if(~ $service cpu) echo /mnt/term/srv/riowctl.*.*
+		if not {
+			echo window: '$wctl' not defined >[1=2]
+			exit usage
+		}
+	}
+	if not echo $wctl
+}
+
+# use mount to make local window
+if(~ $1 -m){
+	shift
+
+	checkwsys
+	
+	dir = /mnt/wsys
+	srv = $wsys
+	rfork ne
+	{
+		unmount /mnt/acme /dev >[2]/dev/null
+		if(mount $srv $dir 'new -pid '^`{cat /dev/ppid}^' '$"*){
+			bind -b $dir /dev
+			# toss geometry parameters to find command
+			while(~ $1 -*)
+				switch($1){
+				case -dx -dy -minx -miny -maxx -maxy
+					shift 2
+				case -r
+					shift 5
+				case -scroll
+					shift
+				case -noscroll
+					shift
+				case -hide
+					shift
+				}
+			if(~ $#* 0) cmd = rc
+			if not cmd = $*
+			echo -n `{basename $cmd(1)} > /dev/label >[2] /dev/null
+			exec $cmd < /dev/cons > /dev/cons >[2] /dev/cons
+		}
+	}&
+}
+
+if not echo new -cd `{pwd} $* >> `{getwctl}
--- /dev/null
+++ b/rc/bin/wloc
@@ -1,0 +1,10 @@
+#!/bin/rc
+
+rfork e
+ifs='
+'
+
+for(i in `{ls /dev/wsys}) {
+	echo window -r `{syscall -o read 0 buf 59 < $i/window >[2] /dev/null |
+	sed 's/............//; s/^ *//; s/  */ /g'} `{cat $i/label}
+}
--- /dev/null
+++ b/rc/bin/wurl2txt
@@ -1,0 +1,15 @@
+#!/bin/rc
+
+switch($#*){
+case 0
+	exit
+case 1
+	name = /`{echo $1 | sed 's;.*//;;
+		s;/.*;;'}^/webpage
+	# send hget errors to 2 so they appear in window
+	hget $1 >[2=1]| {echo $1; echo; htmlfmt} >[2=1] | plumb -i -d edit -a 'action=showdata filename='$name
+	exit
+case *
+	for(i in *)
+		wurl2txt $i
+}
--- /dev/null
+++ b/rc/bin/xls2txt
@@ -1,0 +1,32 @@
+#!/bin/rc
+
+rfork en
+
+if(! ~ $#* 0 1) {
+	echo 'usage: xls2txt [file.xls]' >[1=2]
+	exit usage
+}
+
+switch($#*){
+case 0
+	cat >/tmp/xls2txt.$pid
+	file=/tmp/xls2txt.$pid
+case 1
+	file=$1
+}
+aux/olefs $file || { 
+	echo 'xls2txt: couldn''t mount excel document' >[1=2]
+	rm -f /tmp/xls2txt.$pid
+	exit word
+}
+
+if(! test -f /mnt/doc/Workbook) {
+	echo 'xls2txt: is an MSoffice doc but not an Excel document' >[1=2]
+	rm -f /tmp/xls2txt.$pid
+	exit wordxls
+}
+
+aux/msexceltables /mnt/doc/Workbook
+unmount /mnt/doc
+rm -f /tmp/xls2txt.$pid
+
--- /dev/null
+++ b/rc/bin/yesterday
@@ -1,0 +1,157 @@
+#!/bin/rc
+
+rfork e
+
+
+smon='s/Jan/01/
+	s/Feb/02/
+	s/Mar/03/
+	s/Apr/04/
+	s/May/05/
+	s/Jun/06/
+	s/Jul/07/
+	s/Aug/08/
+	s/Sep/09/
+	s/Oct/10/
+	s/Nov/11/
+	s/Dec/12/'
+
+fn usage {
+	echo 'usage: yesterday [-abcCdDs] [-[[[yy]yy]mm]dd] [-n daysago] file ...' >[1=2]
+	exit 'usage'
+}
+
+fn Xcp {
+	echo cp $1 $2
+	cp $1 $2
+}
+
+fn Xdiff {
+	echo diff $1 $2
+	diff $1 $2
+}
+fn Xdiffn {
+	echo diff -n $1 $2
+	diff -n $1 $2
+}
+fn Xadiff {
+	echo /acme/bin/adiff $1 $2
+	/acme/bin/adiff $1 $2
+}
+
+fn Xcarefulcp {
+	if(! cmp -s $1 $2) Xcp $1 $2
+}
+
+fn Xecho {
+	echo $1
+}
+
+fn Xbind {
+	echo bind $1 $2
+	bind $1 $2
+}
+
+year=`{date|sed 's/.* //'}
+copy=Xecho
+last=()
+defdump=dump
+while(! ~ $#* 0 && ~ $1 -* && ! ~ $1 --){
+	switch($1){
+	case -a
+		copy=Xadiff
+		shift
+	case -b
+		copy=Xbind
+		shift
+	case -c
+		copy=Xcp
+		shift
+	case -d
+		copy=Xdiff
+		shift
+	case -D
+		copy=Xdiffn
+		shift
+	case -C
+		copy=Xcarefulcp
+		shift
+	case -s
+		defdump=snap
+		shift
+	case -n*
+		if(~ $1 -n){
+			if(~ $#* 1)
+				usage
+			shift
+			days=$1
+		}
+		if not
+			days=`{echo $1 | sed 's/^-.//'}
+		last=`{date `{hoc -e `{date -n} ^ '-'$days'*60*60*24'} | \
+				sed -e 's%... (...) (..) ..:..:.. ... (....)%\3/\1\2%' -e 'y/ /0/' -e $smon}
+		shift
+	case -?
+		mon=`{date|sed -e 's/^....(...).*/\1/' -e $smon}
+		last=$year/$mon ^`{echo $1|sed 's/^-/0/'}
+		shift
+	case -??
+		mon=`{date|sed -e 's/^....(...).*/\1/' -e $smon}
+		last=$year/$mon ^`{echo $1|sed 's/^-//'}
+		shift
+	case -????
+		last=$year/ ^ `{echo $1|sed 's/^-//'}
+		shift
+	case -??????
+		last=`{echo $year|sed 's/..$//'} ^ `{echo $1|sed 's/^-(..)/\1\//'}
+		shift
+	case -????????
+		last=`{echo $1|sed 's/^-(....)/\1\//'}
+		shift
+	case *
+		usage
+	}
+}
+if(! ~ $#* 0 && ~ $1 --)
+	shift
+
+if(~ $#* 0)
+	usage
+
+dir=`{pwd}
+if(! ~ $status ''){
+	echo 'yesterday: can''t find directory' >[1=2]
+	exit 'pwd failed'
+}
+
+for(i){
+	xpath=`{cleanname -d $dir -- $i}
+	xdump=$defdump
+	dumppath=$xpath
+	if(~ $xpath /n/*/*){
+		xdump=`{echo $xpath | sed 's:/n/([^/]+)/.*:\1'$defdump':'}
+		dumppath=`{echo $xpath | sed 's:/n/[^/]+(/.*):\1:'}
+	}
+	if(! test -e /n/$xdump/$year)
+		9fs $xdump
+
+	if(~ $#last 0){
+		xlast=`{ls /n/$xdump/$year|sed -n '$p'}
+		switch($defdump){
+		case snap
+			xlast=`{ls $xlast|sed -n '$p'}
+		}
+	}
+	if not
+		xlast=/n/$xdump/$last
+
+	if(! test -e $xlast){
+		echo 'yesterday:' \
+			`{echo $xlast|sed 's/.n.'$defdump'.(....).(..)(..)/\1 \2 \3/'} \
+			'is not a backup day for' $xdump >[1=2]
+		exit 'bad date'
+	}
+	
+	$copy $xlast^$dumppath $xpath
+}
+exit ''
--- /dev/null
+++ b/rc/lib/rcmain
@@ -1,0 +1,34 @@
+# rcmain: Plan 9 version
+if(~ $#home 0) home=/
+if(~ $#ifs 0) ifs=' 	
+'
+switch($#prompt){
+case 0
+	prompt=('% ' '	')
+case 1
+	prompt=($prompt '	')
+}
+if(~ $rcname ?.out) prompt=('broken! ' '	')
+if(flag p) path=/bin
+if not{
+	finit
+	if(~ $#path 0) path=(. /bin)
+}
+fn sigexit
+if(! ~ $#cflag 0){
+	if(flag l && /bin/test -r $home/lib/profile) . $home/lib/profile
+	status=''
+	eval $cflag
+}
+if not if(flag i){
+	if(flag l && /bin/test -r $home/lib/profile) . $home/lib/profile
+	status=''
+	if(! ~ $#* 0) . $*
+	. -i '#d/0'
+}
+if not if(~ $#* 0) . '#d/0'
+if not{
+	status=''
+	. $*
+}
+exit $status