-DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 \
-DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \
-DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 \
- -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=505
+ -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=506
include $(BUILD_EXECUTABLE)
-# Makefile fragment for building mksh R50 2015/03/01
+# Makefile fragment for building mksh R50 2015/04/19
PROG= mksh
MAN= mksh.1
NONSRCS_NOINST= Build.sh Makefile Rebuild.sh check.pl check.t test.sh
CC= /huge-ssd/aosp-arm64/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/*-gcc
CFLAGS= -fno-exceptions -Wno-multichar -fpic -fPIE -ffunction-sections -fdata-sections -funwind-tables -fstack-protector -Wa,--noexecstack -Werror=format-security -fno-short-enums -Wno-unused-but-set-variable -fno-builtin-sin -fno-strict-volatile-bitfields -Wno-psabi -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -g -Wstrict-aliasing=2 -fgcse-after-reload -frerun-cse-after-loop -frename-registers -Os -fomit-frame-pointer -fno-strict-aliasing -Wno-deprecated-declarations -fno-asynchronous-unwind-tables -fstack-protector-strong -fwrapv
-CPPFLAGS= -I. -I'../src' -isystem /huge-ssd/aosp-arm64/bionic/libc/arch-arm64/include -isystem /huge-ssd/aosp-arm64/bionic/libc/include -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi/asm-arm64 -isystem /huge-ssd/aosp-arm64/bionic/libm/include -isystem /huge-ssd/aosp-arm64/bionic/libm/include/arm64 -D_FORTIFY_SOURCE=2 -include /huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/AndroidConfig.h -I/huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/ -DANDROID -DNDEBUG -UDEBUG -DDEBUG_LEAKS -DMKSH_ASSUME_UTF8 -DMKSH_CONSERVATIVE_FDS -DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN -DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 -DHAVE_ATTRIBUTE_NORETURN=1 -DHAVE_ATTRIBUTE_PURE=1 -DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 -DHAVE_SYS_TIME_H=1 -DHAVE_TIME_H=1 -DHAVE_BOTH_TIME_H=1 -DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 -DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 -DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 -DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 -DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 -DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_ERRLIST=0 -DHAVE_SYS_SIGNAME=1 -DHAVE_SYS_SIGLIST=1 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 -DHAVE_GETRUSAGE=1 -DHAVE_GETSID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_ISSETUGID=0 -DHAVE_KILLPG=1 -DHAVE_MEMMOVE=1 -DHAVE_MKNOD=0 -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=0 -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=505
+CPPFLAGS= -I. -I'../src' -isystem /huge-ssd/aosp-arm64/bionic/libc/arch-arm64/include -isystem /huge-ssd/aosp-arm64/bionic/libc/include -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi/asm-arm64 -isystem /huge-ssd/aosp-arm64/bionic/libm/include -isystem /huge-ssd/aosp-arm64/bionic/libm/include/arm64 -D_FORTIFY_SOURCE=2 -include /huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/AndroidConfig.h -I/huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/ -DANDROID -DNDEBUG -UDEBUG -DDEBUG_LEAKS -DMKSH_ASSUME_UTF8 -DMKSH_CONSERVATIVE_FDS -DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN -DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 -DHAVE_ATTRIBUTE_NORETURN=1 -DHAVE_ATTRIBUTE_PURE=1 -DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 -DHAVE_SYS_TIME_H=1 -DHAVE_TIME_H=1 -DHAVE_BOTH_TIME_H=1 -DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 -DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 -DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 -DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 -DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 -DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_ERRLIST=0 -DHAVE_SYS_SIGNAME=1 -DHAVE_SYS_SIGLIST=1 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 -DHAVE_GETRUSAGE=1 -DHAVE_GETSID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_ISSETUGID=0 -DHAVE_KILLPG=1 -DHAVE_MEMMOVE=1 -DHAVE_MKNOD=0 -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=0 -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=506
LDFLAGS= -nostdlib -Bdynamic -fPIE -pie -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined /huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib/crtbegin_dynamic.o
LIBS= -L/huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib -Wl,-rpath-link=/huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib -Wl,--no-whole-archive /huge-ssd/aosp-arm64/out/target/product/flounder/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a -lc /huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib/crtend_android.o
#!/bin/sh
-srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669.2.2 2015/03/01 15:42:50 tg Exp $'
+srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669.2.4 2015/04/19 19:18:08 tg Exp $'
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013, 2014
-# Thorsten Glaser <tg@mirbsd.org>
+# 2011, 2012, 2013, 2014, 2015
+# Thorsten “mirabilos” Glaser <tg@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
# are retained or reproduced in an accompanying document, permission
ac_testn can_lfs_aix '!' can_lfs 0 "... with -D_LARGE_FILES=1" <lft.c
test 1 = $HAVE_CAN_LFS_AIX || CPPFLAGS=$save_CPPFLAGS
fi
+rm -f lft.c
rmf lft* # end of large file support test
#
HAVE_LINK_WORKS=x
ac_testinit link_works '' 'checking if the final link command may succeed'
fv=1
- cat >conftest.c <<-'EOF'
+ cat >conftest.c <<-EOF
#define EXTERN
#define MKSH_INCLUDES_ONLY
#include "sh.h"
- __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.669.2.2 2015/03/01 15:42:50 tg Exp $");
- int main(void) { printf("Hello, World!\n"); return (isatty(0)); }
+ __RCSID("$srcversion");
+ int main(void) { printf("Hello, World!\\n"); return (isatty(0)); }
EOF
case $cm in
llvm)
cta(uari_wrap_32_bit,
(mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3) >
(mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 4));
-#define NUM 21
+#define NUM 22
#else
-#define NUM 15
+#define NUM 16
#endif
/* these are always required */
cta(ari_is_signed, (mksh_ari_t)-1 < (mksh_ari_t)0);
cta(sizet_funcptr_same_size, sizeof(size_t) == sizeof(void (*)(void)));
/* our formatting routines assume this */
cta(ptr_fits_in_long, sizeof(size_t) <= sizeof(long));
+cta(ari_fits_in_long, sizeof(mksh_ari_t) <= sizeof(long));
/* for struct alignment people */
char padding[64 - NUM];
};
addsrcs USE_PRINTF_BUILTIN printf.c
test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
-add_cppflags -DMKSH_BUILD_R=505
+add_cppflags -DMKSH_BUILD_R=506
$e $bi$me: Finished configuration testing, now producing output.$ao
-# $MirOS: src/bin/mksh/check.pl,v 1.37 2014/08/19 07:43:32 tg Exp $
+# $MirOS: src/bin/mksh/check.pl,v 1.37.2.1 2015/04/12 22:32:16 tg Exp $
# $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
-# 2012, 2013, 2014
+# 2012, 2013, 2014, 2015
# Thorsten Glaser <tg@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
}
push(@argv, $temps) if defined $test{'script'};
- #XXX realpathise, use which/whence -p, or sth. like that
+ #XXX realpathise, use command -v/whence -p/which, or sth. like that
#XXX if !$program_kludge, we get by with not doing it for now tho
$new_env{'__progname'} = $argv[0];
-# $MirOS: src/bin/mksh/check.t,v 1.667.2.3 2015/03/01 15:42:51 tg Exp $
+# $MirOS: src/bin/mksh/check.t,v 1.667.2.7 2015/04/19 19:18:10 tg Exp $
# -*- mode: sh -*-
#-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout:
- @(#)MIRBSD KSH R50 2015/03/01
+ @(#)MIRBSD KSH R50 2015/04/19
description:
Check version of shell.
stdin:
category: shell:legacy-no
---
expected-stdout:
- @(#)LEGACY KSH R50 2015/03/01
+ @(#)LEGACY KSH R50 2015/04/19
description:
Check version of legacy shell.
stdin:
expected-stdout:
hello world
---
+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
+ print -r -- "$x,$y"
+ }
+ foo 'bar - baz'
+expected-stdout:
+ bar - baz,z
+---
name: arith-lazy-1
description:
Check that only one side of ternary operator is evaluated
1a:
2: x[A B]
---
+name: read-IFS-2
+description:
+ Complex tests, IFS either colon (IFS-NWS) or backslash (tricky)
+stdin:
+ n=0
+ showargs() { print -nr "$1"; shift; for s_arg in "$@"; do print -nr -- " [$s_arg]"; done; print; }
+ (IFS=\\ a=\<\\\>; showargs 3 $a)
+ (IFS=: b=\<:\>; showargs 4 $b)
+ print -r '<\>' | (IFS=\\ read f g; showargs 5 "$f" "$g")
+ print -r '<\\>' | (IFS=\\ read f g; showargs 6 "$f" "$g")
+ print '<\\\n>' | (IFS=\\ read f g; showargs 7 "$f" "$g")
+ print -r '<\>' | (IFS=\\ read f; showargs 8 "$f")
+ print -r '<\\>' | (IFS=\\ read f; showargs 9 "$f")
+ print '<\\\n>' | (IFS=\\ read f; showargs 10 "$f")
+ print -r '<\>' | (IFS=\\ read -r f g; showargs 11 "$f" "$g")
+ print -r '<\\>' | (IFS=\\ read -r f g; showargs 12 "$f" "$g")
+ print '<\\\n>' | (IFS=\\ read -r f g; showargs 13 "$f" "$g")
+ print -r '<\>' | (IFS=\\ read -r f; showargs 14 "$f")
+ print -r '<\\>' | (IFS=\\ read -r f; showargs 15 "$f")
+ print '<\\\n>' | (IFS=\\ read -r f; showargs 16 "$f")
+ print -r '<:>' | (IFS=: read f g; showargs 17 "$f" "$g")
+ print -r '<::>' | (IFS=: read f g; showargs 18 "$f" "$g")
+ print '<:\n>' | (IFS=: read f g; showargs 19 "$f" "$g")
+ print -r '<:>' | (IFS=: read f; showargs 20 "$f")
+ print -r '<::>' | (IFS=: read f; showargs 21 "$f")
+ print '<:\n>' | (IFS=: read f; showargs 22 "$f")
+ print -r '<:>' | (IFS=: read -r f g; showargs 23 "$f" "$g")
+ print -r '<::>' | (IFS=: read -r f g; showargs 24 "$f" "$g")
+ print '<:\n>' | (IFS=: read -r f g; showargs 25 "$f" "$g")
+ print -r '<:>' | (IFS=: read -r f; showargs 26 "$f")
+ print -r '<::>' | (IFS=: read -r f; showargs 27 "$f")
+ print '<:\n>' | (IFS=: read -r f; showargs 28 "$f")
+expected-stdout:
+ 3 [<] [>]
+ 4 [<] [>]
+ 5 [<] [>]
+ 6 [<] [>]
+ 7 [<>] []
+ 8 [<>]
+ 9 [<\>]
+ 10 [<>]
+ 11 [<] [>]
+ 12 [<] [\>]
+ 13 [<] []
+ 14 [<\>]
+ 15 [<\\>]
+ 16 [<]
+ 17 [<] [>]
+ 18 [<] [:>]
+ 19 [<] []
+ 20 [<:>]
+ 21 [<::>]
+ 22 [<]
+ 23 [<] [>]
+ 24 [<] [:>]
+ 25 [<] []
+ 26 [<:>]
+ 27 [<::>]
+ 28 [<]
+---
name: read-ksh-1
description:
If no var specified, REPLY is used
{220->> Bitte keine Werbung einwerfen! <<\r\r}
{220 Who do you wanna pretend to be today?\r}
---
+name: print-crlf
+description:
+ Check that CR+LF is shown and read as-is
+stdin:
+ cat >foo <<-'EOF'
+ x='bar\r
+ ' #\r
+ if test x"$KSH_VERSION" = x""; then #\r
+ printf '<%s>' "$x" #\r
+ else #\r
+ print -nr -- "<$x>" #\r
+ fi #\r
+ EOF
+ echo "[$("$__progname" foo)]"
+ "$__progname" foo | while IFS= read -r line; do
+ print -r -- "{$line}"
+ done
+expected-stdout:
+ [<bar\r
+ >]
+ {<bar\r}
+---
+name: print-lf
+description:
+ Check that LF-only is shown and read as-is
+stdin:
+ cat >foo <<-'EOF'
+ x='bar
+ ' #
+ if test x"$KSH_VERSION" = x""; then #
+ printf '<%s>' "$x" #
+ else #
+ print -nr -- "<$x>" #
+ fi #
+ EOF
+ echo "[$("$__progname" foo)]"
+ "$__progname" foo | while IFS= read -r line; do
+ print -r -- "{$line}"
+ done
+expected-stdout:
+ [<bar
+ >]
+ {<bar}
+---
name: print-nul-chars
description:
Check handling of NUL characters for print and COMSUB
expected-stderr-pattern:
/\.: missing argument.*\n.*\.: missing argument/
---
-name: alias-function-no-conflict
+name: alias-function-no-conflict-legacy
description:
- make aliases not conflict with functions
- note: for ksh-like functions, the order of preference is
- different; bash outputs baz instead of bar in line 2 below
+ make aliases not conflict with functions, legacy version:
+ undefine these aliases upon definition of the function
+ note: for ksh functions, the order of preference differs in GNU bash
stdin:
+ # POSIX function overrides and removes alias
alias foo='echo bar'
+ foo
foo() {
echo baz
}
+ foo
+ unset -f foo
+ foo 2>/dev/null || echo rab
+ # alias overrides ksh function
alias korn='echo bar'
+ korn
function korn {
echo baz
}
- foo
korn
- unset -f foo
- foo 2>/dev/null || echo rab
+ # alias temporarily overrides POSIX function
+ bla() {
+ echo bfn
+ }
+ bla
+ alias bla='echo bal'
+ bla
+ unalias bla
+ bla
expected-stdout:
- baz
bar
+ baz
rab
+ bar
+ bar
+ bfn
+ bal
+ bfn
---
name: bash-function-parens
description:
echo "$1 {"
echo ' echo "bar='\''$0'\'\"
echo '}'
- echo ${2:-foo}
+ print -r -- "${2:-foo}"
}
mk 'function foo' >f-korn
mk 'foo ()' >f-dash
mk 'function foo ()' >f-bash
- mk 'function stop ()' stop >f-stop
+ # pre-R51 can do without a backslash in front of the second stop
+ mk 'function stop ()' 'stop' >f-stop
print '#!'"$__progname"'\nprint -r -- "${0%/f-argh}"' >f-argh
chmod +x f-*
u=$(./f-argh)
Verify that file descriptors > 2 are private for Korn shells
AT&T ksh93 does this still, which means we must keep it as well
category: shell:legacy-no
-file-setup: file 644 "test.sh"
- echo >&3 Fowl
stdin:
- exec 3>&1
- "$__progname" test.sh
+ 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-exit: e != 0
expected-stderr-pattern:
- /bad file descriptor/
+ /E: open /
---
name: fd-cloexec-2
description:
Verify that file descriptors > 2 are not private for POSIX shells
See Debian Bug #154540, Closes: #499139
-file-setup: file 644 "test.sh"
- echo >&3 Fowl
stdin:
- test -n "$POSH_VERSION" || set -o sh
- exec 3>&1
- "$__progname" test.sh
+ 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
+ test -n "$POSH_VERSION" || set -o posix
+ exec 9>&1
+ ./cld
expected-stdout:
Fowl
---
description:
Verify that file descriptors > 2 are not private for LEGACY KSH
category: shell:legacy-yes
-file-setup: file 644 "test.sh"
- echo >&3 Fowl
stdin:
- exec 3>&1
- "$__progname" test.sh
+ 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
---
[(p:sh)(f1:sh)(f2:sh)] print '(o1:shx)'
[(p:sh)(f1:sh)(f2:sh)] set +x
---
+name: fksh-flags-legacy
+description:
+ Check that even FKSH functions share the shell flags
+stdin:
+ [[ $KSH_VERSION = Version* ]] && set +B
+ foo() {
+ set +f
+ set -e
+ echo 2 "${-/s}" .
+ }
+ set -fh
+ echo 1 "${-/s}" .
+ foo
+ echo 3 "${-/s}" .
+expected-stdout:
+ 1 fh .
+ 2 eh .
+ 3 eh .
+---
+name: fsh-flags
+description:
+ Check that !FKSH functions share the shell flags
+stdin:
+ [[ $KSH_VERSION = Version* ]] && set +B
+ foo() {
+ set +f
+ set -e
+ echo 2 "${-/s}" .
+ }
+ set -fh
+ echo 1 "${-/s}" .
+ foo
+ echo 3 "${-/s}" .
+expected-stdout:
+ 1 fh .
+ 2 eh .
+ 3 eh .
+---
# $Id$
-# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89.2.1 2015/01/11 22:39:44 tg Exp $
+# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89.2.3 2015/04/12 22:32:22 tg Exp $
#-
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015
#-
# ${ENV:-~/.mkshrc}: mksh initialisation file for interactive shells
-# catch non-mksh (including lksh) trying to shell this file
-case $KSH_VERSION in
+# catch non-mksh (including lksh) trying to run this file
+case ${KSH_VERSION:-} in
*MIRBSD\ KSH*) ;;
*) return 0 ;;
esac
-PS1='#'; (( USER_ID )) && PS1='$'; [[ ${HOSTNAME:=$(ulimit -c 0; hostname -s \
- 2>/dev/null)} = *([ ]|localhost) ]] && HOSTNAME=$(ulimit -c 0; hostname \
- 2>/dev/null); : ${EDITOR:=/bin/ed} ${HOSTNAME:=nil} ${TERM:=vt100}
-: ${MKSH:=$(whence -p mksh)}; PS4='[$EPOCHREALTIME] '; PS1=$'\001\r''${|
+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:=$(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''${|
local e=$?
(( e )) && REPLY+="$e|"
- REPLY+=${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \?)}
- REPLY+=@${HOSTNAME%%.*}:
+ REPLY+=${USER}@${HOSTNAME%%.*}:
local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~}
local m=${%d} n p=...; (( m > 0 )) || m=${#d}
REPLY+=$p$d
return $e
-} '"$PS1 "; export EDITOR HOSTNAME MKSH TERM USER
+} '"$PS1 "
alias ls=ls
unalias ls
alias l='ls -F'
alias ll='l -l'
alias lo='l -alo'
alias doch='sudo mksh -c "$(fc -ln -1)"'
-whence -p rot13 >/dev/null || alias rot13='tr \
+command -v rot13 >/dev/null || alias rot13='tr \
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \
nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
-if whence -p hd >/dev/null; then :; elif whence -p hexdump >/dev/null; then
+if command -v hd >/dev/null; then :; elif command -v hexdump >/dev/null; then
function hd {
hexdump -e '"%08.8_ax " 8/1 "%02X " " - " 8/1 "%02X "' \
-e '" |" "%_p"' -e '"|\n"' "$@"
while (( i < ${#line[*]} )); do
hv=${line[i++]}
if (( (pos & 15) == 0 )); then
- (( pos )) && print -r -- "$dasc|"
+ (( pos )) && \
+ print -r -- "$dasc|"
print -n "${pos#16#} "
dasc=' |'
fi
else
dasc+=${line[i-1]#1#}
fi
- (( (pos++ & 15) == 7 )) && print -n -- '- '
+ (( (pos++ & 15) == 7 )) && \
+ print -n -- '- '
done
while (( pos & 15 )); do
print -n ' '
- (( (pos++ & 15) == 7 )) && print -n -- '- '
+ (( (pos++ & 15) == 7 )) && \
+ print -n -- '- '
done
(( hv == 2147483647 )) || print -r -- "$dasc|"
fi; }
# Berkeley C shell compatible dirs, popd, and pushd functions
# Z shell compatible chpwd() hook, used to update DIRSTACK[0]
-DIRSTACKBASE=$(realpath ~/. 2>/dev/null || print -nr -- "${HOME:-/}")
+DIRSTACKBASE=$(realpath ~/. 2>/dev/null || \
+ print -nr -- "${HOME:-/}")
set -A DIRSTACK
function chpwd {
- DIRSTACK[0]=$(realpath . 2>/dev/null || print -r -- "$PWD")
+ DIRSTACK[0]=$(realpath . 2>/dev/null || \
+ print -r -- "$PWD")
[[ $DIRSTACKBASE = ?(*/) ]] || \
DIRSTACK[0]=${DIRSTACK[0]/#$DIRSTACKBASE/~}
:
-/* $OpenBSD: edit.c,v 1.39 2013/12/17 16:37:05 deraadt Exp $ */
+/* $OpenBSD: edit.c,v 1.40 2015/03/12 10:20:30 sthen Exp $ */
/* $OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $ */
-/* $OpenBSD: emacs.c,v 1.49 2015/02/16 01:44:41 tedu Exp $ */
+/* $OpenBSD: emacs.c,v 1.50 2015/03/25 12:10:52 jca Exp $ */
/* $OpenBSD: vi.c,v 1.28 2013/12/18 16:45:46 deraadt Exp $ */
/*-
#ifndef MKSH_NO_CMDLINE_EDITING
-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276.2.3 2015/03/01 15:42:56 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276.2.5 2015/04/12 22:32:22 tg Exp $");
/*
* in later versions we might use libtermcap for this, but since external
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.158.2.4 2015/03/01 15:42:58 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.158.2.5 2015/04/12 22:32:24 tg Exp $");
/*
* string expansion
struct ioword *io = *t->ioact;
char *name;
- if ((io->flag & IOTYPE) != IOREAD)
+ if ((io->ioflag & IOTYPE) != IOREAD)
errorf("%s: %s", "funny $() command",
snptreef(NULL, 32, "%R", io));
shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0,
-/* $OpenBSD: exec.c,v 1.50 2013/06/10 21:09:27 millert Exp $ */
+/* $OpenBSD: exec.c,v 1.51 2015/04/18 18:28:36 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.137.2.2 2015/03/01 15:42:59 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.137.2.4 2015/04/19 19:18:15 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
t->ioact != NULL && t->ioact[0] != NULL &&
t->ioact[1] == NULL &&
/* of type "here document" (or "here string") */
- (t->ioact[0]->flag & IOTYPE) == IOHERE &&
+ (t->ioact[0]->ioflag & IOTYPE) == IOHERE &&
/* the variable assignment begins with a valid varname */
(ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
/* and has no right-hand side (i.e. "varname=") */
/*
* Were we deleted while executing? If so, free the
- * execution tree. TODO: Unfortunately, the table entry
- * is never re-used until the lookup table is expanded.
+ * execution tree.
*/
if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) {
if (tp->flag & ALLOC) {
{
int u = -1;
char *cp = iop->name;
- int iotype = iop->flag & IOTYPE;
+ int iotype = iop->ioflag & IOTYPE;
bool do_open = true, do_close = false;
int flags = 0;
struct ioword iotmp;
/* Used for tracing and error messages to print expanded cp */
iotmp = *iop;
iotmp.name = (iotype == IOHERE) ? NULL : cp;
- iotmp.flag |= IONAMEXP;
+ iotmp.ioflag |= IONAMEXP;
if (Flag(FXTRACE)) {
change_xtrace(2, false);
* The stat() is here to allow redirections to
* things like /dev/null without error.
*/
- if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB) &&
+ if (Flag(FNOCLOBBER) && !(iop->ioflag & IOCLOB) &&
(stat(cp, &statb) < 0 || S_ISREG(statb.st_mode)))
flags |= O_EXCL;
break;
u = 1009;
do_close = true;
} else if ((u = check_fd(cp,
- X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK),
+ X_OK | ((iop->ioflag & IORDUP) ? R_OK : W_OK),
&emsg)) < 0) {
char *sp;
afree(sp, ATEMP);
return (-1);
}
- if (u == iop->unit)
+ if (u == (int)iop->unit)
/* "dup from" == "dup to" */
return (0);
break;
/* Do not save if it has already been redirected (i.e. "cat >x >y"). */
if (e->savefd[iop->unit] == 0) {
/* If these are the same, it means unit was previously closed */
- if (u == iop->unit)
+ if (u == (int)iop->unit)
e->savefd[iop->unit] = -1;
else
/*
if (do_close)
close(iop->unit);
- else if (u != iop->unit) {
+ else if (u != (int)iop->unit) {
if (ksh_dup2(u, iop->unit, true) < 0) {
int eno;
char *sp;
* causes the shell to close its copies
*/
else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {
- if (iop->flag & IORDUP)
+ if (iop->ioflag & IORDUP)
/* possible exec <&p */
coproc_read_close(u);
else
}
/* lexer substitution flags */
- i = (iop->flag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;
+ i = (iop->ioflag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;
/* skip all the fd setup if we just want the value */
if (resbuf != NULL)
if (call_builtin(findcom("read", FC_BI), read_args, Tselect,
false))
return (NULL);
- s = str_val(global("REPLY"));
- if (*s && getn(s, &i))
- return ((i >= 1 && i <= argct) ? ap[i - 1] : null);
+ if (*(s = str_val(global("REPLY"))))
+ return ((getn(s, &i) && i >= 1 && i <= argct) ?
+ ap[i - 1] : null);
print_menu = true;
}
}
#endif
#endif
-__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.259.2.2 2015/01/25 15:35:44 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.259.2.5 2015/04/19 19:18:16 tg Exp $");
#if HAVE_KILLPG
/*
if (fieldstr && !bi_getn(fieldstr, &field))
return (1);
- if (basestr && (!bi_getn(basestr, &base) || base < 1 || base > 36)) {
+ if (basestr && (!getn(basestr, &base) || base < 1 || base > 36)) {
bi_errorf("%s: %s", "bad integer base", basestr);
return (1);
}
c_read(const char **wp)
{
#define is_ifsws(c) (ctype((c), C_IFS) && ctype((c), C_IFSWS))
- int c, fd = 0, rv = 0, lastparm = 0;
+ int c, fd = 0, rv = 0;
bool savehist = false, intoarray = false, aschars = false;
bool rawmode = false, expanding = false;
+ bool lastparmmode = false, lastparmused = false;
enum { LINES, BYTES, UPTO, READALL } readmode = LINES;
char delim = '\n';
size_t bytesleft = 128, bytesread;
if (!bi_getn(builtin_opt.optarg, &c))
return (2);
if (c == -1) {
- readmode = READALL;
+ readmode = readmode == BYTES ? READALL : UPTO;
bytesleft = 1024;
} else
bytesleft = (unsigned int)c;
}
if (!intoarray && wp[1] == NULL)
- lastparm = 1;
+ lastparmmode = true;
c_read_splitlast:
/* copy until IFS character */
}
xsave = Xsavepos(xs, xp);
/* copy word delimiter: IFSWS+IFS,IFSWS */
+ expanding = false;
while (bytesread) {
char ch;
ch = *ccp;
if (!ctype(ch, C_IFS))
break;
- Xcheck(xs, xp);
- Xput(xs, xp, ch);
+ if (lastparmmode && !expanding && !rawmode && ch == '\\') {
+ expanding = true;
+ } else {
+ Xcheck(xs, xp);
+ Xput(xs, xp, ch);
+ }
++ccp;
--bytesread;
+ if (expanding)
+ continue;
if (!ctype(ch, C_IFSWS))
break;
}
--bytesread;
}
/* if no more parameters, rinse and repeat */
- if (lastparm && bytesread) {
- ++lastparm;
+ if (lastparmmode && bytesread) {
+ lastparmused = true;
goto c_read_splitlast;
}
/* get rid of the delimiter unless we pack the rest */
- if (lastparm < 2)
+ if (!lastparmused)
xp = Xrestpos(xs, xp, xsave);
c_read_gotword:
Xput(xs, xp, '\0');
goto c_exitreturn_err;
arg = wp[builtin_opt.optind];
- if (arg) {
- if (!getn(arg, &n)) {
- exstat = 1;
- warningf(true, "%s: %s", arg, "bad number");
- } else
- exstat = n & 0xFF;
- } else if (trap_exstat != -1)
+ if (arg)
+ exstat = bi_getn(arg, &n) ? (n & 0xFF) : 1;
+ else if (trap_exstat != -1)
exstat = trap_exstat;
if (wp[0][0] == 'r') {
/* return */
#include <sys/file.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134.2.3 2015/03/01 15:43:00 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134.2.5 2015/04/19 19:18:18 tg Exp $");
Trap sigtraps[NSIG + 1];
static struct sigaction Sigact_ign;
for (hp = rflag ? hlast : hfirst;
hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1) {
if (!nflag)
- shf_fprintf(shl_stdout, "%d",
- hist_source->line - (int)(histptr - hp));
+ shf_fprintf(shl_stdout, "%lu",
+ (unsigned long)hist_source->line -
+ (unsigned long)(histptr - hp));
shf_putc('\t', shl_stdout);
/* print multi-line commands correctly */
s = *hp;
return;
/* if the name is the same as the name we have */
- if (hname && strcmp(hname, name) == 0)
+ if (hname && name && !strcmp(hname, name))
return;
/*
hist_source->line = 0;
}
- hist_init(hist_source);
+ if (name)
+ hist_init(hist_source);
}
#endif
hist_source = s;
#if HAVE_PERSISTENT_HISTORY
- if ((hname = str_val(global("HISTFILE"))) == NULL)
+ if (((hname = str_val(global("HISTFILE"))) == NULL) || !*hname) {
+ hname = NULL;
return;
+ }
strdupx(hname, hname, APERM);
hs = hist_init_first;
-/* $OpenBSD: jobs.c,v 1.40 2013/09/04 15:49:18 millert Exp $ */
+/* $OpenBSD: jobs.c,v 1.41 2015/04/18 18:28:36 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
- * 2012, 2013, 2014
+ * 2012, 2013, 2014, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105.2.1 2015/01/25 15:44:06 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105.2.2 2015/04/19 19:18:18 tg Exp $");
#if HAVE_KILLPG
#define mksh_killpg killpg
int flags,
const char *where)
{
+ Proc *p;
int rv;
#ifdef MKSH_NO_SIGSUSPEND
sigset_t omask;
j_systime = j->systime;
rv = j->status;
- if ((flags & JW_PIPEST) && (j->proc_list != NULL)) {
+ if (!(p = j->proc_list)) {
+ ; /* nothing */
+ } else if (flags & JW_PIPEST) {
uint32_t num = 0;
- Proc *p = j->proc_list;
struct tbl *vp;
unset(vp_pipest, 1);
rv = vp->val.i;
p = p->next;
}
- } else if (Flag(FPIPEFAIL) && (j->proc_list != NULL)) {
- Proc *p = j->proc_list;
- int i;
+ } else if (Flag(FPIPEFAIL)) {
+ do {
+ int i = proc_errorlevel(p);
- while (p != NULL) {
- if ((i = proc_errorlevel(p)))
+ if (i)
rv = i;
- p = p->next;
- }
+ } while ((p = p->next));
}
if (!(flags & JW_ASYNCNOTIFY)
size_t len;
int job = 0;
- if (ksh_isdigit(*cp)) {
- getn(cp, &job);
+ if (ksh_isdigit(*cp) && getn(cp, &job)) {
/* Look for last_proc->pid (what $! returns) first... */
for (j = job_list; j != NULL; j = j->next)
if (j->last_proc && j->last_proc->pid == job)
for (j = job_list; j != NULL; j = j->next)
if (j->pgrp && j->pgrp == job)
return (j);
- if (ecodep)
- *ecodep = JL_NOSUCH;
- return (NULL);
+ goto j_lookup_nosuch;
}
if (*cp != '%') {
+ j_lookup_invalid:
if (ecodep)
*ecodep = JL_INVALID;
return (NULL);
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- getn(cp, &job);
+ if (!getn(cp, &job))
+ goto j_lookup_invalid;
for (j = job_list; j != NULL; j = j->next)
if (j->job == job)
return (j);
return (last_match);
break;
}
+ j_lookup_nosuch:
if (ecodep)
*ecodep = JL_NOSUCH;
return (NULL);
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013, 2014
+ * 2011, 2012, 2013, 2014, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193.2.1 2015/01/11 22:39:50 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193.2.5 2015/04/19 19:18:19 tg Exp $");
/*
* states while lexing word
if (!ksh_isdigit(dp[c2 + 1]))
goto no_iop;
iop->unit = (iop->unit * 10) + dp[c2 + 1] - '0';
+ if (iop->unit >= FDBASE)
+ goto no_iop;
}
- if (iop->unit >= FDBASE)
- goto no_iop;
-
if (c == '&') {
if ((c2 = getsc()) != '>') {
ungetsc(c2);
goto no_iop;
}
c = c2;
- iop->flag = IOBASH;
+ iop->ioflag = IOBASH;
} else
- iop->flag = 0;
+ iop->ioflag = 0;
c2 = getsc();
/* <<, >>, <> are ok, >< is not */
if (c == c2 || (c == '<' && c2 == '>')) {
- iop->flag |= c == c2 ?
+ iop->ioflag |= c == c2 ?
(c == '>' ? IOCAT : IOHERE) : IORDWR;
- if (iop->flag == IOHERE) {
+ if (iop->ioflag == IOHERE) {
if ((c2 = getsc()) == '-') {
- iop->flag |= IOSKIP;
+ iop->ioflag |= IOSKIP;
c2 = getsc();
} else if (c2 == '<')
- iop->flag |= IOHERESTR;
+ iop->ioflag |= IOHERESTR;
ungetsc(c2);
if (c2 == '\n')
- iop->flag |= IONDELIM;
+ iop->ioflag |= IONDELIM;
}
} else if (c2 == '&')
- iop->flag |= IODUP | (c == '<' ? IORDUP : 0);
+ iop->ioflag |= IODUP | (c == '<' ? IORDUP : 0);
else {
- iop->flag |= c == '>' ? IOWRITE : IOREAD;
+ iop->ioflag |= c == '>' ? IOWRITE : IOREAD;
if (c == '>' && c2 == '|')
- iop->flag |= IOCLOB;
+ iop->ioflag |= IOCLOB;
else
ungetsc(c2);
}
} else
while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
*dp++ = *sp++;
- /* make sure the ident array stays NUL padded */
- memset(dp, 0, (ident + IDENT) - dp + 1);
if (c != EOS)
/* word is not unquoted */
- *ident = '\0';
+ 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' && (cf & (KEYWORD | ALIAS))) {
+ if (*ident != '\0') {
struct tbl *p;
uint32_t h = hash(ident);
* pushed into an SREREAD) which is what
* we want here anyway: find out whether
* the alias name is followed by a POSIX
- * function definition (only the opening
- * parenthesis is checked though)
+ * function definition
*/
++cp;
/* prefer functions over aliases */
goto Again;
}
}
+ } else if (cf & ALIAS) {
+ /* retain typeset et al. even when quoted */
+ if (assign_command((dp = wdstrip(yylval.cp, 0))))
+ strlcpy(ident, dp, sizeof(ident));
+ afree(dp, ATEMP);
}
return (LWORD);
struct ioword **p;
for (p = heres; p < herep; p++)
- if (iseof && !((*p)->flag & IOHERESTR))
+ if (iseof && !((*p)->ioflag & IOHERESTR))
/* only here strings at EOF */
return;
else
char *xp;
int xpos;
- if (iop->flag & IOHERESTR) {
+ if (iop->ioflag & IOHERESTR) {
/* process the here string */
iop->heredoc = xp = evalstr(iop->delim, DOBLANK);
xpos = strlen(xp) - 1;
return;
}
- eof = iop->flag & IONDELIM ? "<<" : evalstr(iop->delim, 0);
+ eof = iop->ioflag & IONDELIM ? "<<" : evalstr(iop->delim, 0);
- if (!(iop->flag & IOEVAL))
+ if (!(iop->ioflag & IOEVAL))
ignore_backslash_newline++;
Xinit(xs, xp, 256, ATEMP);
/* beginning of line */
eofp = eof;
xpos = Xsavepos(xs, xp);
- if (iop->flag & IOSKIP) {
+ if (iop->ioflag & IOSKIP) {
/* skip over leading tabs */
while ((c = getsc()) == '\t')
- /* nothing */;
+ ; /* nothing */
goto heredoc_parse_char;
}
heredoc_read_char:
Xput(xs, xp, '\0');
iop->heredoc = Xclose(xs, xp);
- if (!(iop->flag & IOEVAL))
+ if (!(iop->ioflag & IOEVAL))
ignore_backslash_newline--;
}
void
set_prompt(int to, Source *s)
{
- cur_prompt = to;
+ cur_prompt = (uint8_t)to;
switch (to) {
/* command */
if (*ps1 != '!' || *++ps1 == '!')
shf_putchar(*ps1++, shf);
else
- shf_fprintf(shf, "%d",
- s ? s->line + 1 : 0);
+ shf_fprintf(shf, "%lu", s ?
+ (unsigned long)s->line + 1 : 0UL);
ps1 = shf_sclose(shf);
saved_atemp = ATEMP;
newenv(E_ERRH);
-.\" $MirOS: src/bin/mksh/lksh.1,v 1.5 2013/05/22 18:18:06 tg Exp $
+.\" $MirOS: src/bin/mksh/lksh.1,v 1.5.2.1 2015/03/21 00:12:45 tg Exp $
.\"-
-.\" Copyright (c) 2008, 2009, 2010, 2012, 2013
+.\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015
.\" Thorsten “mirabilos” Glaser <tg@mirbsd.org>
.\"
.\" Provided that these terms and disclaimer and all copyright notices
.\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always.
.\"
-.Dd $Mdocdate: May 22 2013 $
+.Dd $Mdocdate: March 21 2015 $
.\"
.\" Check which macro package we use, and do other -mdoc setup.
.\"
since the MirBSD Korn Shell scripting language is much more consistent.
.Sh LEGACY MODE
.Nm
-has the following differences from
+currently has the following differences from
.Nm mksh :
.Bl -bullet
.It
.Dq LEGACY KSH
instead of
.Dq MIRBSD KSH .
+Note that the rest of the version string is identical between
+the two shell flavours, and the behaviour and differences can
+change between versions; see the accompanying manual page
+.Xr mksh 1
+for the versions this document applies to.
.It
.Nm
only offers the traditional ten file descriptors to scripts.
.Xr getopt 1
command.
.It
-.Nm lksh ,
-unlike
+Unlike
.At
.Nm ksh ,
-does not keep file descriptors \*(Gt 2 private.
+.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.
.El
.Sh SEE ALSO
.Xr mksh 1
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013, 2014
+ * 2011, 2012, 2013, 2014, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include <locale.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/main.c,v 1.285.2.2 2015/03/01 15:43:01 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/main.c,v 1.285.2.4 2015/04/19 19:18:20 tg Exp $");
extern char **environ;
strcmp(source->file, kshname) != 0)
shf_fprintf(shl_out, "%s: ", kshname + (*kshname == '-'));
if (fileline && source && source->file != NULL) {
- shf_fprintf(shl_out, "%s[%d]: ", source->file,
- source->errline > 0 ? source->errline : source->line);
+ shf_fprintf(shl_out, "%s[%lu]: ", source->file,
+ (unsigned long)(source->errline ?
+ source->errline : source->line));
source->errline = 0;
}
}
int
check_fd(const char *name, int mode, const char **emsgp)
{
- int fd, fl;
+ int fd = 0, fl;
if (name[0] == 'p' && !name[1])
return (coproc_getfd(mode, emsgp));
- for (fd = 0; ksh_isdigit(*name); ++name)
+ while (ksh_isdigit(*name)) {
fd = (fd * 10) + *name - '0';
- if (*name || fd >= FDBASE) {
+ if (fd >= FDBASE) {
+ if (emsgp)
+ *emsgp = "file descriptor too large";
+ return (-1);
+ }
+ ++name;
+ }
+ if (*name) {
if (emsgp)
*emsgp = "illegal file descriptor name";
return (-1);
-/* $OpenBSD: misc.c,v 1.39 2015/01/16 06:39:32 deraadt Exp $ */
+/* $OpenBSD: misc.c,v 1.40 2015/03/18 15:12:36 tedu Exp $ */
/* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $ */
/*-
#include <grp.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219.2.2 2015/03/01 15:43:02 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219.2.3 2015/03/20 22:21:04 tg Exp $");
#define KSH_CHVT_FLAG
#ifdef MKSH_SMALL
afree(str, ATEMP);
}
-/* Strip any nul bytes from buf - returns new length (nbytes - # of nuls) */
+/* strip all NUL bytes from buf; output is NUL-terminated if stripped */
void
-strip_nuls(char *buf, int nbytes)
+strip_nuls(char *buf, size_t len)
{
- char *dst;
+ char *cp, *dp, *ep;
- /*
- * nbytes check because some systems (older FreeBSDs) have a
- * buggy memchr()
- */
- if (nbytes && (dst = memchr(buf, '\0', nbytes))) {
- char *end = buf + nbytes;
- char *p, *q;
+ if (!len || !(dp = memchr(buf, '\0', len)))
+ return;
- for (p = dst; p < end; p = q) {
- /* skip a block of nulls */
- while (++p < end && *p == '\0')
- ;
- /* find end of non-null block */
- if (!(q = memchr(p, '\0', end - p)))
- q = end;
- memmove(dst, p, q - p);
- dst += q - p;
- }
- *dst = '\0';
- }
+ ep = buf + len;
+ cp = dp;
+
+ cp_has_nul_byte:
+ while (cp++ < ep && *cp == '\0')
+ ; /* nothing */
+ while (cp < ep && *cp != '\0')
+ *dp++ = *cp++;
+ if (cp < ep)
+ goto cp_has_nul_byte;
+
+ *dp = '\0';
}
/*
-.\" $MirOS: src/bin/mksh/mksh.1,v 1.344.2.3 2015/03/01 15:43:03 tg Exp $
-.\" $OpenBSD: ksh.1,v 1.156 2015/01/16 15:32:32 schwarze Exp $
+.\" $MirOS: src/bin/mksh/mksh.1,v 1.344.2.5 2015/04/12 22:32:30 tg Exp $
+.\" $OpenBSD: ksh.1,v 1.159 2015/03/25 12:10:52 jca Exp $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
.\" 2010, 2011, 2012, 2013, 2014, 2015
.\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always.
.\"
-.Dd $Mdocdate: March 1 2015 $
+.Dd $Mdocdate: April 12 2015 $
.\"
.\" Check which macro package we use, and do other -mdoc setup.
.\"
hash=\*(aqalias \-t\*(aq
history=\*(aqfc \-l\*(aq
integer=\*(aqtypeset \-i\*(aq
-local=\*(aqtypeset\*(aq
+local=typeset
login=\*(aqexec login\*(aq
nameref=\*(aqtypeset \-n\*(aq
nohup=\*(aqnohup \*(aq
r=\*(aqfc \-e \-\*(aq
+source=\*(aqPATH=$PATH:. command .\*(aq
stop=\*(aqkill \-STOP\*(aq
type=\*(aqwhence \-v\*(aq
.Ed
.Ic return
work, and in that
.Ic exit
-terminates the parent shell.
+terminates the parent shell; shell options are shared.
.Pp
Another variant of substitution are the valsubs (value substitutions)
.Pf ${\*(Ba\& Ns Ar command Ns \&;}
.Sq D .
Note that if the
.Ev IFS
-parameter is set to the
-.Dv NULL
-string, no field splitting is done; if the parameter is unset, the default
-value of space, tab, and newline is used.
+parameter is set to the empty string, no field splitting is done;
+if it is unset, the default value of space, tab, and newline is used.
.Pp
Also, note that the field splitting applies only to the immediate result of
the substitution.
.It Ev BASHPID
The PID of the shell or subshell.
.It Ev CDPATH
-Search path for the
+Like
+.Ev PATH ,
+but used to resolve the argument to the
.Ic cd
built-in command.
-It works the same way as
-.Ev PATH
-for those directories not beginning with
-.Ql /
-in
-.Ic cd
-commands.
Note that if
.Ev CDPATH
is set and does not contain
.Sq \&.
-or contains an empty path, the current directory is not searched.
+or an empty string element, the current directory is not searched.
Also, the
.Ic cd
built-in command will display the resulting directory when a match is found
below for more information.
.It Ev HISTFILE
The name of the file used to store command history.
-When assigned to, history is loaded from the specified file.
+When assigned to or unset, the file is opened, history is truncated
+then loaded from the file; subsequent new lines are appended.
Also, several invocations of the shell will share history if their
.Ev HISTFILE
parameters all point to the same file.
.Sy Note :
If
.Ev HISTFILE
-isn't set, no history file is used.
+is unset or empty, no history file is used.
This is different from
.At
.Nm ksh .
or
.Nm lksh )
to behave more like the standard expects.
+.Pp
+For the purpose of
+.Tn POSIX ,
+.Nm mksh
+supports only the
+.Dq C
+locale.
+For users of UTF-8 locales, the following sh code makes the shell
+match the locale:
+.Bd -literal -offset indent
+case ${KSH_VERSION:\-} in
+*MIRBSD\ KSH*\*(Ba*LEGACY\ KSH*)
+ case ${LC_ALL:\-${LC_CTYPE:\-${LANG:\-}}} in
+ *[Uu][Tt][Ff]8*\*(Ba*[Uu][Tt][Ff]\-8*) set \-U ;;
+ *) set +U ;;
+ esac ;;
+esac
+.Ed
.Sh BUGS
Suspending (using \*(haZ) pipelines like the one below will only suspend
the currently running part of the pipeline; in this example,
$ /bin/sleep 666 && echo fubar
.Ed
.Pp
+The truncation process involved when changing
+.Ev HISTFILE
+does not free old history entries (leaks memory) and leaks
+old entries into the new history if their line numbers are
+not overwritten by same-numer entries from the persistent
+history file; truncating the on-disc file to
+.Ev HISTSIZE
+lines has always been broken and prone to history file corruption
+when multiple shells are accessing the file; the rollover process
+for the in-memory portion of the history is slow, should use
+.Xr memmove 3 .
+.Pp
This document attempts to describe
.Nm mksh\ R50e
and up,
+.\" with vendor patches from insert-your-name-here,
compiled without any options impacting functionality, such as
.Dv MKSH_SMALL ,
when not called as
#endif
#ifdef EXTERN
-__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.701.2.4 2015/03/01 15:43:05 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.701.2.7 2015/04/19 19:18:21 tg Exp $");
#endif
-#define MKSH_VERSION "R50 2015/03/01"
+#define MKSH_VERSION "R50 2015/04/19"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
#define mkssert(e) do { } while (/* CONSTCOND */ 0)
#endif
-#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 505)
+#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 506)
#error Must run Build.sh to compile this.
extern void thiswillneverbedefinedIhope(void);
int
EXTERN const char *def_path; /* path to use if PATH not set */
EXTERN char *tmpdir; /* TMPDIR value */
EXTERN const char *prompt;
-EXTERN int cur_prompt; /* PS1 or PS2 */
+EXTERN uint8_t cur_prompt; /* PS1 or PS2 */
EXTERN int current_lineno; /* LINENO value */
/*
* IO redirection
*/
struct ioword {
- int unit; /* unit affected */
- int flag; /* action (below) */
- char *name; /* file name (unused if heredoc) */
- char *delim; /* delimiter for <<,<<- */
- char *heredoc; /* content of heredoc */
+ char *name; /* filename (unused if heredoc) */
+ char *delim; /* delimiter for <<, <<- */
+ char *heredoc; /* content of heredoc */
+ unsigned short ioflag; /* action (below) */
+ short unit; /* unit (fd) affected */
};
/* ioword.flag - type of redirection */
#define VARASN BIT(5) /* check for var=word */
#define ARRAYVAR BIT(6) /* parse x[1 & 2] as one word */
#define ESACONLY BIT(7) /* only accept esac keyword */
-#define CMDWORD BIT(8) /* parsing simple command (alias related) */
-#define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */
-#define LQCHAR BIT(10) /* source string contains QCHAR */
-#define HEREDOC BIT(11) /* parsing a here document body */
+#define HEREDELIM BIT(8) /* parsing <<,<<- delimiter */
+#define LQCHAR BIT(9) /* source string contains QCHAR */
+#define HEREDOC BIT(10) /* parsing a here document body */
#define HERES 10 /* max number of << in line */
void print_columns(struct shf *, unsigned int,
char *(*)(char *, size_t, unsigned int, const void *),
const void *, size_t, size_t, bool);
-void strip_nuls(char *, int);
+void strip_nuls(char *, size_t)
+ MKSH_A_BOUNDED(__string__, 1, 2);
ssize_t blocking_read(int, char *, size_t)
MKSH_A_BOUNDED(__buffer__, 2, 3);
int reset_nonblock(int);
ssize_t shf_vfprintf(struct shf *, const char *, va_list)
MKSH_A_FORMAT(__printf__, 2, 0);
/* syn.c */
+int assign_command(const char *);
void initkeywords(void);
struct op *compile(Source *, bool);
bool parse_usec(const char *, struct timeval *);
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- * 2011, 2012, 2013, 2014
+ * 2011, 2012, 2013, 2014, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94.2.1 2015/01/25 15:35:54 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94.2.3 2015/04/12 22:32:35 tg Exp $");
struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */
static void syntaxerr(const char *) MKSH_A_NORETURN;
static void nesting_push(struct nesting_state *, int);
static void nesting_pop(struct nesting_state *);
-static int assign_command(const char *);
static int inalias(struct source *) MKSH_A_PURE;
static Test_op dbtestp_isa(Test_env *, Test_meta);
static const char *dbtestp_getopnd(Test_env *, Test_op, bool);
return (NULL);
ACCEPT;
iop = yylval.iop;
- if (iop->flag & IONDELIM)
+ if (iop->ioflag & IONDELIM)
goto gotnulldelim;
- ishere = (iop->flag & IOTYPE) == IOHERE;
+ ishere = (iop->ioflag & IOTYPE) == IOHERE;
musthave(LWORD, ishere ? HEREDELIM : 0);
if (ishere) {
iop->delim = yylval.cp;
if (*ident != 0) {
/* unquoted */
gotnulldelim:
- iop->flag |= IOEVAL;
+ iop->ioflag |= IOEVAL;
}
if (herep > &heres[HERES - 1])
yyerror("too many %ss\n", "<<");
} else
iop->name = yylval.cp;
- if (iop->flag & IOBASH) {
+ if (iop->ioflag & IOBASH) {
char *cp;
nextiop = alloc(sizeof(*iop), ATEMP);
*cp++ = '0' + (iop->unit % 10);
*cp = EOS;
- iop->flag &= ~IOBASH;
+ iop->ioflag &= ~IOBASH;
nextiop->unit = 2;
- nextiop->flag = IODUP;
+ nextiop->ioflag = IODUP;
nextiop->delim = NULL;
nextiop->heredoc = NULL;
}
t->lineno = source->line;
while (/* CONSTCOND */ 1) {
cf = (t->u.evalflags ? ARRAYVAR : 0) |
- (XPsize(args) == 0 ? sALIAS|VARASN : CMDWORD);
+ (XPsize(args) == 0 ? sALIAS|VARASN : 0);
switch (tpeek(cf)) {
case REDIR:
while ((iop = synio(cf)) != NULL) {
* a=a
* $
*/
-static int
+int
assign_command(const char *s)
{
if (!*s)
ret = c == /*(*/ ')' ? TO_NONNULL : TO_NONOP;
else if (meta == TM_UNOP || meta == TM_BINOP) {
if (meta == TM_BINOP && c == REDIR &&
- (yylval.iop->flag == IOREAD || yylval.iop->flag == IOWRITE)) {
+ (yylval.iop->ioflag == IOREAD ||
+ yylval.iop->ioflag == IOWRITE)) {
ret = TO_NONNULL;
- save = wdcopy(yylval.iop->flag == IOREAD ?
+ save = wdcopy(yylval.iop->ioflag == IOREAD ?
db_lthan : db_gthan, ATEMP);
} else if (uqword && (ret = test_isop(meta, ident)))
save = yylval.cp;
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.72 2013/09/24 20:19:45 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.72.2.1 2015/04/12 22:32:35 tg Exp $");
#define INDENT 8
t->ioact != NULL && t->ioact[0] != NULL &&
t->ioact[1] == NULL &&
/* of type "here document" (or "here string") */
- (t->ioact[0]->flag & IOTYPE) == IOHERE) {
+ (t->ioact[0]->ioflag & IOTYPE) == IOHERE) {
fptreef(shf, indent, "%S", t->vars[0]);
break;
}
struct ioword *iop = *ioact++;
/* heredoc is NULL when tracing (set -x) */
- if ((iop->flag & (IOTYPE | IOHERESTR)) == IOHERE &&
+ if ((iop->ioflag & (IOTYPE | IOHERESTR)) == IOHERE &&
iop->heredoc) {
shf_putc('\n', shf);
shf_puts(iop->heredoc, shf);
fptreef(shf, indent, "%s",
- iop->flag & IONDELIM ? "<<" :
+ iop->ioflag & IONDELIM ? "<<" :
evalstr(iop->delim, 0));
need_nl = true;
}
static void
pioact(struct shf *shf, struct ioword *iop)
{
- int flag = iop->flag;
- int type = flag & IOTYPE;
- int expected;
+ unsigned short flag = iop->ioflag;
+ unsigned short type = flag & IOTYPE;
+ short expected;
expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :
(type == IOCAT || type == IOWRITE) ? 1 :
(type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :
iop->unit + 1;
if (iop->unit != expected)
- shf_fprintf(shf, "%d", iop->unit);
+ shf_fprintf(shf, "%d", (int)iop->unit);
switch (type) {
case IOREAD:
if (type == IOHERE) {
if (iop->delim)
wdvarput(shf, iop->delim, 0, WDS_TPUTS);
- if (iop->flag & IOHERESTR)
+ if (flag & IOHERESTR)
shf_putc(' ', shf);
} else if (iop->name) {
- if (iop->flag & IONAMEXP)
+ if (flag & IONAMEXP)
print_value_quoted(shf, iop->name);
else
wdvarput(shf, iop->name, 0, WDS_TPUTS);
shf_puts("{IOACT", shf);
while ((iop = *ioact++) != NULL) {
- int type = iop->flag & IOTYPE;
+ unsigned short type = iop->ioflag & IOTYPE;
#define DT(x) case x: shf_puts(#x, shf); break;
-#define DB(x) if (iop->flag & x) shf_puts("|" #x, shf);
+#define DB(x) if (iop->ioflag & x) shf_puts("|" #x, shf);
shf_putc(';', shf);
switch (type) {
DB(IOBASH)
DB(IOHERESTR)
DB(IONDELIM)
- shf_fprintf(shf, ",unit=%d", iop->unit);
+ shf_fprintf(shf, ",unit=%d", (int)iop->unit);
if (iop->delim) {
shf_puts(",delim<", shf);
dumpwdvar(shf, iop->delim);
shf_putc('>', shf);
}
if (iop->name) {
- if (iop->flag & IONAMEXP) {
+ if (iop->ioflag & IONAMEXP) {
shf_puts(",name=", shf);
print_value_quoted(shf, iop->name);
} else {
#include <sys/sysctl.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183.2.2 2015/03/01 15:43:07 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183.2.4 2015/04/19 19:18:23 tg Exp $");
/*-
* Variables
static int
getint(struct tbl *vp, mksh_ari_u *nump, bool arith)
{
- mksh_uari_t c, num, base;
+ mksh_uari_t c, num = 0, base = 10;
const char *s;
bool have_base = false, neg = false;
- if (vp->flag&SPECIAL)
+ if (vp->flag & SPECIAL)
getspec(vp);
/* XXX is it possible for ISSET to be set and val.s to be NULL? */
- if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL))
+ if (!(vp->flag & ISSET) || (!(vp->flag & INTEGER) && vp->val.s == NULL))
return (-1);
- if (vp->flag&INTEGER) {
+ if (vp->flag & INTEGER) {
nump->i = vp->val.i;
return (vp->type);
}
s = vp->val.s + vp->type;
- base = 10;
- num = 0;
- if (arith && s[0] == '0' && (s[1] | 0x20) == 'x') {
- s += 2;
- base = 16;
- have_base = true;
+
+ do {
+ c = (unsigned char)*s++;
+ } while (ksh_isspace(c));
+
+ switch (c) {
+ case '-':
+ neg = true;
+ /* FALLTHROUGH */
+ case '+':
+ c = (unsigned char)*s++;
+ break;
}
- if (Flag(FPOSIX) && arith && s[0] == '0' && ksh_isdigit(s[1]) &&
- !(vp->flag & ZEROFIL)) {
- /* interpret as octal (deprecated) */
- base = 8;
- have_base = true;
+
+ if (c == '0' && arith) {
+ if ((s[0] | 0x20) == 'x') {
+ /* interpret as hexadecimal */
+ base = 16;
+ ++s;
+ goto getint_c_style_base;
+ } else if (Flag(FPOSIX) && ksh_isdigit(s[0]) &&
+ !(vp->flag & ZEROFIL)) {
+ /* interpret as octal (deprecated) */
+ base = 8;
+ getint_c_style_base:
+ have_base = true;
+ c = (unsigned char)*s++;
+ }
}
- while ((c = (unsigned char)*s++)) {
- if (c == '-') {
- neg = true;
- continue;
- } else if (c == '#') {
- if (have_base || num < 1 || num > 36)
+
+ do {
+ if (c == '#') {
+ /* ksh-style base determination */
+ if (have_base || num < 1)
return (-1);
if ((base = num) == 1) {
+ /* mksh-specific extension */
unsigned int wc;
if (!UTFMODE)
wc = 0xEF00 + *(const unsigned char *)s;
nump->u = (mksh_uari_t)wc;
return (1);
- }
+ } else if (base > 36)
+ return (-1);
num = 0;
have_base = true;
continue;
- } else if (ksh_isdigit(c))
+ }
+ if (ksh_isdigit(c))
c -= '0';
- else if (ksh_islower(c))
+ else {
+ c |= 0x20;
+ if (!ksh_islower(c))
+ return (-1);
c -= 'a' - 10;
- else if (ksh_isupper(c))
- c -= 'A' - 10;
- else
- return (-1);
+ }
if (c >= base)
return (-1);
+ /* handle overflow as truncation */
num = num * base + c;
- }
+ } while ((c = (unsigned char)*s++));
+
if (neg)
num = -num;
nump->u = num;
}
static time_t seconds; /* time SECONDS last set */
-static int user_lineno; /* what user set $LINENO to */
+static mksh_uari_t user_lineno; /* what user set $LINENO to */
static void
getspec(struct tbl *vp)
num.i = histsize;
break;
case V_LINENO:
- num.i = current_lineno + user_lineno;
+ num.u = (mksh_uari_t)current_lineno + user_lineno;
break;
case V_LINES:
num.i = x_lins;
break;
case V_LINENO:
/* The -1 is because line numbering starts at 1. */
- user_lineno = num.u - current_lineno - 1;
+ user_lineno = num.u - (mksh_uari_t)current_lineno - 1;
break;
case V_LINES:
if (num.i >= MIN_LINS)
*/
switch (special(vp->name)) {
+#if HAVE_PERSISTENT_HISTORY
+ case V_HISTFILE:
+ sethistfile(NULL);
+ return;
+#endif
case V_IFS:
setctypes(TC_IFSWS, C_IFS);
ifs0 = ' ';