add ulimit and umask as builtins
diff --git a/src/cmd/rc/mkfile b/src/cmd/rc/mkfile
index f7d50e3..09478dc 100644
--- a/src/cmd/rc/mkfile
+++ b/src/cmd/rc/mkfile
@@ -17,6 +17,7 @@
 	subr.$O\
 	trap.$O\
 	tree.$O\
+	unixcrap.$O\
 	var.$O\
 	y.tab.$O\
 	plan9ish.$O\
diff --git a/src/cmd/rc/plan9ish.c b/src/cmd/rc/plan9ish.c
index af1e449..bd9698c 100644
--- a/src/cmd/rc/plan9ish.c
+++ b/src/cmd/rc/plan9ish.c
@@ -34,6 +34,8 @@
 void execfinit(void);
 void execbind(void);
 void execmount(void);
+void execulimit(void);
+void execumask(void);
 builtin Builtin[]={
 	"cd",		execcd,
 	"whatis",	execwhatis,
@@ -45,6 +47,8 @@
 	".",		execdot,
 	"finit",	execfinit,
 	"flag",		execflag,
+	"ulimit",	execulimit,
+	"umask",	execumask,
 	0
 };
 #define	SEP	'\1'
diff --git a/src/cmd/rc/unixcrap.c b/src/cmd/rc/unixcrap.c
new file mode 100644
index 0000000..57da10e
--- /dev/null
+++ b/src/cmd/rc/unixcrap.c
@@ -0,0 +1,197 @@
+#include <u.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <libc.h>
+#include "rc.h"
+#include "exec.h"
+#include "io.h"
+#include "fns.h"
+#include "getflags.h"
+
+extern char **mkargv(word*);
+extern int mapfd(int);
+
+static char *eargs = "cdflmnstuv";
+static int rlx[] = {
+	RLIMIT_CORE,
+	RLIMIT_DATA,
+	RLIMIT_FSIZE,
+	RLIMIT_MEMLOCK,
+	RLIMIT_RSS,
+	RLIMIT_NOFILE,
+	RLIMIT_STACK,
+	RLIMIT_CPU,
+	RLIMIT_NPROC,
+	RLIMIT_RSS,
+};
+
+static void
+eusage(void)
+{
+	fprint(mapfd(2), "usage: ulimit [-SHa%s [limit]]\n", eargs);
+}
+
+#define Notset -4
+#define Unlimited -3
+#define Hard -2
+#define Soft -1
+
+void
+execulimit(void)
+{
+	int fd, n, argc, sethard, setsoft, limit;
+	int flag[256];
+	char **argv, **oargv, *p;
+	char *argv0;
+	struct rlimit rl;
+
+	argv0 = nil;
+	setstatus("");
+	oargv = mkargv(runq->argv->words);
+	argv = oargv+1;
+	for(argc=0; argv[argc]; argc++)
+		;
+
+	memset(flag, 0, sizeof flag);
+	ARGBEGIN{
+	default:
+		if(strchr(eargs, ARGC()) == nil){
+			eusage();
+			return;
+		}
+	case 'S':
+	case 'H':
+	case 'a':
+		flag[ARGC()] = 1;
+		break;
+	}ARGEND
+
+	if(argc > 1){
+		eusage();
+		goto out;
+	}
+
+	fd = mapfd(1);
+
+	sethard = 1;
+	setsoft = 1;
+	if(flag['S'] && flag['H'])
+		;
+	else if(flag['S'])
+		sethard = 0;
+	else if(flag['H'])
+		setsoft = 0;
+
+	limit = Notset;
+	if(argc>0){
+		if(strcmp(argv[0], "unlimited") == 0)
+			limit = Unlimited;
+		else if(strcmp(argv[0], "hard") == 0)
+			limit = Hard;
+		else if(strcmp(argv[0], "soft") == 0)
+			limit = Soft;
+		else if((limit = strtol(argv[0], &p, 0)) < 0 || *p != 0){
+			eusage();
+			goto out;
+		}
+	}
+	if(flag['a']){
+		for(p=eargs; *p; p++){
+			getrlimit(rlx[p-eargs], &rl);
+			n = flag['H'] ? rl.rlim_max : rl.rlim_cur;
+			if(n == -1)
+				fprint(fd, "ulimit -%c unlimited\n", *p);
+			else
+				fprint(fd, "ulimit -%c %d\n", *p, n);
+		}
+		goto out;
+	}
+	for(p=eargs; *p; p++){
+		if(flag[(uchar)*p]){
+			n = 0;
+			getrlimit(rlx[p-eargs], &rl);
+			switch(limit){
+			case Notset:
+				n = flag['H'] ? rl.rlim_max : rl.rlim_cur;
+				if(n == -1)
+					fprint(fd, "ulimit -%c unlimited\n", *p);
+				else
+					fprint(fd, "ulimit -%c %d\n", *p, n);
+				break;
+			case Hard:
+				n = rl.rlim_max;
+				goto set;
+			case Soft:
+				n = rl.rlim_cur;
+				goto set;
+			case Unlimited:
+				n = -1;
+				goto set;
+			default:
+				n = limit;
+			set:
+				if(setsoft)
+					rl.rlim_cur = n;
+				if(sethard)
+					rl.rlim_max = n;
+				if(setrlimit(rlx[p-eargs], &rl) < 0)
+					fprint(mapfd(2), "setrlimit: %r\n");
+			}
+		}
+	}
+
+out:
+	free(oargv);
+	poplist();
+	flush(err);
+}
+
+void
+execumask(void)
+{
+	int n, argc;
+	char **argv, **oargv, *p;
+	char *argv0;
+
+	argv0 = nil;
+	setstatus("");
+	oargv = mkargv(runq->argv->words);
+	argv = oargv+1;
+	for(argc=0; argv[argc]; argc++)
+		;
+
+	ARGBEGIN{
+	default:
+	usage:
+		fprint(mapfd(2), "usage: umask [mode]\n");
+		goto out;
+	}ARGEND
+
+	if(argc > 1)
+		goto usage;
+
+	if(argc == 1){
+		n = strtol(argv[0], &p, 8);
+		if(*p != 0 || p == argv[0])
+			goto usage;
+		if(umask(n) < 0){
+			fprint(mapfd(2), "umask: %r\n");
+			goto out;
+		}
+		goto out;
+	}
+
+	n = umask(0);
+	umask(n);
+	if(n < 0){
+		fprint(mapfd(2), "umask: %r\n");
+		goto out;
+	}
+
+	fprint(mapfd(1), "umask %03o\n", n);
+
+out:
+	free(oargv);
+	poplist();
+	flush(err);
+}