diff options
Diffstat (limited to 'shell')
| -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) { |
