Index: /trunk/src/kash/Makefile.kmk
===================================================================
--- /trunk/src/kash/Makefile.kmk	(revision 1200)
+++ /trunk/src/kash/Makefile.kmk	(revision 1201)
@@ -44,8 +44,8 @@
 	syntax.c \
 	output.c \
+	input.c \
 	\
 	exec.c \
 	expand.c \
-	input.c \
 	jobs.c \
 	miscbltin.c \
Index: /trunk/src/kash/bltin/bltin.h
===================================================================
--- /trunk/src/kash/bltin/bltin.h	(revision 1200)
+++ /trunk/src/kash/bltin/bltin.h	(revision 1201)
@@ -51,6 +51,6 @@
 #undef putchar
 #undef fileno
-#define stdout out1
-#define stderr out2
+#define stdout psh->out1
+#define stderr psh->out2
 #define printf out1fmt
 #define putc(c, file)	outc(c, file)
Index: /trunk/src/kash/exec.c
===================================================================
--- /trunk/src/kash/exec.c	(revision 1200)
+++ /trunk/src/kash/exec.c	(revision 1201)
@@ -218,9 +218,9 @@
 			exraise(psh, EXSHELLPROC);
 		}
-		initshellproc();
-		setinputfile(cmd, 0);
+		initshellproc(psh);
+		setinputfile(psh, cmd, 0);
 		commandname = arg0 = savestr(argv[0]);
 #ifdef EXEC_HASH_BANG_SCRIPT
-		pgetc(); pungetc();		/* fill up input buffer */
+		pgetc(psh); pungetc(psh);		/* fill up input buffer */
 		p = parsenextc;
 		if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
@@ -703,5 +703,5 @@
 		delete_cmd_entry();
 	if (act & DO_ERR)
-		outfmt(out2, "%s: %s\n", name, errmsg(psh, e, E_EXEC));
+		outfmt(psh->out2, "%s: %s\n", name, errmsg(psh, e, E_EXEC));
 	entry->cmdtype = CMDUNKNOWN;
 	return;
Index: /trunk/src/kash/expand.c
===================================================================
--- /trunk/src/kash/expand.c	(revision 1200)
+++ /trunk/src/kash/expand.c	(revision 1201)
@@ -122,9 +122,9 @@
 
 void
-expandhere(union node *arg, int fd)
+expandhere(shinstance *psh, union node *arg, int fd)
 {
 	psh->herefd = fd;
-	expandarg(arg, (struct arglist *)NULL, 0);
-	xwrite(psh, fd, stackblock(psh), expdest - stackblock(psh));
+	expandarg(psh, arg, (struct arglist *)NULL, 0);
+	xwrite(psh, fd, stackblock(psh), psh->expdest - stackblock(psh));
 }
 
