aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2004-03-11 13:34:24 +0000
committerEric Andersen <andersen@codepoet.org>2004-03-11 13:34:24 +0000
commitef02f82bcf667ede9790a5de6aa78459529f29e4 (patch)
tree626513aa59c95e061c7c40fbf6e4669981fb3a21
parentb7b3bda3ba0d3a49ac2ebbb422fe3bec99e2b0b9 (diff)
downloadbusybox-w32-ef02f82bcf667ede9790a5de6aa78459529f29e4.tar.gz
busybox-w32-ef02f82bcf667ede9790a5de6aa78459529f29e4.tar.bz2
busybox-w32-ef02f82bcf667ede9790a5de6aa78459529f29e4.zip
Paul Mundt, lethal at linux-sh dot org writes:
Here's a follow-up replacement to the patch I sent earlier, this adjusts some of the semantics of the dynamic variable setting. Namely, dynamic vars can hook a set handler (which RANDOM uses to adjust the seed). They'll only lose their dynamic status if they're unset. I've used the same approach that bash does to come up with the random number, mostly just for consistency. For example: $ echo $RANDOM 13759 $ echo $RANDOM 20057 $ echo $RANDOM 1502 $ export RANDOM=42 $ echo $RANDOM 24179 $ echo $RANDOM 2046 $ unset RANDOM $ echo $RANDOM $ export RANDOM=42 $ echo $RANDOM 42 $
-rw-r--r--shell/ash.c68
1 files changed, 54 insertions, 14 deletions
diff --git a/shell/ash.c b/shell/ash.c
index eb8706f36..8c2493ece 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -37,6 +37,8 @@
37 * used in busybox and size optimizations, 37 * used in busybox and size optimizations,
38 * support locale, rewrited arith (see notes to this) 38 * support locale, rewrited arith (see notes to this)
39 * 39 *
40 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
41 * dynamic variables.
40 */ 42 */
41 43
42 44
@@ -88,7 +90,7 @@
88#include <signal.h> 90#include <signal.h>
89#include <stdint.h> 91#include <stdint.h>
90#include <sysexits.h> 92#include <sysexits.h>
91 93#include <time.h>
92#include <fnmatch.h> 94#include <fnmatch.h>
93 95
94 96
@@ -1465,6 +1467,7 @@ static void reset(void);
1465#define VNOFUNC 0x40 /* don't call the callback function */ 1467#define VNOFUNC 0x40 /* don't call the callback function */
1466#define VNOSET 0x80 /* do not set variable - just readonly test */ 1468#define VNOSET 0x80 /* do not set variable - just readonly test */
1467#define VNOSAVE 0x100 /* when text is on the heap before setvareq */ 1469#define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1470#define VDYNAMIC 0x200 /* dynamic variable */
1468 1471
1469 1472
1470struct var { 1473struct var {
@@ -1474,6 +1477,9 @@ struct var {
1474 void (*func)(const char *); 1477 void (*func)(const char *);
1475 /* function to be called when */ 1478 /* function to be called when */
1476 /* the variable gets set/unset */ 1479 /* the variable gets set/unset */
1480 char *(*lookup_func)(const char *);
1481 /* function to be called when */
1482 /* the variable is read (if dynamic) */
1477}; 1483};
1478 1484
1479struct localvar { 1485struct localvar {
@@ -1500,6 +1506,9 @@ static void change_lc_all(const char *value);
1500static void change_lc_ctype(const char *value); 1506static void change_lc_ctype(const char *value);
1501#endif 1507#endif
1502 1508
1509static char *get_random(const char *);
1510static void change_random(const char *);
1511
1503#define VTABSIZE 39 1512#define VTABSIZE 39
1504 1513
1505static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin"; 1514static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
@@ -1513,30 +1522,32 @@ static const char defifs[] = " \t\n";
1513 1522
1514static struct var varinit[] = { 1523static struct var varinit[] = {
1515#ifdef IFS_BROKEN 1524#ifdef IFS_BROKEN
1516 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 }, 1525 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0, 0 },
1517#else 1526#else
1518 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 }, 1527 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0, 0 },
1519#endif 1528#endif
1520 1529
1521#ifdef CONFIG_ASH_MAIL 1530#ifdef CONFIG_ASH_MAIL
1522 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail }, 1531 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail, 0 },
1523 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail }, 1532 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail, 0 },
1524#endif 1533#endif
1525 1534
1526 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath }, 1535 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath, 0 },
1527 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 }, 1536 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0, 0 },
1528 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 }, 1537 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0, 0 },
1529 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 }, 1538 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0, 0 },
1530#ifdef CONFIG_ASH_GETOPTS 1539#ifdef CONFIG_ASH_GETOPTS
1531 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset }, 1540 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset, 0 },
1532#endif 1541#endif
1533#ifdef CONFIG_LOCALE_SUPPORT 1542#ifdef CONFIG_LOCALE_SUPPORT
1534 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL=", change_lc_all}, 1543 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL=", change_lc_all, 0},
1535 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE=", change_lc_ctype}, 1544 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE=", change_lc_ctype, 0},
1536#endif 1545#endif
1537#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY 1546#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1538 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE=", NULL}, 1547 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE=", NULL, 0},
1539#endif 1548#endif
1549 {0, VSTRFIXED | VTEXTFIXED | VUNSET | VDYNAMIC, "RANDOM\0",
1550 change_random, get_random},
1540}; 1551};
1541 1552
1542#define vifs varinit[0] 1553#define vifs varinit[0]
@@ -9019,6 +9030,22 @@ static void change_lc_ctype(const char *value)
9019 9030
9020#endif 9031#endif
9021 9032
9033/* Roughly copied from bash.. */
9034static unsigned long rseed = 1;
9035static char *get_random(const char *var)
9036{
9037 char buf[255];
9038 rseed = (rseed + getpid() + ((time_t)time((time_t *)0)));
9039 rseed = rseed * 1103515245 + 12345;
9040 sprintf(buf, "%d", (unsigned int)((rseed >> 16 & 32767)));
9041 return bb_xstrdup(buf);
9042}
9043
9044static void change_random(const char *value)
9045{
9046 rseed = strtoul(value, (char **)NULL, 10);
9047}
9048
9022#ifdef CONFIG_ASH_GETOPTS 9049#ifdef CONFIG_ASH_GETOPTS
9023static int 9050static int
9024getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff) 9051getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
@@ -12031,9 +12058,20 @@ lookupvar(const char *name)
12031{ 12058{
12032 struct var *v; 12059 struct var *v;
12033 12060
12034 if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) { 12061 if ((v = *findvar(hashvar(name), name)) && !(v->flags & (VUNSET|VDYNAMIC))) {
12035 return strchrnul(v->text, '=') + 1; 12062 return strchrnul(v->text, '=') + 1;
12036 } 12063 }
12064
12065 /*
12066 * Dynamic variables are implemented roughly the same way they are
12067 * in bash. Namely, they're "special" so long as they aren't unset.
12068 * As soon as they're unset, they're no longer dynamic, and dynamic
12069 * lookup will no longer happen at that point. -- PFM.
12070 */
12071 if (v && ((v->flags & VDYNAMIC)))
12072 if (v->lookup_func)
12073 return v->lookup_func(name);
12074
12037 return NULL; 12075 return NULL;
12038} 12076}
12039 12077
@@ -12308,6 +12346,8 @@ unsetvar(const char *s)
12308 retval = 1; 12346 retval = 1;
12309 if (flags & VREADONLY) 12347 if (flags & VREADONLY)
12310 goto out; 12348 goto out;
12349 if (flags & VDYNAMIC)
12350 vp->flags &= ~VDYNAMIC;
12311 if (flags & VUNSET) 12351 if (flags & VUNSET)
12312 goto ok; 12352 goto ok;
12313 if ((flags & VSTRFIXED) == 0) { 12353 if ((flags & VSTRFIXED) == 0) {