aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-18 01:05:24 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-18 01:05:24 +0200
commit3bab36b18baa0dc254445828f492051450a38d41 (patch)
treecc264de1f0ae093cfde9e3470756bf1dcc5d21fc
parent6b0695bb66dd38af4d4671fb2381fa3e1dbfe90c (diff)
downloadbusybox-w32-3bab36b18baa0dc254445828f492051450a38d41.tar.gz
busybox-w32-3bab36b18baa0dc254445828f492051450a38d41.tar.bz2
busybox-w32-3bab36b18baa0dc254445828f492051450a38d41.zip
hush: convert exp/ro/local parameters to bitfields in one flag param
function old new delta helper_export_local 174 185 +11 set_local_var 424 420 -4 run_list 1048 1044 -4 set_vars_and_save_old 88 83 -5 set_local_var_from_halves 27 22 -5 run_pipe 1554 1549 -5 builtin_export 173 168 -5 set_pwd_var 40 34 -6 builtin_readonly 70 64 -6 expand_one_var 1625 1618 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/9 up/down: 11/-47) Total: -36 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/hush.c81
1 files changed, 35 insertions, 46 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 4b71344da..7771172b6 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2057,25 +2057,20 @@ static const char* FAST_FUNC get_local_var_value(const char *name)
2057 2057
2058/* str holds "NAME=VAL" and is expected to be malloced. 2058/* str holds "NAME=VAL" and is expected to be malloced.
2059 * We take ownership of it. 2059 * We take ownership of it.
2060 * flg_export:
2061 * 0: do not change export flag
2062 * (if creating new variable, flag will be 0)
2063 * 1: set export flag and putenv the variable
2064 * -1: clear export flag and unsetenv the variable
2065 * flg_read_only is set only when we handle -R var=val
2066 */ 2060 */
2067static int set_local_var(char *str, 2061#define SETFLAG_EXPORT (1 << 0)
2068 int flg_export UNUSED_PARAM, 2062#define SETFLAG_UNEXPORT (1 << 1)
2069 int local_lvl UNUSED_PARAM, 2063#define SETFLAG_MAKE_RO (1 << 2)
2070 int flg_read_only UNUSED_PARAM) 2064#define SETFLAG_LOCAL_SHIFT 3
2065static int set_local_var(char *str, unsigned flags)
2071{ 2066{
2072 struct variable **var_pp; 2067 struct variable **var_pp;
2073 struct variable *cur; 2068 struct variable *cur;
2074 char *free_me = NULL; 2069 char *free_me = NULL;
2075 char *eq_sign; 2070 char *eq_sign;
2076 int name_len; 2071 int name_len;
2072 IF_HUSH_LOCAL(unsigned local_lvl = (flags >> SETFLAG_LOCAL_SHIFT);)
2077 2073
2078 //bb_error_msg("set_local_var('%s',%d,%d,%d)", str, flg_export, local_lvl, flg_read_only);
2079 eq_sign = strchr(str, '='); 2074 eq_sign = strchr(str, '=');
2080 if (!eq_sign) { /* not expected to ever happen? */ 2075 if (!eq_sign) { /* not expected to ever happen? */
2081 free(str); 2076 free(str);
@@ -2096,7 +2091,7 @@ static int set_local_var(char *str,
2096 free(str); 2091 free(str);
2097 return -1; 2092 return -1;
2098 } 2093 }
2099 if (flg_export == -1) { // "&& cur->flg_export" ? 2094 if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ?
2100 debug_printf_env("%s: unsetenv '%s'\n", __func__, str); 2095 debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
2101 *eq_sign = '\0'; 2096 *eq_sign = '\0';
2102 unsetenv(str); 2097 unsetenv(str);
@@ -2120,7 +2115,7 @@ static int set_local_var(char *str,
2120 * z=z 2115 * z=z
2121 */ 2116 */
2122 if (cur->flg_export) 2117 if (cur->flg_export)
2123 flg_export = 1; 2118 flags |= SETFLAG_EXPORT;
2124 break; 2119 break;
2125 } 2120 }
2126#endif 2121#endif
@@ -2151,9 +2146,7 @@ static int set_local_var(char *str,
2151 2146
2152 /* Not found - create new variable struct */ 2147 /* Not found - create new variable struct */
2153 cur = xzalloc(sizeof(*cur)); 2148 cur = xzalloc(sizeof(*cur));
2154#if ENABLE_HUSH_LOCAL 2149 IF_HUSH_LOCAL(cur->func_nest_level = local_lvl;)
2155 cur->func_nest_level = local_lvl;
2156#endif
2157 cur->next = *var_pp; 2150 cur->next = *var_pp;
2158 *var_pp = cur; 2151 *var_pp = cur;
2159 2152
@@ -2161,16 +2154,16 @@ static int set_local_var(char *str,
2161 cur->varstr = str; 2154 cur->varstr = str;
2162 exp: 2155 exp:
2163#if !BB_MMU || ENABLE_HUSH_READONLY 2156#if !BB_MMU || ENABLE_HUSH_READONLY
2164 if (flg_read_only != 0) { 2157 if (flags & SETFLAG_MAKE_RO) {
2165 cur->flg_read_only = flg_read_only; 2158 cur->flg_read_only = 1;
2166 } 2159 }
2167#endif 2160#endif
2168 if (flg_export == 1) 2161 if (flags & SETFLAG_EXPORT)
2169 cur->flg_export = 1; 2162 cur->flg_export = 1;
2170 if (name_len == 4 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S') 2163 if (name_len == 4 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S')
2171 cmdedit_update_prompt(); 2164 cmdedit_update_prompt();
2172 if (cur->flg_export) { 2165 if (cur->flg_export) {
2173 if (flg_export == -1) { 2166 if (flags & SETFLAG_UNEXPORT) {
2174 cur->flg_export = 0; 2167 cur->flg_export = 0;
2175 /* unsetenv was already done */ 2168 /* unsetenv was already done */
2176 } else { 2169 } else {
@@ -2187,10 +2180,9 @@ static int set_local_var(char *str,
2187} 2180}
2188 2181
2189/* Used at startup and after each cd */ 2182/* Used at startup and after each cd */
2190static void set_pwd_var(int exp) 2183static void set_pwd_var(unsigned flag)
2191{ 2184{
2192 set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), 2185 set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag);
2193 /*exp:*/ exp, /*lvl:*/ 0, /*ro:*/ 0);
2194} 2186}
2195 2187
2196static int unset_local_var_len(const char *name, int name_len) 2188static int unset_local_var_len(const char *name, int name_len)
@@ -2248,7 +2240,7 @@ static void unset_vars(char **strings)
2248static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) 2240static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
2249{ 2241{
2250 char *var = xasprintf("%s=%s", name, val); 2242 char *var = xasprintf("%s=%s", name, val);
2251 set_local_var(var, /*flags:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 2243 set_local_var(var, /*flag:*/ 0);
2252} 2244}
2253#endif 2245#endif
2254 2246
@@ -2299,7 +2291,7 @@ static struct variable *set_vars_and_save_old(char **strings)
2299 var_p->next = old; 2291 var_p->next = old;
2300 old = var_p; 2292 old = var_p;
2301 } 2293 }
2302 set_local_var(*s, /*exp:*/ 1, /*lvl:*/ 0, /*ro:*/ 0); 2294 set_local_var(*s, SETFLAG_EXPORT);
2303 } 2295 }
2304 s++; 2296 s++;
2305 } 2297 }
@@ -5805,7 +5797,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
5805 val = NULL; 5797 val = NULL;
5806 } else { 5798 } else {
5807 char *new_var = xasprintf("%s=%s", var, val); 5799 char *new_var = xasprintf("%s=%s", var, val);
5808 set_local_var(new_var, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 5800 set_local_var(new_var, /*flag:*/ 0);
5809 } 5801 }
5810 } 5802 }
5811 } 5803 }
@@ -7775,7 +7767,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
7775 if (new_env) { 7767 if (new_env) {
7776 argv = new_env; 7768 argv = new_env;
7777 while (*argv) { 7769 while (*argv) {
7778 set_local_var(*argv, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 7770 set_local_var(*argv, /*flag:*/ 0);
7779 /* Do we need to flag set_local_var() errors? 7771 /* Do we need to flag set_local_var() errors?
7780 * "assignment to readonly var" and "putenv error" 7772 * "assignment to readonly var" and "putenv error"
7781 */ 7773 */
@@ -7803,7 +7795,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
7803 fprintf(stderr, " %s", p); 7795 fprintf(stderr, " %s", p);
7804 debug_printf_exec("set shell var:'%s'->'%s'\n", 7796 debug_printf_exec("set shell var:'%s'->'%s'\n",
7805 *argv, p); 7797 *argv, p);
7806 set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 7798 set_local_var(p, /*flag:*/ 0);
7807 /* Do we need to flag set_local_var() errors? 7799 /* Do we need to flag set_local_var() errors?
7808 * "assignment to readonly var" and "putenv error" 7800 * "assignment to readonly var" and "putenv error"
7809 */ 7801 */
@@ -8215,7 +8207,7 @@ static int run_list(struct pipe *pi)
8215 } 8207 }
8216 /* Insert next value from for_lcur */ 8208 /* Insert next value from for_lcur */
8217 /* note: *for_lcur already has quotes removed, $var expanded, etc */ 8209 /* note: *for_lcur already has quotes removed, $var expanded, etc */
8218 set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); 8210 set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*flag:*/ 0);
8219 continue; 8211 continue;
8220 } 8212 }
8221 if (rword == RES_IN) { 8213 if (rword == RES_IN) {
@@ -8600,7 +8592,7 @@ int hush_main(int argc, char **argv)
8600 putenv(shell_ver->varstr); 8592 putenv(shell_ver->varstr);
8601 8593
8602 /* Export PWD */ 8594 /* Export PWD */
8603 set_pwd_var(/*exp:*/ 1); 8595 set_pwd_var(SETFLAG_EXPORT);
8604 8596
8605#if BASH_HOSTNAME_VAR 8597#if BASH_HOSTNAME_VAR
8606 /* Set (but not export) HOSTNAME unless already set */ 8598 /* Set (but not export) HOSTNAME unless already set */
@@ -8770,7 +8762,7 @@ int hush_main(int argc, char **argv)
8770 } 8762 }
8771 case 'R': 8763 case 'R':
8772 case 'V': 8764 case 'V':
8773 set_local_var(xstrdup(optarg), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ opt == 'R'); 8765 set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0);
8774 break; 8766 break;
8775# if ENABLE_HUSH_FUNCTIONS 8767# if ENABLE_HUSH_FUNCTIONS
8776 case 'F': { 8768 case 'F': {
@@ -9073,7 +9065,7 @@ static int FAST_FUNC builtin_cd(char **argv)
9073 * Note: do not enforce exporting. If PWD was unset or unexported, 9065 * Note: do not enforce exporting. If PWD was unset or unexported,
9074 * set it again, but do not export. bash does the same. 9066 * set it again, but do not export. bash does the same.
9075 */ 9067 */
9076 set_pwd_var(/*exp:*/ 0); 9068 set_pwd_var(/*flag:*/ 0);
9077 return EXIT_SUCCESS; 9069 return EXIT_SUCCESS;
9078} 9070}
9079 9071
@@ -9312,10 +9304,7 @@ static void print_escaped(const char *s)
9312#endif 9304#endif
9313 9305
9314#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL || ENABLE_HUSH_READONLY 9306#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL || ENABLE_HUSH_READONLY
9315static int helper_export_local(char **argv, 9307static int helper_export_local(char **argv, unsigned flags)
9316 int exp UNUSED_PARAM,
9317 int ro UNUSED_PARAM,
9318 int lvl UNUSED_PARAM)
9319{ 9308{
9320 do { 9309 do {
9321 char *name = *argv; 9310 char *name = *argv;
@@ -9329,7 +9318,7 @@ static int helper_export_local(char **argv,
9329 vpp = get_ptr_to_local_var(name, name_end - name); 9318 vpp = get_ptr_to_local_var(name, name_end - name);
9330 var = vpp ? *vpp : NULL; 9319 var = vpp ? *vpp : NULL;
9331 9320
9332 if (exp == -1) { /* unexporting? */ 9321 if (flags & SETFLAG_UNEXPORT) {
9333 /* export -n NAME (without =VALUE) */ 9322 /* export -n NAME (without =VALUE) */
9334 if (var) { 9323 if (var) {
9335 var->flg_export = 0; 9324 var->flg_export = 0;
@@ -9338,7 +9327,7 @@ static int helper_export_local(char **argv,
9338 } /* else: export -n NOT_EXISTING_VAR: no-op */ 9327 } /* else: export -n NOT_EXISTING_VAR: no-op */
9339 continue; 9328 continue;
9340 } 9329 }
9341 if (exp == 1) { /* exporting? */ 9330 if (flags & SETFLAG_EXPORT) {
9342 /* export NAME (without =VALUE) */ 9331 /* export NAME (without =VALUE) */
9343 if (var) { 9332 if (var) {
9344 var->flg_export = 1; 9333 var->flg_export = 1;
@@ -9349,9 +9338,8 @@ static int helper_export_local(char **argv,
9349 } 9338 }
9350# if ENABLE_HUSH_LOCAL 9339# if ENABLE_HUSH_LOCAL
9351 /* Is this "local" bltin? */ 9340 /* Is this "local" bltin? */
9352 if (exp == 0 9341 if (!(flags & (SETFLAG_EXPORT|SETFLAG_UNEXPORT|SETFLAG_MAKE_RO))) {
9353 IF_HUSH_READONLY(&& ro == 0) /* in !READONLY config, always true */ 9342 unsigned lvl = flags >> SETFLAG_LOCAL_SHIFT;
9354 ) {
9355 if (var && var->func_nest_level == lvl) { 9343 if (var && var->func_nest_level == lvl) {
9356 /* "local x=abc; ...; local x" - ignore second local decl */ 9344 /* "local x=abc; ...; local x" - ignore second local decl */
9357 continue; 9345 continue;
@@ -9376,7 +9364,7 @@ static int helper_export_local(char **argv,
9376 /* (Un)exporting/making local NAME=VALUE */ 9364 /* (Un)exporting/making local NAME=VALUE */
9377 name = xstrdup(name); 9365 name = xstrdup(name);
9378 } 9366 }
9379 set_local_var(name, /*exp:*/ exp, /*lvl:*/ lvl, /*ro:*/ ro); 9367 set_local_var(name, flags);
9380 } while (*++argv); 9368 } while (*++argv);
9381 return EXIT_SUCCESS; 9369 return EXIT_SUCCESS;
9382} 9370}
@@ -9424,7 +9412,7 @@ static int FAST_FUNC builtin_export(char **argv)
9424 return EXIT_SUCCESS; 9412 return EXIT_SUCCESS;
9425 } 9413 }
9426 9414
9427 return helper_export_local(argv, /*exp:*/ (opt_unexport ? -1 : 1), /*ro:*/ 0, /*lvl:*/ 0); 9415 return helper_export_local(argv, opt_unexport ? SETFLAG_UNEXPORT : SETFLAG_EXPORT);
9428} 9416}
9429#endif 9417#endif
9430 9418
@@ -9436,14 +9424,15 @@ static int FAST_FUNC builtin_local(char **argv)
9436 return EXIT_FAILURE; /* bash compat */ 9424 return EXIT_FAILURE; /* bash compat */
9437 } 9425 }
9438 argv++; 9426 argv++;
9439 return helper_export_local(argv, /*exp:*/ 0, /*ro:*/ 0, /*lvl:*/ G.func_nest_level); 9427 return helper_export_local(argv, G.func_nest_level << SETFLAG_LOCAL_SHIFT);
9440} 9428}
9441#endif 9429#endif
9442 9430
9443#if ENABLE_HUSH_READONLY 9431#if ENABLE_HUSH_READONLY
9444static int FAST_FUNC builtin_readonly(char **argv) 9432static int FAST_FUNC builtin_readonly(char **argv)
9445{ 9433{
9446 if (*++argv == NULL) { 9434 argv++;
9435 if (*argv == NULL) {
9447 /* bash: readonly [-p]: list all readonly VARs 9436 /* bash: readonly [-p]: list all readonly VARs
9448 * (-p has no effect in bash) 9437 * (-p has no effect in bash)
9449 */ 9438 */
@@ -9456,7 +9445,7 @@ static int FAST_FUNC builtin_readonly(char **argv)
9456 } 9445 }
9457 return EXIT_SUCCESS; 9446 return EXIT_SUCCESS;
9458 } 9447 }
9459 return helper_export_local(argv, /*exp:*/ 0, /*ro:*/ 1, /*lvl:*/ 0); 9448 return helper_export_local(argv, SETFLAG_MAKE_RO);
9460} 9449}
9461#endif 9450#endif
9462 9451