#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__
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
#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)
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);
return p + 1;
}
+#ifndef __U_BOOT__
static int b_adduint(o_string *o, unsigned int i)
{
int r;
do r=b_addchr(o, *p++); while (r==0 && *p);
return r;
}
+#endif
static int static_get(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';
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?
*/
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");
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;
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;
}
}
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" */
}
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__
#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) {
{
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) {
}
#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)
{
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;
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
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=='=';
}
#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++;
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
* 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)
{
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__
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 {
#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 {
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;
}
debug_printf("\ninteractive=%d\n", interactive);
if (interactive) {
/* Looks like they want an interactive shell */
-#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
+#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