Add in a shell tagline (per lash/hush behavior) to make it easier
to know which shell is in use.  Add in 'help' to list available
builtins, and fixup msh so it can do STANDALONE_SHELL.
 -Erik
diff --git a/ash.c b/ash.c
index 99460d3..4250f50 100644
--- a/ash.c
+++ b/ash.c
@@ -1603,6 +1603,7 @@
 static int exportcmd (int, char **);
 static int histcmd (int, char **);
 static int hashcmd (int, char **);
+static int helpcmd (int, char **);
 static int jobscmd (int, char **);
 static int localcmd (int, char **);
 #ifndef BB_PWD
@@ -1704,6 +1705,7 @@
 	{ BUILTIN_REGULAR   "getopts", getoptscmd },
 #endif
 	{ BUILTIN_NOSPEC    "hash", hashcmd },
+	{ BUILTIN_NOSPEC    "help", helpcmd },
 	{ BUILTIN_REGULAR   "jobs", jobscmd },
 #ifdef JOBS
 	{ BUILTIN_REGULAR   "kill", killcmd },
@@ -3274,6 +3276,7 @@
 setinteractive(int on)
 {
 	static int is_interactive;
+	static int do_banner=0;
 
 	if (on == is_interactive)
 		return;
@@ -3282,6 +3285,12 @@
 	setsignal(SIGTERM);
 	chkmail(1);
 	is_interactive = on;
+	if (do_banner==0 && is_interactive) {
+		/* Looks like they want an interactive shell */
+		printf( "\n\n" BB_BANNER " Built-in shell (ash)\n");
+		printf( "Enter 'help' for a list of built-in commands.\n\n");
+		do_banner=1;
+	}
 }
 
 static void
@@ -3802,6 +3811,51 @@
 
 
 
+/*** List the available builtins ***/
+
+
+static int helpcmd(int argc, char** argv)
+{
+	int col, i;
+	const struct builtincmd *x;
+
+	printf("\nBuilt-in commands:\n");
+	printf("-------------------\n");
+	for (col=0, i=0, x = builtincmds; i < NUMBUILTINS; x++, i++) {
+		if (!x->name || ! (x->name+1))
+			continue;
+		col += printf("%s%s", ((col == 0) ? "\t" : " "), 
+				(x->name+1));
+		if (col > 60) {
+			printf("\n");
+			col = 0;
+		}
+	}
+#ifdef BB_FEATURE_SH_STANDALONE_SHELL
+	{
+		const struct BB_applet *applet;
+		extern const struct BB_applet applets[];
+		extern const size_t NUM_APPLETS;
+
+		for (i=0, applet = applets; i < NUM_APPLETS; applet++, i++) {
+			if (!applet->name)
+				continue;
+		
+			col += printf("%s%s", ((col == 0) ? "\t" : " "), 
+					applet->name);
+			if (col > 60) {
+				printf("\n");
+				col = 0;
+			}
+		}
+	}
+#endif
+	printf("\n\n");
+	return EXIT_SUCCESS;
+}
+
+
+
 /*
  * Resolve a command name.  If you change this routine, you may have to
  * change the shellexec routine as well.
@@ -7755,6 +7809,11 @@
 	EXECCMD = find_builtin("exec");
 	EVALCMD = find_builtin("eval");
 
+#ifndef BB_FEATURE_SH_FANCY_PROMPT
+	unsetenv("PS1");
+	unsetenv("PS2");
+#endif
+
 #if PROFILE
 	monitor(4, etext, profile_buf, sizeof profile_buf, 50);
 #endif
@@ -13088,7 +13147,7 @@
 /*
  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
  * This file contains code for the times builtin.
- * $Id: ash.c,v 1.6 2001/07/06 04:26:23 andersen Exp $
+ * $Id: ash.c,v 1.7 2001/07/07 00:05:55 andersen Exp $
  */
 static int timescmd (int argc, char **argv)
 {
diff --git a/msh.c b/msh.c
index 66c3d54..e85d6ff 100644
--- a/msh.c
+++ b/msh.c
@@ -497,6 +497,7 @@
 static struct op *findcase (struct op *t, char *w );
 static void brkset(struct brkcon *bc );
 static int dolabel(void);
+static int dohelp(void);
 static int dochdir(struct op *t );
 static int doshift(struct op *t );
 static int dologin(struct op *t );
@@ -592,30 +593,31 @@
 };
 
 
