Merge "Upgrade to mksh 50e."
diff --git a/Android.mk b/Android.mk
index 2d572bd..6fd3f57 100644
--- a/Android.mk
+++ b/Android.mk
@@ -45,7 +45,7 @@
-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 @@
-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 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
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_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(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 @@
;' >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 @@
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 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 @@
;;
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 @@
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 @@
$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
Binary files differ
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 @@
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 @@
# 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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
{
char *cp;
- mkssert(xcp != NULL);
strndupx(cp, xcp, nchars, AEDIT);
if (killstack[killsp])
afree(killstack[killsp], AEDIT);
@@ -2455,8 +2451,7 @@
/* 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 @@
#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 @@
#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 *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 @@
/* 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 @@
/* 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 @@
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 @@
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 @@
/* check for special cases */
d = str_val(st->var);
- mkssert(d != NULL);
switch (*pat) {
case '#':
/* anchor at begin */
@@ -622,7 +634,7 @@
case '%':
/* ! DOBLANK,DOBRACE,DOTILDE */
f = (f & DONTRUNCOMMAND) |
- DOPAT | DOTEMP;
+ DOPAT | DOTEMP | DOSCALAR;
st->quotew = quote = 0;
/*
* Prepend open pattern (so |
@@ -631,7 +643,7 @@
*/
if (!Flag(FSH)) {
*dp++ = MAGIC;
- *dp++ = '@' | 0x80;
+ *dp++ = 0x80 | '@';
}
break;
case '=':
@@ -664,7 +676,11 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* $(<...) failed */
subst_exstat = 1;
/* fake EOF */
- c = EOF;
+ c = -1;
} else if (newlines) {
/* spit out saved NLs */
c = '\n';
@@ -877,13 +905,13 @@
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 @@
* 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 @@
tcp = maybe_expand_tilde(sp,
&ds, &tdp,
- f & DOASNTILDE);
+ tobool(f & DOASNTILDE));
if (tcp) {
if (dp != tdp)
word = IFS_WORD;
@@ -1659,7 +1687,7 @@
* 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 @@
}
*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 @@
*/
char *
-tilde(char *cp)
+do_tilde(char *cp)
{
char *dp = null;
@@ -1745,28 +1773,30 @@
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 @@
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 @@
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 @@
/* 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 @@
/* 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 @@
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 @@
case TEXEC:
/* an eval'd TCOM */
- s = t->args[0];
up = makenv();
restoresigs();
cleanup_proc_env();
@@ -455,7 +459,7 @@
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 @@
/* 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 @@
* 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 @@
} 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 @@
*/
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 @@
* 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 @@
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 @@
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 @@
}
/* 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 @@
/* 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 @@
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 @@
}
}
- /* 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 @@
{
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 @@
#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 */
+ cp = buf + (n = ((buf[0] == 0xEF) && (buf[1] == 0xBB) &&
+ (buf[2] == 0xBF)) ? 3 : 0);
- /* 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;
+ /* 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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
static Proc *
new_proc(void)
{
- Proc *p;
+ Proc *p;
if (free_procs != NULL) {
p = free_procs;
@@ -1786,10 +1786,9 @@
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 @@
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 @@
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 @@
#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 @@
*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 @@
/* 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 @@
/* 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 @@
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 @@
* 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 @@
#endif
DO_SETUID(setresuid, (ksheuid, ksheuid, ksheuid));
#else /* !HAVE_SETRESUGID */
- /* seteuid, setegid, setgid don't EAGAIN on Linux */
-#ifndef MKSH__NO_SETEUGID
- seteuid(ksheuid);
-#endif
- DO_SETUID(setuid, (ksheuid));
+ /* setgid, setegid, seteuid don't EAGAIN on Linux */
+ setgid(kshegid);
#ifndef MKSH__NO_SETEUGID
setegid(kshegid);
#endif
- setgid(kshegid);
+ DO_SETUID(setuid, (ksheuid));
+#ifndef MKSH__NO_SETEUGID
+ seteuid(ksheuid);
+#endif
#endif /* !HAVE_SETRESUGID */
} else if ((f == FPOSIX || f == FSH) && newval) {
/* Turning on -o posix or -o sh? */
@@ -304,6 +304,11 @@
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 @@
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 @@
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 @@
{
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 @@
.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 @@
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 @@
.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 @@
.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 @@
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 @@
.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 @@
#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 @@
#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 @@
/* 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 @@
/* 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 @@
#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 *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 @@
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 @@
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 @@
/*
* 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 @@
/*
* 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 @@
if (shf->flags & SHF_ERROR) {
errno = shf->errnosv;
- return (EOF);
+ return (-1);
}
if (shf->flags & SHF_READING) {
@@ -347,7 +347,7 @@
*/
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 @@
ntowrite);
shf->wp = shf->buf + ntowrite;
}
- return (EOF);
+ return (-1);
}
buf += n;
ntowrite -= n;
@@ -399,7 +399,7 @@
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 @@
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->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 @@
/*
* 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 @@
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->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 @@
--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 @@
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 @@
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 @@
* 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 @@
}
/*
- * 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 @@
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 @@
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 @@
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 @@
}
/*
- * 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 @@
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 @@
* Note: fwrite(3) returns 0
* for errors - this doesn't
*/
- return (EOF);
+ return (-1);
}
buf += n;
ncopy -= n;
@@ -767,12 +767,7 @@
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 @@
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 @@
}
}
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 @@
}
}
- 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 @@
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 @@
* 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 @@
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 @@
}
XPput(denv, vp->val.s);
}
+ if (l->flags & BF_STOPENV)
+ break;
}
XPput(denv, NULL);
return ((char **)XPclose(denv));