From 1c03923b0b50d710cf78d02cf2a2fc80090455ef Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Sat, 7 Jul 2001 00:05:55 +0000 Subject: [PATCH] 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 --- ash.c | 61 ++++++++++++++++++++++++- msh.c | 128 ++++++++++++++++++++++++++++++++++++++++------------ sh.c | 9 ++++ shell/ash.c | 61 ++++++++++++++++++++++++- shell/msh.c | 128 ++++++++++++++++++++++++++++++++++++++++------------ 5 files changed, 325 insertions(+), 62 deletions(-) diff --git a/ash.c b/ash.c index 99460d3d6..4250f50e2 100644 --- a/ash.c +++ b/ash.c @@ -1603,6 +1603,7 @@ static int exitcmd (int, char **); 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 @@ static const struct builtincmd builtincmds[] = { { 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 @@ static void setinteractive(int on) { static int is_interactive; + static int do_banner=0; if (on == is_interactive) return; @@ -3282,6 +3285,12 @@ setinteractive(int on) 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 @@ printentry(cmdp, verbose) +/*** 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 @@ shell_main(argc, argv) 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 @@ findvar(struct var **vpp, const char *name) /* * Copyright (c) 1999 Herbert Xu * 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 66c3d54d3..e85d6ff8f 100644 --- a/msh.c +++ b/msh.c @@ -497,6 +497,7 @@ static struct op **find1case (struct op *t, char *w ); 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 @@ static struct res restab[] = { }; -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 @@ extern int shell_main(int argc, char **argv) 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 @@ extern int shell_main(int argc, char **argv) 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 @@ int act; 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 @@ char *c, **v, **envp; 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 @@ char *c, **v, **envp; *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 @@ int (*f)(); * 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 @@ int out; /* * Copyright (c) 1999 Herbert Xu * 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 dotimes () } -static int (*inbuilt(s))() -register char *s; +static int (*inbuilt(char *s))() { - register struct builtin *bp; + const struct builtincmd *bp; + + for (bp = builtincmds; bp->name != NULL; bp++) + if (strcmp(bp->name, s) == 0) + return(bp->builtinfunc); - for (bp = builtin; bp->command != NULL; bp++) - if (strcmp(bp->command, s) == 0) - return(bp->fn); return((int(*)())NULL); } diff --git a/sh.c b/sh.c index e76343640..15a3070a6 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 99460d3d6..4250f50e2 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -1603,6 +1603,7 @@ static int exitcmd (int, char **); 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 @@ static const struct builtincmd builtincmds[] = { { 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 @@ static void setinteractive(int on) { static int is_interactive; + static int do_banner=0; if (on == is_interactive) return; @@ -3282,6 +3285,12 @@ setinteractive(int on) 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 @@ printentry(cmdp, verbose) +/*** 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 @@ shell_main(argc, argv) 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 @@ findvar(struct var **vpp, const char *name) /* * Copyright (c) 1999 Herbert Xu * 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 66c3d54d3..e85d6ff8f 100644 --- a/shell/msh.c +++ b/shell/msh.c @@ -497,6 +497,7 @@ static struct op **find1case (struct op *t, char *w ); 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 @@ static struct res restab[] = { }; -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 @@ extern int shell_main(int argc, char **argv) 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 @@ extern int shell_main(int argc, char **argv) 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 @@ int act; 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 @@ char *c, **v, **envp; 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 @@ char *c, **v, **envp; *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 @@ int (*f)(); * 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 @@ int out; /* * Copyright (c) 1999 Herbert Xu * 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 dotimes () } -static int (*inbuilt(s))() -register char *s; +static int (*inbuilt(char *s))() { - register struct builtin *bp; + const struct builtincmd *bp; + + for (bp = builtincmds; bp->name != NULL; bp++) + if (strcmp(bp->name, s) == 0) + return(bp->builtinfunc); - for (bp = builtin; bp->command != NULL; bp++) - if (strcmp(bp->command, s) == 0) - return(bp->fn); return((int(*)())NULL); } -- 2.25.1