-struct	builtin {
-	char *command;
-	int	 (*fn)();
+struct builtincmd {
+	const char *name;
+	int (*builtinfunc)();
 };
-static struct	builtin	builtin[] = {
+static const struct	builtincmd	builtincmds[] = {
+    {".",		dodot},
     {":",		dolabel},
-    {"cd",		dochdir},
-    {"shift",	doshift},
-    {"exec",	doexec},
-    {"wait",	dowait},
-    {"read",	doread},
-    {"eval",	doeval},
-    {"trap",	dotrap},
     {"break",	dobreak},
+    {"cd",		dochdir},
     {"continue",docontinue},
+    {"eval",	doeval},
+    {"exec",	doexec},
     {"exit",	doexit},
     {"export",	doexport},
-    {"readonly",doreadonly},
-    {"set",		doset},
-    {".",		dodot},
-    {"umask",	doumask},
+    {"help",	dohelp},
     {"login",	dologin},
     {"newgrp",	dologin},
+    {"read",	doread},
+    {"readonly",doreadonly},
+    {"set",		doset},
+    {"shift",	doshift},
     {"times",	dotimes},
+    {"trap",	dotrap},
+    {"umask",	doumask},
+    {"wait",	dowait},
     {0,0}
 };
 
@@ -731,14 +733,18 @@
 		setval(ifs, " \t\n");
 
 	prompt = lookup("PS1");
+#ifdef BB_FEATURE_SH_FANCY_PROMPT
 	if (prompt->value == null)
+#endif
 		setval(prompt, "$ ");
 	if (geteuid() == 0) {
 		setval(prompt, "# ");
 		prompt->status &= ~EXPORT;
 	}
 	cprompt = lookup("PS2");
+#ifdef BB_FEATURE_SH_FANCY_PROMPT
 	if (cprompt->value == null)
+#endif
 		setval(cprompt, "> ");
 
 	iof = filechar;
@@ -794,8 +800,11 @@
 	setdash();
 	if (e.iop < iostack) {
 		PUSHIO(afile, 0, iof);
-		if (isatty(0) && isatty(1) && !cflag)
+		if (isatty(0) && isatty(1) && !cflag) {
 			interactive++;
+			printf( "\n\n" BB_BANNER " Built-in shell (msh)\n");
+			printf( "Enter 'help' for a list of built-in commands.\n\n");
+		}
 	}
 	signal(SIGQUIT, qflag);
 	if (name && name[0] == '-') {
@@ -2314,14 +2323,14 @@
 	switch(t->type) {
 	case TPAREN:
 	case TCOM:
-	    {
-		int child;
-		rv = forkexec(t, pin, pout, act, wp, &child);
-		if (child) {
-			exstat = rv;
-			leave();
+		{
+			int child;
+			rv = forkexec(t, pin, pout, act, wp, &child);
+			if (child) {
+				exstat = rv;
+				leave();
+			}
 		}
-	    }
 		break;
 
 	case TPIPE:
@@ -2828,6 +2837,21 @@
 	register char *sp, *tp;
 	int eacces = 0, asis = 0;
 
+#ifdef BB_FEATURE_SH_STANDALONE_SHELL
+	char *name = c;
+#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
+	name = get_last_path_component(name);
+#endif
+	optind = 1;
+	if (find_applet_by_name(name)) {
+		/* We have to exec here since we vforked.  Running 
+		 * run_applet_by_name() won't work and bad things
+		 * will happen. */
+		execve("/proc/self/exe", v, envp);
+		execve("busybox", v, envp);
+	}
+#endif
+
 	sp = any('/', c)? "": path->value;
 	asis = *sp == '\0';
 	while (asis || *sp != '\0') {
@@ -2842,6 +2866,8 @@
 			*tp++ = '/';
 		for (i = 0; (*tp++ = c[i++]) != '\0';)
 			;
+
+		fprintf(stderr, "calling exec\n");
 		execve(e.linep, v, envp);
 		switch (errno) {
 		case ENOEXEC:
@@ -2917,6 +2943,49 @@
  * built-in commands: doX
  */
 
+static int dohelp()
+{
+	int col;
+	const struct builtincmd *x;
+
+	printf("\nBuilt-in commands:\n");
+	printf("-------------------\n");
+
+	for (col=0, x = builtincmds; x->builtinfunc != NULL; x++) {
+		if (!x->name)
+			continue;
+		col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
+		if (col > 60) {
+			printf("\n");
+			col = 0;
+		}
+	}
+#ifdef BB_FEATURE_SH_STANDALONE_SHELL
+	{
+		int i;
+		const struct BB_applet *applet;
+		extern const struct BB_applet applets[];
+		extern const size_t NUM_APPLETS;
+
+		for (i=0, applet = applets; i < NUM_APPLETS; applet++, i++) {
+			if (!applet->name)
+				continue;
+		
+			col += printf("%s%s", ((col == 0) ? "\t" : " "), 
+					applet->name);
+			if (col > 60) {
+				printf("\n");
+				col = 0;
+			}
+		}
+	}
+#endif
+	printf("\n\n");
+	return EXIT_SUCCESS;
+}
+
+
+
 static int
 dolabel()
 {
@@ -3341,7 +3410,6 @@
 /*
  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
  * This file contains code for the times builtin.
- * $Id: msh.c,v 1.1 2001/06/29 04:57:14 andersen Exp $
  */
 static int dotimes ()
 {
@@ -3362,14 +3430,14 @@
 }
 
 
-static int (*inbuilt(s))()
-register char *s;
+static int (*inbuilt(char *s))()
 {
-	register struct builtin *bp;
+	const struct builtincmd *bp;
 
-	for (bp = builtin; bp->command != NULL; bp++)
-		if (strcmp(bp->command, s) == 0)
-			return(bp->fn);
+	for (bp = builtincmds; bp->name != NULL; bp++)
+		if (strcmp(bp->name, s) == 0)
+			return(bp->builtinfunc);
+
 	return((int(*)())NULL);
 }
 
diff --git a/sh.c b/sh.c
index e763436..15a3070 100644
--- a/sh.c
+++ b/sh.c
@@ -20,6 +20,15 @@
 
 #include "busybox.h"
 
+/* This is to make testing things a bit simpler (to avoid
+ * a full recompile) till we get the new build system in place */
+#if 0
+#undef BB_FEATURE_LASH
+#undef BB_FEATURE_HUSH
+#undef BB_FEATURE_MSH
+#define BB_FEATURE_ASH
+#endif
+
 #if defined BB_FEATURE_ASH
 #include "ash.c"
 #elif defined BB_FEATURE_MSH
diff --git a/shell/ash.c b/shell/ash.c
index 99460d3..4250f50 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -1603,6 +1603,7 @@
 static int exportcmd (int, char **);
 static int histcmd (int, char **);
 static int hashcmd (int, char **);
+static int helpcmd (int, char **);
 static int jobscmd (int, char **);
 static int localcmd (int, char **);
 #ifndef BB_PWD
@@ -1704,6 +1705,7 @@
 	{ BUILTIN_REGULAR   "getopts", getoptscmd },
 #endif
 	{ BUILTIN_NOSPEC    "hash", hashcmd },
+	{ BUILTIN_NOSPEC    "help", helpcmd },
 	{ BUILTIN_REGULAR   "jobs", jobscmd },
 #ifdef JOBS
 	{ BUILTIN_REGULAR   "kill", killcmd },
@@ -3274,6 +3276,7 @@
 setinteractive(int on)
 {
 	static int is_interactive;
+	static int do_banner=0;
 
 	if (on == is_interactive)
 		return;
@@ -3282,6 +3285,12 @@
 	setsignal(SIGTERM);
 	chkmail(1);
 	is_interactive = on;
+	if (do_banner==0 && is_interactive) {
+		/* Looks like they want an interactive shell */
+		printf( "\n\n" BB_BANNER " Built-in shell (ash)\n");
+		printf( "Enter 'help' for a list of built-in commands.\n\n");
+		do_banner=1;
+	}
 }
 
 static void
@@ -3802,6 +3811,51 @@
 
 
 
+/*** List the available builtins ***/
+
+
+static int helpcmd(int argc, char** argv)
+{
+	int col, i;
+	const struct builtincmd *x;
+
+	printf("\nBuilt-in commands:\n");
+	printf("-------------------\n");
+	for (col=0, i=0, x = builtincmds; i < NUMBUILTINS; x++, i++) {
+		if (!x->name || ! (x->name+1))
+			continue;
+		col += printf("%s%s", ((col == 0) ? "\t" : " "), 
+				(x->name+1));
+		if (col > 60) {
+			printf("\n");
+			col = 0;
+		}
+	}
+#ifdef BB_FEATURE_SH_STANDALONE_SHELL
+	{
+		const struct BB_applet *applet;
+		extern const struct BB_applet applets[];
+		extern const size_t NUM_APPLETS;
+
+		for (i=0, applet = applets; i < NUM_APPLETS; applet++, i++) {
+			if (!applet->name)
+				continue;
+		
+			col += printf("%s%s", ((col == 0) ? "\t" : " "), 
+					applet->name);
+			if (col > 60) {
+				printf("\n");
+				col = 0;
+			}
+		}
+	}
+#endif
+	printf("\n\n");
+	return EXIT_SUCCESS;
+}
+
+
+
 /*
  * Resolve a command name.  If you change this routine, you may have to
  * change the shellexec routine as well.
@@ -7755,6 +7809,11 @@
 	EXECCMD = find_builtin("exec");
 	EVALCMD = find_builtin("eval");
 
+#ifndef BB_FEATURE_SH_FANCY_PROMPT
+	unsetenv("PS1");
+	unsetenv("PS2");
+#endif
+
 #if PROFILE
 	monitor(4, etext, profile_buf, sizeof profile_buf, 50);
 #endif
@@ -13088,7 +13147,7 @@
 /*
  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
  * This file contains code for the times builtin.
- * $Id: ash.c,v 1.6 2001/07/06 04:26:23 andersen Exp $
+ * $Id: ash.c,v 1.7 2001/07/07 00:05:55 andersen Exp $
  */
 static int timescmd (int argc, char **argv)
 {
diff --git a/shell/msh.c b/shell/msh.c
index 66c3d54..e85d6ff 100644
--- a/shell/msh.c
+++ b/shell/msh.c
@@ -497,6 +497,7 @@
 static struct op *findcase (struct op *t, char *w );
 static void brkset(struct brkcon *bc );
 static int dolabel(void);
+static int dohelp(void);
 static int dochdir(struct op *t );
 static int doshift(struct op *t );
 static int dologin(struct op *t );
@@ -592,30 +593,31 @@
 };
 
 
-struct	builtin {
-	char *command;
-	int	 (*fn)();
+struct builtincmd {
+	const char *name;
+	int (*builtinfunc)();
 };
-static struct	builtin	builtin[] = {
+static const struct	builtincmd	builtincmds[] = {
+    {".",		dodot},
     {":",		dolabel},
-    {"cd",		dochdir},
-    {"shift",	doshift},
-    {"exec",	doexec},
-    {"wait",	dowait},
-    {"read",	doread},
-    {"eval",	doeval},
-    {"trap",	dotrap},
     {"break",	dobreak},
+    {"cd",		dochdir},
     {"continue",docontinue},
+    {"eval",	doeval},
+    {"exec",	doexec},
     {"exit",	doexit},
     {"export",	doexport},
-    {"readonly",doreadonly},
-    {"set",		doset},
-    {".",		dodot},
-    {"umask",	doumask},
+    {"help",	dohelp},
     {"login",	dologin},
     {"newgrp",	dologin},
+    {"read",	doread},
+    {"readonly",doreadonly},
+    {"set",		doset},
+    {"shift",	doshift},
     {"times",	dotimes},
+    {"trap",	dotrap},
+    {"umask",	doumask},
+    {"wait",	dowait},
     {0,0}
 };
 
@@ -731,14 +733,18 @@
 		setval(ifs, " \t\n");
 
 	prompt = lookup("PS1");
+#ifdef BB_FEATURE_SH_FANCY_PROMPT
 	if (prompt->value == null)
+#endif
 		setval(prompt, "$ ");
 	if (geteuid() == 0) {
 		setval(prompt, "# ");
 		prompt->status &= ~EXPORT;
 	}
 	cprompt = lookup("PS2");
+#ifdef BB_FEATURE_SH_FANCY_PROMPT
 	if (cprompt->value == null)
+#endif
 		setval(cprompt, "> ");
 
 	iof = filechar;
@@ -794,8 +800,11 @@
 	setdash();
 	if (e.iop < iostack) {
 		PUSHIO(afile, 0, iof);
-		if (isatty(0) && isatty(1) && !cflag)
+		if (isatty(0) && isatty(1) && !cflag) {
 			interactive++;
+			printf( "\n\n" BB_BANNER " Built-in shell (msh)\n");
+			printf( "Enter 'help' for a list of built-in commands.\n\n");
+		}
 	}
 	signal(SIGQUIT, qflag);
 	if (name && name[0] == '-') {
@@ -2314,14 +2323,14 @@
 	switch(t->type) {
 	case TPAREN:
 	case TCOM:
-	    {
-		int child;
-		rv = forkexec(t, pin, pout, act, wp, &child);
-		if (child) {
-			exstat = rv;
-			leave();
+		{
+			int child;
+			rv = forkexec(t, pin, pout, act, wp, &child);
+			if (child) {
+				exstat = rv;
+				leave();
+			}
 		}
-	    }
 		break;
 
 	case TPIPE:
@@ -2828,6 +2837,21 @@
 	register char *sp, *tp;
 	int eacces = 0, asis = 0;
 
+#ifdef BB_FEATURE_SH_STANDALONE_SHELL
+	char *name = c;
+#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
+	name = get_last_path_component(name);
+#endif
+	optind = 1;
+	if (find_applet_by_name(name)) {
+		/* We have to exec here since we vforked.  Running 
+		 * run_applet_by_name() won't work and bad things
+		 * will happen. */
+		execve("/proc/self/exe", v, envp);
+		execve("busybox", v, envp);
+	}
+#endif
+
 	sp = any('/', c)? "": path->value;
 	asis = *sp == '\0';
 	while (asis || *sp != '\0') {
@@ -2842,6 +2866,8 @@
 			*tp++ = '/';
 		for (i = 0; (*tp++ = c[i++]) != '\0';)
 			;
+
+		fprintf(stderr, "calling exec\n");
 		execve(e.linep, v, envp);
 		switch (errno) {
 		case ENOEXEC:
@@ -2917,6 +2943,49 @@
  * built-in commands: doX
  */
 
+static int dohelp()
+{
+	int col;
+	const struct builtincmd *x;
+
+	printf("\nBuilt-in commands:\n");
+	printf("-------------------\n");
+
+	for (col=0, x = builtincmds; x->builtinfunc != NULL; x++) {
+		if (!x->name)
+			continue;
+		col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
+		if (col > 60) {
+			printf("\n");
+			col = 0;
+		}
+	}
+#ifdef BB_FEATURE_SH_STANDALONE_SHELL
+	{
+		int i;
+		const struct BB_applet *applet;
+		extern const struct BB_applet applets[];
+		extern const size_t NUM_APPLETS;
+
+		for (i=0, applet = applets; i < NUM_APPLETS; applet++, i++) {
+			if (!applet->name)
+				continue;
+		
+			col += printf("%s%s", ((col == 0) ? "\t" : " "), 
+					applet->name);
+			if (col > 60) {
+				printf("\n");
+				col = 0;
+			}
+		}
+	}
+#endif
+	printf("\n\n");
+	return EXIT_SUCCESS;
+}
+
+
+
 static int
 dolabel()
 {
@@ -3341,7 +3410,6 @@
 /*
  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
  * This file contains code for the times builtin.
- * $Id: msh.c,v 1.1 2001/06/29 04:57:14 andersen Exp $
  */
 static int dotimes ()
 {
@@ -3362,14 +3430,14 @@
 }
 
 
-static int (*inbuilt(s))()
-register char *s;
+static int (*inbuilt(char *s))()
 {
-	register struct builtin *bp;
+	const struct builtincmd *bp;
 
-	for (bp = builtin; bp->command != NULL; bp++)
-		if (strcmp(bp->command, s) == 0)
-			return(bp->fn);
+	for (bp = builtincmds; bp->name != NULL; bp++)
+		if (strcmp(bp->name, s) == 0)
+			return(bp->builtinfunc);
+
 	return((int(*)())NULL);
 }