diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-27 00:24:11 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-27 00:24:11 +0000 |
| commit | 448d30ee17aaab4faa0a927c5dcba1bc990a44db (patch) | |
| tree | 4ea9e11ff010892846bfe1b5ba26a35da7bb8798 /shell | |
| parent | 843cbd54d1703e54234a2496efc920f56cd3f318 (diff) | |
| download | busybox-w32-448d30ee17aaab4faa0a927c5dcba1bc990a44db.tar.gz busybox-w32-448d30ee17aaab4faa0a927c5dcba1bc990a44db.tar.bz2 busybox-w32-448d30ee17aaab4faa0a927c5dcba1bc990a44db.zip | |
ash: fix very weak $RANDOM generator; and move even more things
out of data/bss
text data bss dec hex filename
807935 611 6884 815430 c7146 busybox_old
808035 611 6868 815514 c719a busybox_unstripped
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 118 |
1 files changed, 66 insertions, 52 deletions
diff --git a/shell/ash.c b/shell/ash.c index 4a3d2d48e..8c99e30ef 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -201,6 +201,14 @@ struct globals_misc { | |||
| 201 | /* indicates specified signal received */ | 201 | /* indicates specified signal received */ |
| 202 | char gotsig[NSIG - 1]; | 202 | char gotsig[NSIG - 1]; |
| 203 | char *trap[NSIG]; | 203 | char *trap[NSIG]; |
| 204 | |||
| 205 | /* Rarely referenced stuff */ | ||
| 206 | #if ENABLE_ASH_RANDOM_SUPPORT | ||
| 207 | int32_t random_galois_LFSR; /* Galois LFSR (fast but weak) */ | ||
| 208 | uint32_t random_LCG; /* LCG1 (fast but weak) */ | ||
| 209 | #endif | ||
| 210 | pid_t backgndpid; /* pid of last background process */ | ||
| 211 | smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */ | ||
| 204 | }; | 212 | }; |
| 205 | extern struct globals_misc *const ash_ptr_to_globals_misc; | 213 | extern struct globals_misc *const ash_ptr_to_globals_misc; |
| 206 | #define G_misc (*ash_ptr_to_globals_misc) | 214 | #define G_misc (*ash_ptr_to_globals_misc) |
| @@ -216,12 +224,16 @@ extern struct globals_misc *const ash_ptr_to_globals_misc; | |||
| 216 | #define intpending (G_misc.intpending ) | 224 | #define intpending (G_misc.intpending ) |
| 217 | //#define exsig (G_misc.exsig ) | 225 | //#define exsig (G_misc.exsig ) |
| 218 | #define pendingsig (G_misc.pendingsig ) | 226 | #define pendingsig (G_misc.pendingsig ) |
| 219 | #define isloginsh (G_misc.isloginsh) | 227 | #define isloginsh (G_misc.isloginsh ) |
| 220 | #define nullstr (G_misc.nullstr ) | 228 | #define nullstr (G_misc.nullstr ) |
| 221 | #define optlist (G_misc.optlist ) | 229 | #define optlist (G_misc.optlist ) |
| 222 | #define sigmode (G_misc.sigmode ) | 230 | #define sigmode (G_misc.sigmode ) |
| 223 | #define gotsig (G_misc.gotsig ) | 231 | #define gotsig (G_misc.gotsig ) |
| 224 | #define trap (G_misc.trap ) | 232 | #define trap (G_misc.trap ) |
| 233 | #define random_galois_LFSR (G_misc.random_galois_LFSR) | ||
| 234 | #define random_LCG (G_misc.random_LCG ) | ||
| 235 | #define backgndpid (G_misc.backgndpid ) | ||
| 236 | #define job_warning (G_misc.job_warning) | ||
| 225 | #define INIT_G_misc() do { \ | 237 | #define INIT_G_misc() do { \ |
| 226 | (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \ | 238 | (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \ |
| 227 | barrier(); \ | 239 | barrier(); \ |
| @@ -1006,12 +1018,12 @@ struct parsefile { | |||
| 1006 | struct strpush basestrpush; /* so pushing one is fast */ | 1018 | struct strpush basestrpush; /* so pushing one is fast */ |
| 1007 | }; | 1019 | }; |
| 1008 | 1020 | ||
| 1009 | static struct parsefile basepf; /* top level input file */ | 1021 | static struct parsefile basepf; /* top level input file */ |
| 1010 | static struct parsefile *g_parsefile = &basepf; /* current input file */ | 1022 | static struct parsefile *g_parsefile = &basepf; /* current input file */ |
| 1011 | static int startlinno; /* line # where last token started */ | 1023 | static int startlinno; /* line # where last token started */ |
| 1012 | static char *commandname; /* currently executing command */ | 1024 | static char *commandname; /* currently executing command */ |
| 1013 | static struct strlist *cmdenviron; /* environment for builtin command */ | 1025 | static struct strlist *cmdenviron; /* environment for builtin command */ |
| 1014 | static int exitstatus; /* exit status of last command */ | 1026 | static uint8_t exitstatus; /* exit status of last command */ |
| 1015 | 1027 | ||
| 1016 | 1028 | ||
| 1017 | /* ============ Message printing */ | 1029 | /* ============ Message printing */ |
| @@ -1605,29 +1617,6 @@ nextopt(const char *optstring) | |||
| 1605 | } | 1617 | } |
| 1606 | 1618 | ||
| 1607 | 1619 | ||
| 1608 | /* ============ Math support definitions */ | ||
| 1609 | |||
| 1610 | #if ENABLE_ASH_MATH_SUPPORT_64 | ||
| 1611 | typedef int64_t arith_t; | ||
| 1612 | #define arith_t_type long long | ||
| 1613 | #else | ||
| 1614 | typedef long arith_t; | ||
| 1615 | #define arith_t_type long | ||
| 1616 | #endif | ||
| 1617 | |||
| 1618 | #if ENABLE_ASH_MATH_SUPPORT | ||
| 1619 | static arith_t dash_arith(const char *); | ||
| 1620 | static arith_t arith(const char *expr, int *perrcode); | ||
| 1621 | #endif | ||
| 1622 | |||
| 1623 | #if ENABLE_ASH_RANDOM_SUPPORT | ||
| 1624 | static unsigned long rseed; | ||
| 1625 | #ifndef DYNAMIC_VAR | ||
| 1626 | #define DYNAMIC_VAR | ||
| 1627 | #endif | ||
| 1628 | #endif | ||
| 1629 | |||
| 1630 | |||
| 1631 | /* ============ Shell variables */ | 1620 | /* ============ Shell variables */ |
| 1632 | 1621 | ||
| 1633 | /* | 1622 | /* |
| @@ -1694,7 +1683,7 @@ struct localvar { | |||
| 1694 | #define VNOFUNC 0x40 /* don't call the callback function */ | 1683 | #define VNOFUNC 0x40 /* don't call the callback function */ |
| 1695 | #define VNOSET 0x80 /* do not set variable - just readonly test */ | 1684 | #define VNOSET 0x80 /* do not set variable - just readonly test */ |
| 1696 | #define VNOSAVE 0x100 /* when text is on the heap before setvareq */ | 1685 | #define VNOSAVE 0x100 /* when text is on the heap before setvareq */ |
| 1697 | #ifdef DYNAMIC_VAR | 1686 | #if ENABLE_ASH_RANDOM_SUPPORT |
| 1698 | # define VDYNAMIC 0x200 /* dynamic variable */ | 1687 | # define VDYNAMIC 0x200 /* dynamic variable */ |
| 1699 | #else | 1688 | #else |
| 1700 | # define VDYNAMIC 0 | 1689 | # define VDYNAMIC 0 |
| @@ -1966,7 +1955,7 @@ lookupvar(const char *name) | |||
| 1966 | 1955 | ||
| 1967 | v = *findvar(hashvar(name), name); | 1956 | v = *findvar(hashvar(name), name); |
| 1968 | if (v) { | 1957 | if (v) { |
| 1969 | #ifdef DYNAMIC_VAR | 1958 | #if ENABLE_ASH_RANDOM_SUPPORT |
| 1970 | /* | 1959 | /* |
| 1971 | * Dynamic variables are implemented roughly the same way they are | 1960 | * Dynamic variables are implemented roughly the same way they are |
| 1972 | * in bash. Namely, they're "special" so long as they aren't unset. | 1961 | * in bash. Namely, they're "special" so long as they aren't unset. |
| @@ -2127,7 +2116,7 @@ unsetvar(const char *s) | |||
| 2127 | retval = 1; | 2116 | retval = 1; |
| 2128 | if (flags & VREADONLY) | 2117 | if (flags & VREADONLY) |
| 2129 | goto out; | 2118 | goto out; |
| 2130 | #ifdef DYNAMIC_VAR | 2119 | #if ENABLE_ASH_RANDOM_SUPPORT |
| 2131 | vp->flags &= ~VDYNAMIC; | 2120 | vp->flags &= ~VDYNAMIC; |
| 2132 | #endif | 2121 | #endif |
| 2133 | if (flags & VUNSET) | 2122 | if (flags & VUNSET) |
| @@ -3243,9 +3232,6 @@ struct job { | |||
| 3243 | struct job *prev_job; /* previous job */ | 3232 | struct job *prev_job; /* previous job */ |
| 3244 | }; | 3233 | }; |
| 3245 | 3234 | ||
| 3246 | static pid_t backgndpid; /* pid of last background process */ | ||
| 3247 | static smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */ | ||
| 3248 | |||
| 3249 | static struct job *makejob(/*union node *,*/ int); | 3235 | static struct job *makejob(/*union node *,*/ int); |
| 3250 | #if !JOBS | 3236 | #if !JOBS |
| 3251 | #define forkshell(job, node, mode) forkshell(job, mode) | 3237 | #define forkshell(job, node, mode) forkshell(job, mode) |
| @@ -3257,7 +3243,7 @@ static int waitforjob(struct job *); | |||
| 3257 | enum { doing_jobctl = 0 }; | 3243 | enum { doing_jobctl = 0 }; |
| 3258 | #define setjobctl(on) do {} while (0) | 3244 | #define setjobctl(on) do {} while (0) |
| 3259 | #else | 3245 | #else |
| 3260 | static smallint doing_jobctl; | 3246 | static smallint doing_jobctl; //references:8 |
| 3261 | static void setjobctl(int); | 3247 | static void setjobctl(int); |
| 3262 | #endif | 3248 | #endif |
| 3263 | 3249 | ||
| @@ -3356,17 +3342,17 @@ setsignal(int signo) | |||
| 3356 | 3342 | ||
| 3357 | #if JOBS | 3343 | #if JOBS |
| 3358 | /* pgrp of shell on invocation */ | 3344 | /* pgrp of shell on invocation */ |
| 3359 | static int initialpgrp; | 3345 | static int initialpgrp; //references:2 |
| 3360 | static int ttyfd = -1; | 3346 | static int ttyfd = -1; //5 |
| 3361 | #endif | 3347 | #endif |
| 3362 | /* array of jobs */ | 3348 | /* array of jobs */ |
| 3363 | static struct job *jobtab; | 3349 | static struct job *jobtab; //5 |
| 3364 | /* size of array */ | 3350 | /* size of array */ |
| 3365 | static unsigned njobs; | 3351 | static unsigned njobs; //4 |
| 3366 | /* current job */ | 3352 | /* current job */ |
| 3367 | static struct job *curjob; | 3353 | static struct job *curjob; //lots |
| 3368 | /* number of presumed living untracked jobs */ | 3354 | /* number of presumed living untracked jobs */ |
| 3369 | static int jobless; | 3355 | static int jobless; //4 |
| 3370 | 3356 | ||
| 3371 | static void | 3357 | static void |
| 3372 | set_curjob(struct job *jp, unsigned mode) | 3358 | set_curjob(struct job *jp, unsigned mode) |
| @@ -5041,6 +5027,19 @@ redirectsafe(union node *redir, int flags) | |||
| 5041 | * We have to deal with backquotes, shell variables, and file metacharacters. | 5027 | * We have to deal with backquotes, shell variables, and file metacharacters. |
| 5042 | */ | 5028 | */ |
| 5043 | 5029 | ||
| 5030 | #if ENABLE_ASH_MATH_SUPPORT_64 | ||
| 5031 | typedef int64_t arith_t; | ||
| 5032 | #define arith_t_type long long | ||
| 5033 | #else | ||
| 5034 | typedef long arith_t; | ||
| 5035 | #define arith_t_type long | ||
| 5036 | #endif | ||
| 5037 | |||
| 5038 | #if ENABLE_ASH_MATH_SUPPORT | ||
| 5039 | static arith_t dash_arith(const char *); | ||
| 5040 | static arith_t arith(const char *expr, int *perrcode); | ||
| 5041 | #endif | ||
| 5042 | |||
| 5044 | /* | 5043 | /* |
| 5045 | * expandarg flags | 5044 | * expandarg flags |
| 5046 | */ | 5045 | */ |
| @@ -5358,7 +5357,7 @@ struct backcmd { /* result of evalbackcmd */ | |||
| 5358 | }; | 5357 | }; |
| 5359 | 5358 | ||
| 5360 | /* These forward decls are needed to use "eval" code for backticks handling: */ | 5359 | /* These forward decls are needed to use "eval" code for backticks handling: */ |
| 5361 | static smalluint back_exitstatus; /* exit status of backquoted command */ | 5360 | static uint8_t back_exitstatus; /* exit status of backquoted command */ |
| 5362 | #define EV_EXIT 01 /* exit after evaluating tree */ | 5361 | #define EV_EXIT 01 /* exit after evaluating tree */ |
| 5363 | static void evaltree(union node *, int); | 5362 | static void evaltree(union node *, int); |
| 5364 | 5363 | ||
| @@ -9619,18 +9618,33 @@ setcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) | |||
| 9619 | static void | 9618 | static void |
| 9620 | change_random(const char *value) | 9619 | change_random(const char *value) |
| 9621 | { | 9620 | { |
| 9621 | /* Galois LFSR parameter */ | ||
| 9622 | /* Taps at 32 31 29 1: */ | ||
| 9623 | enum { MASK = 0x8000000b }; | ||
| 9624 | /* Another example - taps at 32 31 30 10: */ | ||
| 9625 | /* MASK = 0x00400007 */ | ||
| 9626 | |||
| 9622 | if (value == NULL) { | 9627 | if (value == NULL) { |
| 9623 | /* "get", generate */ | 9628 | /* "get", generate */ |
| 9624 | char buf[16]; | 9629 | uint32_t t; |
| 9625 | 9630 | ||
| 9626 | rseed = rseed * 1103515245 + 12345; | 9631 | /* LCG has period of 2^32 and alternating lowest bit */ |
| 9627 | sprintf(buf, "%d", (unsigned int)((rseed & 32767))); | 9632 | random_LCG = 1664525 * random_LCG + 1013904223; |
| 9633 | /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */ | ||
| 9634 | t = (random_galois_LFSR << 1); | ||
| 9635 | if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */ | ||
| 9636 | t ^= MASK; | ||
| 9637 | random_galois_LFSR = t; | ||
| 9638 | /* Both are weak, xoring them gives better randomness | ||
| 9639 | * and ~2^64 period. & 0x7fff is probably bash compat | ||
| 9640 | * for $RANDOM range. */ | ||
| 9641 | t = (t ^ random_LCG) & 0x7fff; | ||
| 9628 | /* set without recursion */ | 9642 | /* set without recursion */ |
| 9629 | setvar(vrandom.text, buf, VNOFUNC); | 9643 | setvar(vrandom.text, utoa(t), VNOFUNC); |
| 9630 | vrandom.flags &= ~VNOFUNC; | 9644 | vrandom.flags &= ~VNOFUNC; |
| 9631 | } else { | 9645 | } else { |
| 9632 | /* set/reset */ | 9646 | /* set/reset */ |
| 9633 | rseed = strtoul(value, (char **)NULL, 10); | 9647 | random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10); |
| 9634 | } | 9648 | } |
| 9635 | } | 9649 | } |
| 9636 | #endif | 9650 | #endif |
| @@ -13417,7 +13431,7 @@ int ash_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
| 13417 | rootpid = getpid(); | 13431 | rootpid = getpid(); |
| 13418 | 13432 | ||
| 13419 | #if ENABLE_ASH_RANDOM_SUPPORT | 13433 | #if ENABLE_ASH_RANDOM_SUPPORT |
| 13420 | rseed = rootpid + time(NULL); | 13434 | random_galois_LFSR = random_LCG = rootpid + time(NULL); |
| 13421 | #endif | 13435 | #endif |
| 13422 | init(); | 13436 | init(); |
| 13423 | setstackmark(&smark); | 13437 | setstackmark(&smark); |
