diff --git a/sh.func.c b/sh.func.c
index a9c0dd6..185b994 100644
--- a/sh.func.c
+++ b/sh.func.c
@@ -56,7 +56,6 @@ static	void	preread		(void);
 static	void	doagain		(void);
 static  const char *isrchx	(int);
 static	void	search		(int, int, Char *);
-static	int	getword		(struct Strbuf *);
 static	struct wordent	*histgetword	(struct wordent *);
 static	void	toend		(void);
 static	void	xecho		(int, Char **);
@@ -742,8 +741,8 @@ isrchx(int n)
 }
 
 
-static int Stype;
-static Char *Sgoal;
+int Stype;
+Char *Sgoal;
 
 static void
 search(int type, int level, Char *goal)
@@ -1000,7 +999,7 @@ past:
     return NULL;
 }
 
-static int
+int
 getword(struct Strbuf *wp)
 {
     int found = 0, first;
@@ -1096,6 +1095,13 @@ past:
 	stderror(ERR_NAME | ERR_NOTFOUND, "label");
 	break;
 
+    case TC_EXIT:
+	if (fcurr.eof)
+	    return 1 << 1;
+	setname(short2str(Sgoal));
+	stderror(ERR_NAME | ERR_NOTFOUND, "exit");
+	break;
+
     default:
 	break;
     }
@@ -2719,3 +2725,53 @@ getYN(const char *prompt)
 	continue;
     return doit;
 }
+
+void
+dofunction(Char **v, struct command *t)
+{
+    char *file;
+    struct funcargs **fargv;
+
+    if (!dolzero)
+	stderror(ERR_FUNC);
+
+    if (*(fargv = &fcurr.fargv)) {
+	(*fargv)->next = malloc(sizeof **fargv);
+	(*fargv)->next->prev = *fargv;
+	*fargv = (*fargv)->next;
+    } else {
+	*fargv = malloc(sizeof **fargv);
+	(*fargv)->prev = NULL;
+    }
+
+    {
+	int i = 0;
+	Char **vh = NULL;
+
+	for (v++; *v; v++, i++) {
+	    vh = xrealloc(vh, sizeof(Char *[i + 2]));
+	    vh[i] = xmalloc(sizeof(Char [Strlen(*v) + 1]));
+	    Strcpy(vh[i], *v);
+	}
+
+	vh[i] = NULL;
+	(*fargv)->v = vh;
+    }
+    fcurr.ready = 1;
+
+    if (!srcfile(file = fcurr.file ? fcurr.file :
+		 strsave(short2str(ffile)), 0, 0, NULL))
+	stderror(ERR_SYSTEM, file, strerror(errno));
+    if (file != fcurr.file)
+	xfree(file);
+    /* Reset STRargv on function exit. */
+    setv(STRargv, NULL, VAR_READWRITE);
+
+    if ((*fargv)->prev) {
+	*fargv = (*fargv)->prev;
+	free((*fargv)->next);
+    } else {
+	free(*fargv);
+	*fargv = NULL;
+    }
+}
