]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/hush.c
Merge with git+ssh://gemini_vpn/home/wd/git/u-boot/master
[karo-tx-uboot.git] / common / hush.c
index 7e8a80deb968075b3560119cae1b318db35d4e5a..582635c04c70621b2c94b3b1265e201f8d172313 100644 (file)
@@ -138,6 +138,8 @@ extern int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);      /
 #endif
 
 #ifdef __U_BOOT__
+DECLARE_GLOBAL_DATA_PTR;
+
 #define EXIT_SUCCESS 0
 #define EOF -1
 #define syntax() syntax_err()
@@ -290,12 +292,13 @@ 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
 
 /* "globals" within this file */
-static char *ifs;
+static uchar *ifs;
 static char map[256];
 #ifndef __U_BOOT__
 static int fake_mode;
@@ -416,7 +419,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 +941,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 +950,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 +1024,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;
@@ -1657,7 +1682,7 @@ static int run_pipe_real(struct pipe *pi)
                                return -1;      /* give up after bad command */
                        } else {
                                int rcode;
-#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
+#if defined(CONFIG_CMD_BOOTD)
            extern int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
 
                                /* avoid "bootd" recursion */
@@ -1669,7 +1694,7 @@ static int run_pipe_real(struct pipe *pi)
                                else
                                        flag |= CMD_FLAG_BOOTD;
                                }
-#endif /* CFG_CMD_BOOTD */
+#endif
                                /* found - check max args */
                                if ((child->argc - i) > cmdtp->maxargs) {
                                        printf ("Usage:\n%s\n", cmdtp->usage);
@@ -1843,7 +1868,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 +1946,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 +2174,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 +2185,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 +2207,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 +2324,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=='=';
@@ -2342,6 +2391,7 @@ struct pipe *new_pipe(void) {
        pi->progs = NULL;
        pi->next = NULL;
        pi->followup = 0;  /* invalid */
+       pi->r_mode = RES_NONE;
        return pi;
 }
 
@@ -2749,15 +2799,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 +2869,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 +2963,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 {
@@ -3055,8 +3136,8 @@ void mapset(const unsigned char *set, int code)
 void update_ifs_map(void)
 {
        /* char *ifs and char map[256] are both globals. */
-       ifs = getenv("IFS");
-       if (ifs == NULL) ifs=" \t\n";
+       ifs = (uchar *)getenv("IFS");
+       if (ifs == NULL) ifs=(uchar *)" \t\n";
        /* Precompute a list of 'flow through' behavior so it can be treated
         * quickly up front.  Computation is necessary because of IFS.
         * Special case handling of IFS == " \t\n" is not implemented.
@@ -3065,11 +3146,11 @@ void update_ifs_map(void)
         */
        memset(map,0,sizeof(map)); /* most characters flow through always */
 #ifndef __U_BOOT__
-       mapset("\\$'\"`", 3);      /* never flow through */
-       mapset("<>;&|(){}#", 1);   /* flow through if quoted */
+       mapset((uchar *)"\\$'\"`", 3);      /* never flow through */
+       mapset((uchar *)"<>;&|(){}#", 1);   /* flow through if quoted */
 #else
-       mapset("\\$'\"", 3);       /* never flow through */
-       mapset(";&|#", 1);         /* flow through if quoted */
+       mapset((uchar *)"\\$'\"", 3);       /* never flow through */
+       mapset((uchar *)";&|#", 1);         /* flow through if quoted */
 #endif
        mapset(ifs, 2);            /* also flow through if quoted */
 }
@@ -3089,7 +3170,7 @@ int parse_stream_outer(struct in_str *inp, int flag)
                ctx.type = flag;
                initialize_context(&ctx);
                update_ifs_map();
-               if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset(";$&|", 0);
+               if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset((uchar *)";$&|", 0);
                inp->promptmode=1;
                rcode = parse_stream(&temp, &ctx, inp, '\n');
 #ifdef __U_BOOT__
@@ -3107,7 +3188,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 {
@@ -3182,7 +3274,6 @@ 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;