summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2004-03-16 05:14:10 +0000
committerEric Andersen <andersen@codepoet.org>2004-03-16 05:14:10 +0000
commit16767e2377210fb7489ee4d7d79ad1850c7c932d (patch)
tree60d41b5ef57193173d1eecd747a0ddb3130e90ea
parentca65ca7d450ae6cbc0702e6b10925ccaef982bb4 (diff)
downloadbusybox-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
-rw-r--r--shell/Config.in11
-rw-r--r--shell/ash.c161
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
100config 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
100config CONFIG_HUSH 111config 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 *);
1447static int dash_arith(const char *); 1449static int dash_arith(const char *);
1448#endif 1450#endif
1449 1451
1452#ifdef CONFIG_ASH_RANDOM_SUPPORT
1453static unsigned long rseed;
1454static 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
1452static void reset(void); 1462static 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
1473struct var { 1486struct 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
1485struct localvar { 1494struct localvar {
@@ -1506,8 +1515,6 @@ static void change_lc_all(const char *value);
1506static void change_lc_ctype(const char *value); 1515static void change_lc_ctype(const char *value);
1507#endif 1516#endif
1508 1517
1509static char *get_random(const char *);
1510static 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
1523static struct var varinit[] = { 1530static 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;
1630static void outstr(const char *, FILE *); 1642static void outstr(const char *, FILE *);
1631static void outcslow(int, FILE *); 1643static void outcslow(int, FILE *);
1632static void flushall(void); 1644static void flushall(void);
1633static void flushout(FILE *); 1645static void flusherr(void);
1634static int out1fmt(const char *, ...) 1646static int out1fmt(const char *, ...)
1635 __attribute__((__format__(__printf__,1,2))); 1647 __attribute__((__format__(__printf__,1,2)));
1636static int fmtstr(char *, size_t, const char *, ...) 1648static int fmtstr(char *, size_t, const char *, ...)
1637 __attribute__((__format__(__printf__,3,4))); 1649 __attribute__((__format__(__printf__,3,4)));
1638static void xwrite(int, const void *, size_t);
1639 1650
1640static int preverrout_fd; /* save fd2 before print debug if xflag is set. */ 1651static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1641 1652
@@ -1648,7 +1659,7 @@ static void out1str(const char *p)
1648static void out2str(const char *p) 1659static 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.. */
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) 9050static 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
9050static int 9070static int
@@ -9234,10 +9254,10 @@ flushall(void)
9234} 9254}
9235 9255
9236void 9256void
9237flushout(FILE *dest) 9257flusherr(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
9288static void
9289xwrite(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) {