mirror of
https://github.com/sheumann/hush.git
synced 2024-12-22 14:30:31 +00:00
hush: take care of several easy FIXMEs. -228 bytes.
This commit is contained in:
parent
831dcc439c
commit
c666f71e3b
180
shell/hush.c
180
shell/hush.c
@ -124,6 +124,7 @@ static const char *indenter(int i)
|
|||||||
return &blanks[sizeof(blanks) - i - 1];
|
return &blanks[sizeof(blanks) - i - 1];
|
||||||
}
|
}
|
||||||
#define debug_printf_clean(...) fprintf(stderr, __VA_ARGS__)
|
#define debug_printf_clean(...) fprintf(stderr, __VA_ARGS__)
|
||||||
|
#define DEBUG_CLEAN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -232,10 +233,10 @@ struct child_prog {
|
|||||||
glob_t glob_result; /* result of parameter globbing */
|
glob_t glob_result; /* result of parameter globbing */
|
||||||
int is_stopped; /* is the program currently running? */
|
int is_stopped; /* is the program currently running? */
|
||||||
struct pipe *family; /* pointer back to the child's parent pipe */
|
struct pipe *family; /* pointer back to the child's parent pipe */
|
||||||
int sp; /* number of SPECIAL_VAR_SYMBOL */
|
//sp counting seems to be broken... so commented out, grep for '//sp:'
|
||||||
|
//sp: int sp; /* number of SPECIAL_VAR_SYMBOL */
|
||||||
int type;
|
int type;
|
||||||
};
|
};
|
||||||
// sp counting seems to be broken...
|
|
||||||
/* argv vector may contain variable references (^Cvar^C, ^C0^C etc)
|
/* argv vector may contain variable references (^Cvar^C, ^C0^C etc)
|
||||||
* and on execution these are substituted with their values.
|
* and on execution these are substituted with their values.
|
||||||
* Substitution can make _several_ words out of one argv[n]!
|
* Substitution can make _several_ words out of one argv[n]!
|
||||||
@ -383,7 +384,6 @@ static int b_check_space(o_string *o, int len);
|
|||||||
static int b_addchr(o_string *o, int ch);
|
static int b_addchr(o_string *o, int ch);
|
||||||
static void b_reset(o_string *o);
|
static void b_reset(o_string *o);
|
||||||
static int b_addqchr(o_string *o, int ch, int quote);
|
static int b_addqchr(o_string *o, int ch, int quote);
|
||||||
//static int b_adduint(o_string *o, unsigned i);
|
|
||||||
/* in_str manipulations: */
|
/* in_str manipulations: */
|
||||||
static int static_get(struct in_str *i);
|
static int static_get(struct in_str *i);
|
||||||
static int static_peek(struct in_str *i);
|
static int static_peek(struct in_str *i);
|
||||||
@ -396,7 +396,10 @@ static void mark_open(int fd);
|
|||||||
static void mark_closed(int fd);
|
static void mark_closed(int fd);
|
||||||
static void close_all(void);
|
static void close_all(void);
|
||||||
/* "run" the final data structures: */
|
/* "run" the final data structures: */
|
||||||
//TODO: remove indent argument from non-debug build!
|
#if !defined(DEBUG_CLEAN)
|
||||||
|
#define free_pipe_list(head, indent) free_pipe_list(head)
|
||||||
|
#define free_pipe(pi, indent) free_pipe(pi)
|
||||||
|
#endif
|
||||||
static int free_pipe_list(struct pipe *head, int indent);
|
static int free_pipe_list(struct pipe *head, int indent);
|
||||||
static int free_pipe(struct pipe *pi, int indent);
|
static int free_pipe(struct pipe *pi, int indent);
|
||||||
/* really run the final data structures: */
|
/* really run the final data structures: */
|
||||||
@ -425,7 +428,6 @@ static int parse_group(o_string *dest, struct p_context *ctx, struct in_str *inp
|
|||||||
static const char *lookup_param(const char *src);
|
static const char *lookup_param(const char *src);
|
||||||
static char *make_string(char **inp);
|
static char *make_string(char **inp);
|
||||||
static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input);
|
static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input);
|
||||||
//static int parse_string(o_string *dest, struct p_context *ctx, const char *src);
|
|
||||||
static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, const char *end_trigger);
|
static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, const char *end_trigger);
|
||||||
/* setup: */
|
/* setup: */
|
||||||
static int parse_stream_outer(struct in_str *inp, int parse_flag);
|
static int parse_stream_outer(struct in_str *inp, int parse_flag);
|
||||||
@ -708,9 +710,8 @@ static int builtin_export(char **argv)
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = strdup(name);
|
name = xstrdup(name);
|
||||||
|
{
|
||||||
if (name) {
|
|
||||||
const char *value = strchr(name, '=');
|
const char *value = strchr(name, '=');
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
@ -721,13 +722,9 @@ static int builtin_export(char **argv)
|
|||||||
if (value) {
|
if (value) {
|
||||||
size_t ln = strlen(name);
|
size_t ln = strlen(name);
|
||||||
|
|
||||||
tmp = realloc(name, ln+strlen(value)+2);
|
tmp = xrealloc(name, ln+strlen(value)+2);
|
||||||
if (tmp == NULL)
|
|
||||||
res = -1;
|
|
||||||
else {
|
|
||||||
sprintf(tmp+ln, "=%s", value);
|
sprintf(tmp+ln, "=%s", value);
|
||||||
name = tmp;
|
name = tmp;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* bash does not return an error when trying to export
|
/* bash does not return an error when trying to export
|
||||||
* an undefined variable. Do likewise. */
|
* an undefined variable. Do likewise. */
|
||||||
@ -967,13 +964,9 @@ static int b_check_space(o_string *o, int len)
|
|||||||
/* It would be easy to drop a more restrictive policy
|
/* It would be easy to drop a more restrictive policy
|
||||||
* in here, such as setting a maximum string length */
|
* in here, such as setting a maximum string length */
|
||||||
if (o->length + len > o->maxlen) {
|
if (o->length + len > o->maxlen) {
|
||||||
char *old_data = o->data;
|
|
||||||
/* assert(data == NULL || o->maxlen != 0); */
|
/* assert(data == NULL || o->maxlen != 0); */
|
||||||
o->maxlen += (2*len > B_CHUNK ? 2*len : B_CHUNK);
|
o->maxlen += (2*len > B_CHUNK ? 2*len : B_CHUNK);
|
||||||
o->data = realloc(o->data, 1 + o->maxlen);
|
o->data = xrealloc(o->data, 1 + o->maxlen);
|
||||||
if (o->data == NULL) {
|
|
||||||
free(old_data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return o->data == NULL;
|
return o->data == NULL;
|
||||||
}
|
}
|
||||||
@ -1019,17 +1012,6 @@ static int b_addqchr(o_string *o, int ch, int quote)
|
|||||||
return b_addchr(o, ch);
|
return b_addchr(o, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
//static int b_adduint(o_string *o, unsigned i)
|
|
||||||
//{
|
|
||||||
// int r;
|
|
||||||
// char buf[sizeof(unsigned)*3 + 1];
|
|
||||||
// char *p = buf;
|
|
||||||
// *(utoa_to_buf(i, buf, sizeof(buf))) = '\0';
|
|
||||||
// /* no escape checking necessary */
|
|
||||||
// do r = b_addchr(o, *p++); while (r == 0 && *p);
|
|
||||||
// return r;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
static int static_get(struct in_str *i)
|
static int static_get(struct in_str *i)
|
||||||
{
|
{
|
||||||
int ch = *i->p++;
|
int ch = *i->p++;
|
||||||
@ -1286,7 +1268,7 @@ static void pseudo_exec_argv(char **argv)
|
|||||||
const struct built_in_command *x;
|
const struct built_in_command *x;
|
||||||
|
|
||||||
for (i = 0; is_assignment(argv[i]); i++) {
|
for (i = 0; is_assignment(argv[i]); i++) {
|
||||||
debug_printf("pid %d environment modification: %s\n",
|
debug_printf_exec("pid %d environment modification: %s\n",
|
||||||
getpid(), argv[i]);
|
getpid(), argv[i]);
|
||||||
// FIXME: vfork case??
|
// FIXME: vfork case??
|
||||||
p = insert_var_value(argv[i]);
|
p = insert_var_value(argv[i]);
|
||||||
@ -1317,23 +1299,27 @@ static void pseudo_exec_argv(char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the command matches any busybox internal commands
|
/* Check if the command matches any busybox applets */
|
||||||
* ("applets") here.
|
|
||||||
* FIXME: This feature is not 100% safe, since
|
|
||||||
* BusyBox is not fully reentrant, so we have no guarantee the things
|
|
||||||
* from the .bss are still zeroed, or that things from .data are still
|
|
||||||
* at their defaults. We could exec ourself from /proc/self/exe, but I
|
|
||||||
* 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... */
|
|
||||||
#if ENABLE_FEATURE_SH_STANDALONE
|
#if ENABLE_FEATURE_SH_STANDALONE
|
||||||
debug_printf("running applet %s\n", argv[0]);
|
if (strchr(argv[0], '/') == NULL) {
|
||||||
// FIXME: check NOEXEC bit, and EXEC if not set!
|
const struct bb_applet *a = find_applet_by_name(argv[0]);
|
||||||
run_applet_and_exit(argv[0], argv);
|
if (a) {
|
||||||
// is it ok that run_applet_and_exit() does exit(), not _exit()?
|
if (a->noexec) {
|
||||||
// NB: IIRC on NOMMU we are after _vfork_, not fork!
|
current_applet = a;
|
||||||
|
debug_printf_exec("running applet '%s'\n", argv[0]);
|
||||||
|
// is it ok that run_current_applet_and_exit() does exit(), not _exit()?
|
||||||
|
run_current_applet_and_exit(argv);
|
||||||
|
}
|
||||||
|
/* re-exec ourselves with the new arguments */
|
||||||
|
debug_printf_exec("re-execing applet '%s'\n", argv[0]);
|
||||||
|
execvp(CONFIG_BUSYBOX_EXEC_PATH, argv);
|
||||||
|
/* If they called chroot or otherwise made the binary no longer
|
||||||
|
* executable, fall through */
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
debug_printf("exec of %s\n", argv[0]);
|
|
||||||
|
debug_printf_exec("execing '%s'\n", argv[0]);
|
||||||
execvp(argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
bb_perror_msg("cannot exec '%s'", argv[0]);
|
bb_perror_msg("cannot exec '%s'", argv[0]);
|
||||||
_exit(1);
|
_exit(1);
|
||||||
@ -1426,16 +1412,7 @@ static void insert_bg_job(struct pipe *pi)
|
|||||||
// TODO: do we really need to have so many fields which are just dead weight
|
// TODO: do we really need to have so many fields which are just dead weight
|
||||||
// at execution stage?
|
// at execution stage?
|
||||||
thejob->progs[i].pid = pi->progs[i].pid;
|
thejob->progs[i].pid = pi->progs[i].pid;
|
||||||
//rest:
|
/* all other fields are not used and stay zero */
|
||||||
//char **argv; /* program name and arguments */
|
|
||||||
//struct pipe *group; /* if non-NULL, first in group or subshell */
|
|
||||||
//int subshell; /* flag, non-zero if group must be forked */
|
|
||||||
//struct redir_struct *redirects; /* I/O redirections */
|
|
||||||
//glob_t glob_result; /* result of parameter globbing */
|
|
||||||
//int is_stopped; /* is the program currently running? */
|
|
||||||
//struct pipe *family; /* pointer back to the child's parent pipe */
|
|
||||||
//int sp; /* number of SPECIAL_VAR_SYMBOL */
|
|
||||||
//int type;
|
|
||||||
}
|
}
|
||||||
thejob->next = NULL;
|
thejob->next = NULL;
|
||||||
thejob->cmdtext = xstrdup(get_cmdtext(pi));
|
thejob->cmdtext = xstrdup(get_cmdtext(pi));
|
||||||
@ -1594,10 +1571,6 @@ static int checkjobs(struct pipe* fg_pipe)
|
|||||||
|
|
||||||
if (childpid && errno != ECHILD)
|
if (childpid && errno != ECHILD)
|
||||||
bb_perror_msg("waitpid");
|
bb_perror_msg("waitpid");
|
||||||
|
|
||||||
/* move the shell to the foreground */
|
|
||||||
//if (interactive_fd && tcsetpgrp(interactive_fd, getpgid(0)))
|
|
||||||
// bb_perror_msg("tcsetpgrp-2");
|
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1669,7 +1642,7 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (single_fg && child->argv != NULL) {
|
if (single_fg && child->argv != NULL) {
|
||||||
char **argv_expanded, **free_me;
|
char **argv_expanded;
|
||||||
char **argv = child->argv;
|
char **argv = child->argv;
|
||||||
|
|
||||||
for (i = 0; is_assignment(argv[i]); i++)
|
for (i = 0; is_assignment(argv[i]); i++)
|
||||||
@ -1704,13 +1677,12 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
for (i = 0; is_assignment(argv[i]); i++) {
|
for (i = 0; is_assignment(argv[i]); i++) {
|
||||||
p = insert_var_value(argv[i]);
|
p = insert_var_value(argv[i]);
|
||||||
if (p != argv[i]) {
|
if (p != argv[i]) {
|
||||||
child->sp--;
|
//sp: child->sp--;
|
||||||
putenv(p);
|
putenv(p);
|
||||||
} else {
|
} else {
|
||||||
putenv(xstrdup(p));
|
putenv(xstrdup(p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_me = NULL;
|
|
||||||
for (x = bltins; x->cmd; x++) {
|
for (x = bltins; x->cmd; x++) {
|
||||||
if (strcmp(argv[i], x->cmd) == 0) {
|
if (strcmp(argv[i], x->cmd) == 0) {
|
||||||
if (x->function == builtin_exec && argv[i+1] == NULL) {
|
if (x->function == builtin_exec && argv[i+1] == NULL) {
|
||||||
@ -1723,14 +1695,12 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
* This is perfect for work that comes after exec().
|
* This is perfect for work that comes after exec().
|
||||||
* Is it really safe for inline use? Experimentally,
|
* Is it really safe for inline use? Experimentally,
|
||||||
* things seem to work with glibc. */
|
* things seem to work with glibc. */
|
||||||
// TODO: fflush(NULL)?
|
|
||||||
setup_redirects(child, squirrel);
|
setup_redirects(child, squirrel);
|
||||||
debug_printf_exec(": builtin '%s' '%s'...\n", x->cmd, argv[i+1]);
|
debug_printf_exec(": builtin '%s' '%s'...\n", x->cmd, argv[i+1]);
|
||||||
argv_expanded = argv + i;
|
//sp: if (child->sp) /* btw we can do it unconditionally... */
|
||||||
if (child->sp) /* btw we can do it unconditionally... */
|
argv_expanded = do_variable_expansion(argv + i);
|
||||||
free_me = argv_expanded = do_variable_expansion(argv + i);
|
|
||||||
rcode = x->function(argv_expanded);
|
rcode = x->function(argv_expanded);
|
||||||
free(free_me);
|
free(argv_expanded);
|
||||||
restore_redirects(squirrel);
|
restore_redirects(squirrel);
|
||||||
debug_printf_exec("run_pipe_real return %d\n", rcode);
|
debug_printf_exec("run_pipe_real return %d\n", rcode);
|
||||||
return rcode;
|
return rcode;
|
||||||
@ -1743,11 +1713,11 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
setup_redirects(child, squirrel);
|
setup_redirects(child, squirrel);
|
||||||
save_nofork_data(&nofork_save);
|
save_nofork_data(&nofork_save);
|
||||||
argv_expanded = argv + i;
|
argv_expanded = argv + i;
|
||||||
if (child->sp)
|
//sp: if (child->sp)
|
||||||
free_me = argv_expanded = do_variable_expansion(argv + i);
|
argv_expanded = do_variable_expansion(argv + i);
|
||||||
debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]);
|
debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]);
|
||||||
rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded);
|
rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded);
|
||||||
free(free_me);
|
free(argv_expanded);
|
||||||
restore_redirects(squirrel);
|
restore_redirects(squirrel);
|
||||||
debug_printf_exec("run_pipe_real return %d\n", rcode);
|
debug_printf_exec("run_pipe_real return %d\n", rcode);
|
||||||
return rcode;
|
return rcode;
|
||||||
@ -1802,7 +1772,7 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// in non-interactive case fatal sigs are already SIG_DFL
|
/* in non-interactive case fatal sigs are already SIG_DFL */
|
||||||
close_all();
|
close_all();
|
||||||
if (nextin != 0) {
|
if (nextin != 0) {
|
||||||
dup2(nextin, 0);
|
dup2(nextin, 0);
|
||||||
@ -1833,13 +1803,6 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
if (pi->pgrp < 0)
|
if (pi->pgrp < 0)
|
||||||
pi->pgrp = child->pid;
|
pi->pgrp = child->pid;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Don't check for errors. The child may be dead already,
|
|
||||||
* in which case setpgid returns error code EACCES. */
|
|
||||||
//why we do it at all?? child does it itself
|
|
||||||
//if (interactive_fd)
|
|
||||||
// setpgid(child->pid, pi->pgrp);
|
|
||||||
|
|
||||||
if (nextin != 0)
|
if (nextin != 0)
|
||||||
close(nextin);
|
close(nextin);
|
||||||
if (nextout != 1)
|
if (nextout != 1)
|
||||||
@ -1911,8 +1874,8 @@ static void debug_print_tree(struct pipe *pi, int lvl)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NB: called by pseudo_exec, and therefore must not modify any
|
/* NB: called by pseudo_exec, and therefore must not modify any
|
||||||
// global data until exec/_exit (we can be a child after vfork!)
|
* global data until exec/_exit (we can be a child after vfork!) */
|
||||||
static int run_list_real(struct pipe *pi)
|
static int run_list_real(struct pipe *pi)
|
||||||
{
|
{
|
||||||
#if ENABLE_HUSH_JOB
|
#if ENABLE_HUSH_JOB
|
||||||
@ -2224,9 +2187,7 @@ static int globhack(const char *src, int flags, glob_t *pglob)
|
|||||||
if (*s == '\\') s++;
|
if (*s == '\\') s++;
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
dest = malloc(cnt);
|
dest = xmalloc(cnt);
|
||||||
if (!dest)
|
|
||||||
return GLOB_NOSPACE;
|
|
||||||
if (!(flags & GLOB_APPEND)) {
|
if (!(flags & GLOB_APPEND)) {
|
||||||
pglob->gl_pathv = NULL;
|
pglob->gl_pathv = NULL;
|
||||||
pglob->gl_pathc = 0;
|
pglob->gl_pathc = 0;
|
||||||
@ -2234,9 +2195,7 @@ static int globhack(const char *src, int flags, glob_t *pglob)
|
|||||||
pglob->gl_offs = 0;
|
pglob->gl_offs = 0;
|
||||||
}
|
}
|
||||||
pathc = ++pglob->gl_pathc;
|
pathc = ++pglob->gl_pathc;
|
||||||
pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1) * sizeof(*pglob->gl_pathv));
|
pglob->gl_pathv = xrealloc(pglob->gl_pathv, (pathc+1) * sizeof(*pglob->gl_pathv));
|
||||||
if (pglob->gl_pathv == NULL)
|
|
||||||
return GLOB_NOSPACE;
|
|
||||||
pglob->gl_pathv[pathc-1] = dest;
|
pglob->gl_pathv[pathc-1] = dest;
|
||||||
pglob->gl_pathv[pathc] = NULL;
|
pglob->gl_pathv[pathc] = NULL;
|
||||||
for (s = src; s && *s; s++, dest++) {
|
for (s = src; s && *s; s++, dest++) {
|
||||||
@ -2312,8 +2271,8 @@ static int count_ifs(const char *str)
|
|||||||
while (1) {
|
while (1) {
|
||||||
str += strcspn(str, ifs);
|
str += strcspn(str, ifs);
|
||||||
if (!*str) break;
|
if (!*str) break;
|
||||||
str++; // str += strspn(str, ifs); ?
|
str++; /* str += strspn(str, ifs); */
|
||||||
cnt++; // cnt += strspn(str, ifs); ?
|
cnt++; /* cnt += strspn(str, ifs); - but this code is larger */
|
||||||
}
|
}
|
||||||
debug_printf_expand(" return %d\n", cnt);
|
debug_printf_expand(" return %d\n", cnt);
|
||||||
return cnt;
|
return cnt;
|
||||||
@ -2704,32 +2663,24 @@ static int set_local_var(const char *s, int flg_export)
|
|||||||
if (flg_export > 0 || cur->flg_export > 1)
|
if (flg_export > 0 || cur->flg_export > 1)
|
||||||
cur->flg_export = 1;
|
cur->flg_export = 1;
|
||||||
free((char*)cur->value);
|
free((char*)cur->value);
|
||||||
cur->value = strdup(value);
|
cur->value = xstrdup(value);
|
||||||
}
|
}
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: need simpler/generic rollback on malloc failure - see ash
|
cur = xzalloc(sizeof(*cur));
|
||||||
cur = malloc(sizeof(*cur));
|
cur->name = xstrdup(name);
|
||||||
if (!cur) {
|
cur->value = xstrdup(value);
|
||||||
result = -1;
|
/*cur->next = 0;*/
|
||||||
} else {
|
|
||||||
cur->name = strdup(name);
|
|
||||||
if (!cur->name) {
|
|
||||||
free(cur);
|
|
||||||
result = -1;
|
|
||||||
} else {
|
|
||||||
struct variables *bottom = top_vars;
|
|
||||||
cur->value = strdup(value);
|
|
||||||
cur->next = 0;
|
|
||||||
cur->flg_export = flg_export;
|
cur->flg_export = flg_export;
|
||||||
cur->flg_read_only = 0;
|
/*cur->flg_read_only = 0;*/
|
||||||
|
{
|
||||||
|
struct variables *bottom = top_vars;
|
||||||
while (bottom->next)
|
while (bottom->next)
|
||||||
bottom = bottom->next;
|
bottom = bottom->next;
|
||||||
bottom->next = cur;
|
bottom->next = cur;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
skip:
|
skip:
|
||||||
if (result == 0 && cur->flg_export == 1) {
|
if (result == 0 && cur->flg_export == 1) {
|
||||||
*(value-1) = '=';
|
*(value-1) = '=';
|
||||||
@ -3019,7 +2970,7 @@ static int done_command(struct p_context *ctx)
|
|||||||
/*child->group = NULL;*/
|
/*child->group = NULL;*/
|
||||||
/*child->glob_result.gl_pathv = NULL;*/
|
/*child->glob_result.gl_pathv = NULL;*/
|
||||||
child->family = pi;
|
child->family = pi;
|
||||||
/*child->sp = 0;*/
|
//sp: /*child->sp = 0;*/
|
||||||
child->type = ctx->parse_type;
|
child->type = ctx->parse_type;
|
||||||
|
|
||||||
ctx->child = child;
|
ctx->child = child;
|
||||||
@ -3268,7 +3219,7 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
|
|||||||
debug_printf_parse("handle_dollar entered: ch='%c'\n", ch);
|
debug_printf_parse("handle_dollar entered: ch='%c'\n", ch);
|
||||||
if (isalpha(ch)) {
|
if (isalpha(ch)) {
|
||||||
b_addchr(dest, SPECIAL_VAR_SYMBOL);
|
b_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
ctx->child->sp++;
|
//sp: ctx->child->sp++;
|
||||||
while (1) {
|
while (1) {
|
||||||
debug_printf_parse(": '%c'\n", ch);
|
debug_printf_parse(": '%c'\n", ch);
|
||||||
b_getch(input);
|
b_getch(input);
|
||||||
@ -3282,7 +3233,7 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
|
|||||||
} else if (isdigit(ch)) {
|
} else if (isdigit(ch)) {
|
||||||
make_one_char_var:
|
make_one_char_var:
|
||||||
b_addchr(dest, SPECIAL_VAR_SYMBOL);
|
b_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
ctx->child->sp++;
|
//sp: ctx->child->sp++;
|
||||||
debug_printf_parse(": '%c'\n", ch);
|
debug_printf_parse(": '%c'\n", ch);
|
||||||
b_getch(input);
|
b_getch(input);
|
||||||
b_addchr(dest, ch | quote_mask);
|
b_addchr(dest, ch | quote_mask);
|
||||||
@ -3297,7 +3248,7 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
|
|||||||
goto make_one_char_var;
|
goto make_one_char_var;
|
||||||
case '{':
|
case '{':
|
||||||
b_addchr(dest, SPECIAL_VAR_SYMBOL);
|
b_addchr(dest, SPECIAL_VAR_SYMBOL);
|
||||||
ctx->child->sp++;
|
//sp: ctx->child->sp++;
|
||||||
b_getch(input);
|
b_getch(input);
|
||||||
/* XXX maybe someone will try to escape the '}' */
|
/* XXX maybe someone will try to escape the '}' */
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -3332,13 +3283,6 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static int parse_string(o_string *dest, struct p_context *ctx, const char *src)
|
|
||||||
//{
|
|
||||||
// struct in_str foo;
|
|
||||||
// setup_string_in_str(&foo, src);
|
|
||||||
// return parse_stream(dest, ctx, &foo, NULL);
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
/* return code is 0 for normal exit, 1 for syntax error */
|
/* return code is 0 for normal exit, 1 for syntax error */
|
||||||
static int parse_stream(o_string *dest, struct p_context *ctx,
|
static int parse_stream(o_string *dest, struct p_context *ctx,
|
||||||
struct in_str *input, const char *end_trigger)
|
struct in_str *input, const char *end_trigger)
|
||||||
@ -3711,9 +3655,9 @@ int hush_main(int argc, char **argv)
|
|||||||
opt = parse_string_outer(optarg, FLAG_PARSE_SEMICOLON);
|
opt = parse_string_outer(optarg, FLAG_PARSE_SEMICOLON);
|
||||||
goto final_return;
|
goto final_return;
|
||||||
case 'i':
|
case 'i':
|
||||||
// Well, we cannot just declare interactiveness,
|
/* Well, we cannot just declare interactiveness,
|
||||||
// we have to have some stuff (ctty, etc)
|
* we have to have some stuff (ctty, etc) */
|
||||||
/*interactive_fd++;*/
|
/* interactive_fd++; */
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
fake_mode++;
|
fake_mode++;
|
||||||
|
Loading…
Reference in New Issue
Block a user