• 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:
		
							
								
								
									
										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: | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								jobs.c
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								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 | ||||||
| @@ -339,15 +339,18 @@ exchild(struct op *t, int flags, | |||||||
|     volatile int *xerrok, |     volatile int *xerrok, | ||||||
|     /* used if XPCLOSE or XCCLOSE */ int close_fd) |     /* used if XPCLOSE or XCCLOSE */ int close_fd) | ||||||
| { | { | ||||||
| 	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; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user