Merge remote-tracking branch 'mksh/master'
This commit is contained in:
3
Build.sh
3
Build.sh
@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/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,
|
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||||
# 2011, 2012, 2013, 2014, 2015
|
# 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_NOPWNAM skip PAM calls, for -static on glibc or Solaris
|
||||||
MKSH_NO_CMDLINE_EDITING disable command line editing code entirely
|
MKSH_NO_CMDLINE_EDITING disable command line editing code entirely
|
||||||
MKSH_NO_DEPRECATED_WARNING omit warning when deprecated stuff is run
|
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_LIMITS omit ulimit code
|
||||||
MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available
|
MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available
|
||||||
MKSH_NO_SIGSUSPEND use sigprocmask+pause instead of sigsuspend
|
MKSH_NO_SIGSUSPEND use sigprocmask+pause instead of sigsuspend
|
||||||
|
12
check.t
12
check.t
@ -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 -*-
|
# -*- mode: sh -*-
|
||||||
#-
|
#-
|
||||||
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
# 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
|
# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
|
||||||
|
|
||||||
expected-stdout:
|
expected-stdout:
|
||||||
@(#)MIRBSD KSH R51 2015/05/23
|
@(#)MIRBSD KSH R51 2015/07/06
|
||||||
description:
|
description:
|
||||||
Check version of shell.
|
Check version of shell.
|
||||||
stdin:
|
stdin:
|
||||||
@ -39,7 +39,7 @@ name: KSH_VERSION
|
|||||||
category: shell:legacy-no
|
category: shell:legacy-no
|
||||||
---
|
---
|
||||||
expected-stdout:
|
expected-stdout:
|
||||||
@(#)LEGACY KSH R51 2015/05/23
|
@(#)LEGACY KSH R51 2015/07/06
|
||||||
description:
|
description:
|
||||||
Check version of legacy shell.
|
Check version of legacy shell.
|
||||||
stdin:
|
stdin:
|
||||||
@ -3583,7 +3583,7 @@ expected-stdout:
|
|||||||
a new line
|
a new line
|
||||||
1 echo abc def
|
1 echo abc def
|
||||||
2 echo FOOBAR def
|
2 echo FOOBAR def
|
||||||
3 echo a new line
|
echo a new line
|
||||||
expected-stderr-pattern:
|
expected-stderr-pattern:
|
||||||
/^X*echo FOOBAR def\necho a new line\nX*$/
|
/^X*echo FOOBAR def\necho a new line\nX*$/
|
||||||
---
|
---
|
||||||
@ -3665,7 +3665,7 @@ expected-stdout:
|
|||||||
a new line
|
a new line
|
||||||
1 echo abc def
|
1 echo abc def
|
||||||
2 echo FOOBAR def
|
2 echo FOOBAR def
|
||||||
3 echo a new line
|
echo a new line
|
||||||
expected-stderr-pattern:
|
expected-stderr-pattern:
|
||||||
/^X*13\n32\necho FOOBAR def\necho a new line\nX*$/
|
/^X*13\n32\necho FOOBAR def\necho a new line\nX*$/
|
||||||
---
|
---
|
||||||
@ -8599,6 +8599,7 @@ description:
|
|||||||
Ensure concatenating behaviour matches other shells
|
Ensure concatenating behaviour matches other shells
|
||||||
stdin:
|
stdin:
|
||||||
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
|
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
|
||||||
|
showargs 0 ""$@
|
||||||
x=; showargs 1 "$x"$@
|
x=; showargs 1 "$x"$@
|
||||||
set A; showargs 2 "${@:+}"
|
set A; showargs 2 "${@:+}"
|
||||||
n() { echo "$#"; }
|
n() { echo "$#"; }
|
||||||
@ -8618,6 +8619,7 @@ stdin:
|
|||||||
n "$@"
|
n "$@"
|
||||||
n "$@""$e"
|
n "$@""$e"
|
||||||
expected-stdout:
|
expected-stdout:
|
||||||
|
<0> <> .
|
||||||
<1> <> .
|
<1> <> .
|
||||||
<2> <> .
|
<2> <> .
|
||||||
2
|
2
|
||||||
|
24
dot.mkshrc
24
dot.mkshrc
@ -1,5 +1,5 @@
|
|||||||
# $Id$
|
# $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,
|
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
|
||||||
# 2011, 2012, 2013, 2014, 2015
|
# 2011, 2012, 2013, 2014, 2015
|
||||||
@ -67,8 +67,9 @@ else
|
|||||||
\typeset -Uui16 -Z11 pos=0
|
\typeset -Uui16 -Z11 pos=0
|
||||||
\typeset -Uui16 -Z5 hv=2147483647
|
\typeset -Uui16 -Z5 hv=2147483647
|
||||||
\typeset dasc line i
|
\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[*]'
|
\typeset -i1 'line[*]'
|
||||||
i=0
|
i=0
|
||||||
while (( i < ${#line[*]} )); do
|
while (( i < ${#line[*]} )); do
|
||||||
@ -95,7 +96,7 @@ else
|
|||||||
\builtin print -n -- '- '
|
\builtin print -n -- '- '
|
||||||
done
|
done
|
||||||
(( hv == 2147483647 )) || \builtin print -r -- "$dasc|"
|
(( hv == 2147483647 )) || \builtin print -r -- "$dasc|"
|
||||||
fi; }
|
fi
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -112,7 +113,7 @@ function chpwd {
|
|||||||
\:
|
\:
|
||||||
}
|
}
|
||||||
\chpwd .
|
\chpwd .
|
||||||
function cd {
|
cd() {
|
||||||
\builtin cd "$@" || \return $?
|
\builtin cd "$@" || \return $?
|
||||||
\chpwd "$@"
|
\chpwd "$@"
|
||||||
}
|
}
|
||||||
@ -271,8 +272,8 @@ function smores {
|
|||||||
|
|
||||||
# base64 encoder and decoder, RFC compliant, NUL safe, not EBCDIC safe
|
# base64 encoder and decoder, RFC compliant, NUL safe, not EBCDIC safe
|
||||||
function Lb64decode {
|
function Lb64decode {
|
||||||
[[ -o utf8-mode ]]; \typeset u=$? c s="$*" t
|
|
||||||
\set +U
|
\set +U
|
||||||
|
\typeset c s="$*" t
|
||||||
[[ -n $s ]] || { s=$(\cat; \builtin print x); s=${s%x}; }
|
[[ -n $s ]] || { s=$(\cat; \builtin print x); s=${s%x}; }
|
||||||
\typeset -i i=0 j=0 n=${#s} p=0 v x
|
\typeset -i i=0 j=0 n=${#s} p=0 v x
|
||||||
\typeset -i16 o
|
\typeset -i16 o
|
||||||
@ -303,14 +304,13 @@ function Lb64decode {
|
|||||||
t=
|
t=
|
||||||
done
|
done
|
||||||
\builtin print -n $t
|
\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 \
|
\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 + /
|
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 {
|
function Lb64encode {
|
||||||
[[ -o utf8-mode ]]; \typeset u=$? c s t
|
|
||||||
\set +U
|
\set +U
|
||||||
|
\typeset c s t
|
||||||
if (( $# )); then
|
if (( $# )); then
|
||||||
\read -raN-1 s <<<"$*"
|
\read -raN-1 s <<<"$*"
|
||||||
\unset s[${#s[*]}-1]
|
\unset s[${#s[*]}-1]
|
||||||
@ -339,7 +339,6 @@ function Lb64encode {
|
|||||||
t=
|
t=
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
(( u )) || \set -U
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Better Avalanche for the Jenkins Hash
|
# Better Avalanche for the Jenkins Hash
|
||||||
@ -348,8 +347,8 @@ function Lbafh_init {
|
|||||||
Lbafh_v=0
|
Lbafh_v=0
|
||||||
}
|
}
|
||||||
function Lbafh_add {
|
function Lbafh_add {
|
||||||
[[ -o utf8-mode ]]; \typeset u=$? s
|
|
||||||
\set +U
|
\set +U
|
||||||
|
\typeset s
|
||||||
if (( $# )); then
|
if (( $# )); then
|
||||||
\read -raN-1 s <<<"$*"
|
\read -raN-1 s <<<"$*"
|
||||||
\unset s[${#s[*]}-1]
|
\unset s[${#s[*]}-1]
|
||||||
@ -362,8 +361,6 @@ function Lbafh_add {
|
|||||||
((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 ))
|
((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 ))
|
||||||
((# Lbafh_v ^= Lbafh_v >> 6 ))
|
((# Lbafh_v ^= Lbafh_v >> 6 ))
|
||||||
done
|
done
|
||||||
|
|
||||||
(( u )) || \set -U
|
|
||||||
}
|
}
|
||||||
function Lbafh_finish {
|
function Lbafh_finish {
|
||||||
\typeset -Ui t
|
\typeset -Ui t
|
||||||
@ -378,10 +375,11 @@ function Lbafh_finish {
|
|||||||
# strip comments (and leading/trailing whitespace if IFS is set) from
|
# 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
|
# any file(s) given as argument, or stdin if none, and spew to stdout
|
||||||
function Lstripcom {
|
function Lstripcom {
|
||||||
\cat "$@" | { \set -o noglob; while \read _line; do
|
\set -o noglob
|
||||||
|
\cat "$@" | while \read _line; do
|
||||||
_line=${_line%%#*}
|
_line=${_line%%#*}
|
||||||
[[ -n $_line ]] && \builtin print -r -- $_line
|
[[ -n $_line ]] && \builtin print -r -- $_line
|
||||||
done; }
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# give MidnightBSD's laffer1 a bit of csh feeling
|
# give MidnightBSD's laffer1 a bit of csh feeling
|
||||||
|
8
edit.c
8
edit.c
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#ifndef MKSH_NO_CMDLINE_EDITING
|
#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
|
* 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) {
|
if (modified) {
|
||||||
*xep = '\0';
|
*xep = '\0';
|
||||||
histsave(&source->line, xbuf, true, true);
|
histsave(&source->line, xbuf, HIST_STORE, true);
|
||||||
x_arg = 0;
|
x_arg = 0;
|
||||||
} else
|
} else
|
||||||
x_arg = source->line - (histptr - x_histp);
|
x_arg = source->line - (histptr - x_histp);
|
||||||
@ -4390,8 +4390,8 @@ vi_cmd(int argcnt, const char *cmd)
|
|||||||
return (-1);
|
return (-1);
|
||||||
if (modified) {
|
if (modified) {
|
||||||
es->cbuf[es->linelen] = '\0';
|
es->cbuf[es->linelen] = '\0';
|
||||||
histsave(&source->line, es->cbuf, true,
|
histsave(&source->line, es->cbuf,
|
||||||
true);
|
HIST_STORE, true);
|
||||||
} else
|
} else
|
||||||
argcnt = source->line + 1 -
|
argcnt = source->line + 1 -
|
||||||
(hlast - hnum);
|
(hlast - hnum);
|
||||||
|
15
eval.c
15
eval.c
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#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
|
* string expansion
|
||||||
@ -291,21 +291,14 @@ expand(
|
|||||||
c = *sp++;
|
c = *sp++;
|
||||||
break;
|
break;
|
||||||
case OQUOTE:
|
case OQUOTE:
|
||||||
switch (word) {
|
if (word != IFS_WORD)
|
||||||
case IFS_QUOTE:
|
|
||||||
/* """something */
|
|
||||||
word = IFS_WORD;
|
|
||||||
break;
|
|
||||||
case IFS_WORD:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
word = IFS_QUOTE;
|
word = IFS_QUOTE;
|
||||||
break;
|
|
||||||
}
|
|
||||||
tilde_ok = 0;
|
tilde_ok = 0;
|
||||||
quote = 1;
|
quote = 1;
|
||||||
continue;
|
continue;
|
||||||
case CQUOTE:
|
case CQUOTE:
|
||||||
|
if (word == IFS_QUOTE)
|
||||||
|
word = IFS_WORD;
|
||||||
quote = st->quotew;
|
quote = st->quotew;
|
||||||
continue;
|
continue;
|
||||||
case COMSUB:
|
case COMSUB:
|
||||||
|
46
exec.c
46
exec.c
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#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
|
#ifndef MKSH_DEFAULT_EXECSHELL
|
||||||
#define MKSH_DEFAULT_EXECSHELL UNIXROOT "/bin/sh"
|
#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 void dbteste_error(Test_env *, int, const char *);
|
||||||
static int search_access(const char *, int);
|
static int search_access(const char *, int);
|
||||||
/* XXX: horrible kludge to fit within the framework */
|
/* XXX: horrible kludge to fit within the framework */
|
||||||
static char *plain_fmt_entry(char *, size_t, unsigned int, const void *);
|
static void plain_fmt_entry(char *, size_t, unsigned int, const void *);
|
||||||
static char *select_fmt_entry(char *, size_t, unsigned int, const void *);
|
static void select_fmt_entry(char *, size_t, unsigned int, const void *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* execute command tree
|
* 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)
|
if ((tp = findcom(cp, FC_BI)) == NULL)
|
||||||
errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin");
|
errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin");
|
||||||
|
if (tp->type == CSHELL && tp->val.f == c_cat)
|
||||||
|
break;
|
||||||
continue;
|
continue;
|
||||||
} else if (tp->val.f == c_exec) {
|
} else if (tp->val.f == c_exec) {
|
||||||
if (ap[1] == NULL)
|
if (ap[1] == NULL)
|
||||||
@ -607,25 +609,19 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
|||||||
subst_exstat = 0;
|
subst_exstat = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifndef MKSH_NO_EXTERNAL_CAT
|
|
||||||
} else if (tp->val.f == c_cat) {
|
} else if (tp->val.f == c_cat) {
|
||||||
/*
|
/* if we have any flags, do not use the builtin */
|
||||||
* 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 (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' &&
|
if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' &&
|
||||||
/* argument, begins with -, is not - or -- */
|
/* argument, begins with -, is not - or -- */
|
||||||
(ap[1][1] != '-' || ap[1][2] != '\0'))
|
(ap[1][1] != '-' || ap[1][2] != '\0')) {
|
||||||
/* don't look for builtins or functions */
|
struct tbl *ext_cat;
|
||||||
fcflags = FC_PATH;
|
|
||||||
else
|
ext_cat = findcom(Tcat, FC_PATH | FC_FUNC);
|
||||||
/* go on, use the builtin */
|
if (ext_cat && (ext_cat->type != CTALIAS ||
|
||||||
|
(ext_cat->flag & ISSET)))
|
||||||
|
tp = ext_cat;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
} else if (tp->val.f == c_trap) {
|
} else if (tp->val.f == c_trap) {
|
||||||
t->u.evalflags &= ~DOTCOMEXEC;
|
t->u.evalflags &= ~DOTCOMEXEC;
|
||||||
break;
|
break;
|
||||||
@ -705,6 +701,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
|||||||
|
|
||||||
/* shell built-in */
|
/* shell built-in */
|
||||||
case CSHELL:
|
case CSHELL:
|
||||||
|
do_call_builtin:
|
||||||
rv = call_builtin(tp, (const char **)ap, null, resetspec);
|
rv = call_builtin(tp, (const char **)ap, null, resetspec);
|
||||||
if (resetspec && tp->val.f == c_shift) {
|
if (resetspec && tp->val.f == c_shift) {
|
||||||
l_expand->argc = l_assign->argc;
|
l_expand->argc = l_assign->argc;
|
||||||
@ -729,6 +726,11 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (include(tp->u.fpath, 0, NULL, false) < 0) {
|
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,
|
warningf(true, "%s: %s %s %s: %s", cp,
|
||||||
"can't open", "function definition file",
|
"can't open", "function definition file",
|
||||||
tp->u.fpath, cstrerror(errno));
|
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)) ||
|
if (!(ftp = findfunc(cp, hash(cp), false)) ||
|
||||||
!(ftp->flag & ISSET)) {
|
!(ftp->flag & ISSET)) {
|
||||||
|
if (!strcmp(cp, Tcat))
|
||||||
|
goto no_cat_in_FPATH;
|
||||||
warningf(true, "%s: %s %s", cp,
|
warningf(true, "%s: %s %s", cp,
|
||||||
"function not defined by", tp->u.fpath);
|
"function not defined by", tp->u.fpath);
|
||||||
rv = 127;
|
rv = 127;
|
||||||
@ -1657,7 +1661,7 @@ struct select_menu_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* format a single select menu item */
|
/* format a single select menu item */
|
||||||
static char *
|
static void
|
||||||
select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
|
select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
|
||||||
{
|
{
|
||||||
const struct select_menu_info *smi =
|
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",
|
shf_snprintf(buf, buflen, "%*u) %s",
|
||||||
smi->num_width, i + 1, smi->args[i]);
|
smi->num_width, i + 1, smi->args[i]);
|
||||||
return (buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1711,11 +1714,10 @@ pr_menu(const char * const *ap)
|
|||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static void
|
||||||
plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
|
plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
|
||||||
{
|
{
|
||||||
strlcpy(buf, ((const char * const *)arg)[i], buflen);
|
strlcpy(buf, ((const char * const *)arg)[i], buflen);
|
||||||
return (buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
23
funcs.c
23
funcs.c
@ -38,7 +38,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#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
|
#if HAVE_KILLPG
|
||||||
/*
|
/*
|
||||||
@ -99,7 +99,7 @@ const struct builtin mkshbuiltins[] = {
|
|||||||
{Talias, c_alias},
|
{Talias, c_alias},
|
||||||
{"*=break", c_brkcont},
|
{"*=break", c_brkcont},
|
||||||
{Tgbuiltin, c_builtin},
|
{Tgbuiltin, c_builtin},
|
||||||
{"cat", c_cat},
|
{Tcat, c_cat},
|
||||||
{"cd", c_cd},
|
{"cd", c_cd},
|
||||||
/* dash compatibility hack */
|
/* dash compatibility hack */
|
||||||
{"chdir", c_cd},
|
{"chdir", c_cd},
|
||||||
@ -227,7 +227,7 @@ static int test_primary(Test_env *, bool);
|
|||||||
static Test_op ptest_isa(Test_env *, Test_meta);
|
static Test_op ptest_isa(Test_env *, Test_meta);
|
||||||
static const char *ptest_getopnd(Test_env *, Test_op, bool);
|
static const char *ptest_getopnd(Test_env *, Test_op, bool);
|
||||||
static void ptest_error(Test_env *, int, const char *);
|
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,
|
static void p_time(struct shf *, bool, long, int, int,
|
||||||
const char *, const char *);
|
const char *, const char *);
|
||||||
|
|
||||||
@ -445,7 +445,7 @@ c_print(const char **wp)
|
|||||||
|
|
||||||
if (flags & PO_HIST) {
|
if (flags & PO_HIST) {
|
||||||
Xput(xs, xp, '\0');
|
Xput(xs, xp, '\0');
|
||||||
histsave(&source->line, Xstring(xs, xp), true, false);
|
histsave(&source->line, Xstring(xs, xp), HIST_STORE, false);
|
||||||
Xfree(xs, xp);
|
Xfree(xs, xp);
|
||||||
} else {
|
} else {
|
||||||
int len = Xlength(xs, xp);
|
int len = Xlength(xs, xp);
|
||||||
@ -541,7 +541,7 @@ c_whence(const char **wp)
|
|||||||
uint32_t h = 0;
|
uint32_t h = 0;
|
||||||
|
|
||||||
tp = NULL;
|
tp = NULL;
|
||||||
if ((iam_whence || vflag) && !pflag)
|
if (!pflag)
|
||||||
tp = ktsearch(&keywords, id, h = hash(id));
|
tp = ktsearch(&keywords, id, h = hash(id));
|
||||||
if (!tp && !pflag) {
|
if (!tp && !pflag) {
|
||||||
tp = ktsearch(&aliases, id, h ? h : hash(id));
|
tp = ktsearch(&aliases, id, h ? h : hash(id));
|
||||||
@ -1310,7 +1310,7 @@ c_fgbg(const char **wp)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* format a single kill item */
|
/* format a single kill item */
|
||||||
static char *
|
static void
|
||||||
kill_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
|
kill_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
|
||||||
{
|
{
|
||||||
const struct kill_info *ki = (const struct kill_info *)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->num_width, i,
|
||||||
ki->name_width, sigtraps[i].name,
|
ki->name_width, sigtraps[i].name,
|
||||||
sigtraps[i].mess);
|
sigtraps[i].mess);
|
||||||
return (buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1967,8 +1966,9 @@ c_read(const char **wp)
|
|||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
/* timeout expired for this call */
|
/* timeout expired for this call */
|
||||||
rv = 1;
|
bytesread = 0;
|
||||||
goto c_read_out;
|
/* fake EOF read; all cases return 1 */
|
||||||
|
goto c_read_didread;
|
||||||
default:
|
default:
|
||||||
bi_errorf("%s: %s", Tselect, cstrerror(errno));
|
bi_errorf("%s: %s", Tselect, cstrerror(errno));
|
||||||
rv = 2;
|
rv = 2;
|
||||||
@ -1993,6 +1993,7 @@ c_read(const char **wp)
|
|||||||
goto c_read_readloop;
|
goto c_read_readloop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c_read_didread:
|
||||||
switch (readmode) {
|
switch (readmode) {
|
||||||
case READALL:
|
case READALL:
|
||||||
if (bytesread == 0) {
|
if (bytesread == 0) {
|
||||||
@ -2015,7 +2016,7 @@ c_read(const char **wp)
|
|||||||
if (bytesread == 0) {
|
if (bytesread == 0) {
|
||||||
/* end of file reached */
|
/* end of file reached */
|
||||||
rv = 1;
|
rv = 1;
|
||||||
xp = Xstring(xs, xp);
|
/* may be partial read: $? = 1, but content */
|
||||||
goto c_read_readdone;
|
goto c_read_readdone;
|
||||||
}
|
}
|
||||||
xp += bytesread;
|
xp += bytesread;
|
||||||
@ -2078,7 +2079,7 @@ c_read(const char **wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (savehist)
|
if (savehist)
|
||||||
histsave(&source->line, Xstring(xs, xp), true, false);
|
histsave(&source->line, Xstring(xs, xp), HIST_STORE, false);
|
||||||
|
|
||||||
ccp = cp = Xclose(xs, xp);
|
ccp = cp = Xclose(xs, xp);
|
||||||
expanding = false;
|
expanding = false;
|
||||||
|
103
histrap.c
103
histrap.c
@ -27,7 +27,7 @@
|
|||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#endif
|
#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];
|
Trap sigtraps[ksh_NSIG + 1];
|
||||||
static struct sigaction Sigact_ign;
|
static struct sigaction Sigact_ign;
|
||||||
@ -38,7 +38,7 @@ static int writehistline(int, int, const char *);
|
|||||||
static void writehistfile(int, const char *);
|
static void writehistfile(int, const char *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int hist_execute(char *);
|
static int hist_execute(char *, Area *);
|
||||||
static char **hist_get(const char *, bool, bool);
|
static char **hist_get(const char *, bool, bool);
|
||||||
static char **hist_get_oldest(void);
|
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 */
|
/* maximum considered size of persistent history file */
|
||||||
#define MKSH_MAXHISTFSIZE ((off_t)1048576 * 96)
|
#define MKSH_MAXHISTFSIZE ((off_t)1048576 * 96)
|
||||||
|
|
||||||
|
/* hidden option */
|
||||||
|
#define HIST_DISCARD 5
|
||||||
|
|
||||||
int
|
int
|
||||||
c_fc(const char **wp)
|
c_fc(const char **wp)
|
||||||
{
|
{
|
||||||
@ -223,7 +226,7 @@ c_fc(const char **wp)
|
|||||||
xp += len;
|
xp += len;
|
||||||
line = Xclose(xs, xp);
|
line = Xclose(xs, xp);
|
||||||
}
|
}
|
||||||
return (hist_execute(line));
|
return (hist_execute(line, ATEMP));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editor && (lflag || nflag)) {
|
if (editor && (lflag || nflag)) {
|
||||||
@ -360,18 +363,17 @@ c_fc(const char **wp)
|
|||||||
shf_close(shf);
|
shf_close(shf);
|
||||||
*xp = '\0';
|
*xp = '\0';
|
||||||
strip_nuls(Xstring(xs, xp), Xlength(xs, xp));
|
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 afree’d) */
|
||||||
static int
|
static int
|
||||||
hist_execute(char *cmd)
|
hist_execute(char *cmd, Area *areap)
|
||||||
{
|
{
|
||||||
static int last_line = -1;
|
static int last_line = -1;
|
||||||
Source *sold;
|
Source *sold;
|
||||||
int ret;
|
int ret;
|
||||||
char *p, *q;
|
|
||||||
|
|
||||||
/* Back up over last histsave */
|
/* Back up over last histsave */
|
||||||
if (histptr >= history && last_line != hist_source->line) {
|
if (histptr >= history && last_line != hist_source->line) {
|
||||||
@ -381,22 +383,12 @@ hist_execute(char *cmd)
|
|||||||
last_line = hist_source->line;
|
last_line = hist_source->line;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (p = cmd; p; p = q) {
|
histsave(&hist_source->line, cmd, HIST_STORE, true);
|
||||||
if ((q = strchr(p, '\n'))) {
|
/* now *histptr == cmd without all trailing newlines */
|
||||||
/* kill the newline */
|
afree(cmd, areap);
|
||||||
*q++ = '\0';
|
cmd = *histptr;
|
||||||
if (!*q)
|
/* pdksh says POSIX doesn’t say this is done, testsuite needs it */
|
||||||
/* ignore trailing newline */
|
shellf("%s\n", cmd);
|
||||||
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';
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Commands are executed here instead of pushing them onto the
|
* Commands are executed here instead of pushing them onto the
|
||||||
@ -578,6 +570,7 @@ sethistfile(const char *name)
|
|||||||
afree(hname, APERM);
|
afree(hname, APERM);
|
||||||
hname = NULL;
|
hname = NULL;
|
||||||
/* let's reset the history */
|
/* let's reset the history */
|
||||||
|
histsave(NULL, NULL, HIST_DISCARD, true);
|
||||||
histptr = history - 1;
|
histptr = history - 1;
|
||||||
hist_source->line = 0;
|
hist_source->line = 0;
|
||||||
}
|
}
|
||||||
@ -612,6 +605,8 @@ histsync(void)
|
|||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
|
/* called by histsave(), may not HIST_DISCARD, caller should flush */
|
||||||
|
|
||||||
if (histfd != -1) {
|
if (histfd != -1) {
|
||||||
int lno = hist_source->line;
|
int lno = hist_source->line;
|
||||||
|
|
||||||
@ -631,15 +626,38 @@ histsync(void)
|
|||||||
* save command in history
|
* save command in history
|
||||||
*/
|
*/
|
||||||
void
|
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;
|
static char *enqueued = NULL;
|
||||||
char *c, *cp;
|
char **hp, *c;
|
||||||
|
const char *ccp;
|
||||||
|
|
||||||
strdupx(c, cmd, APERM);
|
if (svmode == HIST_DISCARD) {
|
||||||
if ((cp = strchr(c, '\n')) != NULL)
|
afree(enqueued, APERM);
|
||||||
*cp = '\0';
|
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 (ignoredups && !strcmp(c, *histptr)
|
||||||
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
||||||
&& !histsync()
|
&& !histsync()
|
||||||
@ -649,12 +667,33 @@ histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
++*lnp;
|
++*lnp;
|
||||||
|
}
|
||||||
|
|
||||||
#if HAVE_PERSISTENT_HISTORY
|
#if HAVE_PERSISTENT_HISTORY
|
||||||
if (dowrite && histfd != -1)
|
if (svmode == HIST_STORE && histfd != -1)
|
||||||
writehistfile(*lnp, c);
|
writehistfile(*lnp, c);
|
||||||
#endif
|
#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;
|
hp = histptr;
|
||||||
|
|
||||||
if (++hp >= history + histsize) {
|
if (++hp >= history + histsize) {
|
||||||
@ -707,6 +746,8 @@ hist_init(Source *s)
|
|||||||
enum { hist_init_first, hist_init_retry, hist_init_restore } hs;
|
enum { hist_init_first, hist_init_retry, hist_init_restore } hs;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
histsave(NULL, NULL, HIST_DISCARD, true);
|
||||||
|
|
||||||
if (Flag(FTALKING) == 0)
|
if (Flag(FTALKING) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -864,7 +905,7 @@ histload(Source *s, unsigned char *base, size_t bytes)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s->line = lno--;
|
s->line = lno--;
|
||||||
histsave(&lno, (char *)(base + 4), false, false);
|
histsave(&lno, (char *)(base + 4), HIST_NOTE, false);
|
||||||
}
|
}
|
||||||
/* advance base pointer past NUL */
|
/* advance base pointer past NUL */
|
||||||
bytes -= ++cp - base;
|
bytes -= ++cp - base;
|
||||||
|
22
lex.c
22
lex.c
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#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
|
* states while lexing word
|
||||||
@ -1461,16 +1461,23 @@ getsc_line(Source *s)
|
|||||||
if (s->type == SFILE)
|
if (s->type == SFILE)
|
||||||
shf_fdclose(s->u.shf);
|
shf_fdclose(s->u.shf);
|
||||||
s->str = NULL;
|
s->str = NULL;
|
||||||
} else if (interactive && *s->str &&
|
} else if (interactive && *s->str) {
|
||||||
(cur_prompt != PS1 || !ctype(*s->str, C_IFS | C_IFSWS))) {
|
if (cur_prompt != PS1)
|
||||||
histsave(&s->line, s->str, true, true);
|
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
|
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
||||||
|
else
|
||||||
|
goto check_for_sole_return;
|
||||||
} else if (interactive && cur_prompt == PS1) {
|
} else if (interactive && cur_prompt == PS1) {
|
||||||
|
check_for_sole_return:
|
||||||
cp = Xstring(s->xs, xp);
|
cp = Xstring(s->xs, xp);
|
||||||
while (*cp && ctype(*cp, C_IFSWS))
|
while (*cp && ctype(*cp, C_IFSWS))
|
||||||
++cp;
|
++cp;
|
||||||
if (!*cp)
|
if (!*cp) {
|
||||||
|
histsave(&s->line, NULL, HIST_FLUSH, true);
|
||||||
histsync();
|
histsync();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (interactive)
|
if (interactive)
|
||||||
@ -1495,6 +1502,7 @@ set_prompt(int to, Source *s)
|
|||||||
struct shf *shf;
|
struct shf *shf;
|
||||||
char * volatile ps1;
|
char * volatile ps1;
|
||||||
Area *saved_atemp;
|
Area *saved_atemp;
|
||||||
|
int saved_lineno;
|
||||||
|
|
||||||
ps1 = str_val(global("PS1"));
|
ps1 = str_val(global("PS1"));
|
||||||
shf = shf_sopen(NULL, strlen(ps1) * 2,
|
shf = shf_sopen(NULL, strlen(ps1) * 2,
|
||||||
@ -1506,6 +1514,9 @@ set_prompt(int to, Source *s)
|
|||||||
shf_fprintf(shf, "%lu", s ?
|
shf_fprintf(shf, "%lu", s ?
|
||||||
(unsigned long)s->line + 1 : 0UL);
|
(unsigned long)s->line + 1 : 0UL);
|
||||||
ps1 = shf_sclose(shf);
|
ps1 = shf_sclose(shf);
|
||||||
|
saved_lineno = current_lineno;
|
||||||
|
if (s)
|
||||||
|
current_lineno = s->line + 1;
|
||||||
saved_atemp = ATEMP;
|
saved_atemp = ATEMP;
|
||||||
newenv(E_ERRH);
|
newenv(E_ERRH);
|
||||||
if (kshsetjmp(e->jbuf)) {
|
if (kshsetjmp(e->jbuf)) {
|
||||||
@ -1521,6 +1532,7 @@ set_prompt(int to, Source *s)
|
|||||||
char *cp = substitute(ps1, 0);
|
char *cp = substitute(ps1, 0);
|
||||||
strdupx(prompt, cp, saved_atemp);
|
strdupx(prompt, cp, saved_atemp);
|
||||||
}
|
}
|
||||||
|
current_lineno = saved_lineno;
|
||||||
quitenv(NULL);
|
quitenv(NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
6
main.c
6
main.c
@ -34,7 +34,7 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#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;
|
extern char **environ;
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ static const char *initcoms[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
/* this is what AT&T ksh seems to track, with the addition of emacs */
|
/* this is what AT&T ksh seems to track, with the addition of emacs */
|
||||||
Talias, "-tU",
|
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,
|
"make", "mv", "pr", "rm", "sed", "sh", "vi", "who", NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
@ -825,6 +825,8 @@ shell(Source * volatile s, volatile bool toplevel)
|
|||||||
set_prompt(PS1, s);
|
set_prompt(PS1, s);
|
||||||
}
|
}
|
||||||
t = compile(s, sfirst);
|
t = compile(s, sfirst);
|
||||||
|
if (interactive)
|
||||||
|
histsave(&s->line, NULL, HIST_FLUSH, true);
|
||||||
sfirst = false;
|
sfirst = false;
|
||||||
if (!t)
|
if (!t)
|
||||||
goto source_no_tree;
|
goto source_no_tree;
|
||||||
|
12
mirhash.h
12
mirhash.h
@ -1,6 +1,6 @@
|
|||||||
/*-
|
/*-
|
||||||
* Copyright © 2011, 2014
|
* Copyright © 2011, 2014, 2015
|
||||||
* Thorsten Glaser <tg@mirbsd.org>
|
* Thorsten “mirabilos” Glaser <tg@mirbsd.org>
|
||||||
*
|
*
|
||||||
* Provided that these terms and disclaimer and all copyright notices
|
* Provided that these terms and disclaimer and all copyright notices
|
||||||
* are retained or reproduced in an accompanying document, permission
|
* are retained or reproduced in an accompanying document, permission
|
||||||
@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#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:
|
* 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.
|
* the context is (still) zero, adding a NUL byte is not ignored.
|
||||||
*
|
*
|
||||||
* • BAFHror(eax,cl) evaluates to the unsigned 32-bit integer “eax”,
|
* • 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
|
* • BAFHFinish(ctx) avalanches the context around so every sub-byte
|
||||||
* depends on all input octets; afterwards, the context variable’s
|
* depends on all input octets; afterwards, the context variable’s
|
||||||
@ -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.
|
* • BAFHHostStr(ctx,buf) does the same for C strings.
|
||||||
*
|
*
|
||||||
* All macros may use ctx multiple times in their expansion, but all
|
* 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
|
* To stay portable, never use the BAFHHost*() macros (these are for
|
||||||
* host-local entropy shuffling), and encode numbers using ULEB128.
|
* 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; \
|
} BAFHHost_v; \
|
||||||
\
|
\
|
||||||
BAFHUpdate_s = (const void *)(s); \
|
BAFHUpdate_s = (const void *)(s); \
|
||||||
|
BAFHHost_v.as_u32 = 0; \
|
||||||
if ((BAFHHost_v.as_u8[0] = *BAFHUpdate_s) != 0) \
|
if ((BAFHHost_v.as_u8[0] = *BAFHUpdate_s) != 0) \
|
||||||
++BAFHUpdate_s; \
|
++BAFHUpdate_s; \
|
||||||
if ((BAFHHost_v.as_u8[1] = *BAFHUpdate_s) != 0) \
|
if ((BAFHHost_v.as_u8[1] = *BAFHUpdate_s) != 0) \
|
||||||
|
45
misc.c
45
misc.c
@ -30,7 +30,7 @@
|
|||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#endif
|
#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
|
#define KSH_CHVT_FLAG
|
||||||
#ifdef MKSH_SMALL
|
#ifdef MKSH_SMALL
|
||||||
@ -173,11 +173,11 @@ struct options_info {
|
|||||||
int opts[NELEM(options)];
|
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);
|
static void printoptions(bool);
|
||||||
|
|
||||||
/* format a single select menu item */
|
/* format a single select menu item */
|
||||||
static char *
|
static void
|
||||||
options_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
|
options_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
|
||||||
{
|
{
|
||||||
const struct options_info *oi = (const struct options_info *)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",
|
shf_snprintf(buf, buflen, "%-*s %s",
|
||||||
oi->opt_width, OFN(oi->opts[i]),
|
oi->opt_width, OFN(oi->opts[i]),
|
||||||
Flag(oi->opts[i]) ? "on" : "off");
|
Flag(oi->opts[i]) ? "on" : "off");
|
||||||
return (buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1227,7 +1226,7 @@ print_value_quoted(struct shf *shf, const char *s)
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
print_columns(struct shf *shf, unsigned int n,
|
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)
|
const void *arg, size_t max_oct, size_t max_colz, bool prefcol)
|
||||||
{
|
{
|
||||||
unsigned int i, r, c, rows, cols, nspace, max_col;
|
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);
|
str = alloc(max_oct, ATEMP);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We use (max_col + 1) to consider the space separator.
|
* We use (max_col + 2) to consider the separator space.
|
||||||
* Note that no space is printed after the last column
|
* Note that no spaces are printed after the last column
|
||||||
* to avoid problems with terminals that have auto-wrap.
|
* 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 we can only print one column anyway, skip the goo */
|
||||||
if (cols < 2) {
|
if (cols < 2) {
|
||||||
for (i = 0; i < n; ++i)
|
for (i = 0; i < n; ++i) {
|
||||||
shf_fprintf(shf, "%s\n",
|
(*func)(str, max_oct, i, arg);
|
||||||
(*func)(str, max_oct, i, arg));
|
shf_puts(str, shf);
|
||||||
|
shf_putc('\n', shf);
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1277,18 +1279,19 @@ print_columns(struct shf *shf, unsigned int n,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nspace = (x_cols - max_col * cols) / cols;
|
nspace = (x_cols - max_col * cols) / cols;
|
||||||
|
if (nspace < 2)
|
||||||
|
nspace = 2;
|
||||||
max_col = -max_col;
|
max_col = -max_col;
|
||||||
if (nspace <= 0)
|
|
||||||
nspace = 1;
|
|
||||||
for (r = 0; r < rows; r++) {
|
for (r = 0; r < rows; r++) {
|
||||||
for (c = 0; c < cols; c++) {
|
for (c = 0; c < cols; c++) {
|
||||||
i = c * rows + r;
|
if ((i = c * rows + r) >= n)
|
||||||
if (i < n) {
|
break;
|
||||||
shf_fprintf(shf, "%*s", max_col,
|
(*func)(str, max_oct, i, arg);
|
||||||
(*func)(str, max_oct, i, arg));
|
if (i + rows >= n)
|
||||||
if (c + 1 < cols)
|
shf_puts(str, shf);
|
||||||
shf_fprintf(shf, "%*s", nspace, null);
|
else
|
||||||
}
|
shf_fprintf(shf, "%*s%*s",
|
||||||
|
max_col, str, nspace, null);
|
||||||
}
|
}
|
||||||
shf_putchar('\n', shf);
|
shf_putchar('\n', shf);
|
||||||
}
|
}
|
||||||
|
33
mksh.1
33
mksh.1
@ -1,5 +1,5 @@
|
|||||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.367 2015/05/23 17:43:20 tg Exp $
|
.\" $MirOS: src/bin/mksh/mksh.1,v 1.373 2015/07/06 17:48:35 tg Exp $
|
||||||
.\" $OpenBSD: ksh.1,v 1.159 2015/03/25 12:10:52 jca Exp $
|
.\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $
|
||||||
.\"-
|
.\"-
|
||||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||||
.\" 2010, 2011, 2012, 2013, 2014, 2015
|
.\" 2010, 2011, 2012, 2013, 2014, 2015
|
||||||
@ -74,7 +74,7 @@
|
|||||||
.\" with -mandoc, it might implement .Mx itself, but we want to
|
.\" with -mandoc, it might implement .Mx itself, but we want to
|
||||||
.\" use our own definition. And .Dd must come *first*, always.
|
.\" 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.
|
.\" Check which macro package we use, and do other -mdoc setup.
|
||||||
.\"
|
.\"
|
||||||
@ -476,7 +476,7 @@ and
|
|||||||
.Ql }
|
.Ql }
|
||||||
delimit
|
delimit
|
||||||
.Xr csh 1 Ns -style
|
.Xr csh 1 Ns -style
|
||||||
alterations (see
|
alternations (see
|
||||||
.Sx Brace expansion
|
.Sx Brace expansion
|
||||||
below);
|
below);
|
||||||
and finally,
|
and finally,
|
||||||
@ -1859,7 +1859,8 @@ below for more information.
|
|||||||
.It Ev HISTFILE
|
.It Ev HISTFILE
|
||||||
The name of the file used to store command history.
|
The name of the file used to store command history.
|
||||||
When assigned to or unset, the file is opened, history is truncated
|
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
|
Also, several invocations of the shell will share history if their
|
||||||
.Ev HISTFILE
|
.Ev HISTFILE
|
||||||
parameters all point to the same file.
|
parameters all point to the same file.
|
||||||
@ -2145,7 +2146,7 @@ The
|
|||||||
.Ic alias Fl d
|
.Ic alias Fl d
|
||||||
command may be used to list, change, and add to this cache (e.g.\&
|
command may be used to list, change, and add to this cache (e.g.\&
|
||||||
.Ic alias \-d fac=/usr/local/facilities; cd \*(TIfac/bin ) .
|
.Ic alias \-d fac=/usr/local/facilities; cd \*(TIfac/bin ) .
|
||||||
.Ss Brace expansion (alteration)
|
.Ss Brace expansion (alternation)
|
||||||
Brace expressions take the following form:
|
Brace expressions take the following form:
|
||||||
.Bd -unfilled -offset indent
|
.Bd -unfilled -offset indent
|
||||||
.Sm off
|
.Sm off
|
||||||
@ -3160,15 +3161,13 @@ If a
|
|||||||
is a single dash
|
is a single dash
|
||||||
.Pq Sq -
|
.Pq Sq -
|
||||||
or absent, read from standard input.
|
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
|
For direct builtin calls, the
|
||||||
.Tn POSIX
|
.Tn POSIX
|
||||||
.Fl u
|
.Fl u
|
||||||
option is supported as a no-op.
|
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
|
.Pp
|
||||||
.It Xo
|
.It Xo
|
||||||
.Ic cd
|
.Ic cd
|
||||||
@ -3296,9 +3295,9 @@ option is given, instead of executing
|
|||||||
.Ar cmd ,
|
.Ar cmd ,
|
||||||
information about what would be executed is given (and the same is done for
|
information about what would be executed is given (and the same is done for
|
||||||
.Ar arg ... ) .
|
.Ar arg ... ) .
|
||||||
For special and regular built-in commands and functions, their names are simply
|
For builtins, functions and keywords, their names are simply printed;
|
||||||
printed; for aliases, a command that defines them is printed; and for commands
|
for aliases, a command that defines them is printed;
|
||||||
found by searching the
|
for utilities found by searching the
|
||||||
.Ev PATH
|
.Ev PATH
|
||||||
parameter, the full path of the command is printed.
|
parameter, the full path of the command is printed.
|
||||||
If no command is found
|
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
|
.It Fl N Ar z
|
||||||
Instead of reading till end-of-line, read exactly
|
Instead of reading till end-of-line, read exactly
|
||||||
.Ar z
|
.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
|
.It Fl n Ar z
|
||||||
Instead of reading till end-of-line, read up to
|
Instead of reading till end-of-line, read up to
|
||||||
.Ar z
|
.Ar z
|
||||||
@ -3851,6 +3851,9 @@ The argument must immediately follow the option character.
|
|||||||
Interrupt reading after
|
Interrupt reading after
|
||||||
.Ar n
|
.Ar n
|
||||||
seconds (specified as positive decimal value with an optional fractional part).
|
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
|
.It Fl r
|
||||||
Normally, the ASCII backslash character escapes the special
|
Normally, the ASCII backslash character escapes the special
|
||||||
meaning of the following character and is stripped from the input;
|
meaning of the following character and is stripped from the input;
|
||||||
|
16
sh.h
16
sh.h
@ -172,9 +172,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXTERN
|
#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
|
#endif
|
||||||
#define MKSH_VERSION "R51 2015/05/23"
|
#define MKSH_VERSION "R51 2015/07/06"
|
||||||
|
|
||||||
/* arithmetic types: C implementation */
|
/* arithmetic types: C implementation */
|
||||||
#if !HAVE_CAN_INTTYPES
|
#if !HAVE_CAN_INTTYPES
|
||||||
@ -861,6 +861,7 @@ EXTERN const char T_typeset[] E_INIT("=typeset");
|
|||||||
#define Ttypeset (T_typeset + 1) /* "typeset" */
|
#define Ttypeset (T_typeset + 1) /* "typeset" */
|
||||||
EXTERN const char Talias[] E_INIT("alias");
|
EXTERN const char Talias[] E_INIT("alias");
|
||||||
EXTERN const char Tunalias[] E_INIT("unalias");
|
EXTERN const char Tunalias[] E_INIT("unalias");
|
||||||
|
EXTERN const char Tcat[] E_INIT("cat");
|
||||||
EXTERN const char Tsgset[] E_INIT("*=set");
|
EXTERN const char Tsgset[] E_INIT("*=set");
|
||||||
#define Tset (Tsgset + 2) /* "set" */
|
#define Tset (Tsgset + 2) /* "set" */
|
||||||
EXTERN const char Tsgexport[] E_INIT("*=export");
|
EXTERN const char Tsgexport[] E_INIT("*=export");
|
||||||
@ -1665,6 +1666,13 @@ EXTERN char **history; /* saved commands */
|
|||||||
EXTERN char **histptr; /* last history item */
|
EXTERN char **histptr; /* last history item */
|
||||||
EXTERN mksh_ari_t histsize; /* history size */
|
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 */
|
/* user and system time of last j_waitjed job */
|
||||||
EXTERN struct timeval j_usrtime, j_systime;
|
EXTERN struct timeval j_usrtime, j_systime;
|
||||||
|
|
||||||
@ -1791,7 +1799,7 @@ void hist_init(Source *);
|
|||||||
#if HAVE_PERSISTENT_HISTORY
|
#if HAVE_PERSISTENT_HISTORY
|
||||||
void hist_finish(void);
|
void hist_finish(void);
|
||||||
#endif
|
#endif
|
||||||
void histsave(int *, const char *, bool, bool);
|
void histsave(int *, const char *, int, bool);
|
||||||
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
|
||||||
bool histsync(void);
|
bool histsync(void);
|
||||||
#endif
|
#endif
|
||||||
@ -1934,7 +1942,7 @@ int ksh_getopt(const char **, Getopt *, const char *);
|
|||||||
void print_value_quoted(struct shf *, const char *);
|
void print_value_quoted(struct shf *, const char *);
|
||||||
char *quote_value(const char *);
|
char *quote_value(const char *);
|
||||||
void print_columns(struct shf *, unsigned int,
|
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);
|
const void *, size_t, size_t, bool);
|
||||||
void strip_nuls(char *, size_t)
|
void strip_nuls(char *, size_t)
|
||||||
MKSH_A_BOUNDED(__string__, 1, 2);
|
MKSH_A_BOUNDED(__string__, 1, 2);
|
||||||
|
Reference in New Issue
Block a user