aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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) {