maintain $path and $PATH simultaneously
diff --git a/src/cmd/rc/exec.c b/src/cmd/rc/exec.c
index ebed11d..9ab7c29 100644
--- a/src/cmd/rc/exec.c
+++ b/src/cmd/rc/exec.c
@@ -117,6 +117,7 @@
 	Trapinit();
 	Vinit();
 	itoa(num, mypid=getpid());
+	pathinit();
 	setvar("pid", newword(num, (word *)0));
 	setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
 				:(word *)0);
@@ -369,7 +370,7 @@
 	runq->pc++;
 	poplist();
 }
-char *list2str(word *words){
+char *_list2str(word *words, int c){
 	char *value, *s, *t;
 	int len=0;
 	word *ap;
@@ -379,12 +380,15 @@
 	s=value;
 	for(ap=words;ap;ap=ap->next){
 		for(t=ap->word;*t;) *s++=*t++;
-		*s++=' ';
+		*s++=c;
 	}
 	if(s==value) *s='\0';
 	else s[-1]='\0';
 	return value;
 }
+char *list2str(word *words){
+	return _list2str(words, ' ');
+}
 void Xmatch(void){
 	word *p;
 	char *subject;
@@ -464,6 +468,8 @@
 	freewords(v->val);
 	v->val=runq->argv->words;
 	v->changed=1;
+	if(v->changefn)
+		v->changefn(v);
 	runq->argv->words=0;
 	poplist();
 }
diff --git a/src/cmd/rc/fns.h b/src/cmd/rc/fns.h
index 4c8be10..b9e5cb7 100644
--- a/src/cmd/rc/fns.h
+++ b/src/cmd/rc/fns.h
@@ -27,6 +27,7 @@
 void	codefree(code*);
 int	compile(tree*);
 char *	list2str(word*);
+char *	_list2str(word*, int);
 int	count(word*);
 void	deglob(char*);
 void	dotrap(void);
@@ -39,6 +40,7 @@
 int	match(char*, char*, int);
 int	matchfn(char*, char*);
 void	panic(char*, int);
+void	pathinit(void);
 void	poplist(void);
 void	popword(void);
 void	pprompt(void);
@@ -48,6 +50,7 @@
 void	readhere(void);
 void	setstatus(char*);
 void	setvar(char*, word*);
+void	_setvar(char*, word*, int);
 void	skipnl(void);
 void	start(code*, int, var*);
 int	truestatus(void);
diff --git a/src/cmd/rc/rc.h b/src/cmd/rc/rc.h
index 9a73927..b7edbac 100644
--- a/src/cmd/rc/rc.h
+++ b/src/cmd/rc/rc.h
@@ -84,6 +84,7 @@
 	int fnchanged;
 	int pc;			/* pc of start of function */
 	var *next;	/* next on hash or local list */
+	void	(*changefn)(var*);
 };
 var *vlook(char*), *gvlook(char*), *newvar(char*, var*);
 #define	NVAR	521
diff --git a/src/cmd/rc/simple.c b/src/cmd/rc/simple.c
index 5318c9f..a65bec2 100644
--- a/src/cmd/rc/simple.c
+++ b/src/cmd/rc/simple.c
@@ -168,7 +168,7 @@
 		if(cdpath==0) pfmt(err, "Can't cd %s: %r\n", a->next->word);
 		break;
 	case 1:
-		a=vlook("home")->val;
+		a=vlook("HOME")->val;
 		if(count(a)>=1){
 			if(dochdir(a->word)>=0)
 				setstatus("");
diff --git a/src/cmd/rc/var.c b/src/cmd/rc/var.c
index 73e4e9a..8a200ff 100644
--- a/src/cmd/rc/var.c
+++ b/src/cmd/rc/var.c
@@ -62,10 +62,70 @@
 			if(strcmp(v->name, name)==0) return v;
 	return gvlook(name);
 }
-void setvar(char *name, word *val)
+void _setvar(char *name, word *val, int callfn)
 {
 	register struct var *v=vlook(name);
 	freewords(v->val);
 	v->val=val;
 	v->changed=1;
+	if(callfn && v->changefn)
+		v->changefn(v);
+}
+void setvar(char *name, word *val)
+{
+	_setvar(name, val, 1);
+}
+void bigpath(var *v)
+{
+	/* convert $PATH to $path */
+	char *p, *q;
+	word **l, *w;
+
+	if(v->val == nil){
+		_setvar("path", nil, 0);
+		return;
+	}
+	p = v->val->word;
+	w = nil;
+	l = &w;
+	/*
+	 * Doesn't handle escaped colon nonsense.
+	 */
+	if(p[0] == 0)
+		p = nil;
+	while(p){
+		q = strchr(p, ':');
+		if(q)
+			*q = 0;
+		*l = newword(p[0] ? p : ".", nil);
+		l = &(*l)->next;
+		if(q){
+			*q = ':';
+			p = q+1;
+		}else
+			p = nil;
+	}
+	_setvar("path", w, 0);
+}
+void littlepath(var *v)
+{
+	/* convert $path to $PATH */
+	char *p;
+	word *w;
+
+	p = _list2str(v->val, ':');
+	w = new(word);
+	w->word = p;
+	w->next = nil;
+	_setvar("PATH", w, 1);	/* 1: recompute $path to expose colon problems */
+}
+void pathinit(void)
+{
+	var *v;
+
+	v = gvlook("path");
+	v->changefn = littlepath;
+	v = gvlook("PATH");
+	v->changefn = bigpath;
+	bigpath(v);
 }