Index: trunk/src/kash/Makefile.kmk
===================================================================
--- trunk/src/kash/Makefile.kmk	(revision 1196)
+++ trunk/src/kash/Makefile.kmk	(revision 1198)
@@ -35,19 +35,20 @@
 	error.c \
 	eval.c \
+	histedit.c \
+	mail.c \
+	memalloc.c \
+	mystring.c \
+	options.c \
+	show.c \
+	syntax.c \
+	\
+	output.c \
 	exec.c \
 	expand.c \
-	histedit.c \
 	input.c \
 	jobs.c \
-	mail.c \
-	memalloc.c \
 	miscbltin.c \
-	mystring.c \
-	options.c \
-	output.c \
 	parser.c \
 	redir.c \
-	show.c \
-	syntax.c \
 	trap.c \
 	var.c \
@@ -106,5 +107,5 @@
 # Use the pregenerated code.
 #
-kmk_ash_DEPS := 
+kmk_ash_DEPS :=
 
 define def_copy_generated
@@ -119,5 +120,5 @@
 
 kmk_ash_INCS += generated
-kmk_ash_DEFS += HAVE_SYS_CDEFS_H 
+kmk_ash_DEFS += HAVE_SYS_CDEFS_H
 
 include $(PATH_KBUILD)/footer.kmk
