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
This commit is contained in:
parent
ca65ca7d45
commit
16767e2377
@ -97,6 +97,17 @@ config CONFIG_ASH_OPTIMIZE_FOR_SIZE
|
|||||||
help
|
help
|
||||||
Compile ash for reduced size at price of speed.
|
Compile ash for reduced size at price of speed.
|
||||||
|
|
||||||
|
config CONFIG_ASH_RANDOM_SUPPORT
|
||||||
|
bool " Enable pseudorandom generator and variable $RANDOM"
|
||||||
|
default n
|
||||||
|
depends on CONFIG_ASH
|
||||||
|
help
|
||||||
|
Enable pseudorandom generator and dynamic variable "$RANDOM".
|
||||||
|
Each read of "$RANDOM" will generate a new pseudorandom value.
|
||||||
|
You can reset the generator by using a specified start value.
|
||||||
|
After "unset RANDOM" then generator will switch off and this
|
||||||
|
variable will no longer have special treatment.
|
||||||
|
|
||||||
config CONFIG_HUSH
|
config CONFIG_HUSH
|
||||||
bool "hush"
|
bool "hush"
|
||||||
default n
|
default n
|
||||||
|
161
shell/ash.c
161
shell/ash.c
@ -33,12 +33,14 @@
|
|||||||
* rewrite arith.y to micro stack based cryptic algorithm by
|
* rewrite arith.y to micro stack based cryptic algorithm by
|
||||||
* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
|
* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
|
||||||
*
|
*
|
||||||
* Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2003 to be
|
|
||||||
* used in busybox and size optimizations,
|
|
||||||
* support locale, rewrited arith (see notes to this)
|
|
||||||
*
|
|
||||||
* Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
|
* Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
|
||||||
* dynamic variables.
|
* dynamic variables.
|
||||||
|
*
|
||||||
|
* Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2004 to be
|
||||||
|
* used in busybox and size optimizations,
|
||||||
|
* rewrote arith (see notes to this), added locale support,
|
||||||
|
* rewrote dynamic variables.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -1447,6 +1449,14 @@ static void unsetfunc(const char *);
|
|||||||
static int dash_arith(const char *);
|
static int dash_arith(const char *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ASH_RANDOM_SUPPORT
|
||||||
|
static unsigned long rseed;
|
||||||
|
static void change_random(const char *);
|
||||||
|
# ifndef DYNAMIC_VAR
|
||||||
|
# define DYNAMIC_VAR
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* $NetBSD: init.h,v 1.9 2002/11/24 22:35:40 christos Exp $ */
|
/* $NetBSD: init.h,v 1.9 2002/11/24 22:35:40 christos Exp $ */
|
||||||
|
|
||||||
static void reset(void);
|
static void reset(void);
|
||||||
@ -1467,19 +1477,18 @@ static void reset(void);
|
|||||||
#define VNOFUNC 0x40 /* don't call the callback function */
|
#define VNOFUNC 0x40 /* don't call the callback function */
|
||||||
#define VNOSET 0x80 /* do not set variable - just readonly test */
|
#define VNOSET 0x80 /* do not set variable - just readonly test */
|
||||||
#define VNOSAVE 0x100 /* when text is on the heap before setvareq */
|
#define VNOSAVE 0x100 /* when text is on the heap before setvareq */
|
||||||
#define VDYNAMIC 0x200 /* dynamic variable */
|
#ifdef DYNAMIC_VAR
|
||||||
|
# define VDYNAMIC 0x200 /* dynamic variable */
|
||||||
|
# else
|
||||||
|
# define VDYNAMIC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
struct var {
|
struct var {
|
||||||
struct var *next; /* next entry in hash list */
|
struct var *next; /* next entry in hash list */
|
||||||
int flags; /* flags are defined above */
|
int flags; /* flags are defined above */
|
||||||
const char *text; /* name=value */
|
const char *text; /* name=value */
|
||||||
void (*func)(const char *);
|
void (*func)(const char *); /* function to be called when */
|
||||||
/* function to be called when */
|
|
||||||
/* the variable gets set/unset */
|
/* the variable gets set/unset */
|
||||||
char *(*lookup_func)(const char *);
|
|
||||||
/* function to be called when */
|
|
||||||
/* the variable is read (if dynamic) */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct localvar {
|
struct localvar {
|
||||||
@ -1506,8 +1515,6 @@ static void change_lc_all(const char *value);
|
|||||||
static void change_lc_ctype(const char *value);
|
static void change_lc_ctype(const char *value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char *get_random(const char *);
|
|
||||||
static void change_random(const char *);
|
|
||||||
|
|
||||||
#define VTABSIZE 39
|
#define VTABSIZE 39
|
||||||
|
|
||||||
@ -1522,32 +1529,33 @@ static const char defifs[] = " \t\n";
|
|||||||
|
|
||||||
static struct var varinit[] = {
|
static struct var varinit[] = {
|
||||||
#ifdef IFS_BROKEN
|
#ifdef IFS_BROKEN
|
||||||
{ 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0, 0 },
|
{ 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
|
||||||
#else
|
#else
|
||||||
{ 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0, 0 },
|
{ 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ASH_MAIL
|
#ifdef CONFIG_ASH_MAIL
|
||||||
{ 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail, 0 },
|
{ 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
|
||||||
{ 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail, 0 },
|
{ 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath, 0 },
|
{ 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
|
||||||
{ 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0, 0 },
|
{ 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
|
||||||
{ 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0, 0 },
|
{ 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
|
||||||
{ 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0, 0 },
|
{ 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
|
||||||
#ifdef CONFIG_ASH_GETOPTS
|
#ifdef CONFIG_ASH_GETOPTS
|
||||||
{ 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset, 0 },
|
{ 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_ASH_RANDOM_SUPPORT
|
||||||
|
{0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_LOCALE_SUPPORT
|
#ifdef CONFIG_LOCALE_SUPPORT
|
||||||
{0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL=", change_lc_all, 0},
|
{0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
|
||||||
{0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE=", change_lc_ctype, 0},
|
{0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
|
#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
|
||||||
{0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE=", NULL, 0},
|
{0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
|
||||||
#endif
|
#endif
|
||||||
{0, VSTRFIXED | VTEXTFIXED | VUNSET | VDYNAMIC, "RANDOM\0",
|
|
||||||
change_random, get_random},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define vifs varinit[0]
|
#define vifs varinit[0]
|
||||||
@ -1562,7 +1570,11 @@ static struct var varinit[] = {
|
|||||||
#define vps2 (&vps1)[1]
|
#define vps2 (&vps1)[1]
|
||||||
#define vps4 (&vps2)[1]
|
#define vps4 (&vps2)[1]
|
||||||
#define voptind (&vps4)[1]
|
#define voptind (&vps4)[1]
|
||||||
|
#ifdef CONFIG_ASH_GETOPTS
|
||||||
|
#define vrandom (&voptind)[1]
|
||||||
|
#else
|
||||||
|
#define vrandom (&vps4)[1]
|
||||||
|
#endif
|
||||||
#define defpath (defpathvar + 5)
|
#define defpath (defpathvar + 5)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1630,12 +1642,11 @@ extern char **environ;
|
|||||||
static void outstr(const char *, FILE *);
|
static void outstr(const char *, FILE *);
|
||||||
static void outcslow(int, FILE *);
|
static void outcslow(int, FILE *);
|
||||||
static void flushall(void);
|
static void flushall(void);
|
||||||
static void flushout(FILE *);
|
static void flusherr(void);
|
||||||
static int out1fmt(const char *, ...)
|
static int out1fmt(const char *, ...)
|
||||||
__attribute__((__format__(__printf__,1,2)));
|
__attribute__((__format__(__printf__,1,2)));
|
||||||
static int fmtstr(char *, size_t, const char *, ...)
|
static int fmtstr(char *, size_t, const char *, ...)
|
||||||
__attribute__((__format__(__printf__,3,4)));
|
__attribute__((__format__(__printf__,3,4)));
|
||||||
static void xwrite(int, const void *, size_t);
|
|
||||||
|
|
||||||
static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
|
static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
|
||||||
|
|
||||||
@ -1648,7 +1659,7 @@ static void out1str(const char *p)
|
|||||||
static void out2str(const char *p)
|
static void out2str(const char *p)
|
||||||
{
|
{
|
||||||
outstr(p, stderr);
|
outstr(p, stderr);
|
||||||
flushout(stderr);
|
flusherr();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3287,7 +3298,7 @@ evalcommand(union node *cmd, int flags)
|
|||||||
}
|
}
|
||||||
sp = arglist.list;
|
sp = arglist.list;
|
||||||
}
|
}
|
||||||
xwrite(preverrout_fd, "\n", 1);
|
bb_full_write(preverrout_fd, "\n", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_is_exec = 0;
|
cmd_is_exec = 0;
|
||||||
@ -3304,7 +3315,7 @@ evalcommand(union node *cmd, int flags)
|
|||||||
find_command(argv[0], &cmdentry, cmd_flag, path);
|
find_command(argv[0], &cmdentry, cmd_flag, path);
|
||||||
if (cmdentry.cmdtype == CMDUNKNOWN) {
|
if (cmdentry.cmdtype == CMDUNKNOWN) {
|
||||||
status = 127;
|
status = 127;
|
||||||
flushout(stderr);
|
flusherr();
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4571,7 +4582,7 @@ expandhere(union node *arg, int fd)
|
|||||||
{
|
{
|
||||||
herefd = fd;
|
herefd = fd;
|
||||||
expandarg(arg, (struct arglist *)NULL, 0);
|
expandarg(arg, (struct arglist *)NULL, 0);
|
||||||
xwrite(fd, stackblock(), expdest - (char *)stackblock());
|
bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7905,6 +7916,10 @@ ash_main(int argc, char **argv)
|
|||||||
trputs("Shell args: "); trargs(argv);
|
trputs("Shell args: "); trargs(argv);
|
||||||
#endif
|
#endif
|
||||||
rootpid = getpid();
|
rootpid = getpid();
|
||||||
|
|
||||||
|
#ifdef CONFIG_ASH_RANDOM_SUPPORT
|
||||||
|
rseed = rootpid + ((time_t)time((time_t *)0));
|
||||||
|
#endif
|
||||||
rootshell = 1;
|
rootshell = 1;
|
||||||
init();
|
init();
|
||||||
setstackmark(&smark);
|
setstackmark(&smark);
|
||||||
@ -8365,7 +8380,7 @@ growstackstr(void)
|
|||||||
{
|
{
|
||||||
size_t len = stackblocksize();
|
size_t len = stackblocksize();
|
||||||
if (herefd >= 0 && len >= 1024) {
|
if (herefd >= 0 && len >= 1024) {
|
||||||
xwrite(herefd, stackblock(), len);
|
bb_full_write(herefd, stackblock(), len);
|
||||||
return stackblock();
|
return stackblock();
|
||||||
}
|
}
|
||||||
growstackblock();
|
growstackblock();
|
||||||
@ -9030,21 +9045,26 @@ static void change_lc_ctype(const char *value)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ASH_RANDOM_SUPPORT
|
||||||
/* Roughly copied from bash.. */
|
/* Roughly copied from bash.. */
|
||||||
static unsigned long rseed = 1;
|
|
||||||
static char *get_random(const char *var)
|
|
||||||
{
|
|
||||||
char buf[255];
|
|
||||||
rseed = (rseed + getpid() + ((time_t)time((time_t *)0)));
|
|
||||||
rseed = rseed * 1103515245 + 12345;
|
|
||||||
sprintf(buf, "%d", (unsigned int)((rseed >> 16 & 32767)));
|
|
||||||
return bb_xstrdup(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void change_random(const char *value)
|
static void change_random(const char *value)
|
||||||
{
|
{
|
||||||
rseed = strtoul(value, (char **)NULL, 10);
|
if(value == NULL) {
|
||||||
|
/* "get", generate */
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
|
rseed = rseed * 1103515245 + 12345;
|
||||||
|
sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
|
||||||
|
/* set without recursion */
|
||||||
|
setvar(vrandom.text, buf, VNOFUNC);
|
||||||
|
vrandom.flags &= ~VNOFUNC;
|
||||||
|
} else {
|
||||||
|
/* set/reset */
|
||||||
|
rseed = strtoul(value, (char **)NULL, 10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_ASH_GETOPTS
|
#ifdef CONFIG_ASH_GETOPTS
|
||||||
static int
|
static int
|
||||||
@ -9234,10 +9254,10 @@ flushall(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
flushout(FILE *dest)
|
flusherr(void)
|
||||||
{
|
{
|
||||||
INTOFF;
|
INTOFF;
|
||||||
fflush(dest);
|
fflush(stderr);
|
||||||
INTON;
|
INTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9281,20 +9301,6 @@ fmtstr(char *outbuf, size_t length, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Version of write which resumes after a signal is caught.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
xwrite(int fd, const void *p, size_t n)
|
|
||||||
{
|
|
||||||
ssize_t i;
|
|
||||||
|
|
||||||
do {
|
|
||||||
i = bb_full_write(fd, p, n);
|
|
||||||
} while (i < 0 && errno == EINTR);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* $NetBSD: parser.c,v 1.54 2002/11/24 22:35:42 christos Exp $ */
|
/* $NetBSD: parser.c,v 1.54 2002/11/24 22:35:42 christos Exp $ */
|
||||||
|
|
||||||
@ -10951,7 +10957,7 @@ openhere(union node *redir)
|
|||||||
if (redir->type == NHERE) {
|
if (redir->type == NHERE) {
|
||||||
len = strlen(redir->nhere.doc->narg.text);
|
len = strlen(redir->nhere.doc->narg.text);
|
||||||
if (len <= PIPESIZE) {
|
if (len <= PIPESIZE) {
|
||||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10965,7 +10971,7 @@ openhere(union node *redir)
|
|||||||
#endif
|
#endif
|
||||||
signal(SIGPIPE, SIG_DFL);
|
signal(SIGPIPE, SIG_DFL);
|
||||||
if (redir->type == NHERE)
|
if (redir->type == NHERE)
|
||||||
xwrite(pip[1], redir->nhere.doc->narg.text, len);
|
bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
|
||||||
else
|
else
|
||||||
expandhere(redir->nhere.doc, pip[1]);
|
expandhere(redir->nhere.doc, pip[1]);
|
||||||
_exit(0);
|
_exit(0);
|
||||||
@ -11998,10 +12004,13 @@ setvareq(char *s, int flags)
|
|||||||
flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
|
flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
|
||||||
vp = *findvar(vpp, s);
|
vp = *findvar(vpp, s);
|
||||||
if (vp) {
|
if (vp) {
|
||||||
if (vp->flags & VREADONLY) {
|
if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
|
||||||
|
const char *n;
|
||||||
|
|
||||||
if (flags & VNOSAVE)
|
if (flags & VNOSAVE)
|
||||||
free(s);
|
free(s);
|
||||||
error("%.*s: is read only", strchrnul(s, '=') - s, s);
|
n = vp->text;
|
||||||
|
error("%.*s: is read only", strchrnul(n, '=') - n, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & VNOSET)
|
if (flags & VNOSET)
|
||||||
@ -12058,19 +12067,20 @@ lookupvar(const char *name)
|
|||||||
{
|
{
|
||||||
struct var *v;
|
struct var *v;
|
||||||
|
|
||||||
if ((v = *findvar(hashvar(name), name)) && !(v->flags & (VUNSET|VDYNAMIC))) {
|
if ((v = *findvar(hashvar(name), name))) {
|
||||||
return strchrnul(v->text, '=') + 1;
|
#ifdef DYNAMIC_VAR
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dynamic variables are implemented roughly the same way they are
|
* Dynamic variables are implemented roughly the same way they are
|
||||||
* in bash. Namely, they're "special" so long as they aren't unset.
|
* in bash. Namely, they're "special" so long as they aren't unset.
|
||||||
* As soon as they're unset, they're no longer dynamic, and dynamic
|
* As soon as they're unset, they're no longer dynamic, and dynamic
|
||||||
* lookup will no longer happen at that point. -- PFM.
|
* lookup will no longer happen at that point. -- PFM.
|
||||||
*/
|
*/
|
||||||
if (v && ((v->flags & VDYNAMIC)))
|
if((v->flags & VDYNAMIC))
|
||||||
if (v->lookup_func)
|
(*v->func)(NULL);
|
||||||
return v->lookup_func(name);
|
#endif
|
||||||
|
if(!(v->flags & VUNSET))
|
||||||
|
return strchrnul(v->text, '=') + 1;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -12346,8 +12356,9 @@ unsetvar(const char *s)
|
|||||||
retval = 1;
|
retval = 1;
|
||||||
if (flags & VREADONLY)
|
if (flags & VREADONLY)
|
||||||
goto out;
|
goto out;
|
||||||
if (flags & VDYNAMIC)
|
#ifdef DYNAMIC_VAR
|
||||||
vp->flags &= ~VDYNAMIC;
|
vp->flags &= ~VDYNAMIC;
|
||||||
|
#endif
|
||||||
if (flags & VUNSET)
|
if (flags & VUNSET)
|
||||||
goto ok;
|
goto ok;
|
||||||
if ((flags & VSTRFIXED) == 0) {
|
if ((flags & VSTRFIXED) == 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user