• implement KSHEGID, KSHGID, KSHUID variables by suggestion of Richard K.

(KSHEUID aka USER_ID already exists)
• simplify, speed up LCG and $RANDOM handling again
This commit is contained in:
tg 2011-01-21 21:04:48 +00:00
parent 1d6e0470e0
commit cc31d86e3b
6 changed files with 284 additions and 270 deletions

109
jobs.c
View File

@ -1,7 +1,7 @@
/* $OpenBSD: jobs.c,v 1.38 2009/12/12 04:28:44 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.72 2010/08/28 20:22:19 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.73 2011/01/21 21:04:44 tg Exp $");
#if HAVE_KILLPG
#define mksh_killpg killpg
@ -342,11 +342,9 @@ exchild(struct op *t, int flags,
int rv = 0, forksleep;
sigset_t omask;
struct {
Proc *p;
Job *j;
pid_t cldpid;
} pi;
Proc *p;
Job *j;
pid_t cldpid;
if (flags & XEXEC)
/*
@ -358,11 +356,11 @@ exchild(struct op *t, int flags,
/* no SIGCHLDs while messing with job and process lists */
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
pi.p = new_proc();
pi.p->next = NULL;
pi.p->state = PRUNNING;
pi.p->status = 0;
pi.p->pid = 0;
p = new_proc();
p->next = NULL;
p->state = PRUNNING;
p->status = 0;
p->pid = 0;
/* link process into jobs list */
if (flags & XPIPEI) {
@ -371,78 +369,76 @@ exchild(struct op *t, int flags,
internal_errorf("%s %d",
"exchild: XPIPEI and no last_job - pid",
(int)procpid);
pi.j = last_job;
j = last_job;
if (last_proc)
last_proc->next = pi.p;
last_proc = pi.p;
last_proc->next = p;
last_proc = p;
} else {
pi.j = new_job(); /* fills in pi.j->job */
/* fills in j->job */
j = new_job();
/*
* we don't consider XXCOMs foreground since they don't get
* tty process group and we don't save or restore tty modes.
*/
pi.j->flags = (flags & XXCOM) ? JF_XXCOM :
j->flags = (flags & XXCOM) ? JF_XXCOM :
((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE));
timerclear(&pi.j->usrtime);
timerclear(&pi.j->systime);
pi.j->state = PRUNNING;
pi.j->pgrp = 0;
pi.j->ppid = procpid;
pi.j->age = ++njobs;
pi.j->proc_list = pi.p;
pi.j->coproc_id = 0;
last_job = pi.j;
last_proc = pi.p;
put_job(pi.j, PJ_PAST_STOPPED);
timerclear(&j->usrtime);
timerclear(&j->systime);
j->state = PRUNNING;
j->pgrp = 0;
j->ppid = procpid;
j->age = ++njobs;
j->proc_list = p;
j->coproc_id = 0;
last_job = j;
last_proc = p;
put_job(j, PJ_PAST_STOPPED);
}
snptreef(pi.p->command, sizeof(pi.p->command), "%T", t);
snptreef(p->command, sizeof(p->command), "%T", t);
/* create child process */
forksleep = 1;
while ((pi.cldpid = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
while ((cldpid = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
if (intrsig) /* allow user to ^C out... */
break;
sleep(forksleep);
forksleep <<= 1;
}
if (pi.cldpid < 0) {
kill_job(pi.j, SIGKILL);
remove_job(pi.j, "fork failed");
/* ensure $RANDOM changes between parent and child */
rndset((long)cldpid);
/* fork failed? */
if (cldpid < 0) {
kill_job(j, SIGKILL);
remove_job(j, "fork failed");
sigprocmask(SIG_SETMASK, &omask, NULL);
errorf("can't fork - try again");
}
pi.p->pid = pi.cldpid ? pi.cldpid : (procpid = getpid());
/*
* ensure next child gets a (slightly) different $RANDOM sequence
* from its parent process and other child processes
*/
change_random(&pi, sizeof(pi));
p->pid = cldpid ? cldpid : (procpid = getpid());
#ifndef MKSH_UNEMPLOYED
/* job control set up */
if (Flag(FMONITOR) && !(flags&XXCOM)) {
int dotty = 0;
if (pi.j->pgrp == 0) { /* First process */
pi.j->pgrp = pi.p->pid;
if (j->pgrp == 0) { /* First process */
j->pgrp = p->pid;
dotty = 1;
}
/* set pgrp in both parent and child to deal with race
* condition
*/
setpgid(pi.p->pid, pi.j->pgrp);
setpgid(p->pid, j->pgrp);
if (ttypgrp_ok && dotty && !(flags & XBGND))
tcsetpgrp(tty_fd, pi.j->pgrp);
tcsetpgrp(tty_fd, j->pgrp);
}
#endif
/* used to close pipe input fd */
if (close_fd >= 0 && (((flags & XPCLOSE) && pi.cldpid) ||
((flags & XCCLOSE) && !pi.cldpid)))
if (close_fd >= 0 && (((flags & XPCLOSE) && cldpid) ||
((flags & XCCLOSE) && !cldpid)))
close(close_fd);
if (!pi.cldpid) {
if (!cldpid) {
/* child */
/* Do this before restoring signal */
@ -480,7 +476,7 @@ exchild(struct op *t, int flags,
close(forksleep);
}
}
remove_job(pi.j, "child"); /* in case of $(jobs) command */
remove_job(j, "child"); /* in case of $(jobs) command */
nzombie = 0;
#ifndef MKSH_UNEMPLOYED
ttypgrp_ok = false;
@ -505,27 +501,26 @@ exchild(struct op *t, int flags,
/* shell (parent) stuff */
if (!(flags & XPIPEO)) { /* last process in a job */
j_startjob(pi.j);
j_startjob(j);
if (flags & XCOPROC) {
pi.j->coproc_id = coproc.id;
j->coproc_id = coproc.id;
/* n jobs using co-process output */
coproc.njobs++;
/* j using co-process input */
coproc.job = (void *)pi.j;
coproc.job = (void *)j;
}
if (flags & XBGND) {
j_set_async(pi.j);
j_set_async(j);
if (Flag(FTALKING)) {
shf_fprintf(shl_out, "[%d]", pi.j->job);
for (pi.p = pi.j->proc_list; pi.p;
pi.p = pi.p->next)
shf_fprintf(shl_out, "[%d]", j->job);
for (p = j->proc_list; p; p = p->next)
shf_fprintf(shl_out, " %d",
(int)pi.p->pid);
(int)p->pid);
shf_putchar('\n', shl_out);
shf_flush(shl_out);
}
} else
rv = j_waitj(pi.j, JW_NONE, "jw:last proc");
rv = j_waitj(j, JW_NONE, "jw:last proc");
}
sigprocmask(SIG_SETMASK, &omask, NULL);

176
main.c
View File

@ -4,7 +4,7 @@
/* $OpenBSD: table.c,v 1.13 2009/01/17 22:06:44 millert Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@ -33,15 +33,10 @@
#include <locale.h>
#endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.173 2010/11/01 17:29:04 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.174 2011/01/21 21:04:44 tg Exp $");
extern char **environ;
#if !HAVE_SETRESUGID
extern uid_t kshuid;
extern gid_t kshgid, kshegid;
#endif
#ifndef MKSHRC_PATH
#define MKSHRC_PATH "~/.mkshrc"
#endif
@ -50,10 +45,10 @@ extern gid_t kshgid, kshegid;
#define MKSH_DEFAULT_TMPDIR "/tmp"
#endif
void chvt_reinit(void);
static void reclaim(void);
static void remove_temps(struct temp *);
void chvt_reinit(void);
Source *mksh_init(int, const char *[]);
static mksh_uari_t rndsetup(void);
#ifdef SIGWINCH
static void x_sigwinch(int);
#endif
@ -66,8 +61,9 @@ static const char initsubs[] =
static const char *initcoms[] = {
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,
T_typeset, "-i10", "COLUMNS", "KSHEGID", "KSHGID", "KSHUID", "LINES",
"OPTIND", "PGRP", "PPID", "RANDOM", "SECONDS", "TMOUT", "USER_ID",
NULL,
T_alias,
"integer=typeset -i",
T_local_typeset,
@ -97,7 +93,41 @@ static const char *initcoms[] = {
static int initio_done;
struct env *e = &kshstate_v.env_;
/* top-level parsing and execution environment */
static struct env env;
struct env *e = &env;
static mksh_uari_t
rndsetup(void)
{
register uint32_t h;
struct {
ALLOC_ITEM __alloc_i;
void *dataptr, *stkptr, *mallocptr;
sigjmp_buf jbuf;
struct timeval tv;
struct timezone tz;
} *bufptr;
char *cp;
cp = alloc(sizeof(*bufptr) - ALLOC_SIZE, APERM);
bufptr = (void *)(cp - ALLOC_SIZE); /* undo what alloc() did */
bufptr->dataptr = &rndsetupstate; /* PIE or something */
bufptr->stkptr = &bufptr; /* ASLR in Win/Lin */
bufptr->mallocptr = bufptr; /* randomised malloc in BSD */
sigsetjmp(bufptr->jbuf, 1); /* glibc pointer guard */
gettimeofday(&bufptr->tv, &bufptr->tz); /* introduce variation */
oaat1_init_impl(h);
/* variation through pid, ppid, and the works */
oaat1_addmem_impl(h, &rndsetupstate, sizeof(rndsetupstate));
/* some variation, some possibly entropy, depending on OE */
oaat1_addmem_impl(h, bufptr, sizeof(*bufptr));
oaat1_fini_impl(h);
afree(cp, APERM);
return ((mksh_uari_t)h);
}
void
chvt_reinit(void)
@ -108,8 +138,8 @@ chvt_reinit(void)
kshppid = getppid();
}
Source *
mksh_init(int argc, const char *argv[])
int
main(int argc, const char *argv[])
{
int argi, i;
Source *s;
@ -140,16 +170,17 @@ mksh_init(int argc, const char *argv[])
ainit(&aperm); /* initialise permanent Area */
/* set up base environment */
kshstate_v.env_.type = E_NONE;
ainit(&kshstate_v.env_.area);
newblock(); /* set up global l->vars and l->funs */
env.type = E_NONE;
ainit(&env.area);
/* set up global l->vars and l->funs */
newblock();
/* Do this first so output routines (eg, errorf, shellf) can work */
initio();
argi = parse_args(argv, OF_FIRSTTIME, NULL);
if (argi < 0)
return (NULL);
return (1);
initvar();
@ -197,28 +228,33 @@ mksh_init(int argc, const char *argv[])
def_path = "/bin:/usr/bin:/sbin:/usr/sbin";
#endif
/* Set PATH to def_path (will set the path global variable).
/*
* Set PATH to def_path (will set the path global variable).
* (import of environment below will probably change this setting).
*/
vp = global("PATH");
/* setstr can't fail here */
setstr(vp, def_path, KSH_RETURN_ERROR);
/* Turn on nohup by default for now - will change to off
/*
* Turn on nohup by default for now - will change to off
* by default once people are aware of its existence
* (AT&T ksh does not have a nohup option - it always sends
* the hup).
*/
Flag(FNOHUP) = 1;
/* Turn on brace expansion by default. AT&T kshs that have
/*
* Turn on brace expansion by default. AT&T kshs that have
* alternation always have it on.
*/
Flag(FBRACEEXPAND) = 1;
/* Set edit mode to emacs by default, may be overridden
/*
* Set edit mode to emacs by default, may be overridden
* by the environment or the user. Also, we want tab completion
* on in vi by default. */
* on in vi by default.
*/
change_flag(FEMACS, OF_SPECIAL, 1);
#if !MKSH_S_NOVI
Flag(FVITABCOMPLETE) = 1;
@ -266,7 +302,8 @@ mksh_init(int argc, const char *argv[])
set_current_wd(pwdx);
if (current_wd[0])
simplify_path(current_wd);
/* Only set pwd if we know where we are or if it had a
/*
* Only set pwd if we know where we are or if it had a
* bogus value
*/
if (current_wd[0] || pwd != null)
@ -283,6 +320,10 @@ mksh_init(int argc, const char *argv[])
setint(global("LINES"), 0);
setint(global("OPTIND"), 1);
kshuid = getuid();
kshgid = getgid();
kshegid = getegid();
safe_prompt = ksheuid ? "$ " : "# ";
vp = global("PS1");
/* Set PS1 if unset or we are root and prompt doesn't contain a # */
@ -294,18 +335,19 @@ mksh_init(int argc, const char *argv[])
vp->flag |= INT_U;
setint((vp = global("PPID")), (mksh_uari_t)kshppid);
vp->flag |= INT_U;
setint((vp = global("RANDOM")), (mksh_uari_t)evilhash(kshname));
vp->flag |= INT_U;
setint((vp = global("USER_ID")), (mksh_uari_t)ksheuid);
vp->flag |= INT_U;
setint((vp = global("KSHUID")), (mksh_uari_t)kshuid);
vp->flag |= INT_U;
setint((vp = global("KSHEGID")), (mksh_uari_t)kshegid);
vp->flag |= INT_U;
setint((vp = global("KSHGID")), (mksh_uari_t)kshgid);
vp->flag |= INT_U;
setint((vp = global("RANDOM")), rndsetup());
vp->flag |= INT_U;
/* Set this before parsing arguments */
#if HAVE_SETRESUGID
Flag(FPRIVILEGED) = getuid() != ksheuid || getgid() != getegid();
#else
Flag(FPRIVILEGED) = (kshuid = getuid()) != ksheuid ||
(kshgid = getgid()) != (kshegid = getegid());
#endif
Flag(FPRIVILEGED) = kshuid != ksheuid || kshgid != kshegid;
/* this to note if monitor is set on command line (see below) */
#ifndef MKSH_UNEMPLOYED
@ -316,7 +358,7 @@ mksh_init(int argc, const char *argv[])
argi = parse_args(argv, OF_CMDLINE, NULL);
if (argi < 0)
return (NULL);
return (1);
/* process this later only, default to off (hysterical raisins) */
utf_flag = UTFMODE;
@ -422,7 +464,8 @@ mksh_init(int argc, const char *argv[])
errexit = Flag(FERREXIT);
Flag(FERREXIT) = 0;
/* Do this before profile/$ENV so that if it causes problems in them,
/*
* Do this before profile/$ENV so that if it causes problems in them,
* user will know why things broke.
*/
if (!current_wd[0] && Flag(FTALKING))
@ -464,23 +507,9 @@ mksh_init(int argc, const char *argv[])
} else
Flag(FTRACKALL) = 1; /* set after ENV */
return (s);
}
int
main(int argc, const char *argv[])
{
Source *s;
kshstate_v.lcg_state_ = 5381;
if ((s = mksh_init(argc, argv))) {
/* put more entropy into the LCG */
change_random(s, sizeof(*s));
/* doesn't return */
shell(s, true);
}
return (1);
/* doesn't return */
shell(s, true);
return (0);
}
int
@ -516,7 +545,8 @@ include(const char *name, int argc, const char **argv, int intr_ok)
case LERROR:
return (exstat & 0xff); /* see below */
case LINTR:
/* intr_ok is set if we are including .profile or $ENV.
/*
* intr_ok is set if we are including .profile or $ENV.
* If user ^Cs out, we don't want to kill the shell...
*/
if (intr_ok && (exstat - 128) != SIGTERM)
@ -587,13 +617,15 @@ shell(Source * volatile s, volatile int toplevel)
if (interactive) {
if (i == LINTR)
shellf("\n");
/* Reset any eof that was read as part of a
/*
* Reset any eof that was read as part of a
* multiline command.
*/
if (Flag(FIGNOREEOF) && s->type == SEOF &&
wastty)
s->type = SSTDIN;
/* Used by exit command to get back to
/*
* Used by exit command to get back to
* top level shell. Kind of strange since
* interactive is set if we are reading from
* a tty, but to have stopped jobs, one only
@ -642,7 +674,8 @@ shell(Source * volatile s, volatile int toplevel)
really_exit = 1;
s->type = SSTDIN;
} else {
/* this for POSIX which says EXIT traps
/*
* this for POSIX which says EXIT traps
* shall be taken in the environment
* immediately after the last command
* executed.
@ -742,7 +775,8 @@ quitenv(struct shf *shf)
if (ep->savefd[2]) /* Clear any write errors */
shf_reopen(2, SHF_WR, shl_out);
}
/* Bottom of the stack.
/*
* Bottom of the stack.
* Either main shell is exiting or cleanup_parents_env() was called.
*/
if (ep->oenv == NULL) {
@ -755,7 +789,8 @@ quitenv(struct shf *shf)
if (ep->flags & EF_FAKE_SIGDIE) {
int sig = exstat - 128;
/* ham up our death a bit (AT&T ksh
/*
* ham up our death a bit (AT&T ksh
* only seems to do this for SIGTERM)
* Don't do it for SIGQUIT, since we'd
* dump a core..
@ -839,7 +874,8 @@ remove_temps(struct temp *tp)
unlink(tp->name);
}
/* Initialise tty_fd. Used for saving/reseting tty modes upon
/*
* Initialise tty_fd. Used for saving/reseting tty modes upon
* foreground job completion and for setting up tty process group.
*/
void
@ -937,7 +973,8 @@ warningf(bool fileline, const char *fmt, ...)
shf_flush(shl_out);
}
/* Used by built-in utilities to prefix shell and utility name to message
/*
* Used by built-in utilities to prefix shell and utility name to message
* (also unwinds environments for special builtins).
*/
void
@ -958,7 +995,8 @@ bi_errorf(const char *fmt, ...)
shf_putchar('\n', shl_out);
}
shf_flush(shl_out);
/* POSIX special builtins and ksh special builtins cause
/*
* POSIX special builtins and ksh special builtins cause
* non-interactive shells to exit.
* XXX odd use of KEEPASN; also may not want LERROR here
*/
@ -1133,7 +1171,8 @@ closepipe(int *pv)
close(pv[1]);
}
/* Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn
/*
* Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn
* a string (the X in 2>&X, read -uX, print -uX) into a file descriptor.
*/
int
@ -1156,7 +1195,8 @@ check_fd(const char *name, int mode, const char **emsgp)
return (-1);
}
fl &= O_ACCMODE;
/* X_OK is a kludge to disable this check for dups (x<&1):
/*
* X_OK is a kludge to disable this check for dups (x<&1):
* historical shells never did this check (XXX don't know what
* POSIX has to say).
*/
@ -1192,7 +1232,8 @@ coproc_read_close(int fd)
}
}
/* Called by c_read() and by iosetup() to close the other side of the
/*
* Called by c_read() and by iosetup() to close the other side of the
* read pipe, so reads will actually terminate.
*/
void
@ -1204,7 +1245,8 @@ coproc_readw_close(int fd)
}
}
/* Called by c_print when a write to a fd fails with EPIPE and by iosetup
/*
* Called by c_print when a write to a fd fails with EPIPE and by iosetup
* when co-process input is dup'd
*/
void
@ -1216,7 +1258,8 @@ coproc_write_close(int fd)
}
}
/* Called to check for existence of/value of the co-process file descriptor.
/*
* Called to check for existence of/value of the co-process file descriptor.
* (Used by check_fd() and by c_read/c_print to deal with -p option).
*/
int
@ -1231,7 +1274,8 @@ coproc_getfd(int mode, const char **emsgp)
return (-1);
}
/* called to close file descriptors related to the coprocess (if any)
/*
* called to close file descriptors related to the coprocess (if any)
* Should be called with SIGCHLD blocked.
*/
void