Index: trunk/src/kash/alias.c
===================================================================
--- trunk/src/kash/alias.c	(revision 1196)
+++ trunk/src/kash/alias.c	(revision 1198)
@@ -105,5 +105,5 @@
 #else /* hack */
 	{
-	int len = strlen(val);
+	size_t len = strlen(val);
 	ap->val = ckmalloc(len + 2);
 	memcpy(ap->val, val, len);
Index: trunk/src/kash/cd.c
===================================================================
--- trunk/src/kash/cd.c	(revision 1196)
+++ trunk/src/kash/cd.c	(revision 1198)
@@ -86,5 +86,5 @@
 	char *p, *d;
 	struct stat statb;
-	int print = psh->cdprint;	/* set -cdprint to enable */
+	int print = cdprint(psh);	/* set -cdprint to enable */
 
 	nextopt(psh, nullstr);
@@ -171,7 +171,7 @@
 	psh->cdcomppath = stalloc(psh, strlen(dest) + 1);
 	scopy(dest, psh->cdcomppath);
-	STARTSTACKSTR(p);
+	STARTSTACKSTR(psh, p);
 	if (IS_ROOT(dest)) {
-		STPUTC('/', p);
+		STPUTC(psh, '/', p);
 		psh->cdcomppath++;
 	}
@@ -181,13 +181,13 @@
 			continue;
 		if (! first)
-			STPUTC('/', p);
+			STPUTC(psh, '/', p);
 		first = 0;
 		component = q;
 		while (*q)
-			STPUTC(*q++, p);
+			STPUTC(psh, *q++, p);
 		if (equal(component, ".."))
 			continue;
-		STACKSTRNUL(p);
-		if ((shfile_lstat(&psh->fdtab, stackblock(), &statb) < 0)
+		STACKSTRNUL(psh, p);
+		if ((shfile_lstat(&psh->fdtab, stackblock(psh), &statb) < 0)
 		    || (S_ISLNK(statb.st_mode)))  {
 			/* print = 1; */
@@ -204,5 +204,5 @@
 	updatepwd(psh, badstat ? NULL : dest);
 	INTON;
-	if (print && psh->iflag && psh->curdir)
+	if (print && iflag(psh) && psh->curdir)
 		out1fmt(psh, "%s\n", psh->curdir);
 	return 0;
@@ -272,29 +272,29 @@
 	psh->cdcomppath = stalloc(psh, strlen(dir) + 1);
 	scopy(dir, psh->cdcomppath);
-	STARTSTACKSTR(new);
+	STARTSTACKSTR(psh, new);
 	if (!IS_ROOT(dir)) {
 		p = psh->curdir;
 		while (*p)
-			STPUTC(*p++, new);
+			STPUTC(psh, *p++, new);
 		if (p[-1] == '/')
-			STUNPUTC(new);
+			STUNPUTC(psh, new);
 	}
 	while ((p = getcomponent(psh)) != NULL) {
 		if (equal(p, "..")) {
-			while (new > stackblock() && (STUNPUTC(new), *new) != '/');
+			while (new > stackblock(psh) && (STUNPUTC(psh, new), *new) != '/');
 		} else if (*p != '\0' && ! equal(p, ".")) {
-			STPUTC('/', new);
+			STPUTC(psh, '/', new);
 			while (*p)
-				STPUTC(*p++, new);
-		}
-	}
-	if (new == stackblock())
-		STPUTC('/', new);
-	STACKSTRNUL(new);
+				STPUTC(psh, *p++, new);
+		}
+	}
+	if (new == stackblock(psh))
+		STPUTC(psh, '/', new);
+	STACKSTRNUL(psh, new);
 	INTOFF;
 	if (psh->prevdir)
 		ckfree(psh->prevdir);
 	psh->prevdir = psh->curdir;
-	psh->curdir = savestr(stackblock());
+	psh->curdir = savestr(stackblock(psh));
 	setvar(psh, "PWD", psh->curdir, VEXPORT);
 	INTON;
Index: trunk/src/kash/error.c
===================================================================
--- trunk/src/kash/error.c	(revision 1196)
+++ trunk/src/kash/error.c	(revision 1198)
@@ -116,5 +116,5 @@
 	sh_sigemptyset(&nsigset);
 	sh_sigprocmask(psh, SIG_SETMASK, &nsigset, NULL);
-	if (psh->rootshell && psh->iflag)
+	if (psh->rootshell && iflag(psh))
 		exraise(psh, EXINT);
 	else {
Index: trunk/src/kash/eval.c
===================================================================
--- trunk/src/kash/eval.c	(revision 1196)
+++ trunk/src/kash/eval.c	(revision 1198)
@@ -125,11 +125,11 @@
 
 RESET {
-	evalskip = 0;
-	loopnest = 0;
-	funcnest = 0;
+	psh->evalskip = 0;
+	psh->loopnest = 0;
+	psh->funcnest = 0;
 }
 
 SHELLPROC {
-	exitstatus = 0;
+	psh->exitstatus = 0;
 }
 #endif
@@ -176,15 +176,15 @@
                 p = argv[1];
                 if (argc > 2) {
-                        STARTSTACKSTR(concat);
+                        STARTSTACKSTR(psh, concat);
                         ap = argv + 2;
                         for (;;) {
                                 while (*p)
-                                        STPUTC(*p++, concat);
+                                        STPUTC(psh, *p++, concat);
                                 if ((p = *ap++) == NULL)
                                         break;
-                                STPUTC(' ', concat);
+                                STPUTC(psh, ' ', concat);
                         }
-                        STPUTC('\0', concat);
-                        p = grabstackstr(concat);
+                        STPUTC(psh, '\0', concat);
+                        p = grabstackstr(psh, concat);
                 }
                 evalstring(psh, p, EV_TESTED);
@@ -594,5 +594,5 @@
 				shfile_close(&psh->fdtab, pip[1]);
 			}
-			psh->eflag = 0;
+			eflag(psh) = 0;
 			evaltree(psh, n, EV_EXIT);
 			/* NOTREACHED */
@@ -765,10 +765,10 @@
 	*argv = NULL;
 	lastarg = NULL;
-	if (psh->iflag && psh->funcnest == 0 && argc > 0)
+	if (iflag(psh) && psh->funcnest == 0 && argc > 0)
 		lastarg = argv[-1];
 	argv -= argc;
 
 	/* Print the command if xflag is set. */
-	if (psh->xflag) {
+	if (xflag(psh)) {
 		char sep = 0;
 		out2str(psh, ps4val(psh));
@@ -1062,5 +1062,5 @@
 		if (flags == EV_BACKCMD) {
 			backcmd->buf = psh->memout.buf;
-			backcmd->nleft = psh->memout.nextc - psh->memout.buf;
+			backcmd->nleft = (int)(psh->memout.nextc - psh->memout.buf);
 			psh->memout.buf = NULL;
 		}
@@ -1101,5 +1101,5 @@
 	popstackmark(psh, &smark);
 
-	if (psh->eflag && psh->exitstatus && !(flags & EV_TESTED))
+	if (eflag(psh) && psh->exitstatus && !(flags & EV_TESTED))
 		exitshell(psh, psh->exitstatus);
 }
@@ -1160,5 +1160,5 @@
 breakcmd(shinstance *psh, int argc, char **argv)
 {
-	int n = argc > 1 ? number(argv[1]) : 1;
+	int n = argc > 1 ? number(psh, argv[1]) : 1;
 
 	if (n > psh->loopnest)
@@ -1179,5 +1179,5 @@
 returncmd(shinstance *psh, int argc, char **argv)
 {
-	int ret = argc > 1 ? number(argv[1]) : psh->exitstatus;
+	int ret = argc > 1 ? number(psh, argv[1]) : psh->exitstatus;
 
 	if (psh->funcnest) {
@@ -1215,6 +1215,6 @@
 		struct strlist *sp;
 
-		psh->iflag = 0;		/* exit on error */
-		psh->mflag = 0;
+		iflag(psh) = 0;		/* exit on error */
+		mflag(psh) = 0;
 		optschanged(psh);
 		for (sp = psh->cmdenviron; sp; sp = sp->next)
@@ -1230,5 +1230,5 @@
 	static clock_t tpm = 0;
 	clock_t mins;
-	int i;
+	size_t i;
 
 	if (!tpm)
Index: trunk/src/kash/eval.h
===================================================================
--- trunk/src/kash/eval.h	(revision 1196)
+++ trunk/src/kash/eval.h	(revision 1198)
@@ -54,5 +54,5 @@
 
 /* in_function returns nonzero if we are currently evaluating a function */
-#define in_function()	psh->funcnest
+#define in_function(psh)	(psh)->funcnest
 /*extern int funcnest;
 extern int evalskip;*/
Index: trunk/src/kash/exec.c
===================================================================
--- trunk/src/kash/exec.c	(revision 1196)
+++ trunk/src/kash/exec.c	(revision 1198)
@@ -146,9 +146,9 @@
 	TRACE(("shellexec: argv[0]=%s idx=%d\n", argv[0], idx));
 	if (strchr(argv[0], '/') != NULL) {
-		cmdname = stalloc(strlen(argv[0]) + 5);
+		cmdname = stalloc(psh, strlen(argv[0]) + 5);
 		strcpy(cmdname, argv[0]);
 		tryexec(cmdname, argv, envp, vforked, has_ext);
 		TRACE(("shellexec: cmdname=%s\n", cmdname));
-		stunalloc(cmdname);
+		stunalloc(psh, cmdname);
 		e = errno;
 	} else {
@@ -160,5 +160,5 @@
 					e = errno;
 			}
-			stunalloc(cmdname);
+			stunalloc(psh, cmdname);
 		}
 	}
@@ -275,11 +275,11 @@
 		if (ap == &newargs[NEWARGS])
 bad:		  error("Bad #! line");
-		STARTSTACKSTR(outp);
+		STARTSTACKSTR(psh, outp);
 		do {
-			STPUTC(c, outp);
+			STPUTC(psh, c, outp);
 		} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
-		STPUTC('\0', outp);
+		STPUTC(psh, '\0', outp);
 		n++, inp--;
-		*ap++ = grabstackstr(outp);
+		*ap++ = grabstackstr(psh, outp);
 	}
 	if (ap == newargs + 1) {	/* if no args, maybe no exec is needed */
@@ -349,7 +349,7 @@
         len += 4; /* "4" is for .exe/.com/.cmd/.bat/.btm */
 #endif
-	while (stackblocksize() < len)
-		growstackblock();
-	q = stackblock();
+	while (stackblocksize(psh) < len)
+		growstackblock(psh);
+	q = stackblock(psh);
 	if (p != start) {
 		memcpy(q, start, p - start);
@@ -375,5 +375,5 @@
 	else
 		*path = NULL;
-	return stalloc(len);
+	return stalloc(psh, len);
 }
 
@@ -485,5 +485,5 @@
 		do {
 			name = padvance(&path, cmdp->cmdname);
-			stunalloc(name);
+			stunalloc(psh, name);
 		} while (--idx >= 0);
 		out1str(name);
@@ -623,5 +623,5 @@
 loop:
 	while ((fullname = padvance(&path, name)) != NULL) {
-		stunalloc(fullname);
+		stunalloc(psh, fullname);
 		idx++;
 		if (pathopt) {
@@ -664,10 +664,10 @@
 			if (act & DO_NOFUNC)
 				goto loop;
-			stalloc(strlen(fullname) + 1);
+			stalloc(psh, strlen(fullname) + 1);
 			readcmdfile(fullname);
 			if ((cmdp = cmdlookup(name, 0)) == NULL ||
 			    cmdp->cmdtype != CMDFUNCTION)
 				error("%s not defined in %s", name, fullname);
-			stunalloc(fullname);
+			stunalloc(psh, fullname);
 			goto success;
 		}
@@ -689,5 +689,5 @@
 		INTOFF;
 		if (act & DO_ALTPATH) {
-			stalloc(strlen(fullname) + 1);
+			stalloc(psh, strlen(fullname) + 1);
 			cmdp = &loc_cmd;
 		} else
@@ -1137,5 +1137,5 @@
 				do {
 					name = padvance(&path, arg);
-					stunalloc(name);
+					stunalloc(psh, name);
 				} while (--j >= 0);
 				if (!v_flag)
Index: trunk/src/kash/expand.c
===================================================================
--- trunk/src/kash/expand.c	(revision 1196)
+++ trunk/src/kash/expand.c	(revision 1198)
@@ -124,7 +124,7 @@
 expandhere(union node *arg, int fd)
 {
-	herefd = fd;
+	psh->herefd = fd;
 	expandarg(arg, (struct arglist *)NULL, 0);
-	xwrite(fd, stackblock(), expdest - stackblock());
+	xwrite(psh, fd, stackblock(psh), expdest - stackblock(psh));
 }
 
@@ -144,5 +144,5 @@
 
 	argbackq = arg->narg.backquote;
-	STARTSTACKSTR(expdest);
+	STARTSTACKSTR(psh, expdest);
 	ifsfirst.next = NULL;
 	ifslastp = NULL;
@@ -151,6 +151,6 @@
 		return;			/* here document expanded */
 	}
-	STPUTC('\0', expdest);
-	p = grabstackstr(expdest);
+	STPUTC(psh, '\0', expdest);
+	p = grabstackstr(psh, expdest);
 	exparg.lastp = &exparg.list;
 	/*
@@ -165,5 +165,5 @@
 		if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
 			rmescapes(p);
-		sp = (struct strlist *)stalloc(sizeof (struct strlist));
+		sp = (struct strlist *)stalloc(psh, sizeof (struct strlist));
 		sp->text = p;
 		*exparg.lastp = sp;
@@ -210,5 +210,5 @@
 				break;
 			if ((flag & EXP_FULL) != 0)
-				STPUTC(c, expdest);
+				STPUTC(psh, c, expdest);
 			ifs_split = 0;
 			break;
@@ -218,7 +218,7 @@
 		case CTLESC:
 			if (quotes)
-				STPUTC(c, expdest);
+				STPUTC(psh, c, expdest);
 			c = *p++;
-			STPUTC(c, expdest);
+			STPUTC(psh, c, expdest);
 			break;
 		case CTLVAR:
@@ -239,5 +239,5 @@
 			 * assignments (after the first '=' and after ':'s).
 			 */
-			STPUTC(c, expdest);
+			STPUTC(psh, c, expdest);
 			if (flag & EXP_VARTILDE && *p == '~') {
 				if (c == '=') {
@@ -251,9 +251,9 @@
 			break;
 		default:
-			STPUTC(c, expdest);
+			STPUTC(psh, c, expdest);
 			if (flag & EXP_IFS_SPLIT & ifs_split && strchr(ifs, c) != NULL) {
 				/* We need to get the output split here... */
-				recordregion(expdest - stackblock() - 1,
-						expdest - stackblock(), 0);
+				recordregion(expdest - stackblock(psh) - 1,
+						expdest - stackblock(psh), 0);
 			}
 			break;
@@ -300,6 +300,6 @@
 	while ((c = *home++) != '\0') {
 		if (quotes && SQSYNTAX[(int)c] == CCTL)
-			STPUTC(CTLESC, expdest);
-		STPUTC(c, expdest);
+			STPUTC(psh, CTLESC, expdest);
+		STPUTC(psh, c, expdest);
 	}
 	return (p);
@@ -378,7 +378,7 @@
 #error "integers with more than 10 digits are not supported"
 #endif
-	CHECKSTRSPACE(12 - 2, expdest);
-	USTPUTC('\0', expdest);
-	start = stackblock();
+	CHECKSTRSPACE(psh, 12 - 2, expdest);
+	USTPUTC(psh, '\0', expdest);
+	start = stackblock(psh);
 	p = expdest - 1;
 	while (*p != CTLARI && p >= start)
@@ -408,5 +408,5 @@
 		recordregion(begoff, p - 1 - start, 0);
 	result = expdest - p + 1;
-	STADJUST(-result, expdest);
+	STADJUST(psh, -result, expdest);
 }
 
@@ -427,5 +427,5 @@
 	struct nodelist *saveargbackq;
 	char lastc;
-	int startloc = dest - stackblock();
+	int startloc = dest - stackblock(psh);
 	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
 	int saveherefd;
@@ -436,13 +436,13 @@
 	savelastp = ifslastp;
 	saveargbackq = argbackq;
-	saveherefd = herefd;
-	herefd = -1;
-	p = grabstackstr(dest);
+	saveherefd = psh->herefd;
+	psh->herefd = -1;
+	p = grabstackstr(psh, dest);
 	evalbackcmd(cmd, &in);
-	ungrabstackstr(p, dest);
+	ungrabstackstr(psh, p, dest);
 	ifsfirst = saveifs;
 	ifslastp = savelastp;
 	argbackq = saveargbackq;
-	herefd = saveherefd;
+	psh->herefd = saveherefd;
 
 	p = in.buf;
@@ -462,13 +462,13 @@
 		if (lastc != '\0') {
 			if (quotes && syntax[(int)lastc] == CCTL)
-				STPUTC(CTLESC, dest);
-			STPUTC(lastc, dest);
+				STPUTC(psh, CTLESC, dest);
+			STPUTC(psh, lastc, dest);
 		}
 	}
 
 	/* Eat all trailing newlines */
-	p = stackblock() + startloc;
+	p = stackblock(psh) + startloc;
 	while (dest > p && dest[-1] == '\n')
-		STUNPUTC(dest);
+		STUNPUTC(psh, dest);
 
 	if (in.fd >= 0)
@@ -479,9 +479,9 @@
 		back_exitstatus = waitforjob(in.jp);
 	if (quoted == 0)
-		recordregion(startloc, dest - stackblock(), 0);
+		recordregion(startloc, dest - stackblock(psh), 0);
 	TRACE(("evalbackq: size=%d: \"%.*s\"\n",
-		(dest - stackblock()) - startloc,
-		(dest - stackblock()) - startloc,
-		stackblock() + startloc));
+		(dest - stackblock(psh)) - startloc,
+		(dest - stackblock(psh)) - startloc,
+		stackblock(psh) + startloc));
 	expdest = dest;
 	INTON;
@@ -497,16 +497,16 @@
 	char *q;
 	int c = 0;
-	int saveherefd = herefd;
+	int saveherefd = psh->herefd;
 	struct nodelist *saveargbackq = argbackq;
 	int amount;
 
-	herefd = -1;
+	psh->herefd = -1;
 	argstr(p, 0);
-	STACKSTRNUL(expdest);
-	herefd = saveherefd;
+	STACKSTRNUL(psh, expdest);
+	psh->herefd = saveherefd;
 	argbackq = saveargbackq;
-	startp = stackblock() + startloc;
+	startp = stackblock(psh) + startloc;
 	if (str == NULL)
-	    str = stackblock() + strloc;
+	    str = stackblock(psh) + strloc;
 
 	switch (subtype) {
@@ -514,5 +514,5 @@
 		setvar(str, startp, 0);
 		amount = startp - expdest;
-		STADJUST(amount, expdest);
+		STADJUST(psh, amount, expdest);
 		varflags &= ~VSNUL;
 		if (c != 0)
@@ -593,5 +593,5 @@
 	*loc = c;
 	amount = ((str - 1) - (loc - startp)) - expdest;
-	STADJUST(amount, expdest);
+	STADJUST(psh, amount, expdest);
 	while (loc != str - 1)
 		*startp++ = *loc++;
@@ -600,7 +600,7 @@
 recordright:
 	amount = loc - expdest;
-	STADJUST(amount, expdest);
-	STPUTC('\0', expdest);
-	STADJUST(-1, expdest);
+	STADJUST(psh, amount, expdest);
+	STPUTC(psh, '\0', expdest);
+	STADJUST(psh, -1, expdest);
 	return 1;
 }
@@ -648,7 +648,7 @@
 
 	varlen = 0;
-	startloc = expdest - stackblock();
-
-	if (!set && uflag) {
+	startloc = expdest - stackblock(psh);
+
+	if (!set && uflag(psh)) {
 		switch (subtype) {
 		case VSNORMAL:
@@ -668,6 +668,6 @@
 			varvalue(var, varflags & VSQUOTE, subtype, flag);
 			if (subtype == VSLENGTH) {
-				varlen = expdest - stackblock() - startloc;
-				STADJUST(-varlen, expdest);
+				varlen = expdest - stackblock(psh) - startloc;
+				STADJUST(psh, -varlen, expdest);
 			}
 		} else {
@@ -681,6 +681,6 @@
 				while (*val) {
 					if (quotes && syntax[(int)*val] == CCTL)
-						STPUTC(CTLESC, expdest);
-					STPUTC(*val++, expdest);
+						STPUTC(psh, CTLESC, expdest);
+					STPUTC(psh, *val++, expdest);
 				}
 
@@ -727,10 +727,10 @@
 		 * right after it
 		 */
-		STPUTC('\0', expdest);
-		patloc = expdest - stackblock();
+		STPUTC(psh, '\0', expdest);
+		patloc = expdest - stackblock(psh);
 		if (subevalvar(p, NULL, patloc, subtype,
 			       startloc, varflags) == 0) {
-			int amount = (expdest - stackblock() - patloc) + 1;
-			STADJUST(-amount, expdest);
+			int amount = (expdest - stackblock(psh) - patloc) + 1;
+			STADJUST(psh, -amount, expdest);
 		}
 		/* Remove any recorded regions beyond start of variable */
@@ -760,5 +760,5 @@
 
 	if (apply_ifs)
-		recordregion(startloc, expdest - stackblock(),
+		recordregion(startloc, expdest - stackblock(psh),
 			     varflags & VSQUOTE);
 
@@ -846,10 +846,10 @@
 		while (*p) { \
 			if (syntax[(int)*p] == CCTL) \
-				STPUTC(CTLESC, expdest); \
-			STPUTC(*p++, expdest); \
+				STPUTC(psh, CTLESC, expdest); \
+			STPUTC(psh, *p++, expdest); \
 		} \
 	} else \
 		while (*p) \
-			STPUTC(*p++, expdest); \
+			STPUTC(psh, *p++, expdest); \
 	} while (0)
 
@@ -873,5 +873,5 @@
 		for (i = 0; optlist[i].name; i++) {
 			if (optlist[i].val)
-				STPUTC(optlist[i].letter, expdest);
+				STPUTC(psh, optlist[i].letter, expdest);
 		}
 		break;
@@ -881,5 +881,5 @@
 				STRTODEST(p);
 				if (*ap)
-					STPUTC('\0', expdest);
+					STPUTC(psh, '\0', expdest);
 			}
 			break;
@@ -894,5 +894,5 @@
 			STRTODEST(p);
 			if (*ap && sep)
-				STPUTC(sep, expdest);
+				STPUTC(psh, sep, expdest);
 		}
 		break;
@@ -969,5 +969,5 @@
 	if (ifslastp == NULL) {
 		/* Return entire argument, IFS doesn't apply to any of it */
-		sp = (struct strlist *)stalloc(sizeof *sp);
+		sp = (struct strlist *)stalloc(psh, sizeof *sp);
 		sp->text = start;
 		*arglist->lastp = sp;
@@ -1009,5 +1009,5 @@
 			/* Save this argument... */
 			*q = '\0';
-			sp = (struct strlist *)stalloc(sizeof *sp);
+			sp = (struct strlist *)stalloc(psh, sizeof *sp);
 			sp->text = start;
 			*arglist->lastp = sp;
@@ -1043,5 +1043,5 @@
 	 */
 	if (*start /* || (!ifsspc && start > string) */) {
-		sp = (struct strlist *)stalloc(sizeof *sp);
+		sp = (struct strlist *)stalloc(psh, sizeof *sp);
 		sp->text = start;
 		*arglist->lastp = sp;
@@ -1085,5 +1085,5 @@
 
 	while (str) {
-		if (fflag)
+		if (fflag(psh))
 			goto nometa;
 		p = str->text;
@@ -1264,7 +1264,7 @@
 	struct strlist *sp;
 
-	p = stalloc(strlen(name) + 1);
+	p = stalloc(psh, strlen(name) + 1);
 	scopy(name, p);
-	sp = (struct strlist *)stalloc(sizeof *sp);
+	sp = (struct strlist *)stalloc(psh, sizeof *sp);
 	sp->text = p;
 	*exparg.lastp = sp;
@@ -1509,13 +1509,13 @@
 	char *p;
 
-	setstackmark(&smark);
+	setstackmark(psh, &smark);
 	argbackq = pattern->narg.backquote;
-	STARTSTACKSTR(expdest);
+	STARTSTACKSTR(psh, expdest);
 	ifslastp = NULL;
 	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
-	STPUTC('\0', expdest);
-	p = grabstackstr(expdest);
+	STPUTC(psh, '\0', expdest);
+	p = grabstackstr(psh, expdest);
 	result = patmatch(p, val, 0);
-	popstackmark(&smark);
+	popstackmark(psh, &smark);
 	return result;
 }
@@ -1542,5 +1542,5 @@
 
 	while (*p)
-		STPUTC(*p++, buf);
+		STPUTC(psh, *p++, buf);
 	return buf;
 }
Index: trunk/src/kash/generated/arith.c
===================================================================
--- trunk/src/kash/generated/arith.c	(revision 1196)
+++ trunk/src/kash/generated/arith.c	(revision 1198)
@@ -329,15 +329,15 @@
 			 * concatenate arguments
 			 */
-			STARTSTACKSTR(concat);
+			STARTSTACKSTR(psh, concat);
 			ap = argv + 2;
 			for (;;) {
 				while (*p)
-					STPUTC(*p++, concat);
+					STPUTC(psh, *p++, concat);
 				if ((p = *ap++) == NULL)
 					break;
-				STPUTC(' ', concat);
+				STPUTC(psh, ' ', concat);
 			}
-			STPUTC('\0', concat);
-			p = grabstackstr(concat);
+			STPUTC(psh, '\0', concat);
+			p = grabstackstr(psh, concat);
 		}
 	} else
@@ -382,5 +382,5 @@
 #define YYERROR goto yyerrlab
 #ifdef __cplusplus
