An update to hush from Larry:
It should recover more smoothly from syntax errors, and it now has a decent guess when the reserved word construct is over (or not) to control execution and prompting. I took out all the redundant standalone test copies of libbb routines, but left in a hook so I can include those for my testing. I'll post that include file on my web site. - Larry
This commit is contained in:
parent
0081466925
commit
af44a0e8f4
112
hush.c
112
hush.c
@ -111,96 +111,11 @@
|
|||||||
#include "busybox.h"
|
#include "busybox.h"
|
||||||
#include "cmdedit.h"
|
#include "cmdedit.h"
|
||||||
#else
|
#else
|
||||||
/* in place of #include "busybox.h"; much of this is indeed
|
|
||||||
* pasted in from the copy of busybox.h in busybox-0.49pre */
|
|
||||||
|
|
||||||
#define xrealloc realloc
|
|
||||||
#define applet_name "hush"
|
#define applet_name "hush"
|
||||||
|
#include "standalone.h"
|
||||||
#define shell_main main
|
#define shell_main main
|
||||||
|
#define BB_FEATURE_SH_SIMPLE_PROMPT
|
||||||
extern void *xmalloc(size_t size)
|
#endif
|
||||||
{
|
|
||||||
void *ptr = malloc(size);
|
|
||||||
|
|
||||||
if (!ptr) {
|
|
||||||
fprintf(stderr, "memory_exhausted\n");
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void usage(const char *usage)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Usage: %s\n", usage);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void verror_msg(const char *s, va_list p)
|
|
||||||
{
|
|
||||||
fflush(stdout);
|
|
||||||
fprintf(stderr, "%s: ", applet_name);
|
|
||||||
vfprintf(stderr, s, p);
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void error_msg(const char *s, ...)
|
|
||||||
{
|
|
||||||
va_list p;
|
|
||||||
|
|
||||||
va_start(p, s);
|
|
||||||
verror_msg(s, p);
|
|
||||||
va_end(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void error_msg_and_die(const char *s, ...)
|
|
||||||
{
|
|
||||||
va_list p;
|
|
||||||
|
|
||||||
va_start(p, s);
|
|
||||||
verror_msg(s, p);
|
|
||||||
va_end(p);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vperror_msg(const char *s, va_list p)
|
|
||||||
{
|
|
||||||
fflush(stdout);
|
|
||||||
fprintf(stderr, "%s: ", applet_name);
|
|
||||||
if (s && *s) {
|
|
||||||
vfprintf(stderr, s, p);
|
|
||||||
fputs(": ", stderr);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "%s\n", strerror(errno));
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void perror_msg(const char *s, ...)
|
|
||||||
{
|
|
||||||
va_list p;
|
|
||||||
|
|
||||||
va_start(p, s);
|
|
||||||
vperror_msg(s, p);
|
|
||||||
va_end(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void perror_msg_and_die(const char *s, ...)
|
|
||||||
{
|
|
||||||
va_list p;
|
|
||||||
|
|
||||||
va_start(p, s);
|
|
||||||
vperror_msg(s, p);
|
|
||||||
va_end(p);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *xfopen(const char *path, const char *mode)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
if ((fp = fopen(path, mode)) == NULL)
|
|
||||||
perror_msg_and_die(path);
|
|
||||||
return fp;
|
|
||||||
}
|
|
||||||
#endif /* of busybox.h replacement */
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
REDIRECT_INPUT = 1,
|
REDIRECT_INPUT = 1,
|
||||||
@ -241,7 +156,8 @@ typedef enum {
|
|||||||
RES_UNTIL = 8,
|
RES_UNTIL = 8,
|
||||||
RES_DO = 9,
|
RES_DO = 9,
|
||||||
RES_DONE = 10,
|
RES_DONE = 10,
|
||||||
RES_XXXX = 11
|
RES_XXXX = 11,
|
||||||
|
RES_SNTX = 12
|
||||||
} reserved_style;
|
} reserved_style;
|
||||||
#define FLAG_END (1<<RES_NONE)
|
#define FLAG_END (1<<RES_NONE)
|
||||||
#define FLAG_IF (1<<RES_IF)
|
#define FLAG_IF (1<<RES_IF)
|
||||||
@ -331,7 +247,7 @@ static int fake_mode=0;
|
|||||||
static int interactive=0;
|
static int interactive=0;
|
||||||
static struct close_me *close_me_head = NULL;
|
static struct close_me *close_me_head = NULL;
|
||||||
static char *cwd;
|
static char *cwd;
|
||||||
static struct jobset job_list = { NULL, NULL };
|
/* static struct jobset job_list = { NULL, NULL }; */
|
||||||
static unsigned int last_bg_pid=0;
|
static unsigned int last_bg_pid=0;
|
||||||
static char *PS1;
|
static char *PS1;
|
||||||
static char *PS2 = "> ";
|
static char *PS2 = "> ";
|
||||||
@ -843,6 +759,7 @@ static inline void cmdedit_set_initial_prompt(void)
|
|||||||
|
|
||||||
static inline void setup_prompt_string(int promptmode, char **prompt_str)
|
static inline void setup_prompt_string(int promptmode, char **prompt_str)
|
||||||
{
|
{
|
||||||
|
debug_printf("setup_prompt_string %d ",promptmode);
|
||||||
#ifdef BB_FEATURE_SH_SIMPLE_PROMPT
|
#ifdef BB_FEATURE_SH_SIMPLE_PROMPT
|
||||||
/* Set up the prompt */
|
/* Set up the prompt */
|
||||||
if (promptmode == 1) {
|
if (promptmode == 1) {
|
||||||
@ -857,6 +774,7 @@ static inline void setup_prompt_string(int promptmode, char **prompt_str)
|
|||||||
#else
|
#else
|
||||||
*prompt_str = (promptmode==0)? PS1 : PS2;
|
*prompt_str = (promptmode==0)? PS1 : PS2;
|
||||||
#endif
|
#endif
|
||||||
|
debug_printf("result %s\n",*prompt_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_user_input(struct in_str *i)
|
static void get_user_input(struct in_str *i)
|
||||||
@ -1537,7 +1455,10 @@ int reserved_word(o_string *dest, struct p_context *ctx)
|
|||||||
initialize_context(ctx);
|
initialize_context(ctx);
|
||||||
ctx->stack=new;
|
ctx->stack=new;
|
||||||
} else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
|
} else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
|
||||||
syntax(); /* XXX how do we get out? */
|
syntax();
|
||||||
|
ctx->w = RES_SNTX;
|
||||||
|
b_reset (dest);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
ctx->w=r->code;
|
ctx->w=r->code;
|
||||||
ctx->old_flag = r->flag;
|
ctx->old_flag = r->flag;
|
||||||
@ -1579,7 +1500,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
|
|||||||
}
|
}
|
||||||
if (!child->argv) {
|
if (!child->argv) {
|
||||||
debug_printf("checking %s for reserved-ness\n",dest->data);
|
debug_printf("checking %s for reserved-ness\n",dest->data);
|
||||||
if (reserved_word(dest,ctx)) return 0;
|
if (reserved_word(dest,ctx)) return ctx->w==RES_SNTX;
|
||||||
}
|
}
|
||||||
glob_target = &child->glob_result;
|
glob_target = &child->glob_result;
|
||||||
if (child->argv) flags |= GLOB_APPEND;
|
if (child->argv) flags |= GLOB_APPEND;
|
||||||
@ -1921,11 +1842,16 @@ int parse_stream(o_string *dest, struct p_context *ctx,
|
|||||||
ch,ch,m,dest->quote);
|
ch,ch,m,dest->quote);
|
||||||
if (m==0 || ((m==1 || m==2) && dest->quote)) {
|
if (m==0 || ((m==1 || m==2) && dest->quote)) {
|
||||||
b_addqchr(dest, ch, dest->quote);
|
b_addqchr(dest, ch, dest->quote);
|
||||||
} else if (ch == end_trigger && !dest->quote) {
|
} else if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
|
||||||
debug_printf("leaving parse_stream\n");
|
debug_printf("leaving parse_stream\n");
|
||||||
return 0;
|
return 0;
|
||||||
} else if (m==2 && !dest->quote) { /* IFS */
|
} else if (m==2 && !dest->quote) { /* IFS */
|
||||||
done_word(dest, ctx);
|
done_word(dest, ctx);
|
||||||
|
if (ch=='\n') done_pipe(ctx,PIPE_SEQ);
|
||||||
|
if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
|
||||||
|
debug_printf("leaving parse_stream (stupid duplication)\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#if 0
|
#if 0
|
||||||
if (ch=='\n') {
|
if (ch=='\n') {
|
||||||
/* Yahoo! Time to run with it! */
|
/* Yahoo! Time to run with it! */
|
||||||
|
112
shell/hush.c
112
shell/hush.c
@ -111,96 +111,11 @@
|
|||||||
#include "busybox.h"
|
#include "busybox.h"
|
||||||
#include "cmdedit.h"
|
#include "cmdedit.h"
|
||||||
#else
|
#else
|
||||||
/* in place of #include "busybox.h"; much of this is indeed
|
|
||||||
* pasted in from the copy of busybox.h in busybox-0.49pre */
|
|
||||||
|
|
||||||
#define xrealloc realloc
|
|
||||||
#define applet_name "hush"
|
#define applet_name "hush"
|
||||||
|
#include "standalone.h"
|
||||||
#define shell_main main
|
#define shell_main main
|
||||||
|
#define BB_FEATURE_SH_SIMPLE_PROMPT
|
||||||
extern void *xmalloc(size_t size)
|
#endif
|
||||||
{
|
|
||||||
void *ptr = malloc(size);
|
|
||||||
|
|
||||||
if (!ptr) {
|
|
||||||
fprintf(stderr, "memory_exhausted\n");
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void usage(const char *usage)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Usage: %s\n", usage);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void verror_msg(const char *s, va_list p)
|
|
||||||
{
|
|
||||||
fflush(stdout);
|
|
||||||
fprintf(stderr, "%s: ", applet_name);
|
|
||||||
vfprintf(stderr, s, p);
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void error_msg(const char *s, ...)
|
|
||||||
{
|
|
||||||
va_list p;
|
|
||||||
|
|
||||||
va_start(p, s);
|
|
||||||
verror_msg(s, p);
|
|
||||||
va_end(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void error_msg_and_die(const char *s, ...)
|
|
||||||
{
|
|
||||||
va_list p;
|
|
||||||
|
|
||||||
va_start(p, s);
|
|
||||||
verror_msg(s, p);
|
|
||||||
va_end(p);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vperror_msg(const char *s, va_list p)
|
|
||||||
{
|
|
||||||
fflush(stdout);
|
|
||||||
fprintf(stderr, "%s: ", applet_name);
|
|
||||||
if (s && *s) {
|
|
||||||
vfprintf(stderr, s, p);
|
|
||||||
fputs(": ", stderr);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "%s\n", strerror(errno));
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void perror_msg(const char *s, ...)
|
|
||||||
{
|
|
||||||
va_list p;
|
|
||||||
|
|
||||||
va_start(p, s);
|
|
||||||
vperror_msg(s, p);
|
|
||||||
va_end(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void perror_msg_and_die(const char *s, ...)
|
|
||||||
{
|
|
||||||
va_list p;
|
|
||||||
|
|
||||||
va_start(p, s);
|
|
||||||
vperror_msg(s, p);
|
|
||||||
va_end(p);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *xfopen(const char *path, const char *mode)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
if ((fp = fopen(path, mode)) == NULL)
|
|
||||||
perror_msg_and_die(path);
|
|
||||||
return fp;
|
|
||||||
}
|
|
||||||
#endif /* of busybox.h replacement */
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
REDIRECT_INPUT = 1,
|
REDIRECT_INPUT = 1,
|
||||||
@ -241,7 +156,8 @@ typedef enum {
|
|||||||
RES_UNTIL = 8,
|
RES_UNTIL = 8,
|
||||||
RES_DO = 9,
|
RES_DO = 9,
|
||||||
RES_DONE = 10,
|
RES_DONE = 10,
|
||||||
RES_XXXX = 11
|
RES_XXXX = 11,
|
||||||
|
RES_SNTX = 12
|
||||||
} reserved_style;
|
} reserved_style;
|
||||||
#define FLAG_END (1<<RES_NONE)
|
#define FLAG_END (1<<RES_NONE)
|
||||||
#define FLAG_IF (1<<RES_IF)
|
#define FLAG_IF (1<<RES_IF)
|
||||||
@ -331,7 +247,7 @@ static int fake_mode=0;
|
|||||||
static int interactive=0;
|
static int interactive=0;
|
||||||
static struct close_me *close_me_head = NULL;
|
static struct close_me *close_me_head = NULL;
|
||||||
static char *cwd;
|
static char *cwd;
|
||||||
static struct jobset job_list = { NULL, NULL };
|
/* static struct jobset job_list = { NULL, NULL }; */
|
||||||
static unsigned int last_bg_pid=0;
|
static unsigned int last_bg_pid=0;
|
||||||
static char *PS1;
|
static char *PS1;
|
||||||
static char *PS2 = "> ";
|
static char *PS2 = "> ";
|
||||||
@ -843,6 +759,7 @@ static inline void cmdedit_set_initial_prompt(void)
|
|||||||
|
|
||||||
static inline void setup_prompt_string(int promptmode, char **prompt_str)
|
static inline void setup_prompt_string(int promptmode, char **prompt_str)
|
||||||
{
|
{
|
||||||
|
debug_printf("setup_prompt_string %d ",promptmode);
|
||||||
#ifdef BB_FEATURE_SH_SIMPLE_PROMPT
|
#ifdef BB_FEATURE_SH_SIMPLE_PROMPT
|
||||||
/* Set up the prompt */
|
/* Set up the prompt */
|
||||||
if (promptmode == 1) {
|
if (promptmode == 1) {
|
||||||
@ -857,6 +774,7 @@ static inline void setup_prompt_string(int promptmode, char **prompt_str)
|
|||||||
#else
|
#else
|
||||||
*prompt_str = (promptmode==0)? PS1 : PS2;
|
*prompt_str = (promptmode==0)? PS1 : PS2;
|
||||||
#endif
|
#endif
|
||||||
|
debug_printf("result %s\n",*prompt_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_user_input(struct in_str *i)
|
static void get_user_input(struct in_str *i)
|
||||||
@ -1537,7 +1455,10 @@ int reserved_word(o_string *dest, struct p_context *ctx)
|
|||||||
initialize_context(ctx);
|
initialize_context(ctx);
|
||||||
ctx->stack=new;
|
ctx->stack=new;
|
||||||
} else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
|
} else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
|
||||||
syntax(); /* XXX how do we get out? */
|
syntax();
|
||||||
|
ctx->w = RES_SNTX;
|
||||||
|
b_reset (dest);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
ctx->w=r->code;
|
ctx->w=r->code;
|
||||||
ctx->old_flag = r->flag;
|
ctx->old_flag = r->flag;
|
||||||
@ -1579,7 +1500,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
|
|||||||
}
|
}
|
||||||
if (!child->argv) {
|
if (!child->argv) {
|
||||||
debug_printf("checking %s for reserved-ness\n",dest->data);
|
debug_printf("checking %s for reserved-ness\n",dest->data);
|
||||||
if (reserved_word(dest,ctx)) return 0;
|
if (reserved_word(dest,ctx)) return ctx->w==RES_SNTX;
|
||||||
}
|
}
|
||||||
glob_target = &child->glob_result;
|
glob_target = &child->glob_result;
|
||||||
if (child->argv) flags |= GLOB_APPEND;
|
if (child->argv) flags |= GLOB_APPEND;
|
||||||
@ -1921,11 +1842,16 @@ int parse_stream(o_string *dest, struct p_context *ctx,
|
|||||||
ch,ch,m,dest->quote);
|
ch,ch,m,dest->quote);
|
||||||
if (m==0 || ((m==1 || m==2) && dest->quote)) {
|
if (m==0 || ((m==1 || m==2) && dest->quote)) {
|
||||||
b_addqchr(dest, ch, dest->quote);
|
b_addqchr(dest, ch, dest->quote);
|
||||||
} else if (ch == end_trigger && !dest->quote) {
|
} else if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
|
||||||
debug_printf("leaving parse_stream\n");
|
debug_printf("leaving parse_stream\n");
|
||||||
return 0;
|
return 0;
|
||||||
} else if (m==2 && !dest->quote) { /* IFS */
|
} else if (m==2 && !dest->quote) { /* IFS */
|
||||||
done_word(dest, ctx);
|
done_word(dest, ctx);
|
||||||
|
if (ch=='\n') done_pipe(ctx,PIPE_SEQ);
|
||||||
|
if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
|
||||||
|
debug_printf("leaving parse_stream (stupid duplication)\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#if 0
|
#if 0
|
||||||
if (ch=='\n') {
|
if (ch=='\n') {
|
||||||
/* Yahoo! Time to run with it! */
|
/* Yahoo! Time to run with it! */
|
||||||
|
Loading…
Reference in New Issue
Block a user