wm: infra

Download patch

ref: c5e6a43c868c21c8bf38c2a5885b4a7d37409f2d
parent: 9bad4d3f96208b2db152377d0e44094e3ffe00fd
author: saeed <saeed@cloud9p.org>
date: Mon May 5 19:11:14 IDT 2025

move plan 9 related files to plan9/

--- a/cfg/wm/cpurc
+++ /dev/null
@@ -1,32 +1,0 @@
-#!/bin/rc
-# chat
-hubfs -s grid.chat
-mount -c /srv/grid.chat /n/chat
-touch /n/chat/chat
-mkdir /n/chat/subline
-chmod 666 /srv/grid.chat
-
-# services
-# tcp80, tcp900, etc
-
-aux/listen -q -d /cfg/$sysname/service/ il
-
-# dns
-ndb/dns -s
-# dns over tls
-#ndb/dns -c /sys/lib/tls/acmed/cloud9p.org.crt
-
-# grid's ramfs, required for tcp80 and troffwiki
-ramfs -S grid.ramfs
-chmod 606 /srv/grid.ramfs
-
-# grid's radio
-# radio no longer uses our nfs
-#srvfs grid.audio /usr/pub/audio/
-
-# tls keys
-# moved to cpustart
-
-# mail
-# this used to live in /bin/service and then /cfg/wm/serv,
-# but since it needs to run as upas user, we need to run it seprately
--- a/cfg/wm/cpustart
+++ /dev/null
@@ -1,11 +1,0 @@
-#!/bin/sh
-# tls keys
-# need to started after factotum
-
-auth/secstored
-auth/secstore -n -G factotum >> /mnt/factotum/ctl
-
-# mail
-# this used to live in /bin/service and then /cfg/wm/serv
-site=cloud9p.org
-auth/as upas aux/listen -p 128 -t /cfg/$sysname/service.upas
--- a/cfg/wm/rules/doc
+++ /dev/null
@@ -1,25 +1,0 @@
-# main document server
-# html, pdf, ps and txt (defualt) available.
-/([^'/]+).ps	wm/doc/ps /usr/git/ wm doc HEAD '\1'
-/([^'/]+).pdf	wm/doc/pdf /usr/git/ wm doc HEAD '\1'
-/([^'/]+).htm	cd /usr/git/wm/doc/ ; git/fs ; ms2html < .git/fs/HEAD/tree/'\1'.ms
-#/([^'/]+).html	cd /usr/git/wm/doc/ ; git/fs ; htmlroff -ms -mhtml .git/fs/HEAD/tree/'\1'.ms
-/([^'/]+).html	wm/doc/html /usr/git/ wm doc HEAD '\1'
-/([^'/]+).txt	wm/doc/txt /usr/git/ wm doc HEAD '\1'
-/index.html	wm/doc/weblist /usr/git/ wm doc HEAD
-
-#/([0-9a-f]{40})/([^'/]+).htm	cd /usr/git/wm/doc/ ; git/fs ; ms2html < .git/fs/'\1'/tree/'\2'.ms
-#/([0-9a-f]{40})/([^'/]+).html	cd /usr/git/wm/doc/ ; git/fs ; htmlroff -ms -mhtml .git/fs/'\1'/tree/'\2'.ms
-#/([0-9a-f]{40})/([^'/]+).html	wm/docweb /usr/git/ wm doc '\1' '\2'
-#/([0-9a-f]{40})/([^'/]+).ps	cd /usr/git/wm/doc/ ; git/fs ; troff -ms .git/fs/'\1'/tree/'\2'.ms | dpost | ps2pdf
-#/([0-9a-f]{40})/([^'/]+).txt	cd /usr/git/wm/doc/ ; git/fs ; nroff -ms .git/fs/'\1'/tree/'\2'.ms | col -bf
-#/([0-9a-f]+)/index.html	wm/doc/weblist /usr/git/ wm doc '\1'
-
-# user document server
-# it's like main document server, but works with forks
-/usr/([^'/]+)/([^'/]+).ps	wm/doc/ps /usr/git/ '\1' doc HEAD '\2'
-/usr/([^'/]+)/([^'/]+).pdf	wm/doc/pdf /usr/git/ '\1' doc HEAD '\2'
-/usr/([^'/]+)/([^'/]+).htm	cd /usr/git/\1/doc ; git/fs ; ms2html < .git/fs/HEAD/tree/'\2'.ms
-/usr/([^'/]+)/([^'/]+).html	wm/doc/html /usr/git/ '\1' doc HEAD '\2'
-/usr/([^'/]+)/([^'/]+).txt	wm/doc/txt /usr/git/ '\1' doc HEAD '\2'
-/usr/([^'/]+)/index.html	wm/doc/weblist /usr/git/ '\1' doc HEAD
--- a/cfg/wm/rules/httpfs
+++ /dev/null
@@ -1,4 +1,0 @@
-# the_guest wanted a (working) httpfs, here it is.
-# no, it's not enabled. dont be silly.
-#/(https?\:)/([^'/]*)/(.+)\.(.+)		webfs ; ip/httpfile -f /fd/1 '\1'//'\2'/'\3'.'\4'
-#/(https?\:)/([^'/]*)/(.+)\.(.+)		webfs ; hget '\1'//'\2'/'\3'.'\4'
--- a/cfg/wm/rules/math
+++ /dev/null
@@ -1,9 +1,0 @@
-# mathjax-alike
-# example: /{eqn input here}.png
-
-/([^'/]+).png		{echo .EQ ; echo '\1' ; echo .EN} | eqn | troff | dpost | gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps| crop -c 255 255 255 | topng
-/([^'/]+).bit		{echo .EQ ; echo '\1' ; echo .EN} | eqn | troff | dpost | gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps| crop -c 255 255 255
-/([^'/]+).gif		{echo .EQ ; echo '\1' ; echo .EN} | eqn | troff | dpost | gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps| crop -c 255 255 255 | togif
-/([^'/]+).(jpg|jepg)		{echo .EQ ; echo '\1' ; echo .EN} | eqn | troff | dpost | gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps| crop -c 255 255 255 | tojpg
-
-#/([0-9]+)/([^'/]+).(jpg|jepg)		{echo .EQ ; echo '\2' ; echo .EN} | eqn | troff | dpost | gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps | crop -c 255 255 255 | resize -x+'\1'% | tojpg
--- a/cfg/wm/rules/toys
+++ /dev/null
@@ -1,3 +1,0 @@
-# mathjax(?) alike,
-# see /math/'x sup 2'.gif as an example
-#/([^'/]+).gif		{echo .EQ ; echo '\1' ; echo .EN} | eqn | troff | dpost | ps2gif
--- a/cfg/wm/rules/web
+++ /dev/null
@@ -1,13 +1,0 @@
-/index.html					/bin/shithub/list	/usr/git
-([^'/]+)/usr.html				/bin/shithub/usr	/usr/git '\1'
-(/.well-known/acme-challenge/([^'/]+))		/bin/cat		/usr/web/\1
-([^'/]+)/([^'/]+)/([^'/]+)/info.html		/bin/shithub/info	/usr/git '\1' '\2' '\3'
-([^'/]+)/([^'/]+)/([^'/]+)/files.html		/bin/shithub/files	/usr/git '\1' '\2' '\3'
-([^'/]+)/([^'/]+)/([^'/]+)/branches.html	/bin/shithub/branches	/usr/git '\1' '\2' '\3'
-([^'/]+)/([^'/]+)/([^'/]+)/snap.tar.gz		/bin/shithub/tar	/usr/git '\1' '\2' '\3'
-([^'/]+)/([^'/]+)/([^'/]+)/(([^']+)/)?f.html	/bin/shithub/view	/usr/git '\1' '\2' '\3' '\5'
-([^'/]+)/([^'/]+)/([^'/]+)/(([^']+)/)?raw	/bin/shithub/viewraw	/usr/git '\1' '\2' '\3' '\5'
-([^'/]+)/([^'/]+)/([^'/]+)/log.html		/bin/shithub/log	/usr/git '\1' '\2' '\3'
-([^'/]+)/([^'/]+)/([^'/]+)/commit.html		/bin/shithub/show	/usr/git '\1' '\2' '\3'
-([^'/]+)/([^'/]+)/([^'/]+)/_patch		/bin/shithub/patch	/usr/git '\1' '\2' '\3'
-([^'/]+)/([^'/]+)/([^'/]+)/feed.rss		/bin/shithub/feed	/usr/git '\1' '\2' '\3'
--- a/cfg/wm/service/!tcp22
+++ /dev/null
@@ -1,2 +1,0 @@
-#!/bin/rc
-#exec /bin/aux/trampoline 'net!unix.cloud9p.org!ssh'
--- a/cfg/wm/service/il17019
+++ /dev/null
@@ -1,11 +1,0 @@
-#!/bin/rc
-if(~ $#* 3){
-	netdir=$3
-	remote=$2!`{cat $3/remote}
-}
-fn server {
-	~ $#remote 0 || echo -n $netdir $remote >/proc/$pid/args
-	rm -f /env/'fn#server'
-	. <{n=`{read} && ! ~ $#n 0 && read -c $n} >[2=1]
-}
-exec tlssrv -a /bin/rc -c server
--- a/cfg/wm/service/il17031
+++ /dev/null
@@ -1,3 +1,0 @@
-#!/bin/rc
-exec ramfs -i
-
--- a/cfg/wm/service/startnfs
+++ /dev/null
@@ -1,7 +1,0 @@
-#!/bin/rc
-Kill portmapper | rc
-Kill nfsserver | rc
-rm -f /srv/nfsserver.chat /srv/portmapper.chat
-aux/nfsserver -f /srv/grid.audio -c /lib/ndb/nfs >>[2] /sys/log/nfsserver
-aux/portmapper >>[2] /sys/log/portmapper
-aux/portmapper -t >>[2] /sys/log/portmapper
--- a/cfg/wm/service/tcp17019
+++ /dev/null
@@ -1,11 +1,0 @@
-#!/bin/rc
-if(~ $#* 3){
-	netdir=$3
-	remote=$2!`{cat $3/remote}
-}
-fn server {
-	~ $#remote 0 || echo -n $netdir $remote >/proc/$pid/args
-	rm -f /env/'fn#server'
-	. <{n=`{read} && ! ~ $#n 0 && read -c $n} >[2=1]
-}
-exec tlssrv -a /bin/rc -c server
--- a/cfg/wm/service/tcp17020
+++ /dev/null
@@ -1,2 +1,0 @@
-#!/bin/rc
-exec tlssrv -A /bin/aux/trampoline 'net!$fs!9fs'
--- a/cfg/wm/service/tcp17021
+++ /dev/null
@@ -1,2 +1,0 @@
-#!/bin/rc
-exec tlssrv -a /bin/git/serve -wr/usr/git
--- a/cfg/wm/service/tcp443
+++ /dev/null
@@ -1,3 +1,0 @@
-#!/bin/rc
-exec tlssrv -c/sys/lib/tls/acmed/cloud9p.org.crt -r`{cat $3/remote}\
-/bin/aux/trampoline net!wm!80>>[2]/sys/log/httpd/log
--- a/cfg/wm/service/tcp53
+++ /dev/null
@@ -1,2 +1,0 @@
-#!/bin/rc
-/bin/ndb/dnstcp $3
--- a/cfg/wm/service/tcp565
+++ /dev/null
@@ -1,7 +1,0 @@
-#!/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
--- a/cfg/wm/service/tcp70
+++ /dev/null
@@ -1,9 +1,0 @@
-#!/bin/rc
-mount -c /srv/grid.ramfs /tmp
-
-execfs -m /usr/pub/math /cfg/wm/rules/math
-execfs -m /usr/pub/doc /cfg/wm/rules/doc
-
-bind -ac /usr/pub /usr/web
-
-exec /bin/tcp70 $3 >>[2]/sys/log/gopher
--- a/cfg/wm/service/tcp7777
+++ /dev/null
@@ -1,2 +1,0 @@
-#!/bin/rc
-wm/pasted /usr/pub/paste
--- a/cfg/wm/service/tcp80
+++ /dev/null
@@ -1,14 +1,0 @@
-#!/bin/rc
-mount -c /srv/grid.ramfs /tmp
-
-execfs -m /n/web /cfg/wm/rules/web
-# not to overlap with static content
-bind -a /n/web/ /usr/web
-
-execfs -m /usr/pub/math /cfg/wm/rules/math
-execfs -m /usr/pub/doc  /cfg/wm/rules/doc
-
-bind -b /sys/doc /usr/pub/doc/sys
-bind -b /usr/pub /usr/web
-
-exec /bin/tcp80 $3 >>[2]/sys/log/httpd/log
--- a/cfg/wm/service/tcp900
+++ /dev/null
@@ -1,9 +1,0 @@
-#!/bin/rc
-mount -c /srv/grid.ramfs /tmp
-
-execfs -m /usr/pub/doc /cfg/wm/rules/doc
-execfs -m /usr/pub/math /cfg/wm/rules/math
-execfs -m /usr/pub/http /cfg/wm/rules/httpfs
-
-mount -bc /srv/grid.chat /usr/pub
-exec exportfs -r /usr/pub
--- a/cfg/wm/service/tcp901
+++ /dev/null
@@ -1,2 +1,0 @@
-#!/bin/rc
-exec tlssrv -A /bin/aux/trampoline 'net!$sysname!900'
--- a/cfg/wm/service/tcp9418
+++ /dev/null
@@ -1,2 +1,0 @@
-#!/bin/rc
-git/serve -r /usr/git
--- a/chusr.c
+++ /dev/null
@@ -1,304 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <libsec.h>
-#include <authsrv.h>
-
-#define	KEYDB		"/mnt/keys"
-#define NETKEYDB	"/mnt/netkeys"
-#define KEYDBBUF	(sizeof NETKEYDB)	/* enough for any keydb prefix */
-#define AUTHLOG		"auth"
-
-enum{
-    Nemail      = 10,           /* from authcmdlib.h */
-	MAXNETCHAL	= 100000,		/* max securenet challenge */
-	Maxpath		= 256,
-};
-
-typedef struct
-{
-	char	*user;
-	char	*postid;
-	char	*name;
-	char	*dept;
-	char	*email[Nemail];
-} Acctbio;
-
-typedef struct {
-	char	*keys;
-	char	*msg;
-	char	*who;
-	Biobuf 	*b;
-} Fs;
-
-Fs fs =	{ "/mnt/keys", "plan 9 key", "/adm/keys.who", 0 };
-
-static uchar zeros[16];
-
-
-void    install(char*, char*, Authkey*, long);
-int exists(char*, char*);
-void	private(void);
-int	setkey(char*, char*, Authkey*);
-char*	setdeskey(char*, char*, char*);
-uchar*	setaeskey(char*, char*, uchar*);
-char*	setsecret(char*, char*, char*);
-void	wrbio(char*, Acctbio*);
-int	writefile(char*, char*, int);
-int	deskeyfmt(Fmt*);
-
-void
-usage(void)
-{
-	fprint(2, "usage: %s [-d dept] [-e email] [-i postid] [-s sponsor\'s email] -p pass user\n", argv0);
-	exits("usage");
-}
-
-void
-main(int argc, char *argv[])
-{
-    int debug = 1;
-	char *u, *pass = "";
-	Authkey key;
-	Acctbio a;
-	Fs *f;
-
-	fmtinstall('K', deskeyfmt);
-
-	ARGBEGIN{
-        case 'D':
-            debug = 1;
-            break;
-
-        case 'd':
-            a.dept = EARGF(usage());
-            break;
-
-        case 'i':
-            a.postid = EARGF(usage());
-            break;
-
-        case 'e':
-            a.email[0] = EARGF(usage());
-            break;
-
-        case 'p':
-            pass = EARGF(usage());
-            break;
-
-        case 's':
-            a.email[1] = EARGF(usage());
-            break;
-
-        default:
-            usage();
-
-	}ARGEND
-
-	if(utflen(pass) < 8)
-        usage();
-
-	u = argv[0];
-
-	if(memchr(u, '\0', ANAMELEN) == 0)
-		sysfatal("bad user name");
-    if(!debug)
-	   private();
-
-	a.user = u;
-	memset(&key, 0, sizeof(key));
-	f = &fs;
-
-	passtokey(&key, pass);
-
-	install(f->keys, u, &key, 0);
-
-	if(setsecret(KEYDB, u, pass) == 0)
-		sysfatal("error writing Inferno/POP secret");
-
-	wrbio(f->who, &a);
-
-	print("user %s installed for Plan 9\n", u);
-	syslog(0, AUTHLOG, "user %s installed for plan 9", u);
-
-	exits(0);
-}
-
-void
-install(char *db, char *u, Authkey *key, long t)
-{
-	char buf[KEYDBBUF+ANAMELEN+20];
-	int fd;
-
-	if(!exists(db, u)){
-		snprint(buf, sizeof(buf), "%s/%s", db, u);
-		fd = create(buf, OREAD, 0777|DMDIR);
-		if(fd < 0)
-			sysfatal("can't create user %s: %r", u);
-		close(fd);
-	}
-
-	if(!setkey(db, u, key))
-		sysfatal("can't set key: %r");
-
-	if(t == -1)
-		return;
-	snprint(buf, sizeof(buf), "%s/%s/expire", db, u);
-	fd = open(buf, OWRITE);
-	if(fd < 0 || fprint(fd, "%ld", t) < 0)
-		sysfatal("can't write expiration time");
-	close(fd);
-}
-
-int
-exists(char *db, char *u)
-{
-	char buf[KEYDBBUF+ANAMELEN+6];
-
-	snprint(buf, sizeof(buf), "%s/%s/expire", db, u);
-	if(access(buf, 0) < 0)
-		return 0;
-	return 1;
-}
-
-
-/* these functions are from /sys/src/cmd/auth/lib/ */
-
-int
-deskeyfmt(Fmt *f)
-{
-	uchar key[8];
-	char buf[32];
-	uchar *k;
-	int i;
-
-	k = va_arg(f->args, uchar*);
-	key[0] = 0;
-	for(i = 0; i < 7; i++){
-		key[i] |= k[i] >> i;
-		key[i] &= ~1;
-		key[i+1] = k[i] << (7 - i);
-	}
-	key[7] &= ~1;
-	sprint(buf, "%.3uo %.3uo %.3uo %.3uo %.3uo %.3uo %.3uo %.3uo",
-		key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]);
-	fmtstrcpy(f, buf);
-	return 0;
-}
-
-/* don't allow other processes to debug us and steal keys */
-void
-private(void)
-{
-	int fd;
-	char buf[32];
-	static char pmsg[] = "Warning! %s can't protect itself from debugging: %r\n";
-	static char smsg[] = "Warning! %s can't turn off swapping: %r\n";
-
-	snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
-	fd = open(buf, OWRITE|OCEXEC);
-	if(fd < 0){
-		fprint(2, pmsg, argv0);
-		return;
-	}
-	if(fprint(fd, "private") < 0)
-		fprint(2, pmsg, argv0);
-	if(fprint(fd, "noswap") < 0)
-		fprint(2, smsg, argv0);
-	close(fd);
-}
-
-int
-setkey(char *db, char *user, Authkey *key)
-{
-	int ret;
-
-	ret = setdeskey(db, user, key->des) != nil;
-	if(tsmemcmp(key->aes, zeros, AESKEYLEN) != 0)
-		ret |= setaeskey(db, user, key->aes) != nil;
-	return ret;
-}
-
-char*
-setdeskey(char *db, char *user, char *key)
-{
-	char filename[Maxpath];
-
-	snprint(filename, sizeof filename, "%s/%s/key", db, user);
-	if(writefile(filename, key, DESKEYLEN) != DESKEYLEN)
-		return nil;
-	return key;
-}
-
-uchar*
-setaeskey(char *db, char *user, uchar *key)
-{
-	char filename[Maxpath];
-
-	snprint(filename, sizeof filename, "%s/%s/aeskey", db, user);
-	if(writefile(filename, (char*)key, AESKEYLEN) != AESKEYLEN)
-		return nil;
-	return key;
-}
-
-char*
-setsecret(char *db, char *user, char *secret)
-{
-	char filename[Maxpath];
-
-	snprint(filename, sizeof filename, "%s/%s/secret", db, user);
-	if(writefile(filename, secret, strlen(secret)) != strlen(secret))
-		return nil;
-	return secret;
-}
-
-void
-wrbio(char *file, Acctbio *a)
-{
-	char buf[1024];
-	int i, fd, n;
-
-	fd = open(file, OWRITE);
-	if(fd < 0){
-		fd = create(file, OWRITE, 0660);
-		if(fd < 0)
-			sysfatal("can't create %s", file);
-	}
-	if(seek(fd, 0, 2) < 0)
-		sysfatal("can't seek %s", file);
-
-	if(a->postid == 0)
-		a->postid = "";
-	if(a->name == 0)
-		a->name = "";
-	if(a->dept == 0)
-		a->dept = "";
-	if(a->email[0] == 0)
-		a->email[0] = strdup(a->user);
-
-	n = 0;
-	n += snprint(buf+n, sizeof(buf)-n, "%s|%s|%s|%s",
-		a->user, a->postid, a->name, a->dept);
-	for(i = 0; i < Nemail; i++){
-		if(a->email[i] == 0)
-			break;
-		n += snprint(buf+n, sizeof(buf)-n, "|%s", a->email[i]);
-	}
-	n += snprint(buf+n, sizeof(buf)-n, "\n");
-
-	write(fd, buf, n);
-	close(fd);
-}
-
-int
-writefile(char *file, char *buf, int n)
-{
-	int fd;
-
-	fd = open(file, OWRITE);
-	if(fd < 0)
-		return -1;
-	n = write(fd, buf, n);
-	close(fd);
-	return n;
-}
--- a/doc/html
+++ /dev/null
@@ -1,45 +1,0 @@
-#!/bin/rc -e
-
-. /sys/lib/shithub/common.rc
-
-cd $1
-shift
-
-rfork ne
-nl='
-'
-
-gituser=$1
-repo=$2
-refname=$3
-file=$4
-
-repons $gituser $repo
-if(! ref=`{resolveref $refname}){
-	echo '<b>invalid ref '$refname'</b>'
-	exit
-}
-
-if(! test -d $gitfs/$ref/tree){
-	echo '	<p>No code pushed</p>
-		</body>
-		</html>
-	'
-	exit
-}
-
-cd $gitfs/$ref/tree
-
-echo '	<p>'
-
-echo '<p><div id="content">'
-
-if(test -r $gitfs/$ref/tree/$file.wms)
-	wm/doc/wiki2ms $gitfs/$ref/tree/$file.wms | ms2html
-if not
-	ms2html < $gitfs/$ref/tree/$file.ms
-	
-echo '	</div>
-	</p>
-	</body>
-	</html>'
--- a/doc/pdf
+++ /dev/null
@@ -1,32 +1,0 @@
-#!/bin/rc -e
-
-. /sys/lib/shithub/common.rc
-
-cd $1
-shift
-
-rfork ne
-nl='
-'
-
-gituser=$1
-repo=$2
-refname=$3
-file=$4
-
-repons $gituser $repo
-if(! ref=`{resolveref $refname}){
-	echo 'Invalid ref '$refname''
-	exit
-}
-
-if(! test -d $gitfs/$ref/tree){
-	echo 'No such document'
-	exit
-}
-
-cd $gitfs/$ref/tree
-if(test -r $gitfs/$ref/tree/$file.wms)
-	wm/doc/wiki2ms $gitfs/$ref/tree/$file.wms | troff -ms | dpost | ps2pdf
-if not
-	troff -ms $gitfs/$ref/tree/$file.ms | dpost | ps2pdf
--- a/doc/ps
+++ /dev/null
@@ -1,32 +1,0 @@
-#!/bin/rc -e
-
-. /sys/lib/shithub/common.rc
-
-cd $1
-shift
-
-rfork ne
-nl='
-'
-
-gituser=$1
-repo=$2
-refname=$3
-file=$4
-
-repons $gituser $repo
-if(! ref=`{resolveref $refname}){
-	echo 'Invalid ref '$refname''
-	exit
-}
-
-if(! test -d $gitfs/$ref/tree){
-	echo 'No such document'
-	exit
-}
-
-cd $gitfs/$ref/tree
-if(test -r $gitfs/$ref/tree/$file.wms)
-	wm/doc/wiki2ms $gitfs/$ref/tree/$file.wms | troff -ms | dpost
-if not
-	troff -ms $gitfs/$ref/tree/$file.ms | dpost
--- a/doc/txt
+++ /dev/null
@@ -1,32 +1,0 @@
-#!/bin/rc -e
-
-. /sys/lib/shithub/common.rc
-
-cd $1
-shift
-
-rfork ne
-nl='
-'
-
-gituser=$1
-repo=$2
-refname=$3
-file=$4
-
-repons $gituser $repo
-if(! ref=`{resolveref $refname}){
-	echo 'Invalid ref '$refname''
-	exit
-}
-
-if(! test -d $gitfs/$ref/tree){
-	echo 'No such document'
-	exit
-}
-
-cd $gitfs/$ref/tree
-if(test -r $gitfs/$ref/tree/$file.wms)
-	wm/doc/wiki2ms $gitfs/$ref/tree/$file.wms | nroff -ms | col -bf
-if not
-	nroff -ms $gitfs/$ref/tree/$file.ms | col -bf
--- a/doc/weblist
+++ /dev/null
@@ -1,60 +1,0 @@
-#!/bin/rc -e
-
-. /sys/lib/shithub/common.rc
-
-rfork ne
-nl='
-'
-cd $1
-shift
-
-rfork ne
-nl='
-'
-
-gituser=$1
-repo=$2
-ref=$3
-
-repons $gituser $repo
-
-prelude '' 'Documents'
-#echo '<img src="/static/'$logo'" /><br/>'
-
-if(~ $#intro 0)
-	echo '<h2>Documents</h2><br>'
-
-echo $ref
-cd $gitfs/$ref/tree
-udir=()
-for(doc in `$nl{ls -Q *}){
-	ndir=`{basename -d $doc}
-	if(~ $ndir .)
-		ndir=Root
-	if(! ~ $udir $ndir)
-		echo '</dl>'
-	if(! ~ $udir $ndir){
-		echo '<h3>'$ndir'</h3>'
-		echo '<dl>'
-		udir=$ndir
-	}
-
-	echo '<dt>'
-
-	title = `{grep '.TL$^(.+)' $doc | sed 2p}
-	filename = `{echo $doc | sed s/'(.+).ms'/\1/g}
-
-	if(! ~ $#title 0)
-		echo '<h6>'$filename': '$"title'</h6>'
-	if not
-		echo '<h6>'$filename'</h6>'	
-	echo '</dt><dd>'
-	echo '[<a href="'$filename^.html'">html</a>]'
-	echo '[<a href="'$filename^.txt'">txt</a>]'
-	echo '</dd>'
-}
-echo '
-</div>
-</p>
-</body>
-</html>'
--- a/doc/wiki2ms
+++ /dev/null
@@ -1,145 +1,0 @@
-#!/bin/rc
-nl='
-'
-file=$1
-url=$2
-# wiki2ms
-# convert from wikifs(6) format to ms format
-# usage:
-#	wiki2ms document.wiki https://cloud9p.org/man # normal wiki text
-#	wiki2ms document.wms https://cloud9p.org/man # wiki with ms macros
-# bugs:
-# man page linking is better to be optional
-# very wasteful
-# ms output could've been better
-# some of wikifs functionality is not yet implmented:
-# proper parsing for links
-
-fn quote {
-	echo $1 | sed 's/\//\\\//g' | sed 's/\./\\\./g'
-}
-
-fn comment {
-	ifs=$nl
-	for(i in `{cat}){
-		if(! ~ $i '#'*)
-			echo $i	
-	}
-}
-
-fn removebang {
-	# wasteful, i know
-	echo $1 | sed 's/^(! |!)//g'
-}
-
-fn monospace {
-	ifs=$nl
-	mono=f
-	for(i in `{cat}){
-		if(~ $i !*){
-			if(~ $mono f){
-				mono=t
-				echo '.P1'
-			}
-			removebang $i
-		}
-		if not {
-			if(~ $mono t) {
-				mono=f
-				echo '.P2'
-			}
-			echo $i
-		}
-	}
-	# last line may be a ! line.
-	if(~ $mono t){
-		mono=f
-		echo '.P2'	
-	}
-}
-
-fn directlink {
-	ifs=$nl
-	mono=f
-	for(i in `{cat}){
-		if(~ $i .P1){
-			mono=t
-			echo $i
-		}
-		if not if(~ $i .P2){
-			mono=f
-			echo $i
-		}
-		if not if(~ $mono f)
-			echo $i | sed 's/\[([^\n]+)\|([^\n]+)\]/\n\.LN \2\n\1\n\.LN\n/g'
-		if not
-			echo $i
-	}	
-}
-
-fn indirectlink {
-	ifs=$nl
-	mono=f
-	for(i in `{cat}){
-		if(~ $i .P1){
-			mono=t
-			echo $i
-		}
-		if not if(~ $i .P2){
-			mono=f
-			echo $i
-		}
-		if not if(~ $mono f)
-			echo $i | sed 's/\[([^\n]+)\]/\n\.LN \1\n\1\n\.LN\n/g'
-		if not
-			echo $i
-	}
-}
-
-fn manpage {
-	ifs=$nl
-	mono=f
-	for(i in `{cat}){
-		if(~ $i .P1){
-			mono=t
-			echo $i
-		}
-		if not if(~ $i .P2){
-			mono=f
-			echo $i
-		}
-		if not if(~ $mono f)
-			echo $i | sed 's/([^ ]+)\(([0-9])\)/\n\.LN '^$url^'\2\/\1\n\1\(\2\)\n\.LN\n/g'
-		if not
-			echo $i
-	}
-}
-
-url=`{quote $url}
-
-cat $1 |
-
-# paragraphs
-sed 's/^$/.LP/g' |
-
-# comments
-comment | 
-
-# titles
-sed 's/^((([A-Z]| |-|_|\(|\)))+)$/\.SH\n\1\n\.LP/g' |
-
-# bulleted lists
-sed 's/(^\* )|(^\*)/\.IP \\(bu\n/g' |
-
-# monospaced block
-monospace |
-
-# direct links ([x|y] form)
-directlink |
-
-# indirect links ([x] form)
-indirectlink | 
-
-# man pages, TODO: enable it later
-#manpage
-cat
--- a/mkfile
+++ /dev/null
@@ -1,34 +1,0 @@
-< /$objtype/mkfile
-#BIN=$home
-BIN=/$objtype/bin/wm
-
-TARG=\
-    chusr\
-
-RC=\
-	newuser\
-	pasted\
-	getaudio\
-	doc/html\
-	doc/pdf\
-	doc/ps\
-	doc/txt\
-	doc/weblist\
-	doc/wiki2ms\
-
-</sys/src/cmd/mkmany
-
-install:V:
-	mkdir -p $BIN $BIN/doc
-	for (i in $TARG)
-		mk $MKFLAGS $i.install
-	for (i in $RC)
-		mk $MKFLAGS $i.rcinstall
-
-%.rcinstall:V:
-	cp $stem $BIN/$stem
-
-$BIN:
-	mkdir -p $BIN
-
-
--- a/newuser
+++ /dev/null
@@ -1,65 +1,0 @@
-#!/bin/rc
-run_newuser=t
-args=()
-
-fn usage {
-	echo 'usage: newuser [-n] [-d dept] [-e email] [-i postid] [-s sponsormail] user [pass]' >[1=2]
-	exit 'usage'
-}
-
-fn newu {
-	u=$1
-	p=$2
-
-	auth/keyfs
-
-	if(test -w /srv/cwfs.cmd){
-	echo newuser $u >> /srv/cwfs.cmd
-	wm/chusr $args -p $p $u
-	if(~ $run_newuser t) {
-		# auth/as $u /sys/lib/newuser # messes up with namespace
-		if(! test -f /env/authdom)
-			authdom=`{ndb/query sys $sysname authdom}
-
-		if(! test -f /env/authdom) {
-					echo 'newuser: no authdom variable or entry in ndb' >[1=2]
-					exit 'no authdom'
-		}
-		echo 'key user='$u' proto=dp9ik dom='$authdom' role=client !password='$p >/mnt/factotum/ctl
-		rcpu -u $u -c /sys/lib/newuser
-	}
-	auth/enable $u
-	}
-
-	if not {
-		echo 'no cwfs.cmd or access to it'>[2=1]
-		exit 'no cwfs.cmd or access to it'
-	}
-}
-
-while (~ $1 -*) {
-	switch ($1) {
-		case -[sdier]
-                        if(~ $#x 0)
-				args=$args $1 $2
-        		shift
-		case -n
-			run_newuser=f
-		case -*
-	 		usage
-	}
-	shift
-}
-
-if (~ $#* 1) {
-	pass=`{fortune /lib/dict/pgwindex | awk '{ print $1 }'}
-	pass=($pass^`{fortune /lib/dict/pgwindex | awk '{ print $1 }'})
-	echo password: $"pass
-	newu $1 $pass
-}
-
-if (~ $#* 2)
-	newu $1 $2
-if not
-    usage
-
--- a/pasted
+++ /dev/null
@@ -1,20 +1,0 @@
-#!/bin/rc
-# wm/pasted path
-# a simple pastebin, use with aux/listen
-if(! ~ $#* 1) {
-	echo 'usage: wm/pasted user' >[1=2]
-	exit usage
-}
-
-# not to override files
-fn genrand {
-	dir = $1
-	rand = `{dd -quiet 1 -if /dev/random -bs 1 -count 2 | xd -1 | awk '{$1=""; print $0}' | tr -d ' '}
-	if(test -e $dir/$rand){
-		genrand
-	}
-}
-
-genrand $1
-echo $rand
-read -m -c `{echo '1024 * 1024 * 10'| bc} > $dir/$rand
--- /dev/null
+++ b/plan9/cfg/wm/cpurc
@@ -1,0 +1,32 @@
+#!/bin/rc
+# chat
+hubfs -s grid.chat
+mount -c /srv/grid.chat /n/chat
+touch /n/chat/chat
+mkdir /n/chat/subline
+chmod 666 /srv/grid.chat
+
+# services
+# tcp80, tcp900, etc
+
+aux/listen -q -d /cfg/$sysname/service/ il
+
+# dns
+ndb/dns -s
+# dns over tls
+#ndb/dns -c /sys/lib/tls/acmed/cloud9p.org.crt
+
+# grid's ramfs, required for tcp80 and troffwiki
+ramfs -S grid.ramfs
+chmod 606 /srv/grid.ramfs
+
+# grid's radio
+# radio no longer uses our nfs
+#srvfs grid.audio /usr/pub/audio/
+
+# tls keys
+# moved to cpustart
+
+# mail
+# this used to live in /bin/service and then /cfg/wm/serv,
+# but since it needs to run as upas user, we need to run it seprately
--- /dev/null
+++ b/plan9/cfg/wm/cpustart
@@ -1,0 +1,11 @@
+#!/bin/sh
+# tls keys
+# need to started after factotum
+
+auth/secstored
+auth/secstore -n -G factotum >> /mnt/factotum/ctl
+
+# mail
+# this used to live in /bin/service and then /cfg/wm/serv
+site=cloud9p.org
+auth/as upas aux/listen -p 128 -t /cfg/$sysname/service.upas
--- /dev/null
+++ b/plan9/cfg/wm/rules/doc
@@ -1,0 +1,25 @@
+# main document server
+# html, pdf, ps and txt (defualt) available.
+/([^'/]+).ps	wm/doc/ps /usr/git/ wm doc HEAD '\1'
+/([^'/]+).pdf	wm/doc/pdf /usr/git/ wm doc HEAD '\1'
+/([^'/]+).htm	cd /usr/git/wm/doc/ ; git/fs ; ms2html < .git/fs/HEAD/tree/'\1'.ms
+#/([^'/]+).html	cd /usr/git/wm/doc/ ; git/fs ; htmlroff -ms -mhtml .git/fs/HEAD/tree/'\1'.ms
+/([^'/]+).html	wm/doc/html /usr/git/ wm doc HEAD '\1'
+/([^'/]+).txt	wm/doc/txt /usr/git/ wm doc HEAD '\1'
+/index.html	wm/doc/weblist /usr/git/ wm doc HEAD
+
+#/([0-9a-f]{40})/([^'/]+).htm	cd /usr/git/wm/doc/ ; git/fs ; ms2html < .git/fs/'\1'/tree/'\2'.ms
+#/([0-9a-f]{40})/([^'/]+).html	cd /usr/git/wm/doc/ ; git/fs ; htmlroff -ms -mhtml .git/fs/'\1'/tree/'\2'.ms
+#/([0-9a-f]{40})/([^'/]+).html	wm/docweb /usr/git/ wm doc '\1' '\2'
+#/([0-9a-f]{40})/([^'/]+).ps	cd /usr/git/wm/doc/ ; git/fs ; troff -ms .git/fs/'\1'/tree/'\2'.ms | dpost | ps2pdf
+#/([0-9a-f]{40})/([^'/]+).txt	cd /usr/git/wm/doc/ ; git/fs ; nroff -ms .git/fs/'\1'/tree/'\2'.ms | col -bf
+#/([0-9a-f]+)/index.html	wm/doc/weblist /usr/git/ wm doc '\1'
+
+# user document server
+# it's like main document server, but works with forks
+/usr/([^'/]+)/([^'/]+).ps	wm/doc/ps /usr/git/ '\1' doc HEAD '\2'
+/usr/([^'/]+)/([^'/]+).pdf	wm/doc/pdf /usr/git/ '\1' doc HEAD '\2'
+/usr/([^'/]+)/([^'/]+).htm	cd /usr/git/\1/doc ; git/fs ; ms2html < .git/fs/HEAD/tree/'\2'.ms
+/usr/([^'/]+)/([^'/]+).html	wm/doc/html /usr/git/ '\1' doc HEAD '\2'
+/usr/([^'/]+)/([^'/]+).txt	wm/doc/txt /usr/git/ '\1' doc HEAD '\2'
+/usr/([^'/]+)/index.html	wm/doc/weblist /usr/git/ '\1' doc HEAD
--- /dev/null
+++ b/plan9/cfg/wm/rules/httpfs
@@ -1,0 +1,4 @@
+# the_guest wanted a (working) httpfs, here it is.
+# no, it's not enabled. dont be silly.
+#/(https?\:)/([^'/]*)/(.+)\.(.+)		webfs ; ip/httpfile -f /fd/1 '\1'//'\2'/'\3'.'\4'
+#/(https?\:)/([^'/]*)/(.+)\.(.+)		webfs ; hget '\1'//'\2'/'\3'.'\4'
--- /dev/null
+++ b/plan9/cfg/wm/rules/math
@@ -1,0 +1,9 @@
+# mathjax-alike
+# example: /{eqn input here}.png
+
+/([^'/]+).png		{echo .EQ ; echo '\1' ; echo .EN} | eqn | troff | dpost | gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps| crop -c 255 255 255 | topng
+/([^'/]+).bit		{echo .EQ ; echo '\1' ; echo .EN} | eqn | troff | dpost | gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps| crop -c 255 255 255
+/([^'/]+).gif		{echo .EQ ; echo '\1' ; echo .EN} | eqn | troff | dpost | gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps| crop -c 255 255 255 | togif
+/([^'/]+).(jpg|jepg)		{echo .EQ ; echo '\1' ; echo .EN} | eqn | troff | dpost | gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps| crop -c 255 255 255 | tojpg
+
+#/([0-9]+)/([^'/]+).(jpg|jepg)		{echo .EQ ; echo '\2' ; echo .EN} | eqn | troff | dpost | gs -dNOPAUSE -dQUIET '-sOUTPUTFILE='/fd/1 '-sDEVICE=inferno' - quit.ps | crop -c 255 255 255 | resize -x+'\1'% | tojpg
--- /dev/null
+++ b/plan9/cfg/wm/rules/toys
@@ -1,0 +1,3 @@
+# mathjax(?) alike,
+# see /math/'x sup 2'.gif as an example
+#/([^'/]+).gif		{echo .EQ ; echo '\1' ; echo .EN} | eqn | troff | dpost | ps2gif
--- /dev/null
+++ b/plan9/cfg/wm/rules/web
@@ -1,0 +1,13 @@
+/index.html					/bin/shithub/list	/usr/git
+([^'/]+)/usr.html				/bin/shithub/usr	/usr/git '\1'
+(/.well-known/acme-challenge/([^'/]+))		/bin/cat		/usr/web/\1
+([^'/]+)/([^'/]+)/([^'/]+)/info.html		/bin/shithub/info	/usr/git '\1' '\2' '\3'
+([^'/]+)/([^'/]+)/([^'/]+)/files.html		/bin/shithub/files	/usr/git '\1' '\2' '\3'
+([^'/]+)/([^'/]+)/([^'/]+)/branches.html	/bin/shithub/branches	/usr/git '\1' '\2' '\3'
+([^'/]+)/([^'/]+)/([^'/]+)/snap.tar.gz		/bin/shithub/tar	/usr/git '\1' '\2' '\3'
+([^'/]+)/([^'/]+)/([^'/]+)/(([^']+)/)?f.html	/bin/shithub/view	/usr/git '\1' '\2' '\3' '\5'
+([^'/]+)/([^'/]+)/([^'/]+)/(([^']+)/)?raw	/bin/shithub/viewraw	/usr/git '\1' '\2' '\3' '\5'
+([^'/]+)/([^'/]+)/([^'/]+)/log.html		/bin/shithub/log	/usr/git '\1' '\2' '\3'
+([^'/]+)/([^'/]+)/([^'/]+)/commit.html		/bin/shithub/show	/usr/git '\1' '\2' '\3'
+([^'/]+)/([^'/]+)/([^'/]+)/_patch		/bin/shithub/patch	/usr/git '\1' '\2' '\3'
+([^'/]+)/([^'/]+)/([^'/]+)/feed.rss		/bin/shithub/feed	/usr/git '\1' '\2' '\3'
--- /dev/null
+++ b/plan9/cfg/wm/service/!tcp22
@@ -1,0 +1,2 @@
+#!/bin/rc
+#exec /bin/aux/trampoline 'net!unix.cloud9p.org!ssh'
--- /dev/null
+++ b/plan9/cfg/wm/service/il17019
@@ -1,0 +1,11 @@
+#!/bin/rc
+if(~ $#* 3){
+	netdir=$3
+	remote=$2!`{cat $3/remote}
+}
+fn server {
+	~ $#remote 0 || echo -n $netdir $remote >/proc/$pid/args
+	rm -f /env/'fn#server'
+	. <{n=`{read} && ! ~ $#n 0 && read -c $n} >[2=1]
+}
+exec tlssrv -a /bin/rc -c server
--- /dev/null
+++ b/plan9/cfg/wm/service/il17031
@@ -1,0 +1,3 @@
+#!/bin/rc
+exec ramfs -i
+
--- /dev/null
+++ b/plan9/cfg/wm/service/startnfs
@@ -1,0 +1,7 @@
+#!/bin/rc
+Kill portmapper | rc
+Kill nfsserver | rc
+rm -f /srv/nfsserver.chat /srv/portmapper.chat
+aux/nfsserver -f /srv/grid.audio -c /lib/ndb/nfs >>[2] /sys/log/nfsserver
+aux/portmapper >>[2] /sys/log/portmapper
+aux/portmapper -t >>[2] /sys/log/portmapper
--- /dev/null
+++ b/plan9/cfg/wm/service/tcp17019
@@ -1,0 +1,11 @@
+#!/bin/rc
+if(~ $#* 3){
+	netdir=$3
+	remote=$2!`{cat $3/remote}
+}
+fn server {
+	~ $#remote 0 || echo -n $netdir $remote >/proc/$pid/args
+	rm -f /env/'fn#server'
+	. <{n=`{read} && ! ~ $#n 0 && read -c $n} >[2=1]
+}
+exec tlssrv -a /bin/rc -c server
--- /dev/null
+++ b/plan9/cfg/wm/service/tcp17020
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec tlssrv -A /bin/aux/trampoline 'net!$fs!9fs'
--- /dev/null
+++ b/plan9/cfg/wm/service/tcp17021
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec tlssrv -a /bin/git/serve -wr/usr/git
--- /dev/null
+++ b/plan9/cfg/wm/service/tcp443
@@ -1,0 +1,3 @@
+#!/bin/rc
+exec tlssrv -c/sys/lib/tls/acmed/cloud9p.org.crt -r`{cat $3/remote}\
+/bin/aux/trampoline net!wm!80>>[2]/sys/log/httpd/log
--- /dev/null
+++ b/plan9/cfg/wm/service/tcp53
@@ -1,0 +1,2 @@
+#!/bin/rc
+/bin/ndb/dnstcp $3
--- /dev/null
+++ b/plan9/cfg/wm/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/plan9/cfg/wm/service/tcp70
@@ -1,0 +1,9 @@
+#!/bin/rc
+mount -c /srv/grid.ramfs /tmp
+
+execfs -m /usr/pub/math /cfg/wm/rules/math
+execfs -m /usr/pub/doc /cfg/wm/rules/doc
+
+bind -ac /usr/pub /usr/web
+
+exec /bin/tcp70 $3 >>[2]/sys/log/gopher
--- /dev/null
+++ b/plan9/cfg/wm/service/tcp7777
@@ -1,0 +1,2 @@
+#!/bin/rc
+wm/pasted /usr/pub/paste
--- /dev/null
+++ b/plan9/cfg/wm/service/tcp80
@@ -1,0 +1,14 @@
+#!/bin/rc
+mount -c /srv/grid.ramfs /tmp
+
+execfs -m /n/web /cfg/wm/rules/web
+# not to overlap with static content
+bind -a /n/web/ /usr/web
+
+execfs -m /usr/pub/math /cfg/wm/rules/math
+execfs -m /usr/pub/doc  /cfg/wm/rules/doc
+
+bind -b /sys/doc /usr/pub/doc/sys
+bind -b /usr/pub /usr/web
+
+exec /bin/tcp80 $3 >>[2]/sys/log/httpd/log
--- /dev/null
+++ b/plan9/cfg/wm/service/tcp900
@@ -1,0 +1,9 @@
+#!/bin/rc
+mount -c /srv/grid.ramfs /tmp
+
+execfs -m /usr/pub/doc /cfg/wm/rules/doc
+execfs -m /usr/pub/math /cfg/wm/rules/math
+execfs -m /usr/pub/http /cfg/wm/rules/httpfs
+
+mount -bc /srv/grid.chat /usr/pub
+exec exportfs -r /usr/pub
--- /dev/null
+++ b/plan9/cfg/wm/service/tcp901
@@ -1,0 +1,2 @@
+#!/bin/rc
+exec tlssrv -A /bin/aux/trampoline 'net!$sysname!900'
--- /dev/null
+++ b/plan9/cfg/wm/service/tcp9418
@@ -1,0 +1,2 @@
+#!/bin/rc
+git/serve -r /usr/git
--- /dev/null
+++ b/plan9/chusr.c
@@ -1,0 +1,304 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <libsec.h>
+#include <authsrv.h>
+
+#define	KEYDB		"/mnt/keys"
+#define NETKEYDB	"/mnt/netkeys"
+#define KEYDBBUF	(sizeof NETKEYDB)	/* enough for any keydb prefix */
+#define AUTHLOG		"auth"
+
+enum{
+    Nemail      = 10,           /* from authcmdlib.h */
+	MAXNETCHAL	= 100000,		/* max securenet challenge */
+	Maxpath		= 256,
+};
+
+typedef struct
+{
+	char	*user;
+	char	*postid;
+	char	*name;
+	char	*dept;
+	char	*email[Nemail];
+} Acctbio;
+
+typedef struct {
+	char	*keys;
+	char	*msg;
+	char	*who;
+	Biobuf 	*b;
+} Fs;
+
+Fs fs =	{ "/mnt/keys", "plan 9 key", "/adm/keys.who", 0 };
+
+static uchar zeros[16];
+
+
+void    install(char*, char*, Authkey*, long);
+int exists(char*, char*);
+void	private(void);
+int	setkey(char*, char*, Authkey*);
+char*	setdeskey(char*, char*, char*);
+uchar*	setaeskey(char*, char*, uchar*);
+char*	setsecret(char*, char*, char*);
+void	wrbio(char*, Acctbio*);
+int	writefile(char*, char*, int);
+int	deskeyfmt(Fmt*);
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-d dept] [-e email] [-i postid] [-s sponsor\'s email] -p pass user\n", argv0);
+	exits("usage");
+}
+
+void
+main(int argc, char *argv[])
+{
+    int debug = 1;
+	char *u, *pass = "";
+	Authkey key;
+	Acctbio a;
+	Fs *f;
+
+	fmtinstall('K', deskeyfmt);
+
+	ARGBEGIN{
+        case 'D':
+            debug = 1;
+            break;
+
+        case 'd':
+            a.dept = EARGF(usage());
+            break;
+
+        case 'i':
+            a.postid = EARGF(usage());
+            break;
+
+        case 'e':
+            a.email[0] = EARGF(usage());
+            break;
+
+        case 'p':
+            pass = EARGF(usage());
+            break;
+
+        case 's':
+            a.email[1] = EARGF(usage());
+            break;
+
+        default:
+            usage();
+
+	}ARGEND
+
+	if(utflen(pass) < 8)
+        usage();
+
+	u = argv[0];
+
+	if(memchr(u, '\0', ANAMELEN) == 0)
+		sysfatal("bad user name");
+    if(!debug)
+	   private();
+
+	a.user = u;
+	memset(&key, 0, sizeof(key));
+	f = &fs;
+
+	passtokey(&key, pass);
+
+	install(f->keys, u, &key, 0);
+
+	if(setsecret(KEYDB, u, pass) == 0)
+		sysfatal("error writing Inferno/POP secret");
+
+	wrbio(f->who, &a);
+
+	print("user %s installed for Plan 9\n", u);
+	syslog(0, AUTHLOG, "user %s installed for plan 9", u);
+
+	exits(0);
+}
+
+void
+install(char *db, char *u, Authkey *key, long t)
+{
+	char buf[KEYDBBUF+ANAMELEN+20];
+	int fd;
+
+	if(!exists(db, u)){
+		snprint(buf, sizeof(buf), "%s/%s", db, u);
+		fd = create(buf, OREAD, 0777|DMDIR);
+		if(fd < 0)
+			sysfatal("can't create user %s: %r", u);
+		close(fd);
+	}
+
+	if(!setkey(db, u, key))
+		sysfatal("can't set key: %r");
+
+	if(t == -1)
+		return;
+	snprint(buf, sizeof(buf), "%s/%s/expire", db, u);
+	fd = open(buf, OWRITE);
+	if(fd < 0 || fprint(fd, "%ld", t) < 0)
+		sysfatal("can't write expiration time");
+	close(fd);
+}
+
+int
+exists(char *db, char *u)
+{
+	char buf[KEYDBBUF+ANAMELEN+6];
+
+	snprint(buf, sizeof(buf), "%s/%s/expire", db, u);
+	if(access(buf, 0) < 0)
+		return 0;
+	return 1;
+}
+
+
+/* these functions are from /sys/src/cmd/auth/lib/ */
+
+int
+deskeyfmt(Fmt *f)
+{
+	uchar key[8];
+	char buf[32];
+	uchar *k;
+	int i;
+
+	k = va_arg(f->args, uchar*);
+	key[0] = 0;
+	for(i = 0; i < 7; i++){
+		key[i] |= k[i] >> i;
+		key[i] &= ~1;
+		key[i+1] = k[i] << (7 - i);
+	}
+	key[7] &= ~1;
+	sprint(buf, "%.3uo %.3uo %.3uo %.3uo %.3uo %.3uo %.3uo %.3uo",
+		key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]);
+	fmtstrcpy(f, buf);
+	return 0;
+}
+
+/* don't allow other processes to debug us and steal keys */
+void
+private(void)
+{
+	int fd;
+	char buf[32];
+	static char pmsg[] = "Warning! %s can't protect itself from debugging: %r\n";
+	static char smsg[] = "Warning! %s can't turn off swapping: %r\n";
+
+	snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
+	fd = open(buf, OWRITE|OCEXEC);
+	if(fd < 0){
+		fprint(2, pmsg, argv0);
+		return;
+	}
+	if(fprint(fd, "private") < 0)
+		fprint(2, pmsg, argv0);
+	if(fprint(fd, "noswap") < 0)
+		fprint(2, smsg, argv0);
+	close(fd);
+}
+
+int
+setkey(char *db, char *user, Authkey *key)
+{
+	int ret;
+
+	ret = setdeskey(db, user, key->des) != nil;
+	if(tsmemcmp(key->aes, zeros, AESKEYLEN) != 0)
+		ret |= setaeskey(db, user, key->aes) != nil;
+	return ret;
+}
+
+char*
+setdeskey(char *db, char *user, char *key)
+{
+	char filename[Maxpath];
+
+	snprint(filename, sizeof filename, "%s/%s/key", db, user);
+	if(writefile(filename, key, DESKEYLEN) != DESKEYLEN)
+		return nil;
+	return key;
+}
+
+uchar*
+setaeskey(char *db, char *user, uchar *key)
+{
+	char filename[Maxpath];
+
+	snprint(filename, sizeof filename, "%s/%s/aeskey", db, user);
+	if(writefile(filename, (char*)key, AESKEYLEN) != AESKEYLEN)
+		return nil;
+	return key;
+}
+
+char*
+setsecret(char *db, char *user, char *secret)
+{
+	char filename[Maxpath];
+
+	snprint(filename, sizeof filename, "%s/%s/secret", db, user);
+	if(writefile(filename, secret, strlen(secret)) != strlen(secret))
+		return nil;
+	return secret;
+}
+
+void
+wrbio(char *file, Acctbio *a)
+{
+	char buf[1024];
+	int i, fd, n;
+
+	fd = open(file, OWRITE);
+	if(fd < 0){
+		fd = create(file, OWRITE, 0660);
+		if(fd < 0)
+			sysfatal("can't create %s", file);
+	}
+	if(seek(fd, 0, 2) < 0)
+		sysfatal("can't seek %s", file);
+
+	if(a->postid == 0)
+		a->postid = "";
+	if(a->name == 0)
+		a->name = "";
+	if(a->dept == 0)
+		a->dept = "";
+	if(a->email[0] == 0)
+		a->email[0] = strdup(a->user);
+
+	n = 0;
+	n += snprint(buf+n, sizeof(buf)-n, "%s|%s|%s|%s",
+		a->user, a->postid, a->name, a->dept);
+	for(i = 0; i < Nemail; i++){
+		if(a->email[i] == 0)
+			break;
+		n += snprint(buf+n, sizeof(buf)-n, "|%s", a->email[i]);
+	}
+	n += snprint(buf+n, sizeof(buf)-n, "\n");
+
+	write(fd, buf, n);
+	close(fd);
+}
+
+int
+writefile(char *file, char *buf, int n)
+{
+	int fd;
+
+	fd = open(file, OWRITE);
+	if(fd < 0)
+		return -1;
+	n = write(fd, buf, n);
+	close(fd);
+	return n;
+}
--- /dev/null
+++ b/plan9/doc/html
@@ -1,0 +1,45 @@
+#!/bin/rc -e
+
+. /sys/lib/shithub/common.rc
+
+cd $1
+shift
+
+rfork ne
+nl='
+'
+
+gituser=$1
+repo=$2
+refname=$3
+file=$4
+
+repons $gituser $repo
+if(! ref=`{resolveref $refname}){
+	echo '<b>invalid ref '$refname'</b>'
+	exit
+}
+
+if(! test -d $gitfs/$ref/tree){
+	echo '	<p>No code pushed</p>
+		</body>
+		</html>
+	'
+	exit
+}
+
+cd $gitfs/$ref/tree
+
+echo '	<p>'
+
+echo '<p><div id="content">'
+
+if(test -r $gitfs/$ref/tree/$file.wms)
+	wm/doc/wiki2ms $gitfs/$ref/tree/$file.wms | ms2html
+if not
+	ms2html < $gitfs/$ref/tree/$file.ms
+	
+echo '	</div>
+	</p>
+	</body>
+	</html>'
--- /dev/null
+++ b/plan9/doc/pdf
@@ -1,0 +1,32 @@
+#!/bin/rc -e
+
+. /sys/lib/shithub/common.rc
+
+cd $1
+shift
+
+rfork ne
+nl='
+'
+
+gituser=$1
+repo=$2
+refname=$3
+file=$4
+
+repons $gituser $repo
+if(! ref=`{resolveref $refname}){
+	echo 'Invalid ref '$refname''
+	exit
+}
+
+if(! test -d $gitfs/$ref/tree){
+	echo 'No such document'
+	exit
+}
+
+cd $gitfs/$ref/tree
+if(test -r $gitfs/$ref/tree/$file.wms)
+	wm/doc/wiki2ms $gitfs/$ref/tree/$file.wms | troff -ms | dpost | ps2pdf
+if not
+	troff -ms $gitfs/$ref/tree/$file.ms | dpost | ps2pdf
--- /dev/null
+++ b/plan9/doc/ps
@@ -1,0 +1,32 @@
+#!/bin/rc -e
+
+. /sys/lib/shithub/common.rc
+
+cd $1
+shift
+
+rfork ne
+nl='
+'
+
+gituser=$1
+repo=$2
+refname=$3
+file=$4
+
+repons $gituser $repo
+if(! ref=`{resolveref $refname}){
+	echo 'Invalid ref '$refname''
+	exit
+}
+
+if(! test -d $gitfs/$ref/tree){
+	echo 'No such document'
+	exit
+}
+
+cd $gitfs/$ref/tree
+if(test -r $gitfs/$ref/tree/$file.wms)
+	wm/doc/wiki2ms $gitfs/$ref/tree/$file.wms | troff -ms | dpost
+if not
+	troff -ms $gitfs/$ref/tree/$file.ms | dpost
--- /dev/null
+++ b/plan9/doc/txt
@@ -1,0 +1,32 @@
+#!/bin/rc -e
+
+. /sys/lib/shithub/common.rc
+
+cd $1
+shift
+
+rfork ne
+nl='
+'
+
+gituser=$1
+repo=$2
+refname=$3
+file=$4
+
+repons $gituser $repo
+if(! ref=`{resolveref $refname}){
+	echo 'Invalid ref '$refname''
+	exit
+}
+
+if(! test -d $gitfs/$ref/tree){
+	echo 'No such document'
+	exit
+}
+
+cd $gitfs/$ref/tree
+if(test -r $gitfs/$ref/tree/$file.wms)
+	wm/doc/wiki2ms $gitfs/$ref/tree/$file.wms | nroff -ms | col -bf
+if not
+	nroff -ms $gitfs/$ref/tree/$file.ms | col -bf
--- /dev/null
+++ b/plan9/doc/weblist
@@ -1,0 +1,60 @@
+#!/bin/rc -e
+
+. /sys/lib/shithub/common.rc
+
+rfork ne
+nl='
+'
+cd $1
+shift
+
+rfork ne
+nl='
+'
+
+gituser=$1
+repo=$2
+ref=$3
+
+repons $gituser $repo
+
+prelude '' 'Documents'
+#echo '<img src="/static/'$logo'" /><br/>'
+
+if(~ $#intro 0)
+	echo '<h2>Documents</h2><br>'
+
+echo $ref
+cd $gitfs/$ref/tree
+udir=()
+for(doc in `$nl{ls -Q *}){
+	ndir=`{basename -d $doc}
+	if(~ $ndir .)
+		ndir=Root
+	if(! ~ $udir $ndir)
+		echo '</dl>'
+	if(! ~ $udir $ndir){
+		echo '<h3>'$ndir'</h3>'
+		echo '<dl>'
+		udir=$ndir
+	}
+
+	echo '<dt>'
+
+	title = `{grep '.TL$^(.+)' $doc | sed 2p}
+	filename = `{echo $doc | sed s/'(.+).ms'/\1/g}
+
+	if(! ~ $#title 0)
+		echo '<h6>'$filename': '$"title'</h6>'
+	if not
+		echo '<h6>'$filename'</h6>'	
+	echo '</dt><dd>'
+	echo '[<a href="'$filename^.html'">html</a>]'
+	echo '[<a href="'$filename^.txt'">txt</a>]'
+	echo '</dd>'
+}
+echo '
+</div>
+</p>
+</body>
+</html>'
--- /dev/null
+++ b/plan9/doc/wiki2ms
@@ -1,0 +1,145 @@
+#!/bin/rc
+nl='
+'
+file=$1
+url=$2
+# wiki2ms
+# convert from wikifs(6) format to ms format
+# usage:
+#	wiki2ms document.wiki https://cloud9p.org/man # normal wiki text
+#	wiki2ms document.wms https://cloud9p.org/man # wiki with ms macros
+# bugs:
+# man page linking is better to be optional
+# very wasteful
+# ms output could've been better
+# some of wikifs functionality is not yet implmented:
+# proper parsing for links
+
+fn quote {
+	echo $1 | sed 's/\//\\\//g' | sed 's/\./\\\./g'
+}
+
+fn comment {
+	ifs=$nl
+	for(i in `{cat}){
+		if(! ~ $i '#'*)
+			echo $i	
+	}
+}
+
+fn removebang {
+	# wasteful, i know
+	echo $1 | sed 's/^(! |!)//g'
+}
+
+fn monospace {
+	ifs=$nl
+	mono=f
+	for(i in `{cat}){
+		if(~ $i !*){
+			if(~ $mono f){
+				mono=t
+				echo '.P1'
+			}
+			removebang $i
+		}
+		if not {
+			if(~ $mono t) {
+				mono=f
+				echo '.P2'
+			}
+			echo $i
+		}
+	}
+	# last line may be a ! line.
+	if(~ $mono t){
+		mono=f
+		echo '.P2'	
+	}
+}
+
+fn directlink {
+	ifs=$nl
+	mono=f
+	for(i in `{cat}){
+		if(~ $i .P1){
+			mono=t
+			echo $i
+		}
+		if not if(~ $i .P2){
+			mono=f
+			echo $i
+		}
+		if not if(~ $mono f)
+			echo $i | sed 's/\[([^\n]+)\|([^\n]+)\]/\n\.LN \2\n\1\n\.LN\n/g'
+		if not
+			echo $i
+	}	
+}
+
+fn indirectlink {
+	ifs=$nl
+	mono=f
+	for(i in `{cat}){
+		if(~ $i .P1){
+			mono=t
+			echo $i
+		}
+		if not if(~ $i .P2){
+			mono=f
+			echo $i
+		}
+		if not if(~ $mono f)
+			echo $i | sed 's/\[([^\n]+)\]/\n\.LN \1\n\1\n\.LN\n/g'
+		if not
+			echo $i
+	}
+}
+
+fn manpage {
+	ifs=$nl
+	mono=f
+	for(i in `{cat}){
+		if(~ $i .P1){
+			mono=t
+			echo $i
+		}
+		if not if(~ $i .P2){
+			mono=f
+			echo $i
+		}
+		if not if(~ $mono f)
+			echo $i | sed 's/([^ ]+)\(([0-9])\)/\n\.LN '^$url^'\2\/\1\n\1\(\2\)\n\.LN\n/g'
+		if not
+			echo $i
+	}
+}
+
+url=`{quote $url}
+
+cat $1 |
+
+# paragraphs
+sed 's/^$/.LP/g' |
+
+# comments
+comment | 
+
+# titles
+sed 's/^((([A-Z]| |-|_|\(|\)))+)$/\.SH\n\1\n\.LP/g' |
+
+# bulleted lists
+sed 's/(^\* )|(^\*)/\.IP \\(bu\n/g' |
+
+# monospaced block
+monospace |
+
+# direct links ([x|y] form)
+directlink |
+
+# indirect links ([x] form)
+indirectlink | 
+
+# man pages, TODO: enable it later
+#manpage
+cat
--- /dev/null
+++ b/plan9/mkfile
@@ -1,0 +1,34 @@
+< /$objtype/mkfile
+#BIN=$home
+BIN=/$objtype/bin/wm
+
+TARG=\
+    chusr\
+
+RC=\
+	newuser\
+	pasted\
+	getaudio\
+	doc/html\
+	doc/pdf\
+	doc/ps\
+	doc/txt\
+	doc/weblist\
+	doc/wiki2ms\
+
+</sys/src/cmd/mkmany
+
+install:V:
+	mkdir -p $BIN $BIN/doc
+	for (i in $TARG)
+		mk $MKFLAGS $i.install
+	for (i in $RC)
+		mk $MKFLAGS $i.rcinstall
+
+%.rcinstall:V:
+	cp $stem $BIN/$stem
+
+$BIN:
+	mkdir -p $BIN
+
+
--- /dev/null
+++ b/plan9/newuser
@@ -1,0 +1,65 @@
+#!/bin/rc
+run_newuser=t
+args=()
+
+fn usage {
+	echo 'usage: newuser [-n] [-d dept] [-e email] [-i postid] [-s sponsormail] user [pass]' >[1=2]
+	exit 'usage'
+}
+
+fn newu {
+	u=$1
+	p=$2
+
+	auth/keyfs
+
+	if(test -w /srv/cwfs.cmd){
+	echo newuser $u >> /srv/cwfs.cmd
+	wm/chusr $args -p $p $u
+	if(~ $run_newuser t) {
+		# auth/as $u /sys/lib/newuser # messes up with namespace
+		if(! test -f /env/authdom)
+			authdom=`{ndb/query sys $sysname authdom}
+
+		if(! test -f /env/authdom) {
+					echo 'newuser: no authdom variable or entry in ndb' >[1=2]
+					exit 'no authdom'
+		}
+		echo 'key user='$u' proto=dp9ik dom='$authdom' role=client !password='$p >/mnt/factotum/ctl
+		rcpu -u $u -c /sys/lib/newuser
+	}
+	auth/enable $u
+	}
+
+	if not {
+		echo 'no cwfs.cmd or access to it'>[2=1]
+		exit 'no cwfs.cmd or access to it'
+	}
+}
+
+while (~ $1 -*) {
+	switch ($1) {
+		case -[sdier]
+                        if(~ $#x 0)
+				args=$args $1 $2
+        		shift
+		case -n
+			run_newuser=f
+		case -*
+	 		usage
+	}
+	shift
+}
+
+if (~ $#* 1) {
+	pass=`{fortune /lib/dict/pgwindex | awk '{ print $1 }'}
+	pass=($pass^`{fortune /lib/dict/pgwindex | awk '{ print $1 }'})
+	echo password: $"pass
+	newu $1 $pass
+}
+
+if (~ $#* 2)
+	newu $1 $2
+if not
+    usage
+
--- /dev/null
+++ b/plan9/pasted
@@ -1,0 +1,20 @@
+#!/bin/rc
+# wm/pasted path
+# a simple pastebin, use with aux/listen
+if(! ~ $#* 1) {
+	echo 'usage: wm/pasted user' >[1=2]
+	exit usage
+}
+
+# not to override files
+fn genrand {
+	dir = $1
+	rand = `{dd -quiet 1 -if /dev/random -bs 1 -count 2 | xd -1 | awk '{$1=""; print $0}' | tr -d ' '}
+	if(test -e $dir/$rand){
+		genrand
+	}
+}
+
+genrand $1
+echo $rand
+read -m -c `{echo '1024 * 1024 * 10'| bc} > $dir/$rand
--