-extern "C" { 
+extern "C" {
 char * getenv();
 int yylex();
Index: trunk/src/kash/generated/init.c
===================================================================
--- trunk/src/kash/generated/init.c	(revision 1196)
+++ trunk/src/kash/generated/init.c	(revision 1198)
@@ -44,5 +44,5 @@
 #define DEFEDITOR	"ed"	/* default editor *should* be $EDITOR */
 #undef  editing
-#define editing (Eflag || Vflag)
+#define editing (Eflag(psh) || Vflag(psh))
 #undef  EOF_NLEFT
 #define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
Index: trunk/src/kash/histedit.c
===================================================================
--- trunk/src/kash/histedit.c	(revision 1196)
+++ trunk/src/kash/histedit.c	(revision 1198)
@@ -91,7 +91,7 @@
 	FILE *el_err;
 
-#define editing (Eflag || Vflag)
-
-	if (iflag) {
+#define editing (Eflag(psh) || Vflag(psh))
+
+	if (iflag(psh)) {
 		if (!hist) {
 			/*
@@ -154,10 +154,10 @@
 		}
 		if (el) {
-			if (Vflag)
+			if (Vflag(psh))
 				el_set(el, EL_EDITOR, "vi");
-			else if (Eflag)
+			else if (Eflag(psh))
 				el_set(el, EL_EDITOR, "emacs");
 			el_set(el, EL_BIND, "^I",
-			    tabcomplete ? "rl-complete" : "ed-insert", NULL);
+			    tabcomplete(psh) ? "rl-complete" : "ed-insert", NULL);
 			el_source(el, NULL);
 		}
@@ -418,5 +418,5 @@
 				}
 
-				evalstring(strcpy(stalloc(strlen(s) + 1), s), 0);
+				evalstring(strcpy(stalloc(psh, strlen(s) + 1), s), 0);
 				if (displayhist && hist) {
 					/*
@@ -440,5 +440,5 @@
 
 		fclose(efp);
-		editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
+		editcmd = stalloc(psh, strlen(editor) + strlen(editfile) + 2);
 		sprintf(editcmd, "%s %s", editor, editfile);
 		evalstring(editcmd, 0);	/* XXX - should use no JC command */
@@ -461,16 +461,16 @@
 	int plen = strlen(p);
 
-	STARTSTACKSTR(dest);
+	STARTSTACKSTR(psh, dest);
 	while (*s) {
 		if (*s == *p && strncmp(s, p, plen) == 0) {
 			while (*r)
-				STPUTC(*r++, dest);
+				STPUTC(psh, *r++, dest);
 			s += plen;
 			*p = '\0';	/* so no more matches */
 		} else
-			STPUTC(*s++, dest);
-	}
-	STACKSTRNUL(dest);
-	dest = grabstackstr(dest);
+			STPUTC(psh, *s++, dest);
+	}
+	STACKSTRNUL(psh, dest);
+	dest = grabstackstr(psh, dest);
 
 	return (dest);
@@ -537,14 +537,16 @@
 #else
 int
-histcmd(int argc, char **argv)
-{
-	error("not compiled with history support");
+histcmd(shinstance *psh, int argc, char **argv)
+{
+	error(psh, "not compiled with history support");
 	/* NOTREACHED */
+	return -1;
 }
 int
-inputrc(int argc, char **argv)
-{
-	error("not compiled with history support");
+inputrc(shinstance *psh, int argc, char **argv)
+{
+	error(psh, "not compiled with history support");
 	/* NOTREACHED */
-}
-#endif
+	return -1;
+}
+#endif
Index: trunk/src/kash/input.c
===================================================================
--- trunk/src/kash/input.c	(revision 1196)
+++ trunk/src/kash/input.c	(revision 1198)
@@ -316,5 +316,5 @@
 #endif
 
-	if (vflag) {
+	if (vflag(psh)) {
 		out2str(parsenextc);
 		flushout(out2);
Index: trunk/src/kash/jobs.c
===================================================================
--- trunk/src/kash/jobs.c	(revision 1196)
+++ trunk/src/kash/jobs.c	(revision 1198)
@@ -193,5 +193,5 @@
 out:
 				out2str("sh: can't access tty; job control turned off\n");
-				mflag = 0;
+				mflag(psh) = 0;
 				return;
 			}
@@ -208,5 +208,5 @@
 		    || ldisc != NTTYDISC) {
 			out2str("sh: need new tty driver to run job control; job control turned off\n");
-			mflag = 0;
+			mflag(psh) = 0;
 			return;
 		}
@@ -549,5 +549,5 @@
 	 * put us in it.
 	 */
-	if (mflag && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) {
+	if (mflag(psh) && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) {
 		if (tcsetpgrp(ttyfd, getpid()) == -1)
 			error("Cannot set tty process group (%s) at %d",
@@ -651,5 +651,5 @@
 			retval = WTERMSIG(status) + 128;
 		}
-		if (!iflag)
+		if (!iflag(psh))
 			freejob(job);
 	}
@@ -705,5 +705,5 @@
 	} else if (name[0] == '%') {
 		if (is_number(name + 1)) {
-			jobno = number(name + 1) - 1;
+			jobno = number(psh, name + 1) - 1;
 		} else if (!name[2]) {
 			switch (name[1]) {
@@ -748,5 +748,5 @@
 
 	} else if (is_number(name)) {
-		pid = number(name);
+		pid = number(psh, name);
 		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
 			if (jp->used && jp->nprocs > 0
@@ -870,5 +870,5 @@
 	int pgrp;
 
-	if (rootshell && mode != FORK_NOJOB && mflag) {
+	if (rootshell && mode != FORK_NOJOB && mflag(psh)) {
 		if (jp == NULL || jp->nprocs == 0)
 			pgrp = pid;
@@ -910,5 +910,5 @@
 	if (!vforked)
 		jobctl = 0;		/* do job control only in root shell */
-	if (wasroot && mode != FORK_NOJOB && mflag) {
+	if (wasroot && mode != FORK_NOJOB && mflag(psh)) {
 		if (jp == NULL || jp->nprocs == 0)
 			pgrp = getpid();
@@ -946,5 +946,5 @@
 	}
 #endif
-	if (wasroot && iflag) {
+	if (wasroot && iflag(psh)) {
 		setsignal(SIGINT, vforked);
 		setsignal(SIGQUIT, vforked);
@@ -1090,5 +1090,5 @@
 	if (thisjob && thisjob->state != JOBRUNNING) {
 		int mode = 0;
-		if (!rootshell || !iflag)
+		if (!rootshell || !iflag(psh))
 			mode = SHOW_SIGNALLED;
 		if (job == thisjob)
@@ -1219,5 +1219,5 @@
 
 	cmdnextc = ps->cmd;
-	if (iflag || mflag || sizeof ps->cmd < 100)
+	if (iflag(psh) || mflag(psh) || sizeof ps->cmd < 100)
 		len = sizeof(ps->cmd);
 	else
Index: trunk/src/kash/machdep.h
===================================================================
--- trunk/src/kash/machdep.h	(revision 1196)
+++ trunk/src/kash/machdep.h	(revision 1198)
@@ -40,5 +40,10 @@
  */
 
+#ifdef _MSC_VER
+#define SHELL_SIZE (8 - 1)
+#else
 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
+#endif
+
 /*
  * It appears that grabstackstr() will barf with such alignments
Index: trunk/src/kash/mail.c
===================================================================
--- trunk/src/kash/mail.c	(revision 1196)
+++ trunk/src/kash/mail.c	(revision 1198)
@@ -58,11 +58,12 @@
 #include "error.h"
 #include "mail.h"
+#include "shinstance.h"
 
 
-#define MAXMBOXES 10
+/*#define MAXMBOXES 10*/
 
 
-STATIC int nmboxes;			/* number of mailboxes */
-STATIC time_t mailtime[MAXMBOXES];	/* times of mailboxes */
+/*STATIC int nmboxes;			/* number of mailboxes */
+/*STATIC time_t mailtime[MAXMBOXES];*/	/* times of mailboxes */
 
 
@@ -75,5 +76,5 @@
 
 void
-chkmail(int silent)
+chkmail(shinstance *psh, int silent)
 {
 	int i;
@@ -85,11 +86,11 @@
 
 	if (silent)
-		nmboxes = 10;
-	if (nmboxes == 0)
+		psh->nmboxes = 10;
+	if (psh->nmboxes == 0)
 		return;
-	setstackmark(&smark);
-	mpath = mpathset() ? mpathval() : mailval();
-	for (i = 0 ; i < nmboxes ; i++) {
-		p = padvance(&mpath, nullstr);
+	setstackmark(psh, &smark);
+	mpath = mpathset(psh) ? mpathval(psh) : mailval(psh);
+	for (i = 0 ; i < psh->nmboxes ; i++) {
+		p = padvance(psh, &mpath, nullstr);
 		if (p == NULL)
 			break;
@@ -101,22 +102,22 @@
 		q[-1] = '\0';			/* delete trailing '/' */
 #ifdef notdef /* this is what the System V shell claims to do (it lies) */
-		if (stat(p, &statb) < 0)
+		if (shfile_stat(&psh->fdtab, p, &statb) < 0)
 			statb.st_mtime = 0;
-		if (statb.st_mtime > mailtime[i] && ! silent) {
-			out2str(pathopt ? pathopt : "you have mail");
-			out2c('\n');
+		if (statb.st_mtime > psh->mailtime[i] && ! silent) {
+			out2str(psh, psh->pathopt ? psh->pathopt : "you have mail");
+			out2c(psh, '\n');
 		}
-		mailtime[i] = statb.st_mtime;
+		psh->mailtime[i] = statb.st_mtime;
 #else /* this is what it should do */
-		if (stat(p, &statb) < 0)
+		if (shfile_stat(&psh->fdtab, p, &statb) < 0)
 			statb.st_size = 0;
-		if (statb.st_size > mailtime[i] && ! silent) {
-			out2str(pathopt ? pathopt : "you have mail");
-			out2c('\n');
+		if (statb.st_size > psh->mailtime[i] && ! silent) {
+			out2str(psh, psh->pathopt ? psh->pathopt : "you have mail");
+			out2c(psh, '\n');
 		}
-		mailtime[i] = statb.st_size;
+		psh->mailtime[i] = statb.st_size;
 #endif
 	}
-	nmboxes = i;
-	popstackmark(&smark);
+	psh->nmboxes = i;
+	popstackmark(psh, &smark);
 }
Index: trunk/src/kash/main.c
===================================================================
--- trunk/src/kash/main.c	(revision 1196)
+++ trunk/src/kash/main.c	(revision 1198)
@@ -84,6 +84,8 @@
 /*int rootpid;
 int rootshell;*/
+#ifdef unused_variables
 STATIC union node *curcmd;
 STATIC union node *prevcmd;
+#endif
 
 STATIC void read_profile(struct shinstance *, const char *);
@@ -94,4 +96,6 @@
 extern void init_syntax(void);
 #endif
+STATIC int usage(const char *argv0);
+STATIC int version(const char *argv0);
 
 /*
@@ -109,10 +113,21 @@
 
 	/*
-	 * Global initializations. 
-         */
+	 * Global initializations.
+	 */
 	setlocale(LC_ALL, "");
 #ifdef _MSC_VER
 	init_syntax();
 #endif
+
+	/*
+	 * Check for --version and --help.
+     */
+	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-') {
+		if (!strcmp(argv[1], "--help"))
+			return usage(argv[0]);
+		if (!strcmp(argv[1], "--version"))
+			return version(argv[0]);
+	}
+
 	/*
 	 * Create the root shell instance.
@@ -123,7 +138,7 @@
 	shthread_set_shell(psh);
 	return shell_main(psh, argc, argv);
-}	
-
-int 
+}
+
+int
 shell_main(shinstance *psh, int argc, char **argv)
 {
@@ -161,5 +176,5 @@
 
 		if (psh->exception != EXSHELLPROC) {
-			if (state == 0 || psh->iflag == 0 || ! psh->rootshell)
+			if (state == 0 || iflag(psh) == 0 || ! psh->rootshell)
 				exitshell(psh, psh->exitstatus);
 		}
@@ -189,5 +204,5 @@
 #ifdef DEBUG
 #if DEBUG == 2
-	debug = 1;
+	debug(psh) = 1;
 #endif
 	opentrace(psh);
@@ -215,5 +230,5 @@
 state3:
 	state = 4;
-	if (psh->sflag == 0 || psh->minusc) {
+	if (sflag(psh) == 0 || psh->minusc) {
 		static int sigs[] =  {
 		    SIGINT, SIGQUIT, SIGHUP,
@@ -233,5 +248,5 @@
 		evalstring(psh, psh->minusc, 0);
 
-	if (psh->sflag || psh->minusc == NULL) {
+	if (sflag(psh) || psh->minusc == NULL) {
 state4:	/* XXX ??? - why isn't this before the "if" statement */
 		cmdloop(psh, 1);
@@ -262,5 +277,5 @@
 			dotrap(psh);
 		inter = 0;
-		if (psh->iflag && top) {
+		if (iflag(psh) && top) {
 			inter = 1;
 			showjobs(psh, psh->out2, SHOW_CHANGED);
@@ -274,10 +289,10 @@
 				break;
 			if (!stoppedjobs(psh)) {
-				if (!psh->Iflag)
+				if (!Iflag(psh))
 					break;
 				out2str(psh, "\nUse \"exit\" to leave shell.\n");
 			}
 			numeof++;
-		} else if (n != NULL && psh->nflag == 0) {
+		} else if (n != NULL && nflag(psh) == 0) {
 			psh->job_warning = (psh->job_warning == 2) ? 1 : 0;
 			numeof = 0;
@@ -314,16 +329,16 @@
 		return;
 	/* -q turns off -x and -v just when executing init files */
-	if (psh->qflag)  {
-	    if (psh->xflag)
-		    psh->xflag = 0, xflag_set = 1;
-	    if (psh->vflag)
-		    psh->vflag = 0, vflag_set = 1;
+	if (qflag(psh))  {
+	    if (xflag(psh))
+		    xflag(psh) = 0, xflag_set = 1;
+	    if (vflag(psh))
+		    vflag(psh) = 0, vflag_set = 1;
 	}
 	cmdloop(psh, 0);
-	if (psh->qflag)  {
+	if (qflag(psh))  {
 	    if (xflag_set)
-		    psh->xflag = 1;
+		    xflag(psh) = 1;
 	    if (vflag_set)
-		    psh->vflag = 1;
+		    vflag(psh) = 1;
 	}
 	popfile(psh);
@@ -414,5 +429,5 @@
 		return 0;
 	if (argc > 1)
-		psh->exitstatus = number(argv[1]);
+		psh->exitstatus = number(psh, argv[1]);
 	exitshell(psh, psh->exitstatus);
 	/* NOTREACHED */
@@ -420,4 +435,55 @@
 }
 
+
+STATIC const char *
+strip_argv0(const char *argv0, size_t *lenp)
+{
+	const char *tmp;
+
+	/* skip the path */
+	for (tmp = strpbrk(argv0, "\\/:"); tmp; tmp = strpbrk(argv0, "\\/:"))
+		argv0 = tmp + 1;
+
+	/* find the end, ignoring extenions */
+	tmp = strrchr(argv0, '.');
+	if (!tmp)
+		tmp = strchr(argv0, '\0');
+	*lenp = tmp - argv0;
+	return argv0;
+}
+
+STATIC int
+usage(const char *argv0)
+{
+	size_t len;
+	strip_argv0(argv0, &len);
+
+	fprintf(stdout,
+			"usage: %.*s [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n"
+		    "               [+o option_name] [command_file [argument ...]]\n"
+		    "   or: %.*s -c [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n"
+		    "               [+o option_name] command_string [command_name [argument ...]]\n"
+		    "   or: %.*s -s [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n"
+		    "               [+o option_name] [argument ...]\n"
+		    "   or: %.*s --help\n"
+		    "   or: %.*s --version\n",
+		    len, argv0, len, argv0, len, argv0, len, argv0, len, argv0);
+	return 0;
+}
+
+STATIC int
+version(const char *argv0)
+{
+	size_t len;
+	strip_argv0(argv0, &len);
+
+	fprintf(stdout,
+			"%.*s - kBuild version %d.%d.%d\n",
+		    len, argv0,
+		    KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH);
+	return 0;
+}
+
+
 /*
  * Local Variables:
Index: trunk/src/kash/memalloc.c
===================================================================
--- trunk/src/kash/memalloc.c	(revision 1196)
+++ trunk/src/kash/memalloc.c	(revision 1198)
@@ -59,5 +59,5 @@
 
 pointer
-ckmalloc(int nbytes)
+ckmalloc(size_t nbytes)
 {
 	pointer p;
@@ -65,5 +65,5 @@
 	p = malloc(nbytes);
 	if (p == NULL)
-		error("Out of space");
+		error(NULL, "Out of space");
 	return p;
 }
@@ -75,9 +75,9 @@
 
 pointer
-ckrealloc(pointer p, int nbytes)
+ckrealloc(pointer p, size_t nbytes)
 {
 	p = realloc(p, nbytes);
 	if (p == NULL)
-		error("Out of space");
+		error(NULL, "Out of space");
 	return p;
 }
@@ -108,27 +108,27 @@
  */
 
-#define MINSIZE 504		/* minimum size of a block */
-
-struct stack_block {
-	struct stack_block *prev;
-	char space[MINSIZE];
-};
-
-struct stack_block stackbase;
-struct stack_block *stackp = &stackbase;
-struct stackmark *markp;
-char *stacknxt = stackbase.space;
-int stacknleft = MINSIZE;
-int sstrnleft;
-int herefd = -1;
+//#define MINSIZE 504		/* minimum size of a block */
+
+//struct stack_block {
+//	struct stack_block *prev;
+//	char space[MINSIZE];
+//};
+
+//struct stack_block stackbase;
+//struct stack_block *stackp = &stackbase;
+//struct stackmark *markp;
+//char *stacknxt = stackbase.space;
+//int stacknleft = MINSIZE;
+//int sstrnleft;
+//int herefd = -1;
 
 pointer
-stalloc(int nbytes)
+stalloc(shinstance *psh, size_t nbytes)
 {
 	char *p;
 
 	nbytes = SHELL_ALIGN(nbytes);
-	if (nbytes > stacknleft) {
-		int blocksize;
+	if (nbytes > psh->stacknleft) {
+		size_t blocksize;
 		struct stack_block *sp;
 
@@ -138,13 +138,13 @@
 		INTOFF;
 		sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
-		sp->prev = stackp;
-		stacknxt = sp->space;
-		stacknleft = blocksize;
-		stackp = sp;
+		sp->prev = psh->stackp;
+		psh->stacknxt = sp->space;
+		psh->stacknleft = (int)blocksize;
+		psh->stackp = sp;
 		INTON;
 	}
-	p = stacknxt;
-	stacknxt += nbytes;
-	stacknleft -= nbytes;
+	p = psh->stacknxt;
+	psh->stacknxt += nbytes;
+	psh->stacknleft -= (int)nbytes;
 	return p;
 }
@@ -152,41 +152,41 @@
 
 void
-stunalloc(pointer p)
+stunalloc(shinstance *psh, pointer p)
 {
 	if (p == NULL) {		/*DEBUG */
-		write(2, "stunalloc\n", 10);
-		abort();
-	}
-	stacknleft += stacknxt - (char *)p;
-	stacknxt = p;
-}
-
-
-
-void
-setstackmark(struct stackmark *mark)
-{
-	mark->stackp = stackp;
-	mark->stacknxt = stacknxt;
-	mark->stacknleft = stacknleft;
-	mark->marknext = markp;
-	markp = mark;
-}
-
-
-void
-popstackmark(struct stackmark *mark)
+		shfile_write(&psh->fdtab, 2, "stunalloc\n", 10);
+		sh_abort(psh);
+	}
+	psh->stacknleft += (int)(psh->stacknxt - (char *)p);
+	psh->stacknxt = p;
+}
+
+
+
+void
+setstackmark(shinstance *psh, struct stackmark *mark)
+{
+	mark->stackp = psh->stackp;
+	mark->stacknxt = psh->stacknxt;
+	mark->stacknleft = psh->stacknleft;
+	mark->marknext = psh->markp;
+	psh->markp = mark;
+}
+
+
+void
+popstackmark(shinstance *psh, struct stackmark *mark)
 {
 	struct stack_block *sp;
 
 	INTOFF;
-	markp = mark->marknext;
-	while (stackp != mark->stackp) {
-		sp = stackp;
-		stackp = sp->prev;
+	psh->markp = mark->marknext;
+	while (psh->stackp != mark->stackp) {
+		sp = psh->stackp;
+		psh->stackp = sp->prev;
 		ckfree(sp);
 	}
-	stacknxt = mark->stacknxt;
-	stacknleft = mark->stacknleft;
+	psh->stacknxt = mark->stacknxt;
+	psh->stacknleft = mark->stacknleft;
 	INTON;
 }
@@ -204,9 +204,9 @@
 
 void
-growstackblock(void)
-{
-	int newlen = SHELL_ALIGN(stacknleft * 2 + 100);
-
-	if (stacknxt == stackp->space && stackp != &stackbase) {
+growstackblock(shinstance *psh)
+{
+	int newlen = SHELL_ALIGN(psh->stacknleft * 2 + 100);
+
+	if (psh->stacknxt == psh->stackp->space && psh->stackp != &psh->stackbase) {
 		struct stack_block *oldstackp;
 		struct stackmark *xmark;
@@ -214,13 +214,13 @@
 
 		INTOFF;
-		oldstackp = stackp;
-		sp = stackp;
-		stackp = sp->prev;
+		oldstackp = psh->stackp;
+		sp = psh->stackp;
+		psh->stackp = sp->prev;
 		sp = ckrealloc((pointer)sp,
 		    sizeof(struct stack_block) - MINSIZE + newlen);
-		sp->prev = stackp;
-		stackp = sp;
-		stacknxt = sp->space;
-		stacknleft = newlen;
+		sp->prev = psh->stackp;
+		psh->stackp = sp;
+		psh->stacknxt = sp->space;
+		psh->stacknleft = newlen;
 
 		/*
@@ -228,29 +228,29 @@
 		 * must be relocated to point to the new block
 		 */
-		xmark = markp;
+		xmark = psh->markp;
 		while (xmark != NULL && xmark->stackp == oldstackp) {
-			xmark->stackp = stackp;
-			xmark->stacknxt = stacknxt;
-			xmark->stacknleft = stacknleft;
+			xmark->stackp = psh->stackp;
+			xmark->stacknxt = psh->stacknxt;
+			xmark->stacknleft = psh->stacknleft;
 			xmark = xmark->marknext;
 		}
 		INTON;
 	} else {
-		char *oldspace = stacknxt;
-		int oldlen = stacknleft;
-		char *p = stalloc(newlen);
+		char *oldspace = psh->stacknxt;
+		int oldlen = psh->stacknleft;
+		char *p = stalloc(psh, newlen);
 
 		(void)memcpy(p, oldspace, oldlen);
-		stacknxt = p;			/* free the space */
-		stacknleft += newlen;		/* we just allocated */
-	}
-}
-
-void
-grabstackblock(int len)
+		psh->stacknxt = p;			/* free the space */
+		psh->stacknleft += newlen;		/* we just allocated */
+	}
+}
+
+void
+grabstackblock(shinstance *psh, int len)
 {
 	len = SHELL_ALIGN(len);
-	stacknxt += len;
-	stacknleft -= len;
+	psh->stacknxt += len;
+	psh->stacknleft -= len;
 }
 
@@ -260,7 +260,7 @@
  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
  * the user uses the macro STPUTC to add characters to the string.  In
- * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
+ * effect, STPUTC(psh, c, p) is the same as *p++ = c except that the stack is
  * grown as necessary.  When the user is done, she can just leave the
- * string there and refer to it using stackblock().  Or she can allocate
+ * string there and refer to it using stackblock(psh).  Or she can allocate
  * the space for it using grabstackstr().  If it is necessary to allow
  * someone else to use the stack temporarily and then continue to grow
@@ -274,15 +274,15 @@
 
 char *
-growstackstr(void)
-{
-	int len = stackblocksize();
-	if (herefd >= 0 && len >= 1024) {
-		xwrite(herefd, stackblock(), len);
-		sstrnleft = len - 1;
-		return stackblock();
-	}
-	growstackblock();
-	sstrnleft = stackblocksize() - len - 1;
-	return stackblock() + len;
+growstackstr(shinstance *psh)
+{
+	int len = stackblocksize(psh);
+	if (psh->herefd >= 0 && len >= 1024) {
+		xwrite(psh, psh->herefd, stackblock(psh), len);
+		psh->sstrnleft = len - 1;
+		return stackblock(psh);
+	}
+	growstackblock(psh);
+	psh->sstrnleft = stackblocksize(psh) - len - 1;
+	return stackblock(psh) + len;
 }
 
@@ -292,18 +292,18 @@
 
 char *
-makestrspace(void)
-{
-	int len = stackblocksize() - sstrnleft;
-	growstackblock();
-	sstrnleft = stackblocksize() - len;
-	return stackblock() + len;
-}
-
-void
-ungrabstackstr(char *s, char *p)
-{
-	stacknleft += stacknxt - s;
-	stacknxt = s;
-	sstrnleft = stacknleft - (p - s);
-
-}
+makestrspace(shinstance *psh)
+{
+	int len = stackblocksize(psh) - psh->sstrnleft;
+	growstackblock(psh);
+	psh->sstrnleft = stackblocksize(psh) - len;
+	return stackblock(psh) + len;
+}
+
+void
+ungrabstackstr(shinstance *psh, char *s, char *p)
+{
+	psh->stacknleft += (int)(psh->stacknxt - s);
+	psh->stacknxt = s;
+	psh->sstrnleft = (int)(psh->stacknleft - (p - s));
+
+}
Index: trunk/src/kash/memalloc.h
===================================================================
--- trunk/src/kash/memalloc.h	(revision 1196)
+++ trunk/src/kash/memalloc.h	(revision 1198)
@@ -48,8 +48,8 @@
 extern int herefd;*/
 
-pointer ckmalloc(int);
-pointer ckrealloc(pointer, int);
+pointer ckmalloc(size_t);
+pointer ckrealloc(pointer, size_t);
 char *savestr(const char *);
-pointer stalloc(struct shinstance *, int);
+pointer stalloc(struct shinstance *, size_t);
 void stunalloc(struct shinstance *, pointer);
 void setstackmark(struct shinstance *, struct stackmark *);
@@ -63,15 +63,15 @@
 
 
-#define stackblock() psh->stacknxt
-#define stackblocksize() psh->stacknleft
-#define STARTSTACKSTR(p)	p = stackblock(), psh->sstrnleft = stackblocksize()
-#define STPUTC(c, p)	(--psh->sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(psh), *p++ = (c)))
-#define CHECKSTRSPACE(n, p)	{ if (psh->sstrnleft < n) p = makestrspace(psh); }
-#define USTPUTC(c, p)	(--psh->sstrnleft, *p++ = (c))
-#define STACKSTRNUL(p)	(psh->sstrnleft == 0? (p = growstackstr(psh), *p = '\0') : (*p = '\0'))
-#define STUNPUTC(p)	(++psh->sstrnleft, --p)
-#define STTOPC(p)	p[-1]
-#define STADJUST(amount, p)	(p += (amount), psh->sstrnleft -= (amount))
-#define grabstackstr(p)	stalloc(psh, stackblocksize() - psh->sstrnleft)
+#define stackblock(psh)             (psh)->stacknxt
+#define stackblocksize(psh)         (psh)->stacknleft
+#define STARTSTACKSTR(psh, p)       p = stackblock(psh), (psh)->sstrnleft = stackblocksize(psh)
+#define STPUTC(psh, c, p)           (--(psh)->sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(psh), *p++ = (c)))
+#define CHECKSTRSPACE(psh, n, p)    { if ((psh)->sstrnleft < n) p = makestrspace(psh); }
+#define USTPUTC(psh, c, p)          (--(psh)->sstrnleft, *p++ = (c))
+#define STACKSTRNUL(psh, p)         ((psh)->sstrnleft == 0? (p = growstackstr(psh), *p = '\0') : (*p = '\0'))
+#define STUNPUTC(psh, p)            (++(psh)->sstrnleft, --p)
+#define STTOPC(psh, p)	            p[-1]
+#define STADJUST(psh, amount, p)    (p += (amount), (psh)->sstrnleft -= (amount))
+#define grabstackstr(psh, p)        stalloc((psh), stackblocksize(psh) - (psh)->sstrnleft)
 
 #define ckfree(p)	free((pointer)(p))
Index: trunk/src/kash/miscbltin.c
===================================================================
--- trunk/src/kash/miscbltin.c	(revision 1196)
+++ trunk/src/kash/miscbltin.c	(revision 1198)
@@ -125,5 +125,5 @@
 	status = 0;
 	startword = 2;
-	STARTSTACKSTR(p);
+	STARTSTACKSTR(psh, p);
 	for (;;) {
 		if (read(0, &c, 1) != 1) {
@@ -139,5 +139,5 @@
 			}
 			if (c != '\n')
-				STPUTC(c, p);
+				STPUTC(psh, c, p);
 			continue;
 		}
@@ -153,5 +153,5 @@
 				/* Ignore leading IFS whitespace */
 				if (saveall)
-					STPUTC(c, p);
+					STPUTC(psh, c, p);
 				continue;
 			}
@@ -160,5 +160,5 @@
 				startword = 2;
 				if (saveall)
-					STPUTC(c, p);
+					STPUTC(psh, c, p);
 				continue;
 			}
@@ -171,5 +171,5 @@
 				/* Not just a spare terminator */
 				saveall++;
-			STPUTC(c, p);
+			STPUTC(psh, c, p);
 			continue;
 		}
@@ -181,17 +181,17 @@
 			/* Last variable needs all IFS chars */
 			saveall++;
-			STPUTC(c, p);
+			STPUTC(psh, c, p);
 			continue;
 		}
 
-		STACKSTRNUL(p);
-		setvar(*ap, stackblock(), 0);
+		STACKSTRNUL(psh, p);
+		setvar(*ap, stackblock(psh), 0);
 		ap++;
-		STARTSTACKSTR(p);
-	}
-	STACKSTRNUL(p);
+		STARTSTACKSTR(psh, p);
+	}
+	STACKSTRNUL(psh, p);
 
 	/* Remove trailing IFS chars */
-	for (; stackblock() <= --p; *p = 0) {
+	for (; stackblock(psh) <= --p; *p = 0) {
 		if (!strchr(ifs, *p))
 			break;
@@ -203,5 +203,5 @@
 			break;
 	}
-	setvar(*ap, stackblock(), 0);
+	setvar(*ap, stackblock(psh), 0);
 
 	/* Set any remaining args to "" */
Index: trunk/src/kash/mystring.c
===================================================================
--- trunk/src/kash/mystring.c	(revision 1196)
+++ trunk/src/kash/mystring.c	(revision 1198)
@@ -111,9 +111,9 @@
 
 int
-number(const char *s)
+number(shinstance *psh, const char *s)
 {
 
 	if (! is_number(s))
-		error("Illegal number: %s", s);
+		error(psh, "Illegal number: %s", s);
 	return atoi(s);
 }
Index: trunk/src/kash/mystring.h
===================================================================
--- trunk/src/kash/mystring.h	(revision 1196)
+++ trunk/src/kash/mystring.h	(revision 1198)
@@ -36,8 +36,9 @@
 
 #include <string.h>
+#include "shinstance.h"
 
 void scopyn(const char *, char *, int);
 int prefix(const char *, const char *);
-int number(const char *);
+int number(shinstance *, const char *);
 int is_number(const char *);
 
Index: trunk/src/kash/options.c
===================================================================
--- trunk/src/kash/options.c	(revision 1196)
+++ trunk/src/kash/options.c	(revision 1198)
@@ -66,18 +66,19 @@
 #endif
 #include "show.h"
-
-char *arg0;			/* value of $0 */
-struct shparam shellparam;	/* current positional parameters */
-char **argptr;			/* argument list for builtin commands */
-char *optionarg;		/* set by nextopt (like getopt) */
-char *optptr;			/* used by nextopt */
-
-char *minusc;			/* argument to -c option */
-
-
-STATIC void options(int);
-STATIC void minus_o(char *, int);
-STATIC void setoption(int, int);
-STATIC int getopts(char *, char *, char **, char ***, char **);
+#include "shinstance.h"
+
+//char *arg0;			/* value of $0 */
+//struct shparam shellparam;	/* current positional parameters */
+//char **argptr;			/* argument list for builtin commands */
+//char *optionarg;		/* set by nextopt (like getopt) */
+//char *optptr;			/* used by nextopt */
+
+//char *minusc;			/* argument to -c option */
+
+
+STATIC void options(shinstance *, int);
+STATIC void minus_o(shinstance *, char *, int);
+STATIC void setoption(shinstance *, int, int);
+STATIC int getopts(shinstance *, char *, char *, char **, char ***, char **);
 
 
@@ -87,61 +88,61 @@
 
 void
-procargs(int argc, char **argv)
+procargs(shinstance *psh, int argc, char **argv)
 {
 	int i;
 
-	argptr = argv;
+	psh->argptr = argv;
 	if (argc > 0)
-		argptr++;
+		psh->argptr++;
 	for (i = 0; i < NOPTS; i++)
-		optlist[i].val = 2;
-	options(1);
-	if (*argptr == NULL && minusc == NULL)
-		sflag = 1;
-	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
-		iflag = 1;
-	if (mflag == 2)
-		mflag = iflag;
+		psh->optlist[i].val = 2;
+	options(psh, 1);
+	if (*psh->argptr == NULL && psh->minusc == NULL)
+		sflag(psh) = 1;
+	if (iflag(psh) == 2 && sflag(psh) == 1 && shfile_isatty(&psh->fdtab, 0) && shfile_isatty(&psh->fdtab, 1))
+		iflag(psh) = 1;
+	if (mflag(psh) == 2)
+		mflag(psh) = iflag(psh);
 	for (i = 0; i < NOPTS; i++)
-		if (optlist[i].val == 2)
-			optlist[i].val = 0;
+		if (psh->optlist[i].val == 2)
+			psh->optlist[i].val = 0;
 #if DEBUG == 2
-	debug = 1;
-#endif
-	arg0 = argv[0];
-	if (sflag == 0 && minusc == NULL) {
-		commandname = argv[0];
-		arg0 = *argptr++;
-		setinputfile(arg0, 0);
-		commandname = arg0;
+	debug(psh) = 1;
+#endif
+	psh->arg0 = argv[0];
+	if (sflag(psh) == 0 && psh->minusc == NULL) {
+		psh->commandname = argv[0];
+		psh->arg0 = *psh->argptr++;
+		setinputfile(psh, psh->arg0, 0);
+		psh->commandname = psh->arg0;
 	}
 	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
-	if (minusc != NULL) {
-		if (argptr == NULL || *argptr == NULL)
-			error("Bad -c option");
-		minusc = *argptr++;
-		if (*argptr != 0)
-			arg0 = *argptr++;
-	}
-
-	shellparam.p = argptr;
-	shellparam.reset = 1;
+	if (psh->minusc != NULL) {
+		if (psh->argptr == NULL || *psh->argptr == NULL)
+			error(psh, "Bad -c option");
+		psh->minusc = *psh->argptr++;
+		if (*psh->argptr != 0)
+			psh->arg0 = *psh->argptr++;
+	}
+
+	psh->shellparam.p = psh->argptr;
+	psh->shellparam.reset = 1;
 	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
-	while (*argptr) {
-		shellparam.nparam++;
-		argptr++;
-	}
-	optschanged();
+	while (*psh->argptr) {
+		psh->shellparam.nparam++;
+		psh->argptr++;
+	}
+	optschanged(psh);
 }
 
 
 void
-optschanged(void)
-{
-	setinteractive(iflag);
+optschanged(shinstance *psh)
+{
+	setinteractive(psh, iflag(psh));
 #ifndef SMALL
-	histedit();
-#endif
-	setjobctl(mflag);
+	histedit(psh);
+#endif
+	setjobctl(psh, mflag(psh));
 }
 
@@ -152,5 +153,5 @@
 
 STATIC void
-options(int cmdline)
+options(shinstance *psh, int cmdline)
 {
 	static char empty[] = "";
@@ -160,7 +161,7 @@
 
 	if (cmdline)
-		minusc = NULL;
-	while ((p = *argptr) != NULL) {
-		argptr++;
+		psh->minusc = NULL;
+	while ((p = *psh->argptr) != NULL) {
+		psh->argptr++;
 		if ((c = *p++) == '-') {
 			val = 1;
@@ -169,8 +170,8 @@
                                         /* "-" means turn off -x and -v */
                                         if (p[0] == '\0')
-                                                xflag = vflag = 0;
+                                                xflag(psh) = vflag(psh) = 0;
                                         /* "--" means reset params */
-                                        else if (*argptr == NULL)
-						setparam(argptr);
+                                        else if (*psh->argptr == NULL)
+						setparam(psh, psh->argptr);
                                 }
 				break;	  /* "-" or  "--" terminates options */
@@ -179,5 +180,5 @@
 			val = 0;
 		} else {
-			argptr--;
+			psh->argptr--;
 			break;
 		}
@@ -185,11 +186,11 @@
 			if (c == 'c' && cmdline) {
 				/* command is after shell args*/
-				minusc = empty;
+				psh->minusc = empty;
 			} else if (c == 'o') {
-				minus_o(*argptr, val);
-				if (*argptr)
-					argptr++;
+				minus_o(psh, *psh->argptr, val);
+				if (*psh->argptr)
+					psh->argptr++;
 			} else {
-				setoption(c, val);
+				setoption(psh, c, val);
 			}
 		}
@@ -198,18 +199,18 @@
 
 static void
-set_opt_val(int i, int val)
+set_opt_val(shinstance *psh, int i, int val)
 {
 	int j;
 	int flag;
 
-	if (val && (flag = optlist[i].opt_set)) {
+	if (val && (flag = psh->optlist[i].opt_set)) {
 		/* some options (eg vi/emacs) are mutually exclusive */
 		for (j = 0; j < NOPTS; j++)
-		    if (optlist[j].opt_set == flag)
-			optlist[j].val = 0;
-	}
-	optlist[i].val = val;
+		    if (psh->optlist[j].opt_set == flag)
+			psh->optlist[j].val = 0;
+	}
+	psh->optlist[i].val = val;
 #ifdef DEBUG
-	if (&optlist[i].val == &debug)
+	if (&psh->optlist[i].val == &debug(psh))
 		opentrace();
 #endif
@@ -217,20 +218,20 @@
 
 STATIC void
-minus_o(char *name, int val)
+minus_o(shinstance *psh, char *name, int val)
 {
 	int i;
 
 	if (name == NULL) {
-		out1str("Current option settings\n");
+		out1str(psh, "Current option settings\n");
 		for (i = 0; i < NOPTS; i++)
-			out1fmt("%-16s%s\n", optlist[i].name,
-				optlist[i].val ? "on" : "off");
+			out1fmt(psh, "%-16s%s\n", psh->optlist[i].name,
+				psh->optlist[i].val ? "on" : "off");
 	} else {
 		for (i = 0; i < NOPTS; i++)
-			if (equal(name, optlist[i].name)) {
-				set_opt_val(i, val);
+			if (equal(name, psh->optlist[i].name)) {
+				set_opt_val(psh, i, val);
 				return;
 			}
-		error("Illegal option -o %s", name);
+		error(psh, "Illegal option -o %s", name);
 	}
 }
@@ -238,14 +239,14 @@
 
 STATIC void
-setoption(int flag, int val)
+setoption(shinstance *psh, int flag, int val)
 {
 	int i;
 
 	for (i = 0; i < NOPTS; i++)
-		if (optlist[i].letter == flag) {
-			set_opt_val( i, val );
+		if (psh->optlist[i].letter == flag) {
+			set_opt_val(psh, i, val );
 			return;
 		}
-	error("Illegal option -%c", flag);
+	error(psh, "Illegal option -%c", flag);
 	/* NOTREACHED */
 }
@@ -259,7 +260,7 @@
 	int i;
 
-	for (i = 0; optlist[i].name; i++)
-		optlist[i].val = 0;
-	optschanged();
+	for (i = 0; psh->optlist[i].name; i++)
+		psh->optlist[i].val = 0;
+	optschanged(psh);
 
 }
@@ -272,5 +273,5 @@
 
 void
-setparam(char **argv)
+setparam(shinstance *psh, char **argv)
 {
 	char **newparam;
@@ -285,9 +286,9 @@
 	}
 	*ap = NULL;
-	freeparam(&shellparam);
-	shellparam.malloc = 1;
-	shellparam.nparam = nparam;
-	shellparam.p = newparam;
-	shellparam.optnext = NULL;
+	freeparam(&psh->shellparam);
+	psh->shellparam.malloc = 1;
+	psh->shellparam.nparam = nparam;
+	psh->shellparam.p = newparam;
+	psh->shellparam.optnext = NULL;
 }
 
@@ -316,5 +317,5 @@
 
 int
-shiftcmd(int argc, char **argv)
+shiftcmd(shinstance *psh, int argc, char **argv)
 {
 	int n;
@@ -323,16 +324,16 @@
 	n = 1;
 	if (argc > 1)
-		n = number(argv[1]);
-	if (n > shellparam.nparam)
-		error("can't shift that many");
+		n = number(psh, argv[1]);
+	if (n > psh->shellparam.nparam)
+		error(psh, "can't shift that many");
 	INTOFF;
-	shellparam.nparam -= n;
-	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
-		if (shellparam.malloc)
+	psh->shellparam.nparam -= n;
+	for (ap1 = psh->shellparam.p ; --n >= 0 ; ap1++) {
+		if (psh->shellparam.malloc)
 			ckfree(*ap1);
 	}
-	ap2 = shellparam.p;
+	ap2 = psh->shellparam.p;
 	while ((*ap2++ = *ap1++) != NULL);
-	shellparam.optnext = NULL;
+	psh->shellparam.optnext = NULL;
 	INTON;
 	return 0;
@@ -346,13 +347,13 @@
 
 int
-setcmd(int argc, char **argv)
+setcmd(shinstance *psh, int argc, char **argv)
 {
 	if (argc == 1)
-		return showvars(0, 0, 1);
+		return showvars(psh, 0, 0, 1);
 	INTOFF;
-	options(0);
-	optschanged();
-	if (*argptr != NULL) {
-		setparam(argptr);
+	options(psh, 0);
+	optschanged(psh);
+	if (*psh->argptr != NULL) {
+		setparam(psh, psh->argptr);
 	}
 	INTON;
@@ -362,10 +363,9 @@
 
 void
-getoptsreset(value)
-	const char *value;
-{
-	if (number(value) == 1) {
-		shellparam.optnext = NULL;
-		shellparam.reset = 1;
+getoptsreset(shinstance *psh, const char *value)
+{
+	if (number(psh, value) == 1) {
+		psh->shellparam.optnext = NULL;
+		psh->shellparam.reset = 1;
 	}
 }
@@ -379,27 +379,27 @@
 
 int
-getoptscmd(int argc, char **argv)
+getoptscmd(shinstance *psh, int argc, char **argv)
 {
 	char **optbase;
 
 	if (argc < 3)
-		error("usage: getopts optstring var [arg]");
+		error(psh, "usage: getopts optstring var [arg]");
 	else if (argc == 3)
-		optbase = shellparam.p;
+		optbase = psh->shellparam.p;
 	else
 		optbase = &argv[3];
 
-	if (shellparam.reset == 1) {
-		shellparam.optnext = optbase;
-		shellparam.optptr = NULL;
-		shellparam.reset = 0;
-	}
-
-	return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
-		       &shellparam.optptr);
+	if (psh->shellparam.reset == 1) {
+		psh->shellparam.optnext = optbase;
+		psh->shellparam.optptr = NULL;
+		psh->shellparam.reset = 0;
+	}
+
+	return getopts(psh, argv[1], argv[2], optbase, &psh->shellparam.optnext,
+		       &psh->shellparam.optptr);
 }
 
 STATIC int
-getopts(char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr)
+getopts(shinstance *psh, char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr)
 {
 	char *p, *q;
@@ -417,5 +417,5 @@
 		if (p == NULL || *p != '-' || *++p == '\0') {
 atend:
-			ind = *optnext - optfirst + 1;
+			ind = (int)(*optnext - optfirst + 1);
 			*optnext = NULL;
 			p = NULL;
@@ -434,8 +434,8 @@
 				s[0] = c;
 				s[1] = '\0';
-				err |= setvarsafe("OPTARG", s, 0);
+				err |= setvarsafe(psh, "OPTARG", s, 0);
 			} else {
-				outfmt(&errout, "Illegal option -%c\n", c);
-				(void) unsetvar("OPTARG", 0);
+				outfmt(&psh->errout, "Illegal option -%c\n", c);
+				(void) unsetvar(psh, "OPTARG", 0);
 			}
 			c = '?';
@@ -451,9 +451,9 @@
 				s[0] = c;
 				s[1] = '\0';
-				err |= setvarsafe("OPTARG", s, 0);
+				err |= setvarsafe(psh, "OPTARG", s, 0);
 				c = ':';
 			} else {
-				outfmt(&errout, "No arg for -%c option\n", c);
-				(void) unsetvar("OPTARG", 0);
+				outfmt(&psh->errout, "No arg for -%c option\n", c);
+				(void) unsetvar(psh, "OPTARG", 0);
 				c = '?';
 			}
@@ -463,9 +463,9 @@
 		if (p == **optnext)
 			(*optnext)++;
-		err |= setvarsafe("OPTARG", p, 0);
+		err |= setvarsafe(psh, "OPTARG", p, 0);
 		p = NULL;
 	} else
-		err |= setvarsafe("OPTARG", "", 0);
-	ind = *optnext - optfirst + 1;
+		err |= setvarsafe(psh, "OPTARG", "", 0);
+	ind = (int)(*optnext - optfirst + 1);
 	goto out;
 
@@ -477,13 +477,13 @@
 	*optpptr = p;
 	fmtstr(s, sizeof(s), "%d", ind);
-	err |= setvarsafe("OPTIND", s, VNOFUNC);
+	err |= setvarsafe(psh, "OPTIND", s, VNOFUNC);
 	s[0] = c;
 	s[1] = '\0';
-	err |= setvarsafe(optvar, s, 0);
+	err |= setvarsafe(psh, optvar, s, 0);
 	if (err) {
 		*optnext = NULL;
 		*optpptr = NULL;
-		output_flushall();
-		exraise(EXERROR);
+		output_flushall(psh);
+		exraise(psh, EXERROR);
 	}
 	return done;
@@ -502,5 +502,5 @@
 
 int
-nextopt(const char *optstring)
+nextopt(shinstance *psh, const char *optstring)
 {
 	char *p;
@@ -508,9 +508,9 @@
 	char c;
 
-	if ((p = optptr) == NULL || *p == '\0') {
-		p = *argptr;
+	if ((p = psh->optptr) == NULL || *p == '\0') {
+		p = *psh->argptr;
 		if (p == NULL || *p != '-' || *++p == '\0')
 			return '\0';
-		argptr++;
+		psh->argptr++;
 		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
 			return '\0';
@@ -519,15 +519,15 @@
 	for (q = optstring ; *q != c ; ) {
 		if (*q == '\0')
-			error("Illegal option -%c", c);
+			error(psh, "Illegal option -%c", c);
 		if (*++q == ':')
 			q++;
 	}
 	if (*++q == ':') {
-		if (*p == '\0' && (p = *argptr++) == NULL)
-			error("No arg for -%c option", c);
-		optionarg = p;
+		if (*p == '\0' && (p = *psh->argptr++) == NULL)
+			error(psh, "No arg for -%c option", c);
+		psh->optionarg = p;
 		p = NULL;
 	}
-	optptr = p;
+	psh->optptr = p;
 	return c;
 }
Index: trunk/src/kash/options.h
===================================================================
--- trunk/src/kash/options.h	(revision 1196)
+++ trunk/src/kash/options.h	(revision 1198)
@@ -35,4 +35,7 @@
  */
 
+#ifndef ___options_h
+#define ___options_h
+
 struct shparam {
 	int nparam;		/* # of positional parameters (without $0) */
@@ -58,5 +61,5 @@
 #else
 # define NOPTS 20
-#endif 
+#endif
 
 #ifdef DEFINE_OPTIONS
@@ -69,44 +72,44 @@
 
 DEF_OPT( "errexit",	'e' )	/* exit on error */
-#define eflag optlist[0].val
+#define eflag(psh) (psh)->optlist[0].val
 DEF_OPT( "noglob",	'f' )	/* no pathname expansion */
-#define fflag optlist[1].val
+#define fflag(psh) (psh)->optlist[1].val
 DEF_OPT( "ignoreeof",	'I' )	/* do not exit on EOF */
-#define Iflag optlist[2].val
+#define Iflag(psh) (psh)->optlist[2].val
 DEF_OPT( "interactive",'i' )	/* interactive shell */
-#define iflag optlist[3].val
+#define iflag(psh) (psh)->optlist[3].val
 DEF_OPT( "monitor",	'm' )	/* job control */
-#define mflag optlist[4].val
+#define mflag(psh) (psh)->optlist[4].val
 DEF_OPT( "noexec",	'n' )	/* [U] do not exec commands */
-#define nflag optlist[5].val
+#define nflag(psh) (psh)->optlist[5].val
 DEF_OPT( "stdin",	's' )	/* read from stdin */
-#define sflag optlist[6].val
+#define sflag(psh) (psh)->optlist[6].val
 DEF_OPT( "xtrace",	'x' )	/* trace after expansion */
-#define xflag optlist[7].val
+#define xflag(psh) (psh)->optlist[7].val
 DEF_OPT( "verbose",	'v' )	/* trace read input */
-#define vflag optlist[8].val
+#define vflag(psh) (psh)->optlist[8].val
 DEF_OPTS( "vi",		'V', 'V' )	/* vi style editing */
-#define Vflag optlist[9].val
+#define Vflag(psh) (psh)->optlist[9].val
 DEF_OPTS( "emacs",	'E', 'V' )	/* emacs style editing */
-#define	Eflag optlist[10].val
+#define	Eflag(psh) (psh)->optlist[10].val
 DEF_OPT( "noclobber",	'C' )	/* do not overwrite files with > */
-#define	Cflag optlist[11].val
+#define	Cflag(psh) (psh)->optlist[11].val
 DEF_OPT( "allexport",	'a' )	/* export all variables */
-#define	aflag optlist[12].val
+#define	aflag(psh) (psh)->optlist[12].val
 DEF_OPT( "notify",	'b' )	/* [U] report completion of background jobs */
-#define	bflag optlist[13].val
+#define	bflag(psh) (psh)->optlist[13].val
 DEF_OPT( "nounset",	'u' )	/* error expansion of unset variables */
-#define	uflag optlist[14].val
+#define	uflag(psh) (psh)->optlist[14].val
 DEF_OPT( "quietprofile", 'q' )
-#define	qflag optlist[15].val
+#define	qflag(psh) (psh)->optlist[15].val
 DEF_OPT( "nolog",	0 )	/* [U] no functon defs in command history */
-#define	nolog optlist[16].val
+#define	nolog(psh) (psh)->optlist[16].val
 DEF_OPT( "cdprint",	0 )	/* always print result of cd */
-#define	cdprint optlist[17].val
+#define	cdprint(psh) (psh)->optlist[17].val
 DEF_OPT( "tabcomplete",	0 )	/* <tab> causes filename expansion */
-#define	tabcomplete optlist[18].val
+#define	tabcomplete(psh) (psh)->optlist[18].val
 #ifdef DEBUG
 DEF_OPT( "debug",	0 )	/* enable debug prints */
-#define	debug optlist[19].val
+#define	debug(psh) (psh)->optlist[19].val
 #endif
 
@@ -136,2 +139,4 @@
 int nextopt(struct shinstance *, const char *);
 void getoptsreset(struct shinstance *, const char *);
+
+#endif
Index: trunk/src/kash/output.c
===================================================================
--- trunk/src/kash/output.c	(revision 1196)
+++ trunk/src/kash/output.c	(revision 1198)
@@ -190,5 +190,5 @@
 	if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
 		return;
-	if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
+	if (xwrite(psh, dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
 		dest->flags |= OUTPUT_ERR;
 	dest->nextc = dest->buf;
@@ -480,5 +480,5 @@
 
 int
-xwrite(int fd, char *buf, int nbytes)
+xwrite(shinstance *psh, int fd, char *buf, int nbytes)
 {
 	int ntry;
@@ -489,5 +489,5 @@
 	ntry = 0;
 	for (;;) {
-		i = write(fd, buf, n);
+		i = shfile_write(&psh->fdtab, fd, buf, n);
 		if (i > 0) {
 			if ((n -= i) <= 0)
@@ -511,9 +511,9 @@
 
 int
-xioctl(int fd, unsigned long request, char *arg)
+xioctl(shinstance *psh, int fd, unsigned long request, char *arg)
 {
 	int i;
 
-	while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
+	while ((i = shfile_ioctl(&psh->fdtab, fd, request, arg)) == -1 && errno == EINTR);
 	return i;
 }
Index: trunk/src/kash/output.h
===================================================================
--- trunk/src/kash/output.h	(revision 1196)
+++ trunk/src/kash/output.h	(revision 1198)
@@ -72,6 +72,6 @@
     __attribute__((__format__(__printf__,3,4)));
 void doformat(struct output *, const char *, va_list);
-int xwrite(int, char *, int);
-int xioctl(int, unsigned long, char *);
+int xwrite(struct shinstance *, int, char *, int);
+int xioctl(struct shinstance *, int, unsigned long, char *);
 
 #define outc(c, file)	(--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
Index: trunk/src/kash/parser.c
===================================================================
--- trunk/src/kash/parser.c	(revision 1196)
+++ trunk/src/kash/parser.c	(revision 1198)
@@ -171,5 +171,5 @@
 				n2->type = NBACKGND;
 			} else {
-				n3 = (union node *)stalloc(sizeof (struct nredir));
+				n3 = (union node *)stalloc(psh, sizeof (struct nredir));
 				n3->type = NBACKGND;
 				n3->nredir.n = n2;
@@ -182,5 +182,5 @@
 		}
 		else {
-			n3 = (union node *)stalloc(sizeof (struct nbinary));
+			n3 = (union node *)stalloc(psh, sizeof (struct nbinary));
 			n3->type = NSEMI;
 			n3->nbinary.ch1 = n1;
@@ -239,5 +239,5 @@
 		}
 		n2 = pipeline();
-		n3 = (union node *)stalloc(sizeof (struct nbinary));
+		n3 = (union node *)stalloc(psh, sizeof (struct nbinary));
 		n3->type = t;
 		n3->nbinary.ch1 = n1;
@@ -263,13 +263,13 @@
 	n1 = command();
 	if (readtoken() == TPIPE) {
-		pipenode = (union node *)stalloc(sizeof (struct npipe));
+		pipenode = (union node *)stalloc(psh, sizeof (struct npipe));
 		pipenode->type = NPIPE;
 		pipenode->npipe.backgnd = 0;
-		lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+		lp = (struct nodelist *)stalloc(psh, sizeof (struct nodelist));
 		pipenode->npipe.cmdlist = lp;
 		lp->n = n1;
 		do {
 			prev = lp;
-			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+			lp = (struct nodelist *)stalloc(psh, sizeof (struct nodelist));
 			lp->n = command();
 			prev->next = lp;
@@ -280,5 +280,5 @@
 	tokpushback++;
 	if (negate) {
-		n2 = (union node *)stalloc(sizeof (struct nnot));
+		n2 = (union node *)stalloc(psh, sizeof (struct nnot));
 		n2->type = NNOT;
 		n2->nnot.com = n1;
@@ -320,5 +320,5 @@
 	switch (readtoken()) {
 	case TIF:
-		n1 = (union node *)stalloc(sizeof (struct nif));
+		n1 = (union node *)stalloc(psh, sizeof (struct nif));
 		n1->type = NIF;
 		n1->nif.test = list(0);
@@ -328,5 +328,5 @@
 		n2 = n1;
 		while (readtoken() == TELIF) {
-			n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
+			n2->nif.elsepart = (union node *)stalloc(psh, sizeof (struct nif));
 			n2 = n2->nif.elsepart;
 			n2->type = NIF;
@@ -349,5 +349,5 @@
 	case TUNTIL: {
 		int got;
-		n1 = (union node *)stalloc(sizeof (struct nbinary));
+		n1 = (union node *)stalloc(psh, sizeof (struct nbinary));
 		n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
 		n1->nbinary.ch1 = list(0);
@@ -365,5 +365,5 @@
 		if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
 			synerror("Bad for loop variable");
-		n1 = (union node *)stalloc(sizeof (struct nfor));
+		n1 = (union node *)stalloc(psh, sizeof (struct nfor));
 		n1->type = NFOR;
 		n1->nfor.var = wordtext;
@@ -371,5 +371,5 @@
 			app = &ap;
 			while (readtoken() == TWORD) {
-				n2 = (union node *)stalloc(sizeof (struct narg));
+				n2 = (union node *)stalloc(psh, sizeof (struct narg));
 				n2->type = NARG;
 				n2->narg.text = wordtext;
@@ -385,5 +385,5 @@
 			static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
 								   '@', '=', '\0'};
-			n2 = (union node *)stalloc(sizeof (struct narg));
+			n2 = (union node *)stalloc(psh, sizeof (struct narg));
 			n2->type = NARG;
 			n2->narg.text = argvars;
@@ -411,9 +411,9 @@
 		break;
 	case TCASE:
-		n1 = (union node *)stalloc(sizeof (struct ncase));
+		n1 = (union node *)stalloc(psh, sizeof (struct ncase));
 		n1->type = NCASE;
 		if (readtoken() != TWORD)
 			synexpect(TWORD);
-		n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
+		n1->ncase.expr = n2 = (union node *)stalloc(psh, sizeof (struct narg));
 		n2->type = NARG;
 		n2->narg.text = wordtext;
@@ -427,9 +427,9 @@
 		checkkwd = 2, readtoken();
 		do {
-			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
+			*cpp = cp = (union node *)stalloc(psh, sizeof (struct nclist));
 			cp->type = NCLIST;
 			app = &cp->nclist.pattern;
 			for (;;) {
-				*app = ap = (union node *)stalloc(sizeof (struct narg));
+				*app = ap = (union node *)stalloc(psh, sizeof (struct narg));
 				ap->type = NARG;
 				ap->narg.text = wordtext;
@@ -465,5 +465,5 @@
 		break;
 	case TLP:
-		n1 = (union node *)stalloc(sizeof (struct nredir));
+		n1 = (union node *)stalloc(psh, sizeof (struct nredir));
 		n1->type = NSUBSHELL;
 		n1->nredir.n = list(0);
@@ -511,5 +511,5 @@
 	if (redir) {
 		if (n1->type != NSUBSHELL) {
-			n2 = (union node *)stalloc(sizeof (struct nredir));
+			n2 = (union node *)stalloc(psh, sizeof (struct nredir));
 			n2->type = NREDIR;
 			n2->nredir.n = n1;
@@ -521,5 +521,5 @@
 checkneg:
 	if (negate) {
-		n2 = (union node *)stalloc(sizeof (struct nnot));
+		n2 = (union node *)stalloc(psh, sizeof (struct nnot));
 		n2->type = NNOT;
 		n2->nnot.com = n1;
@@ -561,5 +561,5 @@
 	for (;;) {
 		if (readtoken() == TWORD) {
-			n = (union node *)stalloc(sizeof (struct narg));
+			n = (union node *)stalloc(psh, sizeof (struct narg));
 			n->type = NARG;
 			n->narg.text = wordtext;
@@ -590,5 +590,5 @@
 	*app = NULL;
 	*rpp = NULL;
-	n = (union node *)stalloc(sizeof (struct ncmd));
+	n = (union node *)stalloc(psh, sizeof (struct ncmd));
 	n->type = NCMD;
 	n->ncmd.backgnd = 0;
@@ -598,5 +598,5 @@
 checkneg:
 	if (negate) {
-		n2 = (union node *)stalloc(sizeof (struct nnot));
+		n2 = (union node *)stalloc(psh, sizeof (struct nnot));
 		n2->type = NNOT;
 		n2->nnot.com = n;
@@ -612,5 +612,5 @@
 	union node *n;
 
-	n = (union node *)stalloc(sizeof (struct narg));
+	n = (union node *)stalloc(psh, sizeof (struct narg));
 	n->type = NARG;
 	n->narg.next = NULL;
@@ -697,5 +697,5 @@
 		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
 				here->eofmark, here->striptabs);
-		n = (union node *)stalloc(sizeof (struct narg));
+		n = (union node *)stalloc(psh, sizeof (struct narg));
 		n->narg.type = NARG;
 		n->narg.next = NULL;
@@ -953,5 +953,5 @@
 	parenlevel = 0;
 
-	STARTSTACKSTR(out);
+	STARTSTACKSTR(psh, out);
 	loop: {	/* for each line, until end of word */
 #if ATTY
@@ -967,10 +967,10 @@
 		CHECKEND();	/* set c to PEOF if at end of here document */
 		for (;;) {	/* until end of line or end of word */
-			CHECKSTRSPACE(4, out);	/* permit 4 calls to USTPUTC */
+			CHECKSTRSPACE(psh, 4, out);	/* permit 4 calls to USTPUTC */
 			switch(syntax[c]) {
 			case CNL:	/* '\n' */
 				if (syntax == BASESYNTAX)
 					goto endword;	/* exit outer loop */
-				USTPUTC(c, out);
+				USTPUTC(psh, c, out);
 				plinno++;
 				if (doprompt)
@@ -981,15 +981,15 @@
 				goto loop;		/* continue outer loop */
 			case CWORD:
-				USTPUTC(c, out);
+				USTPUTC(psh, c, out);
 				break;
 			case CCTL:
 				if (eofmark == NULL || ISDBLQUOTE())
-					USTPUTC(CTLESC, out);
-				USTPUTC(c, out);
+					USTPUTC(psh, CTLESC, out);
+				USTPUTC(psh, c, out);
 				break;
 			case CBACK:	/* backslash */
 				c = pgetc();
 				if (c == PEOF) {
-					USTPUTC('\\', out);
+					USTPUTC(psh, '\\', out);
 					pungetc();
 					break;
@@ -1006,20 +1006,20 @@
 				    c != '`' && c != '$' &&
 				    (c != '"' || eofmark != NULL))
-					USTPUTC('\\', out);
+					USTPUTC(psh, '\\', out);
 				if (SQSYNTAX[c] == CCTL)
-					USTPUTC(CTLESC, out);
+					USTPUTC(psh, CTLESC, out);
 				else if (eofmark == NULL) {
-					USTPUTC(CTLQUOTEMARK, out);
-					USTPUTC(c, out);
+					USTPUTC(psh, CTLQUOTEMARK, out);
+					USTPUTC(psh, c, out);
 					if (varnest != 0)
-						USTPUTC(CTLQUOTEEND, out);
+						USTPUTC(psh, CTLQUOTEEND, out);
 					break;
 				}
-				USTPUTC(c, out);
+				USTPUTC(psh, c, out);
 				break;
 			case CSQUOTE:
 				if (syntax != SQSYNTAX) {
 					if (eofmark == NULL)
-						USTPUTC(CTLQUOTEMARK, out);
+						USTPUTC(psh, CTLQUOTEMARK, out);
 					quotef = 1;
 					syntax = SQSYNTAX;
@@ -1029,5 +1029,5 @@
 				    varnest == 0) {
 					/* Ignore inside quoted here document */
-					USTPUTC(c, out);
+					USTPUTC(psh, c, out);
 					break;
 				}
@@ -1038,5 +1038,5 @@
 					syntax = BASESYNTAX;
 					if (varnest != 0)
-						USTPUTC(CTLQUOTEEND, out);
+						USTPUTC(psh, CTLQUOTEEND, out);
 				}
 				break;
@@ -1045,5 +1045,5 @@
 				    varnest == 0) {
 					/* Ignore inside here document */
-					USTPUTC(c, out);
+					USTPUTC(psh, c, out);
 					break;
 				}
@@ -1056,5 +1056,5 @@
 						syntax = DQSYNTAX;
 						SETDBLQUOTE();
-						USTPUTC(CTLQUOTEMARK, out);
+						USTPUTC(psh, CTLQUOTEMARK, out);
 					}
 					break;
@@ -1064,5 +1064,5 @@
 				if (ISDBLQUOTE()) {
 					if (varnest != 0)
-						USTPUTC(CTLQUOTEEND, out);
+						USTPUTC(psh, CTLQUOTEEND, out);
 					syntax = BASESYNTAX;
 					CLRDBLQUOTE();
@@ -1070,5 +1070,5 @@
 					syntax = DQSYNTAX;
 					SETDBLQUOTE();
-					USTPUTC(CTLQUOTEMARK, out);
+					USTPUTC(psh, CTLQUOTEMARK, out);
 				}
 				break;
@@ -1079,21 +1079,21 @@
 				if (varnest > 0 && !ISDBLQUOTE()) {
 					varnest--;
-					USTPUTC(CTLENDVAR, out);
+					USTPUTC(psh, CTLENDVAR, out);
 				} else {
-					USTPUTC(c, out);
+					USTPUTC(psh, c, out);
 				}
 				break;
 			case CLP:	/* '(' in arithmetic */
 				parenlevel++;
-				USTPUTC(c, out);
+				USTPUTC(psh, c, out);
 				break;
 			case CRP:	/* ')' in arithmetic */
 				if (parenlevel > 0) {
-					USTPUTC(c, out);
+					USTPUTC(psh, c, out);
 					--parenlevel;
 				} else {
 					if (pgetc() == ')') {
 						if (--arinest == 0) {
-							USTPUTC(CTLENDARI, out);
+							USTPUTC(psh, CTLENDARI, out);
 							syntax = prevsyntax;
 							if (syntax == DQSYNTAX)
@@ -1102,5 +1102,5 @@
 								CLRDBLQUOTE();
 						} else
-							USTPUTC(')', out);
+							USTPUTC(psh, ')', out);
 					} else {
 						/*
@@ -1109,5 +1109,5 @@
 						 */
 						pungetc();
-						USTPUTC(')', out);
+						USTPUTC(psh, ')', out);
 					}
 				}
@@ -1121,5 +1121,5 @@
 				if (varnest == 0)
 					goto endword;	/* exit outer loop */
-				USTPUTC(c, out);
+				USTPUTC(psh, c, out);
 			}
 			c = pgetc_macro();
@@ -1136,7 +1136,7 @@
 		synerror("Missing '}'");
 	}
-	USTPUTC('\0', out);
-	len = out - stackblock();
-	out = stackblock();
+	USTPUTC(psh, '\0', out);
+	len = out - stackblock(psh);
+	out = stackblock(psh);
 	if (eofmark == NULL) {
 		if ((c == '>' || c == '<')
@@ -1152,5 +1152,5 @@
 	quoteflag = quotef;
 	backquotelist = bqlist;
-	grabstackblock(len);
+	grabstackblock(psh, len);
 	wordtext = out;
 	if (dblquotep != NULL)
@@ -1203,5 +1203,5 @@
 	union node *np;
 
-	np = (union node *)stalloc(sizeof (struct nfile));
+	np = (union node *)stalloc(psh, sizeof (struct nfile));
 	if (c == '>') {
 		np->nfile.fd = 1;
@@ -1222,9 +1222,9 @@
 		case '<':
 			if (sizeof (struct nfile) != sizeof (struct nhere)) {
-				np = (union node *)stalloc(sizeof (struct nhere));
+				np = (union node *)stalloc(psh, sizeof (struct nhere));
 				np->nfile.fd = 0;
 			}
 			np->type = NHERE;
-			heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
+			heredoc = (struct heredoc *)stalloc(psh, sizeof (struct heredoc));
 			heredoc->here = np;
 			if ((c = pgetc()) == '-') {
@@ -1271,5 +1271,5 @@
 	c = pgetc();
 	if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) {
-		USTPUTC('$', out);
+		USTPUTC(psh, '$', out);
 		pungetc();
 	} else if (c == '(') {	/* $(command) or $((arith)) */
@@ -1281,7 +1281,7 @@
 		}
 	} else {
-		USTPUTC(CTLVAR, out);
-		typeloc = out - stackblock();
-		USTPUTC(VSNORMAL, out);
+		USTPUTC(psh, CTLVAR, out);
+		typeloc = out - stackblock(psh);
+		USTPUTC(psh, VSNORMAL, out);
 		subtype = VSNORMAL;
 		if (c == OPENBRACE) {
@@ -1298,15 +1298,15 @@
 		if (is_name(c)) {
 			do {
-				STPUTC(c, out);
+				STPUTC(psh, c, out);
 				c = pgetc();
 			} while (is_in_name(c));
 		} else if (is_digit(c)) {
 			do {
-				USTPUTC(c, out);
+				USTPUTC(psh, c, out);
 				c = pgetc();
 			} while (is_digit(c));
 		}
 		else if (is_special(c)) {
-			USTPUTC(c, out);
+			USTPUTC(psh, c, out);
 			c = pgetc();
 		}
@@ -1314,5 +1314,5 @@
 badsub:			synerror("Bad substitution");
 
-		STPUTC('=', out);
+		STPUTC(psh, '=', out);
 		flags = 0;
 		if (subtype == 0) {
@@ -1347,5 +1347,5 @@
 		if (ISDBLQUOTE() || arinest)
 			flags |= VSQUOTE;
-		*(stackblock() + typeloc) = subtype | flags;
+		*(stackblock(psh) + typeloc) = subtype | flags;
 		if (subtype != VSNORMAL) {
 			varnest++;
@@ -1391,8 +1391,8 @@
 	INTOFF;
 	str = NULL;
-	savelen = out - stackblock();
+	savelen = out - stackblock(psh);
 	if (savelen > 0) {
 		str = ckmalloc(savelen);
-		memcpy(str, stackblock(), savelen);
+		memcpy(str, stackblock(psh), savelen);
 	}
 	savehandler = handler;
@@ -1409,5 +1409,5 @@
 
 
-                STARTSTACKSTR(pout);
+                STARTSTACKSTR(psh, pout);
 		for (;;) {
 			if (needprompt) {
@@ -1436,5 +1436,5 @@
                                 if (pc != '\\' && pc != '`' && pc != '$'
                                     && (!ISDBLQUOTE() || pc != '"'))
-                                        STPUTC('\\', pout);
+                                        STPUTC(psh, '\\', pout);
 				break;
 
@@ -1452,11 +1452,11 @@
 				break;
 			}
-			STPUTC(pc, pout);
+			STPUTC(psh, pc, pout);
                 }
 done:
-                STPUTC('\0', pout);
-                psavelen = pout - stackblock();
+                STPUTC(psh, '\0', pout);
+                psavelen = pout - stackblock(psh);
                 if (psavelen > 0) {
-			pstr = grabstackstr(pout);
+			pstr = grabstackstr(psh, pout);
 			setinputstring(pstr, 1);
                 }
@@ -1465,5 +1465,5 @@
 	while (*nlpp)
 		nlpp = &(*nlpp)->next;
-	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+	*nlpp = (struct nodelist *)stalloc(psh, sizeof (struct nodelist));
 	(*nlpp)->next = NULL;
 	parsebackquote = oldstyle;
@@ -1492,10 +1492,10 @@
 		tokpushback = 0;
 	}
-	while (stackblocksize() <= savelen)
-		growstackblock();
-	STARTSTACKSTR(out);
+	while (stackblocksize(psh) <= savelen)
+		growstackblock(psh);
+	STARTSTACKSTR(psh, out);
 	if (str) {
 		memcpy(out, str, savelen);
-		STADJUST(savelen, out);
+		STADJUST(psh, savelen, out);
 		INTOFF;
 		ckfree(str);
@@ -1506,7 +1506,7 @@
 	handler = savehandler;
 	if (arinest || ISDBLQUOTE())
-		USTPUTC(CTLBACKQ | CTLQUOTE, out);
+		USTPUTC(psh, CTLBACKQ | CTLQUOTE, out);
 	else
-		USTPUTC(CTLBACKQ, out);
+		USTPUTC(psh, CTLBACKQ, out);
 	if (oldstyle)
 		goto parsebackq_oldreturn;
@@ -1523,9 +1523,9 @@
 		prevsyntax = syntax;
 		syntax = ARISYNTAX;
-		USTPUTC(CTLARI, out);
+		USTPUTC(psh, CTLARI, out);
 		if (ISDBLQUOTE())
-			USTPUTC('"',out);
+			USTPUTC(psh, '"',out);
 		else
-			USTPUTC(' ',out);
+			USTPUTC(psh, ' ',out);
 	} else {
 		/*
@@ -1533,5 +1533,5 @@
 		 * parenthesis, which should be equivalent
 		 */
-		USTPUTC('(', out);
+		USTPUTC(psh, '(', out);
 	}
 	goto parsearith_return;
Index: trunk/src/kash/redir.c
===================================================================
--- trunk/src/kash/redir.c	(revision 1196)
+++ trunk/src/kash/redir.c	(revision 1198)
@@ -206,5 +206,5 @@
 		break;
 	case NTO:
-		if (Cflag)
+		if (Cflag(psh))
 			oflags |= O_EXCL;
 		/* FALLTHROUGH */
@@ -267,5 +267,5 @@
 		len = strlen(redir->nhere.doc->narg.text);
 		if (len <= PIPESIZE) {
-			xwrite(pip[1], redir->nhere.doc->narg.text, len);
+			xwrite(psh, pip[1], redir->nhere.doc->narg.text, len);
 			goto out;
 		}
@@ -281,5 +281,5 @@
 		signal(SIGPIPE, SIG_DFL);
 		if (redir->type == NHERE)
-			xwrite(pip[1], redir->nhere.doc->narg.text, len);
+			xwrite(psh, pip[1], redir->nhere.doc->narg.text, len);
 		else
 			expandhere(redir->nhere.doc, pip[1]);
Index: trunk/src/kash/shfile.h
===================================================================
--- trunk/src/kash/shfile.h	(revision 1196)
+++ trunk/src/kash/shfile.h	(revision 1198)
@@ -2,5 +2,5 @@
 /** @file
  *
- * File management. 
+ * File management.
  *
  * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
@@ -55,4 +55,7 @@
 int shfile_pipe(shfdtab *, int [2]);
 int shfile_close(shfdtab *, unsigned);
+long shfile_read(shfdtab *, int, void *, size_t);
+long shfile_write(shfdtab *, int, const void *, size_t);
+long shfile_lseek(shfdtab *, int, long, int);
 int shfile_fcntl(shfdtab *, int fd, int cmd, int arg);
 #ifdef _MSC_VER
@@ -71,5 +74,6 @@
 int shfile_chdir(shfdtab *, const char *);
 char *shfile_getcwd(shfdtab *, char *, int);
-         
+int shfile_isatty(shfdtab *, int);
+
 #endif
 
Index: trunk/src/kash/shinstance.c
===================================================================
--- trunk/src/kash/shinstance.c	(revision 1196)
+++ trunk/src/kash/shinstance.c	(revision 1198)
@@ -30,9 +30,9 @@
 /**
  * Creates a root shell instance.
- * 
+ *
  * @param   inherit     The shell to inherit from. If NULL inherit from environment and such.
  * @param   argc        The argument count.
  * @param   argv        The argument vector.
- * 
+ *
  * @returns pointer to root shell on success, NULL on failure.
  */
@@ -45,5 +45,11 @@
     {
         memset(psh, 0, sizeof(*psh));
-        psh->
+
+        /* memalloc.c */
+        psh->stacknleft = MINSIZE;
+        psh->herefd = -1;
+        psh->stackp = &psh->stackbase;
+        psh->stacknxt = psh->stackbase.space;
+
     }
     return psh;
Index: trunk/src/kash/shinstance.h
===================================================================
--- trunk/src/kash/shinstance.h	(revision 1196)
+++ trunk/src/kash/shinstance.h	(revision 1198)
@@ -31,6 +31,14 @@
 #include "shthread.h"
 #include "shfile.h"
+#include "output.h"
+#include "options.h"
 
 #include "var.h"
+
+#define MINSIZE 504		/* minimum size of a block */
+struct stack_block {
+	struct stack_block *prev;
+	char space[MINSIZE];
+};
 
 
@@ -97,5 +105,5 @@
 #ifdef _MSC_VER
     struct var          vpath2;
-#endif 
+#endif
     struct var          vps1;
     struct var          vps2;
@@ -115,8 +123,14 @@
 
     /* memalloc.h */
-    char               *stacknxt;
-    int                 stacknleft;
+    char               *stacknxt/* = stackbase.space*/;
+    int                 stacknleft/* = MINSIZE*/;
     int                 sstrnleft;
-    int                 herefd;
+    int                 herefd/* = -1 */;
+
+    /* memalloc.c */
+    struct stack_block  stackbase;
+    struct stack_block *stackp/* = &stackbase*/;
+    struct stackmark   *markp;
+
 
     /* jobs.h */
@@ -151,5 +165,5 @@
     /* cd.c */
     char               *curdir;         /**< current working directory */
-    char               *prevdir;	/**< previous working directory */
+    char               *prevdir;        /**< previous working directory */
     char               *cdcomppath;
     int                 getpwd_first;   /**< static in getpwd. (initialized to 1!) */
@@ -160,4 +174,10 @@
     /* eval.c */
     int                 vforked;
+
+    /* mail.c */
+#define MAXMBOXES 10
+    int                 nmboxes;        /**< number of mailboxes */
+    time_t              mailtime[MAXMBOXES]; /**< times of mailboxes */
+
 } shinstance;
 
@@ -172,5 +192,5 @@
 #else
     typedef sigset_t sh_sigset_t;
-#endif 
+#endif
 
 typedef void (*sh_handler)(int);
@@ -179,4 +199,5 @@
 void sh_sigemptyset(sh_sigset_t *set);
 int sh_sigprocmask(shinstance *, int op, sh_sigset_t const *new, sh_sigset_t *old);
+void sh_abort(shinstance *);
 
 /* times */
@@ -193,5 +214,5 @@
 #   include <times.h>
     typedef struct tms sh_tms;
-#endif 
+#endif
 clock_t sh_times(sh_tms *);
 int sh_sysconf_clk_tck(void);
@@ -219,7 +240,8 @@
 #else
 #   include <sys/wait.h>
-#endif 
+#endif
 pid_t sh_waitpid(shinstance *, pid_t, int *, int);
 void sh__exit(shinstance *, int);
 
-#endif
+
+#endif
Index: trunk/src/kash/show.c
===================================================================
--- trunk/src/kash/show.c	(revision 1196)
+++ trunk/src/kash/show.c	(revision 1198)
@@ -276,5 +276,5 @@
 trputc(int c)
 {
-	if (debug != 1)
+	if (debug(psh) != 1)
 		return;
 	putc(c, tracefile);
@@ -283,10 +283,10 @@
 
 void
-trace(const char *fmt, ...)
+trace(shinstance *psh, const char *fmt, ...)
 {
 #ifdef DEBUG
 	va_list va;
 
-	if (debug != 1)
+	if (debug(psh) != 1)
 		return;
         fprintf(tracefile, "[%d] ", getpid());
@@ -298,8 +298,8 @@
 
 void
-tracev(const char *fmt, va_list va)
-{
-#ifdef DEBUG
-	if (debug != 1)
+tracev(shinstance *psh, const char *fmt, va_list va)
+{
+#ifdef DEBUG
+	if (debug(psh) != 1)
 		return;
         fprintf(tracefile, "[%d] ", getpid());
@@ -313,5 +313,5 @@
 trputs(const char *s)
 {
-	if (debug != 1)
+	if (debug(psh) != 1)
 		return;
 	fputs(s, tracefile);
@@ -325,5 +325,5 @@
 	char c;
 
-	if (debug != 1)
+	if (debug(psh) != 1)
 		return;
 	putc('"', tracefile);
@@ -361,8 +361,8 @@
 
 void
-trargs(char **ap)
-{
-#ifdef DEBUG
-	if (debug != 1)
+trargs(shinstance *psh, char **ap)
+{
+#ifdef DEBUG
+	if (debug(psh) != 1)
 		return;
 	while (*ap) {
@@ -386,5 +386,5 @@
 #endif
 
-	if (debug != 1) {
+	if (debug(psh) != 1) {
 		if (tracefile)
 			fflush(tracefile);
@@ -410,5 +410,5 @@
 		if (!freopen(s, "a", tracefile)) {
 			fprintf(stderr, "Can't re-open %s\n", s);
-			debug = 0;
+			debug(psh) = 0;
 			return;
 		}
@@ -416,5 +416,5 @@
 		if ((tracefile = fopen(s, "a")) == NULL) {
 			fprintf(stderr, "Can't open %s\n", s);
-			debug = 0;
+			debug(psh) = 0;
 			return;
 		}
Index: trunk/src/kash/trap.c
===================================================================
--- trunk/src/kash/trap.c	(revision 1196)
+++ trunk/src/kash/trap.c	(revision 1198)
@@ -102,5 +102,5 @@
 
 	if (is_number(p))
-		return number(p);
+		return number(psh, p);
 
 	if (strcasecmp(p, "exit") == 0 )
@@ -190,5 +190,5 @@
 	while (*ap) {
 		if (is_number(*ap))
-			signo = number(*ap);
+			signo = number(psh, *ap);
 		else
 			signo = signame_to_signum(*ap);
@@ -264,15 +264,15 @@
 		switch (signo) {
 		case SIGINT:
-			if (iflag || minusc || sflag == 0)
+			if (iflag(psh) || minusc || sflag(psh) == 0)
 				action = S_CATCH;
 			break;
 		case SIGQUIT:
 #ifdef DEBUG
-			if (debug)
+			if (debug(psh))
 				break;
 #endif
 			/* FALLTHROUGH */
 		case SIGTERM:
-			if (iflag)
+			if (iflag(psh))
 				action = S_IGN;
 			break;
@@ -280,5 +280,5 @@
 		case SIGTSTP:
 		case SIGTTOU:
-			if (mflag)
+			if (mflag(psh))
 				action = S_IGN;
 			break;
@@ -302,5 +302,5 @@
 		}
 		if (sigact == SIG_IGN) {
-			if (mflag && (signo == SIGTSTP ||
+			if (mflag(psh) && (signo == SIGTSTP ||
 			     signo == SIGTTIN || signo == SIGTTOU)) {
 				tsig = S_IGN;	/* don't hard ignore these */
Index: trunk/src/kash/var.c
===================================================================
--- trunk/src/kash/var.c	(revision 1196)
+++ trunk/src/kash/var.c	(revision 1198)
@@ -228,5 +228,5 @@
             if (i > 0)
             {
-                psz[0] = psz[1] = psz[2] = psz[3] = '\0'; 
+                psz[0] = psz[1] = psz[2] = psz[3] = '\0';
                 rc = DosQueryExtLIBPATH(psz, i);
             }
@@ -365,5 +365,5 @@
 	int nlen;
 
-	if (aflag)
+	if (aflag(psh))
 		flags |= VEXPORT;
 	vp = find_var(s, &vpp, &nlen);
@@ -501,5 +501,5 @@
 				nenv++;
 	}
-	ep = env = stalloc((nenv + 1) * sizeof *env);
+	ep = env = stalloc(psh, (nenv + 1) * sizeof *env);
 	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
 		for (vp = *vpp ; vp ; vp = vp->next)
@@ -706,5 +706,5 @@
 	char *name;
 
-	if (! in_function())
+	if (! in_function(psh))
 		error("Not in a function");
 	while ((name = *argptr++) != NULL) {
