• overhaul handling of special variables
• use a combination of the one-at-a-time hash and an LCG for handling the $RANDOM special if !HAVE_ARC4RANDOM instead of rand(3)/srand(3) and get rid of time(3) usage to reduce import footprint • raise entropy state (mostly in the !HAVE_ARC4RANDOM case though…) • simplify handling of the $RANDOM_SPECIAL generally • tweak hash() to save a temp var for non-optimising compilers • some int → mksh_ari_t and other type fixes • general tweaking of code and comments
This commit is contained in:
parent
9f4376d2ad
commit
eafe88aa74
4
check.t
4
check.t
@ -1,4 +1,4 @@
|
|||||||
# $MirOS: src/bin/mksh/check.t,v 1.332 2009/10/15 16:36:25 tg Exp $
|
# $MirOS: src/bin/mksh/check.t,v 1.333 2009/10/17 21:16:01 tg Exp $
|
||||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas 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: 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 $
|
# $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
|
# http://www.research.att.com/~gsf/public/ifs.sh
|
||||||
|
|
||||||
expected-stdout:
|
expected-stdout:
|
||||||
@(#)MIRBSD KSH R39 2009/10/15
|
@(#)MIRBSD KSH R39 2009/10/17
|
||||||
description:
|
description:
|
||||||
Check version of shell.
|
Check version of shell.
|
||||||
stdin:
|
stdin:
|
||||||
|
35
jobs.c
35
jobs.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.61 2009/09/26 03:39:59 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.62 2009/10/17 21:16:02 tg Exp $");
|
||||||
|
|
||||||
#if HAVE_KILLPG
|
#if HAVE_KILLPG
|
||||||
#define mksh_killpg killpg
|
#define mksh_killpg killpg
|
||||||
@ -341,13 +341,16 @@ exchild(struct op *t, int flags,
|
|||||||
{
|
{
|
||||||
static Proc *last_proc; /* for pipelines */
|
static Proc *last_proc; /* for pipelines */
|
||||||
|
|
||||||
int i;
|
int i, rv = 0, forksleep;
|
||||||
sigset_t omask;
|
sigset_t omask;
|
||||||
Proc *p;
|
Proc *p;
|
||||||
Job *j;
|
Job *j;
|
||||||
int rv = 0;
|
struct {
|
||||||
int forksleep;
|
#if !HAVE_ARC4RANDOM
|
||||||
int ischild;
|
pid_t thepid;
|
||||||
|
#endif
|
||||||
|
unsigned char ischild;
|
||||||
|
} pi;
|
||||||
|
|
||||||
if (flags & XEXEC)
|
if (flags & XEXEC)
|
||||||
/* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND
|
/* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND
|
||||||
@ -410,15 +413,17 @@ exchild(struct op *t, int flags,
|
|||||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||||
errorf("cannot fork - try again");
|
errorf("cannot fork - try again");
|
||||||
}
|
}
|
||||||
ischild = i == 0;
|
#if !HAVE_ARC4RANDOM
|
||||||
if (ischild)
|
pi.thepid =
|
||||||
p->pid = procpid = getpid();
|
#endif
|
||||||
else
|
p->pid = (pi.ischild = i == 0) ? (procpid = getpid()) : i;
|
||||||
p->pid = i;
|
|
||||||
|
|
||||||
#if !HAVE_ARC4RANDOM
|
#if !HAVE_ARC4RANDOM
|
||||||
/* ensure next child gets a (slightly) different $RANDOM sequence */
|
/*
|
||||||
change_random(((unsigned long)p->pid << 1) | (ischild ? 1 : 0));
|
* ensure next child gets a (slightly) different $RANDOM sequence
|
||||||
|
* from its parent process and other child processes
|
||||||
|
*/
|
||||||
|
change_random(&pi, sizeof(pi));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MKSH_UNEMPLOYED
|
#ifndef MKSH_UNEMPLOYED
|
||||||
@ -440,10 +445,10 @@ exchild(struct op *t, int flags,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* used to close pipe input fd */
|
/* used to close pipe input fd */
|
||||||
if (close_fd >= 0 && (((flags & XPCLOSE) && !ischild) ||
|
if (close_fd >= 0 && (((flags & XPCLOSE) && !pi.ischild) ||
|
||||||
((flags & XCCLOSE) && ischild)))
|
((flags & XCCLOSE) && pi.ischild)))
|
||||||
close(close_fd);
|
close(close_fd);
|
||||||
if (ischild) { /* child */
|
if (pi.ischild) { /* child */
|
||||||
/* Do this before restoring signal */
|
/* Do this before restoring signal */
|
||||||
if (flags & XCOPROC)
|
if (flags & XCOPROC)
|
||||||
coproc_cleanup(false);
|
coproc_cleanup(false);
|
||||||
|
27
main.c
27
main.c
@ -33,7 +33,7 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.152 2009/10/02 18:08:34 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.153 2009/10/17 21:16:02 tg Exp $");
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
@ -93,7 +93,6 @@ main(int argc, const char *argv[])
|
|||||||
struct block *l;
|
struct block *l;
|
||||||
unsigned char restricted, errexit;
|
unsigned char restricted, errexit;
|
||||||
const char **wp;
|
const char **wp;
|
||||||
pid_t ppid;
|
|
||||||
struct tbl *vp;
|
struct tbl *vp;
|
||||||
struct stat s_stdin;
|
struct stat s_stdin;
|
||||||
#if !defined(_PATH_DEFPATH) && defined(_CS_PATH)
|
#if !defined(_PATH_DEFPATH) && defined(_CS_PATH)
|
||||||
@ -104,11 +103,10 @@ main(int argc, const char *argv[])
|
|||||||
kshpid = procpid = getpid();
|
kshpid = procpid = getpid();
|
||||||
ksheuid = geteuid();
|
ksheuid = geteuid();
|
||||||
kshpgrp = getpgrp();
|
kshpgrp = getpgrp();
|
||||||
ppid = getppid();
|
kshppid = getppid();
|
||||||
|
|
||||||
#if !HAVE_ARC4RANDOM
|
#if !HAVE_ARC4RANDOM
|
||||||
change_random((unsigned long)time(NULL));
|
change_random(&kshstate_, sizeof(kshstate_));
|
||||||
change_random(((unsigned long)ksheuid << 16) | kshpid);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* make sure argv[] is sane */
|
/* make sure argv[] is sane */
|
||||||
@ -267,15 +265,6 @@ main(int argc, const char *argv[])
|
|||||||
setint(global("COLUMNS"), 0);
|
setint(global("COLUMNS"), 0);
|
||||||
setint(global("LINES"), 0);
|
setint(global("LINES"), 0);
|
||||||
setint(global("OPTIND"), 1);
|
setint(global("OPTIND"), 1);
|
||||||
vp = global("RANDOM");
|
|
||||||
#if HAVE_ARC4RANDOM
|
|
||||||
Flag(FARC4RANDOM) = 1;
|
|
||||||
/* avoid calling setspec */
|
|
||||||
vp->flag |= ISSET | INT_U;
|
|
||||||
#else
|
|
||||||
vp->flag |= INT_U;
|
|
||||||
setint(vp, (mksh_ari_t)((unsigned long)kshname + 33 * ppid));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
safe_prompt = ksheuid ? "$ " : "# ";
|
safe_prompt = ksheuid ? "$ " : "# ";
|
||||||
vp = global("PS1");
|
vp = global("PS1");
|
||||||
@ -286,10 +275,15 @@ main(int argc, const char *argv[])
|
|||||||
setstr(vp, safe_prompt, KSH_RETURN_ERROR);
|
setstr(vp, safe_prompt, KSH_RETURN_ERROR);
|
||||||
setint((vp = global("PGRP")), (mksh_uari_t)kshpgrp);
|
setint((vp = global("PGRP")), (mksh_uari_t)kshpgrp);
|
||||||
vp->flag |= INT_U;
|
vp->flag |= INT_U;
|
||||||
setint((vp = global("PPID")), (mksh_uari_t)ppid);
|
setint((vp = global("PPID")), (mksh_uari_t)kshppid);
|
||||||
|
vp->flag |= INT_U;
|
||||||
|
setint((vp = global("RANDOM")), (mksh_uari_t)hash(kshname));
|
||||||
vp->flag |= INT_U;
|
vp->flag |= INT_U;
|
||||||
setint((vp = global("USER_ID")), (mksh_uari_t)ksheuid);
|
setint((vp = global("USER_ID")), (mksh_uari_t)ksheuid);
|
||||||
vp->flag |= INT_U;
|
vp->flag |= INT_U;
|
||||||
|
#if HAVE_ARC4RANDOM
|
||||||
|
Flag(FARC4RANDOM) = 1; /* initialised */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set this before parsing arguments */
|
/* Set this before parsing arguments */
|
||||||
#if HAVE_SETRESUGID
|
#if HAVE_SETRESUGID
|
||||||
@ -1261,11 +1255,10 @@ static struct tbl *ktscan(struct table *, const char *, uint32_t,
|
|||||||
|
|
||||||
/* Bob Jenkins' one-at-a-time hash */
|
/* Bob Jenkins' one-at-a-time hash */
|
||||||
uint32_t
|
uint32_t
|
||||||
hash(const char *cp)
|
oaathash_full(register const uint8_t *bp)
|
||||||
{
|
{
|
||||||
register uint32_t h = 0;
|
register uint32_t h = 0;
|
||||||
register uint8_t c;
|
register uint8_t c;
|
||||||
register const uint8_t *bp = (const uint8_t *)cp;
|
|
||||||
|
|
||||||
while ((c = *bp++)) {
|
while ((c = *bp++)) {
|
||||||
h += c;
|
h += c;
|
||||||
|
8
mksh.1
8
mksh.1
@ -1,4 +1,4 @@
|
|||||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.194 2009/10/10 21:17:30 tg Exp $
|
.\" $MirOS: src/bin/mksh/mksh.1,v 1.195 2009/10/17 21:16:03 tg Exp $
|
||||||
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
|
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
|
||||||
.\"-
|
.\"-
|
||||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
@ -48,7 +48,7 @@
|
|||||||
.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
|
.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
|
||||||
..
|
..
|
||||||
.\"-
|
.\"-
|
||||||
.Dd $Mdocdate: October 10 2009 $
|
.Dd $Mdocdate: October 17 2009 $
|
||||||
.Dt MKSH 1
|
.Dt MKSH 1
|
||||||
.Os MirBSD
|
.Os MirBSD
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -1810,7 +1810,7 @@ is referenced, it is assigned a 15-bit pseudo-random number, i.e. between
|
|||||||
0 and 32767, first, which is taken from
|
0 and 32767, first, which is taken from
|
||||||
.Xr arc4random 3
|
.Xr arc4random 3
|
||||||
if available,
|
if available,
|
||||||
.Xr rand 3
|
a Linear Congruential PRNG
|
||||||
otherwise.
|
otherwise.
|
||||||
.It Ev REPLY
|
.It Ev REPLY
|
||||||
Default parameter for the
|
Default parameter for the
|
||||||
@ -5736,10 +5736,8 @@ Privileged shell profile.
|
|||||||
.Xr arc4random 3 ,
|
.Xr arc4random 3 ,
|
||||||
.Xr getopt 3 ,
|
.Xr getopt 3 ,
|
||||||
.Xr nl_langinfo 3 ,
|
.Xr nl_langinfo 3 ,
|
||||||
.Xr rand 3 ,
|
|
||||||
.Xr setlocale 3 ,
|
.Xr setlocale 3 ,
|
||||||
.Xr signal 3 ,
|
.Xr signal 3 ,
|
||||||
.Xr srand 3 ,
|
|
||||||
.Xr system 3 ,
|
.Xr system 3 ,
|
||||||
.Xr tty 4 ,
|
.Xr tty 4 ,
|
||||||
.Xr shells 5 ,
|
.Xr shells 5 ,
|
||||||
|
39
sh.h
39
sh.h
@ -134,9 +134,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXTERN
|
#ifdef EXTERN
|
||||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.355 2009/10/15 16:36:27 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.356 2009/10/17 21:16:04 tg Exp $");
|
||||||
#endif
|
#endif
|
||||||
#define MKSH_VERSION "R39 2009/10/15"
|
#define MKSH_VERSION "R39 2009/10/17"
|
||||||
|
|
||||||
#ifndef MKSH_INCLUDES_ONLY
|
#ifndef MKSH_INCLUDES_ONLY
|
||||||
|
|
||||||
@ -348,13 +348,25 @@ typedef uint32_t mksh_uari_t;
|
|||||||
#define PATH_MAX 1024 /* pathname size */
|
#define PATH_MAX 1024 /* pathname size */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EXTERN const char *kshname; /* $0 */
|
EXTERN struct {
|
||||||
EXTERN pid_t kshpid; /* $$, shell pid */
|
const char *kshname_; /* $0 */
|
||||||
EXTERN pid_t procpid; /* pid of executing process */
|
pid_t kshpid_; /* $$, shell PID */
|
||||||
EXTERN pid_t kshpgrp; /* process group of shell */
|
pid_t procpid_; /* PID of executing process */
|
||||||
EXTERN uid_t ksheuid; /* effective uid of shell */
|
pid_t kshpgrp_; /* process group of shell */
|
||||||
EXTERN int exstat; /* exit status */
|
uid_t ksheuid_; /* effective UID of shell */
|
||||||
EXTERN int subst_exstat; /* exit status of last $(..)/`..` */
|
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 *safe_prompt; /* safe prompt if PS1 substitution fails */
|
||||||
EXTERN const char initvsn[] I__("KSH_VERSION=@(#)MIRBSD KSH " MKSH_VERSION);
|
EXTERN const char initvsn[] I__("KSH_VERSION=@(#)MIRBSD KSH " MKSH_VERSION);
|
||||||
#define KSH_VERSION (initvsn + /* "KSH_VERSION=@(#)" */ 16)
|
#define KSH_VERSION (initvsn + /* "KSH_VERSION=@(#)" */ 16)
|
||||||
@ -735,8 +747,8 @@ EXTERN size_t current_wd_size;
|
|||||||
*/
|
*/
|
||||||
#define MIN_COLS (2 + MIN_EDIT_SPACE + 3)
|
#define MIN_COLS (2 + MIN_EDIT_SPACE + 3)
|
||||||
#define MIN_LINS 3
|
#define MIN_LINS 3
|
||||||
EXTERN int x_cols I__(80); /* tty columns */
|
EXTERN mksh_ari_t x_cols I__(80); /* tty columns */
|
||||||
EXTERN int x_lins I__(-1); /* tty lines */
|
EXTERN mksh_ari_t x_lins I__(-1); /* tty lines */
|
||||||
|
|
||||||
/* These to avoid bracket matching problems */
|
/* These to avoid bracket matching problems */
|
||||||
#define OPAREN '('
|
#define OPAREN '('
|
||||||
@ -1505,7 +1517,8 @@ void coproc_write_close(int);
|
|||||||
int coproc_getfd(int, const char **);
|
int coproc_getfd(int, const char **);
|
||||||
void coproc_cleanup(int);
|
void coproc_cleanup(int);
|
||||||
struct temp *maketemp(Area *, Temp_type, struct temp **);
|
struct temp *maketemp(Area *, Temp_type, struct temp **);
|
||||||
uint32_t hash(const char *);
|
#define hash(s) oaathash_full((const uint8_t *)(s))
|
||||||
|
uint32_t oaathash_full(register const uint8_t *);
|
||||||
uint32_t hashmem(const void *, size_t);
|
uint32_t hashmem(const void *, size_t);
|
||||||
void ktinit(struct table *, Area *, size_t);
|
void ktinit(struct table *, Area *, size_t);
|
||||||
struct tbl *ktsearch(struct table *, const char *, uint32_t);
|
struct tbl *ktsearch(struct table *, const char *, uint32_t);
|
||||||
@ -1601,7 +1614,7 @@ int is_wdvarname(const char *, int);
|
|||||||
int is_wdvarassign(const char *);
|
int is_wdvarassign(const char *);
|
||||||
char **makenv(void);
|
char **makenv(void);
|
||||||
#if !HAVE_ARC4RANDOM
|
#if !HAVE_ARC4RANDOM
|
||||||
void change_random(unsigned long);
|
void change_random(const void *, size_t);
|
||||||
#endif
|
#endif
|
||||||
void change_winsz(void);
|
void change_winsz(void);
|
||||||
int array_ref_len(const char *);
|
int array_ref_len(const char *);
|
||||||
|
251
var.c
251
var.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.94 2009/09/27 10:31:06 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.95 2009/10/17 21:16:05 tg Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Variables
|
* Variables
|
||||||
@ -46,11 +46,11 @@ static int getint(struct tbl *, mksh_ari_t *, bool);
|
|||||||
static mksh_ari_t intval(struct tbl *);
|
static mksh_ari_t intval(struct tbl *);
|
||||||
static struct tbl *arraysearch(struct tbl *, uint32_t);
|
static struct tbl *arraysearch(struct tbl *, uint32_t);
|
||||||
static const char *array_index_calc(const char *, bool *, uint32_t *);
|
static const char *array_index_calc(const char *, bool *, uint32_t *);
|
||||||
static int rnd_get(void);
|
#if !HAVE_ARC4RANDOM
|
||||||
#if HAVE_ARC4RANDOM
|
static uint32_t oaathash_update(register uint32_t, register const uint8_t *,
|
||||||
static void rnd_set(unsigned long);
|
register size_t);
|
||||||
#else
|
|
||||||
#define rnd_set change_random
|
static uint32_t lcg_seed = 5381;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t set_refflag = 0;
|
uint8_t set_refflag = 0;
|
||||||
@ -972,58 +972,45 @@ makenv(void)
|
|||||||
return ((char **)XPclose(denv));
|
return ((char **)XPclose(denv));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_ARC4RANDOM
|
#if !HAVE_ARC4RANDOM
|
||||||
static int
|
static uint32_t
|
||||||
rnd_get(void)
|
oaathash_update(register uint32_t h, register const uint8_t *cp,
|
||||||
|
register size_t n)
|
||||||
{
|
{
|
||||||
return (arc4random() & 0x7FFF);
|
while (n--) {
|
||||||
}
|
h += *cp++;
|
||||||
|
|
||||||
static void
|
|
||||||
rnd_set(unsigned long newval)
|
|
||||||
{
|
|
||||||
#if HAVE_ARC4RANDOM_PUSHB
|
|
||||||
if (Flag(FARC4RANDOM))
|
|
||||||
/* initialisation, environment import, etc. already done */
|
|
||||||
arc4random_pushb(&newval, sizeof(newval));
|
|
||||||
else
|
|
||||||
/* during start-up phase or somesuch */
|
|
||||||
#endif
|
|
||||||
arc4random_addrandom((void *)&newval, sizeof(newval));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static int
|
|
||||||
rnd_get(void)
|
|
||||||
{
|
|
||||||
return (rand() & 0x7FFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
register unsigned int h;
|
|
||||||
|
|
||||||
h = rand();
|
|
||||||
while (newval) {
|
|
||||||
h += (newval & 0xFF);
|
|
||||||
h += h << 10;
|
h += h << 10;
|
||||||
h ^= h >> 6;
|
h ^= h >> 6;
|
||||||
newval >>= 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
change_random(const void *vp, size_t n)
|
||||||
|
{
|
||||||
|
register uint32_t h;
|
||||||
|
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_seed;
|
||||||
|
i.bp = &lcg_seed;
|
||||||
|
i.sp = &i;
|
||||||
|
gettimeofday(&i.tv, NULL);
|
||||||
|
h = oaathash_update(oaathash_update(1, (void *)&i, sizeof(i)), vp, n);
|
||||||
|
|
||||||
|
/* oaathash_finalise */
|
||||||
h += h << 3;
|
h += h << 3;
|
||||||
h ^= h >> 11;
|
h ^= h >> 11;
|
||||||
h += h << 15;
|
h += h << 15;
|
||||||
|
|
||||||
/* pass all of it, in case RAND_MAX is large */
|
lcg_seed = h;
|
||||||
srand(h);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1058,82 +1045,84 @@ static int user_lineno; /* what user set $LINENO to */
|
|||||||
static void
|
static void
|
||||||
getspec(struct tbl *vp)
|
getspec(struct tbl *vp)
|
||||||
{
|
{
|
||||||
int i;
|
register mksh_ari_t i;
|
||||||
|
int st;
|
||||||
|
|
||||||
switch ((i = special(vp->name))) {
|
switch ((st = special(vp->name))) {
|
||||||
case V_SECONDS:
|
case V_SECONDS:
|
||||||
vp->flag &= ~SPECIAL;
|
/*
|
||||||
/* On start up the value of SECONDS is used before seconds
|
* On start up the value of SECONDS is used before
|
||||||
* has been set - don't do anything in this case
|
* it has been set - don't do anything in this case
|
||||||
* (see initcoms[] in main.c).
|
* (see initcoms[] in main.c).
|
||||||
*/
|
*/
|
||||||
if (vp->flag & ISSET) {
|
if (vp->flag & ISSET) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
setint(vp, tv.tv_sec - seconds);
|
i = tv.tv_sec - seconds;
|
||||||
}
|
} else
|
||||||
vp->flag |= SPECIAL;
|
return;
|
||||||
break;
|
break;
|
||||||
case V_RANDOM:
|
case V_RANDOM:
|
||||||
vp->flag &= ~SPECIAL;
|
#if HAVE_ARC4RANDOM
|
||||||
setint(vp, rnd_get());
|
i = arc4random() & 0x7FFF;
|
||||||
vp->flag |= SPECIAL;
|
#else
|
||||||
|
/*
|
||||||
|
* this is the same Linear Congruential PRNG as Borland
|
||||||
|
* C/C++ allegedly uses in its built-in rand() function
|
||||||
|
*/
|
||||||
|
i = ((lcg_seed = 22695477 * lcg_seed + 1) >> 16) & 0x7FFF;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case V_HISTSIZE:
|
case V_HISTSIZE:
|
||||||
vp->flag &= ~SPECIAL;
|
i = histsize;
|
||||||
setint(vp, (mksh_ari_t)histsize);
|
|
||||||
vp->flag |= SPECIAL;
|
|
||||||
break;
|
break;
|
||||||
case V_OPTIND:
|
case V_OPTIND:
|
||||||
vp->flag &= ~SPECIAL;
|
i = user_opt.uoptind;
|
||||||
setint(vp, (mksh_ari_t)user_opt.uoptind);
|
|
||||||
vp->flag |= SPECIAL;
|
|
||||||
break;
|
break;
|
||||||
case V_LINENO:
|
case V_LINENO:
|
||||||
vp->flag &= ~SPECIAL;
|
i = current_lineno + user_lineno;
|
||||||
setint(vp, (mksh_ari_t)current_lineno + user_lineno);
|
|
||||||
vp->flag |= SPECIAL;
|
|
||||||
break;
|
break;
|
||||||
case V_COLUMNS:
|
case V_COLUMNS:
|
||||||
case V_LINES:
|
case V_LINES:
|
||||||
/* Do NOT export COLUMNS/LINES. Many applications
|
/*
|
||||||
|
* Do NOT export COLUMNS/LINES. Many applications
|
||||||
* check COLUMNS/LINES before checking ws.ws_col/row,
|
* check COLUMNS/LINES before checking ws.ws_col/row,
|
||||||
* so if the app is started with C/L in the environ
|
* so if the app is started with C/L in the environ
|
||||||
* and the window is then resized, the app won't
|
* and the window is then resized, the app won't
|
||||||
* see the change cause the environ doesn't change.
|
* see the change cause the environ doesn't change.
|
||||||
*/
|
*/
|
||||||
vp->flag &= ~SPECIAL;
|
|
||||||
change_winsz();
|
change_winsz();
|
||||||
setint(vp, i == V_COLUMNS ? x_cols : x_lins);
|
i = st == V_COLUMNS ? x_cols : x_lins;
|
||||||
vp->flag |= SPECIAL;
|
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
/* do nothing, do not touch vp at all */
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
vp->flag &= ~SPECIAL;
|
||||||
|
setint(vp, i);
|
||||||
|
vp->flag |= SPECIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
setspec(struct tbl *vp)
|
setspec(struct tbl *vp)
|
||||||
{
|
{
|
||||||
int i;
|
mksh_ari_t i;
|
||||||
char *s;
|
char *s;
|
||||||
|
int st;
|
||||||
|
|
||||||
switch (special(vp->name)) {
|
switch ((st = special(vp->name))) {
|
||||||
case V_PATH:
|
case V_PATH:
|
||||||
if (path)
|
if (path)
|
||||||
afree(path, APERM);
|
afree(path, APERM);
|
||||||
s = str_val(vp);
|
s = str_val(vp);
|
||||||
strdupx(path, s, APERM);
|
strdupx(path, s, APERM);
|
||||||
flushcom(1); /* clear tracked aliases */
|
flushcom(1); /* clear tracked aliases */
|
||||||
break;
|
return;
|
||||||
case V_IFS:
|
case V_IFS:
|
||||||
setctypes(s = str_val(vp), C_IFS);
|
setctypes(s = str_val(vp), C_IFS);
|
||||||
ifs0 = *s;
|
ifs0 = *s;
|
||||||
break;
|
return;
|
||||||
case V_OPTIND:
|
|
||||||
vp->flag &= ~SPECIAL;
|
|
||||||
getopts_reset((int)intval(vp));
|
|
||||||
vp->flag |= SPECIAL;
|
|
||||||
break;
|
|
||||||
case V_TMPDIR:
|
case V_TMPDIR:
|
||||||
if (tmpdir) {
|
if (tmpdir) {
|
||||||
afree(tmpdir, APERM);
|
afree(tmpdir, APERM);
|
||||||
@ -1151,54 +1140,84 @@ setspec(struct tbl *vp)
|
|||||||
strdupx(tmpdir, s, APERM);
|
strdupx(tmpdir, s, APERM);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case V_HISTSIZE:
|
|
||||||
vp->flag &= ~SPECIAL;
|
|
||||||
sethistsize((int)intval(vp));
|
|
||||||
vp->flag |= SPECIAL;
|
|
||||||
break;
|
|
||||||
#if HAVE_PERSISTENT_HISTORY
|
#if HAVE_PERSISTENT_HISTORY
|
||||||
case V_HISTFILE:
|
case V_HISTFILE:
|
||||||
sethistfile(str_val(vp));
|
sethistfile(str_val(vp));
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case V_COLUMNS:
|
|
||||||
vp->flag &= ~SPECIAL;
|
|
||||||
if ((i = intval(vp)) >= MIN_COLS)
|
|
||||||
x_cols = i;
|
|
||||||
vp->flag |= SPECIAL;
|
|
||||||
break;
|
|
||||||
case V_LINES:
|
|
||||||
vp->flag &= ~SPECIAL;
|
|
||||||
if ((i = intval(vp)) >= MIN_LINS)
|
|
||||||
x_lins = i;
|
|
||||||
vp->flag |= SPECIAL;
|
|
||||||
break;
|
|
||||||
case V_RANDOM:
|
|
||||||
vp->flag &= ~SPECIAL;
|
|
||||||
rnd_set(intval(vp));
|
|
||||||
vp->flag |= SPECIAL;
|
|
||||||
break;
|
|
||||||
case V_SECONDS:
|
|
||||||
vp->flag &= ~SPECIAL;
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
seconds = tv.tv_sec - intval(vp);
|
|
||||||
}
|
|
||||||
vp->flag |= SPECIAL;
|
|
||||||
break;
|
|
||||||
case V_TMOUT:
|
case V_TMOUT:
|
||||||
/* AT&T ksh seems to do this (only listen if integer) */
|
/* AT&T ksh seems to do this (only listen if integer) */
|
||||||
if (vp->flag & INTEGER)
|
if (vp->flag & INTEGER)
|
||||||
ksh_tmout = vp->val.i >= 0 ? vp->val.i : 0;
|
ksh_tmout = vp->val.i >= 0 ? vp->val.i : 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* common sub-cases */
|
||||||
|
case V_OPTIND:
|
||||||
|
case V_HISTSIZE:
|
||||||
|
case V_COLUMNS:
|
||||||
|
case V_LINES:
|
||||||
|
case V_RANDOM:
|
||||||
|
case V_SECONDS:
|
||||||
case V_LINENO:
|
case V_LINENO:
|
||||||
vp->flag &= ~SPECIAL;
|
vp->flag &= ~SPECIAL;
|
||||||
/* The -1 is because line numbering starts at 1. */
|
i = intval(vp);
|
||||||
user_lineno = (unsigned int)intval(vp) - current_lineno - 1;
|
|
||||||
vp->flag |= SPECIAL;
|
vp->flag |= SPECIAL;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
/* do nothing, do not touch vp at all */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process the singular parts of the common cases */
|
||||||
|
|
||||||
|
switch (st) {
|
||||||
|
case V_OPTIND:
|
||||||
|
getopts_reset((int)i);
|
||||||
|
break;
|
||||||
|
case V_HISTSIZE:
|
||||||
|
sethistsize((int)i);
|
||||||
|
break;
|
||||||
|
case V_COLUMNS:
|
||||||
|
if (i >= MIN_COLS)
|
||||||
|
x_cols = i;
|
||||||
|
break;
|
||||||
|
case V_LINES:
|
||||||
|
if (i >= MIN_LINS)
|
||||||
|
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
|
||||||
|
* of $RANDOM sequences, but always retains state
|
||||||
|
*/
|
||||||
|
change_random(&i, sizeof(i));
|
||||||
|
#endif /* !HAVE_ARC4RANDOM */
|
||||||
|
break;
|
||||||
|
case V_SECONDS:
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
seconds = tv.tv_sec - i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case V_LINENO:
|
||||||
|
/* The -1 is because line numbering starts at 1. */
|
||||||
|
user_lineno = (unsigned int)i - current_lineno - 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user