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
This commit is contained in:
Eric Andersen 2001-07-07 00:05:55 +00:00
parent b7e6f13b3c
commit 1c03923b0b
5 changed files with 325 additions and 62 deletions

61
ash.c
View File

@ -1603,6 +1603,7 @@ static int exitcmd (int, char **);
static int exportcmd (int, char **); static int exportcmd (int, char **);
static int histcmd (int, char **); static int histcmd (int, char **);
static int hashcmd (int, char **); static int hashcmd (int, char **);
static int helpcmd (int, char **);
static int jobscmd (int, char **); static int jobscmd (int, char **);
static int localcmd (int, char **); static int localcmd (int, char **);
#ifndef BB_PWD #ifndef BB_PWD
@ -1704,6 +1705,7 @@ static const struct builtincmd builtincmds[] = {
{ BUILTIN_REGULAR "getopts", getoptscmd }, { BUILTIN_REGULAR "getopts", getoptscmd },
#endif #endif
{ BUILTIN_NOSPEC "hash", hashcmd }, { BUILTIN_NOSPEC "hash", hashcmd },
{ BUILTIN_NOSPEC "help", helpcmd },
{ BUILTIN_REGULAR "jobs", jobscmd }, { BUILTIN_REGULAR "jobs", jobscmd },
#ifdef JOBS #ifdef JOBS
{ BUILTIN_REGULAR "kill", killcmd }, { BUILTIN_REGULAR "kill", killcmd },
@ -3274,6 +3276,7 @@ static void
setinteractive(int on) setinteractive(int on)
{ {
static int is_interactive; static int is_interactive;
static int do_banner=0;
if (on == is_interactive) if (on == is_interactive)
return; return;
@ -3282,6 +3285,12 @@ setinteractive(int on)
setsignal(SIGTERM); setsignal(SIGTERM);
chkmail(1); chkmail(1);
is_interactive = on; 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 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 * Resolve a command name. If you change this routine, you may have to
* change the shellexec routine as well. * change the shellexec routine as well.
@ -7755,6 +7809,11 @@ shell_main(argc, argv)
EXECCMD = find_builtin("exec"); EXECCMD = find_builtin("exec");
EVALCMD = find_builtin("eval"); EVALCMD = find_builtin("eval");
#ifndef BB_FEATURE_SH_FANCY_PROMPT
unsetenv("PS1");
unsetenv("PS2");
#endif
#if PROFILE #if PROFILE
monitor(4, etext, profile_buf, sizeof profile_buf, 50); monitor(4, etext, profile_buf, sizeof profile_buf, 50);
#endif #endif
@ -13088,7 +13147,7 @@ findvar(struct var **vpp, const char *name)
/* /*
* Copyright (c) 1999 Herbert Xu <herbert@debian.org> * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
* This file contains code for the times builtin. * 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) static int timescmd (int argc, char **argv)
{ {

128
msh.c
View File

@ -497,6 +497,7 @@ static struct op **find1case (struct op *t, char *w );
static struct op *findcase (struct op *t, char *w ); static struct op *findcase (struct op *t, char *w );
static void brkset(struct brkcon *bc ); static void brkset(struct brkcon *bc );
static int dolabel(void); static int dolabel(void);
static int dohelp(void);
static int dochdir(struct op *t ); static int dochdir(struct op *t );
static int doshift(struct op *t ); static int doshift(struct op *t );
static int dologin(struct op *t ); static int dologin(struct op *t );
@ -592,30 +593,31 @@ static struct res restab[] = {
}; };
struct builtin { struct builtincmd {
char *command; const char *name;
int (*fn)(); int (*builtinfunc)();
}; };
static struct builtin builtin[] = { static const struct builtincmd builtincmds[] = {
{".", dodot},
{":", dolabel}, {":", dolabel},
{"cd", dochdir},
{"shift", doshift},
{"exec", doexec},
{"wait", dowait},
{"read", doread},
{"eval", doeval},
{"trap", dotrap},
{"break", dobreak}, {"break", dobreak},
{"cd", dochdir},
{"continue",docontinue}, {"continue",docontinue},
{"eval", doeval},
{"exec", doexec},
{"exit", doexit}, {"exit", doexit},
{"export", doexport}, {"export", doexport},
{"readonly",doreadonly}, {"help", dohelp},
{"set", doset},
{".", dodot},
{"umask", doumask},
{"login", dologin}, {"login", dologin},
{"newgrp", dologin}, {"newgrp", dologin},
{"read", doread},
{"readonly",doreadonly},
{"set", doset},
{"shift", doshift},
{"times", dotimes}, {"times", dotimes},
{"trap", dotrap},
{"umask", doumask},
{"wait", dowait},
{0,0} {0,0}
}; };
@ -731,14 +733,18 @@ extern int shell_main(int argc, char **argv)
setval(ifs, " \t\n"); setval(ifs, " \t\n");
prompt = lookup("PS1"); prompt = lookup("PS1");
#ifdef BB_FEATURE_SH_FANCY_PROMPT
if (prompt->value == null) if (prompt->value == null)
#endif
setval(prompt, "$ "); setval(prompt, "$ ");
if (geteuid() == 0) { if (geteuid() == 0) {
setval(prompt, "# "); setval(prompt, "# ");
prompt->status &= ~EXPORT; prompt->status &= ~EXPORT;
} }
cprompt = lookup("PS2"); cprompt = lookup("PS2");
#ifdef BB_FEATURE_SH_FANCY_PROMPT
if (cprompt->value == null) if (cprompt->value == null)
#endif
setval(cprompt, "> "); setval(cprompt, "> ");
iof = filechar; iof = filechar;
@ -794,8 +800,11 @@ extern int shell_main(int argc, char **argv)
setdash(); setdash();
if (e.iop < iostack) { if (e.iop < iostack) {
PUSHIO(afile, 0, iof); PUSHIO(afile, 0, iof);
if (isatty(0) && isatty(1) && !cflag) if (isatty(0) && isatty(1) && !cflag) {
interactive++; 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); signal(SIGQUIT, qflag);
if (name && name[0] == '-') { if (name && name[0] == '-') {
@ -2314,14 +2323,14 @@ int act;
switch(t->type) { switch(t->type) {
case TPAREN: case TPAREN:
case TCOM: case TCOM:
{ {
int child; int child;
rv = forkexec(t, pin, pout, act, wp, &child); rv = forkexec(t, pin, pout, act, wp, &child);
if (child) { if (child) {
exstat = rv; exstat = rv;
leave(); leave();
}
} }
}
break; break;
case TPIPE: case TPIPE:
@ -2828,6 +2837,21 @@ char *c, **v, **envp;
register char *sp, *tp; register char *sp, *tp;
int eacces = 0, asis = 0; 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; sp = any('/', c)? "": path->value;
asis = *sp == '\0'; asis = *sp == '\0';
while (asis || *sp != '\0') { while (asis || *sp != '\0') {
@ -2842,6 +2866,8 @@ char *c, **v, **envp;
*tp++ = '/'; *tp++ = '/';
for (i = 0; (*tp++ = c[i++]) != '\0';) for (i = 0; (*tp++ = c[i++]) != '\0';)
; ;
fprintf(stderr, "calling exec\n");
execve(e.linep, v, envp); execve(e.linep, v, envp);
switch (errno) { switch (errno) {
case ENOEXEC: case ENOEXEC:
@ -2917,6 +2943,49 @@ int (*f)();
* built-in commands: doX * 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 static int
dolabel() dolabel()
{ {
@ -3341,7 +3410,6 @@ int out;
/* /*
* Copyright (c) 1999 Herbert Xu <herbert@debian.org> * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
* This file contains code for the times builtin. * 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 () static int dotimes ()
{ {
@ -3362,14 +3430,14 @@ static int dotimes ()
} }
static int (*inbuilt(s))() static int (*inbuilt(char *s))()
register 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); return((int(*)())NULL);
} }

9
sh.c
View File

@ -20,6 +20,15 @@
#include "busybox.h" #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 #if defined BB_FEATURE_ASH
#include "ash.c" #include "ash.c"
#elif defined BB_FEATURE_MSH #elif defined BB_FEATURE_MSH

View File

@ -1603,6 +1603,7 @@ static int exitcmd (int, char **);
static int exportcmd (int, char **); static int exportcmd (int, char **);
static int histcmd (int, char **); static int histcmd (int, char **);
static int hashcmd (int, char **); static int hashcmd (int, char **);
static int helpcmd (int, char **);
static int jobscmd (int, char **); static int jobscmd (int, char **);
static int localcmd (int, char **); static int localcmd (int, char **);
#ifndef BB_PWD #ifndef BB_PWD
@ -1704,6 +1705,7 @@ static const struct builtincmd builtincmds[] = {
{ BUILTIN_REGULAR "getopts", getoptscmd }, { BUILTIN_REGULAR "getopts", getoptscmd },
#endif #endif
{ BUILTIN_NOSPEC "hash", hashcmd }, { BUILTIN_NOSPEC "hash", hashcmd },
{ BUILTIN_NOSPEC "help", helpcmd },
{ BUILTIN_REGULAR "jobs", jobscmd }, { BUILTIN_REGULAR "jobs", jobscmd },
#ifdef JOBS #ifdef JOBS
{ BUILTIN_REGULAR "kill", killcmd }, { BUILTIN_REGULAR "kill", killcmd },
@ -3274,6 +3276,7 @@ static void
setinteractive(int on) setinteractive(int on)
{ {
static int is_interactive; static int is_interactive;
static int do_banner=0;
if (on == is_interactive) if (on == is_interactive)
return; return;
@ -3282,6 +3285,12 @@ setinteractive(int on)
setsignal(SIGTERM); setsignal(SIGTERM);
chkmail(1); chkmail(1);
is_interactive = on; 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 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 * Resolve a command name. If you change this routine, you may have to
* change the shellexec routine as well. * change the shellexec routine as well.
@ -7755,6 +7809,11 @@ shell_main(argc, argv)
EXECCMD = find_builtin("exec"); EXECCMD = find_builtin("exec");
EVALCMD = find_builtin("eval"); EVALCMD = find_builtin("eval");
#ifndef BB_FEATURE_SH_FANCY_PROMPT
unsetenv("PS1");
unsetenv("PS2");
#endif
#if PROFILE #if PROFILE
monitor(4, etext, profile_buf, sizeof profile_buf, 50); monitor(4, etext, profile_buf, sizeof profile_buf, 50);
#endif #endif
@ -13088,7 +13147,7 @@ findvar(struct var **vpp, const char *name)
/* /*
* Copyright (c) 1999 Herbert Xu <herbert@debian.org> * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
* This file contains code for the times builtin. * 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) static int timescmd (int argc, char **argv)
{ {

View File

@ -497,6 +497,7 @@ static struct op **find1case (struct op *t, char *w );
static struct op *findcase (struct op *t, char *w ); static struct op *findcase (struct op *t, char *w );
static void brkset(struct brkcon *bc ); static void brkset(struct brkcon *bc );
static int dolabel(void); static int dolabel(void);
static int dohelp(void);
static int dochdir(struct op *t ); static int dochdir(struct op *t );
static int doshift(struct op *t ); static int doshift(struct op *t );
static int dologin(struct op *t ); static int dologin(struct op *t );
@ -592,30 +593,31 @@ static struct res restab[] = {
}; };
struct builtin { struct builtincmd {
char *command; const char *name;
int (*fn)(); int (*builtinfunc)();
}; };
static struct builtin builtin[] = { static const struct builtincmd builtincmds[] = {
{".", dodot},
{":", dolabel}, {":", dolabel},
{"cd", dochdir},
{"shift", doshift},
{"exec", doexec},
{"wait", dowait},
{"read", doread},
{"eval", doeval},
{"trap", dotrap},
{"break", dobreak}, {"break", dobreak},
{"cd", dochdir},
{"continue",docontinue}, {"continue",docontinue},
{"eval", doeval},
{"exec", doexec},
{"exit", doexit}, {"exit", doexit},
{"export", doexport}, {"export", doexport},
{"readonly",doreadonly}, {"help", dohelp},
{"set", doset},
{".", dodot},
{"umask", doumask},
{"login", dologin}, {"login", dologin},
{"newgrp", dologin}, {"newgrp", dologin},
{"read", doread},
{"readonly",doreadonly},
{"set", doset},
{"shift", doshift},
{"times", dotimes}, {"times", dotimes},
{"trap", dotrap},
{"umask", doumask},
{"wait", dowait},
{0,0} {0,0}
}; };
@ -731,14 +733,18 @@ extern int shell_main(int argc, char **argv)
setval(ifs, " \t\n"); setval(ifs, " \t\n");
prompt = lookup("PS1"); prompt = lookup("PS1");
#ifdef BB_FEATURE_SH_FANCY_PROMPT
if (prompt->value == null) if (prompt->value == null)
#endif
setval(prompt, "$ "); setval(prompt, "$ ");
if (geteuid() == 0) { if (geteuid() == 0) {
setval(prompt, "# "); setval(prompt, "# ");
prompt->status &= ~EXPORT; prompt->status &= ~EXPORT;
} }
cprompt = lookup("PS2"); cprompt = lookup("PS2");
#ifdef BB_FEATURE_SH_FANCY_PROMPT
if (cprompt->value == null) if (cprompt->value == null)
#endif
setval(cprompt, "> "); setval(cprompt, "> ");
iof = filechar; iof = filechar;
@ -794,8 +800,11 @@ extern int shell_main(int argc, char **argv)
setdash(); setdash();
if (e.iop < iostack) { if (e.iop < iostack) {
PUSHIO(afile, 0, iof); PUSHIO(afile, 0, iof);
if (isatty(0) && isatty(1) && !cflag) if (isatty(0) && isatty(1) && !cflag) {
interactive++; 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); signal(SIGQUIT, qflag);
if (name && name[0] == '-') { if (name && name[0] == '-') {
@ -2314,14 +2323,14 @@ int act;
switch(t->type) { switch(t->type) {
case TPAREN: case TPAREN:
case TCOM: case TCOM:
{ {
int child; int child;
rv = forkexec(t, pin, pout, act, wp, &child); rv = forkexec(t, pin, pout, act, wp, &child);
if (child) { if (child) {
exstat = rv; exstat = rv;
leave(); leave();
}
} }
}
break; break;
case TPIPE: case TPIPE:
@ -2828,6 +2837,21 @@ char *c, **v, **envp;
register char *sp, *tp; register char *sp, *tp;
int eacces = 0, asis = 0; 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; sp = any('/', c)? "": path->value;
asis = *sp == '\0'; asis = *sp == '\0';
while (asis || *sp != '\0') { while (asis || *sp != '\0') {
@ -2842,6 +2866,8 @@ char *c, **v, **envp;
*tp++ = '/'; *tp++ = '/';
for (i = 0; (*tp++ = c[i++]) != '\0';) for (i = 0; (*tp++ = c[i++]) != '\0';)
; ;
fprintf(stderr, "calling exec\n");
execve(e.linep, v, envp); execve(e.linep, v, envp);
switch (errno) { switch (errno) {
case ENOEXEC: case ENOEXEC:
@ -2917,6 +2943,49 @@ int (*f)();
* built-in commands: doX * 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 static int
dolabel() dolabel()
{ {
@ -3341,7 +3410,6 @@ int out;
/* /*
* Copyright (c) 1999 Herbert Xu <herbert@debian.org> * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
* This file contains code for the times builtin. * 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 () static int dotimes ()
{ {
@ -3362,14 +3430,14 @@ static int dotimes ()
} }
static int (*inbuilt(s))() static int (*inbuilt(char *s))()
register 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); return((int(*)())NULL);
} }