diff options
-rw-r--r-- | shell/ash.c | 68 |
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 | ||
1470 | struct var { | 1473 | struct 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 | ||
1479 | struct localvar { | 1485 | struct localvar { |
@@ -1500,6 +1506,9 @@ static void change_lc_all(const char *value); | |||
1500 | static void change_lc_ctype(const char *value); | 1506 | static void change_lc_ctype(const char *value); |
1501 | #endif | 1507 | #endif |
1502 | 1508 | ||
1509 | static char *get_random(const char *); | ||
1510 | static void change_random(const char *); | ||
1511 | |||
1503 | #define VTABSIZE 39 | 1512 | #define VTABSIZE 39 |
1504 | 1513 | ||
1505 | static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin"; | 1514 | static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin"; |
@@ -1513,30 +1522,32 @@ static const char defifs[] = " \t\n"; | |||
1513 | 1522 | ||
1514 | static struct var varinit[] = { | 1523 | static 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.. */ | ||
9034 | static unsigned long rseed = 1; | ||
9035 | static 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 | |||
9044 | static 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 |
9023 | static int | 9050 | static int |
9024 | getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff) | 9051 | getopts(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) { |