@@ -164,5 +164,5 @@
 	} else {
 		if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
-			rmescapes(p);
+			rmescapes(psh, p);
 		sp = (struct strlist *)stalloc(psh, sizeof (struct strlist));
 		sp->text = p;
@@ -231,5 +231,5 @@
 			break;
 		case CTLENDARI:
-			expari(flag);
+			expari(psh, flag);
 			break;
 		case ':':
@@ -398,5 +398,5 @@
 	removerecordregions(begoff);
 	if (quotes)
-		rmescapes(p+2);
+		rmescapes(psh, p+2);
 	result = arith(p+2);
 	fmtstr(p, 12, "%d", result);
@@ -522,5 +522,5 @@
 	case VSQUESTION:
 		if (*p != CTLENDVAR) {
-			outfmt(&errout, "%s\n", startp);
+			outfmt(&psh->errout, "%s\n", startp);
 			error(psh, (char *)NULL);
 		}
@@ -534,5 +534,5 @@
 			c = *loc;
 			*loc = '\0';
-			if (patmatch(str, startp, varflags & VSQUOTE))
+			if (patmatch(psh, str, startp, varflags & VSQUOTE))
 				goto recordleft;
 			*loc = c;
@@ -546,5 +546,5 @@
 			c = *loc;
 			*loc = '\0';
-			if (patmatch(str, startp, varflags & VSQUOTE))
+			if (patmatch(psh, str, startp, varflags & VSQUOTE))
 				goto recordleft;
 			*loc = c;
@@ -563,5 +563,5 @@
 	case VSTRIMRIGHT:
 	        for (loc = str - 1; loc >= startp;) {
-			if (patmatch(str, loc, varflags & VSQUOTE))
+			if (patmatch(psh, str, loc, varflags & VSQUOTE))
 				goto recordright;
 			loc--;
@@ -579,5 +579,5 @@
 	case VSTRIMRIGHTMAX:
 		for (loc = startp; loc < str - 1; loc++) {
-			if (patmatch(str, loc, varflags & VSQUOTE))
+			if (patmatch(psh, str, loc, varflags & VSQUOTE))
 				goto recordright;
 			if ((varflags & VSQUOTE) && *loc == CTLESC)
@@ -1111,5 +1111,5 @@
 nometa:
 			*exparg.lastp = str;
-			rmescapes(str->text);
+			rmescapes(psh, str->text);
 			exparg.lastp = &str->next;
 		} else {
@@ -1235,5 +1235,5 @@
 		if (dp->d_name[0] == '.' && ! matchdot)
 			continue;
-		if (patmatch(start, dp->d_name, 0)) {
+		if (patmatch(psh, start, dp->d_name, 0)) {
 			if (atend) {
 				scopy(dp->d_name, enddir);
@@ -1516,5 +1516,5 @@
 	STPUTC(psh, '\0', expdest);
 	p = grabstackstr(psh, expdest);
-	result = patmatch(p, val, 0);
+	result = patmatch(psh, p, val, 0);
 	popstackmark(psh, &smark);
 	return result;
@@ -1551,5 +1551,5 @@
 
 int
-wordexpcmd(int argc, char **argv)
+wordexpcmd(shinstance *psh, int argc, char **argv)
 {
 	size_t len;
Index: /trunk/src/kash/generated/init.c
===================================================================
--- /trunk/src/kash/generated/init.c	(revision 1200)
+++ /trunk/src/kash/generated/init.c	(revision 1201)
@@ -173,5 +173,5 @@
 
 void
-init() {
+init(shinstance *psh) {
 
       /* from exec.c: */
@@ -206,5 +206,5 @@
 
 void
-reset() {
+reset(shinstance *psh) {
 
       /* from eval.c: */
@@ -219,11 +219,11 @@
 	      if (exception != EXSHELLPROC)
 		      parselleft = parsenleft = 0;	/* clear input buffer */
-	      popallfiles();
+	      popallfiles(psh);
       }
 
       /* from output.c: */
       {
-	      out1 = &output;
-	      out2 = &errout;
+	      psh->out1 = &psh->output;
+	      psh->out2 = &psh->errout;
 	      if (memout.buf != NULL) {
 		      ckfree(memout.buf);
@@ -252,5 +252,5 @@
 
 void
-initshellproc() {
+initshellproc(shinstance *psh) {
 
       /* from alias.c: */
@@ -271,5 +271,5 @@
       /* from input.c: */
       {
-	      popallfiles();
+	      popallfiles(psh);
       }
 
Index: /trunk/src/kash/histedit.c
===================================================================
--- /trunk/src/kash/histedit.c	(revision 1200)
+++ /trunk/src/kash/histedit.c	(revision 1201)
@@ -196,6 +196,6 @@
 	if (el != NULL && term != NULL)
 		if (el_set(el, EL_TERMINAL, term) != 0) {
-			outfmt(out2, "sh: Can't set terminal type %s\n", term);
-			outfmt(out2, "sh: Using dumb terminal settings.\n");
+			outfmt(psh->out2, "sh: Can't set terminal type %s\n", term);
+			outfmt(psh->out2, "sh: Using dumb terminal settings.\n");
 		}
 }
Index: /trunk/src/kash/input.c
===================================================================
--- /trunk/src/kash/input.c	(revision 1200)
+++ /trunk/src/kash/input.c	(revision 1201)
@@ -69,51 +69,52 @@
 #include "parser.h"
 #include "myhistedit.h"
+#include "shinstance.h"
 
 #define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
 
-MKINIT
-struct strpush {
-	struct strpush *prev;	/* preceding string on stack */
-	char *prevstring;
-	int prevnleft;
-	int prevlleft;
-	struct alias *ap;	/* if push was associated with an alias */
-};
-
-/*
- * The parsefile structure pointed to by the global variable parsefile
- * contains information about the current file being read.
- */
-
-MKINIT
-struct parsefile {
-	struct parsefile *prev;	/* preceding file on stack */
-	int linno;		/* current line */
-	int fd;			/* file descriptor (or -1 if string) */
-	int nleft;		/* number of chars left in this line */
-	int lleft;		/* number of chars left in this buffer */
-	char *nextc;		/* next char in buffer */
-	char *buf;		/* input buffer */
-	struct strpush *strpush; /* for pushing strings at this level */
-	struct strpush basestrpush; /* so pushing one is fast */
-};
-
-
-int plinno = 1;			/* input line number */
-int parsenleft;			/* copy of parsefile->nleft */
-MKINIT int parselleft;		/* copy of parsefile->lleft */
-char *parsenextc;		/* copy of parsefile->nextc */
-MKINIT struct parsefile basepf;	/* top level input file */
-MKINIT char basebuf[BUFSIZ];	/* buffer for top level input file */
-struct parsefile *parsefile = &basepf;	/* current input file */
-int init_editline = 0;		/* editline library initialized? */
-int whichprompt;		/* 1 == PS1, 2 == PS2 */
-
-#ifndef SMALL
-EditLine *el;			/* cookie for editline package */
-#endif
-
-STATIC void pushfile(void);
-static int preadfd(void);
+//MKINIT
+//struct strpush {
+//	struct strpush *prev;	/* preceding string on stack */
+//	char *prevstring;
+//	int prevnleft;
+//	int prevlleft;
+//	struct alias *ap;	/* if push was associated with an alias */
+//};
+//
+///*
+// * The parsefile structure pointed to by the global variable parsefile
+// * contains information about the current file being read.
+// */
+//
+//MKINIT
+//struct parsefile {
+//	struct parsefile *prev;	/* preceding file on stack */
+//	int linno;		/* current line */
+//	int fd;			/* file descriptor (or -1 if string) */
+//	int nleft;		/* number of chars left in this line */
+//	int lleft;		/* number of chars left in this buffer */
+//	char *nextc;		/* next char in buffer */
+//	char *buf;		/* input buffer */
+//	struct strpush *strpush; /* for pushing strings at this level */
+//	struct strpush basestrpush; /* so pushing one is fast */
+//};
+//
+//
+//int plinno = 1;			/* input line number */
+//int parsenleft;			/* copy of parsefile->nleft */
+//MKINIT int parselleft;		/* copy of parsefile->lleft */
+//char *parsenextc;		/* copy of parsefile->nextc */
+//MKINIT struct parsefile basepf;	/* top level input file */
+//MKINIT char basebuf[BUFSIZ];	/* buffer for top level input file */
+//struct parsefile *parsefile = &basepf;	/* current input file */
+//int init_editline = 0;		/* editline library initialized? */
+//int whichprompt;		/* 1 == PS1, 2 == PS2 */
+//
+//#ifndef SMALL
+//EditLine *el;			/* cookie for editline package */
+//#endif
+
+STATIC void pushfile(shinstance *psh);
+static int preadfd(shinstance *psh);
 
 #ifdef mkinit
@@ -123,15 +124,15 @@
 
 INIT {
-	basepf.nextc = basepf.buf = basebuf;
+	psh->basepf.nextc = psh->basepf.buf = psh->basebuf;
 }
 
 RESET {
-	if (exception != EXSHELLPROC)
-		parselleft = parsenleft = 0;	/* clear input buffer */
-	popallfiles();
+	if (psh->exception != EXSHELLPROC)
+		psh->parselleft = psh->parsenleft = 0;	/* clear input buffer */
+	popallfiles(psh);
 }
 
 SHELLPROC {
-	popallfiles();
+	popallfiles(psh);
 }
 #endif
@@ -143,5 +144,5 @@
 
 char *
-pfgets(char *line, int len)
+pfgets(shinstance *psh, char *line, int len)
 {
 	char *p = line;
@@ -150,5 +151,5 @@
 
 	while (--nleft > 0) {
-		c = pgetc_macro();
+		c = pgetc_macro(psh);
 		if (c == PEOF) {
 			if (p == line)
@@ -172,25 +173,25 @@
 
 int
-pgetc(void)
-{
-	return pgetc_macro();
+pgetc(shinstance *psh)
+{
+	return pgetc_macro(psh);
 }
 
 
 static int
-preadfd(void)
+preadfd(shinstance *psh)
 {
 	int nr;
-	char *buf =  parsefile->buf;
-	parsenextc = buf;
+	char *buf = psh->parsefile->buf;
+	psh->parsenextc = buf;
 
 retry:
 #ifndef SMALL
-	if (parsefile->fd == 0 && el) {
+	if (psh->parsefile->fd == 0 && psh->el) {
 		static const char *rl_cp;
 		static int el_len;
 
 		if (rl_cp == NULL)
-			rl_cp = el_gets(el, &el_len);
+			rl_cp = el_gets(psh->el, &el_len);
 		if (rl_cp == NULL)
 			nr = 0;
@@ -209,5 +210,5 @@
 	} else
 #endif
-		nr = read(parsefile->fd, buf, BUFSIZ - 8);
+		nr = shfile_read(&psh->fdtab, psh->parsefile->fd, buf, BUFSIZ - 8);
 
 
@@ -216,9 +217,9 @@
                         if (errno == EINTR)
                                 goto retry;
-                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
-                                int flags = fcntl(0, F_GETFL, 0);
+                        if (psh->parsefile->fd == 0 && errno == EWOULDBLOCK) {
+                                int flags = shfile_fcntl(&psh->fdtab, 0, F_GETFL, 0);
                                 if (flags >= 0 && flags & O_NONBLOCK) {
                                         flags &=~ O_NONBLOCK;
-                                        if (fcntl(0, F_SETFL, flags) >= 0) {
+                                        if (shfile_fcntl(&psh->fdtab, 0, F_SETFL, flags) >= 0) {
 						out2str(psh, "sh: turning off NDELAY mode\n");
                                                 goto retry;
@@ -243,5 +244,5 @@
 
 int
-preadbuffer(void)
+preadbuffer(shinstance *psh)
 {
 	char *p, *q;
@@ -250,23 +251,23 @@
 	char savec;
 
-	if (parsefile->strpush) {
-		popstring();
-		if (--parsenleft >= 0)
-			return (*parsenextc++);
-	}
-	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
+	if (psh->parsefile->strpush) {
+		popstring(psh);
+		if (--psh->parsenleft >= 0)
+			return (*psh->parsenextc++);
+	}
+	if (psh->parsenleft == EOF_NLEFT || psh->parsefile->buf == NULL)
 		return PEOF;
-	flushout(&output);
-	flushout(&errout);
+	flushout(&psh->output);
+	flushout(&psh->errout);
 
 again:
-	if (parselleft <= 0) {
-		if ((parselleft = preadfd()) == -1) {
-			parselleft = parsenleft = EOF_NLEFT;
+	if (psh->parselleft <= 0) {
+		if ((psh->parselleft = preadfd(psh)) == -1) {
+			psh->parselleft = psh->parsenleft = EOF_NLEFT;
 			return PEOF;
 		}
 	}
 
-	q = p = parsenextc;
+	q = p = psh->parsenextc;
 
 	/* delete nul characters */
@@ -283,5 +284,5 @@
 
 		case '\n':
-			parsenleft = q - parsenextc;
+			psh->parsenleft = (int)(q - psh->parsenextc);
 			more = 0; /* Stop processing here */
 			break;
@@ -294,7 +295,7 @@
 		*q++ = *p++;
 check:
-		if (--parselleft <= 0) {
-			parsenleft = q - parsenextc - 1;
-			if (parsenleft < 0)
+		if (--psh->parselleft <= 0) {
+			psh->parsenleft = (int)(q - psh->parsenextc - 1);
+			if (psh->parsenleft < 0)
 				goto again;
 			*q = '\0';
@@ -307,9 +308,9 @@
 
 #ifndef SMALL
-	if (parsefile->fd == 0 && hist && something) {
+	if (psh->parsefile->fd == 0 && hist && something) {
 		HistEvent he;
 		INTOFF;
-		history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
-		    parsenextc);
+		history(hist, &he, psh->whichprompt == 1? H_ENTER : H_APPEND,
+		    psh->parsenextc);
 		INTON;
 	}
@@ -317,11 +318,11 @@
 
 	if (vflag(psh)) {
-		out2str(psh, parsenextc);
-		flushout(out2);
+		out2str(psh, psh->parsenextc);
+		flushout(psh->out2);
 	}
 
 	*q = savec;
 
-	return *parsenextc++;
+	return *psh->parsenextc++;
 }
 
@@ -332,8 +333,8 @@
 
 void
-pungetc(void)
-{
-	parsenleft++;
-	parsenextc--;
+pungetc(shinstance *psh)
+{
+	psh->parsenleft++;
+	psh->parsenextc--;
 }
 
@@ -343,5 +344,5 @@
  */
 void
-pushstring(char *s, int len, void *ap)
+pushstring(shinstance *psh, char *s, int len, void *ap)
 {
 	struct strpush *sp;
@@ -349,35 +350,35 @@
 	INTOFF;
 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
-	if (parsefile->strpush) {
+	if (psh->parsefile->strpush) {
 		sp = ckmalloc(sizeof (struct strpush));
-		sp->prev = parsefile->strpush;
-		parsefile->strpush = sp;
+		sp->prev = psh->parsefile->strpush;
+		psh->parsefile->strpush = sp;
 	} else
-		sp = parsefile->strpush = &(parsefile->basestrpush);
-	sp->prevstring = parsenextc;
-	sp->prevnleft = parsenleft;
-	sp->prevlleft = parselleft;
+		sp = psh->parsefile->strpush = &(psh->parsefile->basestrpush);
+	sp->prevstring = psh->parsenextc;
+	sp->prevnleft = psh->parsenleft;
+	sp->prevlleft = psh->parselleft;
 	sp->ap = (struct alias *)ap;
 	if (ap)
 		((struct alias *)ap)->flag |= ALIASINUSE;
-	parsenextc = s;
-	parsenleft = len;
+	psh->parsenextc = s;
+	psh->parsenleft = len;
 	INTON;
 }
 
 void
-popstring(void)
-{
-	struct strpush *sp = parsefile->strpush;
+popstring(shinstance *psh)
+{
+	struct strpush *sp = psh->parsefile->strpush;
 
 	INTOFF;
-	parsenextc = sp->prevstring;
-	parsenleft = sp->prevnleft;
-	parselleft = sp->prevlleft;
-/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
+	psh->parsenextc = sp->prevstring;
+	psh->parsenleft = sp->prevnleft;
+	psh->parselleft = sp->prevlleft;
+/*dprintf("*** calling popstring: restoring to '%s'\n", psh->parsenextc);*/
 	if (sp->ap)
 		sp->ap->flag &= ~ALIASINUSE;
-	parsefile->strpush = sp->prev;
-	if (sp != &(parsefile->basestrpush))
+	psh->parsefile->strpush = sp->prev;
+	if (sp != &(psh->parsefile->basestrpush))
 		ckfree(sp);
 	INTON;
@@ -390,5 +391,5 @@
 
 void
-setinputfile(const char *fname, int push)
+setinputfile(shinstance *psh, const char *fname, int push)
 {
 	int fd;
@@ -396,14 +397,15 @@
 
 	INTOFF;
-	if ((fd = open(fname, O_RDONLY)) < 0)
+/** @todo shfile fixme */
+	if ((fd = shfile_open(&psh->fdtab, fname, O_RDONLY)) < 0)
 		error(psh, "Can't open %s", fname);
 	if (fd < 10) {
-		fd2 = copyfd(fd, 10);
-		close(fd);
+		fd2 = copyfd(psh, fd, 10);
+		shfile_close(&psh->fdtab, fd);
 		if (fd2 < 0)
 			error(psh, "Out of file descriptors");
 		fd = fd2;
 	}
-	setinputfd(fd, push);
+	setinputfd(psh, fd, push);
 	INTON;
 }
@@ -416,18 +418,18 @@
 
 void
-setinputfd(int fd, int push)
-{
-	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+setinputfd(shinstance *psh, int fd, int push)
+{
+	(void) shfile_fcntl(&psh->fdtab, fd, F_SETFD, FD_CLOEXEC);
 	if (push) {
-		pushfile();
-		parsefile->buf = ckmalloc(BUFSIZ);
-	}
-	if (parsefile->fd > 0)
-		close(parsefile->fd);
-	parsefile->fd = fd;
-	if (parsefile->buf == NULL)
-		parsefile->buf = ckmalloc(BUFSIZ);
-	parselleft = parsenleft = 0;
-	plinno = 1;
+		pushfile(psh);
+		psh->parsefile->buf = ckmalloc(BUFSIZ);
+	}
+	if (psh->parsefile->fd > 0)
+		shfile_close(&psh->fdtab, psh->parsefile->fd);
+	psh->parsefile->fd = fd;
+	if (psh->parsefile->buf == NULL)
+		psh->parsefile->buf = ckmalloc(BUFSIZ);
+	psh->parselleft = psh->parsenleft = 0;
+	psh->plinno = 1;
 }
 
@@ -438,13 +440,13 @@
 
 void
-setinputstring(char *string, int push)
+setinputstring(shinstance *psh, char *string, int push)
 {
 	INTOFF;
 	if (push)
-		pushfile();
-	parsenextc = string;
-	parselleft = parsenleft = strlen(string);
-	parsefile->buf = NULL;
-	plinno = 1;
+		pushfile(psh);
+	psh->parsenextc = string;
+	psh->parselleft = psh->parsenleft = (int)strlen(string);
+	psh->parsefile->buf = NULL;
+	psh->plinno = 1;
 	INTON;
 }
@@ -458,39 +460,39 @@
 
 STATIC void
-pushfile(void)
+pushfile(shinstance *psh)
 {
 	struct parsefile *pf;
 
-	parsefile->nleft = parsenleft;
-	parsefile->lleft = parselleft;
-	parsefile->nextc = parsenextc;
-	parsefile->linno = plinno;
+	psh->parsefile->nleft = psh->parsenleft;
+	psh->parsefile->lleft = psh->parselleft;
+	psh->parsefile->nextc = psh->parsenextc;
+	psh->parsefile->linno = psh->plinno;
 	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
-	pf->prev = parsefile;
+	pf->prev = psh->parsefile;
 	pf->fd = -1;
 	pf->strpush = NULL;
 	pf->basestrpush.prev = NULL;
-	parsefile = pf;
-}
-
-
-void
-popfile(void)
-{
-	struct parsefile *pf = parsefile;
+	psh->parsefile = pf;
+}
+
+
+void
+popfile(shinstance *psh)
+{
+	struct parsefile *pf = psh->parsefile;
 
 	INTOFF;
 	if (pf->fd >= 0)
-		close(pf->fd);
+		shfile_close(&psh->fdtab, pf->fd);
 	if (pf->buf)
 		ckfree(pf->buf);
 	while (pf->strpush)
-		popstring();
-	parsefile = pf->prev;
+		popstring(psh);
+	psh->parsefile = pf->prev;
 	ckfree(pf);
-	parsenleft = parsefile->nleft;
-	parselleft = parsefile->lleft;
-	parsenextc = parsefile->nextc;
-	plinno = parsefile->linno;
+	psh->parsenleft = psh->parsefile->nleft;
+	psh->parselleft = psh->parsefile->lleft;
+	psh->parsenextc = psh->parsefile->nextc;
+	psh->plinno = psh->parsefile->linno;
 	INTON;
 }
@@ -502,8 +504,8 @@
 
 void
-popallfiles(void)
-{
-	while (parsefile != &basepf)
-		popfile();
+popallfiles(shinstance *psh)
+{
+	while (psh->parsefile != &psh->basepf)
+		popfile(psh);
 }
 
@@ -525,12 +527,12 @@
 
 void
-closescript(int vforked)
+closescript(shinstance *psh, int vforked)
 {
 	if (vforked)
 		return;
-	popallfiles();
-	if (parsefile->fd > 0) {
-		close(parsefile->fd);
-		parsefile->fd = 0;
-	}
-}
+	popallfiles(psh);
+	if (psh->parsefile->fd > 0) {
+		shfile_close(&psh->fdtab, psh->parsefile->fd);
+		psh->parsefile->fd = 0;
+	}
+}
Index: /trunk/src/kash/input.h
===================================================================
--- /trunk/src/kash/input.h	(revision 1200)
+++ /trunk/src/kash/input.h	(revision 1201)
@@ -42,8 +42,8 @@
  * package must set its value.
  */
-extern int plinno;
-extern int parsenleft;		/* number of characters left in input buffer */
-extern char *parsenextc;	/* next character in input buffer */
-extern int init_editline;	/* 0 == not setup, 1 == OK, -1 == failed */
+//extern int plinno;
+//extern int parsenleft;		/* number of characters left in input buffer */
+//extern char *parsenextc;	/* next character in input buffer */
+//extern int init_editline;	/* 0 == not setup, 1 == OK, -1 == failed */
 
 char *pfgets(struct shinstance *, char *, int);
@@ -60,3 +60,3 @@
 void closescript(struct shinstance *, int);
 
-#define pgetc_macro()	(--psh->parsenleft >= 0? *psh->parsenextc++ : preadbuffer(psh))
+#define pgetc_macro(psh)	(--(psh)->parsenleft >= 0? *(psh)->parsenextc++ : preadbuffer(psh))
Index: /trunk/src/kash/jobs.c
===================================================================
--- /trunk/src/kash/jobs.c	(revision 1200)
+++ /trunk/src/kash/jobs.c	(revision 1201)
@@ -905,6 +905,6 @@
 		rootshell = 0;
 
-	closescript(vforked);
-	clear_traps(vforked);
+	closescript(psh, vforked);
+	clear_traps(psh, vforked);
 #if JOBS
 	if (!vforked)
@@ -1095,5 +1095,5 @@
 			mode = SHOW_SIGNALLED | SHOW_NO_FREE;
 		if (mode)
-			showjob(out2, thisjob, mode);
+			showjob(psh->out2, thisjob, mode);
 		else {
 			TRACE((psh, "Not printing status, rootshell=%d, job=%p\n",
Index: /trunk/src/kash/parser.c
===================================================================
--- /trunk/src/kash/parser.c	(revision 1200)
+++ /trunk/src/kash/parser.c	(revision 1201)
@@ -209,5 +209,5 @@
 				parseheredoc();
 			else
-				pungetc();		/* push back EOF on input */
+				pungetc(psh);		/* push back EOF on input */
 			return n1;
 		default:
@@ -661,5 +661,5 @@
 		if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
 			synerror("Illegal eof marker for << redirection");
-		rmescapes(wordtext);
+		rmescapes(psh, wordtext);
 		here->eofmark = wordtext;
 		here->next = NULL;
@@ -695,5 +695,5 @@
 			needprompt = 0;
 		}
-		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
+		readtoken1(pgetc(psh), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
 				here->eofmark, here->striptabs);
 		n = (union node *)stalloc(psh, sizeof (struct narg));
@@ -759,5 +759,5 @@
 			if(!noalias &&
 			    (ap = lookupalias(psh, wordtext, 1)) != NULL) {
-				pushstring(ap->val, strlen(ap->val), ap);
+				pushstring(psh, ap->val, strlen(ap->val), ap);
 				checkkwd = savecheckkwd;
 				goto top;
@@ -812,5 +812,5 @@
 	startlinno = plinno;
 	for (;;) {	/* until token or start of word found */
-		c = pgetc_macro();
+		c = pgetc_macro(psh);
 		if (c == ' ' || c == '\t')
 			continue;		/* quick check for white space first */
@@ -819,9 +819,9 @@
 			continue;
 		case '#':
-			while ((c = pgetc()) != '\n' && c != PEOF);
-			pungetc();
+			while ((c = pgetc(psh)) != '\n' && c != PEOF);
+			pungetc(psh);
 			continue;
 		case '\\':
-			if (pgetc() == '\n') {
+			if (pgetc(psh) == '\n') {
 				startlinno = ++plinno;
 				if (doprompt)
@@ -831,5 +831,5 @@
 				continue;
 			}
-			pungetc();
+			pungetc(psh);
 			goto breakloop;
 		case '\n':
@@ -840,17 +840,17 @@
 			RETURN(TEOF);
 		case '&':
-			if (pgetc() == '&')
+			if (pgetc(psh) == '&')
 				RETURN(TAND);
-			pungetc();
+			pungetc(psh);
 			RETURN(TBACKGND);
 		case '|':
-			if (pgetc() == '|')
+			if (pgetc(psh) == '|')
 				RETURN(TOR);
-			pungetc();
+			pungetc(psh);
 			RETURN(TPIPE);
 		case ';':
-			if (pgetc() == ';')
+			if (pgetc(psh) == ';')
 				RETURN(TENDCASE);
-			pungetc();
+			pungetc(psh);
 			RETURN(TSEMI);
 		case '(':
@@ -961,5 +961,5 @@
 			if (syntax == BASESYNTAX)
 				return readtoken();
-			c = pgetc();
+			c = pgetc(psh);
 			goto loop;
 		}
@@ -978,5 +978,5 @@
 				else
 					setprompt(0);
-				c = pgetc();
+				c = pgetc(psh);
 				goto loop;		/* continue outer loop */
 			case CWORD:
@@ -989,8 +989,8 @@
 				break;
 			case CBACK:	/* backslash */
-				c = pgetc();
+				c = pgetc(psh);
 				if (c == PEOF) {
 					USTPUTC(psh, '\\', out);
-					pungetc();
+					pungetc(psh);
 					break;
 				}
@@ -1093,5 +1093,5 @@
 					--parenlevel;
 				} else {
-					if (pgetc() == ')') {
+					if (pgetc(psh) == ')') {
 						if (--arinest == 0) {
 							USTPUTC(psh, CTLENDARI, out);
@@ -1108,5 +1108,5 @@
 						 *  (don't 2nd guess - no error)
 						 */
-						pungetc();
+						pungetc(psh);
 						USTPUTC(psh, ')', out);
 					}
@@ -1123,5 +1123,5 @@
 				USTPUTC(psh, c, out);
 			}
-			c = pgetc_macro();
+			c = pgetc_macro(psh);
 		}
 	}
@@ -1147,5 +1147,5 @@
 			return lasttoken = TREDIR;
 		} else {
-			pungetc();
+			pungetc(psh);
 		}
 	}
@@ -1171,8 +1171,8 @@
 		if (striptabs) {
 			while (c == '\t')
-				c = pgetc();
+				c = pgetc(psh);
 		}
 		if (c == *eofmark) {
-			if (pfgets(line, sizeof line) != NULL) {
+			if (pfgets(psh, line, sizeof line) != NULL) {
 				char *p, *q;
 
@@ -1184,5 +1184,5 @@
 					needprompt = doprompt;
 				} else {
-					pushstring(line, strlen(line), NULL);
+					pushstring(psh, line, strlen(line), NULL);
 				}
 			}
@@ -1206,5 +1206,5 @@
 	if (c == '>') {
 		np->nfile.fd = 1;
-		c = pgetc();
+		c = pgetc(psh);
 		if (c == '>')
 			np->type = NAPPEND;
@@ -1215,9 +1215,9 @@
 		else {
 			np->type = NTO;
-			pungetc();
+			pungetc(psh);
 		}
 	} else {	/* c == '<' */
 		np->nfile.fd = 0;
-		switch (c = pgetc()) {
+		switch (c = pgetc(psh)) {
 		case '<':
 			if (sizeof (struct nfile) != sizeof (struct nhere)) {
@@ -1228,9 +1228,9 @@
 			heredoc = (struct heredoc *)stalloc(psh, sizeof (struct heredoc));
 			heredoc->here = np;
-			if ((c = pgetc()) == '-') {
+			if ((c = pgetc(psh)) == '-') {
 				heredoc->striptabs = 1;
 			} else {
 				heredoc->striptabs = 0;
-				pungetc();
+				pungetc(psh);
 			}
 			break;
@@ -1246,5 +1246,5 @@
 		default:
 			np->type = NFROM;
-			pungetc();
+			pungetc(psh);
 			break;
 		}
@@ -1269,13 +1269,13 @@
 	static const char types[] = "}-+?=";
 
-	c = pgetc();
+	c = pgetc(psh);
 	if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) {
 		USTPUTC(psh, '$', out);
-		pungetc();
+		pungetc(psh);
 	} else if (c == '(') {	/* $(command) or $((arith)) */
-		if (pgetc() == '(') {
+		if (pgetc(psh) == '(') {
 			PARSEARITH();
 		} else {
-			pungetc();
+			pungetc(psh);
 			PARSEBACKQNEW();
 		}
@@ -1286,7 +1286,7 @@
 		subtype = VSNORMAL;
 		if (c == OPENBRACE) {
-			c = pgetc();
+			c = pgetc(psh);
 			if (c == '#') {
-				if ((c = pgetc()) == CLOSEBRACE)
+				if ((c = pgetc(psh)) == CLOSEBRACE)
 					c = '#';
 				else
@@ -1299,15 +1299,15 @@
 			do {
 				STPUTC(psh, c, out);
-				c = pgetc();
+				c = pgetc(psh);
 			} while (is_in_name(c));
 		} else if (is_digit(c)) {
 			do {
 				USTPUTC(psh, c, out);
-				c = pgetc();
+				c = pgetc(psh);
 			} while (is_digit(c));
 		}
 		else if (is_special(c)) {
 			USTPUTC(psh, c, out);
-			c = pgetc();
+			c = pgetc(psh);
 		}
 		else
@@ -1320,5 +1320,5 @@
 			case ':':
 				flags = VSNUL;
-				c = pgetc();
+				c = pgetc(psh);
 				/*FALLTHROUGH*/
 			default:
@@ -1334,14 +1334,14 @@
 					subtype = c == '#' ? VSTRIMLEFT :
 							     VSTRIMRIGHT;
-					c = pgetc();
+					c = pgetc(psh);
 					if (c == cc)
 						subtype++;
 					else
-						pungetc();
+						pungetc(psh);
 					break;
 				}
 			}
 		} else {
-			pungetc();
+			pungetc(psh);
 		}
 		if (ISDBLQUOTE() || arinest)
@@ -1415,10 +1415,10 @@
 				needprompt = 0;
 			}
-			switch (pc = pgetc()) {
+			switch (pc = pgetc(psh)) {
 			case '`':
 				goto done;
 
 			case '\\':
-                                if ((pc = pgetc()) == '\n') {
+                                if ((pc = pgetc(psh)) == '\n') {
 					plinno++;
 					if (doprompt)
@@ -1459,5 +1459,5 @@
                 if (psavelen > 0) {
 			pstr = grabstackstr(psh, pout);
-			setinputstring(pstr, 1);
+			setinputstring(psh, pstr, 1);
                 }
         }
@@ -1489,5 +1489,5 @@
 		 * tokens left from the backquote parsing
 		 */
-                popfile();
+                popfile(psh);
 		tokpushback = 0;
 	}
@@ -1629,5 +1629,5 @@
 setprompt(int which)
 {
-	whichprompt = which;
+	psh->whichprompt = which;
 
 #ifndef SMALL
@@ -1644,5 +1644,5 @@
 getprompt(void *unused)
 	{
-	switch (whichprompt) {
+	switch (psh->whichprompt) {
 	case 0:
 		return "";
Index: /trunk/src/kash/redir.c
===================================================================
--- /trunk/src/kash/redir.c	(revision 1200)
+++ /trunk/src/kash/redir.c	(revision 1201)
@@ -167,7 +167,7 @@
 	}
 	if (memory[1])
-		out1 = &memout;
+		psh->out1 = &psh->memout;
 	if (memory[2])
-		out2 = &memout;
+		psh->out2 = &psh->memout;
 }
 
@@ -283,5 +283,5 @@
 			xwrite(psh, pip[1], redir->nhere.doc->narg.text, len);
 		else
-			expandhere(redir->nhere.doc, pip[1]);
+			expandhere(psh, redir->nhere.doc, pip[1]);
 		_exit(0);
 	}
Index: /trunk/src/kash/shinstance.c
===================================================================
--- /trunk/src/kash/shinstance.c	(revision 1200)
+++ /trunk/src/kash/shinstance.c	(revision 1201)
@@ -52,4 +52,9 @@
         psh->stacknxt = psh->stackbase.space;
 
+        /* input.c */
+        psh->plinno = 1;
+        psh->init_editline = 0;
+        psh->parsefile = &psh->basepf;
+
         /* output.c */
         psh->output.bufsize = OUTBUFSIZ;
@@ -61,5 +66,4 @@
         psh->out2 = &psh->errout;
 
-        /* .c */
     }
     return psh;
Index: /trunk/src/kash/shinstance.h
===================================================================
--- /trunk/src/kash/shinstance.h	(revision 1200)
+++ /trunk/src/kash/shinstance.h	(revision 1201)
@@ -27,4 +27,6 @@
 #ifndef ___shinstance_h___
 #define ___shinstance_h___
+
+#include <stdio.h> /* BUFSIZ */
 
 #include "shtypes.h"
@@ -36,4 +38,5 @@
 #include "var.h"
 
+/* memalloc.c */
 #define MINSIZE 504		/* minimum size of a block */
 struct stack_block {
@@ -41,4 +44,30 @@
 	char space[MINSIZE];
 };
+
+/* input.c */
+struct strpush {
+	struct strpush *prev;	/* preceding string on stack */
+	char *prevstring;
+	int prevnleft;
+	int prevlleft;
+	struct alias *ap;	/* if push was associated with an alias */
+};
+
+/*
+ * The parsefile structure pointed to by the global variable parsefile
+ * contains information about the current file being read.
+ */
+struct parsefile {
+	struct parsefile *prev;	/* preceding file on stack */
+	int linno;		/* current line */
+	int fd;			/* file descriptor (or -1 if string) */
+	int nleft;		/* number of chars left in this line */
+	int lleft;		/* number of chars left in this buffer */
+	char *nextc;		/* next char in buffer */
+	char *buf;		/* input buffer */
+	struct strpush *strpush; /* for pushing strings at this level */
+	struct strpush basestrpush; /* so pushing one is fast */
+};
+
 
 
@@ -136,5 +165,4 @@
     struct stackmark   *markp;
 
-
     /* jobs.h */
     pid_t               backgndpid;     /**< pid of last background process */
@@ -142,8 +170,18 @@
 
     /* input.h */
-    int                 plinno;
+    int                 plinno/* = 1 */;/**< input line number */
     int                 parsenleft;     /**< number of characters left in input buffer */
     char               *parsenextc;     /**< next character in input buffer */
-    int                 init_editline;  /**< 0 == not setup, 1 == OK, -1 == failed */
+    int                 init_editline/* = 0 */;     /**< 0 == not setup, 1 == OK, -1 == failed */
+
+    /* input.c */
+    int                 parselleft;     /**< copy of parsefile->lleft */
+    struct parsefile    basepf;         /**< top level input file */
+    char                basebuf[BUFSIZ];/**< buffer for top level input file */
+    struct parsefile   *parsefile/* = &basepf*/;    /**< current input file */
+#ifndef SMALL
+    EditLine           *el;             /**< cookie for editline package */
+#endif
+
 
     /* exec.h */
