Merge remote-tracking branch 'mksh/master'
This commit is contained in:
commit
c19b8b104c
8
Build.sh
8
Build.sh
|
@ -1,8 +1,8 @@
|
|||
#!/bin/sh
|
||||
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.707 2016/11/11 23:31:29 tg Exp $'
|
||||
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.709 2017/03/17 23:47:05 tg Exp $'
|
||||
#-
|
||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011, 2012, 2013, 2014, 2015, 2016
|
||||
# 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
# mirabilos <m@mirbsd.org>
|
||||
#
|
||||
# Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -586,11 +586,10 @@ fi
|
|||
rmf a.exe* a.out* conftest.c conftest.exe* *core core.* ${tfn}* *.bc *.dbg \
|
||||
*.ll *.o *.gen *.cat1 Rebuild.sh lft no signames.inc test.sh x vv.out
|
||||
|
||||
SRCS="lalloc.c eval.c exec.c expr.c funcs.c histrap.c jobs.c"
|
||||
SRCS="lalloc.c edit.c eval.c exec.c expr.c funcs.c histrap.c jobs.c"
|
||||
SRCS="$SRCS lex.c main.c misc.c shf.c syn.c tree.c var.c"
|
||||
|
||||
if test $legacy = 0; then
|
||||
SRCS="$SRCS edit.c"
|
||||
check_categories="$check_categories shell:legacy-no int:32"
|
||||
else
|
||||
check_categories="$check_categories shell:legacy-yes"
|
||||
|
@ -766,7 +765,6 @@ Harvey)
|
|||
add_cppflags -DMKSH__NO_SETEUGID
|
||||
oswarn=' and will currently not work'
|
||||
add_cppflags -DMKSH_UNEMPLOYED
|
||||
add_cppflags -DMKSH_NOPROSPECTOFWORK
|
||||
# these taken from Harvey-OS github and need re-checking
|
||||
add_cppflags -D_setjmp=setjmp -D_longjmp=longjmp
|
||||
: "${HAVE_CAN_NO_EH_FRAME=0}"
|
||||
|
|
406
check.t
406
check.t
|
@ -1,8 +1,8 @@
|
|||
# $MirOS: src/bin/mksh/check.t,v 1.756 2016/11/11 23:31:31 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.765 2017/03/22 00:20:39 tg Exp $
|
||||
# -*- mode: sh -*-
|
||||
#-
|
||||
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011, 2012, 2013, 2014, 2015, 2016
|
||||
# 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
# mirabilos <m@mirbsd.org>
|
||||
#
|
||||
# Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -30,7 +30,7 @@
|
|||
# (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R54 2016/11/11
|
||||
@(#)MIRBSD KSH R54 2017/03/21
|
||||
description:
|
||||
Check version of shell.
|
||||
stdin:
|
||||
|
@ -39,7 +39,7 @@ name: KSH_VERSION
|
|||
category: shell:legacy-no
|
||||
---
|
||||
expected-stdout:
|
||||
@(#)LEGACY KSH R54 2016/11/11
|
||||
@(#)LEGACY KSH R54 2017/03/21
|
||||
description:
|
||||
Check version of legacy shell.
|
||||
stdin:
|
||||
|
@ -92,23 +92,6 @@ category: disabled
|
|||
stdin:
|
||||
set
|
||||
---
|
||||
name: selftest-legacy
|
||||
description:
|
||||
Check some things in the LEGACY KSH
|
||||
category: shell:legacy-yes
|
||||
stdin:
|
||||
set +o emacs
|
||||
set +o vi
|
||||
[[ "$(set +o) -o" = *"-o emacs -o"* ]] && echo 1=emacs
|
||||
[[ "$(set +o) -o" = *"-o vi -o"* ]] && echo 1=vi
|
||||
set -o emacs
|
||||
set -o vi
|
||||
[[ "$(set +o) -o" = *"-o emacs -o"* ]] && echo 2=emacs
|
||||
[[ "$(set +o) -o" = *"-o vi -o"* ]] && echo 2=vi
|
||||
expected-stdout:
|
||||
2=emacs
|
||||
2=vi
|
||||
---
|
||||
name: selftest-direct-builtin-call
|
||||
description:
|
||||
Check that direct builtin calls work
|
||||
|
@ -119,6 +102,26 @@ stdin:
|
|||
expected-stdout:
|
||||
-c echo foo
|
||||
---
|
||||
name: selftest-pathsep-unix
|
||||
description:
|
||||
Check that $PATHSEP is set correctly.
|
||||
category: !os:os2
|
||||
stdin:
|
||||
PATHSEP=.; export PATHSEP
|
||||
"$__progname" -c 'print -r -- $PATHSEP'
|
||||
expected-stdout:
|
||||
:
|
||||
---
|
||||
name: selftest-pathsep-os2
|
||||
description:
|
||||
Check that $PATHSEP is set correctly.
|
||||
category: os:os2
|
||||
stdin:
|
||||
PATHSEP=.; export PATHSEP
|
||||
"$__progname" -c 'print -r -- $PATHSEP'
|
||||
expected-stdout:
|
||||
;
|
||||
---
|
||||
name: alias-1
|
||||
description:
|
||||
Check that recursion is detected/avoided in aliases.
|
||||
|
@ -261,14 +264,21 @@ name: alias-11
|
|||
description:
|
||||
Check that special argument handling still applies with escaped aliases
|
||||
stdin:
|
||||
alias local='\typeset'
|
||||
function foo {
|
||||
local x=$1 y=z
|
||||
alias local1='\typeset'
|
||||
alias local2='\\builtin typeset'
|
||||
function fooa {
|
||||
local1 x=$1 y=z
|
||||
print -r -- "$x,$y"
|
||||
}
|
||||
foo 'bar - baz'
|
||||
function foob {
|
||||
local2 x=$1 y=z
|
||||
print -r -- "$x,$y"
|
||||
}
|
||||
x=1 y=2; fooa 'bar - baz'
|
||||
x=1 y=2; foob 'bar - baz'
|
||||
expected-stdout:
|
||||
bar - baz,z
|
||||
bar - baz,z
|
||||
---
|
||||
name: arith-compound
|
||||
description:
|
||||
|
@ -4711,6 +4721,23 @@ expected-stdout:
|
|||
8 ok
|
||||
<9> <ab> <a b> .
|
||||
---
|
||||
name: IFS-subst-10
|
||||
description:
|
||||
Scalar context in ${var=$subst}
|
||||
stdin:
|
||||
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
|
||||
set -- one "two three" four
|
||||
unset -v var
|
||||
save_IFS=$IFS
|
||||
IFS=
|
||||
set -- ${var=$*}
|
||||
IFS=$save_IFS
|
||||
echo "var=$var"
|
||||
showargs "$@"
|
||||
expected-stdout:
|
||||
var=onetwo threefour
|
||||
<onetwo threefour> .
|
||||
---
|
||||
name: IFS-arith-1
|
||||
description:
|
||||
http://austingroupbugs.net/view.php?id=832
|
||||
|
@ -5205,6 +5232,24 @@ expected-stdout:
|
|||
line <6>
|
||||
expected-exit: 1
|
||||
---
|
||||
name: lineno-eval-alias
|
||||
description:
|
||||
Check if LINENO is trapped in eval and aliases
|
||||
stdin:
|
||||
${ZSH_VERSION+false} || emulate sh; echo $LINENO
|
||||
echo $LINENO
|
||||
eval ' echo $LINENO
|
||||
echo $LINENO
|
||||
echo $LINENO'
|
||||
echo $LINENO
|
||||
expected-stdout:
|
||||
1
|
||||
2
|
||||
3
|
||||
3
|
||||
3
|
||||
6
|
||||
---
|
||||
name: unknown-trap
|
||||
description:
|
||||
Ensure unknown traps are not a syntax error
|
||||
|
@ -6326,7 +6371,7 @@ name: regression-62
|
|||
description:
|
||||
Check if test -nt/-ot succeeds if second(first) file is missing.
|
||||
stdin:
|
||||
touch a
|
||||
:>a
|
||||
test a -nt b && echo nt OK || echo nt BAD
|
||||
test b -ot a && echo ot OK || echo ot BAD
|
||||
expected-stdout:
|
||||
|
@ -7058,6 +7103,11 @@ description:
|
|||
Check tilde expansion works
|
||||
env-setup: !HOME=/sweet!
|
||||
stdin:
|
||||
:>'c=a'
|
||||
typeset c=[ab]
|
||||
:>'d=a'
|
||||
x=typeset; $x d=[ab]
|
||||
echo "<$c>" "<$d>"
|
||||
wd=$PWD
|
||||
cd /
|
||||
plus=$(print -r -- ~+)
|
||||
|
@ -7067,10 +7117,106 @@ stdin:
|
|||
[[ $minus = "$wd" ]]; echo two $? .
|
||||
[[ $nix = /sweet ]]; echo nix $? .
|
||||
expected-stdout:
|
||||
<[ab]> <a>
|
||||
one 0 .
|
||||
two 0 .
|
||||
nix 0 .
|
||||
---
|
||||
name: tilde-expand-3
|
||||
description:
|
||||
Check mostly Austin 351 stuff
|
||||
stdin:
|
||||
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
|
||||
set "1 b=2" "3 d=4"
|
||||
export a=$1 \c=$2
|
||||
showargs 1 "$a" "$b" "$c" "$d"
|
||||
unset a b c d
|
||||
HOME=/tmp
|
||||
export \a=~ b=~
|
||||
command export c=~
|
||||
builtin export d=~
|
||||
\\builtin export e=~
|
||||
showargs 2 "$a" "$b" "$c" "$d" "$e" ksh
|
||||
unset a b c d e
|
||||
set -o posix
|
||||
export \a=~ b=~
|
||||
command export c=~
|
||||
builtin export d=~
|
||||
\\builtin export e=~
|
||||
showargs 3 "$a" "$b" "$c" "$d" "$e" posix
|
||||
unset a b c d e
|
||||
set +o posix
|
||||
export a=$1
|
||||
showargs 4 "$a" "$b" ksh
|
||||
unset a b
|
||||
showargs 5 a=$1 ksh
|
||||
export \a=$1
|
||||
showargs 6 "$a" "$b" ksh
|
||||
unset a b
|
||||
set -o posix
|
||||
export a=$1
|
||||
showargs 7 "$a" "$b" posix
|
||||
unset a b
|
||||
showargs 8 a=$1 posix
|
||||
export \a=$1
|
||||
showargs 9 "$a" "$b" posix
|
||||
unset a b
|
||||
set +o posix
|
||||
command echo 10 ksh a=~
|
||||
command command export a=~
|
||||
showargs 11 "$a"
|
||||
unset a
|
||||
set -o posix
|
||||
command echo 12 posix a=~
|
||||
command command export a=~
|
||||
showargs 13 "$a"
|
||||
unset a
|
||||
# unspecified whether /tmp or ~
|
||||
var=export; command $var a=~
|
||||
showargs 14 "$a"
|
||||
echo 'echo "<$foo>"' >bar
|
||||
"$__progname" bar
|
||||
var=foo
|
||||
export $var=1
|
||||
"$__progname" bar
|
||||
export $var=~
|
||||
"$__progname" bar
|
||||
# unspecified
|
||||
command -- export a=~
|
||||
showargs 18 "$a"
|
||||
set -A bla
|
||||
typeset bla[1]=~:~
|
||||
global gbl=~ g2=$1
|
||||
local lcl=~ l2=$1
|
||||
readonly ro=~ r2=$1
|
||||
showargs 19 "${bla[1]}" a=~ "$gbl" "$lcl" "$ro" "$g2" "$l2" "$r2"
|
||||
set +o posix
|
||||
echo "20 some arbitrary stuff "=~
|
||||
set -o posix
|
||||
echo "21 some arbitrary stuff "=~
|
||||
expected-stdout:
|
||||
<1> <1 b=2> <> <3> <4> .
|
||||
<2> </tmp> </tmp> </tmp> </tmp> </tmp> <ksh> .
|
||||
<3> <~> </tmp> </tmp> <~> </tmp> <posix> .
|
||||
<4> <1 b=2> <> <ksh> .
|
||||
<5> <a=1> <b=2> <ksh> .
|
||||
<6> <1> <2> <ksh> .
|
||||
<7> <1 b=2> <> <posix> .
|
||||
<8> <a=1> <b=2> <posix> .
|
||||
<9> <1> <2> <posix> .
|
||||
10 ksh a=/tmp
|
||||
<11> </tmp> .
|
||||
12 posix a=~
|
||||
<13> </tmp> .
|
||||
<14> <~> .
|
||||
<>
|
||||
<1>
|
||||
<~>
|
||||
<18> <~> .
|
||||
<19> </tmp:/tmp> <a=~> </tmp> </tmp> </tmp> <1 b=2> <1 b=2> <1 b=2> .
|
||||
20 some arbitrary stuff =/tmp
|
||||
21 some arbitrary stuff =~
|
||||
---
|
||||
name: exit-err-1
|
||||
description:
|
||||
Check some "exit on error" conditions
|
||||
|
@ -7903,11 +8049,11 @@ expected-stderr-pattern:
|
|||
---
|
||||
name: typeset-1
|
||||
description:
|
||||
Check that global does what typeset is supposed to do
|
||||
Check that typeset -g works correctly
|
||||
stdin:
|
||||
set -A arrfoo 65
|
||||
foo() {
|
||||
global -Uui16 arrfoo[*]
|
||||
typeset -g -Uui16 arrfoo[*]
|
||||
}
|
||||
echo before ${arrfoo[0]} .
|
||||
foo
|
||||
|
@ -7917,7 +8063,7 @@ stdin:
|
|||
echo inside before ${arrbar[0]} .
|
||||
arrbar[0]=97
|
||||
echo inside changed ${arrbar[0]} .
|
||||
global -Uui16 arrbar[*]
|
||||
typeset -g -Uui16 arrbar[*]
|
||||
echo inside typeset ${arrbar[0]} .
|
||||
arrbar[0]=48
|
||||
echo inside changed ${arrbar[0]} .
|
||||
|
@ -8173,17 +8319,17 @@ stdin:
|
|||
alias
|
||||
typeset -f
|
||||
expected-stdout:
|
||||
autoload='\typeset -fu'
|
||||
functions='\typeset -f'
|
||||
hash='\builtin alias -t'
|
||||
history='\builtin fc -l'
|
||||
integer='\typeset -i'
|
||||
local='\typeset'
|
||||
login='\exec login'
|
||||
nameref='\typeset -n'
|
||||
autoload='\\builtin typeset -fu'
|
||||
functions='\\builtin typeset -f'
|
||||
hash='\\builtin alias -t'
|
||||
history='\\builtin fc -l'
|
||||
integer='\\builtin typeset -i'
|
||||
local='\\builtin typeset'
|
||||
login='\\builtin exec login'
|
||||
nameref='\\builtin typeset -n'
|
||||
nohup='nohup '
|
||||
r='\builtin fc -e -'
|
||||
type='\builtin whence -v'
|
||||
r='\\builtin fc -e -'
|
||||
type='\\builtin whence -v'
|
||||
---
|
||||
name: aliases-2b
|
||||
description:
|
||||
|
@ -8193,17 +8339,17 @@ stdin:
|
|||
alias
|
||||
typeset -f
|
||||
expected-stdout:
|
||||
autoload='\typeset -fu'
|
||||
functions='\typeset -f'
|
||||
hash='\builtin alias -t'
|
||||
history='\builtin fc -l'
|
||||
integer='\typeset -i'
|
||||
local='\typeset'
|
||||
login='\exec login'
|
||||
nameref='\typeset -n'
|
||||
autoload='\\builtin typeset -fu'
|
||||
functions='\\builtin typeset -f'
|
||||
hash='\\builtin alias -t'
|
||||
history='\\builtin fc -l'
|
||||
integer='\\builtin typeset -i'
|
||||
local='\\builtin typeset'
|
||||
login='\\builtin exec login'
|
||||
nameref='\\builtin typeset -n'
|
||||
nohup='nohup '
|
||||
r='\builtin fc -e -'
|
||||
type='\builtin whence -v'
|
||||
r='\\builtin fc -e -'
|
||||
type='\\builtin whence -v'
|
||||
---
|
||||
name: aliases-3b
|
||||
description:
|
||||
|
@ -8213,17 +8359,17 @@ stdin:
|
|||
./sh -c 'alias; typeset -f'
|
||||
rm -f sh
|
||||
expected-stdout:
|
||||
autoload='\typeset -fu'
|
||||
functions='\typeset -f'
|
||||
hash='\builtin alias -t'
|
||||
history='\builtin fc -l'
|
||||
integer='\typeset -i'
|
||||
local='\typeset'
|
||||
login='\exec login'
|
||||
nameref='\typeset -n'
|
||||
autoload='\\builtin typeset -fu'
|
||||
functions='\\builtin typeset -f'
|
||||
hash='\\builtin alias -t'
|
||||
history='\\builtin fc -l'
|
||||
integer='\\builtin typeset -i'
|
||||
local='\\builtin typeset'
|
||||
login='\\builtin exec login'
|
||||
nameref='\\builtin typeset -n'
|
||||
nohup='nohup '
|
||||
r='\builtin fc -e -'
|
||||
type='\builtin whence -v'
|
||||
r='\\builtin fc -e -'
|
||||
type='\\builtin whence -v'
|
||||
---
|
||||
name: aliases-cmdline
|
||||
description:
|
||||
|
@ -8280,8 +8426,8 @@ stdin:
|
|||
:|| local() { :; }
|
||||
alias local
|
||||
expected-stdout:
|
||||
local='\typeset'
|
||||
local='\typeset'
|
||||
local='\\builtin typeset'
|
||||
local='\\builtin typeset'
|
||||
---
|
||||
name: arrays-1
|
||||
description:
|
||||
|
@ -8691,21 +8837,21 @@ expected-stdout:
|
|||
name: arrassign-fnc-global
|
||||
description:
|
||||
Check locality of array access inside a function
|
||||
with the mksh-specific global keyword
|
||||
with the bash4/mksh/yash/zsh typeset -g keyword
|
||||
stdin:
|
||||
function fn {
|
||||
global x
|
||||
typeset -g x
|
||||
x+=(f)
|
||||
echo ".fn:${x[0]}.${x[1]}.${x[2]}.${x[3]}:"
|
||||
}
|
||||
function rfn {
|
||||
set -A y
|
||||
global y
|
||||
typeset -g y
|
||||
y+=(f)
|
||||
echo ".rfn:${y[0]}.${y[1]}.${y[2]}.${y[3]}:"
|
||||
}
|
||||
function fnr {
|
||||
global z
|
||||
typeset -g z
|
||||
set -A z
|
||||
z+=(f)
|
||||
echo ".fnr:${z[0]}.${z[1]}.${z[2]}.${z[3]}:"
|
||||
|
@ -8843,21 +8989,21 @@ expected-stdout:
|
|||
name: strassign-fnc-global
|
||||
description:
|
||||
Check locality of string access inside a function
|
||||
with the mksh-specific global keyword
|
||||
with the bash4/mksh/yash/zsh typeset -g keyword
|
||||
stdin:
|
||||
function fn {
|
||||
global x
|
||||
typeset -g x
|
||||
x+=f
|
||||
echo ".fn:$x:"
|
||||
}
|
||||
function rfn {
|
||||
y=
|
||||
global y
|
||||
typeset -g y
|
||||
y+=f
|
||||
echo ".rfn:$y:"
|
||||
}
|
||||
function fnr {
|
||||
global z
|
||||
typeset -g z
|
||||
z=
|
||||
z+=f
|
||||
echo ".fnr:$z:"
|
||||
|
@ -9221,7 +9367,7 @@ stdin:
|
|||
while (( i < ${#line[*]} )); do
|
||||
hv=${line[i++]}
|
||||
if (( (pos & 15) == 0 )); then
|
||||
(( pos )) && print "$dasc|"
|
||||
(( pos )) && print -r -- "$dasc|"
|
||||
print -n "${pos#16#} "
|
||||
dasc=' |'
|
||||
fi
|
||||
|
@ -9238,7 +9384,7 @@ stdin:
|
|||
print -n ' '
|
||||
(( (pos++ & 15) == 7 )) && print -n -- '- '
|
||||
done
|
||||
(( hv == 2147483647 )) || print "$dasc|"
|
||||
(( hv == 2147483647 )) || print -r -- "$dasc|"
|
||||
}
|
||||
expected-stdout:
|
||||
00000000 3C 64 E4 DB C3 9B E2 82 - AC C3 9B 40 3E 0A 3C 00 |<d.........@>.<.|
|
||||
|
@ -9364,7 +9510,7 @@ stdin:
|
|||
while [[ -n $line ]]; do
|
||||
hv=1#${line::1}
|
||||
if (( (pos & 15) == 0 )); then
|
||||
(( pos )) && print "$dasc|"
|
||||
(( pos )) && print -r -- "$dasc|"
|
||||
print -n "${pos#16#} "
|
||||
dasc=' |'
|
||||
fi
|
||||
|
@ -9382,7 +9528,7 @@ stdin:
|
|||
print -n ' '
|
||||
(( (pos++ & 15) == 7 )) && print -n -- '- '
|
||||
done
|
||||
(( hv == 2147483647 )) || print "$dasc|"
|
||||
(( hv == 2147483647 )) || print -r -- "$dasc|"
|
||||
}
|
||||
expected-stdout:
|
||||
00000000 5C 20 5C 21 5C 22 5C 23 - 5C 24 5C 25 5C 26 5C 27 |\ \!\"\#\$\%\&\'|
|
||||
|
@ -9391,13 +9537,13 @@ expected-stdout:
|
|||
00000030 20 5C 39 5C 3A 5C 3B 5C - 3C 5C 3D 5C 3E 5C 3F 5C | \9\:\;\<\=\>\?\|
|
||||
00000040 40 5C 41 5C 42 5C 43 5C - 44 1B 5C 46 5C 47 5C 48 |@\A\B\C\D.\F\G\H|
|
||||
00000050 5C 49 5C 4A 5C 4B 5C 4C - 5C 4D 5C 4E 5C 4F 5C 50 |\I\J\K\L\M\N\O\P|
|
||||
00000060 5C 51 5C 52 5C 53 5C 54 - 20 5C 56 5C 57 5C 58 5C |\Q\R\S\T \V\W\X\|
|
||||
00000070 59 5C 5A 5C 5B 5C 5C 5D - 5C 5E 5C 5F 5C 60 07 08 |Y\Z\[\]\^\_\`..|
|
||||
00000080 20 20 5C 64 1B 0C 5C 67 - 5C 68 5C 69 5C 6A 5C 6B | \d..\g\h\i\j\k|
|
||||
00000090 5C 6C 5C 6D 0A 5C 6F 5C - 70 20 5C 71 0D 5C 73 09 |\l\m.\o\p \q.\s.|
|
||||
000000A0 0B 5C 77 5C 79 5C 7A 5C - 7B 5C 7C 5C 7D 5C 7E 20 |.\w\y\z\{\|\}\~ |
|
||||
000000B0 E2 82 AC 64 20 EF BF BD - 20 12 33 20 78 20 53 20 |...d ... .3 x S |
|
||||
000000C0 53 34 0A - |S4.|
|
||||
00000060 5C 51 5C 52 5C 53 5C 54 - 20 5C 55 5C 56 5C 57 5C |\Q\R\S\T \U\V\W\|
|
||||
00000070 58 5C 59 5C 5A 5C 5B 5C - 5C 5D 5C 5E 5C 5F 5C 60 |X\Y\Z\[\\]\^\_\`|
|
||||
00000080 07 08 20 20 5C 64 1B 0C - 5C 67 5C 68 5C 69 5C 6A |.. \d..\g\h\i\j|
|
||||
00000090 5C 6B 5C 6C 5C 6D 0A 5C - 6F 5C 70 20 5C 71 0D 5C |\k\l\m.\o\p \q.\|
|
||||
000000A0 73 09 5C 75 0B 5C 77 5C - 78 5C 79 5C 7A 5C 7B 5C |s.\u.\w\x\y\z\{\|
|
||||
000000B0 7C 5C 7D 5C 7E 20 E2 82 - AC 64 20 EF BF BD 20 12 ||\}\~ ...d ... .|
|
||||
000000C0 33 20 78 20 53 20 53 34 - 0A |3 x S S4.|
|
||||
---
|
||||
name: dollar-doublequoted-strings
|
||||
description:
|
||||
|
@ -9439,7 +9585,7 @@ stdin:
|
|||
while [[ -n $line ]]; do
|
||||
hv=1#${line::1}
|
||||
if (( (pos & 15) == 0 )); then
|
||||
(( pos )) && print "$dasc|"
|
||||
(( pos )) && print -r -- "$dasc|"
|
||||
print -n "${pos#16#} "
|
||||
dasc=' |'
|
||||
fi
|
||||
|
@ -9457,7 +9603,7 @@ stdin:
|
|||
print -n ' '
|
||||
(( (pos++ & 15) == 7 )) && print -n -- '- '
|
||||
done
|
||||
(( hv == 2147483647 )) || print "$dasc|"
|
||||
(( hv == 2147483647 )) || print -r -- "$dasc|"
|
||||
}
|
||||
expected-stdout:
|
||||
00000000 20 21 22 23 24 25 26 27 - 28 29 2A 2B 2C 2D 2E 2F | !"#$%&'()*+,-./|
|
||||
|
@ -9767,7 +9913,7 @@ stdin:
|
|||
while [[ -n $line ]]; do
|
||||
hv=1#${line::1}
|
||||
if (( (pos & 15) == 0 )); then
|
||||
(( pos )) && print "$dasc|"
|
||||
(( pos )) && print -r -- "$dasc|"
|
||||
print -n "${pos#16#} "
|
||||
dasc=' |'
|
||||
fi
|
||||
|
@ -9785,7 +9931,7 @@ stdin:
|
|||
print -n ' '
|
||||
(( (pos++ & 15) == 7 )) && print -n -- '- '
|
||||
done
|
||||
(( hv == 2147483647 )) || print "$dasc|"
|
||||
(( hv == 2147483647 )) || print -r -- "$dasc|"
|
||||
}
|
||||
expected-stdout:
|
||||
00000000 48 65 6C 6C 6F 2C 20 57 - 6F 72 6C 64 21 5C 0A E3 |Hello, World!\..|
|
||||
|
@ -9855,7 +10001,7 @@ stdin:
|
|||
dasc=$dasc$dch
|
||||
dch=
|
||||
elif (( (pos & 7) == 0 )); then
|
||||
(( pos )) && print "$dasc|"
|
||||
(( pos )) && print -r -- "$dasc|"
|
||||
print -n "${pos#16#} "
|
||||
dasc=' |'
|
||||
fi
|
||||
|
@ -9870,7 +10016,7 @@ stdin:
|
|||
print -n ' '
|
||||
(( (pos++ & 7) == 3 )) && print -n -- '- '
|
||||
done
|
||||
(( hv == 2147483647 )) || print "$dasc|"
|
||||
(( hv == 2147483647 )) || print -r -- "$dasc|"
|
||||
}
|
||||
expected-stdout:
|
||||
00000000 0048 0065 006C 006C - 006F 002C 0020 0057 |Hello, W|
|
||||
|
@ -9936,7 +10082,7 @@ stdin:
|
|||
while (( i < ${#line[*]} )); do
|
||||
hv=${line[i++]}
|
||||
if (( (pos & 15) == 0 )); then
|
||||
(( pos )) && print "$dasc|"
|
||||
(( pos )) && print -r -- "$dasc|"
|
||||
print -n "${pos#16#} "
|
||||
dasc=' |'
|
||||
fi
|
||||
|
@ -9953,7 +10099,7 @@ stdin:
|
|||
print -n ' '
|
||||
(( (pos++ & 15) == 7 )) && print -n -- '- '
|
||||
done
|
||||
(( hv == 2147483647 )) || print "$dasc|"
|
||||
(( hv == 2147483647 )) || print -r -- "$dasc|"
|
||||
}
|
||||
expected-stdout:
|
||||
00000000 48 65 6C 6C 6F 2C 20 57 - 6F 72 6C 64 21 5C 0A E3 |Hello, World!\..|
|
||||
|
@ -10019,7 +10165,7 @@ stdin:
|
|||
dasc=$dasc$dch
|
||||
dch=
|
||||
elif (( (pos & 7) == 0 )); then
|
||||
(( pos )) && print "$dasc|"
|
||||
(( pos )) && print -r -- "$dasc|"
|
||||
print -n "${pos#16#} "
|
||||
dasc=' |'
|
||||
fi
|
||||
|
@ -10033,7 +10179,7 @@ stdin:
|
|||
print -n ' '
|
||||
(( (pos++ & 7) == 3 )) && print -n -- '- '
|
||||
done
|
||||
(( hv == 2147483647 )) || print "$dasc|"
|
||||
(( hv == 2147483647 )) || print -r -- "$dasc|"
|
||||
}
|
||||
expected-stdout:
|
||||
00000000 0048 0065 006C 006C - 006F 002C 0020 0057 |Hello, W|
|
||||
|
@ -10123,9 +10269,16 @@ expected-stdout:
|
|||
16#61 16#0 16#62 16#20AC 16#63 .
|
||||
---
|
||||
name: ulimit-1
|
||||
description:
|
||||
Check that ulimit as used in dot.mksh works or is stubbed
|
||||
stdin:
|
||||
ulimit -c 0
|
||||
---
|
||||
name: ulimit-2
|
||||
description:
|
||||
Check if we can use a specific syntax idiom for ulimit
|
||||
category: !os:syllable
|
||||
XXX Haiku works, but only for -n and -V
|
||||
category: !os:haiku,!os:syllable
|
||||
stdin:
|
||||
if ! x=$(ulimit -d) || [[ $x = unknown ]]; then
|
||||
#echo expected to fail on this OS
|
||||
|
@ -10170,7 +10323,6 @@ name: bashiop-1
|
|||
description:
|
||||
Check if GNU bash-like I/O redirection works
|
||||
Part 1: this is also supported by GNU bash
|
||||
category: shell:legacy-no
|
||||
stdin:
|
||||
exec 3>&1
|
||||
function threeout {
|
||||
|
@ -10191,7 +10343,6 @@ name: bashiop-2a
|
|||
description:
|
||||
Check if GNU bash-like I/O redirection works
|
||||
Part 2: this is *not* supported by GNU bash
|
||||
category: shell:legacy-no
|
||||
stdin:
|
||||
exec 3>&1
|
||||
function threeout {
|
||||
|
@ -10212,7 +10363,6 @@ name: bashiop-2b
|
|||
description:
|
||||
Check if GNU bash-like I/O redirection works
|
||||
Part 2: this is *not* supported by GNU bash
|
||||
category: shell:legacy-no
|
||||
stdin:
|
||||
exec 3>&1
|
||||
function threeout {
|
||||
|
@ -10233,7 +10383,6 @@ name: bashiop-2c
|
|||
description:
|
||||
Check if GNU bash-like I/O redirection works
|
||||
Part 2: this is supported by GNU bash 4 only
|
||||
category: shell:legacy-no
|
||||
stdin:
|
||||
echo mir >foo
|
||||
set -o noclobber
|
||||
|
@ -10257,7 +10406,6 @@ name: bashiop-3a
|
|||
description:
|
||||
Check if GNU bash-like I/O redirection fails correctly
|
||||
Part 1: this is also supported by GNU bash
|
||||
category: shell:legacy-no
|
||||
stdin:
|
||||
echo mir >foo
|
||||
set -o noclobber
|
||||
|
@ -10279,7 +10427,6 @@ name: bashiop-3b
|
|||
description:
|
||||
Check if GNU bash-like I/O redirection fails correctly
|
||||
Part 2: this is *not* supported by GNU bash
|
||||
category: shell:legacy-no
|
||||
stdin:
|
||||
echo mir >foo
|
||||
set -o noclobber
|
||||
|
@ -10303,7 +10450,6 @@ description:
|
|||
Check if GNU bash-like I/O redirection works
|
||||
Part 4: this is also supported by GNU bash,
|
||||
but failed in some mksh versions
|
||||
category: shell:legacy-no
|
||||
stdin:
|
||||
exec 3>&1
|
||||
function threeout {
|
||||
|
@ -10325,11 +10471,10 @@ expected-stdout:
|
|||
ras
|
||||
dwa
|
||||
---
|
||||
name: bashiop-5-normal
|
||||
name: bashiop-5
|
||||
description:
|
||||
Check if GNU bash-like I/O redirection is only supported
|
||||
in !POSIX !sh mode as it breaks existing scripts' syntax
|
||||
category: shell:legacy-no
|
||||
stdin:
|
||||
:>x; echo 1 "$("$__progname" -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" .
|
||||
:>x; echo 2 "$("$__progname" -o posix -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" .
|
||||
|
@ -10339,20 +10484,6 @@ expected-stdout:
|
|||
2 = bar .
|
||||
3 = bar .
|
||||
---
|
||||
name: bashiop-5-legacy
|
||||
description:
|
||||
Check if GNU bash-like I/O redirection is not parsed
|
||||
in lksh as it breaks existing scripts' syntax
|
||||
category: shell:legacy-yes
|
||||
stdin:
|
||||
:>x; echo 1 "$("$__progname" -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" .
|
||||
:>x; echo 2 "$("$__progname" -o posix -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" .
|
||||
:>x; echo 3 "$("$__progname" -o sh -c 'echo foo>/dev/null&>x echo bar')" = "$(<x)" .
|
||||
expected-stdout:
|
||||
1 = bar .
|
||||
2 = bar .
|
||||
3 = bar .
|
||||
---
|
||||
name: oksh-eval
|
||||
description:
|
||||
Check expansions.
|
||||
|
@ -10589,7 +10720,6 @@ description:
|
|||
AT&T ksh93 does this still, which means we must keep it as well
|
||||
XXX fails on some old Perl installations
|
||||
need-pass: no
|
||||
category: shell:legacy-no
|
||||
stdin:
|
||||
cat >cld <<-EOF
|
||||
#!$__perlname
|
||||
|
@ -10622,22 +10752,6 @@ stdin:
|
|||
expected-stdout:
|
||||
Fowl
|
||||
---
|
||||
name: fd-cloexec-3
|
||||
description:
|
||||
Verify that file descriptors > 2 are not private for LEGACY KSH
|
||||
category: shell:legacy-yes
|
||||
stdin:
|
||||
cat >cld <<-EOF
|
||||
#!$__perlname
|
||||
open(my \$fh, ">&", 9) or die "E: open \$!";
|
||||
syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!";
|
||||
EOF
|
||||
chmod +x cld
|
||||
exec 9>&1
|
||||
./cld
|
||||
expected-stdout:
|
||||
Fowl
|
||||
---
|
||||
name: comsub-1a
|
||||
description:
|
||||
COMSUB are now parsed recursively, so this works
|
||||
|
@ -11015,7 +11129,7 @@ expected-stdout:
|
|||
inline_TWHILE() {
|
||||
i=1
|
||||
while {
|
||||
\let] " i < 10 "
|
||||
\\builtin let " i < 10 "
|
||||
}
|
||||
do
|
||||
echo $i
|
||||
|
@ -11026,13 +11140,13 @@ expected-stdout:
|
|||
i=1; while (( i < 10 )); do echo $i; let ++i; done
|
||||
); }
|
||||
function comsub_TWHILE {
|
||||
x=$(i=1 ; while { \let] " i < 10 " ; } ; do echo $i ; let ++i ; done )
|
||||
x=$(i=1 ; while { \\builtin let " i < 10 " ; } ; do echo $i ; let ++i ; done )
|
||||
}
|
||||
function reread_TWHILE { x=$((
|
||||
i=1; while (( i < 10 )); do echo $i; let ++i; done
|
||||
)|tr u x); }
|
||||
function reread_TWHILE {
|
||||
x=$(( i=1 ; while { \let] " i < 10 " ; } ; do echo $i ; let ++i ; done ) | tr u x )
|
||||
x=$(( i=1 ; while { \\builtin let " i < 10 " ; } ; do echo $i ; let ++i ; done ) | tr u x )
|
||||
}
|
||||
inline_TUNTIL() {
|
||||
i=10; until (( !--i )) ; do echo $i; done
|
||||
|
@ -11040,7 +11154,7 @@ expected-stdout:
|
|||
inline_TUNTIL() {
|
||||
i=10
|
||||
until {
|
||||
\let] " !--i "
|
||||
\\builtin let " !--i "
|
||||
}
|
||||
do
|
||||
echo $i
|
||||
|
@ -11050,13 +11164,13 @@ expected-stdout:
|
|||
i=10; until (( !--i )) ; do echo $i; done
|
||||
); }
|
||||
function comsub_TUNTIL {
|
||||
x=$(i=10 ; until { \let] " !--i " ; } ; do echo $i ; done )
|
||||
x=$(i=10 ; until { \\builtin let " !--i " ; } ; do echo $i ; done )
|
||||
}
|
||||
function reread_TUNTIL { x=$((
|
||||
i=10; until (( !--i )) ; do echo $i; done
|
||||
)|tr u x); }
|
||||
function reread_TUNTIL {
|
||||
x=$(( i=10 ; until { \let] " !--i " ; } ; do echo $i ; done ) | tr u x )
|
||||
x=$(( i=10 ; until { \\builtin let " !--i " ; } ; do echo $i ; done ) | tr u x )
|
||||
}
|
||||
inline_TCOPROC() {
|
||||
cat * |& ls
|
||||
|
@ -11432,7 +11546,7 @@ expected-stdout:
|
|||
case x in
|
||||
(x)
|
||||
a+=b
|
||||
\set -A c+ -- d e
|
||||
\\builtin set -A c+ -- d e
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
@ -11442,7 +11556,7 @@ expected-stdout:
|
|||
esac
|
||||
); }
|
||||
function comsub_wdarrassign {
|
||||
x=$(case x in (x) a+=b ; \set -A c+ -- d e ;; esac )
|
||||
x=$(case x in (x) a+=b ; \\builtin set -A c+ -- d e ;; esac )
|
||||
}
|
||||
function reread_wdarrassign { x=$((
|
||||
case x in
|
||||
|
@ -11450,7 +11564,7 @@ expected-stdout:
|
|||
esac
|
||||
)|tr u x); }
|
||||
function reread_wdarrassign {
|
||||
x=$(( case x in (x) a+=b ; \set -A c+ -- d e ;; esac ) | tr u x )
|
||||
x=$(( case x in (x) a+=b ; \\builtin set -A c+ -- d e ;; esac ) | tr u x )
|
||||
}
|
||||
---
|
||||
name: comsub-torture-io
|
||||
|
@ -11671,7 +11785,7 @@ expected-stdout:
|
|||
inline_TWHILE() {
|
||||
i=1
|
||||
while {
|
||||
\let] " i < 10 "
|
||||
\\builtin let " i < 10 "
|
||||
} >&3
|
||||
do
|
||||
echo $i
|
||||
|
@ -11682,13 +11796,13 @@ expected-stdout:
|
|||
i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
|
||||
); }
|
||||
function comsub_TWHILE {
|
||||
x=$(i=1 ; while { \let] " i < 10 " ; } >&3 ; do echo $i ; let ++i ; done >&3 )
|
||||
x=$(i=1 ; while { \\builtin let " i < 10 " ; } >&3 ; do echo $i ; let ++i ; done >&3 )
|
||||
}
|
||||
function reread_TWHILE { x=$((
|
||||
i=1; while (( i < 10 )) >&3; do echo $i; let ++i; done >&3
|
||||
)|tr u x); }
|
||||
function reread_TWHILE {
|
||||
x=$(( i=1 ; while { \let] " i < 10 " ; } >&3 ; do echo $i ; let ++i ; done >&3 ) | tr u x )
|
||||
x=$(( i=1 ; while { \\builtin let " i < 10 " ; } >&3 ; do echo $i ; let ++i ; done >&3 ) | tr u x )
|
||||
}
|
||||
inline_TUNTIL() {
|
||||
i=10; until (( !--i )) >&3 ; do echo $i; done >&3
|
||||
|
@ -11696,7 +11810,7 @@ expected-stdout:
|
|||
inline_TUNTIL() {
|
||||
i=10
|
||||
until {
|
||||
\let] " !--i "
|
||||
\\builtin let " !--i "
|
||||
} >&3
|
||||
do
|
||||
echo $i
|
||||
|
@ -11706,13 +11820,13 @@ expected-stdout:
|
|||
i=10; until (( !--i )) >&3 ; do echo $i; done >&3
|
||||
); }
|
||||
function comsub_TUNTIL {
|
||||
x=$(i=10 ; until { \let] " !--i " ; } >&3 ; do echo $i ; done >&3 )
|
||||
x=$(i=10 ; until { \\builtin let " !--i " ; } >&3 ; do echo $i ; done >&3 )
|
||||
}
|
||||
function reread_TUNTIL { x=$((
|
||||
i=10; until (( !--i )) >&3 ; do echo $i; done >&3
|
||||
)|tr u x); }
|
||||
function reread_TUNTIL {
|
||||
x=$(( i=10 ; until { \let] " !--i " ; } >&3 ; do echo $i ; done >&3 ) | tr u x )
|
||||
x=$(( i=10 ; until { \\builtin let " !--i " ; } >&3 ; do echo $i ; done >&3 ) | tr u x )
|
||||
}
|
||||
inline_TCOPROC() {
|
||||
cat * >&3 |& >&3 ls
|
||||
|
|
443
dot.mkshrc
443
dot.mkshrc
|
@ -1,8 +1,8 @@
|
|||
# $Id$
|
||||
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.108 2016/07/26 22:03:41 tg Exp $
|
||||
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.114 2017/03/19 22:31:26 tg Exp $
|
||||
#-
|
||||
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011, 2012, 2013, 2014, 2015, 2016
|
||||
# 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
# mirabilos <m@mirbsd.org>
|
||||
#
|
||||
# Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -22,65 +22,100 @@
|
|||
#-
|
||||
# ${ENV:-~/.mkshrc}: mksh initialisation file for interactive shells
|
||||
|
||||
# catch non-mksh (including lksh) trying to run this file
|
||||
# catch non-mksh, non-lksh, trying to run this file
|
||||
case ${KSH_VERSION:-} in
|
||||
*MIRBSD\ KSH*) ;;
|
||||
*) return 0 ;;
|
||||
*LEGACY\ KSH*|*MIRBSD\ KSH*) ;;
|
||||
*) \return 0 ;;
|
||||
esac
|
||||
|
||||
PS1='#'; (( USER_ID )) && PS1='$'; \: "${TERM:=vt100}${HOSTNAME:=$(\ulimit -c \
|
||||
0; hostname 2>/dev/null)}${EDITOR:=/bin/ed}${USER:=$(\ulimit -c 0; id -un \
|
||||
2>/dev/null || \echo \?)}${MKSH:=$(\builtin whence -p mksh)}"
|
||||
HOSTNAME=${HOSTNAME%%*([ ]).*}; HOSTNAME=${HOSTNAME##*([ ])}
|
||||
[[ $HOSTNAME = ?(ip6-)localhost?(6) ]] && HOSTNAME=
|
||||
\: "${HOSTNAME:=nil}${MKSH:=/bin/mksh}"; \export EDITOR HOSTNAME MKSH TERM USER
|
||||
PS4='[$EPOCHREALTIME] '; PS1=$'\001\r''${|
|
||||
\typeset e=$?
|
||||
# give MidnightBSD's laffer1 a bit of csh feeling
|
||||
function setenv {
|
||||
if (( $# )); then
|
||||
\\builtin eval '\\builtin export "$1"="${2:-}"'
|
||||
else
|
||||
\\builtin typeset -x
|
||||
fi
|
||||
}
|
||||
|
||||
# pager (not control character safe)
|
||||
smores() (
|
||||
\\builtin set +m
|
||||
\\builtin cat "$@" |&
|
||||
\\builtin trap "rv=\$?; \\\\builtin kill $! >/dev/null 2>&1; \\\\builtin exit \$rv" EXIT
|
||||
while IFS= \\builtin read -pr line; do
|
||||
llen=${%line}
|
||||
(( llen == -1 )) && llen=${#line}
|
||||
(( llen = llen ? (llen + COLUMNS - 1) / COLUMNS : 1 ))
|
||||
if (( (curlin += llen) >= LINES )); then
|
||||
\\builtin print -nr -- $'\e[7m--more--\e[0m'
|
||||
\\builtin read -u1 || \\builtin exit $?
|
||||
[[ $REPLY = [Qq]* ]] && \\builtin exit 0
|
||||
curlin=$llen
|
||||
fi
|
||||
\\builtin print -r -- "$line"
|
||||
done
|
||||
)
|
||||
|
||||
\\builtin alias ls=ls l='ls -F' la='l -a' ll='l -l' lo='l -alo'
|
||||
\: "${HOSTNAME:=$(\\builtin ulimit -c 0; \\builtin print -r -- $(hostname \
|
||||
2>/dev/null))}${EDITOR:=/bin/ed}${TERM:=vt100}${USER:=$(\\builtin ulimit \
|
||||
-c 0; id -un 2>/dev/null)}${USER:=?}"
|
||||
[[ $HOSTNAME = ?(?(ip6-)localhost?(6)) ]] && HOSTNAME=nil; \\builtin unalias ls
|
||||
\\builtin export EDITOR HOSTNAME TERM USER
|
||||
|
||||
# minimal support for lksh users
|
||||
if [[ $KSH_VERSION = *LEGACY\ KSH* ]]; then
|
||||
PS1='$USER@${HOSTNAME%%.*}:$PWD>'
|
||||
\\builtin return 0
|
||||
fi
|
||||
|
||||
# mksh-specific from here
|
||||
\: "${MKSH:=$(\\builtin whence -p mksh)}${MKSH:=/bin/mksh}"
|
||||
\\builtin export MKSH
|
||||
|
||||
PS4='[$EPOCHREALTIME] '; PS1='#'; (( USER_ID )) && PS1='$'; PS1=$'\001\r''${|
|
||||
\\builtin typeset e=$?
|
||||
|
||||
(( e )) && REPLY+="$e|"
|
||||
REPLY+=${USER}@${HOSTNAME%%.*}:
|
||||
|
||||
\typeset d=${PWD:-?}/ p=~; [[ $p = ?(*/) ]] || d=${d/#$p\//\~/}
|
||||
d=${d%/}; \typeset m=${%d} n p=...; (( m > 0 )) || m=${#d}
|
||||
\\builtin typeset d=${PWD:-?}/ p=~; [[ $p = ?(*/) ]] || d=${d/#$p\//\~/}
|
||||
d=${d%/}; \\builtin typeset m=${%d} n p=...; (( m > 0 )) || m=${#d}
|
||||
(( m > (n = (COLUMNS/3 < 7 ? 7 : COLUMNS/3)) )) && d=${d:(-n)} || p=
|
||||
REPLY+=$p$d
|
||||
|
||||
\return $e
|
||||
\\builtin return $e
|
||||
} '"$PS1 "
|
||||
\alias ls=ls
|
||||
\unalias ls
|
||||
\alias l='ls -F'
|
||||
\alias la='l -a'
|
||||
\alias ll='l -l'
|
||||
\alias lo='l -alo'
|
||||
\alias doch='sudo mksh -c "$(\builtin fc -ln -1)"'
|
||||
\command -v rot13 >/dev/null || \alias rot13='tr \
|
||||
\\builtin alias doch='sudo mksh -c "$(\\builtin fc -ln -1)"'
|
||||
\\builtin command -v rot13 >/dev/null || \\builtin alias rot13='tr \
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \
|
||||
nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
|
||||
if \command -v hd >/dev/null; then \:; elif \command -v hexdump >/dev/null; then
|
||||
if \\builtin command -v hd >/dev/null; then
|
||||
\:
|
||||
elif \\builtin command -v hexdump >/dev/null; then
|
||||
function hd {
|
||||
hexdump -e '"%08.8_ax " 8/1 "%02X " " - " 8/1 "%02X "' \
|
||||
-e '" |" "%_p"' -e '"|\n"' "$@"
|
||||
}
|
||||
else
|
||||
function hd {
|
||||
\typeset -Uui16 -Z11 pos=0
|
||||
\typeset -Uui16 -Z5 hv=2147483647
|
||||
\typeset dasc line i
|
||||
\set +U
|
||||
\\builtin typeset -Uui16 -Z11 pos=0
|
||||
\\builtin typeset -Uui16 -Z5 hv=2147483647
|
||||
\\builtin typeset dasc line i
|
||||
\\builtin set +U
|
||||
|
||||
\cat "$@" | if \read -arN -1 line; then
|
||||
\typeset -i1 'line[*]'
|
||||
\\builtin cat "$@" | if \\builtin read -arN -1 line; then
|
||||
\\builtin typeset -i1 'line[*]'
|
||||
i=0
|
||||
while (( i < ${#line[*]} )); do
|
||||
hv=${line[i++]}
|
||||
if (( (pos & 15) == 0 )); then
|
||||
(( pos )) && \
|
||||
\builtin print -r -- "$dasc|"
|
||||
\builtin print -n "${pos#16#} "
|
||||
\\builtin print -r -- "$dasc|"
|
||||
\\builtin print -nr "${pos#16#} "
|
||||
dasc=' |'
|
||||
fi
|
||||
\builtin print -n "${hv#16#} "
|
||||
\\builtin print -nr "${hv#16#} "
|
||||
#XXX EBCDIC, but we need [[:print:]] to fix this
|
||||
if (( (hv < 32) || (hv > 126) )); then
|
||||
dasc+=.
|
||||
|
@ -88,69 +123,69 @@ else
|
|||
dasc+=${line[i-1]#1#}
|
||||
fi
|
||||
(( (pos++ & 15) == 7 )) && \
|
||||
\builtin print -n -- '- '
|
||||
\\builtin print -nr -- '- '
|
||||
done
|
||||
while (( pos & 15 )); do
|
||||
\builtin print -n ' '
|
||||
\\builtin print -nr ' '
|
||||
(( (pos++ & 15) == 7 )) && \
|
||||
\builtin print -n -- '- '
|
||||
\\builtin print -nr -- '- '
|
||||
done
|
||||
(( hv == 2147483647 )) || \builtin print -r -- "$dasc|"
|
||||
(( hv == 2147483647 )) || \\builtin print -r -- "$dasc|"
|
||||
fi
|
||||
}
|
||||
fi
|
||||
|
||||
# Berkeley C shell compatible dirs, popd, and pushd functions
|
||||
# Z shell compatible chpwd() hook, used to update DIRSTACK[0]
|
||||
DIRSTACKBASE=$(\builtin realpath ~/. 2>/dev/null || \
|
||||
\builtin print -nr -- "${HOME:-/}")
|
||||
set -A DIRSTACK
|
||||
DIRSTACKBASE=$(\\builtin realpath ~/. 2>/dev/null || \
|
||||
\\builtin print -nr -- "${HOME:-/}")
|
||||
\\builtin set -A DIRSTACK
|
||||
function chpwd {
|
||||
DIRSTACK[0]=$(\builtin realpath . 2>/dev/null || \
|
||||
\builtin print -r -- "$PWD")
|
||||
DIRSTACK[0]=$(\\builtin realpath . 2>/dev/null || \
|
||||
\\builtin print -nr -- "$PWD")
|
||||
[[ $DIRSTACKBASE = ?(*/) ]] || \
|
||||
DIRSTACK[0]=${DIRSTACK[0]/#$DIRSTACKBASE/\~}
|
||||
\:
|
||||
}
|
||||
\chpwd .
|
||||
cd() {
|
||||
\builtin cd "$@" || \return $?
|
||||
\\builtin cd "$@" || \\builtin return $?
|
||||
\chpwd "$@"
|
||||
}
|
||||
function cd_csh {
|
||||
\typeset d t=${1/#\~/$DIRSTACKBASE}
|
||||
\\builtin typeset d t=${1/#\~/$DIRSTACKBASE}
|
||||
|
||||
if ! d=$(\builtin cd "$t" 2>&1); then
|
||||
\builtin print -u2 "${1}: ${d##*cd: $t: }."
|
||||
\return 1
|
||||
if ! d=$(\\builtin cd "$t" 2>&1); then
|
||||
\\builtin print -ru2 "${1}: ${d##*cd: $t: }."
|
||||
\\builtin return 1
|
||||
fi
|
||||
\cd "$t"
|
||||
}
|
||||
function dirs {
|
||||
\typeset d dwidth
|
||||
\typeset -i fl=0 fv=0 fn=0 cpos=0
|
||||
\\builtin typeset d dwidth
|
||||
\\builtin typeset -i fl=0 fv=0 fn=0 cpos=0
|
||||
|
||||
while \getopts ":lvn" d; do
|
||||
while \\builtin getopts ":lvn" d; do
|
||||
case $d {
|
||||
(l) fl=1 ;;
|
||||
(v) fv=1 ;;
|
||||
(n) fn=1 ;;
|
||||
(*) \builtin print -u2 'Usage: dirs [-lvn].'
|
||||
\return 1 ;;
|
||||
(*) \\builtin print -ru2 'Usage: dirs [-lvn].'
|
||||
\\builtin return 1 ;;
|
||||
}
|
||||
done
|
||||
\shift $((OPTIND - 1))
|
||||
\\builtin shift $((OPTIND - 1))
|
||||
if (( $# > 0 )); then
|
||||
\builtin print -u2 'Usage: dirs [-lvn].'
|
||||
\return 1
|
||||
\\builtin print -ru2 'Usage: dirs [-lvn].'
|
||||
\\builtin return 1
|
||||
fi
|
||||
if (( fv )); then
|
||||
fv=0
|
||||
while (( fv < ${#DIRSTACK[*]} )); do
|
||||
d=${DIRSTACK[fv]}
|
||||
(( fl )) && d=${d/#\~/$DIRSTACKBASE}
|
||||
\builtin print -r -- "$fv $d"
|
||||
\builtin let fv++
|
||||
\\builtin print -r -- "$fv $d"
|
||||
(( ++fv ))
|
||||
done
|
||||
else
|
||||
fv=0
|
||||
|
@ -160,136 +195,117 @@ function dirs {
|
|||
(( dwidth = (${%d} > 0 ? ${%d} : ${#d}) ))
|
||||
if (( fn && (cpos += dwidth + 1) >= 79 && \
|
||||
dwidth < 80 )); then
|
||||
\builtin print
|
||||
\\builtin print
|
||||
(( cpos = dwidth + 1 ))
|
||||
fi
|
||||
\builtin print -nr -- "$d "
|
||||
\builtin let fv++
|
||||
\\builtin print -nr -- "$d "
|
||||
(( ++fv ))
|
||||
done
|
||||
\builtin print
|
||||
\\builtin print
|
||||
fi
|
||||
\return 0
|
||||
\\builtin return 0
|
||||
}
|
||||
function popd {
|
||||
\typeset d fa
|
||||
\typeset -i n=1
|
||||
\\builtin typeset d fa
|
||||
\\builtin typeset -i n=1
|
||||
|
||||
while \getopts ":0123456789lvn" d; do
|
||||
while \\builtin getopts ":0123456789lvn" d; do
|
||||
case $d {
|
||||
(l|v|n) fa+=" -$d" ;;
|
||||
(+*) n=2
|
||||
\break ;;
|
||||
(*) \builtin print -u2 'Usage: popd [-lvn] [+<n>].'
|
||||
\return 1 ;;
|
||||
\\builtin break ;;
|
||||
(*) \\builtin print -ru2 'Usage: popd [-lvn] [+<n>].'
|
||||
\\builtin return 1 ;;
|
||||
}
|
||||
done
|
||||
\shift $((OPTIND - n))
|
||||
\\builtin shift $((OPTIND - n))
|
||||
n=0
|
||||
if (( $# > 1 )); then
|
||||
\builtin print -u2 popd: Too many arguments.
|
||||
\return 1
|
||||
\\builtin print -ru2 popd: Too many arguments.
|
||||
\\builtin return 1
|
||||
elif [[ $1 = ++([0-9]) && $1 != +0 ]]; then
|
||||
if (( (n = ${1#+}) >= ${#DIRSTACK[*]} )); then
|
||||
\builtin print -u2 popd: Directory stack not that deep.
|
||||
\return 1
|
||||
\\builtin print -ru2 popd: Directory stack not that deep.
|
||||
\\builtin return 1
|
||||
fi
|
||||
elif [[ -n $1 ]]; then
|
||||
\builtin print -u2 popd: Bad directory.
|
||||
\return 1
|
||||
\\builtin print -ru2 popd: Bad directory.
|
||||
\\builtin return 1
|
||||
fi
|
||||
if (( ${#DIRSTACK[*]} < 2 )); then
|
||||
\builtin print -u2 popd: Directory stack empty.
|
||||
\return 1
|
||||
\\builtin print -ru2 popd: Directory stack empty.
|
||||
\\builtin return 1
|
||||
fi
|
||||
\unset DIRSTACK[n]
|
||||
\set -A DIRSTACK -- "${DIRSTACK[@]}"
|
||||
\cd_csh "${DIRSTACK[0]}" || \return 1
|
||||
\\builtin unset DIRSTACK[n]
|
||||
\\builtin set -A DIRSTACK -- "${DIRSTACK[@]}"
|
||||
\cd_csh "${DIRSTACK[0]}" || \\builtin return 1
|
||||
\dirs $fa
|
||||
}
|
||||
function pushd {
|
||||
\typeset d fa
|
||||
\typeset -i n=1
|
||||
\\builtin typeset d fa
|
||||
\\builtin typeset -i n=1
|
||||
|
||||
while \getopts ":0123456789lvn" d; do
|
||||
while \\builtin getopts ":0123456789lvn" d; do
|
||||
case $d {
|
||||
(l|v|n) fa+=" -$d" ;;
|
||||
(+*) n=2
|
||||
\break ;;
|
||||
(*) \builtin print -u2 'Usage: pushd [-lvn] [<dir>|+<n>].'
|
||||
\return 1 ;;
|
||||
\\builtin break ;;
|
||||
(*) \\builtin print -ru2 'Usage: pushd [-lvn] [<dir>|+<n>].'
|
||||
\\builtin return 1 ;;
|
||||
}
|
||||
done
|
||||
\shift $((OPTIND - n))
|
||||
\\builtin shift $((OPTIND - n))
|
||||
if (( $# == 0 )); then
|
||||
if (( ${#DIRSTACK[*]} < 2 )); then
|
||||
\builtin print -u2 pushd: No other directory.
|
||||
\return 1
|
||||
\\builtin print -ru2 pushd: No other directory.
|
||||
\\builtin return 1
|
||||
fi
|
||||
d=${DIRSTACK[1]}
|
||||
DIRSTACK[1]=${DIRSTACK[0]}
|
||||
\cd_csh "$d" || \return 1
|
||||
\cd_csh "$d" || \\builtin return 1
|
||||
elif (( $# > 1 )); then
|
||||
\builtin print -u2 pushd: Too many arguments.
|
||||
\return 1
|
||||
\\builtin print -ru2 pushd: Too many arguments.
|
||||
\\builtin return 1
|
||||
elif [[ $1 = ++([0-9]) && $1 != +0 ]]; then
|
||||
if (( (n = ${1#+}) >= ${#DIRSTACK[*]} )); then
|
||||
\builtin print -u2 pushd: Directory stack not that deep.
|
||||
\return 1
|
||||
\\builtin print -ru2 pushd: Directory stack not that deep.
|
||||
\\builtin return 1
|
||||
fi
|
||||
while (( n-- )); do
|
||||
d=${DIRSTACK[0]}
|
||||
\unset DIRSTACK[0]
|
||||
\set -A DIRSTACK -- "${DIRSTACK[@]}" "$d"
|
||||
\\builtin unset DIRSTACK[0]
|
||||
\\builtin set -A DIRSTACK -- "${DIRSTACK[@]}" "$d"
|
||||
done
|
||||
\cd_csh "${DIRSTACK[0]}" || \return 1
|
||||
\cd_csh "${DIRSTACK[0]}" || \\builtin return 1
|
||||
else
|
||||
\set -A DIRSTACK -- placeholder "${DIRSTACK[@]}"
|
||||
\cd_csh "$1" || \return 1
|
||||
\\builtin set -A DIRSTACK -- placeholder "${DIRSTACK[@]}"
|
||||
\cd_csh "$1" || \\builtin return 1
|
||||
fi
|
||||
\dirs $fa
|
||||
}
|
||||
|
||||
# pager (not control character safe)
|
||||
smores() (
|
||||
\set +m
|
||||
\cat "$@" |&
|
||||
\trap "rv=\$?; 'kill' $! >/dev/null 2>&1; 'exit' \$rv" EXIT
|
||||
while IFS= \read -pr line; do
|
||||
llen=${%line}
|
||||
(( llen == -1 )) && llen=${#line}
|
||||
(( llen = llen ? (llen + COLUMNS - 1) / COLUMNS : 1 ))
|
||||
if (( (curlin += llen) >= LINES )); then
|
||||
\builtin print -n -- '\e[7m--more--\e[0m'
|
||||
\read -u1 || \exit $?
|
||||
[[ $REPLY = [Qq]* ]] && \exit 0
|
||||
curlin=$llen
|
||||
fi
|
||||
\builtin print -r -- "$line"
|
||||
done
|
||||
)
|
||||
|
||||
# base64 encoder and decoder, RFC compliant, NUL safe, not EBCDIC safe
|
||||
function Lb64decode {
|
||||
\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
|
||||
\\builtin set +U
|
||||
\\builtin typeset c s="$*" t
|
||||
[[ -n $s ]] || { s=$(\\builtin cat; \\builtin print x); s=${s%x}; }
|
||||
\\builtin typeset -i i=0 j=0 n=${#s} p=0 v x
|
||||
\\builtin typeset -i16 o
|
||||
|
||||
while (( i < n )); do
|
||||
c=${s:(i++):1}
|
||||
case $c {
|
||||
(=) \break ;;
|
||||
(=) \\builtin break ;;
|
||||
([A-Z]) (( v = 1#$c - 65 )) ;;
|
||||
([a-z]) (( v = 1#$c - 71 )) ;;
|
||||
([0-9]) (( v = 1#$c + 4 )) ;;
|
||||
(+) v=62 ;;
|
||||
(/) v=63 ;;
|
||||
(*) \continue ;;
|
||||
(*) \\builtin continue ;;
|
||||
}
|
||||
(( x = (x << 6) | v ))
|
||||
case $((p++)) {
|
||||
(0) \continue ;;
|
||||
(0) \\builtin continue ;;
|
||||
(1) (( o = (x >> 4) & 255 )) ;;
|
||||
(2) (( o = (x >> 2) & 255 )) ;;
|
||||
(3) (( o = x & 255 ))
|
||||
|
@ -297,63 +313,60 @@ function Lb64decode {
|
|||
;;
|
||||
}
|
||||
t+=\\x${o#16#}
|
||||
(( ++j & 4095 )) && \continue
|
||||
\builtin print -n $t
|
||||
(( ++j & 4095 )) && \\builtin continue
|
||||
\\builtin print -n $t
|
||||
t=
|
||||
done
|
||||
\builtin print -n $t
|
||||
\\builtin print -n $t
|
||||
}
|
||||
|
||||
\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 {
|
||||
\set +U
|
||||
\typeset c s t
|
||||
\\builtin set +U
|
||||
\\builtin typeset c s t table
|
||||
\\builtin set -A table -- 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 + /
|
||||
if (( $# )); then
|
||||
\read -raN-1 s <<<"$*"
|
||||
\unset s[${#s[*]}-1]
|
||||
\\builtin read -raN-1 s <<<"$*"
|
||||
\\builtin unset s[${#s[*]}-1]
|
||||
else
|
||||
\read -raN-1 s
|
||||
\\builtin read -raN-1 s
|
||||
fi
|
||||
\typeset -i i=0 n=${#s[*]} j v
|
||||
\\builtin typeset -i i=0 n=${#s[*]} v
|
||||
|
||||
while (( i < n )); do
|
||||
(( v = s[i++] << 16 ))
|
||||
(( j = i < n ? s[i++] : 0 ))
|
||||
(( v |= j << 8 ))
|
||||
(( j = i < n ? s[i++] : 0 ))
|
||||
(( v |= j ))
|
||||
t+=${Lb64encode_tbl[v >> 18]}${Lb64encode_tbl[v >> 12 & 63]}
|
||||
c=${Lb64encode_tbl[v >> 6 & 63]}
|
||||
(( v |= s[i++] << 8 ))
|
||||
(( v |= s[i++] ))
|
||||
t+=${table[v >> 18]}${table[v >> 12 & 63]}
|
||||
c=${table[v >> 6 & 63]}
|
||||
if (( i <= n )); then
|
||||
t+=$c${Lb64encode_tbl[v & 63]}
|
||||
t+=$c${table[v & 63]}
|
||||
elif (( i == n + 1 )); then
|
||||
t+=$c=
|
||||
else
|
||||
t+===
|
||||
fi
|
||||
if (( ${#t} == 76 || i >= n )); then
|
||||
\builtin print $t
|
||||
\\builtin print -r $t
|
||||
t=
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Better Avalanche for the Jenkins Hash
|
||||
\typeset -Z11 -Uui16 Lbafh_v
|
||||
\\builtin typeset -Z11 -Uui16 Lbafh_v
|
||||
function Lbafh_init {
|
||||
Lbafh_v=0
|
||||
}
|
||||
function Lbafh_add {
|
||||
\set +U
|
||||
\typeset s
|
||||
\\builtin set +U
|
||||
\\builtin typeset s
|
||||
if (( $# )); then
|
||||
\read -raN-1 s <<<"$*"
|
||||
\unset s[${#s[*]}-1]
|
||||
\\builtin read -raN-1 s <<<"$*"
|
||||
\\builtin unset s[${#s[*]}-1]
|
||||
else
|
||||
\read -raN-1 s
|
||||
\\builtin read -raN-1 s
|
||||
fi
|
||||
\typeset -i i=0 n=${#s[*]}
|
||||
\\builtin typeset -i i=0 n=${#s[*]}
|
||||
|
||||
while (( i < n )); do
|
||||
((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 ))
|
||||
|
@ -361,7 +374,7 @@ function Lbafh_add {
|
|||
done
|
||||
}
|
||||
function Lbafh_finish {
|
||||
\typeset -Ui t
|
||||
\\builtin typeset -Ui t
|
||||
|
||||
((# t = (((Lbafh_v >> 7) & 0x01010101) * 0x1B) ^ \
|
||||
((Lbafh_v << 1) & 0xFEFEFEFE) ))
|
||||
|
@ -373,42 +386,33 @@ 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 {
|
||||
\set -o noglob
|
||||
\cat "$@" | while \read _line; do
|
||||
\\builtin set -o noglob
|
||||
\\builtin cat "$@" | while \\builtin read _line; do
|
||||
_line=${_line%%#*}
|
||||
[[ -n $_line ]] && \builtin print -r -- $_line
|
||||
[[ -n $_line ]] && \\builtin print -r -- $_line
|
||||
done
|
||||
}
|
||||
|
||||
# give MidnightBSD's laffer1 a bit of csh feeling
|
||||
function setenv {
|
||||
if (( $# )); then
|
||||
\eval '\export "$1"="${2:-}"'
|
||||
else
|
||||
\typeset -x
|
||||
fi
|
||||
}
|
||||
|
||||
# toggle built-in aliases and utilities, and aliases and functions from mkshrc
|
||||
function enable {
|
||||
\typeset doprnt=0 mode=1 x y z rv=0
|
||||
\typeset b_alias i_alias i_func nalias=0 nfunc=0 i_all
|
||||
\set -A b_alias
|
||||
\set -A i_alias
|
||||
\set -A i_func
|
||||
\\builtin typeset doprnt=0 mode=1 x y z rv=0
|
||||
\\builtin typeset b_alias i_alias i_func nalias=0 nfunc=0 i_all
|
||||
\\builtin set -A b_alias
|
||||
\\builtin set -A i_alias
|
||||
\\builtin set -A i_func
|
||||
|
||||
# accumulate mksh built-in aliases, in ASCIIbetical order
|
||||
i_alias[nalias]=autoload; b_alias[nalias++]='\typeset -fu'
|
||||
i_alias[nalias]=functions; b_alias[nalias++]='\typeset -f'
|
||||
i_alias[nalias]=hash; b_alias[nalias++]='\builtin alias -t'
|
||||
i_alias[nalias]=history; b_alias[nalias++]='\builtin fc -l'
|
||||
i_alias[nalias]=integer; b_alias[nalias++]='\typeset -i'
|
||||
i_alias[nalias]=local; b_alias[nalias++]='\typeset'
|
||||
i_alias[nalias]=login; b_alias[nalias++]='\exec login'
|
||||
i_alias[nalias]=nameref; b_alias[nalias++]='\typeset -n'
|
||||
i_alias[nalias]=autoload; b_alias[nalias++]='\\builtin typeset -fu'
|
||||
i_alias[nalias]=functions; b_alias[nalias++]='\\builtin typeset -f'
|
||||
i_alias[nalias]=hash; b_alias[nalias++]='\\builtin alias -t'
|
||||
i_alias[nalias]=history; b_alias[nalias++]='\\builtin fc -l'
|
||||
i_alias[nalias]=integer; b_alias[nalias++]='\\builtin typeset -i'
|
||||
i_alias[nalias]=local; b_alias[nalias++]='\\builtin typeset'
|
||||
i_alias[nalias]=login; b_alias[nalias++]='\\builtin exec login'
|
||||
i_alias[nalias]=nameref; b_alias[nalias++]='\\builtin typeset -n'
|
||||
i_alias[nalias]=nohup; b_alias[nalias++]='nohup '
|
||||
i_alias[nalias]=r; b_alias[nalias++]='\builtin fc -e -'
|
||||
i_alias[nalias]=type; b_alias[nalias++]='\builtin whence -v'
|
||||
i_alias[nalias]=r; b_alias[nalias++]='\\builtin fc -e -'
|
||||
i_alias[nalias]=type; b_alias[nalias++]='\\builtin whence -v'
|
||||
|
||||
# accumulate mksh built-in utilities, in definition order, even ifndef
|
||||
i_func[nfunc++]=.
|
||||
|
@ -416,6 +420,7 @@ function enable {
|
|||
i_func[nfunc++]='['
|
||||
i_func[nfunc++]=alias
|
||||
i_func[nfunc++]=break
|
||||
# \\builtin cannot, by design, be overridden
|
||||
i_func[nfunc++]=builtin
|
||||
i_func[nfunc++]=cat
|
||||
i_func[nfunc++]=cd
|
||||
|
@ -434,7 +439,6 @@ function enable {
|
|||
i_func[nfunc++]=jobs
|
||||
i_func[nfunc++]=kill
|
||||
i_func[nfunc++]=let
|
||||
i_func[nfunc++]='let]'
|
||||
i_func[nfunc++]=print
|
||||
i_func[nfunc++]=pwd
|
||||
i_func[nfunc++]=read
|
||||
|
@ -471,11 +475,13 @@ function enable {
|
|||
i_alias[nalias]=la; b_alias[nalias++]='l -a'
|
||||
i_alias[nalias]=ll; b_alias[nalias++]='l -l'
|
||||
i_alias[nalias]=lo; b_alias[nalias++]='l -alo'
|
||||
i_alias[nalias]=doch; b_alias[nalias++]='sudo mksh -c "$(\builtin fc -ln -1)"'
|
||||
i_alias[nalias]=doch; b_alias[nalias++]='sudo mksh -c "$(\\builtin fc -ln -1)"'
|
||||
i_alias[nalias]=rot13; b_alias[nalias++]='tr abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
|
||||
i_alias[nalias]=cls; b_alias[nalias++]='\builtin print -n \\ec'
|
||||
i_alias[nalias]=cls; b_alias[nalias++]='\\builtin print -n \\ec'
|
||||
|
||||
# accumulate functions from dot.mkshrc, in definition order
|
||||
i_func[nfunc++]=setenv
|
||||
i_func[nfunc++]=smores
|
||||
i_func[nfunc++]=hd
|
||||
i_func[nfunc++]=chpwd
|
||||
i_func[nfunc++]=cd
|
||||
|
@ -483,21 +489,19 @@ function enable {
|
|||
i_func[nfunc++]=dirs
|
||||
i_func[nfunc++]=popd
|
||||
i_func[nfunc++]=pushd
|
||||
i_func[nfunc++]=smores
|
||||
i_func[nfunc++]=Lb64decode
|
||||
i_func[nfunc++]=Lb64encode
|
||||
i_func[nfunc++]=Lbafh_init
|
||||
i_func[nfunc++]=Lbafh_add
|
||||
i_func[nfunc++]=Lbafh_finish
|
||||
i_func[nfunc++]=Lstripcom
|
||||
i_func[nfunc++]=setenv
|
||||
i_func[nfunc++]=enable
|
||||
|
||||
# collect all identifiers, sorted ASCIIbetically
|
||||
\set -sA i_all -- "${i_alias[@]}" "${i_func[@]}"
|
||||
\\builtin set -sA i_all -- "${i_alias[@]}" "${i_func[@]}"
|
||||
|
||||
# handle options, we don't do dynamic loading
|
||||
while \getopts "adf:nps" x; do
|
||||
while \\builtin getopts "adf:nps" x; do
|
||||
case $x {
|
||||
(a)
|
||||
mode=-1
|
||||
|
@ -506,8 +510,8 @@ function enable {
|
|||
# deliberately causing an error, like bash-static
|
||||
;|
|
||||
(f)
|
||||
\builtin print -u2 enable: dynamic loading not available
|
||||
\return 2
|
||||
\\builtin print -ru2 enable: dynamic loading not available
|
||||
\\builtin return 2
|
||||
;;
|
||||
(n)
|
||||
mode=0
|
||||
|
@ -516,88 +520,89 @@ function enable {
|
|||
doprnt=1
|
||||
;;
|
||||
(s)
|
||||
\set -sA i_all -- . : break continue eval exec exit \
|
||||
export readonly return set shift times trap unset
|
||||
\\builtin set -sA i_all -- . : break continue eval \
|
||||
exec exit export readonly return set shift times \
|
||||
trap unset
|
||||
;;
|
||||
(*)
|
||||
\builtin print -u2 enable: usage: \
|
||||
\\builtin print -ru2 enable: usage: \
|
||||
"enable [-adnps] [-f filename] [name ...]"
|
||||
return 2
|
||||
;;
|
||||
}
|
||||
done
|
||||
\shift $((OPTIND - 1))
|
||||
\\builtin shift $((OPTIND - 1))
|
||||
|
||||
# display builtins enabled/disabled/all/special?
|
||||
if (( doprnt || ($# == 0) )); then
|
||||
for x in "${i_all[@]}"; do
|
||||
y=$(\alias "$x") || y=
|
||||
[[ $y = "$x='\\builtin whence -p $x >/dev/null || (\\builtin print mksh: $x: not found; exit 127) && \$(\\builtin whence -p $x)'" ]]; z=$?
|
||||
y=$(\\builtin alias "$x") || y=
|
||||
[[ $y = "$x='\\\\builtin whence -p $x >/dev/null || (\\\\builtin print -r mksh: $x: not found; \\\\builtin exit 127) && \$(\\\\builtin whence -p $x)'" ]]; z=$?
|
||||
case $mode:$z {
|
||||
(-1:0|0:0)
|
||||
\print -r -- "enable -n $x"
|
||||
\\builtin print -r -- "enable -n $x"
|
||||
;;
|
||||
(-1:1|1:1)
|
||||
\print -r -- "enable $x"
|
||||
\\builtin print -r -- "enable $x"
|
||||
;;
|
||||
}
|
||||
done
|
||||
\return 0
|
||||
\\builtin return 0
|
||||
fi
|
||||
|
||||
for x in "$@"; do
|
||||
z=0
|
||||
for y in "${i_alias[@]}" "${i_func[@]}"; do
|
||||
[[ $x = "$y" ]] || \continue
|
||||
[[ $x = "$y" ]] || \\builtin continue
|
||||
z=1
|
||||
\break
|
||||
\\builtin break
|
||||
done
|
||||
if (( !z )); then
|
||||
\builtin print -ru2 enable: "$x": not a shell builtin
|
||||
\\builtin print -ru2 enable: "$x": not a shell builtin
|
||||
rv=1
|
||||
\continue
|
||||
\\builtin continue
|
||||
fi
|
||||
if (( !mode )); then
|
||||
# disable this
|
||||
\alias "$x=\\builtin whence -p $x >/dev/null || (\\builtin print mksh: $x: not found; exit 127) && \$(\\builtin whence -p $x)"
|
||||
\\builtin alias "$x=\\\\builtin whence -p $x >/dev/null || (\\\\builtin print -r mksh: $x: not found; \\\\builtin exit 127) && \$(\\\\builtin whence -p $x)"
|
||||
else
|
||||
# find out if this is an alias or not, first
|
||||
z=0
|
||||
y=-1
|
||||
while (( ++y < nalias )); do
|
||||
[[ $x = "${i_alias[y]}" ]] || \continue
|
||||
[[ $x = "${i_alias[y]}" ]] || \\builtin continue
|
||||
z=1
|
||||
\break
|
||||
\\builtin break
|
||||
done
|
||||
if (( z )); then
|
||||
# re-enable the original alias body
|
||||
\alias "$x=${b_alias[y]}"
|
||||
\\builtin alias "$x=${b_alias[y]}"
|
||||
else
|
||||
# re-enable the original utility/function
|
||||
\unalias "$x"
|
||||
\\builtin unalias "$x"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
\return $rv
|
||||
\\builtin return $rv
|
||||
}
|
||||
|
||||
\: place customisations below this line
|
||||
|
||||
for p in ~/.etc/bin ~/bin; do
|
||||
[[ -d $p/. ]] || \continue
|
||||
#XXX OS/2
|
||||
[[ :$PATH: = *:$p:* ]] || PATH=$p:$PATH
|
||||
[[ -d $p/. ]] || \\builtin continue
|
||||
[[ $PATHSEP$PATH$PATHSEP = *"$PATHSEP$p$PATHSEP"* ]] || \
|
||||
PATH=$p$PATHSEP$PATH
|
||||
done
|
||||
|
||||
\export SHELL=$MKSH MANWIDTH=80 LESSHISTFILE=-
|
||||
\alias cls='\builtin print -n \\ec'
|
||||
\\builtin export SHELL=$MKSH MANWIDTH=80 LESSHISTFILE=-
|
||||
\\builtin alias cls='\\builtin print -n \\ec'
|
||||
|
||||
#\unset LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_IDENTIFICATION LC_MONETARY \
|
||||
#\\builtin unset LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_IDENTIFICATION LC_MONETARY \
|
||||
# LC_NAME LC_NUMERIC LC_TELEPHONE LC_TIME
|
||||
#p=en_GB.UTF-8
|
||||
#\export LANG=C LC_CTYPE=$p LC_MEASUREMENT=$p LC_MESSAGES=$p LC_PAPER=$p
|
||||
#\set -U
|
||||
#\\builtin export LANG=C LC_CTYPE=$p LC_MEASUREMENT=$p LC_MESSAGES=$p LC_PAPER=$p
|
||||
#\\builtin set -U
|
||||
|
||||
\unset p
|
||||
\\builtin unset p
|
||||
|
||||
\: place customisations above this line
|
||||
|
|
8
edit.c
8
edit.c
|
@ -5,7 +5,7 @@
|
|||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -28,7 +28,7 @@
|
|||
|
||||
#ifndef MKSH_NO_CMDLINE_EDITING
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.312 2016/11/11 23:48:28 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.313 2017/03/11 22:49:54 tg Exp $");
|
||||
|
||||
/*
|
||||
* in later versions we might use libtermcap for this, but since external
|
||||
|
@ -343,7 +343,7 @@ x_glob_hlp_tilde_and_rem_qchar(char *s, bool magic_flag)
|
|||
* and if so, discern "~foo/bar" and "~/baz" from "~blah";
|
||||
* if we have a directory part (the former), try to expand
|
||||
*/
|
||||
if (*s == '~' && (cp = mksh_sdirsep(s)) != NULL) {
|
||||
if (*s == '~' && (cp = /* not sdirsep */ strchr(s, '/')) != NULL) {
|
||||
/* ok, so split into "~foo"/"bar" or "~"/"baz" */
|
||||
*cp++ = 0;
|
||||
/* try to expand the tilde */
|
||||
|
@ -662,7 +662,7 @@ x_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp,
|
|||
}
|
||||
}
|
||||
|
||||
if (*toglob == '~' && !mksh_vdirsep(toglob)) {
|
||||
if (*toglob == '~' && /* not vdirsep */ !vstrchr(toglob, '/')) {
|
||||
/* neither for '~foo' (but '~foo/bar') */
|
||||
*flagsp |= XCF_IS_NOSPACE;
|
||||
goto dont_add_glob;
|
||||
|
|
35
eval.c
35
eval.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.194 2016/11/11 23:31:34 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.198 2017/03/11 22:49:55 tg Exp $");
|
||||
|
||||
/*
|
||||
* string expansion
|
||||
|
@ -625,13 +625,12 @@ expand(
|
|||
break;
|
||||
case '=':
|
||||
/*
|
||||
* Enabling tilde expansion
|
||||
* after :s here is
|
||||
* non-standard ksh, but is
|
||||
* consistent with rules for
|
||||
* other assignments. Not
|
||||
* sure what POSIX thinks of
|
||||
* this.
|
||||
* Tilde expansion for string
|
||||
* variables in POSIX mode is
|
||||
* governed by Austinbug 351.
|
||||
* In non-POSIX mode historic
|
||||
* ksh behaviour (enable it!)
|
||||
* us followed.
|
||||
* Not doing tilde expansion
|
||||
* for integer variables is a
|
||||
* non-POSIX thing - makes
|
||||
|
@ -640,7 +639,7 @@ expand(
|
|||
*/
|
||||
if (!(x.var->flag & INTEGER))
|
||||
f |= DOASNTILDE | DOTILDE;
|
||||
f |= DOTEMP;
|
||||
f |= DOTEMP | DOSCALAR;
|
||||
/*
|
||||
* These will be done after the
|
||||
* value has been assigned.
|
||||
|
@ -1224,12 +1223,16 @@ varsub(Expand *xp, const char *sp, const char *word,
|
|||
}
|
||||
} else if (c == '@') {
|
||||
/* @x where x is command char */
|
||||
slen += 2;
|
||||
stype |= 0x100;
|
||||
if (word[slen] == CHAR) {
|
||||
stype |= word[slen + 1];
|
||||
slen += 2;
|
||||
switch (c = word[slen + 2] == CHAR ? word[slen + 3] : 0) {
|
||||
case '#':
|
||||
case '/':
|
||||
case 'Q':
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
stype |= 0x100 | c;
|
||||
slen += 4;
|
||||
} else if (stype)
|
||||
/* : is not ok */
|
||||
return (-1);
|
||||
|
@ -1730,7 +1733,7 @@ maybe_expand_tilde(const char *p, XString *dsp, char **dpp, bool isassign)
|
|||
|
||||
Xinit(ts, tp, 16, ATEMP);
|
||||
/* : only for DOASNTILDE form */
|
||||
while (p[0] == CHAR && !mksh_cdirsep(p[1]) &&
|
||||
while (p[0] == CHAR && /* not cdirsep */ p[1] != '/' &&
|
||||
(!isassign || p[1] != ':')) {
|
||||
Xcheck(ts, tp);
|
||||
*tp++ = p[1];
|
||||
|
|
34
exec.c
34
exec.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.187 2016/11/12 03:54:48 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.191 2017/03/22 00:20:51 tg Exp $");
|
||||
|
||||
#ifndef MKSH_DEFAULT_EXECSHELL
|
||||
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
|
||||
|
@ -1005,13 +1005,17 @@ scriptexec(struct op *tp, const char **ap)
|
|||
errorf(Tf_sD_sD_s, tp->str, sh, cstrerror(errno));
|
||||
}
|
||||
|
||||
/* actual 'builtin' built-in utility call is handled in comexec() */
|
||||
int
|
||||
shcomexec(const char **wp)
|
||||
c_builtin(const char **wp)
|
||||
{
|
||||
struct tbl *tp;
|
||||
return (call_builtin(get_builtin(*wp), wp, Tbuiltin, false));
|
||||
}
|
||||
|
||||
tp = ktsearch(&builtins, *wp, hash(*wp));
|
||||
return (call_builtin(tp, wp, "shcomexec", false));
|
||||
struct tbl *
|
||||
get_builtin(const char *s)
|
||||
{
|
||||
return (s && *s ? ktsearch(&builtins, s, hash(s)) : NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1117,6 +1121,14 @@ builtin(const char *name, int (*func) (const char **))
|
|||
/* external utility overrides built-in utility, with flags */
|
||||
flag |= LOW_BI;
|
||||
break;
|
||||
case '-':
|
||||
/* is declaration utility if argv[1] is one (POSIX: command) */
|
||||
flag |= DECL_FWDR;
|
||||
break;
|
||||
case '^':
|
||||
/* is declaration utility (POSIX: export, readonly) */
|
||||
flag |= DECL_UTIL;
|
||||
break;
|
||||
default:
|
||||
goto flags_seen;
|
||||
}
|
||||
|
@ -1150,7 +1162,11 @@ findcom(const char *name, int flags)
|
|||
char *fpath;
|
||||
union mksh_cchack npath;
|
||||
|
||||
if (mksh_vdirsep(name)) {
|
||||
if (mksh_vdirsep(name)
|
||||
#ifdef __OS2__
|
||||
&& (strcmp(name, T_builtin) != 0)
|
||||
#endif
|
||||
) {
|
||||
insert = 0;
|
||||
/* prevent FPATH search below */
|
||||
flags &= ~FC_FUNC;
|
||||
|
@ -1361,9 +1377,7 @@ call_builtin(struct tbl *tp, const char **wp, const char *where, bool resetspec)
|
|||
if (!tp)
|
||||
internal_errorf(Tf_sD_s, where, wp[0]);
|
||||
builtin_argv0 = wp[0];
|
||||
builtin_spec = tobool(!resetspec &&
|
||||
/*XXX odd use of KEEPASN */
|
||||
((tp->flag & SPEC_BI) || (Flag(FPOSIX) && (tp->flag & KEEPASN))));
|
||||
builtin_spec = tobool(!resetspec && (tp->flag & SPEC_BI));
|
||||
shf_reopen(1, SHF_WR, shl_stdout);
|
||||
shl_stdout_ok = true;
|
||||
ksh_getopt_reset(&builtin_opt, GF_ERROR);
|
||||
|
|
94
funcs.c
94
funcs.c
|
@ -5,7 +5,7 @@
|
|||
|
||||
/*-
|
||||
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
* 2010, 2011, 2012, 2013, 2014, 2015, 2016
|
||||
* 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -38,7 +38,7 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.319 2016/11/11 23:48:29 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.331 2017/03/22 00:20:41 tg Exp $");
|
||||
|
||||
#if HAVE_KILLPG
|
||||
/*
|
||||
|
@ -92,6 +92,7 @@ c_false(const char **wp MKSH_A_UNUSED)
|
|||
/*
|
||||
* A leading = means assignments before command are kept.
|
||||
* A leading * means a POSIX special builtin.
|
||||
* A leading ^ means declaration utility, - forwarder.
|
||||
*/
|
||||
const struct builtin mkshbuiltins[] = {
|
||||
{Tsgdot, c_dot},
|
||||
|
@ -100,30 +101,31 @@ const struct builtin mkshbuiltins[] = {
|
|||
/* no =: AT&T manual wrong */
|
||||
{Talias, c_alias},
|
||||
{"*=break", c_brkcont},
|
||||
{Tgbuiltin, c_builtin},
|
||||
{T__builtin, c_builtin},
|
||||
{Tbuiltin, c_builtin},
|
||||
{Tbcat, c_cat},
|
||||
{Tcd, c_cd},
|
||||
/* dash compatibility hack */
|
||||
{"chdir", c_cd},
|
||||
{Tcommand, c_command},
|
||||
{T_command, c_command},
|
||||
{"*=continue", c_brkcont},
|
||||
{"echo", c_print},
|
||||
{"*=eval", c_eval},
|
||||
{"*=exec", c_exec},
|
||||
{"*=exit", c_exitreturn},
|
||||
{Tsgexport, c_typeset},
|
||||
{Tdsgexport, c_typeset},
|
||||
{Tfalse, c_false},
|
||||
{"fc", c_fc},
|
||||
{Tgetopts, c_getopts},
|
||||
{"=global", c_typeset},
|
||||
/* deprecated, replaced by typeset -g */
|
||||
{"^=global", c_typeset},
|
||||
{Tjobs, c_jobs},
|
||||
{"kill", c_kill},
|
||||
{"let", c_let},
|
||||
{"let]", c_let},
|
||||
{"print", c_print},
|
||||
{"pwd", c_pwd},
|
||||
{Tread, c_read},
|
||||
{Tsgreadonly, c_typeset},
|
||||
{Tdsgreadonly, c_typeset},
|
||||
{"!realpath", c_realpath},
|
||||
{"~rename", c_rename},
|
||||
{"*=return", c_exitreturn},
|
||||
|
@ -137,12 +139,12 @@ const struct builtin mkshbuiltins[] = {
|
|||
{"*=times", c_times},
|
||||
{"*=trap", c_trap},
|
||||
{Ttrue, c_true},
|
||||
{Tgtypeset, c_typeset},
|
||||
{Tdgtypeset, c_typeset},
|
||||
{"ulimit", c_ulimit},
|
||||
{"umask", c_umask},
|
||||
{Tunalias, c_unalias},
|
||||
{"*=unset", c_unset},
|
||||
{"=wait", c_wait},
|
||||
{"wait", c_wait},
|
||||
{"whence", c_whence},
|
||||
#ifndef MKSH_UNEMPLOYED
|
||||
{Tbg, c_fgbg},
|
||||
|
@ -307,8 +309,6 @@ c_print(const char **wp)
|
|||
bool hist;
|
||||
/* print words as wide characters? */
|
||||
bool chars;
|
||||
/* print a "--" argument? */
|
||||
bool pminusminus;
|
||||
/* writing to a coprocess (SIGPIPE blocked)? */
|
||||
bool coproc;
|
||||
bool copipe;
|
||||
|
@ -319,47 +319,39 @@ c_print(const char **wp)
|
|||
po.ws = ' ';
|
||||
po.ls = '\n';
|
||||
po.nl = true;
|
||||
po.exp = true;
|
||||
|
||||
if (wp[0][0] == 'e') {
|
||||
/* "echo" builtin */
|
||||
++wp;
|
||||
#ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
|
||||
if (Flag(FSH)) {
|
||||
/*
|
||||
* MidnightBSD /bin/sh needs a BSD echo, that is,
|
||||
* one that supports -e but does not enable it by
|
||||
* default
|
||||
*/
|
||||
po.exp = false;
|
||||
}
|
||||
#endif
|
||||
if (Flag(FPOSIX) ||
|
||||
#ifndef MKSH_MIDNIGHTBSD01ASH_COMPAT
|
||||
Flag(FSH) ||
|
||||
#endif
|
||||
Flag(FAS_BUILTIN)) {
|
||||
/* Debian Policy 10.4 compliant "echo" builtin */
|
||||
/* BSD "echo" cmd, Debian Policy 10.4 compliant */
|
||||
++wp;
|
||||
bsd_echo:
|
||||
if (*wp && !strcmp(*wp, "-n")) {
|
||||
/* recognise "-n" only as the first arg */
|
||||
po.nl = false;
|
||||
++wp;
|
||||
}
|
||||
/* print everything as-is */
|
||||
po.exp = false;
|
||||
} else {
|
||||
bool new_exp = po.exp, new_nl = po.nl;
|
||||
bool new_exp, new_nl = true;
|
||||
|
||||
/**
|
||||
* a compromise between sysV and BSD echo commands:
|
||||
* escape sequences are enabled by default, and -n,
|
||||
* -e and -E are recognised if they appear in argu-
|
||||
* ments with no illegal options (ie, echo -nq will
|
||||
* print -nq).
|
||||
* Different from sysV echo since options are reco-
|
||||
* gnised, different from BSD echo since escape se-
|
||||
* quences are enabled by default.
|
||||
/*-
|
||||
* compromise between various historic echos: only
|
||||
* recognise -Een if they appear in arguments with
|
||||
* no illegal options; e.g. echo -nq outputs '-nq'
|
||||
*/
|
||||
#ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
|
||||
/* MidnightBSD /bin/sh needs -e supported but off */
|
||||
if (Flag(FSH))
|
||||
new_exp = false;
|
||||
else
|
||||
#endif
|
||||
/* otherwise compromise on -e enabled by default */
|
||||
new_exp = true;
|
||||
goto print_tradparse_beg;
|
||||
|
||||
print_tradparse_arg:
|
||||
if ((s = *wp) && *s++ == '-' && *s) {
|
||||
|
@ -375,6 +367,7 @@ c_print(const char **wp)
|
|||
new_nl = false;
|
||||
goto print_tradparse_ch;
|
||||
case '\0':
|
||||
print_tradparse_beg:
|
||||
po.exp = new_exp;
|
||||
po.nl = new_nl;
|
||||
++wp;
|
||||
|
@ -384,10 +377,10 @@ c_print(const char **wp)
|
|||
}
|
||||
} else {
|
||||
/* "print" builtin */
|
||||
const char *opts = "AclNnpRrsu,";
|
||||
const char *opts = "AcelNnpRrsu,";
|
||||
const char *emsg;
|
||||
|
||||
po.pminusminus = false;
|
||||
po.exp = true;
|
||||
|
||||
while ((c = ksh_getopt(wp, &builtin_opt, opts)) != -1)
|
||||
switch (c) {
|
||||
|
@ -417,11 +410,9 @@ c_print(const char **wp)
|
|||
}
|
||||
break;
|
||||
case 'R':
|
||||
/* fake BSD echo command */
|
||||
po.pminusminus = true;
|
||||
po.exp = false;
|
||||
opts = "en";
|
||||
break;
|
||||
/* fake BSD echo but don't reset other flags */
|
||||
wp += builtin_opt.optind;
|
||||
goto bsd_echo;
|
||||
case 'r':
|
||||
po.exp = false;
|
||||
break;
|
||||
|
@ -445,8 +436,7 @@ c_print(const char **wp)
|
|||
if (wp[builtin_opt.optind] &&
|
||||
ksh_isdash(wp[builtin_opt.optind]))
|
||||
builtin_opt.optind++;
|
||||
} else if (po.pminusminus)
|
||||
builtin_opt.optind--;
|
||||
}
|
||||
wp += builtin_opt.optind;
|
||||
}
|
||||
|
||||
|
@ -751,7 +741,7 @@ do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
|
|||
return (rv);
|
||||
}
|
||||
|
||||
/* typeset, global, export, and readonly */
|
||||
/* typeset, global(deprecated), export, and readonly */
|
||||
static void c_typeset_vardump(struct tbl *, uint32_t, int, bool, bool);
|
||||
static void c_typeset_vardump_recursive(struct block *, uint32_t, int, bool,
|
||||
bool);
|
||||
|
@ -793,7 +783,7 @@ c_typeset(const char **wp)
|
|||
}
|
||||
|
||||
/* see comment below regarding possible opions */
|
||||
opts = istset ? "L#R#UZ#afi#lnprtux" : "p";
|
||||
opts = istset ? "L#R#UZ#afgi#lnprtux" : "p";
|
||||
|
||||
builtin_opt.flags |= GF_PLUSOPT;
|
||||
/*
|
||||
|
@ -838,6 +828,9 @@ c_typeset(const char **wp)
|
|||
case 'f':
|
||||
func = true;
|
||||
break;
|
||||
case 'g':
|
||||
localv = (builtin_opt.info & GI_PLUS) ? true : false;
|
||||
break;
|
||||
case 'i':
|
||||
flag = INTEGER;
|
||||
basestr = builtin_opt.optarg;
|
||||
|
@ -2392,6 +2385,7 @@ c_eval(const char **wp)
|
|||
return (1);
|
||||
s = pushs(SWORDS, ATEMP);
|
||||
s->u.strv = wp + builtin_opt.optind;
|
||||
s->line = current_lineno;
|
||||
|
||||
/*-
|
||||
* The following code handles the case where the command is
|
||||
|
@ -2833,7 +2827,6 @@ c_exec(const char **wp MKSH_A_UNUSED)
|
|||
for (i = 0; i < NUFILE; i++) {
|
||||
if (e->savefd[i] > 0)
|
||||
close(e->savefd[i]);
|
||||
#ifndef MKSH_LEGACY_MODE
|
||||
/*
|
||||
* keep all file descriptors > 2 private for ksh,
|
||||
* but not for POSIX or legacy/kludge sh
|
||||
|
@ -2841,7 +2834,6 @@ c_exec(const char **wp MKSH_A_UNUSED)
|
|||
if (!Flag(FPOSIX) && !Flag(FSH) && i > 2 &&
|
||||
e->savefd[i])
|
||||
fcntl(i, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
}
|
||||
e->savefd = NULL;
|
||||
}
|
||||
|
@ -3682,7 +3674,7 @@ c_ulimit(const char **wp)
|
|||
if (!all)
|
||||
print_ulimit(rlimits[i], how);
|
||||
else for (i = 0; i < NELEM(rlimits); ++i) {
|
||||
shprintf("%-20s ", rlimits[i]->name);
|
||||
shprintf("-%c: %-20s ", rlimits[i]->optchar, rlimits[i]->name);
|
||||
print_ulimit(rlimits[i], how);
|
||||
}
|
||||
return (0);
|
||||
|
|
21
lex.c
21
lex.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.228 2016/08/01 21:38:03 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.231 2017/03/22 00:20:43 tg Exp $");
|
||||
|
||||
/*
|
||||
* states while lexing word
|
||||
|
@ -893,9 +893,7 @@ yylex(int cf)
|
|||
|
||||
dp = Xstring(ws, wp);
|
||||
if (state == SBASE && (
|
||||
#ifndef MKSH_LEGACY_MODE
|
||||
(c == '&' && !Flag(FSH) && !Flag(FPOSIX)) ||
|
||||
#endif
|
||||
c == '<' || c == '>') && ((c2 = Xlength(ws, wp)) == 0 ||
|
||||
(c2 == 2 && dp[0] == CHAR && ksh_isdigit(dp[1])))) {
|
||||
struct ioword *iop = alloc(sizeof(struct ioword), ATEMP);
|
||||
|
@ -1016,15 +1014,12 @@ yylex(int cf)
|
|||
while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
|
||||
*dp++ = *sp++;
|
||||
if (c != EOS)
|
||||
/* word is not unquoted */
|
||||
/* word is not unquoted, or space ran out */
|
||||
dp = ident;
|
||||
/* make sure the ident array stays NUL padded */
|
||||
memset(dp, 0, (ident + IDENT) - dp + 1);
|
||||
|
||||
if (!(cf & (KEYWORD | ALIAS)))
|
||||
return (LWORD);
|
||||
|
||||
if (*ident != '\0') {
|
||||
if (*ident != '\0' && (cf & (KEYWORD | ALIAS))) {
|
||||
struct tbl *p;
|
||||
uint32_t h = hash(ident);
|
||||
|
||||
|
@ -1068,6 +1063,7 @@ yylex(int cf)
|
|||
s->start = s->str = p->val.s;
|
||||
s->u.tblp = p;
|
||||
s->flags |= SF_HASALIAS;
|
||||
s->line = source->line;
|
||||
s->next = source;
|
||||
if (source->type == SEOF) {
|
||||
/* prevent infinite recursion at EOS */
|
||||
|
@ -1079,9 +1075,12 @@ yylex(int cf)
|
|||
goto Again;
|
||||
}
|
||||
}
|
||||
} else if (cf & ALIAS) {
|
||||
} else if (*ident == '\0') {
|
||||
/* retain typeset et al. even when quoted */
|
||||
if (assign_command((dp = wdstrip(yylval.cp, 0)), true))
|
||||
struct tbl *tt = get_builtin((dp = wdstrip(yylval.cp, 0)));
|
||||
uint32_t flag = tt ? tt->flag : 0;
|
||||
|
||||
if (flag & (DECL_UTIL | DECL_FWDR))
|
||||
strlcpy(ident, dp, sizeof(ident));
|
||||
afree(dp, ATEMP);
|
||||
}
|
||||
|
|
86
lksh.1
86
lksh.1
|
@ -1,6 +1,6 @@
|
|||
.\" $MirOS: src/bin/mksh/lksh.1,v 1.20 2016/11/11 23:31:35 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/lksh.1,v 1.22 2017/02/27 16:04:37 tg Exp $
|
||||
.\"-
|
||||
.\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016
|
||||
.\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016, 2017
|
||||
.\" mirabilos <m@mirbsd.org>
|
||||
.\"
|
||||
.\" Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -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: November 11 2016 $
|
||||
.Dd $Mdocdate: February 27 2017 $
|
||||
.\"
|
||||
.\" Check which macro package we use, and do other -mdoc setup.
|
||||
.\"
|
||||
|
@ -173,37 +173,34 @@ It is built on
|
|||
refer to its manual page for details on the scripting language.
|
||||
It is recommended to port scripts to
|
||||
.Nm mksh
|
||||
instead of relying on legacy or idiotic POSIX-mandated behaviour,
|
||||
instead of relying on legacy or objectionable POSIX-mandated behaviour,
|
||||
since the MirBSD Korn Shell scripting language is much more consistent.
|
||||
.Pp
|
||||
Do not use
|
||||
.Nm
|
||||
as an interactive or login shell; use
|
||||
.Nm mksh
|
||||
instead.
|
||||
.Pp
|
||||
Note that it's strongly recommended to invoke
|
||||
.Nm
|
||||
with at least the
|
||||
with
|
||||
.Fl o Ic posix
|
||||
option, if not both that
|
||||
.Em and Fl o Ic sh ,
|
||||
to fully enjoy better compatibility to the
|
||||
.Tn POSIX
|
||||
standard (which is probably why you use
|
||||
.Nm
|
||||
over
|
||||
.Nm mksh
|
||||
in the first place) or legacy scripts, respectively.
|
||||
in the first place);
|
||||
.Fl o Ic sh
|
||||
(possibly additionally to the above) may be needed for some legacy scripts.
|
||||
.Sh LEGACY MODE
|
||||
.Nm
|
||||
currently has the following differences from
|
||||
.Nm mksh :
|
||||
.Bl -bullet
|
||||
.It
|
||||
.\"XXX TODO: remove (some systems may wish to have lksh as ksh)
|
||||
There is no explicit support for interactive use,
|
||||
nor any command line editing or history code.
|
||||
Hence,
|
||||
.Nm
|
||||
is not suitable as a user's login shell, either; use
|
||||
.Nm mksh
|
||||
instead.
|
||||
.It
|
||||
The
|
||||
.Ev KSH_VERSION
|
||||
string identifies
|
||||
|
@ -241,25 +238,11 @@ Division of the largest negative number by \-1 is Undefined Behaviour.
|
|||
The compiler is permitted to delete all data and crash the system
|
||||
if Undefined Behaviour occurs (see above for an example).
|
||||
.It
|
||||
.\"XXX TODO: move this to FPOSIX
|
||||
The rotation arithmetic operators are not available.
|
||||
.It
|
||||
The shift arithmetic operators take all bits of the second operand into
|
||||
account; if they exceed permitted precision, the result is unspecified.
|
||||
.It
|
||||
.\"XXX TODO: move this to FPOSIX
|
||||
The
|
||||
.Tn GNU
|
||||
.Nm bash
|
||||
extension &\*(Gt to redirect stdout and stderr in one go is not parsed.
|
||||
.It
|
||||
.\"XXX TODO: drop along with allowing interactivity
|
||||
The
|
||||
.Nm mksh
|
||||
command line option
|
||||
.Fl T
|
||||
is not available.
|
||||
.It
|
||||
Unless
|
||||
.Ic set -o posix
|
||||
is active,
|
||||
|
@ -275,24 +258,13 @@ passes through the errorlevel from the
|
|||
.Xr getopt 1
|
||||
command.
|
||||
.It
|
||||
.\"XXX TODO: move to FPOSIX/FSH
|
||||
Unlike
|
||||
.At
|
||||
.Nm ksh ,
|
||||
.Nm mksh
|
||||
in
|
||||
.Fl o Ic posix
|
||||
or
|
||||
.Fl o Ic sh
|
||||
mode and
|
||||
.Nm lksh
|
||||
do not keep file descriptors \*(Gt 2 private from sub-processes.
|
||||
.It
|
||||
Functions defined with the
|
||||
.Ic function
|
||||
reserved word share the shell options
|
||||
.Pq Ic set -o
|
||||
instead of locally scoping them.
|
||||
.It
|
||||
Support for persistent history is never compiled in.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mksh 1
|
||||
|
@ -301,12 +273,6 @@ instead of locally scoping them.
|
|||
.Pp
|
||||
.Pa https://www.mirbsd.org/ksh\-chan.htm
|
||||
.Sh CAVEATS
|
||||
The distinction between the shell variants
|
||||
.Pq Nm lksh / Nm mksh
|
||||
and shell flags
|
||||
.Pq Fl o Ic posix / Ic sh
|
||||
will be reworked for an upcoming release.
|
||||
.Pp
|
||||
To use
|
||||
.Nm
|
||||
as
|
||||
|
@ -315,16 +281,22 @@ compilation to enable
|
|||
.Ic set -o posix
|
||||
by default if called as
|
||||
.Nm sh
|
||||
.Pq adding Dv \-DMKSH_BINSHPOSIX to Dv CPPFLAGS
|
||||
is highly recommended for better standards compliance.
|
||||
.Pp
|
||||
For better compatibility with legacy scripts, such as many
|
||||
.Tn Debian
|
||||
maintainer scripts, Upstart and SYSV init scripts, and other
|
||||
unfixed scripts, using the compile-time options for enabling
|
||||
unfixed scripts, also adding the
|
||||
.Dv \-DMKSH_BINSHREDUCED
|
||||
compile-time option to enable
|
||||
.Em both
|
||||
.Ic set -o posix -o sh
|
||||
when the shell is run as
|
||||
.Nm sh
|
||||
is recommended.
|
||||
.Nm sh ,
|
||||
as well as integrating the optional disrecommended
|
||||
.Xr printf 1
|
||||
builtin, might be necessary.
|
||||
.Pp
|
||||
.Nm
|
||||
tries to make a cross between a legacy bourne/posix compatibl-ish
|
||||
|
@ -332,14 +304,6 @@ shell and a legacy pdksh-alike but
|
|||
.Dq legacy
|
||||
is not exactly specified.
|
||||
.Pp
|
||||
The
|
||||
.Ic set
|
||||
built-in command does not currently have all options one would expect
|
||||
from a full-blown
|
||||
.Nm mksh
|
||||
or
|
||||
.Nm pdksh .
|
||||
.Pp
|
||||
Talk to the
|
||||
.Mx
|
||||
development team using the mailing list at
|
||||
|
|
41
main.c
41
main.c
|
@ -5,7 +5,7 @@
|
|||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -34,7 +34,7 @@
|
|||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.322 2016/11/11 23:48:30 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.328 2017/03/19 22:31:27 tg Exp $");
|
||||
|
||||
extern char **environ;
|
||||
|
||||
|
@ -56,8 +56,6 @@ static mksh_uari_t rndsetup(void);
|
|||
static void x_sigwinch(int);
|
||||
#endif
|
||||
|
||||
static const char initifs[] = "IFS= \t\n";
|
||||
|
||||
static const char initsubs[] =
|
||||
"${PS2=> }"
|
||||
"${PS3=#? }"
|
||||
|
@ -71,18 +69,18 @@ static const char *initcoms[] = {
|
|||
Ttypeset, "-x", "HOME", TPATH, TSHELL, NULL,
|
||||
Ttypeset, "-i10", "COLUMNS", "LINES", "SECONDS", "TMOUT", NULL,
|
||||
Talias,
|
||||
"integer=\\typeset -i",
|
||||
"local=\\typeset",
|
||||
"integer=\\\\builtin typeset -i",
|
||||
"local=\\\\builtin typeset",
|
||||
/* not "alias -t --": hash -r needs to work */
|
||||
"hash=\\builtin alias -t",
|
||||
"type=\\builtin whence -v",
|
||||
"autoload=\\typeset -fu",
|
||||
"functions=\\typeset -f",
|
||||
"history=\\builtin fc -l",
|
||||
"nameref=\\typeset -n",
|
||||
"hash=\\\\builtin alias -t",
|
||||
"type=\\\\builtin whence -v",
|
||||
"autoload=\\\\builtin typeset -fu",
|
||||
"functions=\\\\builtin typeset -f",
|
||||
"history=\\\\builtin fc -l",
|
||||
"nameref=\\\\builtin typeset -n",
|
||||
"nohup=nohup ",
|
||||
"r=\\builtin fc -e -",
|
||||
"login=\\exec login",
|
||||
"r=\\\\builtin fc -e -",
|
||||
"login=\\\\builtin exec login",
|
||||
NULL,
|
||||
/* this is what AT&T ksh seems to track, with the addition of emacs */
|
||||
Talias, "-tU",
|
||||
|
@ -365,9 +363,10 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
|
|||
}
|
||||
|
||||
/* for security */
|
||||
typeset(initifs, 0, 0, 0, 0);
|
||||
typeset("IFS= \t\n", 0, 0, 0, 0);
|
||||
|
||||
/* assign default shell variable values */
|
||||
typeset("PATHSEP=" MKSH_PATHSEPS, 0, 0, 0, 0);
|
||||
substitute(initsubs, 0);
|
||||
|
||||
/* Figure out the current working directory and set $PWD */
|
||||
|
@ -384,7 +383,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
|
|||
setstr(vp, current_wd, KSH_RETURN_ERROR);
|
||||
|
||||
for (wp = initcoms; *wp != NULL; wp++) {
|
||||
shcomexec(wp);
|
||||
c_builtin(wp);
|
||||
while (*wp != NULL)
|
||||
wp++;
|
||||
}
|
||||
|
@ -631,7 +630,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
|
|||
}
|
||||
|
||||
if (restricted_shell) {
|
||||
shcomexec(restr_com);
|
||||
c_builtin(restr_com);
|
||||
/* After typeset command... */
|
||||
Flag(FRESTRICTED) = 1;
|
||||
}
|
||||
|
@ -661,7 +660,7 @@ main(int argc, const char *argv[])
|
|||
|
||||
if ((rv = main_init(argc, argv, &s, &l)) == 0) {
|
||||
if (Flag(FAS_BUILTIN)) {
|
||||
rv = shcomexec(l->argv);
|
||||
rv = c_builtin(l->argv);
|
||||
} else {
|
||||
shell(s, true);
|
||||
/* NOTREACHED */
|
||||
|
@ -1275,12 +1274,10 @@ bi_errorf(const char *fmt, ...)
|
|||
VWARNINGF_BUILTIN, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
/*
|
||||
* POSIX special builtins and ksh special builtins cause
|
||||
* non-interactive shells to exit. XXX may not want LERROR here
|
||||
*/
|
||||
/* POSIX special builtins cause non-interactive shells to exit */
|
||||
if (builtin_spec) {
|
||||
builtin_argv0 = NULL;
|
||||
/* may not want to use LERROR here */
|
||||
unwind(LERROR);
|
||||
}
|
||||
}
|
||||
|
|
16
misc.c
16
misc.c
|
@ -3,7 +3,7 @@
|
|||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -30,7 +30,7 @@
|
|||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.250 2016/11/12 03:54:48 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.252 2017/03/11 23:56:17 tg Exp $");
|
||||
|
||||
#define KSH_CHVT_FLAG
|
||||
#ifdef MKSH_SMALL
|
||||
|
@ -40,10 +40,6 @@ __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.250 2016/11/12 03:54:48 tg Exp $");
|
|||
#define KSH_CHVT_CODE
|
||||
#define KSH_CHVT_FLAG
|
||||
#endif
|
||||
#ifdef MKSH_LEGACY_MODE
|
||||
#undef KSH_CHVT_CODE
|
||||
#undef KSH_CHVT_FLAG
|
||||
#endif
|
||||
|
||||
/* type bits for unsigned char */
|
||||
unsigned char chtypes[UCHAR_MAX + 1];
|
||||
|
@ -2154,7 +2150,7 @@ getrusage(int what, struct rusage *ru)
|
|||
int
|
||||
unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
|
||||
{
|
||||
int wc, i, c, fc;
|
||||
int wc, i, c, fc, n;
|
||||
|
||||
fc = (*fg)();
|
||||
switch (fc) {
|
||||
|
@ -2242,7 +2238,8 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
|
|||
* four (U: eight) digits; convert to Unicode
|
||||
*/
|
||||
wc = 0;
|
||||
while (i--) {
|
||||
n = 0;
|
||||
while (n < i || i == -1) {
|
||||
wc <<= 4;
|
||||
if ((c = (*fg)()) >= ord('0') && c <= ord('9'))
|
||||
wc += ksh_numdig(c);
|
||||
|
@ -2255,7 +2252,10 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
|
|||
(*fp)(c);
|
||||
break;
|
||||
}
|
||||
++n;
|
||||
}
|
||||
if (!n)
|
||||
goto unknown_escape;
|
||||
if ((cstyle && wc > 0xFF) || fc != 'x')
|
||||
/* Unicode marker */
|
||||
wc += 0x100;
|
||||
|
|
451
mksh.1
451
mksh.1
|
@ -1,8 +1,8 @@
|
|||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.420 2016/11/11 23:31:36 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.435 2017/03/19 22:31:27 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, 2016
|
||||
.\" 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
.\" mirabilos <m@mirbsd.org>
|
||||
.\"
|
||||
.\" Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -76,7 +76,7 @@
|
|||
.\" with -mandoc, it might implement .Mx itself, but we want to
|
||||
.\" use our own definition. And .Dd must come *first*, always.
|
||||
.\"
|
||||
.Dd $Mdocdate: November 11 2016 $
|
||||
.Dd $Mdocdate: March 19 2017 $
|
||||
.\"
|
||||
.\" Check which macro package we use, and do other -mdoc setup.
|
||||
.\"
|
||||
|
@ -186,23 +186,8 @@ sometimes does take portable shell scripting or various standards
|
|||
into account all information is first and foremost presented with
|
||||
.Nm
|
||||
in mind and should be taken as such.
|
||||
.Ss I'm an Android user, so what's mksh?
|
||||
.Nm mksh
|
||||
is a
|
||||
.Ux
|
||||
shell / command interpreter, similar to
|
||||
.Nm COMMAND.COM
|
||||
or
|
||||
.Nm CMD.EXE ,
|
||||
which has been included with
|
||||
.Tn Android Open Source Project
|
||||
for a while now.
|
||||
Basically, it's a program that runs in a terminal (console window),
|
||||
takes user input and runs commands or scripts, which it can also
|
||||
be asked to do by other programs, even in the background.
|
||||
Any privilege pop-ups you might be encountering are thus not
|
||||
.Nm mksh
|
||||
issues but questions by some other program utilising it.
|
||||
.Ss I use Android, OS/2, etc. so what...?
|
||||
Please see the FAQ at the end of this document.
|
||||
.Ss Invocation
|
||||
Most builtins can be called directly, for example if a link points from its
|
||||
name to the shell; not all make sense, have been tested or work at all though.
|
||||
|
@ -1130,17 +1115,17 @@ also by newline) may be one same parse tree.
|
|||
.Pp
|
||||
The following command aliases are defined automatically by the shell:
|
||||
.Bd -literal -offset indent
|
||||
autoload=\*(aq\etypeset \-fu\*(aq
|
||||
functions=\*(aq\etypeset \-f\*(aq
|
||||
hash=\*(aq\ebuiltin alias \-t\*(aq
|
||||
history=\*(aq\ebuiltin fc \-l\*(aq
|
||||
integer=\*(aq\etypeset \-i\*(aq
|
||||
local=\*(aq\etypeset\*(aq
|
||||
login=\*(aq\eexec login\*(aq
|
||||
nameref=\*(aq\etypeset \-n\*(aq
|
||||
autoload=\*(aq\e\ebuiltin typeset \-fu\*(aq
|
||||
functions=\*(aq\e\ebuiltin typeset \-f\*(aq
|
||||
hash=\*(aq\e\ebuiltin alias \-t\*(aq
|
||||
history=\*(aq\e\ebuiltin fc \-l\*(aq
|
||||
integer=\*(aq\e\ebuiltin typeset \-i\*(aq
|
||||
local=\*(aq\e\ebuiltin typeset\*(aq
|
||||
login=\*(aq\e\ebuiltin exec login\*(aq
|
||||
nameref=\*(aq\e\ebuiltin typeset \-n\*(aq
|
||||
nohup=\*(aqnohup \*(aq
|
||||
r=\*(aq\ebuiltin fc \-e \-\*(aq
|
||||
type=\*(aq\ebuiltin whence \-v\*(aq
|
||||
r=\*(aq\e\ebuiltin fc \-e \-\*(aq
|
||||
type=\*(aq\e\ebuiltin whence \-v\*(aq
|
||||
.Ed
|
||||
.Pp
|
||||
Tracked aliases allow the shell to remember where it found a particular
|
||||
|
@ -2035,9 +2020,11 @@ searched when looking for commands and files sourced using the
|
|||
.Dq Li \&.
|
||||
command (see below).
|
||||
An empty string resulting from a leading or trailing
|
||||
colon, or two adjacent colons, is treated as a
|
||||
(semi)colon, or two adjacent ones, is treated as a
|
||||
.Dq Li \&.
|
||||
(the current directory).
|
||||
.It Ev PATHSEP
|
||||
A colon (semicolon on OS/2), for the user's convenience.
|
||||
.It Ev PGRP
|
||||
The process ID of the shell's process group leader.
|
||||
.It Ev PIPESTATUS
|
||||
|
@ -2127,7 +2114,7 @@ Due to a strong suggestion from David G. Korn,
|
|||
.Nm
|
||||
now also supports the following form:
|
||||
.Bd -literal -offset indent
|
||||
PS1=$'\e1\er\e1\ee[7m\e1$PWD\e1\ee[0m\e1\*(Gt '
|
||||
PS1=$\*(aq\e1\er\e1\ee[7m\e1$PWD\e1\ee[0m\e1\*(Gt \*(aq
|
||||
.Ed
|
||||
.It Ev PS2
|
||||
Secondary prompt string, by default
|
||||
|
@ -2185,9 +2172,18 @@ files are created in
|
|||
The effective user id of the shell.
|
||||
.El
|
||||
.Ss Tilde expansion
|
||||
Tilde expansion which is done in parallel with parameter substitution, is done
|
||||
on words starting with an unquoted
|
||||
Tilde expansion, which is done in parallel with parameter substitution,
|
||||
is applied to words starting with an unquoted
|
||||
.Ql \*(TI .
|
||||
In parameter assignments (such as those preceding a simple-command or those
|
||||
occurring in the arguments of a declaration utility), tilde expansion is done
|
||||
after any assignment (i.e. after the equals sign) or after an unquoted colon
|
||||
.Pq Ql \&: ;
|
||||
login names are also delimited by colons.
|
||||
The Korn shell, except in POSIX mode, always expands tildes after unquoted
|
||||
equals signs, not just in assignment context (see below), and enables tab
|
||||
completion for tildes after all unquoted colons during command line editing.
|
||||
.Pp
|
||||
The characters following the tilde, up to the first
|
||||
.Ql / ,
|
||||
if any, are assumed to be a login name.
|
||||
|
@ -2208,21 +2204,6 @@ If the login name is not found in the password file or
|
|||
if any quoting or parameter substitution occurs in the login name, no
|
||||
substitution is performed.
|
||||
.Pp
|
||||
In parameter assignments
|
||||
(such as those preceding a simple-command or those occurring
|
||||
in the arguments of
|
||||
.Ic alias ,
|
||||
.Ic export ,
|
||||
.Ic global ,
|
||||
.Ic readonly
|
||||
and
|
||||
.Ic typeset ) ,
|
||||
tilde expansion is done after any assignment
|
||||
(i.e. after the equals sign)
|
||||
or after an unquoted colon
|
||||
.Pq Ql \&: ;
|
||||
login names are also delimited by colons.
|
||||
.Pp
|
||||
The home directory of previously expanded login names are cached and re-used.
|
||||
The
|
||||
.Ic alias Fl d
|
||||
|
@ -2586,7 +2567,7 @@ Redirections are processed after
|
|||
pipelines are created and in the order they are given, so the following
|
||||
will print an error with a line number prepended to it:
|
||||
.Pp
|
||||
.D1 $ cat /foo/bar 2\*(Gt&1 \*(Gt/dev/null \*(Ba pr \-n \-t
|
||||
.Dl $ cat /foo/bar 2\*(Gt&1 \*(Gt/dev/null \*(Ba pr \-n \-t
|
||||
.Pp
|
||||
File descriptors created by I/O redirections are private to the shell.
|
||||
.Ss Arithmetic expressions
|
||||
|
@ -3022,18 +3003,18 @@ Additional
|
|||
.Nm
|
||||
commands keeping assignments:
|
||||
.Pp
|
||||
.Ic builtin , global , source , typeset ,
|
||||
.Ic wait
|
||||
.Ic global , source , typeset
|
||||
.Pp
|
||||
Builtins that are not special:
|
||||
.Pp
|
||||
.Ic [ , alias , bg , bind ,
|
||||
.Ic cat , cd , command , echo ,
|
||||
.Ic false , fc , fg , getopts ,
|
||||
.Ic jobs , kill , let , print ,
|
||||
.Ic pwd , read , realpath , rename ,
|
||||
.Ic sleep , suspend , test , true ,
|
||||
.Ic ulimit , umask , unalias , whence
|
||||
.Ic builtin , cat , cd , command ,
|
||||
.Ic echo , false , fc , fg ,
|
||||
.Ic getopts , jobs , kill , let ,
|
||||
.Ic print , pwd , read , realpath ,
|
||||
.Ic rename , sleep , suspend , test ,
|
||||
.Ic true , ulimit , umask , unalias ,
|
||||
.Ic wait , whence
|
||||
.Pp
|
||||
Once the type of command has been determined, any command-line parameter
|
||||
assignments are performed and exported for the duration of the command.
|
||||
|
@ -3217,6 +3198,18 @@ Execute the built-in command
|
|||
.Ar command .
|
||||
.Pp
|
||||
.It Xo
|
||||
.Ic \ebuiltin
|
||||
.Ar command Op Ar arg ...
|
||||
.Xc
|
||||
Same as
|
||||
.Ic builtin .
|
||||
Additionally acts as declaration utility forwarder, i.e. this is a
|
||||
declaration utility (see
|
||||
.Sx Tilde expansion )
|
||||
.No iff Ar command
|
||||
is a declaration utility.
|
||||
.Pp
|
||||
.It Xo
|
||||
.Ic cat
|
||||
.Op Fl u
|
||||
.Op Ar
|
||||
|
@ -3346,6 +3339,7 @@ cannot be a shell function;
|
|||
and secondly, special built-in commands lose their specialness
|
||||
(i.e. redirection and utility errors do not cause the shell to
|
||||
exit, and command assignments are not permanent).
|
||||
The declaration utility property is not reset.
|
||||
.Pp
|
||||
If the
|
||||
.Fl p
|
||||
|
@ -3421,8 +3415,10 @@ If the
|
|||
.Ic posix
|
||||
or
|
||||
.Ic sh
|
||||
option is set or this is a direct builtin call, only the first argument
|
||||
is treated as an option, and only if it is exactly
|
||||
option is set or this is a direct builtin call or
|
||||
.Ic print
|
||||
.Fl R ,
|
||||
only the first argument is treated as an option, and only if it is exactly
|
||||
.Dq Li \-n .
|
||||
Backslash interpretation is disabled.
|
||||
.Pp
|
||||
|
@ -3478,6 +3474,7 @@ parameter.
|
|||
Sets the export attribute of the named parameters.
|
||||
Exported parameters are passed in the environment to executed commands.
|
||||
If values are specified, the named parameters are also assigned.
|
||||
This is a declaration utility.
|
||||
.Pp
|
||||
If no parameters are specified, all parameters with the export attribute
|
||||
set are printed one per line; either their names, or, if a
|
||||
|
@ -3632,9 +3629,22 @@ resetting
|
|||
.Ev OPTIND
|
||||
may lead to unexpected results.
|
||||
.Pp
|
||||
.It global Ar ...
|
||||
.It Xo
|
||||
.Ic global
|
||||
.Op Ic +\-aglpnrtUux
|
||||
.Oo Fl L Ns Op Ar n
|
||||
.No \*(Ba Fl R Ns Op Ar n
|
||||
.No \*(Ba Fl Z Ns Op Ar n Oc
|
||||
.Op Fl i Ns Op Ar n
|
||||
.Oo Ar name
|
||||
.Op Ns = Ns Ar value
|
||||
.Ar ... Oc
|
||||
.Xc
|
||||
See
|
||||
.Ic typeset .
|
||||
.Ic typeset Fl g .
|
||||
.No Deprecated , Em will
|
||||
be removed from a future version of
|
||||
.Nm .
|
||||
.Pp
|
||||
.It Xo
|
||||
.Ic hash
|
||||
|
@ -3712,12 +3722,8 @@ If an error occurs during
|
|||
the parsing or evaluation of an expression, the exit status is greater than 1.
|
||||
Since expressions may need to be quoted,
|
||||
.No \&(( Ar expr No ))
|
||||
is syntactic sugar for
|
||||
.No "{ let '" Ns Ar expr Ns "'; }" .
|
||||
.Pp
|
||||
.It Ic let]
|
||||
Internally used alias for
|
||||
.Ic let .
|
||||
is syntactic sugar for:
|
||||
.Dl "{ \e\ebuiltin let \*(aq" Ns Ar expr Ns "\*(aq; }"
|
||||
.Pp
|
||||
.It Xo
|
||||
.Ic mknod
|
||||
|
@ -3757,13 +3763,13 @@ however, distributors may have added this as builtin as a speed hack.
|
|||
.Pp
|
||||
.It Xo
|
||||
.Ic print
|
||||
.Oo Fl AclNnprsu Ns Oo Ar n Oc \*(Ba
|
||||
.Fl R Op Fl en Oc
|
||||
.Oo Fl AcelNnprsu Ns Oo Ar n Oc \*(Ba
|
||||
.Fl R Op Fl n Oc
|
||||
.Op Ar argument ...
|
||||
.Xc
|
||||
Print the specified argument(s) on the standard output,
|
||||
separated by spaces, terminated with a newline.
|
||||
The C escapes mentioned in
|
||||
The escapes mentioned in
|
||||
.Sx Backslash expansion
|
||||
above, as well as
|
||||
.Dq Li \ec ,
|
||||
|
@ -3789,6 +3795,9 @@ utility, tab completion, the
|
|||
built-in utility and the
|
||||
.Ic select
|
||||
statement do.
|
||||
.It Fl e
|
||||
Restore backslash expansion after a previous
|
||||
.Fl r .
|
||||
.It Fl l
|
||||
Change the output word separator to newline.
|
||||
.It Fl N
|
||||
|
@ -3803,7 +3812,7 @@ above).
|
|||
Inhibit backslash expansion.
|
||||
.It Fl s
|
||||
Print to the history file instead of standard output.
|
||||
.It Fl u Op Ar n
|
||||
.It Fl u Ns Op Ar n
|
||||
Print to the file descriptor
|
||||
.Ar n Pq defaults to 1 if omitted
|
||||
instead of standard output.
|
||||
|
@ -3811,31 +3820,13 @@ instead of standard output.
|
|||
.Pp
|
||||
The
|
||||
.Fl R
|
||||
option is used to emulate, to some degree, the
|
||||
option mostly emulates the
|
||||
.Bx
|
||||
.Xr echo 1
|
||||
command which does not process
|
||||
.Ql \e
|
||||
sequences unless the
|
||||
.Fl e
|
||||
option is given.
|
||||
As above, the
|
||||
.Fl n
|
||||
option suppresses the trailing newline.
|
||||
.Pp
|
||||
.It Ic printf Ar format Op Ar arguments ...
|
||||
Formatted output.
|
||||
Approximately the same as the
|
||||
.Xr printf 1 ,
|
||||
utility, except it uses the same
|
||||
.Sx Backslash expansion
|
||||
and I/O code and does not handle floating point as the rest of
|
||||
.Nm mksh .
|
||||
An external utility is preferred over the builtin.
|
||||
This is not normally part of
|
||||
.Nm mksh ;
|
||||
however, distributors may have added this as builtin as a speed hack.
|
||||
Do not use in new code.
|
||||
command which does not expand backslashes and interprets
|
||||
its first argument as option only if it is exactly
|
||||
.Dq Li \-n
|
||||
.Pq to suppress the trailing newline .
|
||||
.Pp
|
||||
.It Ic pwd Op Fl LP
|
||||
Print the present working directory.
|
||||
|
@ -3970,40 +3961,6 @@ If no input is read or a timeout occurred,
|
|||
.Ic read
|
||||
exits with a non-zero status.
|
||||
.Pp
|
||||
Another handy set of tricks:
|
||||
If
|
||||
.Ic read
|
||||
is run in a loop such as
|
||||
.Ic while read foo; do ...; done
|
||||
then leading whitespace will be removed (IFS) and backslashes processed.
|
||||
You might want to use
|
||||
.Ic while IFS= read \-r foo; do ...; done
|
||||
for pristine I/O.
|
||||
Similarly, when using the
|
||||
.Fl a
|
||||
option, use of the
|
||||
.Fl r
|
||||
option might be prudent; the same applies for:
|
||||
.Bd -literal -offset indent
|
||||
find . \-type f \-print0 \*(Ba& \e
|
||||
while IFS= read \-d \*(aq\*(aq \-pr filename; do
|
||||
print \-r \-\- "found \*(Lt${filename#./}\*(Gt"
|
||||
done
|
||||
.Ed
|
||||
.Pp
|
||||
The inner loop will be executed in a subshell and variable changes
|
||||
cannot be propagated if executed in a pipeline:
|
||||
.Bd -literal -offset indent
|
||||
bar \*(Ba baz \*(Ba while read foo; do ...; done
|
||||
.Ed
|
||||
.Pp
|
||||
Use co-processes instead:
|
||||
.Bd -literal -offset indent
|
||||
bar \*(Ba baz \*(Ba&
|
||||
while read \-p foo; do ...; done
|
||||
exec 3\*(Gt&p; exec 3\*(Gt&\-
|
||||
.Ed
|
||||
.Pp
|
||||
.It Xo
|
||||
.Ic readonly
|
||||
.Op Fl p
|
||||
|
@ -4012,6 +3969,7 @@ exec 3\*(Gt&p; exec 3\*(Gt&\-
|
|||
.Ar ... Oc
|
||||
.Xc
|
||||
Sets the read-only attribute of the named parameters.
|
||||
This is a declaration utility.
|
||||
If values are given,
|
||||
parameters are set to them before setting the attribute.
|
||||
Once a parameter is
|
||||
|
@ -4266,7 +4224,6 @@ Background jobs are run with lower priority.
|
|||
.It Fl o Ic braceexpand
|
||||
Enable brace expansion (a.k.a. alternation).
|
||||
This is enabled by default.
|
||||
If disabled, tilde expansion after an equals sign is disabled as a side effect.
|
||||
.It Fl o Ic emacs
|
||||
Enable BRL emacs-like command-line editing (interactive shells only); see
|
||||
.Sx Emacs editing mode .
|
||||
|
@ -4800,28 +4757,23 @@ traps in functions are not yet implemented.
|
|||
A command that exits with a zero value.
|
||||
.Pp
|
||||
.It Xo
|
||||
.Ic global
|
||||
.Oo Op Ic +\-alpnrtUux
|
||||
.Op Fl L Ns Op Ar n
|
||||
.Op Fl R Ns Op Ar n
|
||||
.Op Fl Z Ns Op Ar n
|
||||
.Ic typeset
|
||||
.Op Ic +\-aglpnrtUux
|
||||
.Oo Fl L Ns Op Ar n
|
||||
.No \*(Ba Fl R Ns Op Ar n
|
||||
.No \*(Ba Fl Z Ns Op Ar n Oc
|
||||
.Op Fl i Ns Op Ar n
|
||||
.No \*(Ba Fl f Op Fl tux Oc
|
||||
.Oo Ar name
|
||||
.Op Ns = Ns Ar value
|
||||
.Ar ... Oc
|
||||
.Xc
|
||||
.It Xo
|
||||
.Ic typeset
|
||||
.Oo Op Ic +\-alpnrtUux
|
||||
.Op Fl LRZ Ns Op Ar n
|
||||
.Op Fl i Ns Op Ar n
|
||||
.No \*(Ba Fl f Op Fl tux Oc
|
||||
.Oo Ar name
|
||||
.Op Ns = Ns Ar value
|
||||
.Ar ... Oc
|
||||
.Fl f Op Fl tux
|
||||
.Op Ar name ...
|
||||
.Xc
|
||||
Display or set parameter attributes.
|
||||
This is a declaration utility.
|
||||
With no
|
||||
.Ar name
|
||||
arguments, parameter attributes are displayed; if no options are used, the
|
||||
|
@ -4837,27 +4789,16 @@ parameter values are not printed.
|
|||
If
|
||||
.Ar name
|
||||
arguments are given, the attributes of the named parameters are set
|
||||
.Pq Ic \-
|
||||
.Pq Ic \&\-
|
||||
or cleared
|
||||
.Pq Ic + .
|
||||
.Pq Ic \&+ ;
|
||||
inside a function, this will cause the parameters to be created
|
||||
(with no value) in the local scope (but see
|
||||
.Fl g ) .
|
||||
Values for parameters may optionally be specified.
|
||||
For
|
||||
.Ar name Ns \&[*] ,
|
||||
the change affects the entire array, and no value may be specified.
|
||||
.Pp
|
||||
If
|
||||
.Ic typeset
|
||||
is used inside a function, any parameters specified are localised.
|
||||
This is not done by the otherwise identical
|
||||
.Ic global .
|
||||
.Em Note :
|
||||
This means that
|
||||
.Nm No 's Ic global
|
||||
command is
|
||||
.Em not
|
||||
equivalent to other programming languages' as it does not allow a
|
||||
function called from another function to access a parameter at truly
|
||||
global scope, but only prevents putting an accessed one into local scope.
|
||||
the change affects all elements of the array, and no value may be specified.
|
||||
.Pp
|
||||
When
|
||||
.Fl f
|
||||
|
@ -4877,6 +4818,9 @@ Indexed array attribute.
|
|||
.It Fl f
|
||||
Function mode.
|
||||
Display or set functions and their attributes, instead of parameters.
|
||||
.It Fl g
|
||||
Do not cause named parameters to be created in
|
||||
the local scope when called inside a function.
|
||||
.It Fl i Ns Op Ar n
|
||||
Integer attribute.
|
||||
.Ar n
|
||||
|
@ -5028,7 +4972,7 @@ once they are set.
|
|||
Also note that the types of limits available are system
|
||||
dependent \*(en some systems have only the
|
||||
.Fl f
|
||||
limit.
|
||||
limit, or not even that, or can set only the soft limits
|
||||
.Bl -tag -width 5n
|
||||
.It Fl a
|
||||
Display all limits; unless
|
||||
|
@ -5744,9 +5688,6 @@ Goes to history number
|
|||
.No KILL Pq \*(haU
|
||||
.Xc
|
||||
Deletes the entire input line.
|
||||
If Ctrl-U should only delete the line up to the cursor, use:
|
||||
.Pp
|
||||
.D1 $ bind \-m \*(haU='\*(ha[0\*(haK'
|
||||
.It kill\-region: \*(haW
|
||||
Deletes the input between the cursor and the mark.
|
||||
.It Xo kill\-to\-eol:
|
||||
|
@ -6625,24 +6566,6 @@ The complete legalese is at:
|
|||
.\" to protect it or lose it, which McKusick almost did.
|
||||
.\"
|
||||
.Sh CAVEATS
|
||||
.Nm
|
||||
has a different scope model from
|
||||
.At
|
||||
.Nm ksh ,
|
||||
which leads to subtle differences in semantics for identical builtins.
|
||||
This can cause issues with a
|
||||
.Ic nameref
|
||||
to suddenly point to a local variable by accident; fixing this is hard.
|
||||
.Pp
|
||||
The parts of a pipeline, like below, are executed in subshells.
|
||||
Thus, variable assignments inside them are not visible in the
|
||||
surrounding execution environment.
|
||||
Use co-processes instead.
|
||||
.Bd -literal -offset indent
|
||||
foo \*(Ba bar \*(Ba read baz # will not change $baz
|
||||
foo \*(Ba bar \*(Ba& read \-p baz # will, however, do so
|
||||
.Ed
|
||||
.Pp
|
||||
.Nm mksh
|
||||
provides a consistent 32-bit integer arithmetic implementation, both
|
||||
signed and unsigned, with sign of the result of a remainder operation
|
||||
|
@ -6687,6 +6610,8 @@ case ${KSH_VERSION:\-} in
|
|||
esac
|
||||
.Ed
|
||||
In near future, (Unicode) locale tracking will be implemented though.
|
||||
.Pp
|
||||
See also the FAQ below.
|
||||
.Sh BUGS
|
||||
Suspending (using \*(haZ) pipelines like the one below will only suspend
|
||||
the currently running part of the pipeline; in this example,
|
||||
|
@ -6710,7 +6635,7 @@ for the in-memory portion of the history is slow, should use
|
|||
.Xr memmove 3 .
|
||||
.Pp
|
||||
This document attempts to describe
|
||||
.Nm mksh\ R54
|
||||
.Nm mksh\ R55
|
||||
and up,
|
||||
.\" with vendor patches from insert-your-name-here,
|
||||
compiled without any options impacting functionality, such as
|
||||
|
@ -6727,9 +6652,8 @@ for an operating environment supporting all of its advanced needs.
|
|||
Please report bugs in
|
||||
.Nm
|
||||
to the
|
||||
.Mx
|
||||
mailing list at
|
||||
.Aq Mt miros\-mksh@mirbsd.org
|
||||
mailing list
|
||||
or in the
|
||||
.Li \&#\&!/bin/mksh
|
||||
.Pq or Li \&#ksh
|
||||
|
@ -6738,3 +6662,160 @@ IRC channel at
|
|||
.Pq Port 6697 SSL, 6667 unencrypted ,
|
||||
or at:
|
||||
.Pa https://launchpad.net/mksh
|
||||
.Sh FREQUENTLY ASKED QUESTIONS
|
||||
This FAQ attempts to document some of the questions users of
|
||||
.Nm
|
||||
or readers of this manual page may encounter.
|
||||
.Ss I'm an Android user, so what's mksh?
|
||||
.Nm mksh
|
||||
is a
|
||||
.Ux
|
||||
shell / command interpreter, similar to
|
||||
.Nm COMMAND.COM
|
||||
or
|
||||
.Nm CMD.EXE ,
|
||||
which has been included with
|
||||
.Tn Android Open Source Project
|
||||
for a while now.
|
||||
Basically, it's a program that runs in a terminal (console window),
|
||||
takes user input and runs commands or scripts, which it can also
|
||||
be asked to do by other programs, even in the background.
|
||||
Any privilege pop-ups you might be encountering are thus not
|
||||
.Nm mksh
|
||||
issues but questions by some other program utilising it.
|
||||
.Ss "I'm an OS/2 user, what do I need to know?"
|
||||
Unlike the native command prompt, the current working directory is,
|
||||
for security reasons common on Unix systems which the shell is designed for,
|
||||
not in the search path at all; if you really need this, run the command
|
||||
.Li PATH=.$PATHSEP$PATH
|
||||
or add that to a suitable initialisation file.
|
||||
.Pp
|
||||
You will have gotten this shell through komh's port on Shellworld
|
||||
most likely. It differs from standard mksh in that ASCII (CR+LF)
|
||||
newlines are accepted in many places.
|
||||
.Ss "How do I start mksh on a specific terminal?"
|
||||
Normally:
|
||||
.Dl mksh \-T/dev/tty2
|
||||
.Pp
|
||||
However, if you want for it to return (e.g. for an embedded
|
||||
system rescue shell), use this on your real console device instead:
|
||||
.Dl mksh \-T!/dev/ttyACM0
|
||||
.Pp
|
||||
.Nm
|
||||
can also daemonise (send to the background):
|
||||
.Dl mksh \-T\- \-c \*(aqexec cdio lock\*(aq
|
||||
.Ss "POSIX says..."
|
||||
Run the shell in POSIX mode (and possibly
|
||||
.Nm lksh
|
||||
instead of
|
||||
.Nm mksh ) :
|
||||
.Dl set \-o posix
|
||||
.Ss "My prompt from <some other shell> does not work!"
|
||||
Contact us on the mailing list or on IRC, we'll convert it for you.
|
||||
.Ss "Something is going wrong with my while...read loop"
|
||||
Most likely, you've encountered the problem in which the shell runs
|
||||
all parts of a pipeline as subshell.
|
||||
The inner loop will be executed in a subshell and variable changes
|
||||
cannot be propagated if run in a pipeline:
|
||||
.Bd -literal -offset indent
|
||||
bar \*(Ba baz \*(Ba while read foo; do ...; done
|
||||
.Ed
|
||||
.Pp
|
||||
Use co-processes instead:
|
||||
.Bd -literal -offset indent
|
||||
bar \*(Ba baz \*(Ba&
|
||||
while read \-p foo; do ...; done
|
||||
exec 3\*(Gt&p; exec 3\*(Gt&\-
|
||||
.Ed
|
||||
.Pp
|
||||
If
|
||||
.Ic read
|
||||
is run in a loop such as
|
||||
.Ic while read foo; do ...; done
|
||||
then leading whitespace will be removed (IFS) and backslashes processed.
|
||||
You might want to use
|
||||
.Ic while IFS= read \-r foo; do ...; done
|
||||
for pristine I/O.
|
||||
Similarly, when using the
|
||||
.Fl a
|
||||
option, use of the
|
||||
.Fl r
|
||||
option might be prudent
|
||||
.Pq Dq Li read \-raN\-1 arr \*(Ltfile ;
|
||||
the same applies for NUL-terminated lines:
|
||||
.Bd -literal -offset indent
|
||||
find . \-type f \-print0 \*(Ba& \e
|
||||
while IFS= read \-d \*(aq\*(aq \-pr filename; do
|
||||
print \-r \-\- "found \*(Lt${filename#./}\*(Gt"
|
||||
done
|
||||
.Ed
|
||||
.Pp
|
||||
.Ss "What differences in function-local scopes are there?"
|
||||
.Nm
|
||||
has a different scope model from
|
||||
.At
|
||||
.Nm ksh ,
|
||||
which leads to subtle differences in semantics for identical builtins.
|
||||
This can cause issues with a
|
||||
.Ic nameref
|
||||
to suddenly point to a local variable by accident.
|
||||
.Pp
|
||||
.Tn GNU
|
||||
.Nm bash
|
||||
allows unsetting local variables; in
|
||||
.Nm ,
|
||||
doing so in a function allows back access to the global variable
|
||||
(actually the one in the next scope up) with the same name.
|
||||
The following code, when run before the function definitions, changes
|
||||
the behaviour of
|
||||
.Ic unset
|
||||
to behave like other shells (the alias can be removed after the definitions):
|
||||
.Bd -literal -offset indent
|
||||
case ${KSH_VERSION:\-} in
|
||||
*MIRBSD\ KSH*\*(Ba*LEGACY\ KSH*)
|
||||
function unset_compat {
|
||||
\e\ebuiltin typeset unset_compat_x
|
||||
|
||||
for unset_compat_x in "$@"; do
|
||||
eval "\e\e\e\ebuiltin unset $unset_compat_x[*]"
|
||||
done
|
||||
}
|
||||
\e\ebuiltin alias unset=unset_compat
|
||||
;;
|
||||
esac
|
||||
.Ed
|
||||
.Pp
|
||||
When a local variable is created (e.g. using
|
||||
.Ic local ,
|
||||
.Ic typeset ,
|
||||
.Ic integer ,
|
||||
.Ic \e\ebuiltin typeset )
|
||||
it does not, like in other shells, inherit the value from the global
|
||||
(next scope up) variable with the same name; it is rather created
|
||||
without any value (unset but defined).
|
||||
.Ss "I get an error in this regex comparison"
|
||||
Use extglobs instead of regexes:
|
||||
.Dl "[[ foo =~ (foo\*(Babar).*baz ]] # becomes"
|
||||
.Dl "[[ foo = *@(foo\*(Babar)*baz* ]] # instead"
|
||||
.Ss "Are there any extensions to avoid?"
|
||||
.Tn GNU
|
||||
.Nm bash
|
||||
supports
|
||||
.Dq Li &\*(Gt
|
||||
.Pq and Dq Li \*(Ba&
|
||||
to redirect both stdout and stderr in one go, but this breaks POSIX
|
||||
and Korn Shell syntax; use POSIX redirections instead:
|
||||
.Dl "foo \*(Ba& bar \*(Ba& baz &\*(Gtlog # GNU bash"
|
||||
.Dl "foo 2\*(Gt&1 \*(Ba bar 2\*(Gt&1 \*(Ba baz \*(Gtlog 2\*(Gt&1 # POSIX"
|
||||
.Ss "\*(haL (Ctrl-L) does not clear the screen"
|
||||
Use \*(ha[\*(haL (Escape+Ctrl-L) or rebind it:
|
||||
.Dl bind \*(aq\*(haL=clear-screen\*(aq
|
||||
.Ss "\*(haU (Ctrl-U) clears the entire line"
|
||||
If it should only delete the line up to the cursor, use:
|
||||
.Dl bind \-m \*(haU=\*(aq\*(ha[0\*(haK\*(aq
|
||||
.Ss "Cursor Up behaves differently from zsh"
|
||||
Some shells make Cursor Up search in the history only for
|
||||
commands starting with what was already entered.
|
||||
.Nm
|
||||
separates the shortcuts: Cursor Up goes up one command
|
||||
and PgUp searches the history as described above.
|
||||
|
|
102
sh.h
102
sh.h
|
@ -10,7 +10,7 @@
|
|||
|
||||
/*-
|
||||
* Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -175,9 +175,9 @@
|
|||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.791 2016/11/11 23:31:38 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.797 2017/03/22 00:20:53 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R54 2016/11/11"
|
||||
#define MKSH_VERSION "R54 2017/03/21"
|
||||
|
||||
/* arithmetic types: C implementation */
|
||||
#if !HAVE_CAN_INTTYPES
|
||||
|
@ -630,14 +630,6 @@ im_sorry_dave(void)
|
|||
} while (/* CONSTCOND */ 0)
|
||||
#endif
|
||||
|
||||
#ifdef MKSH_LEGACY_MODE
|
||||
#ifndef MKSH_NO_CMDLINE_EDITING
|
||||
#define MKSH_NO_CMDLINE_EDITING /* defined */
|
||||
#endif
|
||||
#undef MKSH_S_NOVI
|
||||
#define MKSH_S_NOVI 1
|
||||
#endif
|
||||
|
||||
#ifdef MKSH_SMALL
|
||||
#ifndef MKSH_NOPWNAM
|
||||
#define MKSH_NOPWNAM /* defined */
|
||||
|
@ -855,8 +847,8 @@ EXTERN char null[] E_INIT("");
|
|||
|
||||
#ifndef HAVE_STRING_POOLING /* helpers for pooled strings */
|
||||
EXTERN const char T4spaces[] E_INIT(" ");
|
||||
#define T1space (T4spaces + 3)
|
||||
EXTERN const char Tcolsp[] E_INIT(": ");
|
||||
#define T1space (Treal_sp2 + 5)
|
||||
#define Tcolsp (Tf_sD_ + 2)
|
||||
EXTERN const char TC_LEX1[] E_INIT("|&;<>() \t\n");
|
||||
#define TC_IFSWS (TC_LEX1 + 7)
|
||||
EXTERN const char TFCEDIT_dollaru[] E_INIT("${FCEDIT:-/bin/ed} $_");
|
||||
|
@ -865,15 +857,16 @@ EXTERN const char Tsgdot[] E_INIT("*=.");
|
|||
EXTERN const char Taugo[] E_INIT("augo");
|
||||
EXTERN const char Tbracket[] E_INIT("[");
|
||||
#define Tdot (Tsgdot + 2)
|
||||
EXTERN const char Talias[] E_INIT("alias");
|
||||
EXTERN const char Tbadsubst[] E_INIT("bad substitution");
|
||||
#define Talias (Tunalias + 2)
|
||||
#define Tbadsubst (Tfg_badsubst + 10)
|
||||
EXTERN const char Tbg[] E_INIT("bg");
|
||||
EXTERN const char Tbad_bsize[] E_INIT("bad shf/buf/bsize");
|
||||
#define Tbsize (Tbad_bsize + 12)
|
||||
EXTERN const char Tbad_sig_ss[] E_INIT("%s: bad signal '%s'");
|
||||
#define Tbad_sig_s (Tbad_sig_ss + 4)
|
||||
EXTERN const char Tgbuiltin[] E_INIT("=builtin");
|
||||
#define Tbuiltin (Tgbuiltin + 1)
|
||||
EXTERN const char T__builtin[] E_INIT("-\\builtin");
|
||||
#define T_builtin (T__builtin + 1)
|
||||
#define Tbuiltin (T__builtin + 2)
|
||||
EXTERN const char Toomem[] E_INIT("can't allocate %zu data bytes");
|
||||
EXTERN const char Tcant_cd[] E_INIT("restricted shell - can't cd");
|
||||
EXTERN const char Tcant_find[] E_INIT("can't find");
|
||||
|
@ -882,26 +875,27 @@ EXTERN const char Tcant_open[] E_INIT("can't open");
|
|||
EXTERN const char Tbcat[] E_INIT("!cat");
|
||||
#define Tcat (Tbcat + 1)
|
||||
#define Tcd (Tcant_cd + 25)
|
||||
EXTERN const char Tcommand[] E_INIT("command");
|
||||
#define T_command (T_funny_command + 9)
|
||||
#define Tcommand (T_funny_command + 10)
|
||||
EXTERN const char Tcreate[] E_INIT("create");
|
||||
EXTERN const char TELIF_unexpected[] E_INIT("TELIF unexpected");
|
||||
EXTERN const char TEXECSHELL[] E_INIT("EXECSHELL");
|
||||
EXTERN const char Tsgexport[] E_INIT("*=export");
|
||||
#define Texport (Tsgexport + 2)
|
||||
EXTERN const char Tdsgexport[] E_INIT("^*=export");
|
||||
#define Texport (Tdsgexport + 3)
|
||||
#ifdef __OS2__
|
||||
EXTERN const char Textproc[] E_INIT("extproc");
|
||||
#endif
|
||||
EXTERN const char Tfalse[] E_INIT("false");
|
||||
EXTERN const char Tfg[] E_INIT("fg");
|
||||
EXTERN const char Tfg_badsubst[] E_INIT("fileglob: bad substitution");
|
||||
EXTERN const char Tfile[] E_INIT("file");
|
||||
#define Tfile (Tfile_fd + 20)
|
||||
EXTERN const char Tfile_fd[] E_INIT("function definition file");
|
||||
EXTERN const char TFPATH[] E_INIT("FPATH");
|
||||
EXTERN const char T_function[] E_INIT(" function");
|
||||
#define Tfunction (T_function + 1)
|
||||
EXTERN const char T_funny_command[] E_INIT("funny $() command");
|
||||
EXTERN const char T_funny_command[] E_INIT("funny $()-command");
|
||||
EXTERN const char Tgetopts[] E_INIT("getopts");
|
||||
EXTERN const char Thistory[] E_INIT("history");
|
||||
#define Thistory (Tnot_in_history + 7)
|
||||
EXTERN const char Tintovfl[] E_INIT("integer overflow %zu %c %zu prevented");
|
||||
EXTERN const char Tjobs[] E_INIT("jobs");
|
||||
EXTERN const char Tjob_not_started[] E_INIT("job not started");
|
||||
|
@ -917,20 +911,20 @@ EXTERN const char Tnot_found_s[] E_INIT("%s not found");
|
|||
#define TOLDPWD (Tno_OLDPWD + 3)
|
||||
#define Topen (Tcant_open + 6)
|
||||
#define TPATH (TFPATH + 1)
|
||||
EXTERN const char Tpv[] E_INIT("pv");
|
||||
#define Tpv (TpVv + 1)
|
||||
EXTERN const char TpVv[] E_INIT("Vpv");
|
||||
#define TPWD (Tno_OLDPWD + 6)
|
||||
EXTERN const char Tread[] E_INIT("read");
|
||||
EXTERN const char Tsgreadonly[] E_INIT("*=readonly");
|
||||
#define Treadonly (Tsgreadonly + 2)
|
||||
#define Tread (Tshf_read + 4)
|
||||
EXTERN const char Tdsgreadonly[] E_INIT("^*=readonly");
|
||||
#define Treadonly (Tdsgreadonly + 3)
|
||||
EXTERN const char Tredirection_dup[] E_INIT("can't finish (dup) redirection");
|
||||
#define Tredirection (Tredirection_dup + 19)
|
||||
EXTERN const char Treal_sp1[] E_INIT("real ");
|
||||
#define Treal_sp1 (Treal_sp2 + 1)
|
||||
EXTERN const char Treal_sp2[] E_INIT(" real ");
|
||||
EXTERN const char Treq_arg[] E_INIT("requires an argument");
|
||||
EXTERN const char Tselect[] E_INIT("select");
|
||||
EXTERN const char Tsgset[] E_INIT("*=set");
|
||||
#define Tset (Tsgset + 2)
|
||||
#define Tset (Tf_parm + 18)
|
||||
#define Tsh (Tmksh + 2)
|
||||
#define TSHELL (TEXECSHELL + 4)
|
||||
EXTERN const char Tshf_read[] E_INIT("shf_read");
|
||||
|
@ -943,27 +937,27 @@ EXTERN const char Ttoo_many_args[] E_INIT("too many arguments");
|
|||
EXTERN const char Ttrue[] E_INIT("true");
|
||||
EXTERN const char Ttty_fd_dupof[] E_INIT("dup of tty fd");
|
||||
#define Ttty_fd (Ttty_fd_dupof + 7)
|
||||
EXTERN const char Tgtypeset[] E_INIT("=typeset");
|
||||
#define Ttypeset (Tgtypeset + 1)
|
||||
EXTERN const char Tdgtypeset[] E_INIT("^=typeset");
|
||||
#define Ttypeset (Tdgtypeset + 2)
|
||||
#define Tugo (Taugo + 1)
|
||||
EXTERN const char Tunalias[] E_INIT("unalias");
|
||||
#define Tunexpected (TELIF_unexpected + 6)
|
||||
EXTERN const char Tunknown_option[] E_INIT("unknown option");
|
||||
EXTERN const char Tuser_sp1[] E_INIT("user ");
|
||||
#define Tuser_sp1 (Tuser_sp2 + 1)
|
||||
EXTERN const char Tuser_sp2[] E_INIT(" user ");
|
||||
#define Twrite (Tshf_write + 4)
|
||||
EXTERN const char Tf__S[] E_INIT(" %S");
|
||||
EXTERN const char Tf__d[] E_INIT(" %d");
|
||||
#define Tf__d (Tf_sd + 2)
|
||||
EXTERN const char Tf__ss[] E_INIT(" %s%s");
|
||||
EXTERN const char Tf__sN[] E_INIT(" %s\n");
|
||||
#define Tf__sN (Tf_s_s_sN + 5)
|
||||
EXTERN const char Tf_sSs[] E_INIT("%s/%s");
|
||||
EXTERN const char Tf_T[] E_INIT("%T");
|
||||
#define Tf_T (Tf_s_T + 3)
|
||||
EXTERN const char Tf_dN[] E_INIT("%d\n");
|
||||
EXTERN const char Tf_s_[] E_INIT("%s ");
|
||||
EXTERN const char Tf_s_T[] E_INIT("%s %T");
|
||||
EXTERN const char Tf_s_s_sN[] E_INIT("%s %s %s\n");
|
||||
EXTERN const char Tf_s_s[] E_INIT("%s %s");
|
||||
EXTERN const char Tf_s_sD_s[] E_INIT("%s %s: %s");
|
||||
#define Tf_s_s (Tf_sD_s_s + 4)
|
||||
#define Tf_s_sD_s (Tf_cant + 6)
|
||||
EXTERN const char Tf_optfoo[] E_INIT("%s%s-%c: %s");
|
||||
EXTERN const char Tf_sD_[] E_INIT("%s: ");
|
||||
EXTERN const char Tf_szs[] E_INIT("%s: %zd %s");
|
||||
|
@ -976,18 +970,18 @@ EXTERN const char Tf_nonnum[] E_INIT("non-numeric %s %s '%s'");
|
|||
#endif
|
||||
EXTERN const char Tf_S_[] E_INIT("%S ");
|
||||
#define Tf_S (Tf__S + 1)
|
||||
EXTERN const char Tf_lu[] E_INIT("%lu");
|
||||
#define Tf_lu (Tf_toolarge + 17)
|
||||
EXTERN const char Tf_toolarge[] E_INIT("%s %s too large: %lu");
|
||||
EXTERN const char Tf_ldfailed[] E_INIT("%s %s(%d, %ld) failed: %s");
|
||||
#define Tf_ss (Tf__ss + 1)
|
||||
#define Tf_ss (Tf_sss + 2)
|
||||
EXTERN const char Tf_sss[] E_INIT("%s%s%s");
|
||||
EXTERN const char Tf_sD_s_sD_s[] E_INIT("%s: %s %s: %s");
|
||||
EXTERN const char Tf_toomany[] E_INIT("too many %ss\n");
|
||||
EXTERN const char Tf_sd[] E_INIT("%s %d");
|
||||
#define Tf_s (Tf__ss + 3)
|
||||
#define Tf_s (Tf_temp + 28)
|
||||
EXTERN const char Tft_end[] E_INIT("%;");
|
||||
EXTERN const char Tft_R[] E_INIT("%R");
|
||||
#define Tf_d (Tf__d + 1)
|
||||
#define Tf_d (Tf_sd + 3)
|
||||
EXTERN const char Tf_sD_s_qs[] E_INIT("%s: %s '%s'");
|
||||
EXTERN const char Tf_ro[] E_INIT("read-only: %s");
|
||||
EXTERN const char Tf_flags[] E_INIT("%s: flags 0x%X");
|
||||
|
@ -996,8 +990,8 @@ EXTERN const char Tf_ssfaileds[] E_INIT("%s: %s failed: %s");
|
|||
EXTERN const char Tf_sD_sD_s[] E_INIT("%s: %s: %s");
|
||||
EXTERN const char Tf__c_[] E_INIT("-%c ");
|
||||
EXTERN const char Tf_sD_s_s[] E_INIT("%s: %s %s");
|
||||
#define Tf_sN (Tf__sN + 1)
|
||||
#define Tf_sD_s (Tf_s_sD_s + 3)
|
||||
#define Tf_sN (Tf_s_s_sN + 6)
|
||||
#define Tf_sD_s (Tf_temp + 24)
|
||||
EXTERN const char T_devtty[] E_INIT("/dev/tty");
|
||||
#else /* helpers for string pooling */
|
||||
#define T4spaces " "
|
||||
|
@ -1018,7 +1012,8 @@ EXTERN const char T_devtty[] E_INIT("/dev/tty");
|
|||
#define Tbsize "bsize"
|
||||
#define Tbad_sig_ss "%s: bad signal '%s'"
|
||||
#define Tbad_sig_s "bad signal '%s'"
|
||||
#define Tgbuiltin "=builtin"
|
||||
#define T__builtin "-\\builtin"
|
||||
#define T_builtin "\\builtin"
|
||||
#define Tbuiltin "builtin"
|
||||
#define Toomem "can't allocate %zu data bytes"
|
||||
#define Tcant_cd "restricted shell - can't cd"
|
||||
|
@ -1028,11 +1023,12 @@ EXTERN const char T_devtty[] E_INIT("/dev/tty");
|
|||
#define Tbcat "!cat"
|
||||
#define Tcat "cat"
|
||||
#define Tcd "cd"
|
||||
#define T_command "-command"
|
||||
#define Tcommand "command"
|
||||
#define Tcreate "create"
|
||||
#define TELIF_unexpected "TELIF unexpected"
|
||||
#define TEXECSHELL "EXECSHELL"
|
||||
#define Tsgexport "*=export"
|
||||
#define Tdsgexport "^*=export"
|
||||
#define Texport "export"
|
||||
#ifdef __OS2__
|
||||
#define Textproc "extproc"
|
||||
|
@ -1045,7 +1041,7 @@ EXTERN const char T_devtty[] E_INIT("/dev/tty");
|
|||
#define TFPATH "FPATH"
|
||||
#define T_function " function"
|
||||
#define Tfunction "function"
|
||||
#define T_funny_command "funny $() command"
|
||||
#define T_funny_command "funny $()-command"
|
||||
#define Tgetopts "getopts"
|
||||
#define Thistory "history"
|
||||
#define Tintovfl "integer overflow %zu %c %zu prevented"
|
||||
|
@ -1067,7 +1063,7 @@ EXTERN const char T_devtty[] E_INIT("/dev/tty");
|
|||
#define TpVv "Vpv"
|
||||
#define TPWD "PWD"
|
||||
#define Tread "read"
|
||||
#define Tsgreadonly "*=readonly"
|
||||
#define Tdsgreadonly "^*=readonly"
|
||||
#define Treadonly "readonly"
|
||||
#define Tredirection_dup "can't finish (dup) redirection"
|
||||
#define Tredirection "redirection"
|
||||
|
@ -1089,7 +1085,7 @@ EXTERN const char T_devtty[] E_INIT("/dev/tty");
|
|||
#define Ttrue "true"
|
||||
#define Ttty_fd_dupof "dup of tty fd"
|
||||
#define Ttty_fd "tty fd"
|
||||
#define Tgtypeset "=typeset"
|
||||
#define Tdgtypeset "^=typeset"
|
||||
#define Ttypeset "typeset"
|
||||
#define Tugo "ugo"
|
||||
#define Tunalias "unalias"
|
||||
|
@ -1330,7 +1326,7 @@ EXTERN sigset_t sm_default, sm_sigchld;
|
|||
|
||||
/* name of called builtin function (used by error functions) */
|
||||
EXTERN const char *builtin_argv0;
|
||||
/* is called builtin SPEC_BI? (also KEEPASN, odd use though) */
|
||||
/* is called builtin a POSIX special builtin? (error functions only) */
|
||||
EXTERN bool builtin_spec;
|
||||
|
||||
/* current working directory */
|
||||
|
@ -1500,6 +1496,8 @@ EXTERN bool last_lookup_was_array;
|
|||
#define SPEC_BI BIT(12) /* a POSIX special builtin */
|
||||
#define LOWER_BI BIT(13) /* (with LOW_BI) override even w/o flags */
|
||||
#define LOW_BI BIT(14) /* external utility overrides built-in one */
|
||||
#define DECL_UTIL BIT(15) /* is declaration utility */
|
||||
#define DECL_FWDR BIT(16) /* is declaration utility forwarder */
|
||||
|
||||
/*
|
||||
* Attributes that can be set by the user (used to decide if an unset
|
||||
|
@ -2019,7 +2017,8 @@ int glob_str(char *, XPtrV *, bool);
|
|||
char *do_tilde(char *);
|
||||
/* exec.c */
|
||||
int execute(struct op * volatile, volatile int, volatile int * volatile);
|
||||
int shcomexec(const char **);
|
||||
int c_builtin(const char **);
|
||||
struct tbl *get_builtin(const char *);
|
||||
struct tbl *findfunc(const char *, uint32_t, bool);
|
||||
int define(const char *, struct op *);
|
||||
const char *builtin(const char *, int (*)(const char **));
|
||||
|
@ -2086,8 +2085,6 @@ int c_times(const char **);
|
|||
int timex(struct op *, int, volatile int *);
|
||||
void timex_hook(struct op *, char ** volatile *);
|
||||
int c_exec(const char **);
|
||||
/* dummy function (just need pointer value), special case in comexec() */
|
||||
#define c_builtin shcomexec
|
||||
int c_test(const char **);
|
||||
#if HAVE_MKNOD
|
||||
int c_mknod(const char **);
|
||||
|
@ -2303,7 +2300,6 @@ char *shf_smprintf(const char *, ...)
|
|||
ssize_t shf_vfprintf(struct shf *, const char *, va_list)
|
||||
MKSH_A_FORMAT(__printf__, 2, 0);
|
||||
/* syn.c */
|
||||
int assign_command(const char *, bool) MKSH_A_PURE;
|
||||
void initkeywords(void);
|
||||
struct op *compile(Source *, bool);
|
||||
bool parse_usec(const char *, struct timeval *);
|
||||
|
|
16
sh_flags.opt
16
sh_flags.opt
|
@ -1,5 +1,5 @@
|
|||
/*-
|
||||
* Copyright (c) 2013, 2014, 2015
|
||||
* Copyright (c) 2013, 2014, 2015, 2017
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -19,7 +19,7 @@
|
|||
*/
|
||||
|
||||
@SHFLAGS_DEFNS
|
||||
__RCSID("$MirOS: src/bin/mksh/sh_flags.opt,v 1.4 2015/12/12 21:08:44 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh_flags.opt,v 1.5 2017/02/18 02:33:15 tg Exp $");
|
||||
@SHFLAGS_ENUMS
|
||||
#define FN(sname,cname,flags,ochar) cname,
|
||||
#define F0(sname,cname,flags,ochar) cname = 0,
|
||||
|
@ -52,7 +52,7 @@ FN("bgnice", FBGNICE, OF_ANY
|
|||
FN("braceexpand", FBRACEEXPAND, OF_ANY
|
||||
|
||||
/* ./. Emacs command line editing mode */
|
||||
>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
|
||||
>|!MKSH_NO_CMDLINE_EDITING
|
||||
FN("emacs", FEMACS, OF_ANY
|
||||
|
||||
/* -e quit on error */
|
||||
|
@ -60,7 +60,7 @@ FN("emacs", FEMACS, OF_ANY
|
|||
FN("errexit", FERREXIT, OF_ANY
|
||||
|
||||
/* ./. Emacs command line editing mode, gmacs variant */
|
||||
>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
|
||||
>|!MKSH_NO_CMDLINE_EDITING
|
||||
FN("gmacs", FGMACS, OF_ANY
|
||||
|
||||
/* ./. reading EOF does not exit */
|
||||
|
@ -160,19 +160,19 @@ FN("utf8-mode", FUNICODE, OF_ANY
|
|||
FN("verbose", FVERBOSE, OF_ANY
|
||||
|
||||
/* ./. Vi command line editing mode */
|
||||
>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
|
||||
>|!MKSH_NO_CMDLINE_EDITING
|
||||
FN("vi", FVI, OF_ANY
|
||||
|
||||
/* ./. enable ESC as file name completion character (non-standard) */
|
||||
>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
|
||||
>|!MKSH_NO_CMDLINE_EDITING
|
||||
FN("vi-esccomplete", FVIESCCOMPLETE, OF_ANY
|
||||
|
||||
/* ./. enable Tab as file name completion character (non-standard) */
|
||||
>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
|
||||
>|!MKSH_NO_CMDLINE_EDITING
|
||||
FN("vi-tabcomplete", FVITABCOMPLETE, OF_ANY
|
||||
|
||||
/* ./. always read in raw mode (no effect) */
|
||||
>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
|
||||
>|!MKSH_NO_CMDLINE_EDITING
|
||||
FN("viraw", FVIRAW, OF_ANY
|
||||
|
||||
/* -x execution trace (display commands as they are run) */
|
||||
|
|
58
syn.c
58
syn.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016
|
||||
* 2011, 2012, 2013, 2014, 2015, 2016, 2017
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.115 2016/09/01 12:59:12 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.118 2017/03/19 20:59:29 tg Exp $");
|
||||
|
||||
struct nesting_state {
|
||||
int start_token; /* token than began nesting (eg, FOR) */
|
||||
|
@ -244,11 +244,15 @@ nested(int type, int smark, int emark)
|
|||
return (block(type, t, NULL));
|
||||
}
|
||||
|
||||
static const char builtin_cmd[] = {
|
||||
QCHAR, '\\', CHAR, 'b', CHAR, 'u', CHAR, 'i',
|
||||
CHAR, 'l', CHAR, 't', CHAR, 'i', CHAR, 'n', EOS
|
||||
};
|
||||
static const char let_cmd[] = {
|
||||
QCHAR, 'l', CHAR, 'e', CHAR, 't', CHAR, ']', EOS
|
||||
CHAR, 'l', CHAR, 'e', CHAR, 't', EOS
|
||||
};
|
||||
static const char setA_cmd0[] = {
|
||||
QCHAR, 's', CHAR, 'e', CHAR, 't', EOS
|
||||
CHAR, 's', CHAR, 'e', CHAR, 't', EOS
|
||||
};
|
||||
static const char setA_cmd1[] = {
|
||||
CHAR, '-', CHAR, 'A', EOS
|
||||
|
@ -289,11 +293,11 @@ get_command(int cf)
|
|||
t->lineno = source->line;
|
||||
goto get_command_start;
|
||||
while (/* CONSTCOND */ 1) {
|
||||
bool check_assign_cmd;
|
||||
bool check_decl_utility;
|
||||
|
||||
if (XPsize(args) == 0) {
|
||||
get_command_start:
|
||||
check_assign_cmd = true;
|
||||
check_decl_utility = true;
|
||||
cf = sALIAS | CMDASN;
|
||||
} else if (t->u.evalflags)
|
||||
cf = CMDWORD | CMDASN;
|
||||
|
@ -311,16 +315,15 @@ get_command(int cf)
|
|||
|
||||
case LWORD:
|
||||
ACCEPT;
|
||||
/*
|
||||
* the iopn == 0 and XPsize(vars) == 0 are
|
||||
* dubious but AT&T ksh acts this way
|
||||
*/
|
||||
if (iopn == 0 && XPsize(vars) == 0 &&
|
||||
check_assign_cmd) {
|
||||
if (assign_command(ident, false))
|
||||
if (check_decl_utility) {
|
||||
struct tbl *tt = get_builtin(ident);
|
||||
uint32_t flag;
|
||||
|
||||
flag = tt ? tt->flag : 0;
|
||||
if (flag & DECL_UTIL)
|
||||
t->u.evalflags = DOVACHECK;
|
||||
else if (strcmp(ident, Tcommand) != 0)
|
||||
check_assign_cmd = false;
|
||||
if (!(flag & DECL_FWDR))
|
||||
check_decl_utility = false;
|
||||
}
|
||||
if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
|
||||
is_wdvarassign(yylval.cp))
|
||||
|
@ -343,6 +346,7 @@ get_command(int cf)
|
|||
tcp[wdscan(tcp, EOS) - tcp - 3] = EOS;
|
||||
|
||||
/* construct new args strings */
|
||||
XPput(args, wdcopy(builtin_cmd, ATEMP));
|
||||
XPput(args, wdcopy(setA_cmd0, ATEMP));
|
||||
XPput(args, wdcopy(setA_cmd1, ATEMP));
|
||||
XPput(args, tcp);
|
||||
|
@ -412,6 +416,7 @@ get_command(int cf)
|
|||
}
|
||||
t = newtp(TCOM);
|
||||
t->lineno = lno;
|
||||
XPput(args, wdcopy(builtin_cmd, ATEMP));
|
||||
XPput(args, wdcopy(let_cmd, ATEMP));
|
||||
XPput(args, yylval.cp);
|
||||
break;
|
||||
|
@ -937,29 +942,6 @@ compile(Source *s, bool skiputf8bom)
|
|||
return (outtree);
|
||||
}
|
||||
|
||||
/*-
|
||||
* This kludge exists to take care of sh/AT&T ksh oddity in which
|
||||
* the arguments of alias/export/readonly/typeset have no field
|
||||
* splitting, file globbing, or (normal) tilde expansion done.
|
||||
* AT&T ksh seems to do something similar to this since
|
||||
* $ touch a=a; typeset a=[ab]; echo "$a"
|
||||
* a=[ab]
|
||||
* $ x=typeset; $x a=[ab]; echo "$a"
|
||||
* a=a
|
||||
* $
|
||||
*/
|
||||
int
|
||||
assign_command(const char *s, bool docommand)
|
||||
{
|
||||
if (!*s)
|
||||
return (0);
|
||||
return ((strcmp(s, Talias) == 0) ||
|
||||
(strcmp(s, Texport) == 0) ||
|
||||
(strcmp(s, Treadonly) == 0) ||
|
||||
(docommand && (strcmp(s, Tcommand) == 0)) ||
|
||||
(strcmp(s, Ttypeset) == 0));
|
||||
}
|
||||
|
||||
/* Check if we are in the middle of reading an alias */
|
||||
static int
|
||||
inalias(struct source *s)
|
||||
|
|
Loading…
Reference in New Issue