25
misc.c
View File

@ -29,15 +29,10 @@
#include <grp.h>
#endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.149 2011/01/09 21:57:27 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.150 2011/01/21 21:04:45 tg Exp $");
unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */
#if !HAVE_SETRESUGID
uid_t kshuid;
gid_t kshgid, kshegid;
#endif
static int do_gmatch(const unsigned char *, const unsigned char *,
const unsigned char *, const unsigned char *);
static const unsigned char *cclass(const unsigned char *, int);
@ -233,9 +228,10 @@ change_flag(enum sh_flag f, int what, unsigned int newval)
Flag(f) = (unsigned char)newval;
} else if (f == FPRIVILEGED && oldval && !newval) {
/* Turning off -p? */
#if HAVE_SETRESUGID
gid_t kshegid = getgid();
/*XXX this can probably be optimised */
kshegid = kshgid = getgid();
#if HAVE_SETRESUGID
DO_SETUID(setresgid, (kshegid, kshegid, kshegid));
#if HAVE_SETGROUPS
/* setgroups doesn't EAGAIN on Linux */
@ -246,7 +242,7 @@ change_flag(enum sh_flag f, int what, unsigned int newval)
/* seteuid, setegid, setgid don't EAGAIN on Linux */
seteuid(ksheuid = kshuid = getuid());
DO_SETUID(setuid, (ksheuid));
setegid(kshegid = kshgid = getgid());
setegid(kshegid);
setgid(kshegid);
#endif
} else if ((f == FPOSIX || f == FSH) && newval) {
@ -1305,9 +1301,6 @@ chvt(const char *fn)
struct stat sb;
int fd;
/* for entropy */
kshstate_f.h = evilhash(fn);
if (*fn == '-') {
memcpy(dv, "-/dev/null", sizeof("-/dev/null"));
fn = dv + 1;
@ -1362,6 +1355,14 @@ chvt(const char *fn)
ksh_dup2(fd, 2, false);
if (fd > 2)
close(fd);
{
register uint32_t h;
oaat1_init_impl(h);
oaat1_addmem_impl(h, &rndsetupstate, sizeof(rndsetupstate));
oaat1_fini_impl(h);
rndset((long)h);
}
chvt_reinit();
}
#endif

10
mksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.244 2011/01/09 21:57:27 tg Exp $
.\" $MirOS: src/bin/mksh/mksh.1,v 1.245 2011/01/21 21:04:45 tg Exp $
.\" $OpenBSD: ksh.1,v 1.138 2010/09/20 07:41:17 jmc Exp $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
@ -72,7 +72,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always.
.\"
.Dd $Mdocdate: January 9 2011 $
.Dd $Mdocdate: January 21 2011 $
.\"
.\" Check which macro package we use
.\"
@ -1768,6 +1768,12 @@ above for details.
.Sy Note :
This parameter is not imported from the environment when the shell is
started.
.It Ev KSHEGID
The effective group id of the shell.
.It Ev KSHGID
The real group id of the shell.
.It Ev KSHUID
The real user id of the shell.
.It Ev KSH_VERSION
The name and version of the shell (read-only).
See also the version commands in

99
sh.h
View File

@ -154,7 +154,7 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.421 2011/01/09 21:57:29 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.422 2011/01/21 21:04:47 tg Exp $");
#endif
#define MKSH_VERSION "R39 2011/01/08"
@ -519,7 +519,7 @@ enum sh_flag {
FNFLAGS /* (place holder: how many flags are there) */
};
#define Flag(f) (kshstate_v.shell_flags_[(int)(f)])
#define Flag(f) (shell_flags[(int)(f)])
#define UTFMODE Flag(FUNICODE)
/*
@ -569,46 +569,31 @@ extern struct env {
#define LSHELL 8 /* return to interactive shell() */
#define LAEXPR 9 /* error in arithmetic expression */
/*
* some kind of global shell state, for change_random() mostly
*/
EXTERN struct mksh_kshstate_v {
/* for change_random */
struct timeval cr_tv; /* timestamp */
const void *cr_dp; /* argument address */
size_t cr_dsz; /* argument length */
uint32_t lcg_state_; /* previous LCG state */
/* global state */
pid_t procpid_; /* PID of executing process */
int exstat_; /* exit status */
int subst_exstat_; /* exit status of last $(..)/`..` */
struct env env_; /* top-level parsing & execution env. */
short trap_exstat_; /* exit status before running a trap */
uint8_t trap_nested_; /* running nested traps */
uint8_t shell_flags_[FNFLAGS];
} kshstate_v;
EXTERN struct mksh_kshstate_f {
const char *kshname_; /* $0 */
pid_t kshpid_; /* $$, shell PID */
pid_t kshpgrp_; /* process group of shell */
/* sort of shell global state */
EXTERN pid_t procpid; /* PID of executing process */
EXTERN int exstat; /* exit status */
EXTERN int subst_exstat; /* exit status of last $(..)/`..` */
EXTERN short trap_exstat; /* exit status before running a trap */
EXTERN uint8_t trap_nested; /* running nested traps */
EXTERN uint8_t shell_flags[FNFLAGS];
EXTERN const char *kshname; /* $0 */
EXTERN struct {
uid_t kshuid_; /* real UID of shell */
uid_t ksheuid_; /* effective UID of shell */
gid_t kshgid_; /* real GID of shell */
gid_t kshegid_; /* effective GID of shell */
pid_t kshpgrp_; /* process group of shell */
pid_t kshppid_; /* PID of parent of shell */
uint32_t h; /* some kind of hash */
} kshstate_f;
#define kshname kshstate_f.kshname_
#define kshpid kshstate_f.kshpid_
#define procpid kshstate_v.procpid_
#define kshpgrp kshstate_f.kshpgrp_
#define ksheuid kshstate_f.ksheuid_
#define kshppid kshstate_f.kshppid_
#define exstat kshstate_v.exstat_
#define subst_exstat kshstate_v.subst_exstat_
#define trap_exstat kshstate_v.trap_exstat_
#define trap_nested kshstate_v.trap_nested_
pid_t kshpid_; /* $$, shell PID */
} rndsetupstate;
/* evil hack: return hash(kshstate_f concat (kshstate_f'.h:=hash(arg))) */
uint32_t evilhash(const char *);
#define kshpid rndsetupstate.kshpid_
#define kshpgrp rndsetupstate.kshpgrp_
#define kshuid rndsetupstate.kshuid_
#define ksheuid rndsetupstate.ksheuid_
#define kshgid rndsetupstate.kshgid_
#define kshegid rndsetupstate.kshegid_
#define kshppid rndsetupstate.kshppid_
/* option processing */
@ -1407,6 +1392,36 @@ EXTERN struct timeval j_usrtime, j_systime;
'+', (unsigned long)(cnst)); \
} while (/* CONSTCOND */ 0)
/* Bob Jenkins' one-at-a-time hash, with better start value */
#define oaat1_init_impl(h) do { \
(h) = 0x100; \
} while (/* CONSTCOND */ 0)
#define oaat1_addmem_impl(h, buf, len) do { \
register const uint8_t *oaat1_addmem_p = (const void *)(buf); \
register size_t oaat1_addmem_n = (len); \
\
while (oaat1_addmem_n--) { \
(h) += *oaat1_addmem_p++; \
(h) += (h) << 10; \
(h) ^= (h) >> 6; \
} \
} while (/* CONSTCOND */ 0)
#define oaat1_addstr_impl(h, s) do { \
register const uint8_t *oaat1_addstr_p = (const void *)(s); \
register uint8_t oaat1_addstr_c; \
\
while ((oaat1_addstr_c = *oaat1_addstr_p++)) { \
h += oaat1_addstr_c; \
(h) += (h) << 10; \
(h) ^= (h) >> 6; \
} \
} while (/* CONSTCOND */ 0)
#define oaat1_fini_impl(h) do { \
(h) += (h) << 3; \
(h) ^= (h) >> 11; \
(h) += (h) << 15; \
} while (/* CONSTCOND */ 0)
/* lalloc.c */
void ainit(Area *);
void afreeall(Area *);
@ -1614,9 +1629,6 @@ void coproc_write_close(int);
int coproc_getfd(int, const char **);
void coproc_cleanup(int);
struct temp *maketemp(Area *, Temp_type, struct temp **);
#define hash(s) oaathash_full((const uint8_t *)(s))
uint32_t oaathash_full(register const uint8_t *);
uint32_t hashmem(const void *, size_t);
void ktinit(struct table *, Area *, size_t);
struct tbl *ktsearch(struct table *, const char *, uint32_t);
struct tbl *ktenter(struct table *, const char *, uint32_t);
@ -1712,11 +1724,12 @@ const char *skip_wdvarname(const char *, int);
int is_wdvarname(const char *, int);
int is_wdvarassign(const char *);
char **makenv(void);
void change_random(const void *, size_t);
void change_winsz(void);
int array_ref_len(const char *);
char *arrayname(const char *);
mksh_uari_t set_array(const char *, bool, const char **);
uint32_t hash(const void *);
void rndset(long);
enum Test_op {
TO_NONOP = 0, /* non-operator */

135
var.c
View File

@ -1,7 +1,7 @@
/* $OpenBSD: var.c,v 1.34 2007/10/15 02:16:35 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@ -26,7 +26,7 @@
#include <sys/sysctl.h>
#endif
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.114 2010/09/19 19:21:20 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.115 2011/01/21 21:04:48 tg Exp $");
/*
* Variables
@ -39,6 +39,8 @@ __RCSID("$MirOS: src/bin/mksh/var.c,v 1.114 2010/09/19 19:21:20 tg Exp $");
*/
static struct tbl vtemp;
static struct table specials;
static uint32_t lcg_state = 5381;
static char *formatstr(struct tbl *, const char *);
static void exportprep(struct tbl *, const char *);
static int special(const char *);
@ -50,9 +52,6 @@ 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 uint32_t oaathash_update(register uint32_t, register const uint8_t *,
register size_t);
static uint32_t oaathash_finalise(register uint32_t);
uint8_t set_refflag = 0;
@ -986,79 +985,6 @@ makenv(void)
return ((char **)XPclose(denv));
}
/* Bob Jenkins' one-at-a-time hash */
static uint32_t
oaathash_update(register uint32_t h, register const uint8_t *cp,
register size_t n)
{
while (n--) {
h += *cp++;
h += h << 10;
h ^= h >> 6;
}
return (h);
}
static uint32_t
oaathash_finalise(register uint32_t h)
{
h += h << 3;
h ^= h >> 11;
h += h << 15;
return (h);
}
uint32_t
oaathash_full(register const uint8_t *bp)
{
register uint32_t h = 0;
register uint8_t c;
while ((c = *bp++)) {
h += c;
h += h << 10;
h ^= h >> 6;
}
return (oaathash_finalise(h));
}
void
change_random(const void *vp, size_t n)
{
register uint32_t h = 0x100;
#if defined(arc4random_pushb_fast) || defined(MKSH_A4PB)
uint32_t i;
#endif
kshstate_v.cr_dp = vp;
kshstate_v.cr_dsz = n;
gettimeofday(&kshstate_v.cr_tv, NULL);
h = oaathash_update(oaathash_update(h, (void *)&kshstate_v,
sizeof(kshstate_v)), vp, n);
kshstate_v.lcg_state_ = oaathash_finalise(h);
#if defined(arc4random_pushb_fast) || defined(MKSH_A4PB)
/*
* either we have very check entropy get and push available,
* with malloc() pulling in this code already anyway, or the
* user requested us to use the old functions
*/
#if defined(arc4random_pushb_fast)
arc4random_pushb_fast(&kshstate_v.lcg_state_,
sizeof(kshstate_v.lcg_state_));
i = arc4random();
#else
i = arc4random_pushb(&kshstate_v.lcg_state_,
sizeof(kshstate_v.lcg_state_));
#endif
h = oaathash_update(h, (void *)&i, sizeof(i));
kshstate_v.lcg_state_ = oaathash_finalise(h);
#endif
}
/*
* handle special variables with side effects - PATH, SECONDS.
*/
@ -1113,8 +1039,7 @@ getspec(struct tbl *vp)
* this is the same Linear Congruential PRNG as Borland
* C/C++ allegedly uses in its built-in rand() function
*/
i = ((kshstate_v.lcg_state_ =
22695477 * kshstate_v.lcg_state_ + 1) >> 16) & 0x7FFF;
i = ((lcg_state = 22695477 * lcg_state + 1) >> 16) & 0x7FFF;
break;
case V_HISTSIZE:
i = histsize;
@ -1181,17 +1106,17 @@ setspec(struct tbl *vp)
stat(s, &statb) == 0 && S_ISDIR(statb.st_mode))
strdupx(tmpdir, s, APERM);
}
break;
return;
#if HAVE_PERSISTENT_HISTORY
case V_HISTFILE:
sethistfile(str_val(vp));
break;
return;
#endif
case V_TMOUT:
/* AT&T ksh seems to do this (only listen if integer) */
if (vp->flag & INTEGER)
ksh_tmout = vp->val.i >= 0 ? vp->val.i : 0;
break;
return;
/* common sub-cases */
case V_OPTIND:
@ -1232,7 +1157,7 @@ setspec(struct tbl *vp)
* mksh R39d+ no longer has the traditional repeatability
* of $RANDOM sequences, but always retains state
*/
change_random(&i, sizeof(i));
rndset((long)i);
break;
case V_SECONDS:
{
@ -1476,12 +1401,42 @@ change_winsz(void)
}
uint32_t
evilhash(const char *s)
hash(const void *s)
{
register uint32_t h = 0x100;
register uint32_t h;
h = oaathash_update(h, (void *)&kshstate_f, sizeof(kshstate_f));
kshstate_f.h = oaathash_full((const uint8_t *)s);
return (oaathash_finalise(oaathash_update(h,
(void *)&kshstate_f.h, sizeof(kshstate_f.h))));
oaat1_init_impl(h);
oaat1_addstr_impl(h, s);
oaat1_fini_impl(h);
return (h);
}
void
rndset(long v)
{
register uint32_t h;
oaat1_init_impl(h);
oaat1_addmem_impl(h, &lcg_state, sizeof(lcg_state));
oaat1_addmem_impl(h, &v, sizeof(v));
#if defined(arc4random_pushb_fast) || defined(MKSH_A4PB)
/*
* either we have very chap entropy get and push available,
* with malloc() pulling in this code already anyway, or the
* user requested us to use the old functions
*/
lcg_state = h;
oaat1_fini_impl(lcg_state);
#if defined(arc4random_pushb_fast)
arc4random_pushb_fast(&lcg_state, sizeof(lcg_state));
lcg_state = arc4random();
#else
lcg_state = arc4random_pushb(&lcg_state, sizeof(lcg_state));
#endif
oaat1_addmem_impl(h, &lcg_state, sizeof(lcg_state));
#endif
oaat1_fini_impl(h);
lcg_state = h;
}