]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/hush.c
Added support for TQM834x boards.
[karo-tx-uboot.git] / common / hush.c
index 925474332be99bf901efbf8c148e69a3fa6fc2e3..c10b1176f65638dcec691f62a6a1809661dd8661 100644 (file)
@@ -94,7 +94,8 @@
 #include <common.h>        /* readline */
 #include <hush.h>
 #include <command.h>        /* find_cmd */
-#include <cmd_bootm.h>      /* do_bootd */
+/*cmd_boot.c*/
+extern int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);      /* do_bootd */
 #endif
 #ifdef CFG_HUSH_PARSER
 #ifndef __U_BOOT__
 /* #include <dmalloc.h> */
 /* #define DEBUG_SHELL */
 
-#ifdef BB_VER
+#if 1
 #include "busybox.h"
 #include "cmdedit.h"
 #else
 #define applet_name "hush"
 #include "standalone.h"
 #define hush_main main
-#undef BB_FEATURE_SH_FANCY_PROMPT
+#undef CONFIG_FEATURE_SH_FANCY_PROMPT
+#define BB_BANNER
 #endif
 #endif
 #define SPECIAL_VAR_SYMBOL 03
@@ -288,6 +290,7 @@ char **global_argv;
 unsigned int global_argc;
 #endif
 unsigned int last_return_code;
+int nesting_level;
 #ifndef __U_BOOT__
 extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
 #endif
@@ -311,7 +314,7 @@ struct variables *top_vars = &shell_ver;
 #else
 static int flag_repeat = 0;
 static int do_repeat = 0;
-static struct variables *top_vars ;
+static struct variables *top_vars = NULL ;
 #endif /*__U_BOOT__ */
 
 #define B_CHUNK (100)
@@ -414,7 +417,9 @@ static int b_check_space(o_string *o, int len);
 static int b_addchr(o_string *o, int ch);
 static void b_reset(o_string *o);
 static int b_addqchr(o_string *o, int ch, int quote);
+#ifndef __U_BOOT__
 static int b_adduint(o_string *o, unsigned int i);
+#endif
 /*  in_str manipulations: */
 static int static_get(struct in_str *i);
 static int static_peek(struct in_str *i);
@@ -430,7 +435,7 @@ static void setup_string_in_str(struct in_str *i, const char *s);
 /*  close_me manipulations: */
 static void mark_open(int fd);
 static void mark_closed(int fd);
-static void close_all();
+static void close_all(void);
 #endif
 /*  "run" the final data structures: */
 static char *indenter(int i);
@@ -902,7 +907,7 @@ static void b_reset(o_string *o)
 static void b_free(o_string *o)
 {
        b_reset(o);
-       if (o->data != NULL) free(o->data);
+       free(o->data);
        o->data = NULL;
        o->maxlen = 0;
 }
@@ -934,6 +939,7 @@ char *simple_itoa(unsigned int i)
        return p + 1;
 }
 
+#ifndef __U_BOOT__
 static int b_adduint(o_string *o, unsigned int i)
 {
        int r;
@@ -942,6 +948,7 @@ static int b_adduint(o_string *o, unsigned int i)
        do r=b_addchr(o, *p++); while (r==0 && *p);
        return r;
 }
