Updates from both Vladimir and Larry
This commit is contained in:
parent
1eb4acfc23
commit
94ac244dea
101
hush.c
101
hush.c
@ -256,10 +256,8 @@ static const char *cwd;
|
|||||||
static struct jobset *job_list;
|
static struct jobset *job_list;
|
||||||
static unsigned int last_bg_pid;
|
static unsigned int last_bg_pid;
|
||||||
static char *PS1;
|
static char *PS1;
|
||||||
static char PS2[] = "> ";
|
static char *PS2;
|
||||||
|
|
||||||
struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
|
struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
|
||||||
|
|
||||||
struct variables *top_vars = &shell_ver;
|
struct variables *top_vars = &shell_ver;
|
||||||
|
|
||||||
#define B_CHUNK (100)
|
#define B_CHUNK (100)
|
||||||
@ -523,8 +521,8 @@ static int builtin_export(struct child_prog *child)
|
|||||||
name = tmp;
|
name = tmp;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* bash not put error and set error code
|
/* bash does not return an error when trying to export
|
||||||
if exporting not defined variable */
|
* an undefined variable. Do likewise. */
|
||||||
res = 1;
|
res = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -641,7 +639,7 @@ static int builtin_read(struct child_prog *child)
|
|||||||
char string[BUFSIZ];
|
char string[BUFSIZ];
|
||||||
char *var = 0;
|
char *var = 0;
|
||||||
|
|
||||||
string[0] = 0; /* for correct work if stdin have "only EOF" */
|
string[0] = 0; /* In case stdin has only EOF */
|
||||||
/* read string */
|
/* read string */
|
||||||
fgets(string, sizeof(string), stdin);
|
fgets(string, sizeof(string), stdin);
|
||||||
chomp(string);
|
chomp(string);
|
||||||
@ -653,7 +651,7 @@ static int builtin_read(struct child_prog *child)
|
|||||||
res = -1;
|
res = -1;
|
||||||
if (res)
|
if (res)
|
||||||
fprintf(stderr, "read: %m\n");
|
fprintf(stderr, "read: %m\n");
|
||||||
free(var); /* not move up - saved errno */
|
free(var); /* So not move up to avoid breaking errno */
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
do res=getchar(); while(res!='\n' && res!=EOF);
|
do res=getchar(); while(res!='\n' && res!=EOF);
|
||||||
@ -1061,6 +1059,9 @@ static int pipe_wait(struct pipe *pi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* never returns */
|
/* never returns */
|
||||||
|
/* XXX no exit() here. If you don't exec, use _exit instead.
|
||||||
|
* The at_exit handlers apparently confuse the calling process,
|
||||||
|
* in particular stdin handling. Not sure why? */
|
||||||
static void pseudo_exec(struct child_prog *child)
|
static void pseudo_exec(struct child_prog *child)
|
||||||
{
|
{
|
||||||
int i, rcode;
|
int i, rcode;
|
||||||
@ -1076,7 +1077,9 @@ static void pseudo_exec(struct child_prog *child)
|
|||||||
/* If a variable is assigned in a forest, and nobody listens,
|
/* If a variable is assigned in a forest, and nobody listens,
|
||||||
* was it ever really set?
|
* was it ever really set?
|
||||||
*/
|
*/
|
||||||
if (child->argv[0] == NULL) exit(EXIT_SUCCESS);
|
if (child->argv[0] == NULL) {
|
||||||
|
_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the command matches any of the builtins.
|
* Check if the command matches any of the builtins.
|
||||||
@ -1087,7 +1090,7 @@ static void pseudo_exec(struct child_prog *child)
|
|||||||
for (x = bltins; x->cmd; x++) {
|
for (x = bltins; x->cmd; x++) {
|
||||||
if (strcmp(child->argv[0], x->cmd) == 0 ) {
|
if (strcmp(child->argv[0], x->cmd) == 0 ) {
|
||||||
debug_printf("builtin exec %s\n", child->argv[0]);
|
debug_printf("builtin exec %s\n", child->argv[0]);
|
||||||
exit(x->function(child));
|
_exit(x->function(child));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,18 +1131,18 @@ static void pseudo_exec(struct child_prog *child)
|
|||||||
debug_printf("exec of %s\n",child->argv[0]);
|
debug_printf("exec of %s\n",child->argv[0]);
|
||||||
execvp(child->argv[0],child->argv);
|
execvp(child->argv[0],child->argv);
|
||||||
perror_msg("couldn't exec: %s",child->argv[0]);
|
perror_msg("couldn't exec: %s",child->argv[0]);
|
||||||
exit(1);
|
_exit(1);
|
||||||
} else if (child->group) {
|
} else if (child->group) {
|
||||||
debug_printf("runtime nesting to group\n");
|
debug_printf("runtime nesting to group\n");
|
||||||
interactive=0; /* crucial!!!! */
|
interactive=0; /* crucial!!!! */
|
||||||
rcode = run_list_real(child->group);
|
rcode = run_list_real(child->group);
|
||||||
/* OK to leak memory by not calling run_list_test,
|
/* OK to leak memory by not calling run_list_test,
|
||||||
* since this process is about to exit */
|
* since this process is about to exit */
|
||||||
exit(rcode);
|
_exit(rcode);
|
||||||
} else {
|
} else {
|
||||||
/* Can happen. See what bash does with ">foo" by itself. */
|
/* Can happen. See what bash does with ">foo" by itself. */
|
||||||
debug_printf("trying to pseudo_exec null command\n");
|
debug_printf("trying to pseudo_exec null command\n");
|
||||||
exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1713,18 +1716,24 @@ static int set_local_var(const char *s, int flg_export)
|
|||||||
} else {
|
} else {
|
||||||
*value++ = 0;
|
*value++ = 0;
|
||||||
|
|
||||||
for(cur = top_vars; cur; cur = cur->next)
|
for(cur = top_vars; cur; cur = cur->next) {
|
||||||
if(strcmp(cur->name, name)==0)
|
if(strcmp(cur->name, name)==0)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(cur) {
|
if(cur) {
|
||||||
if(strcmp(cur->value, value)==0) {
|
if(strcmp(cur->value, value)==0) {
|
||||||
result = cur->flg_export == flg_export;
|
if(flg_export>0 && cur->flg_export==0)
|
||||||
|
cur->flg_export=flg_export;
|
||||||
|
else
|
||||||
|
result++;
|
||||||
} else {
|
} else {
|
||||||
if(cur->flg_read_only) {
|
if(cur->flg_read_only) {
|
||||||
result = -1;
|
result = -1;
|
||||||
error_msg("%s: readonly variable", name);
|
error_msg("%s: readonly variable", name);
|
||||||
} else {
|
} else {
|
||||||
|
if(flg_export>0 || cur->flg_export>1)
|
||||||
|
cur->flg_export=1;
|
||||||
free(cur->value);
|
free(cur->value);
|
||||||
cur->value = newval;
|
cur->value = newval;
|
||||||
newval = 0; /* protect free */
|
newval = 0; /* protect free */
|
||||||
@ -1741,7 +1750,6 @@ static int set_local_var(const char *s, int flg_export)
|
|||||||
result = -1;
|
result = -1;
|
||||||
} else {
|
} else {
|
||||||
struct variables *bottom = top_vars;
|
struct variables *bottom = top_vars;
|
||||||
|
|
||||||
cur->value = newval;
|
cur->value = newval;
|
||||||
newval = 0; /* protect free */
|
newval = 0; /* protect free */
|
||||||
cur->next = 0;
|
cur->next = 0;
|
||||||
@ -1754,7 +1762,7 @@ static int set_local_var(const char *s, int flg_export)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((result==0 && flg_export==1) || (result>0 && cur->flg_export>0)) {
|
if(result==0 && cur->flg_export==1) {
|
||||||
*(value-1) = '=';
|
*(value-1) = '=';
|
||||||
result = putenv(name);
|
result = putenv(name);
|
||||||
} else {
|
} else {
|
||||||
@ -1771,14 +1779,16 @@ static void unset_local_var(const char *name)
|
|||||||
struct variables *cur;
|
struct variables *cur;
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
for (cur = top_vars; cur; cur=cur->next)
|
for (cur = top_vars; cur; cur=cur->next) {
|
||||||
if(strcmp(cur->name, name)==0)
|
if(strcmp(cur->name, name)==0)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
if(cur!=0) {
|
if(cur!=0) {
|
||||||
struct variables *next = top_vars;
|
struct variables *next = top_vars;
|
||||||
if(cur==next)
|
if(cur->flg_read_only) {
|
||||||
|
error_msg("%s: readonly variable", name);
|
||||||
return;
|
return;
|
||||||
else {
|
} else {
|
||||||
if(cur->flg_export)
|
if(cur->flg_export)
|
||||||
unsetenv(cur->name);
|
unsetenv(cur->name);
|
||||||
free(cur->name);
|
free(cur->name);
|
||||||
@ -2103,9 +2113,9 @@ FILE *generate_stream_from_list(struct pipe *head)
|
|||||||
#if 0
|
#if 0
|
||||||
#define SURROGATE "surrogate response"
|
#define SURROGATE "surrogate response"
|
||||||
write(1,SURROGATE,sizeof(SURROGATE));
|
write(1,SURROGATE,sizeof(SURROGATE));
|
||||||
exit(run_list(head));
|
_exit(run_list(head));
|
||||||
#else
|
#else
|
||||||
exit(run_list_real(head)); /* leaks memory */
|
_exit(run_list_real(head)); /* leaks memory */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
debug_printf("forked child %d\n",pid);
|
debug_printf("forked child %d\n",pid);
|
||||||
@ -2531,19 +2541,44 @@ int shell_main(int argc, char **argv)
|
|||||||
struct jobset joblist_end = { NULL, NULL };
|
struct jobset joblist_end = { NULL, NULL };
|
||||||
char **e = environ;
|
char **e = environ;
|
||||||
|
|
||||||
/* initialize globals */
|
/* FIXME */
|
||||||
if (e) {
|
fprintf(stderr, "sizeof(map)=%d\n", sizeof(map));
|
||||||
for (; *e; e++)
|
|
||||||
set_local_var(*e, 2); /* without call putenv() */
|
|
||||||
}
|
|
||||||
job_list = &joblist_end;
|
|
||||||
|
|
||||||
last_return_code=EXIT_SUCCESS;
|
|
||||||
|
|
||||||
/* XXX what should these be while sourcing /etc/profile? */
|
/* XXX what should these be while sourcing /etc/profile? */
|
||||||
global_argc = argc;
|
global_argc = argc;
|
||||||
global_argv = argv;
|
global_argv = argv;
|
||||||
|
|
||||||
|
/* (re?) initialize globals. Sometimes shell_main() ends up calling
|
||||||
|
* shell_main(), therefore we cannot rely on the BSS to zero out this
|
||||||
|
* stuff. Reset these to 0 every time. */
|
||||||
|
ifs = NULL;
|
||||||
|
memset(map,0,sizeof(map));
|
||||||
|
fake_mode = 0;
|
||||||
|
interactive = 0;
|
||||||
|
close_me_head = NULL;
|
||||||
|
last_bg_pid = 0;
|
||||||
|
|
||||||
|
/* Initialize some more globals to non-zero values */
|
||||||
|
set_cwd();
|
||||||
|
job_list = &joblist_end;
|
||||||
|
#ifdef BB_FEATURE_COMMAND_EDITING
|
||||||
|
cmdedit_set_initial_prompt();
|
||||||
|
#else
|
||||||
|
PS1 = NULL;
|
||||||
|
#endif
|
||||||
|
PS2 = "> ";
|
||||||
|
|
||||||
|
/* initialize our shell local variables with the values
|
||||||
|
* currently living in the environment */
|
||||||
|
if (e) {
|
||||||
|
for (; *e; e++)
|
||||||
|
set_local_var(*e, 2); /* without call putenv() */
|
||||||
|
}
|
||||||
|
|
||||||
|
last_return_code=EXIT_SUCCESS;
|
||||||
|
|
||||||
|
|
||||||
/* If we get started under a job aware app (like bash
|
/* If we get started under a job aware app (like bash
|
||||||
* for example), make sure we are now in charge so we
|
* for example), make sure we are now in charge so we
|
||||||
* don't fight over who gets the foreground */
|
* don't fight over who gets the foreground */
|
||||||
@ -2563,16 +2598,6 @@ int shell_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
input=stdin;
|
input=stdin;
|
||||||
|
|
||||||
/* initialize the cwd -- this is never freed...*/
|
|
||||||
cwd = xgetcwd(0);
|
|
||||||
if (!cwd)
|
|
||||||
cwd = unknown;
|
|
||||||
#ifdef BB_FEATURE_COMMAND_EDITING
|
|
||||||
cmdedit_set_initial_prompt();
|
|
||||||
#else
|
|
||||||
PS1 = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "c:xif")) > 0) {
|
while ((opt = getopt(argc, argv, "c:xif")) > 0) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'c':
|
case 'c':
|
||||||
|
101
shell/hush.c
101
shell/hush.c
@ -256,10 +256,8 @@ static const char *cwd;
|
|||||||
static struct jobset *job_list;
|
static struct jobset *job_list;
|
||||||
static unsigned int last_bg_pid;
|
static unsigned int last_bg_pid;
|
||||||
static char *PS1;
|
static char *PS1;
|
||||||
static char PS2[] = "> ";
|
static char *PS2;
|
||||||
|
|
||||||
struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
|
struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
|
||||||
|
|
||||||
struct variables *top_vars = &shell_ver;
|
struct variables *top_vars = &shell_ver;
|
||||||
|
|
||||||
#define B_CHUNK (100)
|
#define B_CHUNK (100)
|
||||||
@ -523,8 +521,8 @@ static int builtin_export(struct child_prog *child)
|
|||||||
name = tmp;
|
name = tmp;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* bash not put error and set error code
|
/* bash does not return an error when trying to export
|
||||||
if exporting not defined variable */
|
* an undefined variable. Do likewise. */
|
||||||
res = 1;
|
res = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -641,7 +639,7 @@ static int builtin_read(struct child_prog *child)
|
|||||||
char string[BUFSIZ];
|
char string[BUFSIZ];
|
||||||
char *var = 0;
|
char *var = 0;
|
||||||
|
|
||||||
string[0] = 0; /* for correct work if stdin have "only EOF" */
|
string[0] = 0; /* In case stdin has only EOF */
|
||||||
/* read string */
|
/* read string */
|
||||||
fgets(string, sizeof(string), stdin);
|
fgets(string, sizeof(string), stdin);
|
||||||
chomp(string);
|
chomp(string);
|
||||||
@ -653,7 +651,7 @@ static int builtin_read(struct child_prog *child)
|
|||||||
res = -1;
|
res = -1;
|
||||||
if (res)
|
if (res)
|
||||||
fprintf(stderr, "read: %m\n");
|
fprintf(stderr, "read: %m\n");
|
||||||
free(var); /* not move up - saved errno */
|
free(var); /* So not move up to avoid breaking errno */
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
do res=getchar(); while(res!='\n' && res!=EOF);
|
do res=getchar(); while(res!='\n' && res!=EOF);
|
||||||
@ -1061,6 +1059,9 @@ static int pipe_wait(struct pipe *pi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* never returns */
|
/* never returns */
|
||||||
|
/* XXX no exit() here. If you don't exec, use _exit instead.
|
||||||
|
* The at_exit handlers apparently confuse the calling process,
|
||||||
|
* in particular stdin handling. Not sure why? */
|
||||||
static void pseudo_exec(struct child_prog *child)
|
static void pseudo_exec(struct child_prog *child)
|
||||||
{
|
{
|
||||||
int i, rcode;
|
int i, rcode;
|
||||||
@ -1076,7 +1077,9 @@ static void pseudo_exec(struct child_prog *child)
|
|||||||
/* If a variable is assigned in a forest, and nobody listens,
|
/* If a variable is assigned in a forest, and nobody listens,
|
||||||
* was it ever really set?
|
* was it ever really set?
|
||||||
*/
|
*/
|
||||||
if (child->argv[0] == NULL) exit(EXIT_SUCCESS);
|
if (child->argv[0] == NULL) {
|
||||||
|
_exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the command matches any of the builtins.
|
* Check if the command matches any of the builtins.
|
||||||
@ -1087,7 +1090,7 @@ static void pseudo_exec(struct child_prog *child)
|
|||||||
for (x = bltins; x->cmd; x++) {
|
for (x = bltins; x->cmd; x++) {
|
||||||
if (strcmp(child->argv[0], x->cmd) == 0 ) {
|
if (strcmp(child->argv[0], x->cmd) == 0 ) {
|
||||||
debug_printf("builtin exec %s\n", child->argv[0]);
|
debug_printf("builtin exec %s\n", child->argv[0]);
|
||||||
exit(x->function(child));
|
_exit(x->function(child));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,18 +1131,18 @@ static void pseudo_exec(struct child_prog *child)
|
|||||||
debug_printf("exec of %s\n",child->argv[0]);
|
debug_printf("exec of %s\n",child->argv[0]);
|
||||||
execvp(child->argv[0],child->argv);
|
execvp(child->argv[0],child->argv);
|
||||||
perror_msg("couldn't exec: %s",child->argv[0]);
|
perror_msg("couldn't exec: %s",child->argv[0]);
|
||||||
exit(1);
|
_exit(1);
|
||||||
} else if (child->group) {
|
} else if (child->group) {
|
||||||
debug_printf("runtime nesting to group\n");
|
debug_printf("runtime nesting to group\n");
|
||||||
interactive=0; /* crucial!!!! */
|
interactive=0; /* crucial!!!! */
|
||||||
rcode = run_list_real(child->group);
|
rcode = run_list_real(child->group);
|
||||||
/* OK to leak memory by not calling run_list_test,
|
/* OK to leak memory by not calling run_list_test,
|
||||||
* since this process is about to exit */
|
* since this process is about to exit */
|
||||||
exit(rcode);
|
_exit(rcode);
|
||||||
} else {
|
} else {
|
||||||
/* Can happen. See what bash does with ">foo" by itself. */
|
/* Can happen. See what bash does with ">foo" by itself. */
|
||||||
debug_printf("trying to pseudo_exec null command\n");
|
debug_printf("trying to pseudo_exec null command\n");
|
||||||
exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1713,18 +1716,24 @@ static int set_local_var(const char *s, int flg_export)
|
|||||||
} else {
|
} else {
|
||||||
*value++ = 0;
|
*value++ = 0;
|
||||||
|
|
||||||
for(cur = top_vars; cur; cur = cur->next)
|
for(cur = top_vars; cur; cur = cur->next) {
|
||||||
if(strcmp(cur->name, name)==0)
|
if(strcmp(cur->name, name)==0)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(cur) {
|
if(cur) {
|
||||||
if(strcmp(cur->value, value)==0) {
|
if(strcmp(cur->value, value)==0) {
|
||||||
result = cur->flg_export == flg_export;
|
if(flg_export>0 && cur->flg_export==0)
|
||||||
|
cur->flg_export=flg_export;
|
||||||
|
else
|
||||||
|
result++;
|
||||||
} else {
|
} else {
|
||||||
if(cur->flg_read_only) {
|
if(cur->flg_read_only) {
|
||||||
result = -1;
|
result = -1;
|
||||||
error_msg("%s: readonly variable", name);
|
error_msg("%s: readonly variable", name);
|
||||||
} else {
|
} else {
|
||||||
|
if(flg_export>0 || cur->flg_export>1)
|
||||||
|
cur->flg_export=1;
|
||||||
free(cur->value);
|
free(cur->value);
|
||||||
cur->value = newval;
|
cur->value = newval;
|
||||||
newval = 0; /* protect free */
|
newval = 0; /* protect free */
|
||||||
@ -1741,7 +1750,6 @@ static int set_local_var(const char *s, int flg_export)
|
|||||||
result = -1;
|
result = -1;
|
||||||
} else {
|
} else {
|
||||||
struct variables *bottom = top_vars;
|
struct variables *bottom = top_vars;
|
||||||
|
|
||||||
cur->value = newval;
|
cur->value = newval;
|
||||||
newval = 0; /* protect free */
|
newval = 0; /* protect free */
|
||||||
cur->next = 0;
|
cur->next = 0;
|
||||||
@ -1754,7 +1762,7 @@ static int set_local_var(const char *s, int flg_export)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((result==0 && flg_export==1) || (result>0 && cur->flg_export>0)) {
|
if(result==0 && cur->flg_export==1) {
|
||||||
*(value-1) = '=';
|
*(value-1) = '=';
|
||||||
result = putenv(name);
|
result = putenv(name);
|
||||||
} else {
|
} else {
|
||||||
@ -1771,14 +1779,16 @@ static void unset_local_var(const char *name)
|
|||||||
struct variables *cur;
|
struct variables *cur;
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
for (cur = top_vars; cur; cur=cur->next)
|
for (cur = top_vars; cur; cur=cur->next) {
|
||||||
if(strcmp(cur->name, name)==0)
|
if(strcmp(cur->name, name)==0)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
if(cur!=0) {
|
if(cur!=0) {
|
||||||
struct variables *next = top_vars;
|
struct variables *next = top_vars;
|
||||||
if(cur==next)
|
if(cur->flg_read_only) {
|
||||||
|
error_msg("%s: readonly variable", name);
|
||||||
return;
|
return;
|
||||||
else {
|
} else {
|
||||||
if(cur->flg_export)
|
if(cur->flg_export)
|
||||||
unsetenv(cur->name);
|
unsetenv(cur->name);
|
||||||
free(cur->name);
|
free(cur->name);
|
||||||
@ -2103,9 +2113,9 @@ FILE *generate_stream_from_list(struct pipe *head)
|
|||||||
#if 0
|
#if 0
|
||||||
#define SURROGATE "surrogate response"
|
#define SURROGATE "surrogate response"
|
||||||
write(1,SURROGATE,sizeof(SURROGATE));
|
write(1,SURROGATE,sizeof(SURROGATE));
|
||||||
exit(run_list(head));
|
_exit(run_list(head));
|
||||||
#else
|
#else
|
||||||
exit(run_list_real(head)); /* leaks memory */
|
_exit(run_list_real(head)); /* leaks memory */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
debug_printf("forked child %d\n",pid);
|
debug_printf("forked child %d\n",pid);
|
||||||
@ -2531,19 +2541,44 @@ int shell_main(int argc, char **argv)
|
|||||||
struct jobset joblist_end = { NULL, NULL };
|
struct jobset joblist_end = { NULL, NULL };
|
||||||
char **e = environ;
|
char **e = environ;
|
||||||
|
|
||||||
/* initialize globals */
|
/* FIXME */
|
||||||
if (e) {
|
fprintf(stderr, "sizeof(map)=%d\n", sizeof(map));
|
||||||
for (; *e; e++)
|
|
||||||
set_local_var(*e, 2); /* without call putenv() */
|
|
||||||
}
|
|
||||||
job_list = &joblist_end;
|
|
||||||
|
|
||||||
last_return_code=EXIT_SUCCESS;
|
|
||||||
|
|
||||||
/* XXX what should these be while sourcing /etc/profile? */
|
/* XXX what should these be while sourcing /etc/profile? */
|
||||||
global_argc = argc;
|
global_argc = argc;
|
||||||
global_argv = argv;
|
global_argv = argv;
|
||||||
|
|
||||||
|
/* (re?) initialize globals. Sometimes shell_main() ends up calling
|
||||||
|
* shell_main(), therefore we cannot rely on the BSS to zero out this
|
||||||
|
* stuff. Reset these to 0 every time. */
|
||||||
|
ifs = NULL;
|
||||||
|
memset(map,0,sizeof(map));
|
||||||
|
fake_mode = 0;
|
||||||
|
interactive = 0;
|
||||||
|
close_me_head = NULL;
|
||||||
|
last_bg_pid = 0;
|
||||||
|
|
||||||
|
/* Initialize some more globals to non-zero values */
|
||||||
|
set_cwd();
|
||||||
|
job_list = &joblist_end;
|
||||||
|
#ifdef BB_FEATURE_COMMAND_EDITING
|
||||||
|
cmdedit_set_initial_prompt();
|
||||||
|
#else
|
||||||
|
PS1 = NULL;
|
||||||
|
#endif
|
||||||
|
PS2 = "> ";
|
||||||
|
|
||||||
|
/* initialize our shell local variables with the values
|
||||||
|
* currently living in the environment */
|
||||||
|
if (e) {
|
||||||
|
for (; *e; e++)
|
||||||
|
set_local_var(*e, 2); /* without call putenv() */
|
||||||
|
}
|
||||||
|
|
||||||
|
last_return_code=EXIT_SUCCESS;
|
||||||
|
|
||||||
|
|
||||||
/* If we get started under a job aware app (like bash
|
/* If we get started under a job aware app (like bash
|
||||||
* for example), make sure we are now in charge so we
|
* for example), make sure we are now in charge so we
|
||||||
* don't fight over who gets the foreground */
|
* don't fight over who gets the foreground */
|
||||||
@ -2563,16 +2598,6 @@ int shell_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
input=stdin;
|
input=stdin;
|
||||||
|
|
||||||
/* initialize the cwd -- this is never freed...*/
|
|
||||||
cwd = xgetcwd(0);
|
|
||||||
if (!cwd)
|
|
||||||
cwd = unknown;
|
|
||||||
#ifdef BB_FEATURE_COMMAND_EDITING
|
|
||||||
cmdedit_set_initial_prompt();
|
|
||||||
#else
|
|
||||||
PS1 = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "c:xif")) > 0) {
|
while ((opt = getopt(argc, argv, "c:xif")) > 0) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'c':
|
case 'c':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user