diff --git a/Build.sh b/Build.sh index a6637ff..1b0140d 100644 --- a/Build.sh +++ b/Build.sh @@ -1,5 +1,5 @@ #!/bin/sh -srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.452 2010/05/13 18:41:13 tg Exp $' +srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.453 2010/07/04 17:33:53 tg Exp $' #- # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 # Thorsten Glaser @@ -1200,51 +1200,6 @@ EOF # # Environment: library functions # -ac_testn arc4random <<-'EOF' - #include - #if HAVE_STDINT_H - #include - #endif - extern u_int32_t arc4random(void); - int main(void) { return ((int)(arc4random() & 0xFF)); } -EOF - -save_LIBS=$LIBS -if test 0 = $HAVE_ARC4RANDOM; then - test -f arc4random.c || if test -f "$srcdir/arc4random.c"; then - # ensure isolation of source directory from build directory - cp "$srcdir/arc4random.c" . - fi - if test -f arc4random.c; then - ac_testn can_uint8t '' "for uint8_t" <<-'EOF' - #include - #if HAVE_STDINT_H - #include - #endif - int main(void) { return (1 - (uint8_t)1); } - EOF - test $HAVE_CAN_UINT8T = 1 || \ - CPPFLAGS="$CPPFLAGS -D\"uint8_t=unsigned char\"" - - ac_header sys/sysctl.h - addsrcs '!' HAVE_ARC4RANDOM arc4random.c - HAVE_ARC4RANDOM=1 - LIBS="$LIBS arc4random.c" - fi -fi -ac_cppflags ARC4RANDOM - -ac_test arc4random_pushb arc4random 0 <<-'EOF' - #include - #if HAVE_STDINT_H - #include - #endif - extern uint32_t arc4random_pushb(void *, size_t); - int main(int ac, char *av[]) { return ((int)(arc4random_pushb(*av, - (size_t)ac)) & 0xFF); } -EOF -LIBS=$save_LIBS - ac_testn flock_ex '' 'flock and mmap' <<-'EOF' #include #include @@ -1366,18 +1321,6 @@ EOF # save_CC=$CC; save_LDFLAGS=$LDFLAGS; save_LIBS=$LIBS CC="$CC -c -o $tcfn"; LDFLAGS=; LIBS= -ac_test '!' arc4random_decl arc4random 1 'if arc4random() does not need to be declared' <<-'EOF' - #define MKSH_INCLUDES_ONLY - #include "sh.h" - long arc4random(void); /* this clashes if defined before */ - int main(void) { return ((int)arc4random()); } -EOF -ac_test '!' arc4random_pushb_decl arc4random_pushb 1 'if arc4random_pushb() does not need to be declared' <<-'EOF' - #define MKSH_INCLUDES_ONLY - #include "sh.h" - int arc4random_pushb(char, int); /* this clashes if defined before */ - int main(int ac, char *av[]) { return ((int)arc4random_pushb(**av, ac)); } -EOF ac_test '!' flock_decl flock_ex 1 'if flock() does not need to be declared' <<-'EOF' #define MKSH_INCLUDES_ONLY #include "sh.h" diff --git a/jobs.c b/jobs.c index 47eba99..47326a1 100644 --- a/jobs.c +++ b/jobs.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.68 2010/07/04 13:36:42 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.69 2010/07/04 17:33:54 tg Exp $"); #if HAVE_KILLPG #define mksh_killpg killpg @@ -340,15 +340,12 @@ exchild(struct op *t, int flags, { static Proc *last_proc; /* for pipelines */ - int i, rv = 0, forksleep; + int rv = 0, forksleep; sigset_t omask; - Proc *p; - Job *j; struct { -#if !HAVE_ARC4RANDOM - pid_t thepid; -#endif - unsigned char ischild; + Proc *p; + Job *j; + pid_t cldpid; } pi; if (flags & XEXEC) @@ -361,99 +358,93 @@ exchild(struct op *t, int flags, /* no SIGCHLDs while messing with job and process lists */ sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); - p = new_proc(); - p->next = NULL; - p->state = PRUNNING; - p->status = 0; - p->pid = 0; + pi.p = new_proc(); + pi.p->next = NULL; + pi.p->state = PRUNNING; + pi.p->status = 0; + pi.p->pid = 0; /* link process into jobs list */ - if (flags & XPIPEI) { /* continuing with a pipe */ + if (flags & XPIPEI) { + /* continuing with a pipe */ if (!last_job) internal_errorf( "exchild: XPIPEI and no last_job - pid %d", (int)procpid); - j = last_job; + pi.j = last_job; if (last_proc) - last_proc->next = p; - last_proc = p; + last_proc->next = pi.p; + last_proc = pi.p; } else { - j = new_job(); /* fills in j->job */ + pi.j = new_job(); /* fills in pi.j->job */ /* * we don't consider XXCOMs foreground since they don't get * tty process group and we don't save or restore tty modes. */ - j->flags = (flags & XXCOM) ? JF_XXCOM : + pi.j->flags = (flags & XXCOM) ? JF_XXCOM : ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE)); - timerclear(&j->usrtime); - timerclear(&j->systime); - j->state = PRUNNING; - j->pgrp = 0; - j->ppid = procpid; - j->age = ++njobs; - j->proc_list = p; - j->coproc_id = 0; - last_job = j; - last_proc = p; - put_job(j, PJ_PAST_STOPPED); + timerclear(&pi.j->usrtime); + timerclear(&pi.j->systime); + pi.j->state = PRUNNING; + pi.j->pgrp = 0; + pi.j->ppid = procpid; + pi.j->age = ++njobs; + pi.j->proc_list = pi.p; + pi.j->coproc_id = 0; + last_job = pi.j; + last_proc = pi.p; + put_job(pi.j, PJ_PAST_STOPPED); } - snptreef(p->command, sizeof(p->command), "%T", t); + snptreef(pi.p->command, sizeof(pi.p->command), "%T", t); /* create child process */ forksleep = 1; - while ((i = fork()) < 0 && errno == EAGAIN && forksleep < 32) { + while ((pi.cldpid = fork()) < 0 && errno == EAGAIN && forksleep < 32) { if (intrsig) /* allow user to ^C out... */ break; sleep(forksleep); forksleep <<= 1; } - if (i < 0) { - kill_job(j, SIGKILL); - remove_job(j, "fork failed"); + if (pi.cldpid < 0) { + kill_job(pi.j, SIGKILL); + remove_job(pi.j, "fork failed"); sigprocmask(SIG_SETMASK, &omask, NULL); errorf("cannot fork - try again"); } -#if !HAVE_ARC4RANDOM -#ifdef DEBUG - /* reduce extra 3 bytes of entropy, for Valgrind */ - memset(&pi, 0, sizeof(pi)); -#endif - pi.thepid = -#endif - p->pid = (pi.ischild = i == 0) ? (procpid = getpid()) : i; + pi.p->pid = pi.cldpid ? pi.cldpid : (procpid = getpid()); -#if !HAVE_ARC4RANDOM /* * ensure next child gets a (slightly) different $RANDOM sequence * from its parent process and other child processes */ change_random(&pi, sizeof(pi)); -#endif #ifndef MKSH_UNEMPLOYED /* job control set up */ if (Flag(FMONITOR) && !(flags&XXCOM)) { int dotty = 0; - if (j->pgrp == 0) { /* First process */ - j->pgrp = p->pid; + if (pi.j->pgrp == 0) { /* First process */ + pi.j->pgrp = pi.p->pid; dotty = 1; } /* set pgrp in both parent and child to deal with race * condition */ - setpgid(p->pid, j->pgrp); + setpgid(pi.p->pid, pi.j->pgrp); if (ttypgrp_ok && dotty && !(flags & XBGND)) - tcsetpgrp(tty_fd, j->pgrp); + tcsetpgrp(tty_fd, pi.j->pgrp); } #endif /* used to close pipe input fd */ - if (close_fd >= 0 && (((flags & XPCLOSE) && !pi.ischild) || - ((flags & XCCLOSE) && pi.ischild))) + if (close_fd >= 0 && (((flags & XPCLOSE) && pi.cldpid) || + ((flags & XCCLOSE) && !pi.cldpid))) close(close_fd); - if (pi.ischild) { /* child */ + if (!pi.cldpid) { + /* child */ + /* Do this before restoring signal */ if (flags & XCOPROC) coproc_cleanup(false); @@ -465,8 +456,8 @@ exchild(struct op *t, int flags, * their inherited values. */ if (Flag(FMONITOR) && !(flags & XXCOM)) { - for (i = NELEM(tt_sigs); --i >= 0; ) - setsig(&sigtraps[tt_sigs[i]], SIG_DFL, + for (forksleep = NELEM(tt_sigs); --forksleep >= 0; ) + setsig(&sigtraps[tt_sigs[forksleep]], SIG_DFL, SS_RESTORE_DFL|SS_FORCE); } #endif @@ -484,12 +475,12 @@ exchild(struct op *t, int flags, setsig(&sigtraps[SIGQUIT], SIG_IGN, SS_RESTORE_IGN|SS_FORCE); if ((!(flags & (XPIPEI | XCOPROC))) && - ((i = open("/dev/null", 0)) > 0)) { - (void)ksh_dup2(i, 0, true); - close(i); + ((forksleep = open("/dev/null", 0)) > 0)) { + (void)ksh_dup2(forksleep, 0, true); + close(forksleep); } } - remove_job(j, "child"); /* in case of $(jobs) command */ + remove_job(pi.j, "child"); /* in case of $(jobs) command */ nzombie = 0; #ifndef MKSH_UNEMPLOYED ttypgrp_ok = false; @@ -513,24 +504,27 @@ exchild(struct op *t, int flags, /* shell (parent) stuff */ if (!(flags & XPIPEO)) { /* last process in a job */ - j_startjob(j); + j_startjob(pi.j); if (flags & XCOPROC) { - j->coproc_id = coproc.id; - coproc.njobs++; /* n jobs using co-process output */ - coproc.job = (void *) j; /* j using co-process input */ + pi.j->coproc_id = coproc.id; + /* n jobs using co-process output */ + coproc.njobs++; + /* j using co-process input */ + coproc.job = (void *)pi.j; } if (flags & XBGND) { - j_set_async(j); + j_set_async(pi.j); if (Flag(FTALKING)) { - shf_fprintf(shl_out, "[%d]", j->job); - for (p = j->proc_list; p; p = p->next) + shf_fprintf(shl_out, "[%d]", pi.j->job); + for (pi.p = pi.j->proc_list; pi.p; + pi.p = pi.p->next) shf_fprintf(shl_out, " %d", - (int)p->pid); + (int)pi.p->pid); shf_putchar('\n', shl_out); shf_flush(shl_out); } } else - rv = j_waitj(j, JW_NONE, "jw:last proc"); + rv = j_waitj(pi.j, JW_NONE, "jw:last proc"); } sigprocmask(SIG_SETMASK, &omask, NULL); diff --git a/main.c b/main.c index 032e0dc..e08cb50 100644 --- a/main.c +++ b/main.c @@ -33,7 +33,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/main.c,v 1.165 2010/05/22 12:49:15 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/main.c,v 1.166 2010/07/04 17:33:55 tg Exp $"); extern char **environ; @@ -92,8 +92,7 @@ static const char *initcoms[] = { static int initio_done; -static struct env env; -struct env *e = &env; +struct env *e = &kshstate_v.env_; void chvt_reinit(void) @@ -102,10 +101,6 @@ chvt_reinit(void) ksheuid = geteuid(); kshpgrp = getpgrp(); kshppid = getppid(); - -#if !HAVE_ARC4RANDOM - change_random(&kshstate_, sizeof(kshstate_)); -#endif } Source * @@ -140,8 +135,8 @@ mksh_init(int argc, const char *argv[]) ainit(&aperm); /* initialise permanent Area */ /* set up base environment */ - env.type = E_NONE; - ainit(&env.area); + kshstate_v.env_.type = E_NONE; + ainit(&kshstate_v.env_.area); newblock(); /* set up global l->vars and l->funs */ /* Do this first so output routines (eg, errorf, shellf) can work */ @@ -294,13 +289,10 @@ mksh_init(int argc, const char *argv[]) vp->flag |= INT_U; setint((vp = global("PPID")), (mksh_uari_t)kshppid); vp->flag |= INT_U; - setint((vp = global("RANDOM")), (mksh_uari_t)hash(kshname)); + setint((vp = global("RANDOM")), (mksh_uari_t)evilhash(kshname)); vp->flag |= INT_U; setint((vp = global("USER_ID")), (mksh_uari_t)ksheuid); vp->flag |= INT_U; -#if HAVE_ARC4RANDOM - Flag(FARC4RANDOM) = 1; /* initialised */ -#endif /* Set this before parsing arguments */ #if HAVE_SETRESUGID @@ -469,9 +461,14 @@ main(int argc, const char *argv[]) { Source *s; - if ((s = mksh_init(argc, argv))) + kshstate_v.lcg_state_ = 5381; + + if ((s = mksh_init(argc, argv))) { + /* put more entropy into the LCG */ + change_random(s, sizeof(*s)); /* doesn’t return */ shell(s, true); + } return (1); } @@ -1300,26 +1297,6 @@ static int tnamecmp(const void *, const void *); static struct tbl *ktscan(struct table *, const char *, uint32_t, struct tbl ***); -/* Bob Jenkins' one-at-a-time hash */ -uint32_t -oaathash_full(register const uint8_t *bp) -{ - register uint32_t h = 0; - register uint8_t c; - - while ((c = *bp++)) { - h += c; - h += h << 10; - h ^= h >> 6; - } - - h += h << 3; - h ^= h >> 11; - h += h << 15; - - return (h); -} - static void texpand(struct table *tp, size_t nsize) { diff --git a/misc.c b/misc.c index 91620ed..e7b32c9 100644 --- a/misc.c +++ b/misc.c @@ -29,7 +29,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.138 2010/01/29 09:34:29 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.139 2010/07/04 17:33:55 tg Exp $"); unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */ @@ -1266,6 +1266,9 @@ chvt(const char *fn) struct stat sb; int fd; + /* for entropy */ + kshstate_f.h = evilhash(fn); + if (*fn == '-') { memcpy(dv, "-/dev/null", sizeof("-/dev/null")); fn = dv + 1; diff --git a/mksh.1 b/mksh.1 index e4f1bf3..4e89370 100644 --- a/mksh.1 +++ b/mksh.1 @@ -1,4 +1,4 @@ -.\" $MirOS: src/bin/mksh/mksh.1,v 1.226 2010/05/13 18:47:50 tg Exp $ +.\" $MirOS: src/bin/mksh/mksh.1,v 1.227 2010/07/04 17:33:56 tg Exp $ .\" $OpenBSD: ksh.1,v 1.134 2010/05/10 21:04:54 jmc Exp $ .\"- .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 @@ -71,7 +71,7 @@ .\" with -mandoc, it might implement .Mx itself, but we want to .\" use our own definition. And .Dd must come *first*, always. .\" -.Dd $Mdocdate: May 13 2010 $ +.Dd $Mdocdate: July 4 2010 $ .\" .\" Check which macro package we use .\" @@ -1923,11 +1923,7 @@ if the shell doesn't know where it is. Every time .Ev RANDOM is referenced, it is assigned a 15-bit pseudo-random number, i.e. between -0 and 32767, first, which is taken from -.Xr arc4random 3 -if available, -a Linear Congruential PRNG -otherwise. +0 and 32767, first, which is taken from a Linear Congruential PRNG. .It Ev REPLY Default parameter for the .Ic read @@ -3856,11 +3852,6 @@ during file name generation. Print commands and parameter assignments when they are executed, preceded by the value of .Ev PS4 . -.It Ic arc4random -If this shell option, which cannot be unset, exists, -.Xr arc4random 3 -is used for the value of -.Ev RANDOM . .It Ic bgnice Background jobs are run with lower priority. .It Ic braceexpand @@ -5929,7 +5920,6 @@ Privileged shell profile. .Xr pipe 2 , .Xr rename 2 , .Xr wait 2 , -.Xr arc4random 3 , .Xr getopt 3 , .Xr nl_langinfo 3 , .Xr setlocale 3 , diff --git a/sh.h b/sh.h index 8e91397..3ca58df 100644 --- a/sh.h +++ b/sh.h @@ -150,7 +150,7 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.393 2010/07/04 13:36:43 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.394 2010/07/04 17:33:57 tg Exp $"); #endif #define MKSH_VERSION "R39 2010/05/22" @@ -272,16 +272,6 @@ typedef int bool; /* OS-dependent additions (functions, variables, by OS) */ -#if !HAVE_ARC4RANDOM_DECL -extern u_int32_t arc4random(void); -extern void arc4random_addrandom(unsigned char *, int) - MKSH_A_BOUNDED(string, 1, 2); -#endif - -#if !HAVE_ARC4RANDOM_PUSHB_DECL -extern uint32_t arc4random_pushb(const void *, size_t); -#endif - #if !HAVE_FLOCK_DECL extern int flock(int, int); #endif @@ -361,25 +351,6 @@ typedef uint32_t mksh_uari_t; #define LINE 4096 /* input line size */ -EXTERN struct { - const char *kshname_; /* $0 */ - pid_t kshpid_; /* $$, shell PID */ - pid_t procpid_; /* PID of executing process */ - pid_t kshpgrp_; /* process group of shell */ - uid_t ksheuid_; /* effective UID of shell */ - pid_t kshppid_; /* PID of parent of shell */ - int exstat_; /* exit status */ - int subst_exstat_; /* exit status of last $(..)/`..` */ -} kshstate_; -#define kshname kshstate_.kshname_ -#define kshpid kshstate_.kshpid_ -#define procpid kshstate_.procpid_ -#define kshpgrp kshstate_.kshpgrp_ -#define ksheuid kshstate_.ksheuid_ -#define kshppid kshstate_.kshppid_ -#define exstat kshstate_.exstat_ -#define subst_exstat kshstate_.subst_exstat_ - EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */ EXTERN const char initvsn[] I__("KSH_VERSION=@(#)MIRBSD KSH " MKSH_VERSION); #define KSH_VERSION (initvsn + /* "KSH_VERSION=@(#)" */ 16) @@ -514,6 +485,18 @@ EXTERN Area aperm; /* permanent object space */ #define APERM &aperm #define ATEMP &e->area +/* + * flags (the order of these enums MUST match the order in misc.c(options[])) + */ +enum sh_flag { +#define SHFLAGS_ENUMS +#include "sh_flags.h" + FNFLAGS /* (place holder: how many flags are there) */ +}; + +#define Flag(f) (kshstate_v.shell_flags_[(int)(f)]) +#define UTFMODE Flag(FUNICODE) + /* * parsing & execution environment */ @@ -561,6 +544,44 @@ extern struct env { #define LSHELL 8 /* return to interactive shell() */ #define LAEXPR 9 /* error in arithmetic expression */ +/* + * some kind of global shell state, for change_random() mostly + */ + +EXTERN struct { + /* for change_random */ + struct timeval cr_tv; /* timestamp */ + const void *cr_dp; /* argument address */ + size_t cr_dsz; /* argument length */ + uint32_t lcg_state_; /* previous LCG state */ + /* global state */ + pid_t procpid_; /* PID of executing process */ + int exstat_; /* exit status */ + int subst_exstat_; /* exit status of last $(..)/`..` */ + struct env env_; /* top-level parsing & execution env. */ + uint8_t shell_flags_[FNFLAGS]; +} kshstate_v; +EXTERN struct { + const char *kshname_; /* $0 */ + pid_t kshpid_; /* $$, shell PID */ + pid_t kshpgrp_; /* process group of shell */ + uid_t ksheuid_; /* effective UID of shell */ + pid_t kshppid_; /* PID of parent of shell */ + uint32_t h; /* some kind of hash */ +} kshstate_f; +#define kshname kshstate_f.kshname_ +#define kshpid kshstate_f.kshpid_ +#define procpid kshstate_v.procpid_ +#define kshpgrp kshstate_f.kshpgrp_ +#define ksheuid kshstate_f.ksheuid_ +#define kshppid kshstate_f.kshppid_ +#define exstat kshstate_v.exstat_ +#define subst_exstat kshstate_v.subst_exstat_ + +/* evil hack: return hash(kshstate_f concat (kshstate_f'.h:=hash(arg))) */ +uint32_t evilhash(const char *); + + /* option processing */ #define OF_CMDLINE 0x01 /* command line */ #define OF_SET 0x02 /* set builtin */ @@ -576,20 +597,6 @@ struct shoption { }; extern const struct shoption options[]; -/* - * flags (the order of these enums MUST match the order in misc.c(options[])) - */ -enum sh_flag { -#define SHFLAGS_ENUMS -#include "sh_flags.h" - FNFLAGS /* (place holder: how many flags are there) */ -}; - -#define Flag(f) (shell_flags[(int)(f)]) -#define UTFMODE Flag(FUNICODE) - -EXTERN unsigned char shell_flags[FNFLAGS]; - /* null value for variable; comparision pointer for unset */ EXTERN char null[] I__(""); /* helpers for string pooling */ @@ -1635,9 +1642,7 @@ const char *skip_wdvarname(const char *, int); int is_wdvarname(const char *, int); int is_wdvarassign(const char *); char **makenv(void); -#if !HAVE_ARC4RANDOM void change_random(const void *, size_t); -#endif void change_winsz(void); int array_ref_len(const char *); char *arrayname(const char *); diff --git a/sh_flags.h b/sh_flags.h index 2852627..5a9e02c 100644 --- a/sh_flags.h +++ b/sh_flags.h @@ -1,5 +1,5 @@ #if defined(SHFLAGS_DEFNS) -__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.5 2010/01/28 15:18:51 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.6 2010/07/04 17:33:58 tg Exp $"); #define FN(sname,cname,ochar,flags) /* nothing */ #elif defined(SHFLAGS_ENUMS) #define FN(sname,cname,ochar,flags) cname, @@ -21,11 +21,6 @@ __RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.5 2010/01/28 15:18:51 tg Exp $"); /* -a all new parameters are created with the export attribute */ F0("allexport", FEXPORT, 'a', OF_ANY) -#if HAVE_ARC4RANDOM -/* ./. backwards compat: available if arc4random(3) is used for $RANDOM */ -FN("arc4random", FARC4RANDOM, 0, OF_INTERNAL) -#endif - #if HAVE_NICE /* ./. bgnice */ FN("bgnice", FBGNICE, 0, OF_ANY) diff --git a/var.c b/var.c index 3a8052a..f772579 100644 --- a/var.c +++ b/var.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/var.c,v 1.104 2010/01/28 20:26:52 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/var.c,v 1.105 2010/07/04 17:33:58 tg Exp $"); /* * Variables @@ -46,12 +46,9 @@ static int getint(struct tbl *, mksh_ari_t *, bool); static mksh_ari_t intval(struct tbl *); static struct tbl *arraysearch(struct tbl *, uint32_t); static const char *array_index_calc(const char *, bool *, uint32_t *); -#if !HAVE_ARC4RANDOM static uint32_t oaathash_update(register uint32_t, register const uint8_t *, register size_t); - -static uint32_t lcg_state = 5381; -#endif +static uint32_t oaathash_finalise(register uint32_t); uint8_t set_refflag = 0; @@ -982,7 +979,7 @@ makenv(void) return ((char **)XPclose(denv)); } -#if !HAVE_ARC4RANDOM +/* Bob Jenkins' one-at-a-time hash */ static uint32_t oaathash_update(register uint32_t h, register const uint8_t *cp, register size_t n) @@ -996,33 +993,43 @@ oaathash_update(register uint32_t h, register const uint8_t *cp, return (h); } -void -change_random(const void *vp, size_t n) +static uint32_t +oaathash_finalise(register uint32_t h) { - register uint32_t h = 0x100; - struct { - const void *sp, *bp, *dp; - size_t dsz; - struct timeval tv; - uint32_t s; - } i; - - i.dp = vp; - i.dsz = n; - i.s = lcg_state; - i.bp = &lcg_state; - i.sp = &i; - gettimeofday(&i.tv, NULL); - h = oaathash_update(oaathash_update(h, (void *)&i, sizeof(i)), vp, n); - - /* oaathash_finalise */ h += h << 3; h ^= h >> 11; h += h << 15; - lcg_state = h; + return (h); +} + +uint32_t +oaathash_full(register const uint8_t *bp) +{ + register uint32_t h = 0; + register uint8_t c; + + while ((c = *bp++)) { + h += c; + h += h << 10; + h ^= h >> 6; + } + + return (oaathash_finalise(h)); +} + +void +change_random(const void *vp, size_t n) +{ + register uint32_t h = 0x100; + + kshstate_v.cr_dp = vp; + kshstate_v.cr_dsz = n; + gettimeofday(&kshstate_v.cr_tv, NULL); + h = oaathash_update(oaathash_update(h, (void *)&kshstate_v, + sizeof(kshstate_v)), vp, n); + kshstate_v.lcg_state_ = oaathash_finalise(h); } -#endif /* * handle special variables with side effects - PATH, SECONDS. @@ -1074,15 +1081,12 @@ getspec(struct tbl *vp) return; break; case V_RANDOM: -#if HAVE_ARC4RANDOM - i = arc4random() & 0x7FFF; -#else /* * this is the same Linear Congruential PRNG as Borland * C/C++ allegedly uses in its built-in rand() function */ - i = ((lcg_state = 22695477 * lcg_state + 1) >> 16) & 0x7FFF; -#endif + i = ((kshstate_v.lcg_state_ = + 22695477 * kshstate_v.lcg_state_ + 1) >> 16) & 0x7FFF; break; case V_HISTSIZE: i = histsize; @@ -1196,25 +1200,11 @@ setspec(struct tbl *vp) x_lins = i; break; case V_RANDOM: -#if HAVE_ARC4RANDOM -#if HAVE_ARC4RANDOM_PUSHB - if (Flag(FARC4RANDOM)) - /* - * things like initialisation, environment import, - * etc. are already done - */ - arc4random_pushb(&i, sizeof(i)); - else - /* during start-up phase or somesuch */ -#endif /* HAVE_ARC4RANDOM_PUSHB */ - arc4random_addrandom((void *)&i, sizeof(i)); -#else /* !HAVE_ARC4RANDOM */ /* - * mksh R40+ no longer has the traditional repeatability + * mksh R39d+ no longer has the traditional repeatability * of $RANDOM sequences, but always retains state */ change_random(&i, sizeof(i)); -#endif /* !HAVE_ARC4RANDOM */ break; case V_SECONDS: { @@ -1259,13 +1249,12 @@ unsetspec(struct tbl *vp) unspecial(vp->name); break; - /* AT&T ksh man page says OPTIND, OPTARG and _ lose special meaning, - * but OPTARG does not (still set by getopts) and _ is also still - * set in various places. - * Don't know what AT&T does for: - * HISTSIZE, HISTFILE, - * Unsetting these in AT&T ksh does not loose the 'specialness': - * no effect: IFS, COLUMNS, PATH, TMPDIR + /* + * AT&T ksh man page says OPTIND, OPTARG and _ lose special + * meaning, but OPTARG does not (still set by getopts) and _ is + * also still set in various places. Don't know what AT&T does + * for HISTSIZE, HISTFILE. Unsetting these in AT&T ksh does not + * loose the 'specialness': IFS, COLUMNS, PATH, TMPDIR */ } } @@ -1452,3 +1441,14 @@ change_winsz(void) if (x_lins < MIN_LINS) x_lins = 24; } + +uint32_t +evilhash(const char *s) +{ + register uint32_t h = 0x100; + + h = oaathash_update(h, (void *)&kshstate_f, sizeof(kshstate_f)); + kshstate_f.h = oaathash_full((const uint8_t *)s); + return (oaathash_finalise(oaathash_update(h, + (void *)&kshstate_f.h, sizeof(kshstate_f.h)))); +}