+#endif
 
 static int static_get(struct in_str *i)
 {
@@ -958,7 +965,7 @@ static int static_peek(struct in_str *i)
 #ifndef __U_BOOT__
 static inline void cmdedit_set_initial_prompt(void)
 {
-#ifndef BB_FEATURE_SH_FANCY_PROMPT
+#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
        PS1 = NULL;
 #else
        PS1 = getenv("PS1");
@@ -970,11 +977,10 @@ static inline void cmdedit_set_initial_prompt(void)
 static inline void setup_prompt_string(int promptmode, char **prompt_str)
 {
        debug_printf("setup_prompt_string %d ",promptmode);
-#ifndef BB_FEATURE_SH_FANCY_PROMPT
+#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
        /* Set up the prompt */
        if (promptmode == 1) {
-               if (PS1)
-                       free(PS1);
+               free(PS1);
                PS1=xmalloc(strlen(cwd)+4);
                sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ?  "$ ":"# ");
                *prompt_str = PS1;
@@ -995,7 +1001,7 @@ static void get_user_input(struct in_str *i)
        static char the_command[BUFSIZ];
 
        setup_prompt_string(i->promptmode, &prompt_str);
-#ifdef BB_FEATURE_COMMAND_EDITING
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
        /*
         ** enable command line editing only while a command line
         ** is actually being read; otherwise, we'll end up bequeathing
@@ -1016,12 +1022,30 @@ static void get_user_input(struct in_str *i)
        int n;
        static char the_command[CFG_CBSIZE];
 
+#ifdef CONFIG_BOOT_RETRY_TIME
+#  ifdef CONFIG_RESET_TO_RETRY
+       extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+#  else
+#      error "This currently only works with CONFIG_RESET_TO_RETRY enabled"
+#  endif
+       reset_cmd_timeout();
+#endif
        i->__promptme = 1;
        if (i->promptmode == 1) {
                n = readline(CFG_PROMPT);
        } else {
                n = readline(CFG_PROMPT_HUSH_PS2);
        }
+#ifdef CONFIG_BOOT_RETRY_TIME
+       if (n == -2) {
+         puts("\nTimeout waiting for command\n");
+#  ifdef CONFIG_RESET_TO_RETRY
+         do_reset(NULL, 0, 0, NULL);
+#  else
+#      error "This currently only works with CONFIG_RESET_TO_RETRY enabled"
+#  endif
+       }
+#endif
        if (n == -1 ) {
                flag_repeat = 0;
                i->__promptme = 0;
@@ -1048,12 +1072,12 @@ static void get_user_input(struct in_str *i)
                i->p = the_command;
        }
        else {
-               if (console_buffer[0] != '\n') {
-                       if (strlen(the_command) + strlen(console_buffer)
+               if (console_buffer[0] != '\n') {
+                       if (strlen(the_command) + strlen(console_buffer)
                            < CFG_CBSIZE) {
-                               n = strlen(the_command);
-                               the_command[n-1] = ' ';
-                               strcpy(&the_command[n],console_buffer);
+                               n = strlen(the_command);
+                               the_command[n-1] = ' ';
+                               strcpy(&the_command[n],console_buffer);
                        }
                        else {
                                the_command[0] = '\n';
@@ -1176,7 +1200,7 @@ static void mark_closed(int fd)
        free(tmp);
 }
 
-static void close_all()
+static void close_all(void)
 {
        struct close_me *c;
        for (c=close_me_head; c; c=c->next) {
@@ -1257,8 +1281,8 @@ static void pseudo_exec(struct child_prog *child)
                        if (p != child->argv[i]) free(p);
                }
                child->argv+=i;  /* XXX this hack isn't so horrible, since we are about
-                                       to exit, and therefore don't need to keep data
-                                       structures consistent for free() use. */
+                                       to exit, and therefore don't need to keep data
+                                       structures consistent for free() use. */
                /* If a variable is assigned in a forest, and nobody listens,
                 * was it ever really set?
                 */
@@ -1290,18 +1314,18 @@ static void pseudo_exec(struct child_prog *child)
                 * really dislike relying on /proc for things.  We could exec ourself
                 * from global_argv[0], but if we are in a chroot, we may not be able
                 * to find ourself... */
-#ifdef BB_FEATURE_SH_STANDALONE_SHELL
+#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
                {
                        int argc_l;
                        char** argv_l=child->argv;
                        char *name = child->argv[0];
 
-#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
+#ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
                        /* Following discussions from November 2000 on the busybox mailing
                         * list, the default configuration, (without
                         * get_last_path_component()) lets the user force use of an
                         * external command by specifying the full (with slashes) filename.
-                        * If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then applets
+                        * If you enable CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN then applets
                         * _aways_ override external commands, so if you want to run
                         * /bin/cat, it will use BusyBox cat even if /bin/cat exists on the
                         * filesystem and is _not_ busybox.  Some systems may want this,
@@ -1524,13 +1548,26 @@ static int run_pipe_real(struct pipe *pi)
        struct child_prog *child;
        struct built_in_command *x;
        char *p;
+# if __GNUC__
+       /* Avoid longjmp clobbering */
+       (void) &i;
+       (void) &nextin;
+       (void) &nextout;
+       (void) &child;
+# endif
 #else
        int nextin;
        int flag = do_repeat ? CMD_FLAG_REPEAT : 0;
        struct child_prog *child;
        cmd_tbl_t *cmdtp;
        char *p;
-#endif
+# if __GNUC__
+       /* Avoid longjmp clobbering */
+       (void) &i;
+       (void) &nextin;
+       (void) &child;
+# endif
+#endif /* __U_BOOT__ */
 
        nextin = 0;
 #ifndef __U_BOOT__
@@ -1635,14 +1672,18 @@ static int run_pipe_real(struct pipe *pi)
                                        child->argv[i]);
                                return -1;
                        }
-                       /* Look up command in command table */
+                       /* Look up command in command table */
+
+
                        if ((cmdtp = find_cmd(child->argv[i])) == NULL) {
                                printf ("Unknown command '%s' - try 'help'\n", child->argv[i]);
                                return -1;      /* give up after bad command */
                        } else {
                                int rcode;
 #if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
-                               /* avoid "bootd" recursion */
+           extern int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+
+                               /* avoid "bootd" recursion */
                                if (cmdtp->cmd == do_bootd) {
                                        if (flag & CMD_FLAG_BOOTD) {
                                                printf ("'bootd' recursion detected\n");
@@ -1652,7 +1693,7 @@ static int run_pipe_real(struct pipe *pi)
                                        flag |= CMD_FLAG_BOOTD;
                                }
 #endif /* CFG_CMD_BOOTD */
-                               /* found - check max args */
+                               /* found - check max args */
                                if ((child->argc - i) > cmdtp->maxargs) {
                                        printf ("Usage:\n%s\n", cmdtp->usage);
                                        return -1;
@@ -1663,15 +1704,20 @@ static int run_pipe_real(struct pipe *pi)
                                rcode = x->function(child);
 #else
                                /* OK - call function to do the command */
+
                                rcode = (cmdtp->cmd)
-                                       (cmdtp, flag,child->argc-i,&child->argv[i]);
+(cmdtp, flag,child->argc-i,&child->argv[i]);
                                if ( !cmdtp->repeatable )
                                        flag_repeat = 0;
+
+
 #endif
                                child->argv-=i;  /* XXX restore hack so free() can work right */
 #ifndef __U_BOOT__
+
                                restore_redirects(squirrel);
 #endif
+
                                return rcode;
                        }
                }
@@ -1820,7 +1866,7 @@ static int run_list_real(struct pipe *pi)
                if (rmode == RES_THEN || rmode == RES_ELSE) if_code = next_if_code;
                if (rmode == RES_THEN &&  if_code) continue;
                if (rmode == RES_ELSE && !if_code) continue;
-               if (rmode == RES_ELIF && !if_code) continue;
+               if (rmode == RES_ELIF && !if_code) break;
                if (rmode == RES_FOR && pi->num_progs) {
                        if (!list) {
                                /* if no variable values after "in" we skip "for" */
@@ -1898,6 +1944,10 @@ static int run_list_real(struct pipe *pi)
                }
                last_return_code=rcode;
 #else
+               if (rcode < -1) {
+                       last_return_code = -rcode - 2;
+                       return -2;      /* exit */
+               }
                last_return_code=(rcode == 0) ? 0 : 1;
 #endif
 #ifndef __U_BOOT__
@@ -1952,11 +2002,11 @@ static int free_pipe(struct pipe *pi, int indent)
 #ifndef __U_BOOT__
                        globfree(&child->glob_result);
 #else
-                       for (a = child->argc;a >= 0;a--) {
-                               free(child->argv[a]);
-                       }
+                       for (a = child->argc;a >= 0;a--) {
+                               free(child->argv[a]);
+                       }
                                        free(child->argv);
-                       child->argc = 0;
+                       child->argc = 0;
 #endif
                        child->argv=NULL;
                } else if (child->group) {
@@ -2090,17 +2140,17 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)
 {
        int gr;
 
-       /* short-circuit for null word */
+       /* short-circuit for null word */
        /* we can code this better when the debug_printf's are gone */
-       if (dest->length == 0) {
-               if (dest->nonnull) {
-                       /* bash man page calls this an "explicit" null */
-                       gr = globhack(dest->data, flags, pglob);
-                       debug_printf("globhack returned %d\n",gr);
-               } else {
+       if (dest->length == 0) {
+               if (dest->nonnull) {
+                       /* bash man page calls this an "explicit" null */
+                       gr = globhack(dest->data, flags, pglob);
+                       debug_printf("globhack returned %d\n",gr);
+               } else {
                        return 0;
                }
-       } else if (glob_needed(dest->data)) {
+       } else if (glob_needed(dest->data)) {
                gr = glob(dest->data, flags, NULL, pglob);
                debug_printf("glob returned %d\n",gr);
                if (gr == GLOB_NOMATCH) {
@@ -2122,6 +2172,10 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)
 }
 #endif
 
+#ifdef __U_BOOT__
+static char *get_dollar_var(char ch);
+#endif
+
 /* This is used to get/check local shell variables */
 static char *get_local_var(const char *s)
 {
@@ -2129,6 +2183,12 @@ static char *get_local_var(const char *s)
 
        if (!s)
                return NULL;
+
+#ifdef __U_BOOT__
+       if (*s == '$')
+               return get_dollar_var(s[1]);
+#endif
+
        for (cur = top_vars; cur; cur=cur->next)
                if(strcmp(cur->name, s)==0)
                        return cur->value;
@@ -2145,12 +2205,19 @@ static int set_local_var(const char *s, int flg_export)
        int result=0;
        struct variables *cur;
 
+#ifdef __U_BOOT__
+       /* might be possible! */
+       if (!isalpha(*s))
+               return -1;
+#endif
+
        name=strdup(s);
 
 #ifdef __U_BOOT__
        if (getenv(name) != NULL) {
                printf ("ERROR: "
-                               "There is a global environmet variable with the same name.\n");
+                               "There is a global environment variable with the same name.\n");
+               free(name);
                return -1;
        }
 #endif
@@ -2255,7 +2322,10 @@ static void unset_local_var(const char *name)
 
 static int is_assignment(const char *s)
 {
-       if (s==NULL || !isalpha(*s)) return 0;
+       if (s == NULL)
+               return 0;
+
+       if (!isalpha(*s)) return 0;
        ++s;
        while(isalnum(*s) || *s=='_') ++s;
        return *s=='=';
@@ -2319,6 +2389,7 @@ struct pipe *new_pipe(void) {
        pi->progs = NULL;
        pi->next = NULL;
        pi->followup = 0;  /* invalid */
+       pi->r_mode = RES_NONE;
        return pi;
 }
 
@@ -2344,34 +2415,35 @@ static void initialize_context(struct p_context *ctx)
  * should handle if, then, elif, else, fi, for, while, until, do, done.
  * case, function, and select are obnoxious, save those for later.
  */
+struct reserved_combo {
+       char *literal;
+       int code;
+       long flag;
+};
+/* Mostly a list of accepted follow-up reserved words.
+ * FLAG_END means we are done with the sequence, and are ready
+ * to turn the compound list into a command.
+ * FLAG_START means the word must start a new compound list.
+ */
+static struct reserved_combo reserved_list[] = {
+       { "if",    RES_IF,    FLAG_THEN | FLAG_START },
+       { "then",  RES_THEN,  FLAG_ELIF | FLAG_ELSE | FLAG_FI },
+       { "elif",  RES_ELIF,  FLAG_THEN },
+       { "else",  RES_ELSE,  FLAG_FI   },
+       { "fi",    RES_FI,    FLAG_END  },
+       { "for",   RES_FOR,   FLAG_IN   | FLAG_START },
+       { "while", RES_WHILE, FLAG_DO   | FLAG_START },
+       { "until", RES_UNTIL, FLAG_DO   | FLAG_START },
+       { "in",    RES_IN,    FLAG_DO   },
+       { "do",    RES_DO,    FLAG_DONE },
+       { "done",  RES_DONE,  FLAG_END  }
+};
+#define NRES (sizeof(reserved_list)/sizeof(struct reserved_combo))
+
 int reserved_word(o_string *dest, struct p_context *ctx)
 {
-       struct reserved_combo {
-               char *literal;
-               int code;
-               long flag;
-       };
-       /* Mostly a list of accepted follow-up reserved words.
-        * FLAG_END means we are done with the sequence, and are ready
-        * to turn the compound list into a command.
-        * FLAG_START means the word must start a new compound list.
-        */
-       static struct reserved_combo reserved_list[] = {
-               { "if",    RES_IF,    FLAG_THEN | FLAG_START },
-               { "then",  RES_THEN,  FLAG_ELIF | FLAG_ELSE | FLAG_FI },
-               { "elif",  RES_ELIF,  FLAG_THEN },
-               { "else",  RES_ELSE,  FLAG_FI   },
-               { "fi",    RES_FI,    FLAG_END  },
-               { "for",   RES_FOR,   FLAG_IN   | FLAG_START },
-               { "while", RES_WHILE, FLAG_DO   | FLAG_START },
-               { "until", RES_UNTIL, FLAG_DO   | FLAG_START },
-               { "in",    RES_IN,    FLAG_DO   },
-               { "do",    RES_DO,    FLAG_DONE },
-               { "done",  RES_DONE,  FLAG_END  }
-       };
        struct reserved_combo *r;
        for (r=reserved_list;
-#define NRES sizeof(reserved_list)/sizeof(struct reserved_combo)
                r<reserved_list+NRES; r++) {
                if (strcmp(dest->data, r->literal) == 0) {
                        debug_printf("found reserved word %s, code %d\n",r->literal,r->code);
@@ -2448,7 +2520,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
                }
 #ifndef __U_BOOT__
                glob_target = &child->glob_result;
-               if (child->argv) flags |= GLOB_APPEND;
+               if (child->argv) flags |= GLOB_APPEND;
 #else
                for (cnt = 1, s = dest->data; s && *s; s++) {
                        if (*s == '\\') s++;
@@ -2508,9 +2580,9 @@ static int done_command(struct p_context *ctx)
        struct child_prog *prog=ctx->child;
 
        if (prog && prog->group == NULL
-                && prog->argv == NULL
+                && prog->argv == NULL
 #ifndef __U_BOOT__
-                && prog->redirects == NULL) {
+                && prog->redirects == NULL) {
 #else
                                                                                ) {
 #endif
@@ -2725,15 +2797,35 @@ static int parse_group(o_string *dest, struct p_context *ctx,
  * see the bash man page under "Parameter Expansion" */
 static char *lookup_param(char *src)
 {
-       char *p=NULL;
-       if (src) {
+       char *p;
+
+       if (!src)
+               return NULL;
+
                p = getenv(src);
                if (!p)
                        p = get_local_var(src);
-       }
+
        return p;
 }
 
+#ifdef __U_BOOT__
+static char *get_dollar_var(char ch)
+{
+       static char buf[40];
+
+       buf[0] = '\0';
+       switch (ch) {
+               case '?':
+                       sprintf(buf, "%u", (unsigned int)last_return_code);
+                       break;
+               default:
+                       return NULL;
+       }
+       return buf;
+}
+#endif
+
 /* return code: 0 for OK, 1 for syntax error */
 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input)
 {
@@ -2775,7 +2867,15 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
                        break;
 #endif
                case '?':
+#ifndef __U_BOOT__
                        b_adduint(dest,last_return_code);
+#else
+                       ctx->child->sp++;
+                       b_addchr(dest, SPECIAL_VAR_SYMBOL);
+                       b_addchr(dest, '$');
+                       b_addchr(dest, '?');
+                       b_addchr(dest, SPECIAL_VAR_SYMBOL);
+#endif
                        advance = 1;
                        break;
 #ifndef __U_BOOT__
@@ -2861,8 +2961,11 @@ int parse_stream(o_string *dest, struct p_context *ctx,
                if (input->__promptme == 0) return 1;
 #endif
                next = (ch == '\n') ? 0 : b_peek(input);
-               debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d\n",
-                       ch,ch,m,dest->quote);
+
+               debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d - %c\n",
+                       ch >= ' ' ? ch : '.', ch, m,
+                       dest->quote, ctx->stack == NULL ? '*' : '.');
+
                if (m==0 || ((m==1 || m==2) && dest->quote)) {
                        b_addqchr(dest, ch, dest->quote);
                } else {
@@ -3083,7 +3186,18 @@ int parse_stream_outer(struct in_str *inp, int flag)
 #ifndef __U_BOOT__
                        run_list(ctx.list_head);
 #else
-                       if (((code = run_list(ctx.list_head)) == -1))
+                       code = run_list(ctx.list_head);
+                       if (code == -2) {       /* exit */
+                               b_free(&temp);
+                               code = 0;
+                               /* XXX hackish way to not allow exit from main loop */
+                               if (inp->peek == file_peek) {
+                                       printf("exit not allowed from main input shell.\n");
+                                       continue;
+                               }
+                               break;
+                       }
+                       if (code == -1)
                            flag_repeat = 0;
 #endif
                } else {
@@ -3156,14 +3270,29 @@ int parse_file_outer(void)
 }
 
 #ifdef __U_BOOT__
+static void u_boot_hush_reloc(void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+       unsigned long addr;
+       struct reserved_combo *r;
+
+       for (r=reserved_list; r<reserved_list+NRES; r++) {
+               addr = (ulong) (r->literal) + gd->reloc_off;
+               r->literal = (char *)addr;
+       }
+}
+
 int u_boot_hush_start(void)
 {
-       top_vars = malloc(sizeof(struct variables));
-       top_vars->name = "HUSH_VERSION";
-       top_vars->value = "0.01";
-       top_vars->next = 0;
-       top_vars->flg_export = 0;
-       top_vars->flg_read_only = 1;
+       if (top_vars == NULL) {
+               top_vars = malloc(sizeof(struct variables));
+               top_vars->name = "HUSH_VERSION";
+               top_vars->value = "0.01";
+               top_vars->next = 0;
+               top_vars->flg_export = 0;
+               top_vars->flg_read_only = 1;
+               u_boot_hush_reloc();
+       }
        return 0;
 }
 
@@ -3194,7 +3323,7 @@ static void *xrealloc(void *ptr, size_t size)
 /* Make sure we have a controlling tty.  If we get started under a job
  * aware app (like bash for example), make sure we are now in charge so
  * we don't fight over who gets the foreground */
-static void setup_job_control()
+static void setup_job_control(void)
 {
        static pid_t shell_pgrp;
        /* Loop until we are in the foreground.  */
@@ -3243,7 +3372,7 @@ int hush_main(int argc, char **argv)
 
        /* Initialize some more globals to non-zero values */
        set_cwd();
-#ifdef BB_FEATURE_COMMAND_EDITING
+#ifdef CONFIG_FEATURE_COMMAND_EDITING
        cmdedit_set_initial_prompt();
 #else
        PS1 = NULL;
@@ -3312,7 +3441,10 @@ int hush_main(int argc, char **argv)
        debug_printf("\ninteractive=%d\n", interactive);
        if (interactive) {
                /* Looks like they want an interactive shell */
-               fprintf(stdout, "\nhush -- the humble shell v0.01 (testing)\n\n");
+#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+               printf( "\n\n" BB_BANNER " hush - the humble shell v0.01 (testing)\n");
+               printf( "Enter 'help' for a list of built-in commands.\n\n");
+#endif
                setup_job_control();
        }
 
@@ -3327,7 +3459,7 @@ int hush_main(int argc, char **argv)
        input = xfopen(argv[optind], "r");
        opt = parse_file_outer(input);
 
-#ifdef BB_FEATURE_CLEAN_UP
+#ifdef CONFIG_FEATURE_CLEAN_UP
        fclose(input);
        if (cwd && cwd != unknown)
                free((char*)cwd);