• 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:
tg 2009-10-17 21:16:05 +00:00
parent 9f4376d2ad
commit eafe88aa74
6 changed files with 200 additions and 172 deletions

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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;
} }
} }