Merge remote-tracking branch 'mksh/master'

This commit is contained in:
KO Myung-Hun
2015-07-08 19:31:55 +09:00
14 changed files with 226 additions and 160 deletions

View File

@ -1,5 +1,5 @@
#!/bin/sh
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.679 2015/05/01 16:08:26 tg Exp $'
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.681 2015/07/06 17:48:28 tg Exp $'
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015
@ -2654,7 +2654,6 @@ MKSH_NOPROSPECTOFWORK disable jobs, co-processes, etc. (do not use)
MKSH_NOPWNAM skip PAM calls, for -static on glibc or Solaris
MKSH_NO_CMDLINE_EDITING disable command line editing code entirely
MKSH_NO_DEPRECATED_WARNING omit warning when deprecated stuff is run
MKSH_NO_EXTERNAL_CAT omit hack to skip cat builtin when flags passed
MKSH_NO_LIMITS omit ulimit code
MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available
MKSH_NO_SIGSUSPEND use sigprocmask+pause instead of sigsuspend

12
check.t
View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.694 2015/05/23 17:43:18 tg Exp $
# $MirOS: src/bin/mksh/check.t,v 1.699 2015/07/06 17:48:29 tg Exp $
# -*- mode: sh -*-
#-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -30,7 +30,7 @@
# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout:
@(#)MIRBSD KSH R51 2015/05/23
@(#)MIRBSD KSH R51 2015/07/06
description:
Check version of shell.
stdin:
@ -39,7 +39,7 @@ name: KSH_VERSION
category: shell:legacy-no
---
expected-stdout:
@(#)LEGACY KSH R51 2015/05/23
@(#)LEGACY KSH R51 2015/07/06
description:
Check version of legacy shell.
stdin:
@ -3583,7 +3583,7 @@ expected-stdout:
a new line
1 echo abc def
2 echo FOOBAR def
3 echo a new line
echo a new line
expected-stderr-pattern:
/^X*echo FOOBAR def\necho a new line\nX*$/
---
@ -3665,7 +3665,7 @@ expected-stdout:
a new line
1 echo abc def
2 echo FOOBAR def
3 echo a new line
echo a new line
expected-stderr-pattern:
/^X*13\n32\necho FOOBAR def\necho a new line\nX*$/
---
@ -8599,6 +8599,7 @@ description:
Ensure concatenating behaviour matches other shells
stdin:
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
showargs 0 ""$@
x=; showargs 1 "$x"$@
set A; showargs 2 "${@:+}"
n() { echo "$#"; }
@ -8618,6 +8619,7 @@ stdin:
n "$@"
n "$@""$e"
expected-stdout:
<0> <> .
<1> <> .
<2> <> .
2

View File

@ -1,5 +1,5 @@
# $Id$
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.97 2015/04/29 20:56:18 tg Exp $
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.99 2015/07/05 19:02:16 tg Exp $
#-
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015
@ -67,8 +67,9 @@ else
\typeset -Uui16 -Z11 pos=0
\typeset -Uui16 -Z5 hv=2147483647
\typeset dasc line i
\set +U
\cat "$@" | { \set +U; if \read -arN -1 line; then
\cat "$@" | if \read -arN -1 line; then
\typeset -i1 'line[*]'
i=0
while (( i < ${#line[*]} )); do
@ -95,7 +96,7 @@ else
\builtin print -n -- '- '
done
(( hv == 2147483647 )) || \builtin print -r -- "$dasc|"
fi; }
fi
}
fi
@ -112,7 +113,7 @@ function chpwd {
\:
}
\chpwd .
function cd {
cd() {
\builtin cd "$@" || \return $?
\chpwd "$@"
}
@ -271,8 +272,8 @@ function smores {
# base64 encoder and decoder, RFC compliant, NUL safe, not EBCDIC safe
function Lb64decode {
[[ -o utf8-mode ]]; \typeset u=$? c s="$*" t
\set +U
\typeset c s="$*" t
[[ -n $s ]] || { s=$(\cat; \builtin print x); s=${s%x}; }
\typeset -i i=0 j=0 n=${#s} p=0 v x
\typeset -i16 o
@ -303,14 +304,13 @@ function Lb64decode {
t=
done
\builtin print -n $t
(( u )) || \set -U
}
\set -A Lb64encode_tbl -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
function Lb64encode {
[[ -o utf8-mode ]]; \typeset u=$? c s t
\set +U
\typeset c s t
if (( $# )); then
\read -raN-1 s <<<"$*"
\unset s[${#s[*]}-1]
@ -339,7 +339,6 @@ function Lb64encode {
t=
fi
done
(( u )) || \set -U
}
# Better Avalanche for the Jenkins Hash
@ -348,8 +347,8 @@ function Lbafh_init {
Lbafh_v=0
}
function Lbafh_add {
[[ -o utf8-mode ]]; \typeset u=$? s
\set +U
\typeset s
if (( $# )); then
\read -raN-1 s <<<"$*"
\unset s[${#s[*]}-1]
@ -362,8 +361,6 @@ function Lbafh_add {
((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 ))
((# Lbafh_v ^= Lbafh_v >> 6 ))
done
(( u )) || \set -U
}
function Lbafh_finish {
\typeset -Ui t
@ -378,10 +375,11 @@ function Lbafh_finish {
# strip comments (and leading/trailing whitespace if IFS is set) from
# any file(s) given as argument, or stdin if none, and spew to stdout
function Lstripcom {
\cat "$@" | { \set -o noglob; while \read _line; do
\set -o noglob
\cat "$@" | while \read _line; do
_line=${_line%%#*}
[[ -n $_line ]] && \builtin print -r -- $_line
done; }
done
}
# give MidnightBSD's laffer1 a bit of csh feeling

8
edit.c
View File

@ -28,7 +28,7 @@
#ifndef MKSH_NO_CMDLINE_EDITING
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.286 2015/05/03 11:28:53 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.287 2015/07/05 19:37:13 tg Exp $");
/*
* in later versions we might use libtermcap for this, but since external
@ -3101,7 +3101,7 @@ x_edit_line(int c MKSH_A_UNUSED)
}
if (modified) {
*xep = '\0';
histsave(&source->line, xbuf, true, true);
histsave(&source->line, xbuf, HIST_STORE, true);
x_arg = 0;
} else
x_arg = source->line - (histptr - x_histp);
@ -4390,8 +4390,8 @@ vi_cmd(int argcnt, const char *cmd)
return (-1);
if (modified) {
es->cbuf[es->linelen] = '\0';
histsave(&source->line, es->cbuf, true,
true);
histsave(&source->line, es->cbuf,
HIST_STORE, true);
} else
argcnt = source->line + 1 -
(hlast - hnum);

15
eval.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.169 2015/05/23 17:43:19 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.170 2015/07/06 17:45:33 tg Exp $");
/*
* string expansion
@ -291,21 +291,14 @@ expand(
c = *sp++;
break;
case OQUOTE:
switch (word) {
case IFS_QUOTE:
/* """something */
word = IFS_WORD;
break;
case IFS_WORD:
break;
default:
if (word != IFS_WORD)
word = IFS_QUOTE;
break;
}
tilde_ok = 0;
quote = 1;
continue;
case CQUOTE:
if (word == IFS_QUOTE)
word = IFS_WORD;
quote = st->quotew;
continue;
case COMSUB:

46
exec.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.152 2015/04/29 18:32:43 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.155 2015/07/06 17:48:31 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL UNIXROOT "/bin/sh"
@ -41,8 +41,8 @@ static const char *dbteste_getopnd(Test_env *, Test_op, bool);
static void dbteste_error(Test_env *, int, const char *);
static int search_access(const char *, int);
/* XXX: horrible kludge to fit within the framework */
static char *plain_fmt_entry(char *, size_t, unsigned int, const void *);
static char *select_fmt_entry(char *, size_t, unsigned int, const void *);
static void plain_fmt_entry(char *, size_t, unsigned int, const void *);
static void select_fmt_entry(char *, size_t, unsigned int, const void *);
/*
* execute command tree
@ -551,6 +551,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
}
if ((tp = findcom(cp, FC_BI)) == NULL)
errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin");
if (tp->type == CSHELL && tp->val.f == c_cat)
break;
continue;
} else if (tp->val.f == c_exec) {
if (ap[1] == NULL)
@ -607,25 +609,19 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
subst_exstat = 0;
break;
}
#ifndef MKSH_NO_EXTERNAL_CAT
} else if (tp->val.f == c_cat) {
/*
* if we have any flags, do not use the builtin
* in theory, we could allow -u, but that would
* mean to use ksh_getopt here and possibly ad-
* ded complexity and more code and isn't worth
* additional hassle (and the builtin must call
* ksh_getopt already but can't come back here)
*/
/* if we have any flags, do not use the builtin */
if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' &&
/* argument, begins with -, is not - or -- */
(ap[1][1] != '-' || ap[1][2] != '\0'))
/* don't look for builtins or functions */
fcflags = FC_PATH;
else
/* go on, use the builtin */
(ap[1][1] != '-' || ap[1][2] != '\0')) {
struct tbl *ext_cat;
ext_cat = findcom(Tcat, FC_PATH | FC_FUNC);
if (ext_cat && (ext_cat->type != CTALIAS ||
(ext_cat->flag & ISSET)))
tp = ext_cat;
}
break;
#endif
} else if (tp->val.f == c_trap) {
t->u.evalflags &= ~DOTCOMEXEC;
break;
@ -705,6 +701,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
/* shell built-in */
case CSHELL:
do_call_builtin:
rv = call_builtin(tp, (const char **)ap, null, resetspec);
if (resetspec && tp->val.f == c_shift) {
l_expand->argc = l_assign->argc;
@ -729,6 +726,11 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
break;
}
if (include(tp->u.fpath, 0, NULL, false) < 0) {
if (!strcmp(cp, Tcat)) {
no_cat_in_FPATH:
tp = findcom(Tcat, FC_BI);
goto do_call_builtin;
}
warningf(true, "%s: %s %s %s: %s", cp,
"can't open", "function definition file",
tp->u.fpath, cstrerror(errno));
@ -737,6 +739,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
}
if (!(ftp = findfunc(cp, hash(cp), false)) ||
!(ftp->flag & ISSET)) {
if (!strcmp(cp, Tcat))
goto no_cat_in_FPATH;
warningf(true, "%s: %s %s", cp,
"function not defined by", tp->u.fpath);
rv = 127;
@ -1657,7 +1661,7 @@ struct select_menu_info {
};
/* format a single select menu item */
static char *
static void
select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
{
const struct select_menu_info *smi =
@ -1665,7 +1669,6 @@ select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
shf_snprintf(buf, buflen, "%*u) %s",
smi->num_width, i + 1, smi->args[i]);
return (buf);
}
/*
@ -1711,11 +1714,10 @@ pr_menu(const char * const *ap)
true);
}
static char *
static void
plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
{
strlcpy(buf, ((const char * const *)arg)[i], buflen);
return (buf);
}
void

23
funcs.c
View File

@ -38,7 +38,7 @@
#endif
#endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.272 2015/05/01 23:16:29 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.277 2015/07/06 17:48:32 tg Exp $");
#if HAVE_KILLPG
/*
@ -99,7 +99,7 @@ const struct builtin mkshbuiltins[] = {
{Talias, c_alias},
{"*=break", c_brkcont},
{Tgbuiltin, c_builtin},
{"cat", c_cat},
{Tcat, c_cat},
{"cd", c_cd},
/* dash compatibility hack */
{"chdir", c_cd},
@ -227,7 +227,7 @@ static int test_primary(Test_env *, bool);
static Test_op ptest_isa(Test_env *, Test_meta);
static const char *ptest_getopnd(Test_env *, Test_op, bool);
static void ptest_error(Test_env *, int, const char *);
static char *kill_fmt_entry(char *, size_t, unsigned int, const void *);
static void kill_fmt_entry(char *, size_t, unsigned int, const void *);
static void p_time(struct shf *, bool, long, int, int,
const char *, const char *);
@ -445,7 +445,7 @@ c_print(const char **wp)
if (flags & PO_HIST) {
Xput(xs, xp, '\0');
histsave(&source->line, Xstring(xs, xp), true, false);
histsave(&source->line, Xstring(xs, xp), HIST_STORE, false);
Xfree(xs, xp);
} else {
int len = Xlength(xs, xp);
@ -541,7 +541,7 @@ c_whence(const char **wp)
uint32_t h = 0;
tp = NULL;
if ((iam_whence || vflag) && !pflag)
if (!pflag)
tp = ktsearch(&keywords, id, h = hash(id));
if (!tp && !pflag) {
tp = ktsearch(&aliases, id, h ? h : hash(id));
@ -1310,7 +1310,7 @@ c_fgbg(const char **wp)
#endif
/* format a single kill item */
static char *
static void
kill_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
{
const struct kill_info *ki = (const struct kill_info *)arg;
@ -1320,7 +1320,6 @@ kill_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
ki->num_width, i,
ki->name_width, sigtraps[i].name,
sigtraps[i].mess);
return (buf);
}
int
@ -1967,8 +1966,9 @@ c_read(const char **wp)
break;
case 0:
/* timeout expired for this call */
rv = 1;
goto c_read_out;
bytesread = 0;
/* fake EOF read; all cases return 1 */
goto c_read_didread;
default:
bi_errorf("%s: %s", Tselect, cstrerror(errno));
rv = 2;
@ -1993,6 +1993,7 @@ c_read(const char **wp)
goto c_read_readloop;
}
c_read_didread:
switch (readmode) {
case READALL:
if (bytesread == 0) {
@ -2015,7 +2016,7 @@ c_read(const char **wp)
if (bytesread == 0) {
/* end of file reached */
rv = 1;
xp = Xstring(xs, xp);
/* may be partial read: $? = 1, but content */
goto c_read_readdone;
}
xp += bytesread;
@ -2078,7 +2079,7 @@ c_read(const char **wp)
}
if (savehist)
histsave(&source->line, Xstring(xs, xp), true, false);
histsave(&source->line, Xstring(xs, xp), HIST_STORE, false);
ccp = cp = Xclose(xs, xp);
expanding = false;

103
histrap.c
View File

@ -27,7 +27,7 @@
#include <sys/file.h>
#endif
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.143 2015/04/29 20:44:35 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.148 2015/07/05 19:53:45 tg Exp $");
Trap sigtraps[ksh_NSIG + 1];
static struct sigaction Sigact_ign;
@ -38,7 +38,7 @@ static int writehistline(int, int, const char *);
static void writehistfile(int, const char *);
#endif
static int hist_execute(char *);
static int hist_execute(char *, Area *);
static char **hist_get(const char *, bool, bool);
static char **hist_get_oldest(void);
@ -84,6 +84,9 @@ static const char TFCEDIT_dollaru[] = "${FCEDIT:-/bin/ed} $_";
/* maximum considered size of persistent history file */
#define MKSH_MAXHISTFSIZE ((off_t)1048576 * 96)
/* hidden option */
#define HIST_DISCARD 5
int
c_fc(const char **wp)
{
@ -223,7 +226,7 @@ c_fc(const char **wp)
xp += len;
line = Xclose(xs, xp);
}
return (hist_execute(line));
return (hist_execute(line, ATEMP));
}
if (editor && (lflag || nflag)) {
@ -360,18 +363,17 @@ c_fc(const char **wp)
shf_close(shf);
*xp = '\0';
strip_nuls(Xstring(xs, xp), Xlength(xs, xp));
return (hist_execute(Xstring(xs, xp)));
return (hist_execute(Xstring(xs, xp), hist_source->areap));
}
}
/* Save cmd in history, execute cmd (cmd gets trashed) */
/* save cmd in history, execute cmd (cmd gets afreed) */
static int
hist_execute(char *cmd)
hist_execute(char *cmd, Area *areap)
{
static int last_line = -1;
Source *sold;
int ret;
char *p, *q;
/* Back up over last histsave */
if (histptr >= history && last_line != hist_source->line) {
@ -381,22 +383,12 @@ hist_execute(char *cmd)
last_line = hist_source->line;
}
for (p = cmd; p; p = q) {
if ((q = strchr(p, '\n'))) {
/* kill the newline */
*q++ = '\0';
if (!*q)
/* ignore trailing newline */
q = NULL;
}
histsave(&hist_source->line, p, true, true);
/* POSIX doesn't say this is done... */
shellf("%s\n", p);
if (q)
/* restore \n (trailing \n not restored) */
q[-1] = '\n';
}
histsave(&hist_source->line, cmd, HIST_STORE, true);
/* now *histptr == cmd without all trailing newlines */
afree(cmd, areap);
cmd = *histptr;
/* pdksh says POSIX doesnt say this is done, testsuite needs it */
shellf("%s\n", cmd);
/*-
* Commands are executed here instead of pushing them onto the
@ -578,6 +570,7 @@ sethistfile(const char *name)
afree(hname, APERM);
hname = NULL;
/* let's reset the history */
histsave(NULL, NULL, HIST_DISCARD, true);
histptr = history - 1;
hist_source->line = 0;
}
@ -612,6 +605,8 @@ histsync(void)
{
bool changed = false;
/* called by histsave(), may not HIST_DISCARD, caller should flush */
if (histfd != -1) {
int lno = hist_source->line;
@ -631,15 +626,38 @@ histsync(void)
* save command in history
*/
void
histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
histsave(int *lnp, const char *cmd, int svmode, bool ignoredups)
{
char **hp;
char *c, *cp;
static char *enqueued = NULL;
char **hp, *c;
const char *ccp;
strdupx(c, cmd, APERM);
if ((cp = strchr(c, '\n')) != NULL)
*cp = '\0';
if (svmode == HIST_DISCARD) {
afree(enqueued, APERM);
enqueued = NULL;
return;
}
if (svmode == HIST_APPEND) {
if (!enqueued)
svmode = HIST_STORE;
} else if (enqueued) {
c = enqueued;
enqueued = NULL;
--*lnp;
histsave(lnp, c, HIST_STORE, true);
afree(c, APERM);
}
if (svmode == HIST_FLUSH)
return;
ccp = cmd + strlen(cmd);
while (ccp > cmd && ccp[-1] == '\n')
--ccp;
strndupx(c, cmd, ccp - cmd, APERM);
if (svmode != HIST_APPEND) {
if (ignoredups && !strcmp(c, *histptr)
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
&& !histsync()
@ -649,12 +667,33 @@ histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
return;
}
++*lnp;
}
#if HAVE_PERSISTENT_HISTORY
if (dowrite && histfd != -1)
if (svmode == HIST_STORE && histfd != -1)
writehistfile(*lnp, c);
#endif
if (svmode == HIST_QUEUE || svmode == HIST_APPEND) {
size_t nenq, ncmd;
if (!enqueued) {
if (*c)
enqueued = c;
else
afree(c, APERM);
return;
}
nenq = strlen(enqueued);
ncmd = strlen(c);
enqueued = aresize(enqueued, nenq + 1 + ncmd + 1, APERM);
enqueued[nenq] = '\n';
memcpy(enqueued + nenq + 1, c, ncmd + 1);
afree(c, APERM);
return;
}
hp = histptr;
if (++hp >= history + histsize) {
@ -707,6 +746,8 @@ hist_init(Source *s)
enum { hist_init_first, hist_init_retry, hist_init_restore } hs;
#endif
histsave(NULL, NULL, HIST_DISCARD, true);
if (Flag(FTALKING) == 0)
return;
@ -864,7 +905,7 @@ histload(Source *s, unsigned char *base, size_t bytes)
}
} else {
s->line = lno--;
histsave(&lno, (char *)(base + 4), false, false);
histsave(&lno, (char *)(base + 4), HIST_NOTE, false);
}
/* advance base pointer past NUL */
bytes -= ++cp - base;

22
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.201 2015/04/29 20:07:33 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.204 2015/07/05 19:53:46 tg Exp $");
/*
* states while lexing word
@ -1461,16 +1461,23 @@ getsc_line(Source *s)
if (s->type == SFILE)
shf_fdclose(s->u.shf);
s->str = NULL;
} else if (interactive && *s->str &&
(cur_prompt != PS1 || !ctype(*s->str, C_IFS | C_IFSWS))) {
histsave(&s->line, s->str, true, true);
} else if (interactive && *s->str) {
if (cur_prompt != PS1)
histsave(&s->line, s->str, HIST_APPEND, true);
else if (!ctype(*s->str, C_IFS | C_IFSWS))
histsave(&s->line, s->str, HIST_QUEUE, true);
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
else
goto check_for_sole_return;
} else if (interactive && cur_prompt == PS1) {
check_for_sole_return:
cp = Xstring(s->xs, xp);
while (*cp && ctype(*cp, C_IFSWS))
++cp;
if (!*cp)
if (!*cp) {
histsave(&s->line, NULL, HIST_FLUSH, true);
histsync();
}
#endif
}
if (interactive)
@ -1495,6 +1502,7 @@ set_prompt(int to, Source *s)
struct shf *shf;
char * volatile ps1;
Area *saved_atemp;
int saved_lineno;
ps1 = str_val(global("PS1"));
shf = shf_sopen(NULL, strlen(ps1) * 2,
@ -1506,6 +1514,9 @@ set_prompt(int to, Source *s)
shf_fprintf(shf, "%lu", s ?
(unsigned long)s->line + 1 : 0UL);
ps1 = shf_sclose(shf);
saved_lineno = current_lineno;
if (s)
current_lineno = s->line + 1;
saved_atemp = ATEMP;
newenv(E_ERRH);
if (kshsetjmp(e->jbuf)) {
@ -1521,6 +1532,7 @@ set_prompt(int to, Source *s)
char *cp = substitute(ps1, 0);
strdupx(prompt, cp, saved_atemp);
}
current_lineno = saved_lineno;
quitenv(NULL);
}
break;

6
main.c
View File

@ -34,7 +34,7 @@
#include <locale.h>
#endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.293 2015/04/29 20:07:33 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.295 2015/07/06 17:48:34 tg Exp $");
extern char **environ;
@ -87,7 +87,7 @@ static const char *initcoms[] = {
NULL,
/* this is what AT&T ksh seems to track, with the addition of emacs */
Talias, "-tU",
"cat", "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls",
Tcat, "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls",
"make", "mv", "pr", "rm", "sed", "sh", "vi", "who", NULL,
NULL
};
@ -825,6 +825,8 @@ shell(Source * volatile s, volatile bool toplevel)
set_prompt(PS1, s);
}
t = compile(s, sfirst);
if (interactive)
histsave(&s->line, NULL, HIST_FLUSH, true);
sfirst = false;
if (!t)
goto source_no_tree;

View File

@ -1,6 +1,6 @@
/*-
* Copyright © 2011, 2014
* Thorsten Glaser <tg@mirbsd.org>
* Copyright © 2011, 2014, 2015
* Thorsten “mirabilos” Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
* are retained or reproduced in an accompanying document, permission
@ -44,7 +44,7 @@
#include <sys/types.h>
__RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.4 2015/05/30 22:14:06 tg Exp $");
/*-
* BAFH itself is defined by the following primitives:
@ -61,7 +61,8 @@ __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
* the context is (still) zero, adding a NUL byte is not ignored.
*
* • BAFHror(eax,cl) evaluates to the unsigned 32-bit integer “eax”,
* rotated right by “cl” ∈ [0;31]; no casting, be careful!
* rotated right by “cl” ∈ [0; 31] (no casting, be careful!) where
* “eax” must be uint32_t and “cl” an in-range integer.
*
* • BAFHFinish(ctx) avalanches the context around so every sub-byte
* depends on all input octets; afterwards, the context variables
@ -88,7 +89,7 @@ __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
* • BAFHHostStr(ctx,buf) does the same for C strings.
*
* All macros may use ctx multiple times in their expansion, but all
* other arguments are always evaluated at most once.
* other arguments are always evaluated at most once except BAFHror.
*
* To stay portable, never use the BAFHHost*() macros (these are for
* host-local entropy shuffling), and encode numbers using ULEB128.
@ -206,6 +207,7 @@ __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
} BAFHHost_v; \
\
BAFHUpdate_s = (const void *)(s); \
BAFHHost_v.as_u32 = 0; \
if ((BAFHHost_v.as_u8[0] = *BAFHUpdate_s) != 0) \
++BAFHUpdate_s; \
if ((BAFHHost_v.as_u8[1] = *BAFHUpdate_s) != 0) \

45
misc.c
View File

@ -30,7 +30,7 @@
#include <grp.h>
#endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.232 2015/05/01 23:16:30 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.236 2015/07/05 14:58:33 tg Exp $");
#define KSH_CHVT_FLAG
#ifdef MKSH_SMALL
@ -173,11 +173,11 @@ struct options_info {
int opts[NELEM(options)];
};
static char *options_fmt_entry(char *, size_t, unsigned int, const void *);
static void options_fmt_entry(char *, size_t, unsigned int, const void *);
static void printoptions(bool);
/* format a single select menu item */
static char *
static void
options_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
{
const struct options_info *oi = (const struct options_info *)arg;
@ -185,7 +185,6 @@ options_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
shf_snprintf(buf, buflen, "%-*s %s",
oi->opt_width, OFN(oi->opts[i]),
Flag(oi->opts[i]) ? "on" : "off");
return (buf);
}
static void
@ -1227,7 +1226,7 @@ print_value_quoted(struct shf *shf, const char *s)
*/
void
print_columns(struct shf *shf, unsigned int n,
char *(*func)(char *, size_t, unsigned int, const void *),
void (*func)(char *, size_t, unsigned int, const void *),
const void *arg, size_t max_oct, size_t max_colz, bool prefcol)
{
unsigned int i, r, c, rows, cols, nspace, max_col;
@ -1256,17 +1255,20 @@ print_columns(struct shf *shf, unsigned int n,
str = alloc(max_oct, ATEMP);
/*
* We use (max_col + 1) to consider the space separator.
* Note that no space is printed after the last column
* to avoid problems with terminals that have auto-wrap.
* We use (max_col + 2) to consider the separator space.
* Note that no spaces are printed after the last column
* to avoid problems with terminals that have auto-wrap,
* but we need to also take this into account in x_cols.
*/
cols = x_cols / (max_col + 1);
cols = (x_cols + 1) / (max_col + 2);
/* if we can only print one column anyway, skip the goo */
if (cols < 2) {
for (i = 0; i < n; ++i)
shf_fprintf(shf, "%s\n",
(*func)(str, max_oct, i, arg));
for (i = 0; i < n; ++i) {
(*func)(str, max_oct, i, arg);
shf_puts(str, shf);
shf_putc('\n', shf);
}
goto out;
}
@ -1277,18 +1279,19 @@ print_columns(struct shf *shf, unsigned int n,
}
nspace = (x_cols - max_col * cols) / cols;
if (nspace < 2)
nspace = 2;
max_col = -max_col;
if (nspace <= 0)
nspace = 1;
for (r = 0; r < rows; r++) {
for (c = 0; c < cols; c++) {
i = c * rows + r;
if (i < n) {
shf_fprintf(shf, "%*s", max_col,
(*func)(str, max_oct, i, arg));
if (c + 1 < cols)
shf_fprintf(shf, "%*s", nspace, null);
}
if ((i = c * rows + r) >= n)
break;
(*func)(str, max_oct, i, arg);
if (i + rows >= n)
shf_puts(str, shf);
else
shf_fprintf(shf, "%*s%*s",
max_col, str, nspace, null);
}
shf_putchar('\n', shf);
}

33
mksh.1
View File

@ -1,5 +1,5 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.367 2015/05/23 17:43:20 tg Exp $
.\" $OpenBSD: ksh.1,v 1.159 2015/03/25 12:10:52 jca Exp $
.\" $MirOS: src/bin/mksh/mksh.1,v 1.373 2015/07/06 17:48:35 tg Exp $
.\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
.\" 2010, 2011, 2012, 2013, 2014, 2015
@ -74,7 +74,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always.
.\"
.Dd $Mdocdate: May 23 2015 $
.Dd $Mdocdate: July 6 2015 $
.\"
.\" Check which macro package we use, and do other -mdoc setup.
.\"
@ -476,7 +476,7 @@ and
.Ql }
delimit
.Xr csh 1 Ns -style
alterations (see
alternations (see
.Sx Brace expansion
below);
and finally,
@ -1859,7 +1859,8 @@ below for more information.
.It Ev HISTFILE
The name of the file used to store command history.
When assigned to or unset, the file is opened, history is truncated
then loaded from the file; subsequent new lines are appended.
then loaded from the file; subsequent new commands (possibly consisting
of several lines) are appended once they successfully compiled.
Also, several invocations of the shell will share history if their
.Ev HISTFILE
parameters all point to the same file.
@ -2145,7 +2146,7 @@ The
.Ic alias Fl d
command may be used to list, change, and add to this cache (e.g.\&
.Ic alias \-d fac=/usr/local/facilities; cd \*(TIfac/bin ) .
.Ss Brace expansion (alteration)
.Ss Brace expansion (alternation)
Brace expressions take the following form:
.Bd -unfilled -offset indent
.Sm off
@ -3160,15 +3161,13 @@ If a
is a single dash
.Pq Sq -
or absent, read from standard input.
Unless compiled with
.Dv MKSH_NO_EXTERNAL_CAT ,
if any options are given, an external
.Xr cat 1
utility is invoked instead if called from the shell.
For direct builtin calls, the
.Tn POSIX
.Fl u
option is supported as a no-op.
For calls from shell, if any options are given, an external
.Xr cat 1
utility is preferred over the builtin.
.Pp
.It Xo
.Ic cd
@ -3296,9 +3295,9 @@ option is given, instead of executing
.Ar cmd ,
information about what would be executed is given (and the same is done for
.Ar arg ... ) .
For special and regular built-in commands and functions, their names are simply
printed; for aliases, a command that defines them is printed; and for commands
found by searching the
For builtins, functions and keywords, their names are simply printed;
for aliases, a command that defines them is printed;
for utilities found by searching the
.Ev PATH
parameter, the full path of the command is printed.
If no command is found
@ -3832,7 +3831,8 @@ if empty, instead of the ASCII newline character as input line delimiter.
.It Fl N Ar z
Instead of reading till end-of-line, read exactly
.Ar z
bytes; less if EOF or a timeout occurs.
bytes.
If EOF or a timeout occurs, a partial read is returned with exit status 1.
.It Fl n Ar z
Instead of reading till end-of-line, read up to
.Ar z
@ -3851,6 +3851,9 @@ The argument must immediately follow the option character.
Interrupt reading after
.Ar n
seconds (specified as positive decimal value with an optional fractional part).
The exit status of
.Nm read
is 1 if the timeout occurred, but partial reads may still be returned.
.It Fl r
Normally, the ASCII backslash character escapes the special
meaning of the following character and is stripped from the input;

16
sh.h
View File

@ -172,9 +172,9 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.730 2015/05/23 17:43:22 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.734 2015/07/06 17:48:37 tg Exp $");
#endif
#define MKSH_VERSION "R51 2015/05/23"
#define MKSH_VERSION "R51 2015/07/06"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
@ -861,6 +861,7 @@ EXTERN const char T_typeset[] E_INIT("=typeset");
#define Ttypeset (T_typeset + 1) /* "typeset" */
EXTERN const char Talias[] E_INIT("alias");
EXTERN const char Tunalias[] E_INIT("unalias");
EXTERN const char Tcat[] E_INIT("cat");
EXTERN const char Tsgset[] E_INIT("*=set");
#define Tset (Tsgset + 2) /* "set" */
EXTERN const char Tsgexport[] E_INIT("*=export");
@ -1665,6 +1666,13 @@ EXTERN char **history; /* saved commands */
EXTERN char **histptr; /* last history item */
EXTERN mksh_ari_t histsize; /* history size */
/* flags to histsave */
#define HIST_FLUSH 0
#define HIST_QUEUE 1
#define HIST_APPEND 2
#define HIST_STORE 3
#define HIST_NOTE 4
/* user and system time of last j_waitjed job */
EXTERN struct timeval j_usrtime, j_systime;
@ -1791,7 +1799,7 @@ void hist_init(Source *);
#if HAVE_PERSISTENT_HISTORY
void hist_finish(void);
#endif
void histsave(int *, const char *, bool, bool);
void histsave(int *, const char *, int, bool);
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
bool histsync(void);
#endif
@ -1934,7 +1942,7 @@ int ksh_getopt(const char **, Getopt *, const char *);
void print_value_quoted(struct shf *, const char *);
char *quote_value(const char *);
void print_columns(struct shf *, unsigned int,
char *(*)(char *, size_t, unsigned int, const void *),
void (*)(char *, size_t, unsigned int, const void *),
const void *, size_t, size_t, bool);
void strip_nuls(char *, size_t)
MKSH_A_BOUNDED(__string__, 1, 2);