hush: we can't do without variable->value member, saving 25 bytes of code
and some runtime memory. Rename few variables.
This commit is contained in:
parent
d76c049cc4
commit
28c0f0f4fe
80
shell/hush.c
80
shell/hush.c
@ -286,8 +286,7 @@ struct close_me {
|
|||||||
#define setenv(...) setenv_is_leaky_dont_use()
|
#define setenv(...) setenv_is_leaky_dont_use()
|
||||||
struct variable {
|
struct variable {
|
||||||
struct variable *next;
|
struct variable *next;
|
||||||
char *name; /* points to "name=" portion */
|
char *varstr; /* points to "name=" portion */
|
||||||
char *value; /* points directly after "=" */
|
|
||||||
int max_len; /* if > 0, name is part of initial env; else name is malloced */
|
int max_len; /* if > 0, name is part of initial env; else name is malloced */
|
||||||
smallint flg_export; /* putenv should be done on this var */
|
smallint flg_export; /* putenv should be done on this var */
|
||||||
smallint flg_read_only;
|
smallint flg_read_only;
|
||||||
@ -334,8 +333,7 @@ static const char version_str[] = "HUSH_VERSION="HUSH_VER_STR;
|
|||||||
|
|
||||||
static const struct variable const_shell_ver = {
|
static const struct variable const_shell_ver = {
|
||||||
.next = NULL,
|
.next = NULL,
|
||||||
.name = (char*)version_str,
|
.varstr = (char*)version_str,
|
||||||
.value = (char*)version_str + sizeof("HUSH_VERSION=")-1,
|
|
||||||
.max_len = 1, /* 0 can provoke free(name) */
|
.max_len = 1, /* 0 can provoke free(name) */
|
||||||
.flg_export = 1,
|
.flg_export = 1,
|
||||||
.flg_read_only = 1,
|
.flg_read_only = 1,
|
||||||
@ -554,8 +552,8 @@ static char **expand_strvec_to_strvec(char **argv);
|
|||||||
static char *expand_strvec_to_string(char **argv);
|
static char *expand_strvec_to_string(char **argv);
|
||||||
/* used for expansion of right hand of assignments */
|
/* used for expansion of right hand of assignments */
|
||||||
static char *expand_string_to_string(const char *str);
|
static char *expand_string_to_string(const char *str);
|
||||||
static struct variable *get_local_var(const char *var);
|
static struct variable *get_local_var(const char *name);
|
||||||
static int set_local_var(char *s, int flg_export);
|
static int set_local_var(char *str, int flg_export);
|
||||||
static void unset_local_var(const char *name);
|
static void unset_local_var(const char *name);
|
||||||
|
|
||||||
/* Table of built-in functions. They can be forked or not, depending on
|
/* Table of built-in functions. They can be forked or not, depending on
|
||||||
@ -831,7 +829,7 @@ static int builtin_export(char **argv)
|
|||||||
var = get_local_var(name);
|
var = get_local_var(name);
|
||||||
if (var) {
|
if (var) {
|
||||||
var->flg_export = 1;
|
var->flg_export = 1;
|
||||||
putenv(var->name);
|
putenv(var->varstr);
|
||||||
}
|
}
|
||||||
/* 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. */
|
||||||
@ -976,7 +974,7 @@ static int builtin_set(char **argv)
|
|||||||
|
|
||||||
if (temp == NULL)
|
if (temp == NULL)
|
||||||
for (e = top_var; e; e = e->next)
|
for (e = top_var; e; e = e->next)
|
||||||
puts(e->name);
|
puts(e->varstr);
|
||||||
else
|
else
|
||||||
set_local_var(xstrdup(temp), 0);
|
set_local_var(xstrdup(temp), 0);
|
||||||
|
|
||||||
@ -2676,39 +2674,39 @@ static char* expand_strvec_to_string(char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* This is used to get/check local shell variables */
|
/* This is used to get/check local shell variables */
|
||||||
static struct variable *get_local_var(const char *s)
|
static struct variable *get_local_var(const char *name)
|
||||||
{
|
{
|
||||||
struct variable *cur;
|
struct variable *cur;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (!s)
|
if (!name)
|
||||||
return NULL;
|
return NULL;
|
||||||
len = strlen(s);
|
len = strlen(name);
|
||||||
for (cur = top_var; cur; cur = cur->next) {
|
for (cur = top_var; cur; cur = cur->next) {
|
||||||
if (strncmp(cur->name, s, len) == 0 && cur->name[len] == '=')
|
if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
|
||||||
return cur;
|
return cur;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* name holds "NAME=VAL" and is expected to be malloced.
|
/* str holds "NAME=VAL" and is expected to be malloced.
|
||||||
* We take ownership of it. */
|
* We take ownership of it. */
|
||||||
static int set_local_var(char *name, int flg_export)
|
static int set_local_var(char *str, int flg_export)
|
||||||
{
|
{
|
||||||
struct variable *cur;
|
struct variable *cur;
|
||||||
char *value;
|
char *value;
|
||||||
int name_len;
|
int name_len;
|
||||||
|
|
||||||
value = strchr(name, '=');
|
value = strchr(str, '=');
|
||||||
if (!value) { /* not expected to ever happen? */
|
if (!value) { /* not expected to ever happen? */
|
||||||
free(name);
|
free(str);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
name_len = value - name;
|
name_len = value - str;
|
||||||
cur = top_var; /* cannot be NULL (we have HUSH_VERSION and it's RO) */
|
cur = top_var; /* cannot be NULL (we have HUSH_VERSION and it's RO) */
|
||||||
while (1) {
|
while (1) {
|
||||||
if (strncmp(cur->name, name, name_len) != 0 || cur->name[name_len] != '=') {
|
if (strncmp(cur->varstr, str, name_len) != 0 || cur->varstr[name_len] != '=') {
|
||||||
if (!cur->next) {
|
if (!cur->next) {
|
||||||
/* cur points to last var in linked list */
|
/* cur points to last var in linked list */
|
||||||
break;
|
break;
|
||||||
@ -2716,45 +2714,44 @@ static int set_local_var(char *name, int flg_export)
|
|||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* We already have a var with this name */
|
/* We found an existing var with this name */
|
||||||
|
*value = '\0';
|
||||||
if (cur->flg_read_only) {
|
if (cur->flg_read_only) {
|
||||||
bb_error_msg("%s: readonly variable", name);
|
bb_error_msg("%s: readonly variable", str);
|
||||||
free(name);
|
free(str);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*value = '\0';
|
unsetenv(str); /* just in case */
|
||||||
unsetenv(name); /* just in case */
|
*value = '=';
|
||||||
*value++ = '=';
|
if (strcmp(cur->varstr, str) == 0) {
|
||||||
if (strcmp(cur->value, value) == 0) {
|
|
||||||
free_and_exp:
|
free_and_exp:
|
||||||
free(name);
|
free(str);
|
||||||
goto exp;
|
goto exp;
|
||||||
}
|
}
|
||||||
if (cur->max_len >= strlen(name)) {
|
if (cur->max_len >= strlen(str)) {
|
||||||
/* This one is from startup env, reuse space */
|
/* This one is from startup env, reuse space */
|
||||||
strcpy(cur->name, name);
|
strcpy(cur->varstr, str);
|
||||||
goto free_and_exp;
|
goto free_and_exp;
|
||||||
}
|
}
|
||||||
/* max_len == 0 signifies "malloced" var, which we can
|
/* max_len == 0 signifies "malloced" var, which we can
|
||||||
* (and has to) free */
|
* (and has to) free */
|
||||||
if (!cur->max_len)
|
if (!cur->max_len)
|
||||||
free(cur->name);
|
free(cur->varstr);
|
||||||
cur->max_len = 0;
|
cur->max_len = 0;
|
||||||
goto set_name_and_exp;
|
goto set_str_and_exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not found - create next variable struct */
|
/* Not found - create next variable struct */
|
||||||
cur->next = xzalloc(sizeof(*cur));
|
cur->next = xzalloc(sizeof(*cur));
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
|
|
||||||
set_name_and_exp:
|
set_str_and_exp:
|
||||||
cur->name = name;
|
cur->varstr = str;
|
||||||
exp:
|
exp:
|
||||||
cur->value = cur->name + name_len + 1;
|
|
||||||
if (flg_export)
|
if (flg_export)
|
||||||
cur->flg_export = 1;
|
cur->flg_export = 1;
|
||||||
if (cur->flg_export)
|
if (cur->flg_export)
|
||||||
return putenv(cur->name);
|
return putenv(cur->varstr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2769,7 +2766,7 @@ static void unset_local_var(const char *name)
|
|||||||
name_len = strlen(name);
|
name_len = strlen(name);
|
||||||
cur = top_var;
|
cur = top_var;
|
||||||
while (cur) {
|
while (cur) {
|
||||||
if (strncmp(cur->name, name, name_len) == 0 && cur->name[name_len] == '=') {
|
if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') {
|
||||||
if (cur->flg_read_only) {
|
if (cur->flg_read_only) {
|
||||||
bb_error_msg("%s: readonly variable", name);
|
bb_error_msg("%s: readonly variable", name);
|
||||||
return;
|
return;
|
||||||
@ -2777,9 +2774,9 @@ static void unset_local_var(const char *name)
|
|||||||
/* prev is ok to use here because 1st variable, HUSH_VERSION,
|
/* prev is ok to use here because 1st variable, HUSH_VERSION,
|
||||||
* is ro, and we cannot reach this code on the 1st pass */
|
* is ro, and we cannot reach this code on the 1st pass */
|
||||||
prev->next = cur->next;
|
prev->next = cur->next;
|
||||||
unsetenv(cur->name);
|
unsetenv(cur->varstr);
|
||||||
if (!cur->max_len)
|
if (!cur->max_len)
|
||||||
free(cur->name);
|
free(cur->varstr);
|
||||||
free(cur);
|
free(cur);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3256,7 +3253,7 @@ static const char *lookup_param(const char *src)
|
|||||||
{
|
{
|
||||||
struct variable *var = get_local_var(src);
|
struct variable *var = get_local_var(src);
|
||||||
if (var)
|
if (var)
|
||||||
return var->value;
|
return strchr(var->varstr, '=') + 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3682,14 +3679,13 @@ int hush_main(int argc, char **argv)
|
|||||||
if (value) { /* paranoia */
|
if (value) { /* paranoia */
|
||||||
cur_var->next = xzalloc(sizeof(*cur_var));
|
cur_var->next = xzalloc(sizeof(*cur_var));
|
||||||
cur_var = cur_var->next;
|
cur_var = cur_var->next;
|
||||||
cur_var->name = *e;
|
cur_var->varstr = *e;
|
||||||
cur_var->value = value + 1;
|
|
||||||
cur_var->max_len = strlen(*e);
|
cur_var->max_len = strlen(*e);
|
||||||
cur_var->flg_export = 1;
|
cur_var->flg_export = 1;
|
||||||
}
|
}
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
putenv(shell_ver.name);
|
putenv(shell_ver.varstr);
|
||||||
|
|
||||||
#if ENABLE_FEATURE_EDITING
|
#if ENABLE_FEATURE_EDITING
|
||||||
line_input_state = new_line_input_t(FOR_SHELL);
|
line_input_state = new_line_input_t(FOR_SHELL);
|
||||||
@ -3827,7 +3823,7 @@ int hush_main(int argc, char **argv)
|
|||||||
while (cur_var) {
|
while (cur_var) {
|
||||||
struct variable *tmp = cur_var;
|
struct variable *tmp = cur_var;
|
||||||
if (!cur_var->max_len)
|
if (!cur_var->max_len)
|
||||||
free(cur_var->name);
|
free(cur_var->varstr);
|
||||||
cur_var = cur_var->next;
|
cur_var = cur_var->next;
|
||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user