X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=shell%2Fash.c;h=481b84138dbed7da9286ca525934f34097d3fa08;hb=4b8b37f9815892a1c221c0ca9f8eec623ab71866;hp=37bdc701a5490adfff1dc1821db26d9987dc0b21;hpb=e305c28285ac365d6573802b33a2d542fd236022;p=oweals%2Fbusybox.git diff --git a/shell/ash.c b/shell/ash.c index 37bdc701a..481b84138 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -51,16 +51,21 @@ #include #include #include "math.h" +#if ENABLE_ASH_RANDOM_SUPPORT +# include "random.h" +#else +# define CLEAR_RANDOM_T(rnd) ((void)0) +#endif #if defined SINGLE_APPLET_MAIN /* STANDALONE does not make sense, and won't compile */ -#undef CONFIG_FEATURE_SH_STANDALONE -#undef ENABLE_FEATURE_SH_STANDALONE -#undef IF_FEATURE_SH_STANDALONE -#undef IF_NOT_FEATURE_SH_STANDALONE(...) -#define ENABLE_FEATURE_SH_STANDALONE 0 -#define IF_FEATURE_SH_STANDALONE(...) -#define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ +# undef CONFIG_FEATURE_SH_STANDALONE +# undef ENABLE_FEATURE_SH_STANDALONE +# undef IF_FEATURE_SH_STANDALONE +# undef IF_NOT_FEATURE_SH_STANDALONE(...) +# define ENABLE_FEATURE_SH_STANDALONE 0 +# define IF_FEATURE_SH_STANDALONE(...) +# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ #endif #ifndef PIPE_BUF @@ -197,9 +202,7 @@ struct globals_misc { /* Rarely referenced stuff */ #if ENABLE_ASH_RANDOM_SUPPORT - /* Random number generators */ - int32_t random_galois_LFSR; /* Galois LFSR (fast but weak). signed! */ - uint32_t random_LCG; /* LCG (fast but weak) */ + random_t random_gen; #endif pid_t backgndpid; /* pid of last background process */ smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */ @@ -224,8 +227,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc; #define gotsig (G_misc.gotsig ) #define trap (G_misc.trap ) #define trap_ptr (G_misc.trap_ptr ) -#define random_galois_LFSR (G_misc.random_galois_LFSR) -#define random_LCG (G_misc.random_LCG ) +#define random_gen (G_misc.random_gen ) #define backgndpid (G_misc.backgndpid ) #define job_warning (G_misc.job_warning) #define INIT_G_misc() do { \ @@ -1155,6 +1157,49 @@ errmsg(int e, const char *em) /* ============ Memory allocation */ +#if 0 +/* I consider these wrappers nearly useless: + * ok, they return you to nearest exception handler, but + * how much memory do you leak in the process, making + * memory starvation worse? + */ +static void * +ckrealloc(void * p, size_t nbytes) +{ + p = realloc(p, nbytes); + if (!p) + ash_msg_and_raise_error(bb_msg_memory_exhausted); + return p; +} + +static void * +ckmalloc(size_t nbytes) +{ + return ckrealloc(NULL, nbytes); +} + +static void * +ckzalloc(size_t nbytes) +{ + return memset(ckmalloc(nbytes), 0, nbytes); +} + +static char * +ckstrdup(const char *s) +{ + char *p = strdup(s); + if (!p) + ash_msg_and_raise_error(bb_msg_memory_exhausted); + return p; +} +#else +/* Using bbox equivalents. They exit if out of memory */ +# define ckrealloc xrealloc +# define ckmalloc xmalloc +# define ckzalloc xzalloc +# define ckstrdup xstrdup +#endif + /* * It appears that grabstackstr() will barf with such alignments * because stalloc() will return a string allocated in a new stackblock. @@ -1164,7 +1209,7 @@ enum { /* Most machines require the value returned from malloc to be aligned * in some way. The following macro will get this right * on many machines. */ - SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1, + SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1, /* Minimum size of a block */ MINSIZE = SHELL_ALIGN(504), }; @@ -1210,43 +1255,10 @@ extern struct globals_memstack *const ash_ptr_to_globals_memstack; herefd = -1; \ } while (0) + #define stackblock() ((void *)g_stacknxt) #define stackblocksize() g_stacknleft - -static void * -ckrealloc(void * p, size_t nbytes) -{ - p = realloc(p, nbytes); - if (!p) - ash_msg_and_raise_error(bb_msg_memory_exhausted); - return p; -} - -static void * -ckmalloc(size_t nbytes) -{ - return ckrealloc(NULL, nbytes); -} - -static void * -ckzalloc(size_t nbytes) -{ - return memset(ckmalloc(nbytes), 0, nbytes); -} - -/* - * Make a copy of a string in safe storage. - */ -static char * -ckstrdup(const char *s) -{ - char *p = strdup(s); - if (!p) - ash_msg_and_raise_error(bb_msg_memory_exhausted); - return p; -} - /* * Parse trees for commands are allocated in lifo order, so we use a stack * to make this more efficient, and also to avoid all sorts of exception @@ -3272,9 +3284,6 @@ struct job { }; static struct job *makejob(/*union node *,*/ int); -#if !JOBS -#define forkshell(job, node, mode) forkshell(job, mode) -#endif static int forkshell(struct job *, union node *, int); static int waitforjob(struct job *); @@ -4541,9 +4550,6 @@ clear_traps(void) static void closescript(void); /* Called after fork(), in child */ -#if !JOBS -# define forkchild(jp, n, mode) forkchild(jp, mode) -#endif static NOINLINE void forkchild(struct job *jp, union node *n, int mode) { @@ -4601,9 +4607,9 @@ forkchild(struct job *jp, union node *n, int mode) * * Our solution: ONLY bare $(trap) or `trap` is special. */ - /* This is needed to prevent EXIT trap firing and such - * (trap_ptr will be freed in trapcmd()) */ + /* Save trap handler strings for trap builtin to print */ trap_ptr = memcpy(xmalloc(sizeof(trap)), trap, sizeof(trap)); + /* Fall through into clearing traps */ } clear_traps(); #if JOBS @@ -4721,10 +4727,12 @@ forkshell(struct job *jp, union node *n, int mode) freejob(jp); ash_msg_and_raise_error("can't fork"); } - if (pid == 0) + if (pid == 0) { + CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */ forkchild(jp, n, mode); - else + } else { forkparent(jp, n, mode, pid); + } return pid; } @@ -6371,8 +6379,18 @@ subevalvar(char *p, char *str, int strloc, int subtype, /* * Add the value of a specialized variable to the stack string. - */ -static ssize_t + * name parameter (examples): + * ash -c 'echo $1' name:'1=' + * ash -c 'echo $qwe' name:'qwe=' + * ash -c 'echo $$' name:'$=' + * ash -c 'echo ${$}' name:'$=' + * ash -c 'echo ${$##q}' name:'$=q' + * ash -c 'echo ${#$}' name:'$=' + * note: examples with bad shell syntax: + * ash -c 'echo ${#$1}' name:'$=1' + * ash -c 'echo ${#1#}' name:'1=#' + */ +static NOINLINE ssize_t varvalue(char *name, int varflags, int flags, struct strlist *var_str_list) { int num; @@ -6407,7 +6425,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list) return -1; numvar: len = cvtnum(num); - break; + goto check_1char_name; case '-': expdest = makestrspace(NOPTS, expdest); for (i = NOPTS - 1; i >= 0; i--) { @@ -6416,6 +6434,12 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list) len++; } } + check_1char_name: +#if 0 + /* handles cases similar to ${#$1} */ + if (name[2] != '\0') + raise_error_syntax("bad substitution"); +#endif break; case '@': if (sep) @@ -7761,7 +7785,7 @@ static char *funcstring; /* block to allocate strings from */ #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ #define EV_BACKCMD 04 /* command executing within back quotes */ -static const short nodesize[N_NUMBER] = { +static const uint8_t nodesize[N_NUMBER] = { [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)), [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)), [NREDIR ] = SHELL_ALIGN(sizeof(struct nredir)), @@ -8539,12 +8563,13 @@ setinteractive(int on) static smallint did_banner; if (!did_banner) { - out1fmt( - "\n\n" - "%s built-in shell (ash)\n" + /* note: ash and hush share this string */ + out1fmt("\n\n%s %s\n" "Enter 'help' for a list of built-in commands." "\n\n", - bb_banner); + bb_banner, + "built-in shell (ash)" + ); did_banner = 1; } } @@ -10058,34 +10083,18 @@ setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) static void FAST_FUNC change_random(const char *value) { - /* Galois LFSR parameter */ - /* Taps at 32 31 29 1: */ - enum { MASK = 0x8000000b }; - /* Another example - taps at 32 31 30 10: */ - /* MASK = 0x00400007 */ + uint32_t t; if (value == NULL) { /* "get", generate */ - uint32_t t; - - /* LCG has period of 2^32 and alternating lowest bit */ - random_LCG = 1664525 * random_LCG + 1013904223; - /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */ - t = (random_galois_LFSR << 1); - if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */ - t ^= MASK; - random_galois_LFSR = t; - /* Both are weak, combining them gives better randomness - * and ~2^64 period. & 0x7fff is probably bash compat - * for $RANDOM range. Combining with subtraction is - * just for fun. + and ^ would work equally well. */ - t = (t - random_LCG) & 0x7fff; + t = next_random(&random_gen); /* set without recursion */ setvar(vrandom.text, utoa(t), VNOFUNC); vrandom.flags &= ~VNOFUNC; } else { /* set/reset */ - random_galois_LFSR = random_LCG = strtoul(value, NULL, 10); + t = strtoul(value, NULL, 10); + INIT_RANDOM_T(&random_gen, (t ? t : 1), t); } } #endif @@ -11274,6 +11283,8 @@ parsesub: { badsub: raise_error_syntax("bad substitution"); } + if (c != '}' && subtype == VSLENGTH) + goto badsub; STPUTC('=', out); flags = 0; @@ -12267,18 +12278,25 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) for (signo = 0; signo < NSIG; signo++) { char *tr = trap_ptr[signo]; if (tr) { - out1fmt("trap -- %s %s%s\n", + /* note: bash adds "SIG", but only if invoked + * as "bash". If called as "sh", or if set -o posix, + * then it prints short signal names. + * We are printing short names: */ + out1fmt("trap -- %s %s\n", single_quote(tr), - (signo == 0 ? "" : "SIG"), get_signame(signo)); - if (trap_ptr != trap) - free(tr); + /* trap_ptr != trap only if we are in special-cased `trap` code. + * In this case, we will exit very soon, no need to free(). */ + /* if (trap_ptr != trap && tp[0]) */ + /* free(tr); */ } } + /* if (trap_ptr != trap) { free(trap_ptr); trap_ptr = trap; } + */ return 0; } @@ -12901,8 +12919,7 @@ printlim(enum limtype how, const struct rlimit *limit, static int FAST_FUNC ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { - int c; - rlim_t val = 0; + rlim_t val; enum limtype how = SOFT | HARD; const struct limits *l; int set, all = 0; @@ -12963,6 +12980,7 @@ ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) continue; set = *argptr ? 1 : 0; + val = 0; if (set) { char *p = *argptr; @@ -12971,15 +12989,13 @@ ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) if (strncmp(p, "unlimited\n", 9) == 0) val = RLIM_INFINITY; else { - val = (rlim_t) 0; - - while ((c = *p++) >= '0' && c <= '9') { - val = (val * 10) + (long)(c - '0'); - // val is actually 'unsigned long int' and can't get < 0 - if (val < (rlim_t) 0) - break; - } - if (c) + if (sizeof(val) == sizeof(int)) + val = bb_strtou(p, NULL, 10); + else if (sizeof(val) == sizeof(long)) + val = bb_strtoul(p, NULL, 10); + else + val = bb_strtoull(p, NULL, 10); + if (errno) ash_msg_and_raise_error("bad number"); val <<= l->factor_shift; } @@ -13059,7 +13075,6 @@ init(void) /* from var.c: */ { char **envp; - char ppid[sizeof(int)*3 + 2]; const char *p; struct stat st1, st2; @@ -13070,8 +13085,7 @@ init(void) } } - sprintf(ppid, "%u", (unsigned) getppid()); - setvar("PPID", ppid, 0); + setvar("PPID", utoa(getppid()), 0); p = lookupvar("PWD"); if (p) @@ -13252,11 +13266,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) #endif rootpid = getpid(); -#if ENABLE_ASH_RANDOM_SUPPORT - /* Can use monotonic_ns() for better randomness but for now it is - * not used anywhere else in busybox... so avoid bloat */ - random_galois_LFSR = random_LCG = rootpid + monotonic_us(); -#endif init(); setstackmark(&smark); procargs(argv); @@ -13310,7 +13319,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) } if (sflag || minusc == NULL) { -#if ENABLE_FEATURE_EDITING_SAVEHISTORY +#if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY if (iflag) { const char *hp = lookupvar("HISTFILE"); if (hp)