further optimise and simplify the handling of $RANDOM, reads and writes
to it are now either arc4random or rand/srand, but srand retains the old state; set +o arc4random is no longer possible, but if it's there we use arc4random(3), if not, we use rand(3) for $RANDOM reads; optimise special variable handling too and fix a few consts and other minor things
This commit is contained in:
parent
b50b43e3bf
commit
a59d14b565
8
check.t
8
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.310 2009/09/24 17:15:29 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.311 2009/09/26 03:39:57 tg Exp $
|
||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||
@ -25,7 +25,7 @@
|
||||
# http://www.research.att.com/~gsf/public/ifs.sh
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R39 2009/09/24
|
||||
@(#)MIRBSD KSH R39 2009/09/25
|
||||
description:
|
||||
Check version of shell.
|
||||
stdin:
|
||||
@ -4042,8 +4042,8 @@ description:
|
||||
isn't exec-ed
|
||||
stdin:
|
||||
sortprog=$(whence -p sort) || sortprog=cat
|
||||
env | $sortprog >bar1
|
||||
FOO=bar exec; env | $sortprog >bar2
|
||||
env | $sortprog | grep -v '^RANDOM=' >bar1
|
||||
FOO=bar exec; env | $sortprog | grep -v '^RANDOM=' >bar2
|
||||
cmp -s bar1 bar2
|
||||
---
|
||||
name: xxx-what-do-you-call-this-1
|
||||
|
6
funcs.c
6
funcs.c
@ -25,7 +25,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.134 2009/09/23 18:04:56 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.135 2009/09/26 03:39:58 tg Exp $");
|
||||
|
||||
#if HAVE_KILLPG
|
||||
/*
|
||||
@ -94,7 +94,7 @@ const struct builtin mkshbuiltins[] = {
|
||||
#endif
|
||||
{"pwd", c_pwd},
|
||||
{"*=readonly", c_typeset},
|
||||
{"=typeset", c_typeset},
|
||||
{T__typeset, c_typeset},
|
||||
{"+unalias", c_unalias},
|
||||
{"whence", c_whence},
|
||||
#ifndef MKSH_UNEMPLOYED
|
||||
@ -2309,7 +2309,7 @@ c_set(const char **wp)
|
||||
const char **owp;
|
||||
|
||||
if (wp[1] == NULL) {
|
||||
static const char *args [] = { "set", "-", NULL };
|
||||
static const char *args[] = { "set", "-", NULL };
|
||||
return (c_typeset(args));
|
||||
}
|
||||
|
||||
|
6
jobs.c
6
jobs.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.60 2009/09/20 16:40:55 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.61 2009/09/26 03:39:59 tg Exp $");
|
||||
|
||||
#if HAVE_KILLPG
|
||||
#define mksh_killpg killpg
|
||||
@ -416,8 +416,8 @@ exchild(struct op *t, int flags,
|
||||
else
|
||||
p->pid = i;
|
||||
|
||||
#if !HAVE_ARC4RANDOM || !defined(MKSH_SMALL)
|
||||
/* Ensure next child gets a (slightly) different $RANDOM sequence */
|
||||
#if !HAVE_ARC4RANDOM
|
||||
/* ensure next child gets a (slightly) different $RANDOM sequence */
|
||||
change_random(((unsigned long)p->pid << 1) | (ischild ? 1 : 0));
|
||||
#endif
|
||||
|
||||
|
84
main.c
84
main.c
@ -33,7 +33,7 @@
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.148 2009/09/26 01:08:27 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.149 2009/09/26 03:40:00 tg Exp $");
|
||||
|
||||
extern char **environ;
|
||||
|
||||
@ -47,17 +47,17 @@ static void remove_temps(struct temp *);
|
||||
|
||||
static const char initifs[] = "IFS= \t\n";
|
||||
|
||||
static const char initsubs[] = "${PS2=> } ${PS3=#? } ${PS4=+ }";
|
||||
static const char initsubs[] =
|
||||
"${PS2=> } ${PS3=#? } ${PS4=+ } ${SECONDS=0} ${TMOUT=0}";
|
||||
|
||||
static const char *initcoms[] = {
|
||||
"typeset", "-r", initvsn, NULL,
|
||||
"typeset", "-x", "SHELL", "PATH", "HOME", NULL,
|
||||
"typeset", "-i10", "COLUMNS=0", "LINES=0", "OPTIND=1", NULL,
|
||||
"typeset", "-Ui10", "PGRP", "PPID", "RANDOM", "USER_ID", NULL,
|
||||
"eval", "typeset -i10 SECONDS=\"${SECONDS-0}\" TMOUT=\"${TMOUT-0}\"",
|
||||
NULL,
|
||||
"alias", "integer=typeset -i", "local=typeset", NULL,
|
||||
T_typeset, "-r", initvsn, NULL,
|
||||
T_typeset, "-x", "HOME", "PATH", "RANDOM", "SHELL", NULL,
|
||||
T_typeset, "-i10", "COLUMNS", "LINES", "OPTIND", "PGRP", "PPID",
|
||||
"RANDOM", "SECONDS", "TMOUT", "USER_ID", NULL,
|
||||
"alias",
|
||||
"integer=typeset -i",
|
||||
T_local_typeset,
|
||||
"hash=alias -t", /* not "alias -t --": hash -r needs to work */
|
||||
"type=whence -v",
|
||||
#ifndef MKSH_UNEMPLOYED
|
||||
@ -101,8 +101,14 @@ main(int argc, const char *argv[])
|
||||
char *cp;
|
||||
#endif
|
||||
|
||||
kshpid = procpid = getpid();
|
||||
ksheuid = geteuid();
|
||||
kshpgrp = getpgrp();
|
||||
ppid = getppid();
|
||||
|
||||
#if !HAVE_ARC4RANDOM
|
||||
change_random((unsigned long)time(NULL) * getpid());
|
||||
change_random((unsigned long)time(NULL));
|
||||
change_random(((unsigned long)ksheuid << 16) | kshpid);
|
||||
#endif
|
||||
|
||||
/* make sure argv[] is sane */
|
||||
@ -204,13 +210,14 @@ main(int argc, const char *argv[])
|
||||
#endif
|
||||
|
||||
#ifdef MKSH_BINSHREDUCED
|
||||
/* Set FPOSIX if we're called as -sh or /bin/sh or so */
|
||||
/* set FPOSIX if we're called as -sh or /bin/sh or so */
|
||||
{
|
||||
const char *cc;
|
||||
|
||||
cc = kshname;
|
||||
i = 0; argi = 0;
|
||||
while (cc[i] != '\0')
|
||||
/* the following line matches '-' and '/' ;-) */
|
||||
if ((cc[i++] | 2) == '/')
|
||||
argi = i;
|
||||
if (((cc[argi] | 0x20) == 's') && ((cc[argi + 1] | 0x20) == 'h'))
|
||||
@ -223,7 +230,6 @@ main(int argc, const char *argv[])
|
||||
for (wp = (const char **)environ; *wp != NULL; wp++)
|
||||
typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
|
||||
|
||||
kshpid = procpid = getpid();
|
||||
typeset(initifs, 0, 0, 0, 0); /* for security */
|
||||
|
||||
/* assign default shell variable values */
|
||||
@ -252,31 +258,38 @@ main(int argc, const char *argv[])
|
||||
/* setstr can't fail here */
|
||||
setstr(pwd_v, current_wd, KSH_RETURN_ERROR);
|
||||
}
|
||||
ppid = getppid();
|
||||
#if !HAVE_ARC4RANDOM || !defined(MKSH_SMALL)
|
||||
change_random(((unsigned long)kshname) ^
|
||||
((unsigned long)time(NULL) * kshpid * ppid));
|
||||
#endif
|
||||
#if HAVE_ARC4RANDOM
|
||||
Flag(FARC4RANDOM) = 2; /* use arc4random(3) until $RANDOM is written */
|
||||
#endif
|
||||
|
||||
for (wp = initcoms; *wp != NULL; wp++) {
|
||||
shcomexec(wp);
|
||||
while (*wp != NULL)
|
||||
wp++;
|
||||
}
|
||||
setint(global("COLUMNS"), 0);
|
||||
setint(global("LINES"), 0);
|
||||
setint(global("OPTIND"), 1);
|
||||
vp = global("RANDOM");
|
||||
#if HAVE_ARC4RANDOM
|
||||
/* avoid calling setspec */
|
||||
Flag(FARC4RANDOM) = 1;
|
||||
vp->flag |= ISSET | INT_U;
|
||||
#else
|
||||
vp->flag |= INT_U;
|
||||
setint(vp, (mksh_ari_t)((unsigned long)kshname + 33 * ppid));
|
||||
#endif
|
||||
|
||||
safe_prompt = (ksheuid = geteuid()) ? "$ " : "# ";
|
||||
safe_prompt = ksheuid ? "$ " : "# ";
|
||||
vp = global("PS1");
|
||||
/* Set PS1 if unset or we are root and prompt doesn't contain a # */
|
||||
if (!(vp->flag & ISSET) ||
|
||||
(!ksheuid && !strchr(str_val(vp), '#')))
|
||||
/* setstr can't fail here */
|
||||
setstr(vp, safe_prompt, KSH_RETURN_ERROR);
|
||||
setint(global("PGRP"), (mksh_uari_t)(kshpgrp = getpgrp()));
|
||||
setint(global("PPID"), (mksh_uari_t)ppid);
|
||||
setint(global("USER_ID"), (mksh_uari_t)ksheuid);
|
||||
setint((vp = global("PGRP")), (mksh_uari_t)kshpgrp);
|
||||
vp->flag |= INT_U;
|
||||
setint((vp = global("PPID")), (mksh_uari_t)ppid);
|
||||
vp->flag |= INT_U;
|
||||
setint((vp = global("USER_ID")), (mksh_uari_t)ksheuid);
|
||||
vp->flag |= INT_U;
|
||||
|
||||
/* Set this before parsing arguments */
|
||||
#if HAVE_SETRESUGID
|
||||
@ -408,7 +421,7 @@ main(int argc, const char *argv[])
|
||||
|
||||
if (restricted) {
|
||||
static const char *restr_com[] = {
|
||||
"typeset", "-r", "PATH",
|
||||
T_typeset, "-r", "PATH",
|
||||
"ENV", "SHELL",
|
||||
NULL
|
||||
};
|
||||
@ -1263,27 +1276,6 @@ hash(const char *cp)
|
||||
return (h);
|
||||
}
|
||||
|
||||
#if !HAVE_ARC4RANDOM || !defined(MKSH_SMALL)
|
||||
uint32_t
|
||||
hashmem(const void *cp, size_t len)
|
||||
{
|
||||
register uint32_t h = 0;
|
||||
register const uint8_t *bp = (const uint8_t *)cp;
|
||||
|
||||
while (len--) {
|
||||
h += *bp++;
|
||||
h += h << 10;
|
||||
h ^= h >> 6;
|
||||
}
|
||||
|
||||
h += h << 3;
|
||||
h ^= h >> 11;
|
||||
h += h << 15;
|
||||
|
||||
return (h);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
texpand(struct table *tp, size_t nsize)
|
||||
{
|
||||
|
26
mksh.1
26
mksh.1
@ -1,4 +1,4 @@
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.191 2009/09/20 17:23:51 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.192 2009/09/26 03:40:00 tg Exp $
|
||||
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
|
||||
.\"-
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
@ -48,7 +48,7 @@
|
||||
.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
|
||||
..
|
||||
.\"-
|
||||
.Dd $Mdocdate: September 20 2009 $
|
||||
.Dd $Mdocdate: September 26 2009 $
|
||||
.Dt MKSH 1
|
||||
.Os MirBSD
|
||||
.Sh NAME
|
||||
@ -1807,10 +1807,11 @@ 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.
|
||||
See the description of
|
||||
.Ic set \-o Ic arc4random
|
||||
below for details.
|
||||
0 and 32767, first, which is taken from
|
||||
.Xr arc4random 3
|
||||
if available,
|
||||
.Xr rand 3
|
||||
otherwise.
|
||||
.It Ev REPLY
|
||||
Default parameter for the
|
||||
.Ic read
|
||||
@ -3735,17 +3736,10 @@ Print commands and parameter assignments when they are executed, preceded by
|
||||
the value of
|
||||
.Ev PS4 .
|
||||
.It Ic arc4random
|
||||
Use
|
||||
If this shell option, which cannot be unset, exists,
|
||||
.Xr arc4random 3
|
||||
high-quality random numbers for the value of
|
||||
.Ev RANDOM
|
||||
if set (to either 1 or 2), or a semi-predictable sequence from
|
||||
.Xr rand 3
|
||||
if unset.
|
||||
Setting this flag will change its value to 1; the default value is 2,
|
||||
which means it automatically switches to 0 if
|
||||
.Ev RANDOM
|
||||
is written to.
|
||||
is used for the value of
|
||||
.Ev RANDOM .
|
||||
.It Ic bgnice
|
||||
Background jobs are run with lower priority.
|
||||
.It Ic braceexpand
|
||||
|
30
sh.h
30
sh.h
@ -134,9 +134,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.348 2009/09/24 17:15:32 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.349 2009/09/26 03:40:01 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R39 2009/09/24"
|
||||
#define MKSH_VERSION "R39 2009/09/25"
|
||||
|
||||
#ifndef MKSH_INCLUDES_ONLY
|
||||
|
||||
@ -567,8 +567,11 @@ EXTERN char null[] I__("");
|
||||
/* helpers for string pooling */
|
||||
#define T_synerr "syntax error"
|
||||
EXTERN const char r_fc_e_[] I__("r=fc -e -");
|
||||
#define fc_e_ (r_fc_e_ + 2) /* "fc -e -" */
|
||||
#define fc_e_n 7 /* strlen(fc_e_) */
|
||||
#define fc_e_ (r_fc_e_ + 2) /* "fc -e -" */
|
||||
#define fc_e_n 7 /* strlen(fc_e_) */
|
||||
EXTERN const char T_local_typeset[] I__("local=typeset");
|
||||
#define T__typeset (T_local_typeset + 5) /* "=typeset" */
|
||||
#define T_typeset (T_local_typeset + 6) /* "typeset" */
|
||||
|
||||
enum temp_type {
|
||||
TT_HEREDOC_EXP, /* expanded heredoc */
|
||||
@ -963,21 +966,6 @@ struct builtin {
|
||||
|
||||
extern const struct builtin mkshbuiltins[];
|
||||
|
||||
/* var spec values */
|
||||
#define V_NONE 0
|
||||
#define V_COLUMNS 1
|
||||
#define V_HISTFILE 2
|
||||
#define V_HISTSIZE 3
|
||||
#define V_IFS 4
|
||||
#define V_LINENO 5
|
||||
#define V_LINES 6
|
||||
#define V_OPTIND 7
|
||||
#define V_PATH 8
|
||||
#define V_RANDOM 9
|
||||
#define V_SECONDS 10
|
||||
#define V_TMOUT 11
|
||||
#define V_TMPDIR 12
|
||||
|
||||
/* values for set_prompt() */
|
||||
#define PS1 0 /* command */
|
||||
#define PS2 1 /* command continuation */
|
||||
@ -1601,11 +1589,9 @@ void initvar(void);
|
||||
struct tbl *global(const char *);
|
||||
struct tbl *local(const char *, bool);
|
||||
char *str_val(struct tbl *);
|
||||
mksh_ari_t intval(struct tbl *);
|
||||
int setstr(struct tbl *, const char *, int);
|
||||
struct tbl *setint_v(struct tbl *, struct tbl *, bool);
|
||||
void setint(struct tbl *, mksh_ari_t);
|
||||
int getint(struct tbl *, mksh_ari_t *, bool);
|
||||
struct tbl *typeset(const char *, Tflag, Tflag, int, int);
|
||||
void unset(struct tbl *, int);
|
||||
const char *skip_varname(const char *, int);
|
||||
@ -1613,7 +1599,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 || !defined(MKSH_SMALL)
|
||||
#if !HAVE_ARC4RANDOM
|
||||
void change_random(unsigned long);
|
||||
#endif
|
||||
void change_winsz(void);
|
||||
|
@ -1,5 +1,5 @@
|
||||
#if defined(SHFLAGS_DEFNS)
|
||||
__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.2 2009/09/24 17:15:33 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.3 2009/09/26 03:40:02 tg Exp $");
|
||||
#define FN(sname,cname,ochar,flags) /* nothing */
|
||||
#elif defined(SHFLAGS_ENUMS)
|
||||
#define FN(sname,cname,ochar,flags) cname,
|
||||
@ -22,9 +22,8 @@ __RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.2 2009/09/24 17:15:33 tg Exp $");
|
||||
F0("allexport", FEXPORT, 'a', OF_ANY)
|
||||
|
||||
#if HAVE_ARC4RANDOM
|
||||
/* ./. for $RANDOM (non-standard), use the following function scheme: */
|
||||
/* 0:rand(3) 1:arc4random(3) 2:switch from 1 to 0 on write */
|
||||
FN("arc4random", FARC4RANDOM, 0, OF_ANY)
|
||||
/* ./. backwards compat: available if arc4random(3) is used for $RANDOM */
|
||||
FN("arc4random", FARC4RANDOM, 0, OF_INTERNAL)
|
||||
#endif
|
||||
|
||||
#if HAVE_NICE
|
||||
|
4
syn.c
4
syn.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.43 2009/09/23 18:04:58 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.44 2009/09/26 03:40:02 tg Exp $");
|
||||
|
||||
struct nesting_state {
|
||||
int start_token; /* token than began nesting (eg, FOR) */
|
||||
@ -877,7 +877,7 @@ assign_command(char *s)
|
||||
return ((strcmp(s, "alias") == 0) ||
|
||||
(strcmp(s, "export") == 0) ||
|
||||
(strcmp(s, "readonly") == 0) ||
|
||||
(strcmp(s, "typeset") == 0));
|
||||
(strcmp(s, T_typeset) == 0));
|
||||
}
|
||||
|
||||
/* Check if we are in the middle of reading an alias */
|
||||
|
190
var.c
190
var.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.91 2009/09/23 18:22:38 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.92 2009/09/26 03:40:02 tg Exp $");
|
||||
|
||||
/*
|
||||
* Variables
|
||||
@ -42,10 +42,16 @@ static void unspecial(const char *);
|
||||
static void getspec(struct tbl *);
|
||||
static void setspec(struct tbl *);
|
||||
static void unsetspec(struct tbl *);
|
||||
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 *);
|
||||
static int rnd_get(void);
|
||||
#if HAVE_ARC4RANDOM
|
||||
static void rnd_set(unsigned long);
|
||||
#else
|
||||
#define rnd_set change_random
|
||||
#endif
|
||||
|
||||
uint8_t set_refflag = 0;
|
||||
|
||||
@ -101,38 +107,33 @@ popblock(void)
|
||||
}
|
||||
|
||||
/* called by main() to initialise variable data structures */
|
||||
#define VARSPEC_DEFNS
|
||||
#include "var_spec.h"
|
||||
|
||||
enum var_specs {
|
||||
#define VARSPEC_ENUMS
|
||||
#include "var_spec.h"
|
||||
V_MAX
|
||||
};
|
||||
|
||||
static const char * const initvar_names[] = {
|
||||
#define VARSPEC_ITEMS
|
||||
#include "var_spec.h"
|
||||
};
|
||||
|
||||
void
|
||||
initvar(void)
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
int v;
|
||||
} names[] = {
|
||||
{ "COLUMNS", V_COLUMNS },
|
||||
#if HAVE_PERSISTENT_HISTORY
|
||||
{ "HISTFILE", V_HISTFILE },
|
||||
#endif
|
||||
{ "HISTSIZE", V_HISTSIZE },
|
||||
{ "IFS", V_IFS },
|
||||
{ "LINENO", V_LINENO },
|
||||
{ "LINES", V_LINES },
|
||||
{ "OPTIND", V_OPTIND },
|
||||
{ "PATH", V_PATH },
|
||||
{ "RANDOM", V_RANDOM },
|
||||
{ "SECONDS", V_SECONDS },
|
||||
{ "TMOUT", V_TMOUT },
|
||||
{ "TMPDIR", V_TMPDIR },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
int i;
|
||||
int i = 0;
|
||||
struct tbl *tp;
|
||||
|
||||
ktinit(&specials, APERM,
|
||||
/* must be 80% of 2^n (currently 12 specials) */ 16);
|
||||
for (i = 0; names[i].name; i++) {
|
||||
tp = ktenter(&specials, names[i].name, hash(names[i].name));
|
||||
while (i < V_MAX - 1) {
|
||||
tp = ktenter(&specials, initvar_names[i],
|
||||
hash(initvar_names[i]));
|
||||
tp->flag = DEFINED|ISSET;
|
||||
tp->type = names[i].v;
|
||||
tp->type = ++i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,7 +385,7 @@ str_val(struct tbl *vp)
|
||||
}
|
||||
|
||||
/* get variable integer value, with error checking */
|
||||
mksh_ari_t
|
||||
static mksh_ari_t
|
||||
intval(struct tbl *vp)
|
||||
{
|
||||
mksh_ari_t num;
|
||||
@ -461,7 +462,7 @@ setint(struct tbl *vq, mksh_ari_t n)
|
||||
setspec(vq);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
getint(struct tbl *vp, mksh_ari_t *nump, bool arith)
|
||||
{
|
||||
char *s;
|
||||
@ -964,150 +965,55 @@ makenv(void)
|
||||
return ((char **)XPclose(denv));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get us a random number, either from rand(3) or arc4random(3), with
|
||||
* the latter being preferred. If Flag(FARC4RANDOM) is 0, we use rand(3),
|
||||
* otherwise arc4random(3). We have static caches to make change_random
|
||||
* and writes to $RANDOM a cheap operation.
|
||||
*/
|
||||
#if HAVE_ARC4RANDOM && !defined(MKSH_SMALL)
|
||||
static uint32_t rnd_cache[2];
|
||||
static unsigned char rnd_lastflag = 2;
|
||||
#if HAVE_ARC4RANDOM_PUSHB
|
||||
static bool rnd_wpush = false;
|
||||
#define rnd_mix(v,w) rnd_cmix(v,w)
|
||||
#else
|
||||
#define rnd_mix(v,w) rnd_cmix(v)
|
||||
#endif
|
||||
|
||||
static void rnd_mix(unsigned long, bool);
|
||||
|
||||
static void
|
||||
rnd_mix(unsigned long newval, bool wantpush)
|
||||
{
|
||||
struct {
|
||||
union {
|
||||
int rval;
|
||||
uint32_t arval;
|
||||
} v0;
|
||||
uint32_t v1;
|
||||
uint32_t v2;
|
||||
unsigned long v3;
|
||||
#if HAVE_ARC4RANDOM_PUSHB
|
||||
bool neededpush;
|
||||
bool wantingpush;
|
||||
#endif
|
||||
} v;
|
||||
|
||||
#if HAVE_ARC4RANDOM_PUSHB
|
||||
v.neededpush = rnd_wpush;
|
||||
v.wantingpush = wantpush;
|
||||
rnd_wpush = v.neededpush || v.wantingpush;
|
||||
#endif
|
||||
|
||||
v.v0.rval = rand();
|
||||
v.v1 = rnd_cache[0];
|
||||
v.v2 = rnd_cache[1];
|
||||
v.v3 = newval;
|
||||
|
||||
rnd_cache[0] = hashmem(&v, sizeof(v));
|
||||
v.v0.arval = arc4random();
|
||||
rnd_cache[1] = hashmem(&v, sizeof(v));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_ARC4RANDOM
|
||||
static int
|
||||
rnd_get(void)
|
||||
{
|
||||
#if HAVE_ARC4RANDOM && defined(MKSH_SMALL)
|
||||
return (arc4random() & 0x7FFF);
|
||||
#else
|
||||
#if HAVE_ARC4RANDOM
|
||||
#if HAVE_ARC4RANDOM_PUSHB
|
||||
uint32_t rv = 0;
|
||||
#endif
|
||||
if (Flag(FARC4RANDOM) != rnd_lastflag) {
|
||||
if (Flag(FARC4RANDOM) == 0)
|
||||
/* transition to 0 by set: srand */
|
||||
srand(arc4random() & 0x7FFF);
|
||||
else if (rnd_lastflag == 0)
|
||||
/* transition from 0: addrandom */
|
||||
rnd_mix(rand(), true);
|
||||
rnd_lastflag = Flag(FARC4RANDOM);
|
||||
}
|
||||
if (Flag(FARC4RANDOM)) {
|
||||
if (rnd_cache[0] || rnd_cache[1]) {
|
||||
#if HAVE_ARC4RANDOM_PUSHB
|
||||
if (rnd_wpush) {
|
||||
rv = arc4random_pushb(rnd_cache,
|
||||
sizeof(rnd_cache));
|
||||
rnd_wpush = false;
|
||||
} else
|
||||
#endif
|
||||
arc4random_addrandom((void *)rnd_cache,
|
||||
sizeof(rnd_cache));
|
||||
}
|
||||
rnd_cache[0] = rnd_cache[1] = 0;
|
||||
return ((
|
||||
#if HAVE_ARC4RANDOM_PUSHB
|
||||
rv ? rv :
|
||||
#endif
|
||||
arc4random()) & 0x7FFF);
|
||||
}
|
||||
#endif
|
||||
return (rand() & 0x7FFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
rnd_set(unsigned long newval)
|
||||
{
|
||||
#if HAVE_ARC4RANDOM && defined(MKSH_SMALL)
|
||||
#if HAVE_ARC4RANDOM_PUSHB
|
||||
arc4random_pushb(&newval, sizeof(newval));
|
||||
#else
|
||||
arc4random_addrandom((void *)&newval, sizeof(newval));
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#if HAVE_ARC4RANDOM
|
||||
rnd_mix(newval, true);
|
||||
if (Flag(FARC4RANDOM) == 1)
|
||||
return;
|
||||
if (Flag(FARC4RANDOM) == 2)
|
||||
Flag(FARC4RANDOM) = 0;
|
||||
/* transition to 0 by write: only srand */
|
||||
rnd_lastflag = 0;
|
||||
#endif
|
||||
srand(newval & 0x7FFF);
|
||||
#endif
|
||||
static int
|
||||
rnd_get(void)
|
||||
{
|
||||
return (rand() & 0x7FFF);
|
||||
}
|
||||
|
||||
#if !HAVE_ARC4RANDOM || !defined(MKSH_SMALL)
|
||||
/*
|
||||
* Called after a fork to bump the random number generator.
|
||||
* Done to ensure children will not get the same random number sequence
|
||||
* as the parent processes.
|
||||
* Also called as rnd_set - mksh R40+ no longer has the traditional
|
||||
* repeatability of randomness sequences, state is always retained.
|
||||
*/
|
||||
void
|
||||
change_random(unsigned long newval)
|
||||
{
|
||||
int rval = 0;
|
||||
register unsigned int h;
|
||||
|
||||
#if HAVE_ARC4RANDOM
|
||||
if (Flag(FARC4RANDOM)) {
|
||||
rnd_mix(newval, false);
|
||||
return;
|
||||
h = rand();
|
||||
while (newval) {
|
||||
h += (newval & 0xFF);
|
||||
h += h << 10;
|
||||
h ^= h >> 6;
|
||||
newval >>= 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
rval += newval & 0x7FFF;
|
||||
newval >>= 15;
|
||||
rval += newval & 0x7FFF;
|
||||
newval >>= 15;
|
||||
rval += newval + rand();
|
||||
rval = (rval & 0x7FFF) ^ (rval >> 15);
|
||||
h += h << 3;
|
||||
h ^= h >> 11;
|
||||
h += h << 15;
|
||||
|
||||
srand(rval);
|
||||
/* pass all of it, in case RAND_MAX is large */
|
||||
srand(h);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
39
var_spec.h
Normal file
39
var_spec.h
Normal file
@ -0,0 +1,39 @@
|
||||
#if defined(VARSPEC_DEFNS)
|
||||
__RCSID("$MirOS: src/bin/mksh/var_spec.h,v 1.1 2009/09/26 03:40:03 tg Exp $");
|
||||
#define FN(name) /* nothing */
|
||||
#elif defined(VARSPEC_ENUMS)
|
||||
#define FN(name) V_##name,
|
||||
#define F0(name) V_##name = 0,
|
||||
#elif defined(VARSPEC_ITEMS)
|
||||
#define F0(name) /* nothing */
|
||||
#define FN(name) #name,
|
||||
#endif
|
||||
|
||||
#ifndef F0
|
||||
#define F0 FN
|
||||
#endif
|
||||
|
||||
/* 0 is always V_NONE */
|
||||
F0(NONE)
|
||||
|
||||
/* 1 and up are special variables */
|
||||
FN(COLUMNS)
|
||||
#if HAVE_PERSISTENT_HISTORY
|
||||
FN(HISTFILE)
|
||||
#endif
|
||||
FN(HISTSIZE)
|
||||
FN(IFS)
|
||||
FN(LINENO)
|
||||
FN(LINES)
|
||||
FN(OPTIND)
|
||||
FN(PATH)
|
||||
FN(RANDOM)
|
||||
FN(SECONDS)
|
||||
FN(TMOUT)
|
||||
FN(TMPDIR)
|
||||
|
||||
#undef FN
|
||||
#undef F0
|
||||
#undef VARSPEC_DEFNS
|
||||
#undef VARSPEC_ENUMS
|
||||
#undef VARSPEC_ITEMS
|
Loading…
x
Reference in New Issue
Block a user