]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/hush.c
Update MPC5200 FIFO Control settings
[karo-tx-uboot.git] / common / hush.c
index dbb952ddba315e250e3539568c12973277fd9982..eb7f7f15606ab652d43e2012db487fae0292962c 100644 (file)
@@ -290,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
@@ -313,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)
@@ -416,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);
@@ -936,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;
@@ -944,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)
 {
@@ -1017,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;
@@ -1843,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" */
@@ -1921,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__
@@ -2145,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)
 {
@@ -2152,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;
@@ -2168,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
@@ -2278,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=='=';
@@ -2749,15 +2796,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)
 {
@@ -2799,7 +2866,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__
@@ -2885,8 +2960,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 {
@@ -3107,7 +3185,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 {
@@ -3194,13 +3283,15 @@ static void u_boot_hush_reloc(void)
 
 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;
-       u_boot_hush_reloc();
+       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;
 }