summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2015-03-10 22:22:24 -0700
committerElliott Hughes <enh@google.com>2015-03-10 22:22:24 -0700
commit50012061ca3ad8e8a7f88c72130a5e22d797897e (patch)
treeb4d1dfad9d7d0f8170180cb28d73d685ced1fd2a
parent948ca12d46512a832fe53ee24fd580e7addaf28d (diff)
downloadmksh-50012061ca3ad8e8a7f88c72130a5e22d797897e.tar.gz
Upgrade to mksh 50e.
Change-Id: I341673d83c67f83761aa02c8372da6bbc419286f
-rw-r--r--Android.mk4
-rw-r--r--Makefrag.inc12
-rw-r--r--mkshrc4
-rw-r--r--src/Build.sh56
-rw-r--r--src/check.t541
-rw-r--r--src/dot.mkshrc15
-rw-r--r--src/edit.c16
-rw-r--r--src/eval.c108
-rw-r--r--src/exec.c215
-rw-r--r--src/expr.c4
-rw-r--r--src/funcs.c55
-rw-r--r--src/histrap.c13
-rw-r--r--src/jobs.c42
-rw-r--r--src/lalloc.c6
-rw-r--r--src/lex.c27
-rw-r--r--src/main.c15
-rw-r--r--src/misc.c30
-rw-r--r--src/mksh.158
-rw-r--r--src/sh.h22
-rw-r--r--src/shf.c113
-rw-r--r--src/syn.c5
-rw-r--r--src/var.c9
22 files changed, 890 insertions, 480 deletions
diff --git a/Android.mk b/Android.mk
index 2d572bd..6fd3f57 100644
--- a/Android.mk
+++ b/Android.mk
@@ -45,7 +45,7 @@ LOCAL_CFLAGS += \
-Wno-deprecated-declarations \
-fno-asynchronous-unwind-tables \
-fno-strict-aliasing \
- -fstack-protector -fwrapv \
+ -fstack-protector-strong -fwrapv \
# ...and CPPFLAGS.
LOCAL_CFLAGS += \
@@ -79,6 +79,6 @@ LOCAL_CFLAGS += \
-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=504
+ -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=505
include $(BUILD_EXECUTABLE)
diff --git a/Makefrag.inc b/Makefrag.inc
index b7a35bd..c5d5f6d 100644
--- a/Makefrag.inc
+++ b/Makefrag.inc
@@ -1,4 +1,4 @@
-# Makefile fragment for building mksh R50 2014/10/03
+# Makefile fragment for building mksh R50 2015/03/01
PROG= mksh
MAN= mksh.1
@@ -8,11 +8,11 @@ OBJS_BP= lalloc.o eval.o exec.o expr.o funcs.o histrap.o jobs.o lex.o main.o mi
INDSRCS= emacsfn.h rlimits.opt sh.h sh_flags.opt var_spec.h
NONSRCS_INST= dot.mkshrc $(MAN)
NONSRCS_NOINST= Build.sh Makefile Rebuild.sh check.pl check.t test.sh
-CC= /huge-ssd/aosp-x86_64/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8/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 -fwrapv
-CPPFLAGS= -I. -I'../src' -isystem /huge-ssd/aosp-x86_64/bionic/libc/arch-x86/include -isystem /huge-ssd/aosp-x86_64/bionic/libc/include -isystem /huge-ssd/aosp-x86_64/bionic/libc/kernel/uapi -isystem /huge-ssd/aosp-x86_64/bionic/libc/kernel/uapi/asm-x86 -isystem /huge-ssd/aosp-x86_64/bionic/libm/include -isystem /huge-ssd/aosp-x86_64/bionic/libm/include/x86 -D_FORTIFY_SOURCE=2 -I/huge-ssd/aosp-x86_64/build/core/combo/include/arch/linux-x86/ -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=503
-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-x86_64/out/target/product/generic_x86_64/obj/lib/crtbegin_dynamic.o
-LIBS= -L/huge-ssd/aosp-x86_64/out/target/product/generic_x86_64/obj/lib -Wl,-rpath-link=/huge-ssd/aosp-x86_64/out/target/product/generic_x86_64/obj/lib -Wl,--no-whole-archive /huge-ssd/aosp-x86_64/out/target/product/generic_x86_64/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a -lc /huge-ssd/aosp-x86_64/out/target/product/generic_x86_64/obj/lib/crtend_android.o
+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
+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
.depend $(OBJS_BP): rlimits.gen sh_flags.gen
rlimits.gen: ../src/Build.sh ../src/rlimits.opt
diff --git a/mkshrc b/mkshrc
index 98cbeac..510fdb7 100644
--- a/mkshrc
+++ b/mkshrc
@@ -31,7 +31,7 @@ function hd {
local dasc line i
cat "$@" | { set +U; if read -arN -1 line; then
- typeset -i1 line
+ typeset -i1 'line[*]'
i=0
while (( i < ${#line[*]} )); do
hv=${line[i++]}
@@ -60,7 +60,7 @@ function setenv {
eval export "\"$1\""'="$2"'
}
-for p in ~/.bin; do
+for p in ~/bin; do
[[ -d $p/. ]] || continue
[[ :$PATH: = *:$p:* ]] || PATH=$p:$PATH
done
diff --git a/src/Build.sh b/src/Build.sh
index c59163b..5c90eb8 100644
--- a/src/Build.sh
+++ b/src/Build.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669 2014/10/07 15:22:12 tg Exp $'
+srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669.2.2 2015/03/01 15:42:50 tg Exp $'
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014
@@ -1700,22 +1700,22 @@ rmf lft* # end of large file support test
ac_test can_inttypes '!' stdint_h 1 "for standard 32-bit integer types" <<-'EOF'
#include <sys/types.h>
#include <stddef.h>
- int main(int ac, char **av) { return ((uint32_t)(ptrdiff_t)*av + (int32_t)ac); }
+ int main(int ac, char **av) { return ((uint32_t)(size_t)*av + (int32_t)ac); }
EOF
ac_test can_ucbints '!' can_inttypes 1 "for UCB 32-bit integer types" <<-'EOF'
#include <sys/types.h>
#include <stddef.h>
- int main(int ac, char **av) { return ((u_int32_t)(ptrdiff_t)*av + (int32_t)ac); }
+ int main(int ac, char **av) { return ((u_int32_t)(size_t)*av + (int32_t)ac); }
EOF
ac_test can_int8type '!' stdint_h 1 "for standard 8-bit integer type" <<-'EOF'
#include <sys/types.h>
#include <stddef.h>
- int main(int ac, char **av) { return ((uint8_t)(ptrdiff_t)av[ac]); }
+ int main(int ac, char **av) { return ((uint8_t)(size_t)av[ac]); }
EOF
ac_test can_ucbint8 '!' can_int8type 1 "for UCB 8-bit integer type" <<-'EOF'
#include <sys/types.h>
#include <stddef.h>
- int main(int ac, char **av) { return ((u_int8_t)(ptrdiff_t)av[ac]); }
+ int main(int ac, char **av) { return ((u_int8_t)(size_t)av[ac]); }
EOF
ac_test rlim_t <<-'EOF'
@@ -1784,7 +1784,7 @@ else
#define EXTERN
#define MKSH_INCLUDES_ONLY
#include "sh.h"
- __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.669 2014/10/07 15:22:12 tg Exp $");
+ __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)); }
EOF
case $cm in
@@ -1969,13 +1969,13 @@ EOF
ac_test setlocale_ctype '' 'setlocale(LC_CTYPE, "")' <<-'EOF'
#include <locale.h>
#include <stddef.h>
- int main(void) { return ((int)(ptrdiff_t)(void *)setlocale(LC_CTYPE, "")); }
+ int main(void) { return ((int)(size_t)(void *)setlocale(LC_CTYPE, "")); }
EOF
ac_test langinfo_codeset setlocale_ctype 0 'nl_langinfo(CODESET)' <<-'EOF'
#include <langinfo.h>
#include <stddef.h>
- int main(void) { return ((int)(ptrdiff_t)(void *)nl_langinfo(CODESET)); }
+ int main(void) { return ((int)(size_t)(void *)nl_langinfo(CODESET)); }
EOF
ac_test select <<-'EOF'
@@ -2150,9 +2150,9 @@ cta(uari_has_32_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4
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 22
+#define NUM 21
#else
-#define NUM 16
+#define NUM 15
#endif
/* these are always required */
cta(ari_is_signed, (mksh_ari_t)-1 < (mksh_ari_t)0);
@@ -2161,11 +2161,10 @@ cta(uari_is_unsigned, (mksh_uari_t)-1 > (mksh_uari_t)0);
cta(ari_size_no_matter_of_signedness, sizeof(mksh_ari_t) == sizeof(mksh_uari_t));
cta(sizet_size_no_matter_of_signedness, sizeof(ssize_t) == sizeof(size_t));
-cta(ptrdifft_sizet_same_size, sizeof(ptrdiff_t) == sizeof(size_t));
-cta(ptrdifft_voidptr_same_size, sizeof(ptrdiff_t) == sizeof(void *));
-cta(ptrdifft_funcptr_same_size, sizeof(ptrdiff_t) == sizeof(void (*)(void)));
+cta(sizet_voidptr_same_size, sizeof(size_t) == sizeof(void *));
+cta(sizet_funcptr_same_size, sizeof(size_t) == sizeof(void (*)(void)));
/* our formatting routines assume this */
-cta(ptr_fits_in_long, sizeof(ptrdiff_t) <= sizeof(long));
+cta(ptr_fits_in_long, sizeof(size_t) <= sizeof(long));
/* for struct alignment people */
char padding[64 - NUM];
};
@@ -2264,6 +2263,11 @@ mksh_cfg= NSIG
;' >conftest.c
# GNU sed 2.03 segfaults when optimising this to sed -n
NSIG=`vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \
+ grep -v '^#' | \
+ sed '/mksh_cfg.*= *$/{
+ N
+ s/\n/ /
+ }' | \
grep '^ *mksh_cfg *=' | \
sed 's/^ *mksh_cfg *=[ ]*\([()0-9x+-][()0-9x+ -]*\).*$/\1/'`
case $NSIG in
@@ -2295,6 +2299,11 @@ mksh_cfg= NSIG
echo ';' >>conftest.c
# GNU sed 2.03 croaks on optimising this, too
vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \
+ grep -v '^#' | \
+ sed '/mksh_cfg.*= *$/{
+ N
+ s/\n/ /
+ }' | \
grep '^ *mksh_cfg *=' | \
sed 's/^ *mksh_cfg *=[ ]*\([0-9][0-9x]*\).*$/:\1 '$name/
done | sed -n '/^:[^ ]/s/^://p' | while read nr name; do
@@ -2316,7 +2325,7 @@ addsrcs '!' HAVE_STRLCPY strlcpy.c
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=504
+add_cppflags -DMKSH_BUILD_R=505
$e $bi$me: Finished configuration testing, now producing output.$ao
@@ -2431,9 +2440,12 @@ llvm)
;;
esac
echo ": # work around NeXTstep bug" >Rebuild.sh
-for file in "$srcdir"/*.opt; do
+cd "$srcdir"
+optfiles=`echo *.opt`
+cd "$curdir"
+for file in $optfiles; do
echo "echo + Running genopt on '$file'..."
- echo "(srcfile='$file'; BUILDSH_RUN_GENOPT=1; . '$srcdir/Build.sh')"
+ echo "(srcfile='$srcdir/$file'; BUILDSH_RUN_GENOPT=1; . '$srcdir/Build.sh')"
done >>Rebuild.sh
echo set -x >>Rebuild.sh
for file in $SRCS; do
@@ -2467,11 +2479,11 @@ if test $cm = makefile; then
extras='emacsfn.h rlimits.opt sh.h sh_flags.opt var_spec.h'
test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc"
gens= genq=
- for file in "$srcdir"/*.opt; do
+ for file in $optfiles; do
genf=`basename "$file" | sed 's/.opt$/.gen/'`
gens="$gens $genf"
- genq="$genq$nl$genf: $srcdir/Build.sh $file
- srcfile=$file; BUILDSH_RUN_GENOPT=1; . $srcdir/Build.sh"
+ genq="$genq$nl$genf: $srcdir/Build.sh $srcdir/$file
+ srcfile=$srcdir/$file; BUILDSH_RUN_GENOPT=1; . $srcdir/Build.sh"
done
cat >Makefrag.inc <<EOF
# Makefile fragment for building mksh $dstversion
@@ -2515,9 +2527,9 @@ EOF
$e Generated Makefrag.inc successfully.
exit 0
fi
-for file in "$srcdir"/*.opt; do
+for file in $optfiles; do
$e "+ Running genopt on '$file'..."
- do_genopt "$file" || exit 1
+ do_genopt "$srcdir/$file" || exit 1
done
if test $cm = combine; then
objs="-o $mkshexe"
diff --git a/src/check.t b/src/check.t
index 2e1d032..cd7c50d 100644
--- a/src/check.t
+++ b/src/check.t
@@ -1,8 +1,8 @@
-# $MirOS: src/bin/mksh/check.t,v 1.661 2014/10/07 15:22:14 tg Exp $
-# OpenBSD src/regress/bin/ksh updated: 2013/12/02 20:39:44
+# $MirOS: src/bin/mksh/check.t,v 1.667.2.3 2015/03/01 15:42:51 tg Exp $
+# -*- mode: sh -*-
#-
# Copyright © 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
@@ -24,10 +24,13 @@
# http://www.research.att.com/~gsf/public/ifs.sh
#
# More testsuites at:
-# http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
+# http://svnweb.freebsd.org/base/head/bin/test/tests/legacy_test.sh?view=co&content-type=text%2Fplain
+#
+# Integrated testsuites from:
+# (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 2014/10/07
+ @(#)MIRBSD KSH R50 2015/03/01
description:
Check version of shell.
stdin:
@@ -36,7 +39,7 @@ name: KSH_VERSION
category: shell:legacy-no
---
expected-stdout:
- @(#)LEGACY KSH R50 2014/10/07
+ @(#)LEGACY KSH R50 2015/03/01
description:
Check version of legacy shell.
stdin:
@@ -2359,6 +2362,14 @@ stdin:
expected-stdout:
baz
---
+name: heredoc-9f
+description:
+ Check long here strings
+stdin:
+ cat <<< "$( : )aa"
+expected-stdout:
+ aa
+---
name: heredoc-10
description:
Check direct here document assignment
@@ -2389,6 +2400,14 @@ stdin:
vf=<<<$'=f $x \x40='
# now check
print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} ve={$ve} vf={$vf} |"
+ # check append
+ v=<<-EOF
+ vapp1
+ EOF
+ v+=<<-EOF
+ vapp2
+ EOF
+ print -r -- "| ${v//$'\n'/^} |"
expected-stdout:
function foo {
vc=<<-EOF
@@ -2404,6 +2423,7 @@ expected-stdout:
} ve={=e $x \x40=
} vf={=f $x @=
} |
+ | vapp1^vapp2^ |
---
name: heredoc-11
description:
@@ -2433,6 +2453,14 @@ stdin:
eval "$fnd"
foo
print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} |"
+ # check append
+ v=<<-
+ vapp1
+ <<
+ v+=<<-''
+ vapp2
+
+ print -r -- "| ${v//$'\n'/^} |"
expected-stdout:
function foo {
vc=<<-
@@ -2450,6 +2478,52 @@ expected-stdout:
} vc={=c u \x40=
} vd={=d $x \x40=
} |
+ | vapp1^vapp2^ |
+---
+name: heredoc-12
+description:
+ Check here documents can use $* and $@; note shells vary:
+ • pdksh 5.2.14 acts the same
+ • dash has 1 and 2 the same but 3 lacks the space
+ • ksh93, bash4 differ in 2 by using space ipv colon
+stdin:
+ set -- a b
+ nl='
+ '
+ IFS=" $nl"; n=1
+ cat <<EOF
+ $n foo $* foo
+ $n bar "$*" bar
+ $n baz $@ baz
+ $n bla "$@" bla
+ EOF
+ IFS=":"; n=2
+ cat <<EOF
+ $n foo $* foo
+ $n bar "$*" bar
+ $n baz $@ baz
+ $n bla "$@" bla
+ EOF
+ IFS=; n=3
+ cat <<EOF
+ $n foo $* foo
+ $n bar "$*" bar
+ $n baz $@ baz
+ $n bla "$@" bla
+ EOF
+expected-stdout:
+ 1 foo a b foo
+ 1 bar "a b" bar
+ 1 baz a b baz
+ 1 bla "a b" bla
+ 2 foo a:b foo
+ 2 bar "a:b" bar
+ 2 baz a:b baz
+ 2 bla "a:b" bla
+ 3 foo a b foo
+ 3 bar "a b" bar
+ 3 baz a b baz
+ 3 bla "a b" bla
---
name: heredoc-comsub-1
description:
@@ -3585,23 +3659,23 @@ name: IFS-space-1
description:
Simple test, default IFS
stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
set -- A B C
showargs 1 $*
showargs 2 "$*"
showargs 3 $@
showargs 4 "$@"
expected-stdout:
- <1> <A> <B> <C>
- <2> <A B C>
- <3> <A> <B> <C>
- <4> <A> <B> <C>
+ <1> <A> <B> <C> .
+ <2> <A B C> .
+ <3> <A> <B> <C> .
+ <4> <A> <B> <C> .
---
name: IFS-colon-1
description:
Simple test, IFS=:
stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS=:
set -- A B C
showargs 1 $*
@@ -3609,16 +3683,16 @@ stdin:
showargs 3 $@
showargs 4 "$@"
expected-stdout:
- <1> <A> <B> <C>
- <2> <A:B:C>
- <3> <A> <B> <C>
- <4> <A> <B> <C>
+ <1> <A> <B> <C> .
+ <2> <A:B:C> .
+ <3> <A> <B> <C> .
+ <4> <A> <B> <C> .
---
name: IFS-null-1
description:
Simple test, IFS=""
stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS=""
set -- A B C
showargs 1 $*
@@ -3626,16 +3700,16 @@ stdin:
showargs 3 $@
showargs 4 "$@"
expected-stdout:
- <1> <A> <B> <C>
- <2> <ABC>
- <3> <A> <B> <C>
- <4> <A> <B> <C>
+ <1> <A> <B> <C> .
+ <2> <ABC> .
+ <3> <A> <B> <C> .
+ <4> <A> <B> <C> .
---
name: IFS-space-colon-1
description:
Simple test, IFS=<white-space>:
stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="$IFS:"
set --
showargs 1 $*
@@ -3644,52 +3718,52 @@ stdin:
showargs 4 "$@"
showargs 5 : "$@"
expected-stdout:
- <1>
- <2> <>
- <3>
- <4>
- <5> <:>
+ <1> .
+ <2> <> .
+ <3> .
+ <4> .
+ <5> <:> .
---
name: IFS-space-colon-2
description:
Simple test, IFS=<white-space>:
AT&T ksh fails this, POSIX says the test is correct.
stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="$IFS:"
set --
showargs :"$@"
expected-stdout:
- <:>
+ <:> .
---
name: IFS-space-colon-4
description:
Simple test, IFS=<white-space>:
stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="$IFS:"
set --
showargs "$@$@"
expected-stdout:
-
+ .
---
name: IFS-space-colon-5
description:
Simple test, IFS=<white-space>:
Don't know what POSIX thinks of this. AT&T ksh does not do this.
stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="$IFS:"
set --
showargs "${@:-}"
expected-stdout:
- <>
+ <> .
---
name: IFS-subst-1
description:
Simple test, IFS=<white-space>:
stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="$IFS:"
x=":b: :"
echo -n '1:'; for i in $x ; do echo -n " [$i]" ; done ; echo
@@ -3711,53 +3785,80 @@ stdin:
expected-stdout:
1: [] [b] []
2: [:b::]
- <3> <> <b> <>
- <4> <:b::>
+ <3> <> <b> <> .
+ <4> <:b::> .
5: [a] [b]
- <6> <a> <b>
+ <6> <a> <b> .
7: [a] [] [c]
- <8> <a> <> <c>
+ <8> <a> <> <c> .
9: [h] [ith] [ere]
- <10> <h> <ith> <ere>
- <11> <h:ith:ere>
+ <10> <h> <ith> <ere> .
+ <11> <h:ith:ere> .
12: [A] [B] [] [D]
- <13> <A> <B> <> <D>
+ <13> <A> <B> <> <D> .
---
name: IFS-subst-2
description:
Check leading whitespace after trim does not make a field
stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
x="X 1 2"
showargs 1 shift ${x#X}
expected-stdout:
- <1> <shift> <1> <2>
+ <1> <shift> <1> <2> .
---
-name: IFS-subst-3
+name: IFS-subst-3-arr
description:
Check leading IFS non-whitespace after trim does make a field
but leading IFS whitespace does not, nor empty replacements
stdin:
- showargs() { for i; do echo -n " <$i>"; done; echo; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
showargs 0 ${-+}
IFS=:
showargs 1 ${-+:foo:bar}
IFS=' '
showargs 2 ${-+ foo bar}
expected-stdout:
- <0>
- <1> <> <foo> <bar>
- <2> <foo> <bar>
+ <0> .
+ <1> <> <foo> <bar> .
+ <2> <foo> <bar> .
+---
+name: IFS-subst-3-ass
+description:
+ Check non-field semantics
+stdin:
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
+ showargs 0 x=${-+}
+ IFS=:
+ showargs 1 x=${-+:foo:bar}
+ IFS=' '
+ showargs 2 x=${-+ foo bar}
+expected-stdout:
+ <0> <x=> .
+ <1> <x=> <foo> <bar> .
+ <2> <x=> <foo> <bar> .
+---
+name: IFS-subst-3-lcl
+description:
+ Check non-field semantics, smaller corner case (LP#1381965)
+stdin:
+ set -x
+ local regex=${2:-}
+ exit 1
+expected-exit: e != 0
+expected-stderr-pattern:
+ /regex=/
---
name: IFS-subst-4-1
description:
reported by mikeserv
stdin:
+ pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a
IFS= ; q="$*" ; nq=$*
- printf '<%s>\n' "$*" $* "$q" "$nq"
+ pfn "$*" $* "$q" "$nq"
[ "$q" = "$nq" ] && echo =true || echo =false
expected-stdout:
<spacedivdedargument
@@ -3776,11 +3877,12 @@ name: IFS-subst-4-2
description:
extended testsuite based on problem by mikeserv
stdin:
+ pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a
IFS= ; q="$@" ; nq=$@
- printf '<%s>\n' "$*" $* "$q" "$nq"
+ pfn "$*" $* "$q" "$nq"
[ "$q" = "$nq" ] && echo =true || echo =false
expected-stdout:
<spacedivdedargument
@@ -3799,6 +3901,7 @@ name: IFS-subst-4-3
description:
extended testsuite based on problem by mikeserv
stdin:
+ pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a; IFS=
@@ -3806,14 +3909,14 @@ stdin:
nqs=$*
qk="$@"
nqk=$@
- printf '= qs '; printf '<%s>\n' "$qs"
- printf '=nqs '; printf '<%s>\n' "$nqs"
- printf '= qk '; printf '<%s>\n' "$qk"
- printf '=nqk '; printf '<%s>\n' "$nqk"
- printf '~ qs '; printf '<%s>\n' "$*"
- printf '~nqs '; printf '<%s>\n' $*
- printf '~ qk '; printf '<%s>\n' "$@"
- printf '~nqk '; printf '<%s>\n' $@
+ print -nr -- '= qs '; pfn "$qs"
+ print -nr -- '=nqs '; pfn "$nqs"
+ print -nr -- '= qk '; pfn "$qk"
+ print -nr -- '=nqk '; pfn "$nqk"
+ print -nr -- '~ qs '; pfn "$*"
+ print -nr -- '~nqs '; pfn $*
+ print -nr -- '~ qk '; pfn "$@"
+ print -nr -- '~nqk '; pfn $@
expected-stdout:
= qs <spacedivdedargument
here>
@@ -3842,21 +3945,22 @@ name: IFS-subst-4-4
description:
extended testsuite based on problem by mikeserv
stdin:
+ pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a; IFS=
qs="$*"
- printf '= qs '; printf '<%s>\n' "$qs"
- printf '~ qs '; printf '<%s>\n' "$*"
+ print -nr -- '= qs '; pfn "$qs"
+ print -nr -- '~ qs '; pfn "$*"
nqs=$*
- printf '=nqs '; printf '<%s>\n' "$nqs"
- printf '~nqs '; printf '<%s>\n' $*
+ print -nr -- '=nqs '; pfn "$nqs"
+ print -nr -- '~nqs '; pfn $*
qk="$@"
- printf '= qk '; printf '<%s>\n' "$qk"
- printf '~ qk '; printf '<%s>\n' "$@"
+ print -nr -- '= qk '; pfn "$qk"
+ print -nr -- '~ qk '; pfn "$@"
nqk=$@
- printf '=nqk '; printf '<%s>\n' "$nqk"
- printf '~nqk '; printf '<%s>\n' $@
+ print -nr -- '=nqk '; pfn "$nqk"
+ print -nr -- '~nqk '; pfn $@
expected-stdout:
= qs <spacedivdedargument
here>
@@ -3885,22 +3989,23 @@ name: IFS-subst-4-4p
description:
extended testsuite based on problem by mikeserv
stdin:
+ pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a; IFS=
unset v
qs=${v:-"$*"}
- printf '= qs '; printf '<%s>\n' "$qs"
- printf '~ qs '; printf '<%s>\n' ${v:-"$*"}
+ print -nr -- '= qs '; pfn "$qs"
+ print -nr -- '~ qs '; pfn ${v:-"$*"}
nqs=${v:-$*}
- printf '=nqs '; printf '<%s>\n' "$nqs"
- printf '~nqs '; printf '<%s>\n' ${v:-$*}
+ print -nr -- '=nqs '; pfn "$nqs"
+ print -nr -- '~nqs '; pfn ${v:-$*}
qk=${v:-"$@"}
- printf '= qk '; printf '<%s>\n' "$qk"
- printf '~ qk '; printf '<%s>\n' ${v:-"$@"}
+ print -nr -- '= qk '; pfn "$qk"
+ print -nr -- '~ qk '; pfn ${v:-"$@"}
nqk=${v:-$@}
- printf '=nqk '; printf '<%s>\n' "$nqk"
- printf '~nqk '; printf '<%s>\n' ${v:-$@}
+ print -nr -- '=nqk '; pfn "$nqk"
+ print -nr -- '~nqk '; pfn ${v:-$@}
expected-stdout:
= qs <spacedivdedargument
here>
@@ -3929,21 +4034,22 @@ name: IFS-subst-4-5
description:
extended testsuite based on problem by mikeserv
stdin:
+ pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a; IFS=,
qs="$*"
- printf '= qs '; printf '<%s>\n' "$qs"
- printf '~ qs '; printf '<%s>\n' "$*"
+ print -nr -- '= qs '; pfn "$qs"
+ print -nr -- '~ qs '; pfn "$*"
nqs=$*
- printf '=nqs '; printf '<%s>\n' "$nqs"
- printf '~nqs '; printf '<%s>\n' $*
+ print -nr -- '=nqs '; pfn "$nqs"
+ print -nr -- '~nqs '; pfn $*
qk="$@"
- printf '= qk '; printf '<%s>\n' "$qk"
- printf '~ qk '; printf '<%s>\n' "$@"
+ print -nr -- '= qk '; pfn "$qk"
+ print -nr -- '~ qk '; pfn "$@"
nqk=$@
- printf '=nqk '; printf '<%s>\n' "$nqk"
- printf '~nqk '; printf '<%s>\n' $@
+ print -nr -- '=nqk '; pfn "$nqk"
+ print -nr -- '~nqk '; pfn $@
expected-stdout:
= qs <space,divded,argument
here>
@@ -3972,22 +4078,23 @@ name: IFS-subst-4-5p
description:
extended testsuite based on problem by mikeserv
stdin:
+ pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a; IFS=,
unset v
qs=${v:-"$*"}
- printf '= qs '; printf '<%s>\n' "$qs"
- printf '~ qs '; printf '<%s>\n' ${v:-"$*"}
+ print -nr -- '= qs '; pfn "$qs"
+ print -nr -- '~ qs '; pfn ${v:-"$*"}
nqs=${v:-$*}
- printf '=nqs '; printf '<%s>\n' "$nqs"
- printf '~nqs '; printf '<%s>\n' ${v:-$*}
+ print -nr -- '=nqs '; pfn "$nqs"
+ print -nr -- '~nqs '; pfn ${v:-$*}
qk=${v:-"$@"}
- printf '= qk '; printf '<%s>\n' "$qk"
- printf '~ qk '; printf '<%s>\n' ${v:-"$@"}
+ print -nr -- '= qk '; pfn "$qk"
+ print -nr -- '~ qk '; pfn ${v:-"$@"}
nqk=${v:-$@}
- printf '=nqk '; printf '<%s>\n' "$nqk"
- printf '~nqk '; printf '<%s>\n' ${v:-$@}
+ print -nr -- '=nqk '; pfn "$nqk"
+ print -nr -- '~nqk '; pfn ${v:-$@}
expected-stdout:
= qs <space,divded,argument
here>
@@ -4026,38 +4133,55 @@ description:
'emulate sh' zsh has extra fields in
- a5ins (IFS_NWS unquoted $*)
- b5ins, matching mksh’s
+ !!WARNING!! more to come: http://austingroupbugs.net/view.php?id=888
stdin:
- "$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=; set -- "" 2 ""; pfb $*; x=$*; pfn "$x"'
echo '=a1zns'
- "$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=; set -- "" 2 ""; pfb "$*"; x="$*"; pfn "$x"'
echo '=a2zqs'
- "$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=; set -- "" 2 ""; pfb $@; x=$@; pfn "$x"'
echo '=a3zna'
- "$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=; set -- "" 2 ""; pfb "$@"; x="$@"; pfn "$x"'
echo '=a4zqa'
- "$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=,; set -- "" 2 ""; pfb $*; x=$*; pfn "$x"'
echo '=a5ins'
- "$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=,; set -- "" 2 ""; pfb "$*"; x="$*"; pfn "$x"'
echo '=a6iqs'
- "$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=,; set -- "" 2 ""; pfb $@; x=$@; pfn "$x"'
echo '=a7ina'
- "$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=,; set -- "" 2 ""; pfb "$@"; x="$@"; pfn "$x"'
echo '=a8iqa'
- "$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=; set -- A B "" "" C; pfb $*; x=$*; pfn "$x"'
echo '=b1zns'
- "$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=; set -- A B "" "" C; pfb "$*"; x="$*"; pfn "$x"'
echo '=b2zqs'
- "$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=; set -- A B "" "" C; pfb $@; x=$@; pfn "$x"'
echo '=b3zna'
- "$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=; set -- A B "" "" C; pfb "$@"; x="$@"; pfn "$x"'
echo '=b4zqa'
- "$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=,; set -- A B "" "" C; pfb $*; x=$*; pfn "$x"'
echo '=b5ins'
- "$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=,; set -- A B "" "" C; pfb "$*"; x="$*"; pfn "$x"'
echo '=b6iqs'
- "$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=,; set -- A B "" "" C; pfb $@; x=$@; pfn "$x"'
echo '=b7ina'
- "$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+ "$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
+ IFS=,; set -- A B "" "" C; pfb "$@"; x="$@"; pfn "$x"'
echo '=b8iqa'
expected-stdout:
[2]
@@ -4133,13 +4257,69 @@ expected-stdout:
<A B C>
=b8iqa
---
+name: IFS-subst-6
+description:
+ Regression wrt. vector expansion in trim
+stdin:
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
+ IFS=
+ x=abc
+ set -- a b
+ showargs ${x#$*}
+expected-stdout:
+ <c> .
+---
+name: IFS-subst-7
+description:
+ ksh93 bug wrt. vector expansion in trim
+stdin:
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
+ IFS="*"
+ a=abcd
+ set -- '' c
+ showargs "$*" ${a##"$*"}
+expected-stdout:
+ <*c> <abcd> .
+---
+name: IFS-subst-8
+description:
+ http://austingroupbugs.net/view.php?id=221
+stdin:
+ n() { echo "$#"; }; n "${foo-$@}"
+expected-stdout:
+ 1
+---
+name: IFS-subst-9
+description:
+ Scalar context for $*/$@ in [[ and case
+stdin:
+ "$__progname" -c 'IFS=; set a b; [[ $* = "$1$2" ]]; echo 1 $?' sh a b
+ "$__progname" -c 'IFS=; [[ $* = ab ]]; echo 2 "$?"' sh a b
+ "$__progname" -c 'IFS=; [[ "$*" = ab ]]; echo 3 "$?"' sh a b
+ "$__progname" -c 'IFS=; [[ $* = a ]]; echo 4 "$?"' sh a b
+ "$__progname" -c 'IFS=; [[ "$*" = a ]]; echo 5 "$?"' sh a b
+ "$__progname" -c 'IFS=; [[ "$@" = a ]]; echo 6 "$?"' sh a b
+ "$__progname" -c 'IFS=; case "$@" in a) echo 7 a;; ab) echo 7 b;; a\ b) echo 7 ok;; esac' sh a b
+ "$__progname" -c 'IFS=; case $* in a) echo 8 a;; ab) echo 8 ok;; esac' sh a b
+ "$__progname" -c 'pfsp() { for s_arg in "$@"; do print -nr -- "<$s_arg> "; done; print .; }; IFS=; star=$* at="$@"; pfsp 9 "$star" "$at"' sh a b
+expected-stdout:
+ 1 0
+ 2 0
+ 3 0
+ 4 1
+ 5 1
+ 6 1
+ 7 ok
+ 8 ok
+ <9> <ab> <a b> .
+---
name: IFS-arith-1
description:
http://austingroupbugs.net/view.php?id=832
stdin:
${ZSH_VERSION+false} || emulate sh
${BASH_VERSION+set -o posix}
- showargs() { for x in "$@"; do echo -n "<$x> "; done; echo .; }
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS=0
showargs $((1230456))
expected-stdout:
@@ -7063,6 +7243,7 @@ description:
XXX if the OS can already execute them, we lose
note: cygwin execve(2) doesn't return to us with ENOEXEC, we lose
note: Ultrix perl5 t4 returns 65280 (exit-code 255) and no text
+ XXX fails when LD_PRELOAD is set with -e and Perl chokes it (ASan)
need-pass: no
category: !os:cygwin,!os:msys,!os:ultrix,!os:uwin-nt,!smksh
env-setup: !FOO=BAR!
@@ -8013,6 +8194,66 @@ expected-stdout:
.fnr:f:
.f2r:f:
---
+name: unset-fnc-local-ksh
+description:
+ Check that “unset” removes a previous “local”
+ (ksh93 syntax compatible version); apparently,
+ there are shells which fail this?
+stdin:
+ function f {
+ echo f0: $x
+ typeset x
+ echo f1: $x
+ x=fa
+ echo f2: $x
+ unset x
+ echo f3: $x
+ x=fb
+ echo f4: $x
+ }
+ x=o
+ echo before: $x
+ f
+ echo after: $x
+expected-stdout:
+ before: o
+ f0: o
+ f1:
+ f2: fa
+ f3: o
+ f4: fb
+ after: fb
+---
+name: unset-fnc-local-sh
+description:
+ Check that “unset” removes a previous “local”
+ (Debian Policy §10.4 sh version); apparently,
+ there are shells which fail this?
+stdin:
+ f() {
+ echo f0: $x
+ local x
+ echo f1: $x
+ x=fa
+ echo f2: $x
+ unset x
+ echo f3: $x
+ x=fb
+ echo f4: $x
+ }
+ x=o
+ echo before: $x
+ f
+ echo after: $x
+expected-stdout:
+ before: o
+ f0: o
+ f1:
+ f2: fa
+ f3: o
+ f4: fb
+ after: fb
+---
name: varexpand-substr-1
description:
Check if bash-style substring expansion works
@@ -8172,13 +8413,21 @@ name: varexpand-null-1
description:
Ensure empty strings expand emptily
stdin:
- print x ${a} ${b} y
- print z ${a#?} ${b%?} w
- print v ${a=} ${b/c/d} u
-expected-stdout:
- x y
- z w
- v u
+ print s ${a} . ${b} S
+ print t ${a#?} . ${b%?} T
+ print r ${a=} . ${b/c/d} R
+ print q
+ print s "${a}" . "${b}" S
+ print t "${a#?}" . "${b%?}" T
+ print r "${a=}" . "${b/c/d}" R
+expected-stdout:
+ s . S
+ t . T
+ r . R
+ q
+ s . S
+ t . T
+ r . R
---
name: varexpand-null-2
description:
@@ -8194,13 +8443,41 @@ expected-stdout:
name: varexpand-null-3
description:
Ensure concatenating behaviour matches other shells
- although the line 2<> is probably wrong? XNULLSUB case.
stdin:
- x=; printf "1<%s>\n" "$x$@"
- set A; printf "2<%s>\n" "${@:+}"
-expected-stdout:
- 1<>
- 2<>
+ showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
+ x=; showargs 1 "$x"$@
+ set A; showargs 2 "${@:+}"
+ n() { echo "$#"; }
+ unset e
+ set -- a b
+ n """$@"
+ n "$@"
+ n "$@"""
+ n "$e""$@"
+ n "$@"
+ n "$@""$e"
+ set --
+ n """$@"
+ n "$@"
+ n "$@"""
+ n "$e""$@"
+ n "$@"
+ n "$@""$e"
+expected-stdout:
+ <1> <> .
+ <2> <> .
+ 2
+ 2
+ 2
+ 2
+ 2
+ 2
+ 1
+ 0
+ 1
+ 1
+ 0
+ 1
---
name: print-funny-chars
description:
@@ -10921,6 +11198,7 @@ stdin:
(mypid=$$; try mypid)
echo =15
) 2>&1 | sed -e 's/^[^]]*]//' -e 's/^[^:]*: *//'
+ exit ${PIPESTATUS[0]}
expected-stdout:
y
=1
@@ -11655,3 +11933,26 @@ expected-stdout:
expected-stderr-pattern:
/.*/
---
+name: xtrace-2
+description:
+ Check that "set -x" is off during PS4 expansion
+stdin:
+ f() {
+ print -n "(f1:$-)"
+ set -x
+ print -n "(f2:$-)"
+ }
+ PS4='[(p:$-)$(f)] '
+ print "(o0:$-)"
+ set -x -o inherit-xtrace
+ print "(o1:$-)"
+ set +x
+ print "(o2:$-)"
+expected-stdout:
+ (o0:sh)
+ (o1:shx)
+ (o2:sh)
+expected-stderr:
+ [(p:sh)(f1:sh)(f2:sh)] print '(o1:shx)'
+ [(p:sh)(f1:sh)(f2:sh)] set +x
+---
diff --git a/src/dot.mkshrc b/src/dot.mkshrc
index 233a10c..4878fd7 100644
--- a/src/dot.mkshrc
+++ b/src/dot.mkshrc
@@ -1,8 +1,8 @@
# $Id$
-# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89 2014/07/28 21:45:44 tg Exp $
+# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89.2.1 2015/01/11 22:39:44 tg Exp $
#-
# Copyright (c) 2002, 2003, 2004, 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
@@ -67,7 +67,7 @@ else
local dasc line i
cat "$@" | { set +U; if read -arN -1 line; then
- typeset -i1 line
+ typeset -i1 'line[*]'
i=0
while (( i < ${#line[*]} )); do
hv=${line[i++]}
@@ -263,9 +263,8 @@ function smores {
# base64 encoder and decoder, RFC compliant, NUL safe
function Lb64decode {
- [[ -o utf8-mode ]]; local u=$?
+ [[ -o utf8-mode ]]; local u=$? c s="$*" t
set +U
- local c s="$*" t=
[[ -n $s ]] || { s=$(cat; print x); s=${s%x}; }
local -i i=0 j=0 n=${#s} p=0 v x
local -i16 o
@@ -302,9 +301,8 @@ function Lb64decode {
set -A Lb64encode_code -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
function Lb64encode {
- [[ -o utf8-mode ]]; local u=$?
+ [[ -o utf8-mode ]]; local u=$? c s t
set +U
- local c s t
if (( $# )); then
read -raN-1 s <<<"$*"
unset s[${#s[*]}-1]
@@ -342,9 +340,8 @@ function Lbafh_init {
Lbafh_v=0
}
function Lbafh_add {
- [[ -o utf8-mode ]]; local u=$?
+ [[ -o utf8-mode ]]; local u=$? s
set +U
- local s
if (( $# )); then
read -raN-1 s <<<"$*"
unset s[${#s[*]}-1]
diff --git a/src/edit.c b/src/edit.c
index ee5ed5c..9165ecd 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -1,6 +1,6 @@
/* $OpenBSD: edit.c,v 1.39 2013/12/17 16:37:05 deraadt Exp $ */
/* $OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $ */
-/* $OpenBSD: emacs.c,v 1.48 2013/12/17 16:37:05 deraadt Exp $ */
+/* $OpenBSD: emacs.c,v 1.49 2015/02/16 01:44:41 tedu Exp $ */
/* $OpenBSD: vi.c,v 1.28 2013/12/18 16:45:46 deraadt Exp $ */
/*-
@@ -28,7 +28,7 @@
#ifndef MKSH_NO_CMDLINE_EDITING
-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276 2014/07/13 11:34:28 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276.2.3 2015/03/01 15:42:56 tg Exp $");
/*
* in later versions we might use libtermcap for this, but since external
@@ -327,7 +327,7 @@ x_glob_hlp_tilde_and_rem_qchar(char *s, bool magic_flag)
/* ok, so split into "~foo"/"bar" or "~"/"baz" */
*cp++ = 0;
/* try to expand the tilde */
- if (!(dp = tilde(s + 1))) {
+ if (!(dp = do_tilde(s + 1))) {
/* nope, revert damage */
*--cp = '/';
} else {
@@ -592,8 +592,6 @@ x_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp,
char **words = NULL;
bool is_command;
- mkssert(buf != NULL);
-
len = x_locate_word(buf, buflen, pos, startp, &is_command);
if (!((*flagsp) & XCF_COMMAND))
is_command = false;
@@ -1009,7 +1007,6 @@ enum emacs_funcs {
static const struct x_ftab x_ftab[] = {
#define EMACSFN_ITEMS
#include "emacsfn.h"
- { 0, NULL, 0 }
};
static struct x_defbindings const x_defbindings[] = {
@@ -2240,7 +2237,6 @@ x_push(int nchars)
{
char *cp;
- mkssert(xcp != NULL);
strndupx(cp, xcp, nchars, AEDIT);
if (killstack[killsp])
afree(killstack[killsp], AEDIT);
@@ -2455,8 +2451,7 @@ x_bind(const char *a1, const char *a2,
/* List function names */
if (list) {
for (f = 0; f < NELEM(x_ftab); f++)
- if (x_ftab[f].xf_name &&
- !(x_ftab[f].xf_flags & XF_NOBIND))
+ if (!(x_ftab[f].xf_flags & XF_NOBIND))
shprintf("%s\n", x_ftab[f].xf_name);
return (0);
}
@@ -2517,8 +2512,7 @@ x_bind(const char *a1, const char *a2,
#endif
} else {
for (f = 0; f < NELEM(x_ftab); f++)
- if (x_ftab[f].xf_name &&
- strcmp(x_ftab[f].xf_name, a2) == 0)
+ if (!strcmp(x_ftab[f].xf_name, a2))
break;
if (f == NELEM(x_ftab) || x_ftab[f].xf_flags & XF_NOBIND) {
bi_errorf("%s: %s %s", a2, "no such", Tfunction);
diff --git a/src/eval.c b/src/eval.c
index 49a4c33..f9c189d 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2,7 +2,7 @@
/*-
* 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
@@ -23,7 +23,7 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.153 2014/10/07 15:22:16 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.158.2.4 2015/03/01 15:42:58 tg Exp $");
/*
* string expansion
@@ -59,10 +59,11 @@ typedef struct {
#define XSUBMID 6 /* middle of expanding ${} */
/* States used for field splitting */
-#define IFS_WORD 0 /* word has chars (or quotes) */
+#define IFS_WORD 0 /* word has chars (or quotes except "$@") */
#define IFS_WS 1 /* have seen IFS white-space */
#define IFS_NWS 2 /* have seen IFS non-white-space */
#define IFS_IWS 3 /* begin of word, ignore IFS WS */
+#define IFS_QUOTE 4 /* beg.w/quote, become IFS_WORD unless "$@" */
static int varsub(Expand *, const char *, const char *, int *, int *);
static int comsub(Expand *, const char *, int);
@@ -70,7 +71,7 @@ static char *valsub(struct op *, Area *);
static char *trimsub(char *, char *, int);
static void glob(char *, XPtrV *, bool);
static void globit(XString *, char **, char *, XPtrV *, int);
-static const char *maybe_expand_tilde(const char *, XString *, char **, int);
+static const char *maybe_expand_tilde(const char *, XString *, char **, bool);
#ifndef MKSH_NOPWNAM
static char *homedir(char *);
#endif
@@ -237,7 +238,7 @@ expand(
/* record number of trailing newlines in COMSUB */
int newlines = 0;
bool saw_eq, make_magic;
- int tilde_ok;
+ unsigned int tilde_ok;
size_t len;
char *cp;
@@ -246,7 +247,7 @@ expand(
/* for alias, readonly, set, typeset commands */
if ((f & DOVACHECK) && is_wdvarassign(ccp)) {
f &= ~(DOVACHECK | DOBLANK | DOGLOB | DOTILDE);
- f |= DOASNTILDE | DOASNFIELD;
+ f |= DOASNTILDE | DOSCALAR;
}
if (Flag(FNOGLOB))
f &= ~DOGLOB;
@@ -290,7 +291,17 @@ expand(
c = *sp++;
break;
case OQUOTE:
- word = IFS_WORD;
+ switch (word) {
+ case IFS_QUOTE:
+ /* """something */
+ word = IFS_WORD;
+ break;
+ case IFS_WORD:
+ break;
+ default:
+ word = IFS_QUOTE;
+ break;
+ }
tilde_ok = 0;
quote = 1;
continue;
@@ -383,6 +394,8 @@ expand(
if (f & DOBLANK)
doblank++;
tilde_ok = 0;
+ if (word == IFS_QUOTE && type != XNULLSUB)
+ word = IFS_WORD;
if (type == XBASE) {
/* expand? */
if (!st->next) {
@@ -516,7 +529,6 @@ expand(
/* check for special cases */
d = str_val(st->var);
- mkssert(d != NULL);
switch (*pat) {
case '#':
/* anchor at begin */
@@ -622,7 +634,7 @@ expand(
case '%':
/* ! DOBLANK,DOBRACE,DOTILDE */
f = (f & DONTRUNCOMMAND) |
- DOPAT | DOTEMP;
+ DOPAT | DOTEMP | DOSCALAR;
st->quotew = quote = 0;
/*
* Prepend open pattern (so |
@@ -631,7 +643,7 @@ expand(
*/
if (!Flag(FSH)) {
*dp++ = MAGIC;
- *dp++ = '@' | 0x80;
+ *dp++ = 0x80 | '@';
}
break;
case '=':
@@ -664,7 +676,11 @@ expand(
f |= DOTEMP;
/* FALLTHROUGH */
default:
- word = quote ? IFS_WORD : IFS_IWS;
+ /* '-' '+' '?' */
+ if (quote)
+ word = IFS_WORD;
+ else if (dp == Xstring(ds, dp))
+ word = IFS_IWS;
/* Enable tilde expansion */
tilde_ok = 1;
f |= DOTILDE;
@@ -704,10 +720,16 @@ expand(
x.str = trimsub(str_val(st->var),
dp, st->stype);
if (x.str[0] != '\0') {
- word = IFS_WS;
+ word = IFS_IWS;
type = XSUB;
- } else
- type = quote ? XSUB : XNULLSUB;
+ } else if (quote) {
+ word = IFS_WORD;
+ type = XSUB;
+ } else {
+ if (dp == Xstring(ds, dp))
+ word = IFS_IWS;
+ type = XNULLSUB;
+ }
if (f & DOBLANK)
doblank++;
st = st->prev;
@@ -743,7 +765,7 @@ expand(
if (f & DOBLANK)
doblank++;
st = st->prev;
- word = quote || (!*x.str && (f & DOASNFIELD)) ? IFS_WORD : IFS_WS;
+ word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS;
continue;
case '?': {
char *s = Xrestpos(ds, dp, st->base);
@@ -759,11 +781,12 @@ expand(
case 0x100 | 'Q':
dp = Xrestpos(ds, dp, st->base);
type = XSUB;
- word = quote || (!*x.str && (f & DOASNFIELD)) ? IFS_WORD : IFS_WS;
+ word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS;
if (f & DOBLANK)
doblank++;
st = st->prev;
continue;
+ /* default: '-' '+' */
}
st = st->prev;
type = XBASE;
@@ -799,8 +822,8 @@ expand(
type = XBASE;
if (f & DOBLANK) {
doblank--;
- if (dp == Xstring(ds, dp))
- word = IFS_WS;
+ if (dp == Xstring(ds, dp) && word != IFS_WORD)
+ word = IFS_IWS;
}
continue;
@@ -834,15 +857,20 @@ expand(
continue;
}
c = ifs0;
- if ((f & DOASNFIELD)) {
- /* assignment, do not field-split */
+ if ((f & DOHEREDOC)) {
+ /* pseudo-field-split reliably */
+ if (c == 0)
+ c = ' ';
+ break;
+ }
+ if ((f & DOSCALAR)) {
+ /* do not field-split */
if (x.split) {
c = ' ';
break;
}
- if (c == 0) {
+ if (c == 0)
continue;
- }
}
if (c == 0) {
if (quote && !x.split)
@@ -867,7 +895,7 @@ expand(
/* $(<...) failed */
subst_exstat = 1;
/* fake EOF */
- c = EOF;
+ c = -1;
} else if (newlines) {
/* spit out saved NLs */
c = '\n';
@@ -877,13 +905,13 @@ expand(
if (c == '\n')
/* save newlines */
newlines++;
- if (newlines && c != EOF) {
+ if (newlines && c != -1) {
shf_ungetc(c, x.u.shf);
c = '\n';
--newlines;
}
}
- if (c == EOF) {
+ if (c == -1) {
newlines = 0;
if (x.u.shf)
shf_close(x.u.shf);
@@ -911,7 +939,7 @@ expand(
* IFS_IWS -/WS w/NWS -
* (w means generate a word)
*/
- if ((word == IFS_WORD) || (c &&
+ if ((word == IFS_WORD) || (word == IFS_QUOTE) || (c &&
(word == IFS_IWS || word == IFS_NWS) &&
!ctype(c, C_IFSWS))) {
emit_word:
@@ -1023,7 +1051,7 @@ expand(
tcp = maybe_expand_tilde(sp,
&ds, &tdp,
- f & DOASNTILDE);
+ tobool(f & DOASNTILDE));
if (tcp) {
if (dp != tdp)
word = IFS_WORD;
@@ -1659,7 +1687,7 @@ debunk(char *dp, const char *sp, size_t dlen)
* past the name, otherwise returns 0.
*/
static const char *
-maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign)
+maybe_expand_tilde(const char *p, XString *dsp, char **dpp, bool isassign)
{
XString ts;
char *dp = *dpp;
@@ -1676,7 +1704,7 @@ maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign)
}
*tp = '\0';
r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ?
- tilde(Xstring(ts, tp)) : NULL;
+ do_tilde(Xstring(ts, tp)) : NULL;
Xfree(ts, tp);
if (r) {
while (*r) {
@@ -1698,7 +1726,7 @@ maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign)
*/
char *
-tilde(char *cp)
+do_tilde(char *cp)
{
char *dp = null;
@@ -1745,28 +1773,30 @@ homedir(char *name)
static void
alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
{
- int count = 0;
+ unsigned int count = 0;
char *brace_start, *brace_end, *comma = NULL;
char *field_start;
- char *p;
+ char *p = exp_start;
/* search for open brace */
- for (p = exp_start; (p = strchr(p, MAGIC)) && p[1] != '{' /*}*/; p += 2)
- ;
+ while ((p = strchr(p, MAGIC)) && p[1] != '{' /*}*/)
+ p += 2;
brace_start = p;
/* find matching close brace, if any */
if (p) {
comma = NULL;
count = 1;
- for (p += 2; *p && count; p++) {
- if (ISMAGIC(*p)) {
- if (*++p == '{' /*}*/)
- count++;
+ p += 2;
+ while (*p && count) {
+ if (ISMAGIC(*p++)) {
+ if (*p == '{' /*}*/)
+ ++count;
else if (*p == /*{*/ '}')
--count;
else if (*p == ',' && count == 1)
comma = p;
+ ++p;
}
}
}
@@ -1795,7 +1825,7 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
for (p = brace_start + 2; p != brace_end; p++) {
if (ISMAGIC(*p)) {
if (*++p == '{' /*}*/)
- count++;
+ ++count;
else if ((*p == /*{*/ '}' && --count == 0) ||
(*p == ',' && count == 1)) {
char *news;
diff --git a/src/exec.c b/src/exec.c
index b60511d..9b94aaf 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -2,7 +2,7 @@
/*-
* 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
@@ -23,7 +23,7 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.133 2014/10/03 17:32:11 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.137.2.2 2015/03/01 15:42:59 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
@@ -32,7 +32,7 @@ __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.133 2014/10/03 17:32:11 tg Exp $");
static int comexec(struct op *, struct tbl * volatile, const char **,
int volatile, volatile int *);
static void scriptexec(struct op *, const char **) MKSH_A_NORETURN;
-static int call_builtin(struct tbl *, const char **, const char *);
+static int call_builtin(struct tbl *, const char **, const char *, bool);
static int iosetup(struct ioword *, struct tbl *);
static int herein(struct ioword *, char **);
static const char *do_selectargs(const char **, bool);
@@ -81,6 +81,8 @@ execute(struct op * volatile t,
/* we want to run an executable, do some variance checks */
if (t->type == TCOM) {
/* check if this is 'var=<<EOF' */
+ /*XXX this is broken, don’t use! */
+ /*XXX https://bugs.launchpad.net/mksh/+bug/1380389 */
if (
/* we have zero arguments, i.e. no programme to run */
t->args[0] == NULL &&
@@ -94,20 +96,23 @@ execute(struct op * volatile t,
/* 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=") */
- ccp[0] == CHAR && ccp[1] == '=' && ccp[2] == EOS &&
+ ccp[0] == CHAR && ((ccp[1] == '=' && ccp[2] == EOS) ||
+ /* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR &&
+ ccp[3] == '=' && ccp[4] == EOS)) &&
/* plus we can have a here document content */
herein(t->ioact[0], &cp) == 0 && cp && *cp) {
char *sp = cp, *dp;
- size_t n = ccp - t->vars[0] + 2, z;
+ size_t n = ccp - t->vars[0] + (ccp[1] == '+' ? 4 : 2);
+ size_t z;
/* drop redirection (will be garbage collected) */
t->ioact = NULL;
/* set variable to its expanded value */
- z = strlen(cp) + 1;
- if (notoktomul(z, 2) || notoktoadd(z * 2, n))
+ z = strlen(cp);
+ if (notoktomul(z, 2) || notoktoadd(z * 2, n + 1))
internal_errorf(Toomem, (size_t)-1);
- dp = alloc(z * 2 + n, ATEMP);
+ dp = alloc(z * 2 + n + 1, APERM);
memcpy(dp, t->vars[0], n);
t->vars[0] = dp;
dp += n;
@@ -398,7 +403,7 @@ execute(struct op * volatile t,
case TCASE:
i = 0;
- ccp = evalstr(t->str, DOTILDE);
+ ccp = evalstr(t->str, DOTILDE | DOSCALAR);
for (t = t->left; t != NULL && t->type == TPAT; t = t->right) {
for (ap = (const char **)t->vars; *ap; ap++) {
if (i || ((s = evalstr(*ap, DOTILDE|DOPAT)) &&
@@ -441,7 +446,6 @@ execute(struct op * volatile t,
case TEXEC:
/* an eval'd TCOM */
- s = t->args[0];
up = makenv();
restoresigs();
cleanup_proc_env();
@@ -455,7 +459,7 @@ execute(struct op * volatile t,
if (rv == ENOEXEC)
scriptexec(t, (const char **)up);
else
- errorf("%s: %s", s, cstrerror(rv));
+ errorf("%s: %s", t->str, cstrerror(rv));
}
Break:
exstat = rv & 0xFF;
@@ -500,18 +504,21 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
/* Must be static (XXX but why?) */
static struct op texec;
int type_flags;
- bool keepasn_ok;
+ bool resetspec;
int fcflags = FC_BI|FC_FUNC|FC_PATH;
- bool bourne_function_call = false;
struct block *l_expand, *l_assign;
+ int optc;
+ const char *exec_argv0 = NULL;
+ bool exec_clrenv = false;
- /*
- * snag the last argument for $_ XXX not the same as AT&T ksh,
- * which only seems to set $_ after a newline (but not in
- * functions/dot scripts, but in interactive and script) -
- * perhaps save last arg here and set it in shell()?.
- */
+ /* snag the last argument for $_ */
if (Flag(FTALKING) && *(lastp = ap)) {
+ /*
+ * XXX not the same as AT&T ksh, which only seems to set $_
+ * after a newline (but not in functions/dot scripts, but in
+ * interactive and script) - perhaps save last arg here and
+ * set it in shell()?.
+ */
while (*++lastp)
;
/* setstr() can't fail here */
@@ -532,7 +539,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
* FOO=bar command FOO is neither kept nor exported
* PATH=... foobar use new PATH in foobar search
*/
- keepasn_ok = true;
+ resetspec = false;
while (tp && tp->type == CSHELL) {
/* undo effects of command */
fcflags = FC_BI|FC_FUNC|FC_PATH;
@@ -548,10 +555,25 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
} else if (tp->val.f == c_exec) {
if (ap[1] == NULL)
break;
- ap++;
+ ksh_getopt_reset(&builtin_opt, GF_ERROR);
+ while ((optc = ksh_getopt(ap, &builtin_opt, "a:c")) != -1)
+ switch (optc) {
+ case 'a':
+ exec_argv0 = builtin_opt.optarg;
+ break;
+ case 'c':
+ exec_clrenv = true;
+ /* ensure we can actually do this */
+ resetspec = true;
+ break;
+ default:
+ rv = 2;
+ goto Leave;
+ }
+ ap += builtin_opt.optind;
flags |= XEXEC;
} else if (tp->val.f == c_command) {
- int optc, saw_p = 0;
+ bool saw_p = false;
/*
* Ugly dealing with options in two places (here
@@ -559,8 +581,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
*/
ksh_getopt_reset(&builtin_opt, 0);
while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) == 'p')
- saw_p = 1;
- if (optc != EOF)
+ saw_p = true;
+ if (optc != -1)
/* command -vV or something */
break;
/* don't look for functions */
@@ -579,7 +601,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
* POSIX says special builtins lose their status
* if accessed using command.
*/
- keepasn_ok = false;
+ resetspec = true;
if (!ap[0]) {
/* ensure command with no args exits with 0 */
subst_exstat = 0;
@@ -614,20 +636,21 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
if (t->u.evalflags & DOTCOMEXEC)
flags |= XEXEC;
l_expand = e->loc;
- if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN))))
+ if (!resetspec && (!ap[0] || (tp && (tp->flag & KEEPASN))))
type_flags = 0;
else {
/* create new variable/function block */
newblock();
/* ksh functions don't keep assignments, POSIX functions do. */
- if (keepasn_ok && tp && tp->type == CFUNC &&
- !(tp->flag & FKSH)) {
- bourne_function_call = true;
+ if (!resetspec && tp && tp->type == CFUNC &&
+ !(tp->flag & FKSH))
type_flags = EXPORT;
- } else
+ else
type_flags = LOCAL|LOCAL_COPY|EXPORT;
}
l_assign = e->loc;
+ if (exec_clrenv)
+ l_assign->flags |= BF_STOPENV;
if (Flag(FEXPORT))
type_flags |= EXPORT;
if (Flag(FXTRACE))
@@ -635,7 +658,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
for (i = 0; t->vars[i]; i++) {
/* do NOT lookup in the new var/fn block just created */
e->loc = l_expand;
- cp = evalstr(t->vars[i], DOASNTILDE | DOASNFIELD);
+ cp = evalstr(t->vars[i], DOASNTILDE | DOSCALAR);
e->loc = l_assign;
if (Flag(FXTRACE)) {
const char *ccp;
@@ -651,8 +674,6 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
}
/* but assign in there as usual */
typeset(cp, type_flags, 0, 0, 0);
- if (bourne_function_call && !(type_flags & EXPORT))
- typeset(cp, LOCAL | LOCAL_COPY | EXPORT, 0, 0, 0);
}
if (Flag(FXTRACE)) {
@@ -684,8 +705,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
/* shell built-in */
case CSHELL:
- rv = call_builtin(tp, (const char **)ap, null);
- if (!keepasn_ok && tp->val.f == c_shift) {
+ rv = call_builtin(tp, (const char **)ap, null, resetspec);
+ if (resetspec && tp->val.f == c_shift) {
l_expand->argc = l_assign->argc;
l_expand->argv = l_assign->argv;
}
@@ -810,14 +831,24 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
break;
}
- /* set $_ to programme's full path */
+ /* set $_ to program's full path */
/* setstr() can't fail here */
setstr(typeset("_", LOCAL | EXPORT, 0, INTEGER, 0),
tp->val.s, KSH_RETURN_ERROR);
- if (flags&XEXEC) {
+ /* to fork, we set up a TEXEC node and call execute */
+ texec.type = TEXEC;
+ /* for vistree/dumptree */
+ texec.left = t;
+ texec.str = tp->val.s;
+ texec.args = ap;
+
+ /* in this case we do not fork, of course */
+ if (flags & XEXEC) {
+ if (exec_argv0)
+ texec.args[0] = exec_argv0;
j_exit();
- if (!(flags&XBGND)
+ if (!(flags & XBGND)
#ifndef MKSH_UNEMPLOYED
|| Flag(FMONITOR)
#endif
@@ -827,12 +858,6 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
}
}
- /* to fork we set up a TEXEC node and call execute */
- texec.type = TEXEC;
- /* for tprint */
- texec.left = t;
- texec.str = tp->val.s;
- texec.args = ap;
rv = exchild(&texec, flags, xerrok, -1);
break;
}
@@ -849,10 +874,8 @@ scriptexec(struct op *tp, const char **ap)
{
const char *sh;
#ifndef MKSH_SMALL
- unsigned char *cp;
- /* 64 == MAXINTERP in MirBSD <sys/param.h> */
- char buf[64];
int fd;
+ unsigned char buf[68];
#endif
union mksh_ccphack args, cap;
@@ -866,33 +889,35 @@ scriptexec(struct op *tp, const char **ap)
#ifndef MKSH_SMALL
if ((fd = open(tp->str, O_RDONLY | O_BINARY)) >= 0) {
- /* read first MAXINTERP octets from file */
- if (read(fd, buf, sizeof(buf)) <= 0)
- /* read error -> no good */
- buf[0] = '\0';
+ unsigned char *cp;
+ unsigned short m;
+ ssize_t n;
+
+ /* read first couple of octets from file */
+ n = read(fd, buf, sizeof(buf) - 1);
close(fd);
+ /* read error or short read? */
+ if (n < 5)
+ goto nomagic;
+ /* terminate buffer */
+ buf[n] = '\0';
/* skip UTF-8 Byte Order Mark, if present */
- cp = (unsigned char *)buf;
- if ((cp[0] == 0xEF) && (cp[1] == 0xBB) && (cp[2] == 0xBF))
- cp += 3;
- /* save begin of shebang for later */
- fd = (char *)cp - buf; /* either 0 or (if BOM) 3 */
-
- /* scan for newline (or CR) or NUL _before_ end of buffer */
- while ((size_t)((char *)cp - buf) < sizeof(buf))
- if (*cp == '\0' || *cp == '\n' || *cp == '\r') {
- *cp = '\0';
- break;
- } else
- ++cp;
+ cp = buf + (n = ((buf[0] == 0xEF) && (buf[1] == 0xBB) &&
+ (buf[2] == 0xBF)) ? 3 : 0);
+
+ /* scan for newline or NUL (end of buffer) */
+ while (*cp && *cp != '\n')
+ ++cp;
/* if the shebang line is longer than MAXINTERP, bail out */
- if ((size_t)((char *)cp - buf) >= sizeof(buf))
+ if (!*cp)
goto noshebang;
+ /* replace newline by NUL */
+ *cp = '\0';
/* restore begin of shebang position (buf+0 or buf+3) */
- cp = (unsigned char *)(buf + fd);
- /* bail out if read error (above) or no shebang */
+ cp = buf + n;
+ /* bail out if no shebang magic found */
if ((cp[0] != '#') || (cp[1] != '!'))
goto noshebang;
@@ -918,22 +943,24 @@ scriptexec(struct op *tp, const char **ap)
if (*cp)
*tp->args-- = (char *)cp;
}
+ goto nomagic;
noshebang:
- if (buf[0] == 0x7F && buf[1] == 'E' && buf[2] == 'L' &&
- buf[3] == 'F')
+ m = buf[0] << 8 | buf[1];
+ if (m == 0x7F45 && buf[2] == 'L' && buf[3] == 'F')
errorf("%s: not executable: %d-bit ELF file", tp->str,
- 32 * ((uint8_t)buf[4]));
- fd = buf[0] << 8 | buf[1];
- if ((fd == /* OMAGIC */ 0407) ||
- (fd == /* NMAGIC */ 0410) ||
- (fd == /* ZMAGIC */ 0413) ||
- (fd == /* QMAGIC */ 0314) ||
- (fd == /* ECOFF_I386 */ 0x4C01) ||
- (fd == /* ECOFF_M68K */ 0x0150 || fd == 0x5001) ||
- (fd == /* ECOFF_SH */ 0x0500 || fd == 0x0005) ||
- (fd == /* "MZ" */ 0x4D5A) ||
- (fd == /* gzip */ 0x1F8B))
- errorf("%s: not executable: magic %04X", tp->str, fd);
+ 32 * buf[4]);
+ if ((m == /* OMAGIC */ 0407) ||
+ (m == /* NMAGIC */ 0410) ||
+ (m == /* ZMAGIC */ 0413) ||
+ (m == /* QMAGIC */ 0314) ||
+ (m == /* ECOFF_I386 */ 0x4C01) ||
+ (m == /* ECOFF_M68K */ 0x0150 || m == 0x5001) ||
+ (m == /* ECOFF_SH */ 0x0500 || m == 0x0005) ||
+ (m == /* "MZ" */ 0x4D5A) ||
+ (m == /* gzip */ 0x1F8B) || (m == /* .Z */ 0x1F9D))
+ errorf("%s: not executable: magic %04X", tp->str, m);
+ nomagic:
+ ;
}
#endif
args.ro = tp->args;
@@ -952,7 +979,7 @@ shcomexec(const char **wp)
struct tbl *tp;
tp = ktsearch(&builtins, *wp, hash(*wp));
- return (call_builtin(tp, wp, "shcomexec"));
+ return (call_builtin(tp, wp, "shcomexec", false));
}
/*
@@ -1001,8 +1028,6 @@ define(const char *name, struct op *t)
while (/* CONSTCOND */ 1) {
tp = findfunc(name, nhash, true);
- /* because findfunc:create=true */
- mkssert(tp != NULL);
if (tp->flag & ISSET)
was_set = true;
@@ -1265,22 +1290,22 @@ search_path(const char *name, const char *lpath,
}
static int
-call_builtin(struct tbl *tp, const char **wp, const char *where)
+call_builtin(struct tbl *tp, const char **wp, const char *where, bool resetspec)
{
int rv;
if (!tp)
internal_errorf("%s: %s", where, wp[0]);
builtin_argv0 = wp[0];
- builtin_flag = tp->flag;
+ 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);
rv = (*tp->val.f)(wp);
shf_flush(shl_stdout);
shl_stdout_ok = false;
- builtin_flag = 0;
builtin_argv0 = NULL;
+ builtin_spec = false;
return (rv);
}
@@ -1467,7 +1492,7 @@ hereinval(const char *content, int sub, char **resbuf, struct shf *shf)
if (yylex(sub) != LWORD)
internal_errorf("%s: %s", "herein", "yylex");
source = osource;
- ccp = evalstr(yylval.cp, 0);
+ ccp = evalstr(yylval.cp, DOSCALAR | DOHEREDOC);
}
if (resbuf == NULL)
@@ -1487,7 +1512,7 @@ herein(struct ioword *iop, char **resbuf)
struct temp *h;
int i;
- /* ksh -c 'cat << EOF' can cause this... */
+ /* ksh -c 'cat <<EOF' can cause this... */
if (iop->heredoc == NULL) {
warningf(true, "%s missing", "here document");
/* special to iosetup(): don't print error */
@@ -1522,7 +1547,7 @@ herein(struct ioword *iop, char **resbuf)
return (-2);
}
- if (shf_close(shf) == EOF) {
+ if (shf_close(shf) == -1) {
i = errno;
close(fd);
warningf(true, "can't %s temporary file %s: %s",
@@ -1559,7 +1584,8 @@ do_selectargs(const char **ap, bool print_menu)
if (print_menu || !*str_val(global("REPLY")))
pr_menu(ap);
shellf("%s", str_val(global("PS3")));
- if (call_builtin(findcom("read", FC_BI), read_args, Tselect))
+ if (call_builtin(findcom("read", FC_BI), read_args, Tselect,
+ false))
return (NULL);
s = str_val(global("REPLY"));
if (*s && getn(s, &i))
@@ -1709,6 +1735,7 @@ static const char *
dbteste_getopnd(Test_env *te, Test_op op, bool do_eval)
{
const char *s = *te->pos.wp;
+ int flags = DOTILDE | DOSCALAR;
if (!s)
return (NULL);
@@ -1719,11 +1746,9 @@ dbteste_getopnd(Test_env *te, Test_op op, bool do_eval)
return (null);
if (op == TO_STEQL || op == TO_STNEQ)
- s = evalstr(s, DOTILDE | DOPAT);
- else
- s = evalstr(s, DOTILDE);
+ flags |= DOPAT;
- return (s);
+ return (evalstr(s, flags));
}
static void
diff --git a/src/expr.c b/src/expr.c
index 057666e..6b328ad 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: expr.c,v 1.23 2013/12/17 16:37:06 deraadt Exp $ */
+/* $OpenBSD: expr.c,v 1.24 2014/12/08 14:26:31 otto Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@@ -23,7 +23,7 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.76 2014/06/24 19:53:19 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.76.2.1 2015/01/25 15:44:05 tg Exp $");
/* the order of these enums is constrained by the order of opinfo[] */
enum token {
diff --git a/src/funcs.c b/src/funcs.c
index bb7971e..9603aff 100644
--- a/src/funcs.c
+++ b/src/funcs.c
@@ -5,7 +5,7 @@
/*-
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- * 2010, 2011, 2012, 2013, 2014
+ * 2010, 2011, 2012, 2013, 2014, 2015
* Thorsten Glaser <tg@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.258 2014/09/03 19:55:51 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.259.2.2 2015/01/25 15:35:44 tg Exp $");
#if HAVE_KILLPG
/*
@@ -550,7 +550,7 @@ c_whence(const char **wp)
if (vflag || (tp->type != CALIAS && tp->type != CEXEC &&
tp->type != CTALIAS))
shf_puts(id, shl_stdout);
- if (vflag)
+ if (vflag) {
switch (tp->type) {
case CKEYWD:
case CALIAS:
@@ -559,11 +559,20 @@ c_whence(const char **wp)
shf_puts(" is a", shl_stdout);
break;
}
+ switch (tp->type) {
+ case CKEYWD:
+ case CSHELL:
+ case CTALIAS:
+ case CEXEC:
+ shf_putc(' ', shl_stdout);
+ break;
+ }
+ }
switch (tp->type) {
case CKEYWD:
if (vflag)
- shf_puts(" reserved word", shl_stdout);
+ shf_puts("reserved word", shl_stdout);
break;
case CALIAS:
if (vflag)
@@ -590,16 +599,17 @@ c_whence(const char **wp)
}
break;
case CSHELL:
- if (vflag)
- shprintf("%s %s %s",
- (tp->flag & SPEC_BI) ? " special" : null,
- "shell", Tbuiltin);
+ if (vflag) {
+ if (tp->flag & SPEC_BI)
+ shf_puts("special ", shl_stdout);
+ shprintf("%s %s", "shell", Tbuiltin);
+ }
break;
case CTALIAS:
case CEXEC:
if (tp->flag & ISSET) {
if (vflag) {
- shf_puts(" is ", shl_stdout);
+ shf_puts("is ", shl_stdout);
if (tp->type == CTALIAS)
shprintf("a tracked %s%s for ",
(tp->flag & EXPORT) ?
@@ -609,12 +619,12 @@ c_whence(const char **wp)
shf_puts(tp->val.s, shl_stdout);
} else {
if (vflag)
- shprintf(" %s\n", "not found");
+ shf_puts("not found", shl_stdout);
rv = 1;
}
break;
default:
- shprintf("%s is *GOK*", id);
+ shf_puts(" is *GOK*", shl_stdout);
break;
}
if (vflag || !rv)
@@ -1587,12 +1597,16 @@ c_shift(const char **wp)
return (1);
arg = wp[builtin_opt.optind];
- if (arg) {
- evaluate(arg, &val, KSH_UNWIND_ERROR, false);
- n = val;
- } else
+ if (!arg)
n = 1;
- if (n < 0) {
+ else if (!evaluate(arg, &val, KSH_RETURN_ERROR, false)) {
+ /* error already printed */
+ bi_errorfz();
+ return (1);
+ } else if (!(n = val)) {
+ /* nothing to do */
+ return (0);
+ } else if (n < 0) {
bi_errorf("%s: %s", arg, "bad number");
return (1);
}
@@ -1813,7 +1827,7 @@ c_read(const char **wp)
char *cp, *allocd = NULL, *xp;
const char *ccp;
XString xs;
- ptrdiff_t xsave = 0;
+ size_t xsave = 0;
mksh_ttyst tios;
bool restore_tios = false;
#if HAVE_SELECT
@@ -2417,9 +2431,8 @@ c_set(const char **wp)
return (c_typeset(args));
}
- argi = parse_args(wp, OF_SET, &setargs);
- if (argi < 0)
- return (1);
+ if ((argi = parse_args(wp, OF_SET, &setargs)) < 0)
+ return (2);
/* set $# and $* */
if (setargs) {
wp += argi - 1;
@@ -2794,8 +2807,6 @@ c_test(const char **wp)
for (argc = 0; wp[argc]; argc++)
;
- mkssert(argc > 0);
- mkssert(wp[0] != NULL);
if (strcmp(wp[0], "[") == 0) {
if (strcmp(wp[--argc], "]") != 0) {
diff --git a/src/histrap.c b/src/histrap.c
index d15cc8d..6d2badf 100644
--- a/src/histrap.c
+++ b/src/histrap.c
@@ -1,9 +1,9 @@
-/* $OpenBSD: history.c,v 1.39 2010/05/19 17:36:08 jasper Exp $ */
+/* $OpenBSD: history.c,v 1.40 2014/11/20 15:22:39 tedu Exp $ */
/* $OpenBSD: trap.c,v 1.23 2010/05/19 17:36:08 jasper Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2014
+ * 2011, 2012, 2014, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@@ -27,7 +27,7 @@
#include <sys/file.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134 2014/06/09 13:25:53 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134.2.3 2015/03/01 15:43:00 tg Exp $");
Trap sigtraps[NSIG + 1];
static struct sigaction Sigact_ign;
@@ -303,7 +303,7 @@ c_fc(const char **wp)
for (hp = rflag ? hlast : hfirst;
hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1)
shf_fprintf(shf, "%s\n", *hp);
- if (shf_close(shf) == EOF) {
+ if (shf_close(shf) == -1) {
bi_errorf("can't %s temporary file %s: %s",
"write", tf->tffn, cstrerror(errno));
return (1);
@@ -423,14 +423,14 @@ hist_get(const char *str, bool approx, bool allow_cur)
if (getn(str, &n)) {
hp = histptr + (n < 0 ? n : (n - hist_source->line));
- if ((ptrdiff_t)hp < (ptrdiff_t)history) {
+ if ((size_t)hp < (size_t)history) {
if (approx)
hp = hist_get_oldest();
else {
bi_errorf("%s: %s", str, Tnot_in_history);
hp = NULL;
}
- } else if ((ptrdiff_t)hp > (ptrdiff_t)histptr) {
+ } else if ((size_t)hp > (size_t)histptr) {
if (approx)
hp = hist_get_newest(allow_cur);
else {
@@ -634,7 +634,6 @@ histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
char **hp;
char *c, *cp;
- mkssert(cmd != NULL);
strdupx(c, cmd, APERM);
if ((cp = strchr(c, '\n')) != NULL)
*cp = '\0';
diff --git a/src/jobs.c b/src/jobs.c
index 18179c1..d919c16 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -23,7 +23,7 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105 2014/10/03 12:32:48 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105.2.1 2015/01/25 15:44:06 tg Exp $");
#if HAVE_KILLPG
#define mksh_killpg killpg
@@ -1047,7 +1047,7 @@ j_async(void)
static void
j_set_async(Job *j)
{
- Job *jl, *oldest;
+ Job *jl, *oldest;
if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE)
remove_job(async_job, "async");
@@ -1084,7 +1084,7 @@ j_set_async(Job *j)
static void
j_startjob(Job *j)
{
- Proc *p;
+ Proc *p;
j->flags |= JF_STARTED;
for (p = j->proc_list; p->next; p = p->next)
@@ -1421,8 +1421,8 @@ j_sigchld(int sig MKSH_A_UNUSED)
static void
check_job(Job *j)
{
- int jstate;
- Proc *p;
+ int jstate;
+ Proc *p;
/* XXX debugging (nasty - interrupt routine using shl_out) */
if (!(j->flags & JF_STARTED)) {
@@ -1524,14 +1524,14 @@ check_job(Job *j)
static void
j_print(Job *j, int how, struct shf *shf)
{
- Proc *p;
- int state;
- int status;
- int coredumped;
- char jobchar = ' ';
- char buf[64];
+ Proc *p;
+ int state;
+ int status;
+ int coredumped;
+ char jobchar = ' ';
+ char buf[64];
const char *filler;
- int output = 0;
+ int output = 0;
if (how == JP_PGRP) {
/*
@@ -1737,8 +1737,8 @@ static Proc *free_procs;
static Job *
new_job(void)
{
- int i;
- Job *newj, *j;
+ int i;
+ Job *newj, *j;
if (free_jobs != NULL) {
newj = free_jobs;
@@ -1766,7 +1766,7 @@ new_job(void)
static Proc *
new_proc(void)
{
- Proc *p;
+ Proc *p;
if (free_procs != NULL) {
p = free_procs;
@@ -1786,10 +1786,9 @@ new_proc(void)
static void
remove_job(Job *j, const char *where)
{
- Proc *p, *tmp;
- Job **prev, *curr;
+ Proc *p, *tmp;
+ Job **prev, *curr;
- mkssert(j != NULL);
prev = &job_list;
curr = job_list;
while (curr && curr != j) {
@@ -1830,9 +1829,8 @@ remove_job(Job *j, const char *where)
static void
put_job(Job *j, int where)
{
- Job **prev, *curr;
+ Job **prev, *curr;
- mkssert(j != NULL);
/* Remove job from list (if there) */
prev = &job_list;
curr = job_list;
@@ -1869,8 +1867,8 @@ put_job(Job *j, int where)
static int
kill_job(Job *j, int sig)
{
- Proc *p;
- int rval = 0;
+ Proc *p;
+ int rval = 0;
for (p = j->proc_list; p != NULL; p = p->next)
if (p->pid != 0)
diff --git a/src/lalloc.c b/src/lalloc.c
index f5dc830..9c1dd6d 100644
--- a/src/lalloc.c
+++ b/src/lalloc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2009, 2010, 2011, 2013
+ * Copyright (c) 2009, 2010, 2011, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@@ -20,7 +20,7 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20 2013/06/03 22:28:33 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20.2.1 2015/01/25 15:35:47 tg Exp $");
/* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */
#if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0)
@@ -29,7 +29,7 @@ __RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20 2013/06/03 22:28:33 tg Exp $");
#define remalloc(p,n) realloc_osi((p), (n))
#endif
-#define ALLOC_ISUNALIGNED(p) (((ptrdiff_t)(p)) % ALLOC_SIZE)
+#define ALLOC_ISUNALIGNED(p) (((size_t)(p)) % ALLOC_SIZE)
static ALLOC_ITEM *findptr(ALLOC_ITEM **, char *, Area *);
diff --git a/src/lex.c b/src/lex.c
index 9d39998..502284a 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -23,7 +23,7 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193 2014/06/29 11:28:28 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193.2.1 2015/01/11 22:39:50 tg Exp $");
/*
* states while lexing word
@@ -854,7 +854,7 @@ yylex(int cf)
*dp = '\0';
/* store the quoted string */
*wp++ = OQUOTE;
- XcheckN(ws, wp, (dp - sp));
+ XcheckN(ws, wp, (dp - sp) * 2);
dp = sp;
while ((c = *dp++)) {
if (c == '\\') {
@@ -1027,17 +1027,24 @@ yylex(int cf)
/* copy word to unprefixed string ident */
sp = yylval.cp;
dp = ident;
- if ((cf & HEREDELIM) && (sp[1] == '<'))
- while ((dp - ident) < IDENT) {
- if ((c = *sp++) == CHAR)
- *dp++ = *sp++;
- else if ((c != OQUOTE) && (c != CQUOTE))
- break;
+ if ((cf & HEREDELIM) && (sp[1] == '<')) {
+ herestringloop:
+ switch ((c = *sp++)) {
+ case CHAR:
+ ++sp;
+ /* FALLTHROUGH */
+ case OQUOTE:
+ case CQUOTE:
+ goto herestringloop;
+ default:
+ break;
}
- else
+ /* dummy value */
+ *dp++ = 'x';
+ } else
while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
*dp++ = *sp++;
- /* Make sure the ident array stays '\0' padded */
+ /* make sure the ident array stays NUL padded */
memset(dp, 0, (ident + IDENT) - dp + 1);
if (c != EOS)
/* word is not unquoted */
diff --git a/src/main.c b/src/main.c
index f12d9b9..59d0b1e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: main.c,v 1.54 2013/11/28 10:33:37 sobrado Exp $ */
+/* $OpenBSD: main.c,v 1.55 2015/02/09 09:09:30 jsg Exp $ */
/* $OpenBSD: tty.c,v 1.10 2014/08/10 02:44:26 guenther Exp $ */
/* $OpenBSD: io.c,v 1.25 2014/08/11 20:28:47 guenther Exp $ */
/* $OpenBSD: table.c,v 1.15 2012/02/19 07:52:30 otto Exp $ */
@@ -34,7 +34,7 @@
#include <locale.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/main.c,v 1.284 2014/10/03 17:19:27 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/main.c,v 1.285.2.2 2015/03/01 15:43:01 tg Exp $");
extern char **environ;
@@ -892,6 +892,13 @@ unwind(int i)
/* FALLTHROUGH */
default:
quitenv(NULL);
+ /*
+ * quitenv() may have reclaimed the memory
+ * used by source which will end badly when
+ * we jump to a function that expects it to
+ * be valid
+ */
+ source = NULL;
}
}
}
@@ -1014,8 +1021,6 @@ cleanup_parents_env(void)
struct env *ep;
int fd;
- mkssert(e != NULL);
-
/*
* Don't clean up temporary files - parent will probably need them.
* Also, can't easily reclaim memory since variables, etc. could be
@@ -1244,7 +1249,7 @@ bi_errorf(const char *fmt, ...)
* non-interactive shells to exit.
* XXX odd use of KEEPASN; also may not want LERROR here
*/
- if (builtin_flag & SPEC_BI) {
+ if (builtin_spec) {
builtin_argv0 = NULL;
unwind(LERROR);
}
diff --git a/src/misc.c b/src/misc.c
index 82d47d6..7c8d114 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1,9 +1,9 @@
-/* $OpenBSD: misc.c,v 1.38 2013/11/28 10:33:37 sobrado Exp $ */
+/* $OpenBSD: misc.c,v 1.39 2015/01/16 06:39:32 deraadt Exp $ */
/* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $ */
/*-
* 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
@@ -30,7 +30,7 @@
#include <grp.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219 2014/01/05 21:57:27 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219.2.2 2015/03/01 15:43:02 tg Exp $");
#define KSH_CHVT_FLAG
#ifdef MKSH_SMALL
@@ -281,15 +281,15 @@ change_flag(enum sh_flag f, int what, bool newset)
#endif
DO_SETUID(setresuid, (ksheuid, ksheuid, ksheuid));
#else /* !HAVE_SETRESUGID */
- /* seteuid, setegid, setgid don't EAGAIN on Linux */
+ /* setgid, setegid, seteuid don't EAGAIN on Linux */
+ setgid(kshegid);
#ifndef MKSH__NO_SETEUGID
- seteuid(ksheuid);
+ setegid(kshegid);
#endif
DO_SETUID(setuid, (ksheuid));
#ifndef MKSH__NO_SETEUGID
- setegid(kshegid);
+ seteuid(ksheuid);
#endif
- setgid(kshegid);
#endif /* !HAVE_SETRESUGID */
} else if ((f == FPOSIX || f == FSH) && newval) {
/* Turning on -o posix or -o sh? */
@@ -304,6 +304,11 @@ change_flag(enum sh_flag f, int what, bool newset)
void
change_xtrace(unsigned char newval, bool dosnapshot)
{
+ static bool in_xtrace;
+
+ if (in_xtrace)
+ return;
+
if (!dosnapshot && newval == Flag(FXTRACE))
return;
@@ -328,8 +333,13 @@ change_xtrace(unsigned char newval, bool dosnapshot)
shl_xtrace->fd = 2;
changed_xtrace:
- if ((Flag(FXTRACE) = newval) == 2)
+ if ((Flag(FXTRACE) = newval) == 2) {
+ in_xtrace = true;
+ Flag(FXTRACE) = 0;
shf_puts(substitute(str_val(global("PS4")), 0), shl_xtrace);
+ Flag(FXTRACE) = 2;
+ in_xtrace = false;
+ }
}
/*
@@ -485,7 +495,6 @@ parse_args(const char **argv,
if (arrayset) {
const char *ccp = NULL;
- mkssert(array != NULL);
if (*array)
ccp = skip_varname(array, false);
if (!ccp || !(!ccp[0] || (ccp[0] == '+' && !ccp[1]))) {
@@ -1384,8 +1393,7 @@ do_realpath(const char *upath)
{
char *xp, *ip, *tp, *ipath, *ldest = NULL;
XString xs;
- ptrdiff_t pos;
- size_t len;
+ size_t pos, len;
int llen;
struct stat sb;
#ifdef MKSH__NO_PATH_MAX
diff --git a/src/mksh.1 b/src/mksh.1
index 480184e..5ad143c 100644
--- a/src/mksh.1
+++ b/src/mksh.1
@@ -1,9 +1,9 @@
-.\" $MirOS: src/bin/mksh/mksh.1,v 1.344 2014/10/07 15:30:12 tg Exp $
-.\" $OpenBSD: ksh.1,v 1.153 2014/08/17 07:15:41 jmc Exp $
+.\" $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 $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-.\" 2010, 2011, 2012, 2013, 2014
-.\" Thorsten Glaser <tg@mirbsd.org>
+.\" 2010, 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
@@ -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: October 7 2014 $
+.Dd $Mdocdate: March 1 2015 $
.\"
.\" Check which macro package we use, and do other -mdoc setup.
.\"
@@ -673,11 +673,11 @@ are reserved words, not meta-characters.
.It Xo case Ar word No in
.Oo Op \&(
.Ar pattern
-.Op \*(Ba Ar pat
+.Op \*(Ba Ar pattern
.No ... Ns )
.Ar list
-.Op ;; \*(Ba ;&\& \*(Ba ;\*(Ba\ \&
-.Oc ... esac
+.Ic terminator
+.Oc No ... esac
.Xc
The
.Ic case
@@ -707,9 +707,11 @@ For historical reasons, open and close braces may be used instead of
and
.Ic esac
e.g.\&
-.Ic case $foo { *) echo bar;; } .
+.Ic case $foo { *) echo bar ;; } .
.Pp
-The list terminators are:
+The list
+.Ic terminator Ns s
+are:
.Bl -tag -width 4n
.It Ql ;;
Terminate after the list.
@@ -2923,6 +2925,10 @@ trapped) will have their default effect in a function.
.It
The EXIT trap, if set in a function, will be executed after the function
returns.
+.It
+Shell options
+.Pq Ic set Fl o
+have local scope, i.e. changes inside a function are reset upon its exit.
.El
.Ss Command execution
After evaluation of command-line arguments, redirections, and parameter
@@ -3370,9 +3376,25 @@ string which the shell then parses and executes in the current environment.
.Pp
.It Xo
.Ic exec
+.Op Fl a Ar argv0
+.Op Fl c
.Op Ar command Op Ar arg ...
.Xc
The command is executed without forking, replacing the shell process.
+This is currently absolute, i.e.\&
+.Ic exec
+never returns, even if the
+.Ar command
+is not found.
+The
+.Fl a
+option permits setting a different
+.Li argv[0]
+value, and
+.Fl c
+clears the environment before executing the child process, except for the
+.Ev _
+variable and direct assignments.
.Pp
If no command is given except for I/O redirection, the I/O redirection is
permanent and the shell is
@@ -6457,6 +6479,17 @@ If you require 64-bit integer arithmetics, use
instead, but be aware that, in POSIX, it's legal for the OS to make
.Li print $((2147483647 + 1))
delete all files on your system, as it's Undefined Behaviour.
+.Pp
+.Nm mksh
+provides a consistent, clear interface normally.
+This may deviate from POSIX in optional or opinionated places, such
+as whether leading-digit-zero numbers should be interpreted as octal.
+.Ic set \-o posix
+will cause the shell (either
+.Nm mksh
+or
+.Nm lksh )
+to behave more like the standard expects.
.Sh BUGS
Suspending (using \*(haZ) pipelines like the one below will only suspend
the currently running part of the pipeline; in this example,
@@ -6468,16 +6501,19 @@ $ /bin/sleep 666 && echo fubar
.Ed
.Pp
This document attempts to describe
-.Nm mksh\ R50
+.Nm mksh\ R50e
and up,
compiled without any options impacting functionality, such as
.Dv MKSH_SMALL ,
when not called as
.Pa /bin/sh
which, on some systems only, enables
+.Ic set \-o posix
+or
.Ic set \-o sh
automatically (whose behaviour differs across targets),
for an operating environment supporting all of its advanced needs.
+.Pp
Please report bugs in
.Nm
to the
diff --git a/src/sh.h b/src/sh.h
index b3d1c0b..d053ed2 100644
--- a/src/sh.h
+++ b/src/sh.h
@@ -10,7 +10,7 @@
/*-
* Copyright © 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
@@ -169,9 +169,9 @@
#endif
#ifdef EXTERN
-__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.697 2014/10/07 15:22:17 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.701.2.4 2015/03/01 15:43:05 tg Exp $");
#endif
-#define MKSH_VERSION "R50 2014/10/07"
+#define MKSH_VERSION "R50 2015/03/01"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
@@ -312,9 +312,13 @@ struct rusage {
#undef PATH_MAX
#else
#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
#define PATH_MAX 1024
#endif
#endif
+#endif
#ifndef SIZE_MAX
#ifdef SIZE_T_MAX
#define SIZE_MAX SIZE_T_MAX
@@ -533,7 +537,7 @@ char *ucstrstr(char *, const char *);
#define mkssert(e) do { } while (/* CONSTCOND */ 0)
#endif
-#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 504)
+#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 505)
#error Must run Build.sh to compile this.
extern void thiswillneverbedefinedIhope(void);
int
@@ -992,8 +996,8 @@ EXTERN sigset_t sm_default, sm_sigchld;
/* name of called builtin function (used by error functions) */
EXTERN const char *builtin_argv0;
-/* flags of called builtin (SPEC_BI, etc.) */
-EXTERN uint32_t builtin_flag;
+/* is called builtin SPEC_BI? */
+EXTERN bool builtin_spec;
/* current working directory */
EXTERN char *current_wd;
@@ -1233,6 +1237,7 @@ struct block {
/* Values for struct block.flags */
#define BF_DOGETOPTS BIT(0) /* save/restore getopts state */
+#define BF_STOPENV BIT(1) /* do not export further */
/*
* Used by ktwalk() and ktnext() routines.
@@ -1396,7 +1401,8 @@ struct ioword {
#define DOVACHECK BIT(9) /* var assign check (for typeset, set, etc) */
#define DOMARKDIRS BIT(10) /* force markdirs behaviour */
#define DOTCOMEXEC BIT(11) /* not an eval flag, used by sh -c hack */
-#define DOASNFIELD BIT(12) /* is assignment, change field handling */
+#define DOSCALAR BIT(12) /* change field handling to non-list context */
+#define DOHEREDOC BIT(13) /* change scalar handling to heredoc body */
#define X_EXTRA 20 /* this many extra bytes in X string */
@@ -1645,7 +1651,7 @@ char *evalonestr(const char *cp, int);
char *debunk(char *, const char *, size_t);
void expand(const char *, XPtrV *, int);
int glob_str(char *, XPtrV *, bool);
-char *tilde(char *);
+char *do_tilde(char *);
/* exec.c */
int execute(struct op * volatile, volatile int, volatile int * volatile);
int shcomexec(const char **);
diff --git a/src/shf.c b/src/shf.c
index 33e89bd..cc30442 100644
--- a/src/shf.c
+++ b/src/shf.c
@@ -2,7 +2,7 @@
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
- * 2012, 2013
+ * 2012, 2013, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@@ -25,7 +25,7 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.62 2013/10/09 11:59:30 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.62.2.2 2015/03/01 15:43:07 tg Exp $");
/* flags to shf_emptybuf() */
#define EB_READSW 0x01 /* about to switch to reading */
@@ -232,7 +232,7 @@ shf_close(struct shf *shf)
if (shf->fd >= 0) {
ret = shf_flush(shf);
if (close(shf->fd) < 0)
- ret = EOF;
+ ret = -1;
}
if (shf->flags & SHF_ALLOCS)
afree(shf, shf->areap);
@@ -251,7 +251,7 @@ shf_fdclose(struct shf *shf)
if (shf->fd >= 0) {
ret = shf_flush(shf);
if (close(shf->fd) < 0)
- ret = EOF;
+ ret = -1;
shf->rnleft = 0;
shf->rp = shf->buf;
shf->wnleft = 0;
@@ -283,20 +283,20 @@ shf_sclose(struct shf *shf)
/*
* Un-read what has been read but not examined, or write what has been
- * buffered. Returns 0 for success, EOF for (write) error.
+ * buffered. Returns 0 for success, -1 for (write) error.
*/
int
shf_flush(struct shf *shf)
{
if (shf->flags & SHF_STRING)
- return ((shf->flags & SHF_WR) ? EOF : 0);
+ return ((shf->flags & SHF_WR) ? -1 : 0);
if (shf->fd < 0)
internal_errorf("%s: %s", "shf_flush", "no fd");
if (shf->flags & SHF_ERROR) {
errno = shf->errnosv;
- return (EOF);
+ return (-1);
}
if (shf->flags & SHF_READING) {
@@ -315,7 +315,7 @@ shf_flush(struct shf *shf)
/*
* Write out any buffered data. If currently reading, flushes the read
- * buffer. Returns 0 for success, EOF for (write) error.
+ * buffer. Returns 0 for success, -1 for (write) error.
*/
static int
shf_emptybuf(struct shf *shf, int flags)
@@ -327,7 +327,7 @@ shf_emptybuf(struct shf *shf, int flags)
if (shf->flags & SHF_ERROR) {
errno = shf->errnosv;
- return (EOF);
+ return (-1);
}
if (shf->flags & SHF_READING) {
@@ -347,7 +347,7 @@ shf_emptybuf(struct shf *shf, int flags)
*/
if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) ||
!(shf->flags & SHF_ALLOCB))
- return (EOF);
+ return (-1);
/* allocate more space for buffer */
nbuf = aresize2(shf->buf, 2, shf->wbsize, shf->areap);
shf->rp = nbuf + (shf->rp - shf->buf);
@@ -379,7 +379,7 @@ shf_emptybuf(struct shf *shf, int flags)
ntowrite);
shf->wp = shf->buf + ntowrite;
}
- return (EOF);
+ return (-1);
}
buf += n;
ntowrite -= n;
@@ -399,7 +399,7 @@ shf_emptybuf(struct shf *shf, int flags)
return (ret);
}
-/* Fill up a read buffer. Returns EOF for a read error, 0 otherwise. */
+/* Fill up a read buffer. Returns -1 for a read error, 0 otherwise. */
static int
shf_fillbuf(struct shf *shf)
{
@@ -414,11 +414,11 @@ shf_fillbuf(struct shf *shf)
if (shf->flags & (SHF_EOF | SHF_ERROR)) {
if (shf->flags & SHF_ERROR)
errno = shf->errnosv;
- return (EOF);
+ return (-1);
}
- if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
- return (EOF);
+ if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1)
+ return (-1);
shf->flags |= SHF_READING;
@@ -434,7 +434,7 @@ shf_fillbuf(struct shf *shf)
shf->errnosv = errno;
shf->rnleft = 0;
shf->rp = shf->buf;
- return (EOF);
+ return (-1);
}
if ((shf->rnleft = n) == 0)
shf->flags |= SHF_EOF;
@@ -443,7 +443,7 @@ shf_fillbuf(struct shf *shf)
/*
* Read a buffer from shf. Returns the number of bytes read into buf, if
- * no bytes were read, returns 0 if end of file was seen, EOF if a read
+ * no bytes were read, returns 0 if end of file was seen, -1 if a read
* error occurred.
*/
ssize_t
@@ -459,7 +459,7 @@ shf_read(char *buf, ssize_t bsize, struct shf *shf)
while (bsize > 0) {
if (shf->rnleft == 0 &&
- (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
+ (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
break;
ncopy = shf->rnleft;
if (ncopy > bsize)
@@ -471,12 +471,12 @@ shf_read(char *buf, ssize_t bsize, struct shf *shf)
shf->rnleft -= ncopy;
}
/* Note: fread(3S) returns 0 for errors - this doesn't */
- return (orig_bsize == bsize ? (shf_error(shf) ? EOF : 0) :
+ return (orig_bsize == bsize ? (shf_error(shf) ? -1 : 0) :
orig_bsize - bsize);
}
/*
- * Read up to a newline or EOF. The newline is put in buf; buf is always
+ * Read up to a newline or -1. The newline is put in buf; buf is always
* NUL terminated. Returns NULL on read error or if nothing was read
* before end of file, returns a pointer to the NUL byte in buf
* otherwise.
@@ -498,7 +498,7 @@ shf_getse(char *buf, ssize_t bsize, struct shf *shf)
--bsize;
do {
if (shf->rnleft == 0) {
- if (shf_fillbuf(shf) == EOF)
+ if (shf_fillbuf(shf) == -1)
return (NULL);
if (shf->rnleft == 0) {
*buf = '\0';
@@ -520,22 +520,22 @@ shf_getse(char *buf, ssize_t bsize, struct shf *shf)
return (buf);
}
-/* Returns the char read. Returns EOF for error and end of file. */
+/* Returns the char read. Returns -1 for error and end of file. */
int
shf_getchar(struct shf *shf)
{
if (!(shf->flags & SHF_RD))
internal_errorf("%s: flags 0x%X", "shf_getchar", shf->flags);
- if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
- return (EOF);
+ if (shf->rnleft == 0 && (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
+ return (-1);
--shf->rnleft;
return (*shf->rp++);
}
/*
* Put a character back in the input stream. Returns the character if
- * successful, EOF if there is no room.
+ * successful, -1 if there is no room.
*/
int
shf_ungetc(int c, struct shf *shf)
@@ -543,12 +543,12 @@ shf_ungetc(int c, struct shf *shf)
if (!(shf->flags & SHF_RD))
internal_errorf("%s: flags 0x%X", "shf_ungetc", shf->flags);
- if ((shf->flags & SHF_ERROR) || c == EOF ||
+ if ((shf->flags & SHF_ERROR) || c == -1 ||
(shf->rp == shf->buf && shf->rnleft))
- return (EOF);
+ return (-1);
- if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
- return (EOF);
+ if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1)
+ return (-1);
if (shf->rp == shf->buf)
shf->rp = shf->buf + shf->rbsize;
@@ -558,7 +558,7 @@ shf_ungetc(int c, struct shf *shf)
* we don't want to modify a string.
*/
if ((int)(shf->rp[-1]) != c)
- return (EOF);
+ return (-1);
shf->flags &= ~SHF_EOF;
shf->rp--;
shf->rnleft++;
@@ -571,7 +571,7 @@ shf_ungetc(int c, struct shf *shf)
}
/*
- * Write a character. Returns the character if successful, EOF if the
+ * Write a character. Returns the character if successful, -1 if the
* char could not be written.
*/
int
@@ -580,8 +580,8 @@ shf_putchar(int c, struct shf *shf)
if (!(shf->flags & SHF_WR))
internal_errorf("%s: flags 0x%X", "shf_putchar", shf->flags);
- if (c == EOF)
- return (EOF);
+ if (c == -1)
+ return (-1);
if (shf->flags & SHF_UNBUF) {
unsigned char cc = (unsigned char)c;
@@ -591,7 +591,7 @@ shf_putchar(int c, struct shf *shf)
internal_errorf("%s: %s", "shf_putchar", "no fd");
if (shf->flags & SHF_ERROR) {
errno = shf->errnosv;
- return (EOF);
+ return (-1);
}
while ((n = write(shf->fd, &cc, 1)) != 1)
if (n < 0) {
@@ -600,12 +600,12 @@ shf_putchar(int c, struct shf *shf)
continue;
shf->flags |= SHF_ERROR;
shf->errnosv = errno;
- return (EOF);
+ return (-1);
}
} else {
/* Flush deals with strings and sticky errors */
- if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF)
- return (EOF);
+ if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == -1)
+ return (-1);
shf->wnleft--;
*shf->wp++ = c;
}
@@ -614,19 +614,19 @@ shf_putchar(int c, struct shf *shf)
}
/*
- * Write a string. Returns the length of the string if successful, EOF
+ * Write a string. Returns the length of the string if successful, -1
* if the string could not be written.
*/
ssize_t
shf_puts(const char *s, struct shf *shf)
{
if (!s)
- return (EOF);
+ return (-1);
return (shf_write(s, strlen(s), shf));
}
-/* Write a buffer. Returns nbytes if successful, EOF if there is an error. */
+/* Write a buffer. Returns nbytes if successful, -1 if there is an error. */
ssize_t
shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
{
@@ -653,13 +653,13 @@ shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
if (shf->flags & SHF_STRING) {
/* resize buffer until there's enough space left */
while (nbytes > shf->wnleft)
- if (shf_emptybuf(shf, EB_GROW) == EOF)
- return (EOF);
+ if (shf_emptybuf(shf, EB_GROW) == -1)
+ return (-1);
/* then write everything into the buffer */
} else {
/* flush deals with sticky errors */
- if (shf_emptybuf(shf, EB_GROW) == EOF)
- return (EOF);
+ if (shf_emptybuf(shf, EB_GROW) == -1)
+ return (-1);
/* write chunks larger than window size directly */
if (nbytes > shf->wbsize) {
ncopy = nbytes;
@@ -679,7 +679,7 @@ shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
* Note: fwrite(3) returns 0
* for errors - this doesn't
*/
- return (EOF);
+ return (-1);
}
buf += n;
ncopy -= n;
@@ -767,12 +767,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
ssize_t field, precision, len;
unsigned long lnum;
/* %#o produces the longest output */
- char numbuf[(8 * sizeof(long) + 2) / 3 + 1
-#ifdef DEBUG
- /* a NUL for LLVM/Clang scan-build */
- + 1
-#endif
- ];
+ char numbuf[(8 * sizeof(long) + 2) / 3 + 1];
/* this stuff for dealing with the buffer */
ssize_t nwritten = 0;
@@ -910,16 +905,6 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
integral:
flags |= FL_NUMBER;
cp = numbuf + sizeof(numbuf);
-#ifdef DEBUG
- /*
- * this is necessary so Clang 3.2 realises
- * utf_skipcols/shf_putc in the output loop
- * terminate; these values are always ASCII
- * so an out-of-bounds access cannot happen
- * but Clang doesn't know that
- */
- *--cp = '\0';
-#endif
switch (c) {
case 'd':
@@ -971,10 +956,6 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
}
}
len = numbuf + sizeof(numbuf) - (s = cp);
-#ifdef DEBUG
- /* see above comment for Clang 3.2 */
- --len;
-#endif
if (flags & FL_DOT) {
if (precision > len) {
field = precision;
@@ -1068,7 +1049,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
}
}
- return (shf_error(shf) ? EOF : nwritten);
+ return (shf_error(shf) ? -1 : nwritten);
}
#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
diff --git a/src/syn.c b/src/syn.c
index 6a544df..0e6e677 100644
--- a/src/syn.c
+++ b/src/syn.c
@@ -23,7 +23,7 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94 2014/01/05 21:57:29 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94.2.1 2015/01/25 15:35:54 tg Exp $");
struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */
@@ -196,10 +196,11 @@ synio(int cf)
musthave(LWORD, ishere ? HEREDELIM : 0);
if (ishere) {
iop->delim = yylval.cp;
- if (*ident != 0)
+ if (*ident != 0) {
/* unquoted */
gotnulldelim:
iop->flag |= IOEVAL;
+ }
if (herep > &heres[HERES - 1])
yyerror("too many %ss\n", "<<");
*herep++ = iop;
diff --git a/src/var.c b/src/var.c
index 9f05ec1..452b6e2 100644
--- a/src/var.c
+++ b/src/var.c
@@ -2,7 +2,7 @@
/*-
* 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
@@ -28,7 +28,7 @@
#include <sys/sysctl.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183 2014/10/04 11:47:19 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183.2.2 2015/03/01 15:43:07 tg Exp $");
/*-
* Variables
@@ -308,7 +308,6 @@ local(const char *n, bool copy)
* dereference namerefs; must come first
*/
n = array_index_calc(n, &array, &val);
- mkssert(n != NULL);
h = hash(n);
if (!ksh_isalphx(*n)) {
vp = &vtemp;
@@ -679,8 +678,6 @@ exportprep(struct tbl *vp, const char *val)
char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
size_t namelen, vallen;
- mkssert(val != NULL);
-
namelen = strlen(vp->name);
vallen = strlen(val) + 1;
@@ -1114,6 +1111,8 @@ makenv(void)
}
XPput(denv, vp->val.s);
}
+ if (l->flags & BF_STOPENV)
+ break;
}
XPput(denv, NULL);
return ((char **)XPclose(denv));