diff options
| author | Eric Andersen <andersen@codepoet.org> | 2004-03-16 05:14:10 +0000 |
|---|---|---|
| committer | Eric Andersen <andersen@codepoet.org> | 2004-03-16 05:14:10 +0000 |
| commit | 16767e2377210fb7489ee4d7d79ad1850c7c932d (patch) | |
| tree | 60d41b5ef57193173d1eecd747a0ddb3130e90ea /shell | |
| parent | ca65ca7d450ae6cbc0702e6b10925ccaef982bb4 (diff) | |
| download | busybox-w32-16767e2377210fb7489ee4d7d79ad1850c7c932d.tar.gz busybox-w32-16767e2377210fb7489ee4d7d79ad1850c7c932d.tar.bz2 busybox-w32-16767e2377210fb7489ee4d7d79ad1850c7c932d.zip | |
Patch from vodz to fix the dynamic vars patch, which I should not
have checked in. Vladimir writes:
Your patch have many problem.
1. You always added + time(). This cannot reset RANDOM=value for debuging
with
replay sequential.
2. Hmm. I examine bash 2.04 source. This pseudorandom generator use low bits
of
counter value. You use high bits. This make bad pseudorandom values after
have
0-value. For example, if + time() do remove, your generator always return 0
after
first generate 0.
3. Memory leak per call. Use ash-unlike unecessary bb_strdup function.
4. Unsupport show last $RANDOM value for "set" and "export" command.
5. Bloat code. Busybox-unlike patch - added unstandart feature as default
hardcode.
Last patch attached.
Erik, why you apply Paul patch with have 5-th point problem? :(
Last patch have ash change xwrite() to fresh libbb/bb_full_write interfase
(haved loop after EINTR).
--w
vodz
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/Config.in | 11 | ||||
| -rw-r--r-- | shell/ash.c | 161 |
2 files changed, 97 insertions, 75 deletions
diff --git a/shell/Config.in b/shell/Config.in index bcb5e719b..34baaa45c 100644 --- a/shell/Config.in +++ b/shell/Config.in | |||
| @@ -97,6 +97,17 @@ config CONFIG_ASH_OPTIMIZE_FOR_SIZE | |||
| 97 | help | 97 | help |
| 98 | Compile ash for reduced size at price of speed. | 98 | Compile ash for reduced size at price of speed. |
| 99 | 99 | ||
| 100 | config CONFIG_ASH_RANDOM_SUPPORT | ||
| 101 | bool " Enable pseudorandom generator and variable $RANDOM" | ||
| 102 | default n | ||
| 103 | depends on CONFIG_ASH | ||
| 104 | help | ||
| 105 | Enable pseudorandom generator and dynamic variable "$RANDOM". | ||
| 106 | Each read of "$RANDOM" will generate a new pseudorandom value. | ||
| 107 | You can reset the generator by using a specified start value. | ||
| 108 | After "unset RANDOM" then generator will switch off and this | ||
| 109 | variable will no longer have special treatment. | ||
| 110 | |||
| 100 | config CONFIG_HUSH | 111 | config CONFIG_HUSH |
| 101 | bool "hush" | 112 | bool "hush" |
| 102 | default n | 113 | default n |
diff --git a/shell/ash.c b/shell/ash.c index 060860c07..5072528f4 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -33,12 +33,14 @@ | |||
| 33 | * rewrite arith.y to micro stack based cryptic algorithm by | 33 | * rewrite arith.y to micro stack based cryptic algorithm by |
| 34 | * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com> | 34 | * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com> |
| 35 | * | 35 | * |
| 36 | * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2003 to be | ||
| 37 | * used in busybox and size optimizations, | ||
| 38 | * support locale, rewrited arith (see notes to this) | ||
| 39 | * | ||
| 40 | * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support | 36 | * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support |
| 41 | * dynamic variables. | 37 | * dynamic variables. |
| 38 | * | ||
| 39 | * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2004 to be | ||
| 40 | * used in busybox and size optimizations, | ||
| 41 | * rewrote arith (see notes to this), added locale support, | ||
| 42 | * rewrote dynamic variables. | ||
| 43 | * | ||
| 42 | */ | 44 | */ |
| 43 | 45 | ||
| 44 | 46 | ||
| @@ -1447,6 +1449,14 @@ static void unsetfunc(const char *); | |||
| 1447 | static int dash_arith(const char *); | 1449 | static int dash_arith(const char *); |
| 1448 | #endif | 1450 | #endif |
| 1449 | 1451 | ||
| 1452 | #ifdef CONFIG_ASH_RANDOM_SUPPORT | ||
| 1453 | static unsigned long rseed; | ||
| 1454 | static void change_random(const char *); | ||
| 1455 | # ifndef DYNAMIC_VAR | ||
| 1456 | # define DYNAMIC_VAR | ||
| 1457 | # endif | ||
| 1458 | #endif | ||
| 1459 | |||
| 1450 | /* $NetBSD: init.h,v 1.9 2002/11/24 22:35:40 christos Exp $ */ | 1460 | /* $NetBSD: init.h,v 1.9 2002/11/24 22:35:40 christos Exp $ */ |
| 1451 | 1461 | ||
| 1452 | static void reset(void); | 1462 | static void reset(void); |
| @@ -1467,19 +1477,18 @@ static void reset(void); | |||
| 1467 | #define VNOFUNC 0x40 /* don't call the callback function */ | 1477 | #define VNOFUNC 0x40 /* don't call the callback function */ |
| 1468 | #define VNOSET 0x80 /* do not set variable - just readonly test */ | 1478 | #define VNOSET 0x80 /* do not set variable - just readonly test */ |
| 1469 | #define VNOSAVE 0x100 /* when text is on the heap before setvareq */ | 1479 | #define VNOSAVE 0x100 /* when text is on the heap before setvareq */ |
| 1470 | #define VDYNAMIC 0x200 /* dynamic variable */ | 1480 | #ifdef DYNAMIC_VAR |
| 1471 | 1481 | # define VDYNAMIC 0x200 /* dynamic variable */ | |
| 1482 | # else | ||
| 1483 | # define VDYNAMIC 0 | ||
| 1484 | #endif | ||
| 1472 | 1485 | ||
| 1473 | struct var { | 1486 | struct var { |
| 1474 | struct var *next; /* next entry in hash list */ | 1487 | struct var *next; /* next entry in hash list */ |
| 1475 | int flags; /* flags are defined above */ | 1488 | int flags; /* flags are defined above */ |
| 1476 | const char *text; /* name=value */ | 1489 | const char *text; /* name=value */ |
| 1477 | void (*func)(const char *); | 1490 | void (*func)(const char *); /* function to be called when */ |
| 1478 | /* function to be called when */ | ||
| 1479 | /* the variable gets set/unset */ | 1491 | /* the variable gets set/unset */ |
| 1480 | char *(*lookup_func)(const char *); | ||
| 1481 | /* function to be called when */ | ||
| 1482 | /* the variable is read (if dynamic) */ | ||
| 1483 | }; | 1492 | }; |
| 1484 | 1493 | ||
| 1485 | struct localvar { | 1494 | struct localvar { |
| @@ -1506,8 +1515,6 @@ static void change_lc_all(const char *value); | |||
| 1506 | static void change_lc_ctype(const char *value); | 1515 | static void change_lc_ctype(const char *value); |
| 1507 | #endif | 1516 | #endif |
| 1508 | 1517 | ||
| 1509 | static char *get_random(const char *); | ||
| 1510 | static void change_random(const char *); | ||
| 1511 | 1518 | ||
| 1512 | #define VTABSIZE 39 | 1519 | #define VTABSIZE 39 |
| 1513 | 1520 | ||
| @@ -1522,32 +1529,33 @@ static const char defifs[] = " \t\n"; | |||
| 1522 | 1529 | ||
| 1523 | static struct var varinit[] = { | 1530 | static struct var varinit[] = { |
| 1524 | #ifdef IFS_BROKEN | 1531 | #ifdef IFS_BROKEN |
| 1525 | { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0, 0 }, | 1532 | { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 }, |
| 1526 | #else | 1533 | #else |
| 1527 | { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0, 0 }, | 1534 | { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 }, |
| 1528 | #endif | 1535 | #endif |
| 1529 | 1536 | ||
| 1530 | #ifdef CONFIG_ASH_MAIL | 1537 | #ifdef CONFIG_ASH_MAIL |
| 1531 | { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail, 0 }, | 1538 | { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail }, |
| 1532 | { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail, 0 }, | 1539 | { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail }, |
| 1533 | #endif | 1540 | #endif |
| 1534 | 1541 | ||
| 1535 | { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath, 0 }, | 1542 | { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath }, |
| 1536 | { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0, 0 }, | 1543 | { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 }, |
| 1537 | { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0, 0 }, | 1544 | { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 }, |
| 1538 | { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0, 0 }, | 1545 | { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 }, |
| 1539 | #ifdef CONFIG_ASH_GETOPTS | 1546 | #ifdef CONFIG_ASH_GETOPTS |
| 1540 | { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset, 0 }, | 1547 | { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset }, |
| 1548 | #endif | ||
| 1549 | #ifdef CONFIG_ASH_RANDOM_SUPPORT | ||
| 1550 | {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random }, | ||
| 1541 | #endif | 1551 | #endif |
| 1542 | #ifdef CONFIG_LOCALE_SUPPORT | 1552 | #ifdef CONFIG_LOCALE_SUPPORT |
| 1543 | {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL=", change_lc_all, 0}, | 1553 | {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all }, |
| 1544 | {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE=", change_lc_ctype, 0}, | 1554 | {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype }, |
| 1545 | #endif | 1555 | #endif |
| 1546 | #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY | 1556 | #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY |
| 1547 | {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE=", NULL, 0}, | 1557 | {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL }, |
| 1548 | #endif | 1558 | #endif |
| 1549 | {0, VSTRFIXED | VTEXTFIXED | VUNSET | VDYNAMIC, "RANDOM\0", | ||
| 1550 | change_random, get_random}, | ||
| 1551 | }; | 1559 | }; |
| 1552 | 1560 | ||
| 1553 | #define vifs varinit[0] | 1561 | #define vifs varinit[0] |
| @@ -1562,7 +1570,11 @@ static struct var varinit[] = { | |||
| 1562 | #define vps2 (&vps1)[1] | 1570 | #define vps2 (&vps1)[1] |
| 1563 | #define vps4 (&vps2)[1] | 1571 | #define vps4 (&vps2)[1] |
| 1564 | #define voptind (&vps4)[1] | 1572 | #define voptind (&vps4)[1] |
| 1565 | 1573 | #ifdef CONFIG_ASH_GETOPTS | |
| 1574 | #define vrandom (&voptind)[1] | ||
| 1575 | #else | ||
| 1576 | #define vrandom (&vps4)[1] | ||
| 1577 | #endif | ||
| 1566 | #define defpath (defpathvar + 5) | 1578 | #define defpath (defpathvar + 5) |
| 1567 | 1579 | ||
| 1568 | /* | 1580 | /* |
| @@ -1630,12 +1642,11 @@ extern char **environ; | |||
| 1630 | static void outstr(const char *, FILE *); | 1642 | static void outstr(const char *, FILE *); |
| 1631 | static void outcslow(int, FILE *); | 1643 | static void outcslow(int, FILE *); |
| 1632 | static void flushall(void); | 1644 | static void flushall(void); |
| 1633 | static void flushout(FILE *); | 1645 | static void flusherr(void); |
| 1634 | static int out1fmt(const char *, ...) | 1646 | static int out1fmt(const char *, ...) |
| 1635 | __attribute__((__format__(__printf__,1,2))); | 1647 | __attribute__((__format__(__printf__,1,2))); |
| 1636 | static int fmtstr(char *, size_t, const char *, ...) | 1648 | static int fmtstr(char *, size_t, const char *, ...) |
| 1637 | __attribute__((__format__(__printf__,3,4))); | 1649 | __attribute__((__format__(__printf__,3,4))); |
| 1638 | static void xwrite(int, const void *, size_t); | ||
| 1639 | 1650 | ||
| 1640 | static int preverrout_fd; /* save fd2 before print debug if xflag is set. */ | 1651 | static int preverrout_fd; /* save fd2 before print debug if xflag is set. */ |
| 1641 | 1652 | ||
| @@ -1648,7 +1659,7 @@ static void out1str(const char *p) | |||
| 1648 | static void out2str(const char *p) | 1659 | static void out2str(const char *p) |
| 1649 | { | 1660 | { |
| 1650 | outstr(p, stderr); | 1661 | outstr(p, stderr); |
| 1651 | flushout(stderr); | 1662 | flusherr(); |
| 1652 | } | 1663 | } |
| 1653 | 1664 | ||
| 1654 | /* | 1665 | /* |
| @@ -3287,7 +3298,7 @@ evalcommand(union node *cmd, int flags) | |||
| 3287 | } | 3298 | } |
| 3288 | sp = arglist.list; | 3299 | sp = arglist.list; |
| 3289 | } | 3300 | } |
| 3290 | xwrite(preverrout_fd, "\n", 1); | 3301 | bb_full_write(preverrout_fd, "\n", 1); |
| 3291 | } | 3302 | } |
| 3292 | 3303 | ||
| 3293 | cmd_is_exec = 0; | 3304 | cmd_is_exec = 0; |
| @@ -3304,7 +3315,7 @@ evalcommand(union node *cmd, int flags) | |||
| 3304 | find_command(argv[0], &cmdentry, cmd_flag, path); | 3315 | find_command(argv[0], &cmdentry, cmd_flag, path); |
| 3305 | if (cmdentry.cmdtype == CMDUNKNOWN) { | 3316 | if (cmdentry.cmdtype == CMDUNKNOWN) { |
| 3306 | status = 127; | 3317 | status = 127; |
| 3307 | flushout(stderr); | 3318 | flusherr(); |
| 3308 | goto bail; | 3319 | goto bail; |
| 3309 | } | 3320 | } |
| 3310 | 3321 | ||
| @@ -4571,7 +4582,7 @@ expandhere(union node *arg, int fd) | |||
| 4571 | { | 4582 | { |
| 4572 | herefd = fd; | 4583 | herefd = fd; |
| 4573 | expandarg(arg, (struct arglist *)NULL, 0); | 4584 | expandarg(arg, (struct arglist *)NULL, 0); |
| 4574 | xwrite(fd, stackblock(), expdest - (char *)stackblock()); | 4585 | bb_full_write(fd, stackblock(), expdest - (char *)stackblock()); |
| 4575 | } | 4586 | } |
| 4576 | 4587 | ||
| 4577 | 4588 | ||
| @@ -7905,6 +7916,10 @@ ash_main(int argc, char **argv) | |||
| 7905 | trputs("Shell args: "); trargs(argv); | 7916 | trputs("Shell args: "); trargs(argv); |
| 7906 | #endif | 7917 | #endif |
| 7907 | rootpid = getpid(); | 7918 | rootpid = getpid(); |
| 7919 | |||
| 7920 | #ifdef CONFIG_ASH_RANDOM_SUPPORT | ||
| 7921 | rseed = rootpid + ((time_t)time((time_t *)0)); | ||
| 7922 | #endif | ||
| 7908 | rootshell = 1; | 7923 | rootshell = 1; |
| 7909 | init(); | 7924 | init(); |
| 7910 | setstackmark(&smark); | 7925 | setstackmark(&smark); |
| @@ -8365,7 +8380,7 @@ growstackstr(void) | |||
| 8365 | { | 8380 | { |
| 8366 | size_t len = stackblocksize(); | 8381 | size_t len = stackblocksize(); |
| 8367 | if (herefd >= 0 && len >= 1024) { | 8382 | if (herefd >= 0 && len >= 1024) { |
| 8368 | xwrite(herefd, stackblock(), len); | 8383 | bb_full_write(herefd, stackblock(), len); |
| 8369 | return stackblock(); | 8384 | return stackblock(); |
| 8370 | } | 8385 | } |
| 8371 | growstackblock(); | 8386 | growstackblock(); |
| @@ -9030,21 +9045,26 @@ static void change_lc_ctype(const char *value) | |||
| 9030 | 9045 | ||
| 9031 | #endif | 9046 | #endif |
| 9032 | 9047 | ||
| 9048 | #ifdef CONFIG_ASH_RANDOM_SUPPORT | ||
| 9033 | /* Roughly copied from bash.. */ | 9049 | /* 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) | 9050 | static void change_random(const char *value) |
| 9045 | { | 9051 | { |
| 9046 | rseed = strtoul(value, (char **)NULL, 10); | 9052 | if(value == NULL) { |
| 9053 | /* "get", generate */ | ||
| 9054 | char buf[16]; | ||
| 9055 | |||
| 9056 | rseed = rseed * 1103515245 + 12345; | ||
| 9057 | sprintf(buf, "%d", (unsigned int)((rseed & 32767))); | ||
| 9058 | /* set without recursion */ | ||
| 9059 | setvar(vrandom.text, buf, VNOFUNC); | ||
| 9060 | vrandom.flags &= ~VNOFUNC; | ||
| 9061 | } else { | ||
| 9062 | /* set/reset */ | ||
| 9063 | rseed = strtoul(value, (char **)NULL, 10); | ||
| 9064 | } | ||
| 9047 | } | 9065 | } |
| 9066 | #endif | ||
| 9067 | |||
| 9048 | 9068 | ||
| 9049 | #ifdef CONFIG_ASH_GETOPTS | 9069 | #ifdef CONFIG_ASH_GETOPTS |
| 9050 | static int | 9070 | static int |
| @@ -9234,10 +9254,10 @@ flushall(void) | |||
| 9234 | } | 9254 | } |
| 9235 | 9255 | ||
| 9236 | void | 9256 | void |
| 9237 | flushout(FILE *dest) | 9257 | flusherr(void) |
| 9238 | { | 9258 | { |
| 9239 | INTOFF; | 9259 | INTOFF; |
| 9240 | fflush(dest); | 9260 | fflush(stderr); |
| 9241 | INTON; | 9261 | INTON; |
| 9242 | } | 9262 | } |
| 9243 | 9263 | ||
| @@ -9281,20 +9301,6 @@ fmtstr(char *outbuf, size_t length, const char *fmt, ...) | |||
| 9281 | } | 9301 | } |
| 9282 | 9302 | ||
| 9283 | 9303 | ||
| 9284 | /* | ||
| 9285 | * Version of write which resumes after a signal is caught. | ||
| 9286 | */ | ||
| 9287 | |||
| 9288 | static void | ||
| 9289 | xwrite(int fd, const void *p, size_t n) | ||
| 9290 | { | ||
| 9291 | ssize_t i; | ||
| 9292 | |||
| 9293 | do { | ||
| 9294 | i = bb_full_write(fd, p, n); | ||
| 9295 | } while (i < 0 && errno == EINTR); | ||
| 9296 | } | ||
| 9297 | |||
| 9298 | 9304 | ||
| 9299 | /* $NetBSD: parser.c,v 1.54 2002/11/24 22:35:42 christos Exp $ */ | 9305 | /* $NetBSD: parser.c,v 1.54 2002/11/24 22:35:42 christos Exp $ */ |
| 9300 | 9306 | ||
| @@ -10951,7 +10957,7 @@ openhere(union node *redir) | |||
| 10951 | if (redir->type == NHERE) { | 10957 | if (redir->type == NHERE) { |
| 10952 | len = strlen(redir->nhere.doc->narg.text); | 10958 | len = strlen(redir->nhere.doc->narg.text); |
| 10953 | if (len <= PIPESIZE) { | 10959 | if (len <= PIPESIZE) { |
| 10954 | xwrite(pip[1], redir->nhere.doc->narg.text, len); | 10960 | bb_full_write(pip[1], redir->nhere.doc->narg.text, len); |
| 10955 | goto out; | 10961 | goto out; |
| 10956 | } | 10962 | } |
| 10957 | } | 10963 | } |
| @@ -10965,7 +10971,7 @@ openhere(union node *redir) | |||
| 10965 | #endif | 10971 | #endif |
| 10966 | signal(SIGPIPE, SIG_DFL); | 10972 | signal(SIGPIPE, SIG_DFL); |
| 10967 | if (redir->type == NHERE) | 10973 | if (redir->type == NHERE) |
| 10968 | xwrite(pip[1], redir->nhere.doc->narg.text, len); | 10974 | bb_full_write(pip[1], redir->nhere.doc->narg.text, len); |
| 10969 | else | 10975 | else |
| 10970 | expandhere(redir->nhere.doc, pip[1]); | 10976 | expandhere(redir->nhere.doc, pip[1]); |
| 10971 | _exit(0); | 10977 | _exit(0); |
| @@ -11998,10 +12004,13 @@ setvareq(char *s, int flags) | |||
| 11998 | flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1)); | 12004 | flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1)); |
| 11999 | vp = *findvar(vpp, s); | 12005 | vp = *findvar(vpp, s); |
| 12000 | if (vp) { | 12006 | if (vp) { |
| 12001 | if (vp->flags & VREADONLY) { | 12007 | if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) { |
| 12008 | const char *n; | ||
| 12009 | |||
| 12002 | if (flags & VNOSAVE) | 12010 | if (flags & VNOSAVE) |
| 12003 | free(s); | 12011 | free(s); |
| 12004 | error("%.*s: is read only", strchrnul(s, '=') - s, s); | 12012 | n = vp->text; |
| 12013 | error("%.*s: is read only", strchrnul(n, '=') - n, n); | ||
| 12005 | } | 12014 | } |
| 12006 | 12015 | ||
| 12007 | if (flags & VNOSET) | 12016 | if (flags & VNOSET) |
| @@ -12058,19 +12067,20 @@ lookupvar(const char *name) | |||
| 12058 | { | 12067 | { |
| 12059 | struct var *v; | 12068 | struct var *v; |
| 12060 | 12069 | ||
| 12061 | if ((v = *findvar(hashvar(name), name)) && !(v->flags & (VUNSET|VDYNAMIC))) { | 12070 | if ((v = *findvar(hashvar(name), name))) { |
| 12062 | return strchrnul(v->text, '=') + 1; | 12071 | #ifdef DYNAMIC_VAR |
| 12063 | } | ||
| 12064 | |||
| 12065 | /* | 12072 | /* |
| 12066 | * Dynamic variables are implemented roughly the same way they are | 12073 | * Dynamic variables are implemented roughly the same way they are |
| 12067 | * in bash. Namely, they're "special" so long as they aren't unset. | 12074 | * 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 | 12075 | * As soon as they're unset, they're no longer dynamic, and dynamic |
| 12069 | * lookup will no longer happen at that point. -- PFM. | 12076 | * lookup will no longer happen at that point. -- PFM. |
| 12070 | */ | 12077 | */ |
| 12071 | if (v && ((v->flags & VDYNAMIC))) | 12078 | if((v->flags & VDYNAMIC)) |
| 12072 | if (v->lookup_func) | 12079 | (*v->func)(NULL); |
| 12073 | return v->lookup_func(name); | 12080 | #endif |
| 12081 | if(!(v->flags & VUNSET)) | ||
| 12082 | return strchrnul(v->text, '=') + 1; | ||
| 12083 | } | ||
| 12074 | 12084 | ||
| 12075 | return NULL; | 12085 | return NULL; |
| 12076 | } | 12086 | } |
| @@ -12346,8 +12356,9 @@ unsetvar(const char *s) | |||
| 12346 | retval = 1; | 12356 | retval = 1; |
| 12347 | if (flags & VREADONLY) | 12357 | if (flags & VREADONLY) |
| 12348 | goto out; | 12358 | goto out; |
| 12349 | if (flags & VDYNAMIC) | 12359 | #ifdef DYNAMIC_VAR |
| 12350 | vp->flags &= ~VDYNAMIC; | 12360 | vp->flags &= ~VDYNAMIC; |
| 12361 | #endif | ||
| 12351 | if (flags & VUNSET) | 12362 | if (flags & VUNSET) |
| 12352 | goto ok; | 12363 | goto ok; |
| 12353 | if ((flags & VSTRFIXED) == 0) { | 12364 | if ((flags & VSTRFIXED) == 0) { |
