summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo Cerqueira <ricardo@cyngn.com>2015-03-10 11:58:49 +0000
committerRicardo Cerqueira <ricardo@cyngn.com>2015-03-10 11:58:49 +0000
commit82aac8e655414ee400ff0534637c43b1c90cadae (patch)
tree1a2669dfad137eef21bc0cdf1da774183c162b24
parent13346b7ef17b94819ef9f85fe38e07a5ade145d1 (diff)
parentae04631768fefc45c2d18865ec88872853421a52 (diff)
downloadandroid_external_mksh-stable/cm-12.1-YOG7D.tar.gz
android_external_mksh-stable/cm-12.1-YOG7D.tar.bz2
android_external_mksh-stable/cm-12.1-YOG7D.zip
Android 5.1.0 release 1
-rw-r--r--Android.mk112
-rw-r--r--Makefrag.inc40
-rw-r--r--mkmf.sh52
-rw-r--r--src/Build.sh356
-rw-r--r--src/check.pl45
-rw-r--r--src/check.t556
-rw-r--r--src/dot.mkshrc85
-rw-r--r--src/edit.c144
-rw-r--r--src/eval.c136
-rw-r--r--src/exec.c33
-rw-r--r--src/expr.c40
-rw-r--r--src/funcs.c287
-rw-r--r--src/histrap.c14
-rw-r--r--src/jobs.c76
-rw-r--r--src/lex.c32
-rw-r--r--src/main.c169
-rw-r--r--src/mirhash.h224
-rw-r--r--src/misc.c74
-rw-r--r--src/mksh.1159
-rw-r--r--src/rlimits.gen174
-rw-r--r--src/rlimits.opt96
-rw-r--r--src/sh.h154
-rw-r--r--src/sh_flags.gen136
-rw-r--r--src/sh_flags.h166
-rw-r--r--src/sh_flags.opt179
-rw-r--r--src/shf.c4
-rw-r--r--src/signames.inc31
-rw-r--r--src/strlcpy.c5
-rw-r--r--src/syn.c8
-rw-r--r--src/tree.c11
-rw-r--r--src/var.c218
31 files changed, 2627 insertions, 1189 deletions
diff --git a/Android.mk b/Android.mk
index 9989f67..2d572bd 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,18 +1,18 @@
# Copyright © 2010, 2013
-# Thorsten Glaser <t.glaser@tarent.de>
+# Thorsten Glaser <t.glaser@tarent.de>
# This file is provided under the same terms as mksh.
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
# /system/etc/mkshrc
include $(CLEAR_VARS)
-LOCAL_MODULE:= mkshrc
-LOCAL_MODULE_CLASS:= ETC
-LOCAL_MODULE_PATH:= $(TARGET_OUT)/etc
-LOCAL_SRC_FILES:= $(LOCAL_MODULE)
+LOCAL_MODULE := mkshrc
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
@@ -20,49 +20,65 @@ include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
-LOCAL_MODULE:= sh
+LOCAL_MODULE := sh
+LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
# mksh source files
-LOCAL_SRC_FILES:= src/lalloc.c src/edit.c src/eval.c src/exec.c \
- src/expr.c src/funcs.c src/histrap.c src/jobs.c \
- src/lex.c src/main.c src/misc.c src/shf.c \
- src/syn.c src/tree.c src/var.c
-
-LOCAL_SYSTEM_SHARED_LIBRARIES:= libc
-
-LOCAL_C_INCLUDES:= $(LOCAL_PATH)/src
-# additional flags first, then from Makefrag.inc: CFLAGS, CPPFLAGS
-LOCAL_CFLAGS:= -DMKSHRC_PATH=\"/system/etc/mkshrc\" \
- -DMKSH_DEFAULT_EXECSHELL=\"/system/bin/sh\" \
- -DMKSH_DEFAULT_TMPDIR=\"/data/local\" \
- -Wno-deprecated-declarations \
- -fno-asynchronous-unwind-tables -fwrapv \
- -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_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_GETTIMEOFDAY=1 -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=481
-
-# check_categories= shell:legacy-no int:32 android convfds no-histfile
+LOCAL_SRC_FILES := \
+ src/lalloc.c src/edit.c src/eval.c src/exec.c \
+ src/expr.c src/funcs.c src/histrap.c src/jobs.c \
+ src/lex.c src/main.c src/misc.c src/shf.c \
+ src/syn.c src/tree.c src/var.c
+
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/src
+
+# Additional flags first...
+LOCAL_CFLAGS += \
+ -DMKSHRC_PATH=\"/system/etc/mkshrc\" \
+ -DMKSH_DEFAULT_EXECSHELL=\"/system/bin/sh\" \
+ -DMKSH_DEFAULT_TMPDIR=\"/data/local\" \
+
+# ...then from Makefrag.inc: CFLAGS...
+LOCAL_CFLAGS += \
+ -Wno-deprecated-declarations \
+ -fno-asynchronous-unwind-tables \
+ -fno-strict-aliasing \
+ -fstack-protector -fwrapv \
+
+# ...and CPPFLAGS.
+LOCAL_CFLAGS += \
+ -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=504
include $(BUILD_EXECUTABLE)
diff --git a/Makefrag.inc b/Makefrag.inc
new file mode 100644
index 0000000..b7a35bd
--- /dev/null
+++ b/Makefrag.inc
@@ -0,0 +1,40 @@
+# Makefile fragment for building mksh R50 2014/10/03
+
+PROG= mksh
+MAN= mksh.1
+SRCS= lalloc.c eval.c exec.c expr.c funcs.c histrap.c jobs.c lex.c main.c misc.c shf.c syn.c tree.c var.c edit.c
+SRCS_FP= ../src/lalloc.c ../src/eval.c ../src/exec.c ../src/expr.c ../src/funcs.c ../src/histrap.c ../src/jobs.c ../src/lex.c ../src/main.c ../src/misc.c ../src/shf.c ../src/syn.c ../src/tree.c ../src/var.c ../src/edit.c
+OBJS_BP= lalloc.o eval.o exec.o expr.o funcs.o histrap.o jobs.o lex.o main.o misc.o shf.o syn.o tree.o var.o edit.o
+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
+
+.depend $(OBJS_BP): rlimits.gen sh_flags.gen
+rlimits.gen: ../src/Build.sh ../src/rlimits.opt
+ srcfile=../src/rlimits.opt; BUILDSH_RUN_GENOPT=1; . ../src/Build.sh
+sh_flags.gen: ../src/Build.sh ../src/sh_flags.opt
+ srcfile=../src/sh_flags.opt; BUILDSH_RUN_GENOPT=1; . ../src/Build.sh
+
+# not BSD make only:
+#VPATH= ../src
+#all: $(PROG)
+#$(PROG): $(OBJS_BP)
+# $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS_BP) $(LIBS)
+#$(OBJS_BP): $(SRCS_FP) $(NONSRCS)
+#.c.o:
+# $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+# for all make variants:
+#REGRESS_FLAGS= -f
+#regress:
+# ./test.sh $(REGRESS_FLAGS)
+check_categories= shell:legacy-no int:32 android convfds no-histfile
+
+# for BSD make only:
+#.PATH: ../src
+#.include <bsd.prog.mk>
diff --git a/mkmf.sh b/mkmf.sh
index f819e0d..fafa34b 100644
--- a/mkmf.sh
+++ b/mkmf.sh
@@ -49,39 +49,27 @@ LIBS=
# possible to the values used later. (You also must example the
# results gathered from Makefrag.inc to see they are the same
# across all Android platforms, or add appropriate ifdefs.)
-# Since we no longer use the NDK, the AOSP has to have been
-# built before using this script (targetting generic/emulator).
+# Since we no longer use the NDK, AOSP has to have been
+# built before using this script.
+
+CC=$ANDROID_TOOLCHAIN/*-gcc
+
+target_arch=$(cd $ANDROID_BUILD_TOP; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core make --no-print-directory -f build/core/config.mk dumpvar-TARGET_ARCH)
-CC=$aospdir/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin/arm-linux-androideabi-gcc
addvar CPPFLAGS \
- -I$aospdir/libnativehelper/include/nativehelper \
- -isystem $aospdir/system/core/include \
- -isystem $aospdir/hardware/libhardware/include \
- -isystem $aospdir/hardware/libhardware_legacy/include \
- -isystem $aospdir/hardware/ril/include \
- -isystem $aospdir/libnativehelper/include \
- -isystem $aospdir/frameworks/native/include \
- -isystem $aospdir/frameworks/native/opengl/include \
- -isystem $aospdir/frameworks/av/include \
- -isystem $aospdir/frameworks/base/include \
- -isystem $aospdir/external/skia/include \
- -isystem $aospdir/out/target/product/generic/obj/include \
- -isystem $aospdir/bionic/libc/arch-arm/include \
+ -isystem $aospdir/bionic/libc/arch-$target_arch/include \
-isystem $aospdir/bionic/libc/include \
- -isystem $aospdir/bionic/libstdc++/include \
-isystem $aospdir/bionic/libc/kernel/uapi \
- -isystem $aospdir/bionic/libc/kernel/uapi/asm-arm \
+ -isystem $aospdir/bionic/libc/kernel/uapi/asm-$target_arch \
-isystem $aospdir/bionic/libm/include \
- -isystem $aospdir/bionic/libm/include/arm \
- -isystem $aospdir/bionic/libthread_db/include \
+ -isystem $aospdir/bionic/libm/include/$target_arch \
-D_FORTIFY_SOURCE=2 \
- -include $aospdir/build/core/combo/include/arch/linux-arm/AndroidConfig.h \
- -I$aospdir/build/core/combo/include/arch/linux-arm/ \
+ -include $aospdir/build/core/combo/include/arch/linux-$target_arch/AndroidConfig.h \
+ -I$aospdir/build/core/combo/include/arch/linux-$target_arch/ \
-DANDROID -DNDEBUG -UDEBUG
addvar CFLAGS \
-fno-exceptions \
-Wno-multichar \
- -msoft-float \
-fpic \
-fPIE \
-ffunction-sections \
@@ -91,14 +79,10 @@ addvar CFLAGS \
-Wa,--noexecstack \
-Werror=format-security \
-fno-short-enums \
- -march=armv7-a \
- -mfloat-abi=softfp \
- -mfpu=vfpv3-d16 \
-Wno-unused-but-set-variable \
-fno-builtin-sin \
-fno-strict-volatile-bitfields \
-Wno-psabi \
- -mthumb-interwork \
-fmessage-length=0 \
-W \
-Wall \
@@ -114,7 +98,6 @@ addvar CFLAGS \
-fgcse-after-reload \
-frerun-cse-after-loop \
-frename-registers \
- -mthumb \
-Os \
-fomit-frame-pointer \
-fno-strict-aliasing
@@ -131,18 +114,15 @@ addvar LDFLAGS \
-Wl,-z,now \
-Wl,--warn-shared-textrel \
-Wl,--fatal-warnings \
- -Wl,--icf=safe \
- -Wl,--fix-cortex-a8 \
-Wl,--no-undefined \
- $aospdir/out/target/product/generic/obj/lib/crtbegin_dynamic.o
+ $ANDROID_PRODUCT_OUT/obj/lib/crtbegin_dynamic.o
addvar LIBS \
- -L$aospdir/out/target/product/generic/obj/lib \
- -Wl,-rpath-link=$aospdir/out/target/product/generic/obj/lib \
+ -L$ANDROID_PRODUCT_OUT/obj/lib \
+ -Wl,-rpath-link=$ANDROID_PRODUCT_OUT/obj/lib \
-Wl,--no-whole-archive \
- $aospdir/out/target/product/generic/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a \
+ $ANDROID_PRODUCT_OUT/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a \
-lc \
- $aospdir/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin/../lib/gcc/arm-linux-androideabi/4.7/armv7-a/libgcc.a \
- $aospdir/out/target/product/generic/obj/lib/crtend_android.o
+ $ANDROID_PRODUCT_OUT/obj/lib/crtend_android.o
### Flags used by test builds
diff --git a/src/Build.sh b/src/Build.sh
index 45af9dd..c59163b 100644
--- a/src/Build.sh
+++ b/src/Build.sh
@@ -1,8 +1,8 @@
#!/bin/sh
-srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.645 2013/08/10 13:44:25 tg Exp $'
+srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669 2014/10/07 15:22:12 tg Exp $'
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013
+# 2011, 2012, 2013, 2014
# Thorsten Glaser <tg@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
@@ -28,9 +28,6 @@ srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.645 2013/08/10 13:44:25 tg Exp $'
LC_ALL=C
export LC_ALL
-echo "For the build logs, demonstrate that /dev/null and /dev/tty exist:"
-ls -l /dev/null /dev/tty
-
case $ZSH_VERSION:$VERSION in
:zsh*) ZSH_VERSION=2 ;;
esac
@@ -46,6 +43,162 @@ if test -d /usr/xpg4/bin/. >/dev/null 2>&1; then
export PATH
fi
+nl='
+'
+safeIFS=' '
+safeIFS=" $safeIFS$nl"
+IFS=$safeIFS
+allu=QWERTYUIOPASDFGHJKLZXCVBNM
+alll=qwertyuiopasdfghjklzxcvbnm
+alln=0123456789
+alls=______________________________________________________________
+
+genopt_die() {
+ if test -n "$1"; then
+ echo >&2 "E: $*"
+ echo >&2 "E: in '$srcfile': '$line'"
+ else
+ echo >&2 "E: invalid input in '$srcfile': '$line'"
+ fi
+ rm -f "$bn.gen"
+ exit 1
+}
+
+genopt_soptc() {
+ optc=`echo "$line" | sed 's/^[<>]\(.\).*$/\1/'`
+ test x"$optc" = x'|' && return
+ optclo=`echo "$optc" | tr $allu $alll`
+ if test x"$optc" = x"$optclo"; then
+ islo=1
+ else
+ islo=0
+ fi
+ sym=`echo "$line" | sed 's/^[<>]/|/'`
+ o_str=$o_str$nl"<$optclo$islo$sym"
+}
+
+genopt_scond() {
+ case x$cond in
+ x)
+ cond=
+ ;;
+ x*' '*)
+ cond=`echo "$cond" | sed 's/^ //'`
+ cond="#if $cond"
+ ;;
+ x'!'*)
+ cond=`echo "$cond" | sed 's/^!//'`
+ cond="#ifndef $cond"
+ ;;
+ x*)
+ cond="#ifdef $cond"
+ ;;
+ esac
+}
+
+do_genopt() {
+ srcfile=$1
+ test -f "$srcfile" || genopt_die Source file \$srcfile not set.
+ bn=`basename "$srcfile" | sed 's/.opt$//'`
+ o_gen=
+ o_str=
+ o_sym=
+ ddefs=
+ state=0
+ exec <"$srcfile"
+ IFS=
+ while IFS= read line; do
+ IFS=$safeIFS
+ case $state:$line in
+ 2:'|'*)
+ # end of input
+ o_sym=`echo "$line" | sed 's/^.//'`
+ o_gen=$o_gen$nl"#undef F0"
+ o_gen=$o_gen$nl"#undef FN"
+ o_gen=$o_gen$ddefs
+ state=3
+ ;;
+ 1:@@)
+ # begin of data block
+ o_gen=$o_gen$nl"#endif"
+ o_gen=$o_gen$nl"#ifndef F0"
+ o_gen=$o_gen$nl"#define F0 FN"
+ o_gen=$o_gen$nl"#endif"
+ state=2
+ ;;
+ *:@@*)
+ genopt_die ;;
+ 0:@*|1:@*)
+ # begin of a definition block
+ sym=`echo "$line" | sed 's/^@//'`
+ if test $state = 0; then
+ o_gen=$o_gen$nl"#if defined($sym)"
+ else
+ o_gen=$o_gen$nl"#elif defined($sym)"
+ fi
+ ddefs="$ddefs$nl#undef $sym"
+ state=1
+ ;;
+ 0:*|3:*)
+ genopt_die ;;
+ 1:*)
+ # definition line
+ o_gen=$o_gen$nl$line
+ ;;
+ 2:'<'*'|'*)
+ genopt_soptc
+ ;;
+ 2:'>'*'|'*)
+ genopt_soptc
+ cond=`echo "$line" | sed 's/^[^|]*|//'`
+ genopt_scond
+ case $optc in
+ '|') optc=0 ;;
+ *) optc=\'$optc\' ;;
+ esac
+ IFS= read line || genopt_die Unexpected EOF
+ IFS=$safeIFS
+ test -n "$cond" && o_gen=$o_gen$nl"$cond"
+ o_gen=$o_gen$nl"$line, $optc)"
+ test -n "$cond" && o_gen=$o_gen$nl"#endif"
+ ;;
+ esac
+ done
+ case $state:$o_sym in
+ 3:) genopt_die Expected optc sym at EOF ;;
+ 3:*) ;;
+ *) genopt_die Missing EOF marker ;;
+ esac
+ echo "$o_str" | sort | while IFS='|' read x opts cond; do
+ IFS=$safeIFS
+ test -n "$x" || continue
+ genopt_scond
+ test -n "$cond" && echo "$cond"
+ echo "\"$opts\""
+ test -n "$cond" && echo "#endif"
+ done | {
+ echo "#ifndef $o_sym$o_gen"
+ echo "#else"
+ cat
+ echo "#undef $o_sym"
+ echo "#endif"
+ } >"$bn.gen"
+ IFS=$safeIFS
+ return 0
+}
+
+if test x"$BUILDSH_RUN_GENOPT" = x"1"; then
+ set x -G "$srcfile"
+ shift
+fi
+if test x"$1" = x"-G"; then
+ do_genopt "$2"
+ exit $?
+fi
+
+echo "For the build logs, demonstrate that /dev/null and /dev/tty exist:"
+ls -l /dev/null /dev/tty
+
v() {
$e "$*"
eval "$@"
@@ -66,18 +219,12 @@ vq() {
rmf() {
for _f in "$@"; do
case $_f in
- Build.sh|check.pl|check.t|dot.mkshrc|*.c|*.h|*.ico|*.1) ;;
+ Build.sh|check.pl|check.t|dot.mkshrc|*.1|*.c|*.h|*.ico|*.opt) ;;
*) rm -f "$_f" ;;
esac
done
}
-allu=QWERTYUIOPASDFGHJKLZXCVBNM
-alll=qwertyuiopasdfghjklzxcvbnm
-alln=0123456789
-alls=______________________________________________________________
-nl='
-'
tcfn=no
bi=
ui=
@@ -193,8 +340,9 @@ ac_testn() {
ac_ifcpp() {
expr=$1; shift
ac_testn "$@" <<-EOF
+ #include <unistd.h>
extern int thiswillneverbedefinedIhope(void);
- int main(void) { return (
+ int main(void) { return (isatty(0) +
#$expr
0
#else
@@ -251,7 +399,8 @@ ac_flags() {
else
ac_testn can_$vn '' "$ft" <<-'EOF'
/* evil apo'stroph in comment test */
- int main(void) { return (0); }
+ #include <unistd.h>
+ int main(void) { return (isatty(0)); }
EOF
fi
eval fv=\$HAVE_CAN_`upper $vn`
@@ -291,19 +440,14 @@ ac_header() {
esac
done
echo "#include <$hf>" >>x
- echo 'int main(void) { return (0); }' >>x
+ echo '#include <unistd.h>' >>x
+ echo 'int main(void) { return (isatty(0)); }' >>x
ac_testn "$hv" "" "<$hf>" <x
rmf x
test 1 = $na || ac_cppflags
}
addsrcs() {
- addsrcs_s=0
- if test x"$1" = x"-s"; then
- # optstatic
- addsrcs_s=1
- shift
- fi
if test x"$1" = x"!"; then
fr=0
shift
@@ -311,13 +455,6 @@ addsrcs() {
fr=1
fi
eval i=\$$1
- if test $addsrcs_s = 1; then
- if test -f "$2" || test -f "$srcdir/$2"; then
- # always add $2, since it exists
- fr=1
- i=1
- fi
- fi
test $fr = "$i" && case " $SRCS " in
*\ $2\ *) ;;
*) SRCS="$SRCS $2" ;;
@@ -325,9 +462,21 @@ addsrcs() {
}
-curdir=`pwd` srcdir=`dirname "$0" 2>/dev/null` check_categories=
-test -n "$srcdir" || srcdir=. # in case dirname does not exist
-dstversion=`sed -n '/define MKSH_VERSION/s/^.*"\([^"]*\)".*$/\1/p' $srcdir/sh.h`
+curdir=`pwd` srcdir=`dirname "$0" 2>/dev/null`
+case x$srcdir in
+x)
+ srcdir=.
+ ;;
+*\ *|*" "*|*"$nl"*)
+ echo >&2 Source directory should not contain space or tab or newline.
+ echo >&2 Errors may occur.
+ ;;
+*"'"*)
+ echo Source directory must not contain single quotes.
+ exit 1
+ ;;
+esac
+dstversion=`sed -n '/define MKSH_VERSION/s/^.*"\([^"]*\)".*$/\1/p' "$srcdir/sh.h"`
add_cppflags -DMKSH_BUILDSH
e=echo
@@ -336,6 +485,7 @@ eq=0
pm=0
cm=normal
optflags=-std-compile-opts
+check_categories=
last=
tfn=
legacy=0
@@ -362,6 +512,10 @@ do
:-c)
last=c
;;
+ :-G)
+ echo "$me: Do not call me with '-G'!" >&2
+ exit 1
+ ;;
:-g)
# checker, debug, valgrind build
add_cppflags -DDEBUG
@@ -423,7 +577,7 @@ if test -d $tfn || test -d $tfn.exe; then
echo "$me: Error: ./$tfn is a directory!" >&2
exit 1
fi
-rmf a.exe* a.out* conftest.c *core core.* lft ${tfn}* no *.bc *.ll *.o \
+rmf a.exe* a.out* conftest.c *core core.* lft ${tfn}* no *.bc *.ll *.o *.gen \
Rebuild.sh signames.inc test.sh x vv.out
SRCS="lalloc.c eval.c exec.c expr.c funcs.c histrap.c jobs.c"
@@ -462,7 +616,7 @@ oswarn=
ccpc=-Wc,
ccpl=-Wl,
tsts=
-ccpr='|| for _f in ${tcfn}*; do case $_f in Build.sh|check.pl|check.t|dot.mkshrc|*.c|*.h|*.ico|*.1) ;; *) rm -f "$_f" ;; esac; done'
+ccpr='|| for _f in ${tcfn}*; do case $_f in Build.sh|check.pl|check.t|dot.mkshrc|*.1|*.c|*.h|*.ico|*.opt) ;; *) rm -f "$_f" ;; esac; done'
# Evil hack
if test x"$TARGET_OS" = x"Android"; then
@@ -786,7 +940,12 @@ AIX)
;;
Darwin)
vv '|' "hwprefs machine_type os_type os_class >&2"
+ vv '|' "sw_vers >&2"
+ vv '|' "system_profiler SPSoftwareDataType SPHardwareDataType >&2"
+ vv '|' "/bin/sh --version >&2"
+ vv '|' "xcodebuild -version >&2"
vv '|' "uname -a >&2"
+ vv '|' "sysctl kern.version hw.machine hw.model hw.memsize hw.availcpu hw.cpufrequency hw.byteorder hw.cpu64bit_capable >&2"
;;
IRIX*)
vv '|' "uname -a >&2"
@@ -905,7 +1064,10 @@ vv ']' "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c | \
sed 's/^/[ /' x
eval `cat x`
rmf x vv.out
-echo 'int main(void) { return (0); }' >conftest.c
+cat >conftest.c <<'EOF'
+#include <unistd.h>
+int main(void) { return (isatty(0)); }
+EOF
case $ct in
ack)
# work around "the famous ACK const bug"
@@ -1091,13 +1253,15 @@ if ac_ifcpp 'if 0' compiler_fails '' \
dec)
CFLAGS="$CFLAGS ${ccpl}-non_shared"
ac_testn can_delexe compiler_fails 0 'for the -non_shared linker option' <<-EOF
- int main(void) { return (0); }
+ #include <unistd.h>
+ int main(void) { return (isatty(0)); }
EOF
;;
dmc)
CFLAGS="$CFLAGS ${ccpl}/DELEXECUTABLE"
ac_testn can_delexe compiler_fails 0 'for the /DELEXECUTABLE linker option' <<-EOF
- int main(void) { return (0); }
+ #include <unistd.h>
+ int main(void) { return (isatty(0)); }
EOF
;;
*)
@@ -1193,7 +1357,8 @@ kencc|tcc|tendra)
;;
sunpro)
cat >x <<-'EOF'
- int main(void) { return (0); }
+ #include <unistd.h>
+ int main(void) { return (isatty(0)); }
#define __IDSTRING_CONCAT(l,p) __LINTED__ ## l ## _ ## p
#define __IDSTRING_EXPAND(l,p) __IDSTRING_CONCAT(l,p)
#define pad void __IDSTRING_EXPAND(__LINE__,x)(void) { }
@@ -1235,7 +1400,9 @@ gcc)
# mksh is not written in CFrustFrust!
ac_flags 1 no_eh_frame -fno-asynchronous-unwind-tables
ac_flags 1 fnostrictaliasing -fno-strict-aliasing
- ac_flags 1 fstackprotectorall -fstack-protector-all
+ ac_flags 1 fstackprotectorstrong -fstack-protector-strong
+ test 1 = $HAVE_CAN_FSTACKPROTECTORSTRONG || \
+ ac_flags 1 fstackprotectorall -fstack-protector-all
test $cm = dragonegg && case " $CC $CFLAGS $LDFLAGS " in
*\ -fplugin=*dragonegg*) ;;
*) ac_flags 1 fplugin_dragonegg -fplugin=dragonegg ;;
@@ -1356,8 +1523,8 @@ ac_test attribute_bounded '' 'for __attribute__((__bounded__))' <<-'EOF'
#include <string.h>
#undef __attribute__
int xcopy(const void *, void *, size_t)
- __attribute__((__bounded__ (__buffer__, 1, 3)))
- __attribute__((__bounded__ (__buffer__, 2, 3)));
+ __attribute__((__bounded__(__buffer__, 1, 3)))
+ __attribute__((__bounded__(__buffer__, 2, 3)));
int main(int ac, char *av[]) { return (xcopy(av[0], av[--ac], 1)); }
int xcopy(const void *s, void *d, size_t n) {
/*
@@ -1379,7 +1546,7 @@ ac_test attribute_format '' 'for __attribute__((__format__))' <<-'EOF'
#undef __attribute__
#undef fprintf
extern int fprintf(FILE *, const char *format, ...)
- __attribute__((__format__ (__printf__, 2, 3)));
+ __attribute__((__format__(__printf__, 2, 3)));
int main(int ac, char **av) { return (fprintf(stderr, "%s%d", *av, ac)); }
#endif
EOF
@@ -1396,14 +1563,29 @@ ac_test attribute_noreturn '' 'for __attribute__((__noreturn__))' <<-'EOF'
void fnord(void) { exit(0); }
#endif
EOF
+ac_test attribute_pure '' 'for __attribute__((__pure__))' <<-'EOF'
+ #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
+ extern int thiswillneverbedefinedIhope(void);
+ /* force a failure: TenDRA and gcc 1.42 have false positive here */
+ int main(void) { return (thiswillneverbedefinedIhope()); }
+ #else
+ #include <unistd.h>
+ #undef __attribute__
+ int foo(const char *) __attribute__((__pure__));
+ int main(int ac, char **av) { return (foo(av[ac - 1]) + isatty(0)); }
+ int foo(const char *s) { return ((int)s[0]); }
+ #endif
+EOF
ac_test attribute_unused '' 'for __attribute__((__unused__))' <<-'EOF'
#if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
extern int thiswillneverbedefinedIhope(void);
/* force a failure: TenDRA and gcc 1.42 have false positive here */
int main(void) { return (thiswillneverbedefinedIhope()); }
#else
+ #include <unistd.h>
+ #undef __attribute__
int main(int ac __attribute__((__unused__)), char **av
- __attribute__((__unused__))) { return (0); }
+ __attribute__((__unused__))) { return (isatty(0)); }
#endif
EOF
ac_test attribute_used '' 'for __attribute__((__used__))' <<-'EOF'
@@ -1412,8 +1594,10 @@ ac_test attribute_used '' 'for __attribute__((__used__))' <<-'EOF'
/* force a failure: TenDRA and gcc 1.42 have false positive here */
int main(void) { return (thiswillneverbedefinedIhope()); }
#else
+ #include <unistd.h>
+ #undef __attribute__
static const char fnord[] __attribute__((__used__)) = "42";
- int main(void) { return (0); }
+ int main(void) { return (isatty(0)); }
#endif
EOF
@@ -1465,7 +1649,8 @@ ac_test both_time_h '' 'whether <sys/time.h> and <time.h> can both be included'
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
- int main(void) { struct tm tm; return ((int)sizeof(tm)); }
+ #include <unistd.h>
+ int main(void) { struct tm tm; return ((int)sizeof(tm) + isatty(0)); }
EOF
ac_header sys/bsdtypes.h
ac_header sys/file.h sys/types.h
@@ -1491,11 +1676,12 @@ ac_header values.h
# Environment: definitions
#
echo '#include <sys/types.h>
+#include <unistd.h>
/* check that off_t can represent 2^63-1 correctly, thx FSF */
-#define LARGE_OFF_T (((off_t)1 << 62) - 1 + ((off_t)1 << 62))
+#define LARGE_OFF_T ((((off_t)1 << 31) << 31) - 1 + (((off_t)1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 &&
LARGE_OFF_T % 2147483647 == 1) ? 1 : -1];
-int main(void) { return (0); }' >lft.c
+int main(void) { return (isatty(0)); }' >lft.c
ac_testn can_lfs '' "for large file support" <lft.c
save_CPPFLAGS=$CPPFLAGS
add_cppflags -D_FILE_OFFSET_BITS=64
@@ -1546,7 +1732,7 @@ ac_test rlim_t <<-'EOF'
#include <sys/resource.h>
#endif
#include <unistd.h>
- int main(void) { return ((int)(rlim_t)0); }
+ int main(void) { return (((int)(rlim_t)0) + isatty(0)); }
EOF
# only testn: added later below
@@ -1598,8 +1784,8 @@ else
#define EXTERN
#define MKSH_INCLUDES_ONLY
#include "sh.h"
- __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.645 2013/08/10 13:44:25 tg Exp $");
- int main(void) { printf("Hello, World!\n"); return (0); }
+ __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.669 2014/10/07 15:22:12 tg Exp $");
+ int main(void) { printf("Hello, World!\n"); return (isatty(0)); }
EOF
case $cm in
llvm)
@@ -1638,12 +1824,14 @@ test x"NetBSD" = x"$TARGET_OS" && $e Ignore the compatibility warning.
ac_testn sys_errlist '' "the sys_errlist[] array and sys_nerr" <<-'EOF'
extern const int sys_nerr;
extern const char * const sys_errlist[];
- int main(void) { return (*sys_errlist[sys_nerr - 1]); }
+ extern int isatty(int);
+ int main(void) { return (*sys_errlist[sys_nerr - 1] + isatty(0)); }
EOF
ac_testn _sys_errlist '!' sys_errlist 0 "the _sys_errlist[] array and _sys_nerr" <<-'EOF'
extern const int _sys_nerr;
extern const char * const _sys_errlist[];
- int main(void) { return (*_sys_errlist[_sys_nerr - 1]); }
+ extern int isatty(int);
+ int main(void) { return (*_sys_errlist[_sys_nerr - 1] + isatty(0)); }
EOF
if test 1 = "$HAVE__SYS_ERRLIST"; then
add_cppflags -Dsys_nerr=_sys_nerr
@@ -1656,11 +1844,13 @@ for what in name list; do
uwhat=`upper $what`
ac_testn sys_sig$what '' "the sys_sig${what}[] array" <<-EOF
extern const char * const sys_sig${what}[];
- int main(void) { return (sys_sig${what}[0][0]); }
+ extern int isatty(int);
+ int main(void) { return (sys_sig${what}[0][0] + isatty(0)); }
EOF
ac_testn _sys_sig$what '!' sys_sig$what 0 "the _sys_sig${what}[] array" <<-EOF
extern const char * const _sys_sig${what}[];
- int main(void) { return (_sys_sig${what}[0][0]); }
+ extern int isatty(int);
+ int main(void) { return (_sys_sig${what}[0][0] + isatty(0)); }
EOF
eval uwhat_v=\$HAVE__SYS_SIG$uwhat
if test 1 = "$uwhat_v"; then
@@ -1703,12 +1893,22 @@ ac_test getrusage <<-'EOF'
}
EOF
+ac_test getsid <<-'EOF'
+ #include <unistd.h>
+ int main(void) { return ((int)getsid(0)); }
+EOF
+
ac_test gettimeofday <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
int main(void) { struct timeval tv; return (gettimeofday(&tv, NULL)); }
EOF
+ac_test issetugid <<-'EOF'
+ #include <unistd.h>
+ int main(void) { return (issetugid()); }
+EOF
+
ac_test killpg <<-'EOF'
#include <signal.h>
int main(int ac, char *av[]) { return (av[0][killpg(123, ac)]); }
@@ -1722,7 +1922,7 @@ ac_test memmove <<-'EOF'
#include <strings.h>
#endif
int main(int ac, char *av[]) {
- return (*(int *)(void *)memmove(av[0], av[1], ac));
+ return (*(int *)(void *)memmove(av[0], av[1], (size_t)ac));
}
EOF
@@ -1894,12 +2094,12 @@ EOF
ac_test sys_errlist_decl sys_errlist 0 "for declaration of sys_errlist[] and sys_nerr" <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
- int main(void) { return (*sys_errlist[sys_nerr - 1]); }
+ int main(void) { return (*sys_errlist[sys_nerr - 1] + isatty(0)); }
EOF
ac_test sys_siglist_decl sys_siglist 0 'for declaration of sys_siglist[]' <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
- int main(void) { return (sys_siglist[0][0]); }
+ int main(void) { return (sys_siglist[0][0] + isatty(0)); }
EOF
#
@@ -1970,7 +2170,7 @@ cta(ptr_fits_in_long, sizeof(ptrdiff_t) <= sizeof(long));
char padding[64 - NUM];
};
char ctasserts_dblcheck[sizeof(struct ctasserts) == 64 ? 1 : -1];
- int main(void) { return (sizeof(ctasserts_dblcheck)); }
+ int main(void) { return (sizeof(ctasserts_dblcheck) + isatty(0)); }
EOF
CFLAGS=$save_CFLAGS
eval test 1 = \$HAVE_COMPILE_TIME_ASSERTS_$$ || exit 1
@@ -2054,6 +2254,9 @@ if test 0 = $HAVE_SYS_SIGNAME; then
#define NSIG (SIGMAX+1)
#elif defined(_SIGMAX)
#define NSIG (_SIGMAX+1)
+#else
+/* XXX better error out, see sh.h */
+#define NSIG 64
#endif
#endif
int
@@ -2072,9 +2275,10 @@ mksh_cfg= NSIG
test $printf = echo || test "`printf %d 42`" = 42 || printf=echo
test $printf = echo || NSIG=`printf %d "$NSIG" 2>/dev/null`
$printf "NSIG=$NSIG ... "
- sigs="INT SEGV ABRT KILL ALRM BUS CHLD CLD CONT DIL EMT FPE HUP ILL"
- sigs="$sigs INFO IO IOT LOST PIPE PROF PWR QUIT RESV SAK STOP SYS TERM"
- sigs="$sigs TRAP TSTP TTIN TTOU URG USR1 USR2 VTALRM WINCH XCPU XFSZ"
+ sigs="ABRT FPE ILL INT SEGV TERM ALRM BUS CHLD CONT HUP KILL PIPE QUIT"
+ sigs="$sigs STOP TSTP TTIN TTOU USR1 USR2 POLL PROF SYS TRAP URG VTALRM"
+ sigs="$sigs XCPU XFSZ INFO WINCH EMT IO DIL LOST PWR SAK CLD IOT RESV"
+ sigs="$sigs STKFLT UNUSED"
test 1 = $HAVE_CPP_DD && test $NSIG -gt 1 && sigs="$sigs "`vq \
"$CPP $CFLAGS $CPPFLAGS $NOWARN -dD conftest.c" | \
grep '[ ]SIG[A-Z0-9][A-Z0-9]*[ ]' | \
@@ -2108,12 +2312,11 @@ mksh_cfg= NSIG
$e done.
fi
-addsrcs -s '!' HAVE_STRLCPY strlcpy.c
+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"
-test -n "$LDSTATIC" && add_cppflags -DMKSH_OPTSTATIC
-add_cppflags -DMKSH_BUILD_R=481
+add_cppflags -DMKSH_BUILD_R=504
$e $bi$me: Finished configuration testing, now producing output.$ao
@@ -2175,6 +2378,10 @@ cat >test.sh <<-EOF
fi
(( vflag )) && args[\${#args[*]}]=-v
(( xflag )) && args[\${#args[*]}]=-x # force usage by synerr
+ if [[ -n \$TMPDIR && -d \$TMPDIR/. ]]; then
+ args[\${#args[*]}]=-T
+ args[\${#args[*]}]=\$TMPDIR
+ fi
print Testing mksh for conformance:
fgrep -e MirOS: -e MIRBSD "\$sflag"
print "This shell is actually:\\n\\t\$KSH_VERSION"
@@ -2224,6 +2431,10 @@ llvm)
;;
esac
echo ": # work around NeXTstep bug" >Rebuild.sh
+for file in "$srcdir"/*.opt; do
+ echo "echo + Running genopt on '$file'..."
+ echo "(srcfile='$file'; BUILDSH_RUN_GENOPT=1; . '$srcdir/Build.sh')"
+done >>Rebuild.sh
echo set -x >>Rebuild.sh
for file in $SRCS; do
op=`echo x"$file" | sed 's/^x\(.*\)\.c$/\1./'`
@@ -2253,8 +2464,15 @@ echo tcfn=$mkshexe >>Rebuild.sh
echo "$CC $CFLAGS $LDFLAGS -o \$tcfn $lobjs $LIBS $ccpr" >>Rebuild.sh
echo "test -f \$tcfn || exit 1; $SIZE \$tcfn" >>Rebuild.sh
if test $cm = makefile; then
- extras='emacsfn.h sh.h sh_flags.h var_spec.h'
+ 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
+ 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"
+ done
cat >Makefrag.inc <<EOF
# Makefile fragment for building mksh $dstversion
@@ -2272,6 +2490,8 @@ CPPFLAGS= $CPPFLAGS
LDFLAGS= $LDFLAGS
LIBS= $LIBS
+.depend \$(OBJS_BP):$gens$genq
+
# not BSD make only:
#VPATH= $srcdir
#all: \$(PROG)
@@ -2295,6 +2515,10 @@ EOF
$e Generated Makefrag.inc successfully.
exit 0
fi
+for file in "$srcdir"/*.opt; do
+ $e "+ Running genopt on '$file'..."
+ do_genopt "$file" || exit 1
+done
if test $cm = combine; then
objs="-o $mkshexe"
for file in $SRCS; do
@@ -2402,7 +2626,7 @@ MKSH_DISABLE_TTY_WARNING shut up warning about ctty if OS cant be fixed
MKSH_DONT_EMIT_IDSTRING omit RCS IDs from binary
MKSH_MIDNIGHTBSD01ASH_COMPAT set -o sh: additional compatibility quirk
MKSH_NOPROSPECTOFWORK disable jobs, co-processes, etc. (do not use)
-MKSH_NOPWNAM skip PAM calls, for -static on eglibc, Solaris
+MKSH_NOPWNAM skip PAM calls, for -static on glibc or Solaris
MKSH_NO_CMDLINE_EDITING disable command line editing code entirely
MKSH_NO_DEPRECATED_WARNING omit warning when deprecated stuff is run
MKSH_NO_EXTERNAL_CAT omit hack to skip cat builtin when flags passed
@@ -2429,7 +2653,7 @@ $ (sh Build.sh -r -c lto && ./test.sh -f) 2>&1 | tee log
Copy dot.mkshrc to /etc/skel/.mkshrc; install mksh into $prefix/bin; or
/bin; install the manpage, if omitting the -r flag a catmanpage is made
using $NROFF. Consider using a forward script as /etc/skel/.mkshrc like
-https://www.mirbsd.org/cvs.cgi/contrib/hosted/tg/deb/mksh/debian/.mkshrc?rev=HEAD
+http://anonscm.debian.org/cgit/collab-maint/mksh.git/plain/debian/.mkshrc
and put dot.mkshrc as /etc/mkshrc so users need not keep up their HOME.
EOD
diff --git a/src/check.pl b/src/check.pl
index ecd8f8d..d688509 100644
--- a/src/check.pl
+++ b/src/check.pl
@@ -1,8 +1,8 @@
-# $MirOS: src/bin/mksh/check.pl,v 1.32 2013/07/21 18:35:56 tg Exp $
-# $OpenBSD: th,v 1.16 2013/06/14 20:52:08 millert Exp $
+# $MirOS: src/bin/mksh/check.pl,v 1.37 2014/08/19 07:43:32 tg Exp $
+# $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
-# 2012, 2013
+# 2012, 2013, 2014
# Thorsten Glaser <tg@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
@@ -172,7 +172,6 @@ BEGIN {
use Getopt::Std;
use Config;
-use File::Temp qw/ :mktemp /;
$os = defined $^O ? $^O : 'unknown';
@@ -251,7 +250,7 @@ die "$prog: no test set specified (use -s)\n" if !defined $opt_s;
$test_prog = $opt_p;
$verbose = defined $opt_v && $opt_v;
$test_set = $opt_s;
-$temp_dir = $opt_T || "/tmp";
+$temp_base = $opt_T || "/tmp";
if (defined $opt_t) {
die "$prog: bad -t argument (should be number > 0): $opt_t\n"
if $opt_t !~ /^\d+$/ || $opt_t <= 0;
@@ -300,6 +299,18 @@ chop($pwd = `pwd 2>/dev/null`);
die "$prog: couldn't get current working directory\n" if $pwd eq '';
die "$prog: couldn't cd to $pwd - $!\n" if !chdir($pwd);
+die "$prog: couldn't cd to $temp_base - $!\n" if !chdir($temp_base);
+die "$prog: couldn't get temporary directory base\n" unless -d '.';
+$temps = sprintf("chk%d-%d.", $$, time());
+$tempi = 0;
+until (mkdir(($tempdir = sprintf("%s%03d", $temps, $tempi)), 0700)) {
+ die "$prog: couldn't get temporary directory\n" if $tempi++ >= 999;
+}
+die "$prog: couldn't cd to $tempdir - $!\n" if !chdir($tempdir);
+chop($temp_dir = `pwd 2>/dev/null`);
+die "$prog: couldn't get temporary directory\n" if $temp_dir eq '';
+die "$prog: couldn't cd to $pwd - $!\n" if !chdir($pwd);
+
if (!$program_kludge) {
$test_prog = "$pwd/$test_prog" if substr($test_prog, 0, 1) ne '/';
die "$prog: $test_prog is not executable - bye\n"
@@ -314,15 +325,12 @@ $SIG{'ALRM'} = 'catch_sigalrm';
$| = 1;
# Create temp files
-($fh, $temps) = mkstemp("${temp_dir}/rts.XXXXXXXX");
-close($fh);
-($fh, $tempi) = mkstemp("${temp_dir}/rti.XXXXXXXX");
-close($fh);
-($fh, $tempo) = mkstemp("${temp_dir}/rto.XXXXXXXX");
-close($fh);
-($fh, $tempe) = mkstemp("${temp_dir}/rte.XXXXXXXX");
-close($fh);
-$tempdir = mkdtemp("${temp_dir}/rtd.XXXXXXXX");
+$temps = "${temp_dir}/rts";
+$tempi = "${temp_dir}/rti";
+$tempo = "${temp_dir}/rto";
+$tempe = "${temp_dir}/rte";
+$tempdir = "${temp_dir}/rtd";
+mkdir($tempdir, 0700) or die "$prog: couldn't mkdir $tempdir - $!\n";
if (-d $test_set) {
$file_prefix_skip = length($test_set) + 1;
@@ -340,6 +348,7 @@ if ($tot_failed || $tot_passed) {
print " ($nifailed ignored)" if $nifailed;
print " ($nxfailed unexpected)" if $nxfailed;
print " (as expected)" if $nfailed && !$nxfailed && !$nifailed;
+ print " ($nfailed expected)" if $nfailed && ($nxfailed || $nifailed);
print "\nTotal passed: $tot_passed";
print " ($nxpassed unexpected)" if $nxpassed;
print "\n";
@@ -365,6 +374,7 @@ cleanup_exit
unlink($tempi, $tempo, $tempe, $temps);
&scrub_dir($tempdir) if defined $tempdir;
rmdir($tempdir) if defined $tempdir;
+ rmdir($temp_dir) if defined $temp_dir;
if ($sig) {
$SIG{$sig} = 'DEFAULT';
@@ -903,7 +913,7 @@ eval_exit
} else {
$expr = $expect;
$expr =~ s/\b([wse])\b/\$$1/g;
- $expr =~ s/\b(SIG[A-Z0-9]+)\b/&$1/g;
+ $expr =~ s/\b(SIG[A-Z][A-Z0-9]*)\b/&$1/g;
}
$w = eval $expr;
if ($@ ne '') {
@@ -923,12 +933,13 @@ read_test
%test = ();
%cnt = ();
while (<$in>) {
+ chop;
next if /^\s*$/;
next if /^ *#/;
last if /^\s*---\s*$/;
$start_lineno = $. if !defined $start_lineno;
if (!/^([-\w]+):\s*(|\S|\S.*\S)\s*$/) {
- print STDERR "$prog:$file:$.: unrecognised line\n";
+ print STDERR "$prog:$file:$.: unrecognised line \"$_\"\n";
return undef;
}
($field, $val) = ($1, $2);
@@ -1154,7 +1165,7 @@ read_test
print STDERR "$prog:$test{':long-name'}: expected-exit value $val not in 0..255\n";
return undef;
}
- } elsif ($val !~ /^([\s<>+-=*%\/&|!()]|\b[wse]\b|\bSIG[A-Z0-9]+\b)+$/) {
+ } elsif ($val !~ /^([\s<>+-=*%\/&|!()]|\b[wse]\b|\bSIG[A-Z][A-Z0-9]*\b)+$/) {
print STDERR "$prog:$test{':long-name'}: bad expected-exit expression: $val\n";
return undef;
}
diff --git a/src/check.t b/src/check.t
index 8df826f..2e1d032 100644
--- a/src/check.t
+++ b/src/check.t
@@ -1,12 +1,8 @@
-# $MirOS: src/bin/mksh/check.t,v 1.629 2013/08/14 20:26:15 tg Exp $
-# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
-# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
-# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
-# $OpenBSD: regress.t,v 1.15 2013/07/01 17:25:27 jca Exp $
-# $OpenBSD: obsd-regress.t,v 1.5 2013/07/01 17:25:27 jca Exp $
+# $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
#-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013
+# 2011, 2012, 2013, 2014
# Thorsten Glaser <tg@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
@@ -31,7 +27,7 @@
# http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
expected-stdout:
- @(#)MIRBSD KSH R48 2013/08/14
+ @(#)MIRBSD KSH R50 2014/10/07
description:
Check version of shell.
stdin:
@@ -40,7 +36,7 @@ name: KSH_VERSION
category: shell:legacy-no
---
expected-stdout:
- @(#)LEGACY KSH R48 2013/08/14
+ @(#)LEGACY KSH R50 2014/10/07
description:
Check version of legacy shell.
stdin:
@@ -74,6 +70,18 @@ stdin:
expected-stdout:
<fnord>
---
+name: selftest-exec
+description:
+ Ensure that the test run directory (default /tmp but can be changed
+ with check.pl flag -T or test.sh $TMPDIR) is not mounted noexec, as
+ we execute scripts from the scratch directory during several tests.
+stdin:
+ print '#!'"$__progname"'\necho tf' >lq
+ chmod +x lq
+ ./lq
+expected-stdout:
+ tf
+---
name: selftest-env
description:
Just output the environment variables set (always fails)
@@ -1640,6 +1648,14 @@ expected-stdout:
1=02.
2=02.
---
+name: expand-number-1
+description:
+ Check that positional arguments do not overflow
+stdin:
+ echo "1 ${12345678901234567890} ."
+expected-stdout:
+ 1 .
+---
name: eglob-bad-1
description:
Check that globbing isn't done when glob has syntax error
@@ -2071,12 +2087,18 @@ stdin:
echo [!-ab]*
echo [!ab]*
echo []ab]*
+ :>'./!bc'
+ :>'./^bc'
+ echo [^ab]*
+ echo [!ab]*
expected-stdout:
-bc abc bbc
-bc abc bbc
cbc
-bc cbc
abc bbc
+ ^bc abc bbc
+ !bc -bc ^bc cbc
---
name: glob-range-2
description:
@@ -2126,6 +2148,18 @@ stdin:
expected-stdout:
-bc abc bbc cbc ebc
---
+name: glob-trim-1
+description:
+ Check against a regression from fixing IFS-subst-2
+stdin:
+ x='#foo'
+ print -r "before='$x'"
+ x=${x%%#*}
+ print -r "after ='$x'"
+expected-stdout:
+ before='#foo'
+ after =''
+---
name: heredoc-1
description:
Check ordering/content of redundent here documents.
@@ -3689,6 +3723,428 @@ expected-stdout:
12: [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; }
+ x="X 1 2"
+ showargs 1 shift ${x#X}
+expected-stdout:
+ <1> <shift> <1> <2>
+---
+name: IFS-subst-3
+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 0 ${-+}
+ IFS=:
+ showargs 1 ${-+:foo:bar}
+ IFS=' '
+ showargs 2 ${-+ foo bar}
+expected-stdout:
+ <0>
+ <1> <> <foo> <bar>
+ <2> <foo> <bar>
+---
+name: IFS-subst-4-1
+description:
+ reported by mikeserv
+stdin:
+ a='space divded argument
+ here'
+ IFS=\ ; set -- $a
+ IFS= ; q="$*" ; nq=$*
+ printf '<%s>\n' "$*" $* "$q" "$nq"
+ [ "$q" = "$nq" ] && echo =true || echo =false
+expected-stdout:
+ <spacedivdedargument
+ here>
+ <space>
+ <divded>
+ <argument
+ here>
+ <spacedivdedargument
+ here>
+ <spacedivdedargument
+ here>
+ =true
+---
+name: IFS-subst-4-2
+description:
+ extended testsuite based on problem by mikeserv
+stdin:
+ a='space divded argument
+ here'
+ IFS=\ ; set -- $a
+ IFS= ; q="$@" ; nq=$@
+ printf '<%s>\n' "$*" $* "$q" "$nq"
+ [ "$q" = "$nq" ] && echo =true || echo =false
+expected-stdout:
+ <spacedivdedargument
+ here>
+ <space>
+ <divded>
+ <argument
+ here>
+ <space divded argument
+ here>
+ <space divded argument
+ here>
+ =true
+---
+name: IFS-subst-4-3
+description:
+ extended testsuite based on problem by mikeserv
+stdin:
+ a='space divded argument
+ here'
+ IFS=\ ; set -- $a; IFS=
+ qs="$*"
+ 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' $@
+expected-stdout:
+ = qs <spacedivdedargument
+ here>
+ =nqs <spacedivdedargument
+ here>
+ = qk <space divded argument
+ here>
+ =nqk <space divded argument
+ here>
+ ~ qs <spacedivdedargument
+ here>
+ ~nqs <space>
+ <divded>
+ <argument
+ here>
+ ~ qk <space>
+ <divded>
+ <argument
+ here>
+ ~nqk <space>
+ <divded>
+ <argument
+ here>
+---
+name: IFS-subst-4-4
+description:
+ extended testsuite based on problem by mikeserv
+stdin:
+ a='space divded argument
+ here'
+ IFS=\ ; set -- $a; IFS=
+ qs="$*"
+ printf '= qs '; printf '<%s>\n' "$qs"
+ printf '~ qs '; printf '<%s>\n' "$*"
+ nqs=$*
+ printf '=nqs '; printf '<%s>\n' "$nqs"
+ printf '~nqs '; printf '<%s>\n' $*
+ qk="$@"
+ printf '= qk '; printf '<%s>\n' "$qk"
+ printf '~ qk '; printf '<%s>\n' "$@"
+ nqk=$@
+ printf '=nqk '; printf '<%s>\n' "$nqk"
+ printf '~nqk '; printf '<%s>\n' $@
+expected-stdout:
+ = qs <spacedivdedargument
+ here>
+ ~ qs <spacedivdedargument
+ here>
+ =nqs <spacedivdedargument
+ here>
+ ~nqs <space>
+ <divded>
+ <argument
+ here>
+ = qk <space divded argument
+ here>
+ ~ qk <space>
+ <divded>
+ <argument
+ here>
+ =nqk <space divded argument
+ here>
+ ~nqk <space>
+ <divded>
+ <argument
+ here>
+---
+name: IFS-subst-4-4p
+description:
+ extended testsuite based on problem by mikeserv
+stdin:
+ 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:-"$*"}
+ nqs=${v:-$*}
+ printf '=nqs '; printf '<%s>\n' "$nqs"
+ printf '~nqs '; printf '<%s>\n' ${v:-$*}
+ qk=${v:-"$@"}
+ printf '= qk '; printf '<%s>\n' "$qk"
+ printf '~ qk '; printf '<%s>\n' ${v:-"$@"}
+ nqk=${v:-$@}
+ printf '=nqk '; printf '<%s>\n' "$nqk"
+ printf '~nqk '; printf '<%s>\n' ${v:-$@}
+expected-stdout:
+ = qs <spacedivdedargument
+ here>
+ ~ qs <spacedivdedargument
+ here>
+ =nqs <spacedivdedargument
+ here>
+ ~nqs <space>
+ <divded>
+ <argument
+ here>
+ = qk <space divded argument
+ here>
+ ~ qk <space>
+ <divded>
+ <argument
+ here>
+ =nqk <space divded argument
+ here>
+ ~nqk <space>
+ <divded>
+ <argument
+ here>
+---
+name: IFS-subst-4-5
+description:
+ extended testsuite based on problem by mikeserv
+stdin:
+ a='space divded argument
+ here'
+ IFS=\ ; set -- $a; IFS=,
+ qs="$*"
+ printf '= qs '; printf '<%s>\n' "$qs"
+ printf '~ qs '; printf '<%s>\n' "$*"
+ nqs=$*
+ printf '=nqs '; printf '<%s>\n' "$nqs"
+ printf '~nqs '; printf '<%s>\n' $*
+ qk="$@"
+ printf '= qk '; printf '<%s>\n' "$qk"
+ printf '~ qk '; printf '<%s>\n' "$@"
+ nqk=$@
+ printf '=nqk '; printf '<%s>\n' "$nqk"
+ printf '~nqk '; printf '<%s>\n' $@
+expected-stdout:
+ = qs <space,divded,argument
+ here>
+ ~ qs <space,divded,argument
+ here>
+ =nqs <space,divded,argument
+ here>
+ ~nqs <space>
+ <divded>
+ <argument
+ here>
+ = qk <space divded argument
+ here>
+ ~ qk <space>
+ <divded>
+ <argument
+ here>
+ =nqk <space divded argument
+ here>
+ ~nqk <space>
+ <divded>
+ <argument
+ here>
+---
+name: IFS-subst-4-5p
+description:
+ extended testsuite based on problem by mikeserv
+stdin:
+ 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:-"$*"}
+ nqs=${v:-$*}
+ printf '=nqs '; printf '<%s>\n' "$nqs"
+ printf '~nqs '; printf '<%s>\n' ${v:-$*}
+ qk=${v:-"$@"}
+ printf '= qk '; printf '<%s>\n' "$qk"
+ printf '~ qk '; printf '<%s>\n' ${v:-"$@"}
+ nqk=${v:-$@}
+ printf '=nqk '; printf '<%s>\n' "$nqk"
+ printf '~nqk '; printf '<%s>\n' ${v:-$@}
+expected-stdout:
+ = qs <space,divded,argument
+ here>
+ ~ qs <space,divded,argument
+ here>
+ =nqs <space,divded,argument
+ here>
+ ~nqs <space>
+ <divded>
+ <argument
+ here>
+ = qk <space divded argument
+ here>
+ ~ qk <space>
+ <divded>
+ <argument
+ here>
+ =nqk <space divded argument
+ here>
+ ~nqk <space>
+ <divded>
+ <argument
+ here>
+---
+name: IFS-subst-5
+description:
+ extended testsuite based on IFS-subst-3
+ differs slightly from ksh93:
+ - omit trailing field in a3zna, a7ina (unquoted $@ expansion)
+ - has extra middle fields in b5ins, b7ina (IFS_NWS unquoted expansion)
+ differs slightly from bash:
+ - omit leading field in a5ins, a7ina (IFS_NWS unquoted expansion)
+ differs slightly from zsh:
+ - differs in assignment, not expansion; probably zsh bug
+ - has extra middle fields in b5ins, b7ina (IFS_NWS unquoted expansion)
+ 'emulate sh' zsh has extra fields in
+ - a5ins (IFS_NWS unquoted $*)
+ - b5ins, matching mksh’s
+stdin:
+ "$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+ echo '=a1zns'
+ "$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+ echo '=a2zqs'
+ "$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+ echo '=a3zna'
+ "$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+ echo '=a4zqa'
+ "$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+ echo '=a5ins'
+ "$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+ echo '=a6iqs'
+ "$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+ echo '=a7ina'
+ "$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+ echo '=a8iqa'
+ "$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+ echo '=b1zns'
+ "$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+ echo '=b2zqs'
+ "$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+ echo '=b3zna'
+ "$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+ echo '=b4zqa'
+ "$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
+ echo '=b5ins'
+ "$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
+ echo '=b6iqs'
+ "$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
+ echo '=b7ina'
+ "$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
+ echo '=b8iqa'
+expected-stdout:
+ [2]
+ <2>
+ =a1zns
+ [2]
+ <2>
+ =a2zqs
+ [2]
+ < 2 >
+ =a3zna
+ []
+ [2]
+ []
+ < 2 >
+ =a4zqa
+ [2]
+ <,2,>
+ =a5ins
+ [,2,]
+ <,2,>
+ =a6iqs
+ [2]
+ < 2 >
+ =a7ina
+ []
+ [2]
+ []
+ < 2 >
+ =a8iqa
+ [A]
+ [B]
+ [C]
+ <ABC>
+ =b1zns
+ [ABC]
+ <ABC>
+ =b2zqs
+ [A]
+ [B]
+ [C]
+ <A B C>
+ =b3zna
+ [A]
+ [B]
+ []
+ []
+ [C]
+ <A B C>
+ =b4zqa
+ [A]
+ [B]
+ []
+ []
+ [C]
+ <A,B,,,C>
+ =b5ins
+ [A,B,,,C]
+ <A,B,,,C>
+ =b6iqs
+ [A]
+ [B]
+ []
+ []
+ [C]
+ <A B C>
+ =b7ina
+ [A]
+ [B]
+ []
+ []
+ [C]
+ <A B C>
+ =b8iqa
+---
+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 .; }
+ IFS=0
+ showargs $((1230456))
+expected-stdout:
+ <123> <456> .
+---
name: integer-base-err-1
description:
Can't have 0 base (causes shell to exit)
@@ -4806,11 +5262,12 @@ description:
them exit 0. The POSIX behaviour is needed by BSD make.
stdin:
set -e
- echo `false; echo hi`
+ echo `false; echo hi` $(<this-file-does-not-exist)
echo $?
expected-stdout:
0
+expected-stderr-pattern: /this-file-does-not-exist/
---
name: regression-40
description:
@@ -5426,6 +5883,18 @@ expected-stdout:
expected-stderr-pattern:
/read-only/
---
+name: readonly-4
+description:
+ Do not permit bypassing readonly for first array item
+stdin:
+ set -A arr -- foo bar
+ readonly arr
+ arr=baz
+ print -r -- "${arr[@]}"
+expected-exit: e != 0
+expected-stderr-pattern:
+ /read[ -]?only/
+---
name: syntax-1
description:
Check that lone ampersand is a syntax error
@@ -6444,6 +6913,7 @@ stdin:
echo 6 "$("$__progname" -c '! (exit 23) | (exit 42) | :; echo $?')" .
echo 7 "$("$__progname" -o pipefail -c '(exit 23) | (exit 42) | :; echo $?')" .
echo 8 "$("$__progname" -o pipefail -c '! (exit 23) | (exit 42) | :; echo $?')" .
+ echo 9 "$("$__progname" -o pipefail -c 'x=$( (exit 23) | (exit 42) | :); echo $?')" .
expected-stdout:
1 42 .
2 0 .
@@ -6453,6 +6923,7 @@ expected-stdout:
6 1 .
7 42 .
8 0 .
+ 9 42 .
---
name: persist-history-1
description:
@@ -6733,7 +7204,6 @@ expected-stdout:
r='fc -e -'
source='PATH=$PATH:. command .'
stop='kill -STOP'
- suspend='kill -STOP $$'
type='whence -v'
---
name: aliases-1-hartz4
@@ -6802,7 +7272,6 @@ expected-stdout:
r='fc -e -'
source='PATH=$PATH:. command .'
stop='kill -STOP'
- suspend='kill -STOP $$'
type='whence -v'
---
name: aliases-3b
@@ -6826,7 +7295,6 @@ expected-stdout:
r='fc -e -'
source='PATH=$PATH:. command .'
stop='kill -STOP'
- suspend='kill -STOP $$'
type='whence -v'
---
name: aliases-2b-hartz4
@@ -7000,12 +7468,19 @@ stdin:
v="c d"
set -A foo -- [1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b
echo "${#foo[*]}|${foo[0]}|${foo[1]}|${foo[2]}|${foo[3]}|${foo[4]}|${foo[5]}|"
+ # we don't want this at all:
+ # 5|a|$v|c d||$v|b|
+ set -A arr "[5]=meh"
+ echo "<${arr[0]}><${arr[5]}>"
expected-stdout:
- 5|a|$v|c d||$v|b|
+ 5|[1]=$v|[2]=c d|[4]=$v|[0]=a|[5]=b||
+ <[5]=meh><>
---
name: arrays-5
description:
Check if bash-style arrays with specified indices work as expected
+ (taken out temporarily to fix arrays-4; see also arrays-9a comment)
+category: disabled
stdin:
v="c d"
foo=([1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b)
@@ -7013,10 +7488,17 @@ stdin:
x=([128]=foo bar baz)
echo k= ${!x[*]} .
echo v= ${x[*]} .
+ # Check that we do not break this by globbing
+ :>b=blah
+ bleh=5
+ typeset -a arr
+ arr+=([bleh]=blah)
+ echo "<${arr[0]}><${arr[5]}>"
expected-stdout:
5|a|$v|c d||$v|b|
k= 128 129 130 .
v= foo bar baz .
+ <><blah>
---
name: arrays-6
description:
@@ -7078,15 +7560,15 @@ stdin:
echo !arz[0]: ${!arz[0]}
echo !arz[1]: ${!arz[1]}
expected-stdout:
- !arz: 0
- !arz[0]:
- !arz[1]:
!arz: arz
- !arz[0]: 0
- !arz[1]:
- !arz: 0
- !arz[0]:
- !arz[1]:
+ !arz[0]: arz[0]
+ !arz[1]: arz[1]
+ !arz: arz
+ !arz[0]: arz[0]
+ !arz[1]: arz[1]
+ !arz: arz
+ !arz[0]: arz[0]
+ !arz[1]: arz[1]
---
name: arrays-8
description:
@@ -7177,11 +7659,11 @@ description:
stdin:
unset foo; foo=(bar); foo+=(baz); echo 1 ${!foo[*]} : ${foo[*]} .
unset foo; foo=(foo bar); foo+=(baz); echo 2 ${!foo[*]} : ${foo[*]} .
- unset foo; foo=([2]=foo [0]=bar); foo+=(baz [5]=quux); echo 3 ${!foo[*]} : ${foo[*]} .
+# unset foo; foo=([2]=foo [0]=bar); foo+=(baz [5]=quux); echo 3 ${!foo[*]} : ${foo[*]} .
expected-stdout:
1 0 1 : bar baz .
2 0 1 2 : foo bar baz .
- 3 0 2 3 5 : bar foo baz quux .
+# 3 0 2 3 5 : bar foo baz quux .
---
name: arrays-9b
description:
@@ -7660,14 +8142,9 @@ stdin:
typeset -i8 foo=10
bar=baz
unset baz
- bla=foo
print ${foo@#} ${bar@#} ${baz@#} .
- print ${foo@#123} ${bar@#456} ${baz@#789} .
- print ${foo@#bla} ${bar@#bar} ${baz@#OPTIND} .
expected-stdout:
- D50219A0 20E5DB5B 00000000 .
- 554A1C76 004A212E CB209562 .
- 6B21CF91 20E5DB5B 124EA49D .
+ 9B15FBFB CFBDD32B 00000000 .
---
name: varexpand-special-quote
description:
@@ -7714,6 +8191,17 @@ stdin:
expected-stdout:
<1> <> <2> <> <+> <> <3> <> <+> <> .
---
+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<>
+---
name: print-funny-chars
description:
Check print builtin's capability to output designated characters
@@ -8772,7 +9260,7 @@ expected-stdout:
---
name: oksh-eval
description:
- $OpenBSD: eval.sh,v 1.1 2010/03/24 08:29:44 fgsch Exp $
+ Check expansions.
stdin:
a=
for n in ${a#*=}; do echo 1hu ${n} .; done
@@ -8932,8 +9420,7 @@ stdin:
---
name: oksh-varfunction-mod1
description:
- $OpenBSD: varfunction.sh,v 1.1 2003/12/15 05:28:40 otto Exp $
- Calling
+ (Inspired by PR 2450 on OpenBSD.) Calling
FOO=bar f
where f is a ksh style function, should not set FOO in the current
env. If f is a Bourne style function, FOO should be set. Furthermore,
@@ -8941,7 +9428,6 @@ description:
from oksh, setting FOO in the function itself must change the value in
setting FOO in the function itself should not change the value in
global environment.
- Inspired by PR 2450.
stdin:
print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
@@ -10502,7 +10988,7 @@ expected-stdout:
ir2: ir2
s1: ir2=ind
s2: typeset -n ir2
- !ind[1]: 1
+ !ind[1]: blub[1]
!ir2: ir2
ind[1]: e2
ir2: e3
diff --git a/src/dot.mkshrc b/src/dot.mkshrc
index 607f40d..7329ee5 100644
--- a/src/dot.mkshrc
+++ b/src/dot.mkshrc
@@ -1,8 +1,8 @@
# $Id$
-# $MirOS: src/bin/mksh/dot.mkshrc,v 1.84 2013/08/10 13:43:50 tg Exp $
+# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89 2014/07/28 21:45:44 tg Exp $
#-
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013
+# 2011, 2012, 2013, 2014
# Thorsten Glaser <tg@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
@@ -105,14 +105,14 @@ function chpwd {
}
chpwd .
function cd {
- builtin cd "$@"
+ builtin cd "$@" || return $?
chpwd "$@"
}
function cd_csh {
local d t=${1/#~/$DIRSTACKBASE}
if ! d=$(builtin cd "$t" 2>&1); then
- print -u2 "${1}: ${d##*$t - }."
+ print -u2 "${1}: ${d##*cd: $t: }."
return 1
fi
cd "$t"
@@ -242,20 +242,23 @@ function pushd {
# pager (not control character safe)
function smores {
- local dummy line llen curlin=0
-
- cat "$@" | while IFS= read -r line; do
- llen=${%line}
- (( llen == -1 )) && llen=${#line}
- (( llen = llen ? (llen + COLUMNS - 1) / COLUMNS : 1 ))
- if (( (curlin += llen) >= LINES )); then
- print -n -- '\033[7m--more--\033[0m'
- read -u1 dummy
- [[ $dummy = [Qq]* ]] && return 0
- curlin=$llen
- fi
- print -r -- "$line"
- done
+ (
+ set +m
+ cat "$@" |&
+ trap "rv=\$?; kill $! >/dev/null 2>&1; exit \$rv" EXIT
+ while IFS= read -pr line; do
+ llen=${%line}
+ (( llen == -1 )) && llen=${#line}
+ (( llen = llen ? (llen + COLUMNS - 1) / COLUMNS : 1 ))
+ if (( (curlin += llen) >= LINES )); then
+ print -n -- '\033[7m--more--\033[0m'
+ read -u1 || exit $?
+ [[ $REPLY = [Qq]* ]] && exit 0
+ curlin=$llen
+ fi
+ print -r -- "$line"
+ done
+ )
}
# base64 encoder and decoder, RFC compliant, NUL safe
@@ -333,9 +336,12 @@ function Lb64encode {
(( u )) || set -U
}
-# mksh NUL counting, never zero
-typeset -Z11 -Uui16 Lnzathash_v
-function Lnzathash_add {
+# Better Avalanche for the Jenkins Hash
+typeset -Z11 -Uui16 Lbafh_v
+function Lbafh_init {
+ Lbafh_v=0
+}
+function Lbafh_add {
[[ -o utf8-mode ]]; local u=$?
set +U
local s
@@ -348,37 +354,20 @@ function Lnzathash_add {
local -i i=0 n=${#s[*]}
while (( i < n )); do
- ((# Lnzathash_v = (Lnzathash_v + s[i++] + 1) * 1025 ))
- ((# Lnzathash_v ^= Lnzathash_v >> 6 ))
+ ((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 ))
+ ((# Lbafh_v ^= Lbafh_v >> 6 ))
done
(( u )) || set -U
}
-function Lnzaathash_end {
- ((# Lnzathash_v *= 1025 ))
- ((# Lnzathash_v ^= Lnzathash_v >> 6 ))
- ((# Lnzathash_v += Lnzathash_v << 3 ))
- ((# Lnzathash_v = (Lnzathash_v ^
- (Lnzathash_v >> 11)) * 32769 ))
- print ${Lnzathash_v#16#}
-}
-function Lnzaathash {
- Lnzathash_v=0
- Lnzathash_add "$@"
- Lnzaathash_end
-}
-function Lnzathash {
- Lnzathash_v=0
- Lnzathash_add "$@"
- Lnzathash_end
-}
-function Lnzathash_end {
- if (( Lnzathash_v )); then
- Lnzaathash_end
- else
- Lnzathash_v=1
- print ${Lnzathash_v#16#}
- fi
+function Lbafh_finish {
+ local -Ui t
+
+ ((# t = (((Lbafh_v >> 7) & 0x01010101) * 0x1B) ^ \
+ ((Lbafh_v << 1) & 0xFEFEFEFE) ))
+ ((# Lbafh_v = t ^ (t >>> 8) ^ (Lbafh_v >>> 8) ^ \
+ (Lbafh_v >>> 16) ^ (Lbafh_v >>> 24) ))
+ :
}
# strip comments (and leading/trailing whitespace if IFS is set) from
diff --git a/src/edit.c b/src/edit.c
index 675e7ed..ee5ed5c 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -1,11 +1,11 @@
-/* $OpenBSD: edit.c,v 1.38 2013/06/03 15:41:59 tedu Exp $ */
+/* $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.44 2011/09/05 04:50:33 marco Exp $ */
-/* $OpenBSD: vi.c,v 1.26 2009/06/29 22:50:19 martynas Exp $ */
+/* $OpenBSD: emacs.c,v 1.48 2013/12/17 16:37:05 deraadt Exp $ */
+/* $OpenBSD: vi.c,v 1.28 2013/12/18 16:45:46 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@@ -28,7 +28,7 @@
#ifndef MKSH_NO_CMDLINE_EDITING
-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.270 2013/08/14 20:26:17 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276 2014/07/13 11:34:28 tg Exp $");
/*
* in later versions we might use libtermcap for this, but since external
@@ -82,7 +82,7 @@ static int x_basename(const char *, const char *);
static void x_free_words(int, char **);
static int x_escape(const char *, size_t, int (*)(const char *, size_t));
static int x_emacs(char *);
-static void x_init_prompt(void);
+static void x_init_prompt(bool);
#if !MKSH_S_NOVI
static int x_vi(char *);
#endif
@@ -148,6 +148,7 @@ x_getc(void)
if (x_cols != xx_cols && editmode == 1) {
/* redraw line in Emacs mode */
xx_cols = x_cols;
+ x_init_prompt(false);
x_e_rebuildline(MKSH_CLRTOEOL_STRING);
}
}
@@ -960,12 +961,11 @@ static void x_delete(size_t, bool);
static size_t x_bword(void);
static size_t x_fword(bool);
static void x_goto(char *);
-static char *x_bs0(char *, char *);
+static char *x_bs0(char *, char *) MKSH_A_PURE;
static void x_bs3(char **);
static int x_size_str(char *);
static int x_size2(char *, char **);
static void x_zots(char *);
-static void x_zotc2(int);
static void x_zotc3(char **);
static void x_load_hist(char **);
static int x_search(char *, int, int);
@@ -990,7 +990,7 @@ static int x_fold_case(int);
#endif
static char *x_lastcp(void);
static void do_complete(int, Comp_type);
-static size_t x_nb2nc(size_t);
+static size_t x_nb2nc(size_t) MKSH_A_PURE;
static int unget_char = -1;
@@ -1167,16 +1167,17 @@ x_e_getmbc(char *sbuf)
}
static void
-x_init_prompt(void)
+x_init_prompt(bool doprint)
{
- prompt_trunc = pprompt(prompt, 0);
+ prompt_trunc = pprompt(prompt, doprint ? 0 : -1);
pwidth = prompt_trunc % x_cols;
prompt_trunc -= pwidth;
if ((mksh_uari_t)pwidth > ((mksh_uari_t)x_cols - 3 - MIN_EDIT_SPACE)) {
/* force newline after prompt */
prompt_trunc = -1;
pwidth = 0;
- x_e_putc2('\n');
+ if (doprint)
+ x_e_putc2('\n');
}
}
@@ -1196,7 +1197,7 @@ x_emacs(char *buf)
x_histp = histptr + 1;
x_last_command = XFUNC_error;
- x_init_prompt();
+ x_init_prompt(true);
x_displen = (xx_cols = x_cols) - 2 - (x_col = pwidth);
x_adj_done = 0;
x_adj_ok = true;
@@ -1606,7 +1607,7 @@ x_size_str(char *cp)
static int
x_size2(char *cp, char **dcp)
{
- int c = *(unsigned char *)cp;
+ uint8_t c = *(unsigned char *)cp;
if (UTFMODE && (c > 0x7F))
return (utf_widthadj(cp, (const char **)dcp));
@@ -1615,7 +1616,7 @@ x_size2(char *cp, char **dcp)
if (c == '\t')
/* Kludge, tabs are always four spaces. */
return (4);
- if (c < ' ' || c == 0x7f)
+ if (ISCTRL(c) && /* but not C1 */ c < 0x80)
/* control unsigned char */
return (2);
return (1);
@@ -1627,24 +1628,11 @@ x_zots(char *str)
int adj = x_adj_done;
x_lastcp();
- while (*str && str < xlp && adj == x_adj_done)
+ while (*str && str < xlp && x_col < xx_cols && adj == x_adj_done)
x_zotc3(&str);
}
static void
-x_zotc2(int c)
-{
- if (c == '\t') {
- /* Kludge, tabs are always four spaces. */
- x_e_puts(" ");
- } else if (c < ' ' || c == 0x7f) {
- x_e_putc2('^');
- x_e_putc2(UNCTRL(c));
- } else
- x_e_putc2(c);
-}
-
-static void
x_zotc3(char **cp)
{
unsigned char c = **(unsigned char **)cp;
@@ -1653,7 +1641,7 @@ x_zotc3(char **cp)
/* Kludge, tabs are always four spaces. */
x_e_puts(" ");
(*cp)++;
- } else if (c < ' ' || c == 0x7f) {
+ } else if (ISCTRL(c) && /* but not C1 */ c < 0x80) {
x_e_putc2('^');
x_e_putc2(UNCTRL(c));
(*cp)++;
@@ -1765,7 +1753,10 @@ x_newline(int c MKSH_A_UNUSED)
static int
x_end_of_text(int c MKSH_A_UNUSED)
{
- x_zotc2(edchars.eof);
+ char tmp = edchars.eof;
+ char *cp = &tmp;
+
+ x_zotc3(&cp);
x_putc('\r');
x_putc('\n');
x_flush();
@@ -2377,6 +2368,7 @@ x_mapin(const char *cp, Area *ap)
/* XXX -- should handle \^ escape? */
if (*cp == '^') {
cp++;
+ /*XXX or ^^ escape? this is ugly. */
if (*cp >= '?')
/* includes '?'; ASCII */
*op++ = CTRL(*cp);
@@ -2398,7 +2390,7 @@ x_mapout2(int c, char **buf)
{
char *p = *buf;
- if (c < ' ' || c == 0x7f) {
+ if (ISCTRL(c)) {
*p++ = '^';
*p++ = UNCTRL(c);
} else
@@ -3341,8 +3333,6 @@ x_mode(bool onoff)
#if !MKSH_S_NOVI
/* +++ vi editing mode +++ */
-#define Ctrl(c) (c&0x1f)
-
struct edstate {
char *cbuf;
ssize_t winleft;
@@ -3363,7 +3353,7 @@ static void save_cbuf(void);
static void restore_cbuf(void);
static int putbuf(const char *, ssize_t, bool);
static void del_range(int, int);
-static int findch(int, int, bool, bool);
+static int findch(int, int, bool, bool) MKSH_A_PURE;
static int forwword(int);
static int backword(int);
static int endword(int);
@@ -3376,13 +3366,14 @@ static void redraw_line(bool);
static void refresh(int);
static int outofwin(void);
static void rewindow(void);
-static int newcol(int, int);
+static int newcol(unsigned char, int);
static void display(char *, char *, int);
static void ed_mov_opt(int, char *);
static int expand_word(int);
static int complete_word(int, int);
static int print_expansions(struct edstate *, int);
-#define char_len(c) ((c) < ' ' || (c) == 0x7F ? 2 : 1)
+#define char_len(c) ((ISCTRL((unsigned char)c) && \
+ /* but not C1 */ (unsigned char)c < 0x80) ? 2 : 1)
static void x_vi_zotc(int);
static void vi_error(void);
static void vi_macro_reset(void);
@@ -3535,7 +3526,7 @@ x_vi(char *buf)
es = &ebuf;
undo = &undobuf;
- x_init_prompt();
+ x_init_prompt(true);
x_col = pwidth;
if (wbuf_len != x_cols - 3 && ((wbuf_len = x_cols - 3))) {
@@ -3556,7 +3547,7 @@ x_vi(char *buf)
x_flush();
while (/* CONSTCOND */ 1) {
if (macro.p) {
- c = *macro.p++;
+ c = (unsigned char)*macro.p++;
/* end of current macro? */
if (!c) {
/* more macros left to finish? */
@@ -3618,7 +3609,7 @@ vi_hook(int ch)
case VNORMAL:
if (insert != 0) {
- if (ch == Ctrl('v')) {
+ if (ch == CTRL('v')) {
state = VLIT;
ch = '^';
}
@@ -3730,7 +3721,7 @@ vi_hook(int ch)
break;
case VXCH:
- if (ch == Ctrl('['))
+ if (ch == CTRL('['))
state = VNORMAL;
else {
curcmd[cmdlen++] = ch;
@@ -3739,7 +3730,7 @@ vi_hook(int ch)
break;
case VSEARCH:
- if (ch == '\r' || ch == '\n' /*|| ch == Ctrl('[')*/ ) {
+ if (ch == '\r' || ch == '\n' /*|| ch == CTRL('[')*/ ) {
restore_cbuf();
/* Repeat last search? */
if (srchlen == 0) {
@@ -3754,10 +3745,10 @@ vi_hook(int ch)
memcpy(srchpat, locpat, srchlen + 1);
}
state = VCMD;
- } else if (ch == edchars.erase || ch == Ctrl('h')) {
+ } else if (ch == edchars.erase || ch == CTRL('h')) {
if (srchlen != 0) {
srchlen--;
- es->linelen -= char_len((unsigned char)locpat[srchlen]);
+ es->linelen -= char_len(locpat[srchlen]);
es->cursor = es->linelen;
refresh(0);
return (0);
@@ -3772,10 +3763,10 @@ vi_hook(int ch)
refresh(0);
return (0);
} else if (ch == edchars.werase) {
- int i, n = srchlen;
+ unsigned int i, n;
struct edstate new_es, *save_es;
- new_es.cursor = n;
+ new_es.cursor = srchlen;
new_es.cbuf = locpat;
save_es = es;
@@ -3783,9 +3774,10 @@ vi_hook(int ch)
n = backword(1);
es = save_es;
- for (i = srchlen; --i >= n; )
- es->linelen -= char_len((unsigned char)locpat[i]);
- srchlen = n;
+ i = (unsigned)srchlen;
+ while (--i >= n)
+ es->linelen -= char_len(locpat[i]);
+ srchlen = (int)n;
es->cursor = es->linelen;
refresh(0);
return (0);
@@ -3794,12 +3786,12 @@ vi_hook(int ch)
vi_error();
else {
locpat[srchlen++] = ch;
- if (ch < ' ' || ch == 0x7f) {
+ if (ISCTRL(ch) && /* but not C1 */ ch < 0x80) {
if ((size_t)es->linelen + 2 >
(size_t)es->cbufsize)
vi_error();
es->cbuf[es->linelen++] = '^';
- es->cbuf[es->linelen++] = ch ^ '@';
+ es->cbuf[es->linelen++] = UNCTRL(ch);
} else {
if (es->linelen >= es->cbufsize)
vi_error();
@@ -3910,7 +3902,7 @@ nextstate(int ch)
return (VXCH);
else if (ch == '.')
return (VREDO);
- else if (ch == Ctrl('v'))
+ else if (ch == CTRL('v'))
return (VVERSION);
else if (is_cmd(ch))
return (VCMD);
@@ -3923,7 +3915,7 @@ vi_insert(int ch)
{
int tcursor;
- if (ch == edchars.erase || ch == Ctrl('h')) {
+ if (ch == edchars.erase || ch == CTRL('h')) {
if (insert == REPLACE) {
if (es->cursor == undo->cursor) {
vi_error();
@@ -3980,7 +3972,7 @@ vi_insert(int ch)
* buffer (if user inserts & deletes char, ibuf gets trashed and
* we don't want to use it)
*/
- if (first_insert && ch != Ctrl('['))
+ if (first_insert && ch != CTRL('['))
saved_inslen = 0;
switch (ch) {
case '\0':
@@ -3990,7 +3982,7 @@ vi_insert(int ch)
case '\n':
return (1);
- case Ctrl('['):
+ case CTRL('['):
expanded = NONE;
if (first_insert) {
first_insert = false;
@@ -4008,19 +4000,19 @@ vi_insert(int ch)
return (redo_insert(lastac - 1));
/* { Begin nonstandard vi commands */
- case Ctrl('x'):
+ case CTRL('x'):
expand_word(0);
break;
- case Ctrl('f'):
+ case CTRL('f'):
complete_word(0, 0);
break;
- case Ctrl('e'):
+ case CTRL('e'):
print_expansions(es, 0);
break;
- case Ctrl('i'):
+ case CTRL('i'):
if (Flag(FVITABCOMPLETE)) {
complete_word(0, 0);
break;
@@ -4075,8 +4067,8 @@ vi_cmd(int argcnt, const char *cmd)
}
switch (*cmd) {
- case Ctrl('l'):
- case Ctrl('r'):
+ case CTRL('l'):
+ case CTRL('r'):
redraw_line(true);
break;
@@ -4263,7 +4255,7 @@ vi_cmd(int argcnt, const char *cmd)
case 'j':
case '+':
- case Ctrl('n'):
+ case CTRL('n'):
if (grabhist(modified, hnum + argcnt) < 0)
return (-1);
else {
@@ -4274,7 +4266,7 @@ vi_cmd(int argcnt, const char *cmd)
case 'k':
case '-':
- case Ctrl('p'):
+ case CTRL('p'):
if (grabhist(modified, hnum - argcnt) < 0)
return (-1);
else {
@@ -4506,26 +4498,26 @@ vi_cmd(int argcnt, const char *cmd)
/* AT&T ksh */
case '=':
/* Nonstandard vi/ksh */
- case Ctrl('e'):
+ case CTRL('e'):
print_expansions(es, 1);
break;
/* Nonstandard vi/ksh */
- case Ctrl('i'):
+ case CTRL('i'):
if (!Flag(FVITABCOMPLETE))
return (-1);
complete_word(1, argcnt);
break;
/* some annoying AT&T kshs */
- case Ctrl('['):
+ case CTRL('['):
if (!Flag(FVIESCCOMPLETE))
return (-1);
/* AT&T ksh */
case '\\':
/* Nonstandard vi/ksh */
- case Ctrl('f'):
+ case CTRL('f'):
complete_word(1, argcnt);
break;
@@ -4533,7 +4525,7 @@ vi_cmd(int argcnt, const char *cmd)
/* AT&T ksh */
case '*':
/* Nonstandard vi/ksh */
- case Ctrl('x'):
+ case CTRL('x'):
expand_word(1);
break;
@@ -4612,7 +4604,7 @@ domove(int argcnt, const char *cmd, int sub)
break;
case 'h':
- case Ctrl('h'):
+ case CTRL('h'):
if (!sub && es->cursor == 0)
return (-1);
ncursor = es->cursor - argcnt;
@@ -5028,7 +5020,7 @@ grabsearch(int save, int start, int fwd, const char *pat)
{
char *hptr;
int hist;
- int anchored;
+ bool anchored;
if ((start == 0 && fwd == 0) || (start >= hlast - 1 && fwd == 1))
return (-1);
@@ -5036,7 +5028,7 @@ grabsearch(int save, int start, int fwd, const char *pat)
start++;
else
start--;
- anchored = *pat == '^' ? (++pat, 1) : 0;
+ anchored = *pat == '^' ? (++pat, true) : false;
if ((hist = findhist(start, fwd, pat, anchored)) < 0) {
/* (start != 0 && fwd && match(holdbufp, pat) >= 0) */
if (start != 0 && fwd && strcmp(holdbufp, pat) >= 0) {
@@ -5125,7 +5117,7 @@ rewindow(void)
}
static int
-newcol(int ch, int col)
+newcol(unsigned char ch, int col)
{
if (ch == '\t')
return ((col | 7) + 1);
@@ -5153,10 +5145,10 @@ display(char *wb1, char *wb2, int leftside)
*twb1++ = ' ';
} while (++col < winwidth && (col & 7) != 0);
else if (col < winwidth) {
- if (ch < ' ' || ch == 0x7f) {
+ if (ISCTRL(ch) && /* but not C1 */ ch < 0x80) {
*twb1++ = '^';
if (++col < winwidth) {
- *twb1++ = ch ^ '@';
+ *twb1++ = UNCTRL(ch);
col++;
}
} else {
@@ -5433,9 +5425,9 @@ print_expansions(struct edstate *est, int cmd MKSH_A_UNUSED)
static void
x_vi_zotc(int c)
{
- if (c < ' ' || c == 0x7f) {
+ if (ISCTRL(c)) {
x_putc('^');
- c ^= '@';
+ c = UNCTRL(c);
}
x_putc(c);
}
diff --git a/src/eval.c b/src/eval.c
index b6ff1dc..49a4c33 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: eval.c,v 1.39 2013/07/01 17:25:27 jca Exp $ */
+/* $OpenBSD: eval.c,v 1.40 2013/09/14 20:09:30 millert Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* 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.142 2013/07/24 18:03:57 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.153 2014/10/07 15:22:16 tg Exp $");
/*
* string expansion
@@ -62,6 +62,7 @@ typedef struct {
#define IFS_WORD 0 /* word has chars (or quotes) */
#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 */
static int varsub(Expand *, const char *, const char *, int *, int *);
static int comsub(Expand *, const char *, int);
@@ -74,7 +75,7 @@ static const char *maybe_expand_tilde(const char *, XString *, char **, int);
static char *homedir(char *);
#endif
static void alt_expand(XPtrV *, char *, char *, char *, int);
-static int utflen(const char *);
+static int utflen(const char *) MKSH_A_PURE;
static void utfincptr(const char *, mksh_ari_t *);
/* UTFMODE functions */
@@ -244,8 +245,8 @@ expand(
internal_errorf("expand(NULL)");
/* for alias, readonly, set, typeset commands */
if ((f & DOVACHECK) && is_wdvarassign(ccp)) {
- f &= ~(DOVACHECK|DOBLANK|DOGLOB|DOTILDE);
- f |= DOASNTILDE;
+ f &= ~(DOVACHECK | DOBLANK | DOGLOB | DOTILDE);
+ f |= DOASNTILDE | DOASNFIELD;
}
if (Flag(FNOGLOB))
f &= ~DOGLOB;
@@ -261,7 +262,7 @@ expand(
fdo = 0;
saw_eq = false;
/* must be 1/0 */
- tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0;
+ tilde_ok = (f & (DOTILDE | DOASNTILDE)) ? 1 : 0;
doblank = 0;
make_magic = false;
word = (f&DOBLANK) ? IFS_WS : IFS_WORD;
@@ -324,9 +325,9 @@ expand(
}
continue;
case EXPRSUB:
- word = IFS_WORD;
tilde_ok = 0;
if (f & DONTRUNCOMMAND) {
+ word = IFS_WORD;
*dp++ = '$'; *dp++ = '('; *dp++ = '(';
while (*sp != '\0') {
Xcheck(ds, dp);
@@ -343,11 +344,10 @@ expand(
v_evaluate(&v, substitute(sp, 0),
KSH_UNWIND_ERROR, true);
sp = strnul(sp) + 1;
- cp = str_val(&v);
- while (*cp) {
- Xcheck(ds, dp);
- *dp++ = *cp++;
- }
+ x.str = str_val(&v);
+ type = XSUB;
+ if (f & DOBLANK)
+ doblank++;
}
continue;
case OSUBST: {
@@ -412,27 +412,10 @@ expand(
if (stype)
sp += slen;
switch (stype & 0x17F) {
- case 0x100 | '#': {
- char *beg, *end;
- mksh_ari_t seed;
- register uint32_t h;
-
- beg = wdcopy(sp, ATEMP);
- end = beg + (wdscan(sp, CSUBST) - sp);
- end[-2] = EOS;
- end = wdstrip(beg, 0);
- afree(beg, ATEMP);
- evaluate(substitute(end, 0),
- &seed, KSH_UNWIND_ERROR, true);
- /* hash with seed, for now */
- h = seed;
- NZATUpdateString(h,
- str_val(st->var));
- NZAATFinish(h);
+ case 0x100 | '#':
x.str = shf_smprintf("%08X",
- (unsigned int)h);
+ (unsigned int)hash(str_val(st->var)));
break;
- }
case 0x100 | 'Q': {
struct shf shf;
@@ -440,7 +423,7 @@ expand(
print_value_quoted(&shf, str_val(st->var));
x.str = shf_sclose(&shf);
break;
- }
+ }
case '0': {
char *beg, *mid, *end, *stg;
mksh_ari_t from = 0, num = -1, flen, finc = 0;
@@ -490,7 +473,7 @@ expand(
utfincptr(beg, &num);
strndupx(x.str, beg, num, ATEMP);
goto do_CSUBST;
- }
+ }
case '/': {
char *s, *p, *d, *sbeg, *end;
char *pat, *rrep;
@@ -634,7 +617,7 @@ expand(
if (rrep != null)
afree(rrep, ATEMP);
goto do_CSUBST;
- }
+ }
case '#':
case '%':
/* ! DOBLANK,DOBRACE,DOTILDE */
@@ -667,7 +650,7 @@ expand(
* a arithmetic operator.
*/
if (!(x.var->flag & INTEGER))
- f |= DOASNTILDE|DOTILDE;
+ f |= DOASNTILDE | DOTILDE;
f |= DOTEMP;
/*
* These will be done after the
@@ -681,6 +664,7 @@ expand(
f |= DOTEMP;
/* FALLTHROUGH */
default:
+ word = quote ? IFS_WORD : IFS_IWS;
/* Enable tilde expansion */
tilde_ok = 1;
f |= DOTILDE;
@@ -689,7 +673,7 @@ expand(
/* skip word */
sp += wdscan(sp, CSUBST) - sp;
continue;
- }
+ }
case CSUBST:
/* only get here if expanding word */
do_CSUBST:
@@ -700,7 +684,7 @@ expand(
*dp = '\0';
quote = st->quotep;
f = st->f;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank--;
switch (st->stype & 0x17F) {
case '#':
@@ -719,11 +703,12 @@ expand(
*/
x.str = trimsub(str_val(st->var),
dp, st->stype);
- if (x.str[0] != '\0' || st->quotep)
+ if (x.str[0] != '\0') {
+ word = IFS_WS;
type = XSUB;
- else
- type = XNULLSUB;
- if (f&DOBLANK)
+ } else
+ type = quote ? XSUB : XNULLSUB;
+ if (f & DOBLANK)
doblank++;
st = st->prev;
continue;
@@ -755,9 +740,10 @@ expand(
dp, len), KSH_UNWIND_ERROR);
x.str = str_val(st->var);
type = XSUB;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank++;
st = st->prev;
+ word = quote || (!*x.str && (f & DOASNFIELD)) ? IFS_WORD : IFS_WS;
continue;
case '?': {
char *s = Xrestpos(ds, dp, st->base);
@@ -766,14 +752,15 @@ expand(
dp == s ?
"parameter null or not set" :
(debunk(s, s, strlen(s) + 1), s));
- }
+ }
case '0':
case '/':
case 0x100 | '#':
case 0x100 | 'Q':
dp = Xrestpos(ds, dp, st->base);
type = XSUB;
- if (f&DOBLANK)
+ word = quote || (!*x.str && (f & DOASNFIELD)) ? IFS_WORD : IFS_WS;
+ if (f & DOBLANK)
doblank++;
st = st->prev;
continue;
@@ -810,13 +797,8 @@ expand(
* other stuff inside the quotes).
*/
type = XBASE;
- if (f&DOBLANK) {
+ if (f & DOBLANK) {
doblank--;
- /*
- * not really correct: x=; "$x$@" should
- * generate a null argument and
- * set A; "${@:+}" shouldn't.
- */
if (dp == Xstring(ds, dp))
word = IFS_WS;
}
@@ -826,7 +808,7 @@ expand(
case XSUBMID:
if ((c = *x.str++) == 0) {
type = XBASE;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank--;
continue;
}
@@ -840,21 +822,33 @@ expand(
if ((c = *x.str++) == '\0') {
/*
* force null words to be created so
- * set -- '' 2 ''; foo "$@" will do
+ * set -- "" 2 ""; echo "$@" will do
* the right thing
*/
if (quote && x.split)
word = IFS_WORD;
if ((x.str = *x.u.strv++) == NULL) {
type = XBASE;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank--;
continue;
}
c = ifs0;
+ if ((f & DOASNFIELD)) {
+ /* assignment, do not field-split */
+ if (x.split) {
+ c = ' ';
+ break;
+ }
+ if (c == 0) {
+ continue;
+ }
+ }
if (c == 0) {
if (quote && !x.split)
continue;
+ if (!quote && word == IFS_WS)
+ continue;
/* this is so we don't terminate */
c = ' ';
/* now force-emit a word */
@@ -896,7 +890,7 @@ expand(
if (x.split)
subst_exstat = waitlast();
type = XBASE;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank--;
continue;
}
@@ -912,14 +906,14 @@ expand(
* word | ws nws 0
* -----------------------------------
* IFS_WORD w/WS w/NWS w
- * IFS_WS -/WS w/NWS -
- * IFS_NWS -/NWS w/NWS w
+ * IFS_WS -/WS -/NWS -
+ * IFS_NWS -/NWS w/NWS -
+ * IFS_IWS -/WS w/NWS -
* (w means generate a word)
- * Note that IFS_NWS/0 generates a word (AT&T ksh
- * doesn't do this, but POSIX does).
*/
- if (word == IFS_WORD ||
- (!ctype(c, C_IFSWS) && c && word == IFS_NWS)) {
+ if ((word == IFS_WORD) || (c &&
+ (word == IFS_IWS || word == IFS_NWS) &&
+ !ctype(c, C_IFSWS))) {
emit_word:
*dp++ = '\0';
cp = Xclose(ds, dp);
@@ -937,7 +931,8 @@ expand(
strlen(cp) + 1));
fdo = 0;
saw_eq = false;
- tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0;
+ /* must be 1/0 */
+ tilde_ok = (f & (DOTILDE | DOASNTILDE)) ? 1 : 0;
if (c == 0)
return;
Xinit(ds, dp, 128, ATEMP);
@@ -1021,7 +1016,7 @@ expand(
* through the sequence ${A=a=}~
*/
if (type == XBASE &&
- (f & (DOTILDE|DOASNTILDE)) &&
+ (f & (DOTILDE | DOASNTILDE)) &&
(tilde_ok & 2)) {
const char *tcp;
char *tdp = dp;
@@ -1269,17 +1264,12 @@ varsub(Expand *xp, const char *sp, const char *word,
if (*sp == '!' && sp[1]) {
++sp;
xp->var = global(sp);
- if (vstrchr(sp, '[')) {
- if (xp->var->flag & ISSET)
- xp->str = shf_smprintf("%lu",
- arrayindex(xp->var));
- else
- xp->str = null;
- } else if (xp->var->flag & ISSET)
- xp->str = xp->var->name;
+ if (vstrchr(sp, '['))
+ xp->str = shf_smprintf("%s[%lu]",
+ xp->var->name,
+ arrayindex(xp->var));
else
- /* ksh93 compat */
- xp->str = "0";
+ xp->str = xp->var->name;
} else {
xp->var = global(sp);
xp->str = str_val(xp->var);
diff --git a/src/exec.c b/src/exec.c
index 50ec9ca..b60511d 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
+ * 2011, 2012, 2013, 2014
* 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.125 2013/07/21 20:44:44 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.133 2014/10/03 17:32:11 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
@@ -462,7 +462,7 @@ execute(struct op * volatile t,
if (vp_pipest->flag & INT_L) {
unset(vp_pipest, 1);
vp_pipest->flag = DEFINED | ISSET | INTEGER | RDONLY |
- ARRAY | INT_U;
+ ARRAY | INT_U | INT_L;
vp_pipest->val.i = rv;
}
@@ -604,19 +604,15 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
/* go on, use the builtin */
break;
#endif
-#if !defined(MKSH_SMALL)
} else if (tp->val.f == c_trap) {
t->u.evalflags &= ~DOTCOMEXEC;
break;
-#endif
} else
break;
tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC));
}
-#if !defined(MKSH_SMALL)
if (t->u.evalflags & DOTCOMEXEC)
flags |= XEXEC;
-#endif
l_expand = e->loc;
if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN))))
type_flags = 0;
@@ -639,7 +635,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);
+ cp = evalstr(t->vars[i], DOASNTILDE | DOASNFIELD);
e->loc = l_assign;
if (Flag(FXTRACE)) {
const char *ccp;
@@ -656,7 +652,7 @@ 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);
+ typeset(cp, LOCAL | LOCAL_COPY | EXPORT, 0, 0, 0);
}
if (Flag(FXTRACE)) {
@@ -816,7 +812,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
/* set $_ to programme's full path */
/* setstr() can't fail here */
- setstr(typeset("_", LOCAL|EXPORT, 0, INTEGER, 0),
+ setstr(typeset("_", LOCAL | EXPORT, 0, INTEGER, 0),
tp->val.s, KSH_RETURN_ERROR);
if (flags&XEXEC) {
@@ -869,7 +865,7 @@ scriptexec(struct op *tp, const char **ap)
*tp->args-- = tp->str;
#ifndef MKSH_SMALL
- if ((fd = open(tp->str, O_RDONLY)) >= 0) {
+ 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 */
@@ -884,14 +880,14 @@ scriptexec(struct op *tp, const char **ap)
fd = (char *)cp - buf; /* either 0 or (if BOM) 3 */
/* scan for newline (or CR) or NUL _before_ end of buffer */
- while ((char *)cp < (buf + sizeof(buf)))
+ while ((size_t)((char *)cp - buf) < sizeof(buf))
if (*cp == '\0' || *cp == '\n' || *cp == '\r') {
*cp = '\0';
break;
} else
++cp;
/* if the shebang line is longer than MAXINTERP, bail out */
- if ((char *)cp >= (buf + sizeof(buf)))
+ if ((size_t)((char *)cp - buf) >= sizeof(buf))
goto noshebang;
/* restore begin of shebang position (buf+0 or buf+3) */
@@ -923,6 +919,10 @@ scriptexec(struct op *tp, const char **ap)
*tp->args-- = (char *)cp;
}
noshebang:
+ if (buf[0] == 0x7F && buf[1] == 'E' && 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) ||
@@ -931,7 +931,6 @@ scriptexec(struct op *tp, const char **ap)
(fd == /* ECOFF_I386 */ 0x4C01) ||
(fd == /* ECOFF_M68K */ 0x0150 || fd == 0x5001) ||
(fd == /* ECOFF_SH */ 0x0500 || fd == 0x0005) ||
- (fd == 0x7F45 && buf[2] == 'L' && buf[3] == 'F') ||
(fd == /* "MZ" */ 0x4D5A) ||
(fd == /* gzip */ 0x1F8B))
errorf("%s: not executable: magic %04X", tp->str, fd);
@@ -1374,7 +1373,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
warningf(true, "%s: %s", cp, "restricted");
return (-1);
}
- u = open(cp, flags, 0666);
+ u = open(cp, flags | O_BINARY, 0666);
}
if (u < 0) {
/* herein() may already have printed message */
@@ -1507,7 +1506,7 @@ herein(struct ioword *iop, char **resbuf)
* so temp doesn't get removed too soon).
*/
h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
- if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY, 0)) < 0) {
+ if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY | O_BINARY, 0)) < 0) {
i = errno;
warningf(true, "can't %s temporary file %s: %s",
!shf ? "create" : "open", h->tffn, cstrerror(i));
@@ -1669,7 +1668,7 @@ static Test_op
dbteste_isa(Test_env *te, Test_meta meta)
{
Test_op ret = TO_NONOP;
- int uqword;
+ bool uqword;
const char *p;
if (!*te->pos.wp)
diff --git a/src/expr.c b/src/expr.c
index e91c0da..057666e 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: expr.c,v 1.22 2013/03/28 08:39:28 nicm Exp $ */
+/* $OpenBSD: expr.c,v 1.23 2013/12/17 16:37:06 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* 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/expr.c,v 1.72 2013/07/21 18:38:56 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.76 2014/06/24 19:53:19 tg Exp $");
/* the order of these enums is constrained by the order of opinfo[] */
enum token {
@@ -916,8 +916,7 @@ ksh_access(const char *fn, int mode)
return (rv);
}
-#ifndef MKSH_mirbsd_wcwidth
-/* From: X11/xc/programs/xterm/wcwidth.c,v 1.6 2013/05/31 23:27:09 tg Exp $ */
+/* From: X11/xc/programs/xterm/wcwidth.c,v 1.8 2014/06/24 19:53:53 tg Exp $ */
struct mb_ucsrange {
unsigned short beg;
@@ -925,11 +924,11 @@ struct mb_ucsrange {
};
static int mb_ucsbsearch(const struct mb_ucsrange arr[], size_t elems,
- unsigned int val);
+ unsigned int val) MKSH_A_PURE;
/*
- * Generated by MirOS: contrib/code/Snippets/eawparse,v 1.1 2013/05/31 23:27:16 tg Exp $
- * from Unicode 6.2.0
+ * Generated by MirOS: contrib/code/Snippets/eawparse,v 1.2 2013/11/30 13:45:17 tg Exp $
+ * from the Unicode Character Database, Version 7.0.0
*/
static const struct mb_ucsrange mb_ucs_combining[] = {
@@ -940,8 +939,9 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0x05C1, 0x05C2 },
{ 0x05C4, 0x05C5 },
{ 0x05C7, 0x05C7 },
- { 0x0600, 0x0604 },
+ { 0x0600, 0x0605 },
{ 0x0610, 0x061A },
+ { 0x061C, 0x061C },
{ 0x064B, 0x065F },
{ 0x0670, 0x0670 },
{ 0x06D6, 0x06DD },
@@ -958,8 +958,7 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0x0825, 0x0827 },
{ 0x0829, 0x082D },
{ 0x0859, 0x085B },
- { 0x08E4, 0x08FE },
- { 0x0900, 0x0902 },
+ { 0x08E4, 0x0902 },
{ 0x093A, 0x093A },
{ 0x093C, 0x093C },
{ 0x0941, 0x0948 },
@@ -995,16 +994,19 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0x0B82, 0x0B82 },
{ 0x0BC0, 0x0BC0 },
{ 0x0BCD, 0x0BCD },
+ { 0x0C00, 0x0C00 },
{ 0x0C3E, 0x0C40 },
{ 0x0C46, 0x0C48 },
{ 0x0C4A, 0x0C4D },
{ 0x0C55, 0x0C56 },
{ 0x0C62, 0x0C63 },
+ { 0x0C81, 0x0C81 },
{ 0x0CBC, 0x0CBC },
{ 0x0CBF, 0x0CBF },
{ 0x0CC6, 0x0CC6 },
{ 0x0CCC, 0x0CCD },
{ 0x0CE2, 0x0CE3 },
+ { 0x0D01, 0x0D01 },
{ 0x0D41, 0x0D44 },
{ 0x0D4D, 0x0D4D },
{ 0x0D62, 0x0D63 },
@@ -1050,13 +1052,14 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0x17C6, 0x17C6 },
{ 0x17C9, 0x17D3 },
{ 0x17DD, 0x17DD },
- { 0x180B, 0x180D },
+ { 0x180B, 0x180E },
{ 0x18A9, 0x18A9 },
{ 0x1920, 0x1922 },
{ 0x1927, 0x1928 },
{ 0x1932, 0x1932 },
{ 0x1939, 0x193B },
{ 0x1A17, 0x1A18 },
+ { 0x1A1B, 0x1A1B },
{ 0x1A56, 0x1A56 },
{ 0x1A58, 0x1A5E },
{ 0x1A60, 0x1A60 },
@@ -1064,6 +1067,7 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0x1A65, 0x1A6C },
{ 0x1A73, 0x1A7C },
{ 0x1A7F, 0x1A7F },
+ { 0x1AB0, 0x1ABE },
{ 0x1B00, 0x1B03 },
{ 0x1B34, 0x1B34 },
{ 0x1B36, 0x1B3A },
@@ -1073,7 +1077,7 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0x1B80, 0x1B81 },
{ 0x1BA2, 0x1BA5 },
{ 0x1BA8, 0x1BA9 },
- { 0x1BAB, 0x1BAB },
+ { 0x1BAB, 0x1BAD },
{ 0x1BE6, 0x1BE6 },
{ 0x1BE8, 0x1BE9 },
{ 0x1BED, 0x1BED },
@@ -1085,12 +1089,13 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0x1CE2, 0x1CE8 },
{ 0x1CED, 0x1CED },
{ 0x1CF4, 0x1CF4 },
- { 0x1DC0, 0x1DE6 },
+ { 0x1CF8, 0x1CF9 },
+ { 0x1DC0, 0x1DF5 },
{ 0x1DFC, 0x1DFF },
{ 0x200B, 0x200F },
{ 0x202A, 0x202E },
{ 0x2060, 0x2064 },
- { 0x206A, 0x206F },
+ { 0x2066, 0x206F },
{ 0x20D0, 0x20F0 },
{ 0x2CEF, 0x2CF1 },
{ 0x2D7F, 0x2D7F },
@@ -1113,11 +1118,13 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0xA9B3, 0xA9B3 },
{ 0xA9B6, 0xA9B9 },
{ 0xA9BC, 0xA9BC },
+ { 0xA9E5, 0xA9E5 },
{ 0xAA29, 0xAA2E },
{ 0xAA31, 0xAA32 },
{ 0xAA35, 0xAA36 },
{ 0xAA43, 0xAA43 },
{ 0xAA4C, 0xAA4C },
+ { 0xAA7C, 0xAA7C },
{ 0xAAB0, 0xAAB0 },
{ 0xAAB2, 0xAAB4 },
{ 0xAAB7, 0xAAB8 },
@@ -1130,7 +1137,7 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0xABED, 0xABED },
{ 0xFB1E, 0xFB1E },
{ 0xFE00, 0xFE0F },
- { 0xFE20, 0xFE26 },
+ { 0xFE20, 0xFE2D },
{ 0xFEFF, 0xFEFF },
{ 0xFFF9, 0xFFFB }
};
@@ -1188,4 +1195,3 @@ utf_wcwidth(unsigned int wc)
return (2);
return (1);
}
-#endif
diff --git a/src/funcs.c b/src/funcs.c
index 53ab789..bb7971e 100644
--- a/src/funcs.c
+++ b/src/funcs.c
@@ -1,11 +1,11 @@
-/* $OpenBSD: c_ksh.c,v 1.33 2009/02/07 14:03:24 kili Exp $ */
-/* $OpenBSD: c_sh.c,v 1.43 2013/04/19 17:39:45 deraadt Exp $ */
+/* $OpenBSD: c_ksh.c,v 1.34 2013/12/17 16:37:05 deraadt Exp $ */
+/* $OpenBSD: c_sh.c,v 1.45 2014/08/27 08:26:04 jmc Exp $ */
/* $OpenBSD: c_test.c,v 1.18 2009/03/01 20:11:06 otto Exp $ */
-/* $OpenBSD: c_ulimit.c,v 1.17 2008/03/21 12:51:19 millert Exp $ */
+/* $OpenBSD: c_ulimit.c,v 1.19 2013/11/28 10:33:37 sobrado Exp $ */
/*-
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- * 2010, 2011, 2012, 2013
+ * 2010, 2011, 2012, 2013, 2014
* 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.244 2013/06/03 22:28:32 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.258 2014/09/03 19:55:51 tg Exp $");
#if HAVE_KILLPG
/*
@@ -60,6 +60,10 @@ __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.244 2013/06/03 22:28:32 tg Exp $");
#define c_ulimit c_true
#endif
+#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
+static int c_suspend(const char **);
+#endif
+
/* getn() that prints error */
static int
bi_getn(const char *as, int *ai)
@@ -123,6 +127,9 @@ const struct builtin mkshbuiltins[] = {
{"*=return", c_exitreturn},
{Tsgset, c_set},
{"*=shift", c_shift},
+#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
+ {"suspend", c_suspend},
+#endif
{"test", c_test},
{"*=times", c_times},
{"*=trap", c_trap},
@@ -641,6 +648,7 @@ c_typeset(const char **wp)
const char *opts;
const char *fieldstr = NULL, *basestr = NULL;
bool localv = false, func = false, pflag = false, istset = true;
+ enum namerefflag new_refflag = SRF_NOP;
switch (**wp) {
@@ -721,7 +729,7 @@ c_typeset(const char **wp)
flag = LCASEV;
break;
case 'n':
- set_refflag = (builtin_opt.info & GI_PLUS) ?
+ new_refflag = (builtin_opt.info & GI_PLUS) ?
SRF_DISABLE : SRF_ENABLE;
break;
/* export, readonly: POSIX -p flag */
@@ -745,8 +753,6 @@ c_typeset(const char **wp)
flag = EXPORT;
break;
case '?':
- errout:
- set_refflag = SRF_NOP;
return (1);
}
if (builtin_opt.info & GI_PLUS) {
@@ -761,10 +767,10 @@ c_typeset(const char **wp)
}
if (fieldstr && !bi_getn(fieldstr, &field))
- goto errout;
+ return (1);
if (basestr && (!bi_getn(basestr, &base) || base < 1 || base > 36)) {
bi_errorf("%s: %s", "bad integer base", basestr);
- goto errout;
+ return (1);
}
if (!(builtin_opt.info & GI_MINUSMINUS) && wp[builtin_opt.optind] &&
@@ -776,9 +782,9 @@ c_typeset(const char **wp)
}
if (func && (((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT)) ||
- set_refflag != SRF_NOP)) {
+ new_refflag != SRF_NOP)) {
bi_errorf("only -t, -u and -x options may be used with -f");
- goto errout;
+ return (1);
}
if (wp[builtin_opt.optind]) {
/*
@@ -802,10 +808,18 @@ c_typeset(const char **wp)
* are also set in this command
*/
if ((fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL | LCASEV |
- INTEGER | INT_U | INT_L)) || set_refflag != SRF_NOP)
+ INTEGER | INT_U | INT_L)) || new_refflag != SRF_NOP)
fclr |= ~fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL |
LCASEV | INTEGER | INT_U | INT_L);
}
+ if (new_refflag != SRF_NOP) {
+ fclr &= ~(ARRAY | ASSOC);
+ fset &= ~(ARRAY | ASSOC);
+ fclr |= EXPORT;
+ fset |= ASSOC;
+ if (new_refflag == SRF_DISABLE)
+ fclr |= ASSOC;
+ }
/* set variables and attributes */
if (wp[builtin_opt.optind] &&
@@ -836,14 +850,12 @@ c_typeset(const char **wp)
}
} else if (!typeset(wp[i], fset, fclr, field, base)) {
bi_errorf("%s: %s", wp[i], "is not an identifier");
- goto errout;
+ return (1);
}
}
- set_refflag = SRF_NOP;
return (rv);
}
- set_refflag = SRF_NOP;
/* list variables and attributes */
/* no difference at this point.. */
@@ -1345,8 +1357,10 @@ c_kill(const char **wp)
for (; wp[i]; i++) {
if (!bi_getn(wp[i], &n))
return (1);
+#if (NSIG < 128)
if (n > 128 && n < 128 + NSIG)
n -= 128;
+#endif
if (n > 0 && n < NSIG)
shprintf("%s\n", sigtraps[n].name);
else
@@ -3333,16 +3347,6 @@ ptest_error(Test_env *te, int ofs, const char *msg)
#define SOFT 0x1
#define HARD 0x2
-struct limits {
- const char *name;
- int resource; /* resource to get/set */
- unsigned int factor; /* multiply by to get rlim_{cur,max} values */
- char option;
-};
-
-static void print_ulimit(const struct limits *, int);
-static int set_ulimit(const struct limits *, const char *, int);
-
/* Magic to divine the 'm' and 'v' limits */
#ifdef RLIMIT_AS
@@ -3385,165 +3389,38 @@ static int set_ulimit(const struct limits *, const char *, int);
#undef ULIMIT_M_IS_VMEM
#endif
+#if defined(ULIMIT_M_IS_RSS) && defined(ULIMIT_M_IS_VMEM)
+# error nonsensical m ulimit
+#endif
+
+#if defined(ULIMIT_V_IS_VMEM) && defined(ULIMIT_V_IS_AS)
+# error nonsensical v ulimit
+#endif
+
+#define RLIMITS_DEFNS
+#include "rlimits.gen"
+
+static void print_ulimit(const struct limits *, int);
+static int set_ulimit(const struct limits *, const char *, int);
+
+static const struct limits * const rlimits[] = {
+#define RLIMITS_ITEMS
+#include "rlimits.gen"
+};
+
+static const char rlimits_opts[] =
+#define RLIMITS_OPTCS
+#include "rlimits.gen"
+ ;
int
c_ulimit(const char **wp)
{
- static const struct limits limits[] = {
- /* do not use options -H, -S or -a or change the order */
-#ifdef RLIMIT_CPU
- { "time(cpu-seconds)", RLIMIT_CPU, 1, 't' },
-#endif
-#ifdef RLIMIT_FSIZE
- { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
-#endif
-#ifdef RLIMIT_CORE
- { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
-#endif
-#ifdef RLIMIT_DATA
- { "data(KiB)", RLIMIT_DATA, 1024, 'd' },
-#endif
-#ifdef RLIMIT_STACK
- { "stack(KiB)", RLIMIT_STACK, 1024, 's' },
-#endif
-#ifdef RLIMIT_MEMLOCK
- { "lockedmem(KiB)", RLIMIT_MEMLOCK, 1024, 'l' },
-#endif
-#ifdef RLIMIT_NOFILE
- { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
-#endif
-#ifdef RLIMIT_NPROC
- { "processes", RLIMIT_NPROC, 1, 'p' },
-#endif
-#ifdef RLIMIT_SWAP
- { "swap(KiB)", RLIMIT_SWAP, 1024, 'w' },
-#endif
-#ifdef RLIMIT_LOCKS
- { "flocks", RLIMIT_LOCKS, -1, 'L' },
-#endif
-#ifdef RLIMIT_TIME
- { "humantime(seconds)", RLIMIT_TIME, 1, 'T' },
-#endif
-#ifdef RLIMIT_NOVMON
- { "vnodemonitors", RLIMIT_NOVMON, 1, 'V' },
-#endif
-#ifdef RLIMIT_SIGPENDING
- { "sigpending", RLIMIT_SIGPENDING, 1, 'i' },
-#endif
-#ifdef RLIMIT_MSGQUEUE
- { "msgqueue(bytes)", RLIMIT_MSGQUEUE, 1, 'q' },
-#endif
-#ifdef RLIMIT_AIO_MEM
- { "AIOlockedmem(KiB)", RLIMIT_AIO_MEM, 1024, 'M' },
-#endif
-#ifdef RLIMIT_AIO_OPS
- { "AIOoperations", RLIMIT_AIO_OPS, 1, 'O' },
-#endif
-#ifdef RLIMIT_TCACHE
- { "cachedthreads", RLIMIT_TCACHE, 1, 'C' },
-#endif
-#ifdef RLIMIT_SBSIZE
- { "sockbufsiz(KiB)", RLIMIT_SBSIZE, 1024, 'B' },
-#endif
-#ifdef RLIMIT_PTHREAD
- { "threadsperprocess", RLIMIT_PTHREAD, 1, 'P' },
-#endif
-#ifdef RLIMIT_NICE
- { "maxnice", RLIMIT_NICE, 1, 'e' },
-#endif
-#ifdef RLIMIT_RTPRIO
- { "maxrtprio", RLIMIT_RTPRIO, 1, 'r' },
-#endif
-#if defined(ULIMIT_M_IS_RSS)
- { "resident-set(KiB)", RLIMIT_RSS, 1024, 'm' },
-#elif defined(ULIMIT_M_IS_VMEM)
- { "memory(KiB)", RLIMIT_VMEM, 1024, 'm' },
-#endif
-#if defined(ULIMIT_V_IS_VMEM)
- { "virtual-memory(KiB)", RLIMIT_VMEM, 1024, 'v' },
-#elif defined(ULIMIT_V_IS_AS)
- { "address-space(KiB)", RLIMIT_AS, 1024, 'v' },
-#endif
- { NULL, 0, 0, 0 }
- };
- static const char opts[] = "a"
-#ifdef RLIMIT_SBSIZE
- "B"
-#endif
-#ifdef RLIMIT_TCACHE
- "C"
-#endif
-#ifdef RLIMIT_CORE
- "c"
-#endif
-#ifdef RLIMIT_DATA
- "d"
-#endif
-#ifdef RLIMIT_NICE
- "e"
-#endif
-#ifdef RLIMIT_FSIZE
- "f"
-#endif
- "H"
-#ifdef RLIMIT_SIGPENDING
- "i"
-#endif
-#ifdef RLIMIT_LOCKS
- "L"
-#endif
-#ifdef RLIMIT_MEMLOCK
- "l"
-#endif
-#ifdef RLIMIT_AIO_MEM
- "M"
-#endif
-#if defined(ULIMIT_M_IS_RSS) || defined(ULIMIT_M_IS_VMEM)
- "m"
-#endif
-#ifdef RLIMIT_NOFILE
- "n"
-#endif
-#ifdef RLIMIT_AIO_OPS
- "O"
-#endif
-#ifdef RLIMIT_PTHREAD
- "P"
-#endif
-#ifdef RLIMIT_NPROC
- "p"
-#endif
-#ifdef RLIMIT_MSGQUEUE
- "q"
-#endif
-#ifdef RLIMIT_RTPRIO
- "r"
-#endif
- "S"
-#ifdef RLIMIT_STACK
- "s"
-#endif
-#ifdef RLIMIT_TIME
- "T"
-#endif
-#ifdef RLIMIT_CPU
- "t"
-#endif
-#ifdef RLIMIT_NOVMON
- "V"
-#endif
-#if defined(ULIMIT_V_IS_VMEM) || defined(ULIMIT_V_IS_AS)
- "v"
-#endif
-#ifdef RLIMIT_SWAP
- "w"
-#endif
- ;
+ size_t i = 0;
int how = SOFT | HARD, optc, what = 'f';
bool all = false;
- const struct limits *l;
- while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
+ while ((optc = ksh_getopt(wp, &builtin_opt, rlimits_opts)) != -1)
switch (optc) {
case 'H':
how = HARD;
@@ -3555,31 +3432,32 @@ c_ulimit(const char **wp)
all = true;
break;
case '?':
- bi_errorf("usage: ulimit [-%s] [value]", opts);
+ bi_errorf("usage: ulimit [-%s] [value]", rlimits_opts);
return (1);
default:
what = optc;
}
- for (l = limits; l->name && l->option != what; l++)
- ;
- if (!l->name) {
- internal_warningf("ulimit: %c", what);
- return (1);
+ while (i < NELEM(rlimits)) {
+ if (rlimits[i]->optchar == what)
+ goto found;
+ ++i;
}
-
+ internal_warningf("ulimit: %c", what);
+ return (1);
+ found:
if (wp[builtin_opt.optind]) {
if (all || wp[builtin_opt.optind + 1]) {
bi_errorf("too many arguments");
return (1);
}
- return (set_ulimit(l, wp[builtin_opt.optind], how));
+ return (set_ulimit(rlimits[i], wp[builtin_opt.optind], how));
}
if (!all)
- print_ulimit(l, how);
- else for (l = limits; l->name; l++) {
- shprintf("%-20s ", l->name);
- print_ulimit(l, how);
+ print_ulimit(rlimits[i], how);
+ else for (i = 0; i < NELEM(rlimits); ++i) {
+ shprintf("%-20s ", rlimits[i]->name);
+ print_ulimit(rlimits[i], how);
}
return (0);
}
@@ -3611,7 +3489,11 @@ set_ulimit(const struct limits *l, const char *v, int how)
}
if (getrlimit(l->resource, &limit) < 0) {
- /* some can't be read, e.g. Linux RLIMIT_LOCKS */
+#ifndef MKSH_SMALL
+ bi_errorf("limit %s could not be read, contact the mksh developers: %s",
+ l->name, cstrerror(errno));
+#endif
+ /* some can't be read */
limit.rlim_cur = RLIM_INFINITY;
limit.rlim_max = RLIM_INFINITY;
}
@@ -3735,7 +3617,7 @@ c_cat(const char **wp)
fn = *wp++;
if (fn[0] == '-' && fn[1] == '\0')
fd = STDIN_FILENO;
- else if ((fd = open(fn, O_RDONLY)) < 0) {
+ else if ((fd = open(fn, O_RDONLY | O_BINARY)) < 0) {
eno = errno;
bi_errorf("%s: %s", fn, cstrerror(eno));
rv = 1;
@@ -3844,3 +3726,24 @@ c_sleep(const char **wp)
return (rv);
}
#endif
+
+#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
+static int
+c_suspend(const char **wp)
+{
+ if (wp[1] != NULL) {
+ bi_errorf("too many arguments");
+ return (1);
+ }
+ if (Flag(FLOGIN)) {
+ /* Can't suspend an orphaned process group. */
+ if (getpgid(kshppid) == getpgid(0) ||
+ getsid(kshppid) != getsid(0)) {
+ bi_errorf("can't suspend a login shell");
+ return (1);
+ }
+ }
+ j_suspend();
+ return (0);
+}
+#endif
diff --git a/src/histrap.c b/src/histrap.c
index 3b28f23..d15cc8d 100644
--- a/src/histrap.c
+++ b/src/histrap.c
@@ -3,7 +3,7 @@
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012
+ * 2011, 2012, 2014
* 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.131 2012/12/28 02:28:35 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134 2014/06/09 13:25:53 tg Exp $");
Trap sigtraps[NSIG + 1];
static struct sigaction Sigact_ign;
@@ -442,7 +442,7 @@ hist_get(const char *str, bool approx, bool allow_cur)
hp = NULL;
}
} else {
- int anchored = *str == '?' ? (++str, 0) : 1;
+ bool anchored = *str == '?' ? (++str, false) : true;
/* the -1 is to avoid the current fc command */
if ((n = findhist(histptr - history - 1, 0, str, anchored)) < 0)
@@ -509,7 +509,7 @@ histnum(int n)
* direction.
*/
int
-findhist(int start, int fwd, const char *str, int anchored)
+findhist(int start, int fwd, const char *str, bool anchored)
{
char **hp;
int maxhist = histptr - history;
@@ -720,7 +720,8 @@ hist_init(Source *s)
retry:
/* we have a file and are interactive */
- if ((fd = open(hname, O_RDWR | O_CREAT | O_APPEND, 0600)) < 0)
+ if ((fd = open(hname, O_RDWR | O_CREAT | O_APPEND | O_BINARY,
+ 0600)) < 0)
return;
histfd = savefd(fd);
@@ -756,7 +757,7 @@ hist_init(Source *s)
/* create temporary file */
nhname = shf_smprintf("%s.%d", hname, (int)procpid);
if ((fd = open(nhname, O_RDWR | O_CREAT | O_TRUNC |
- O_EXCL, 0600)) < 0) {
+ O_EXCL | O_BINARY, 0600)) < 0) {
/* just don't truncate then, meh. */
goto hist_trunc_dont;
}
@@ -976,6 +977,7 @@ inittraps(void)
trap_exstat = -1;
/* Populate sigtraps based on sys_signame and sys_siglist. */
+ /*XXX this is idiotic, use a multi-key/value hashtable! */
for (i = 0; i <= NSIG; i++) {
sigtraps[i].signal = i;
if (i == ksh_SIGERR) {
diff --git a/src/jobs.c b/src/jobs.c
index 3277c78..18179c1 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: jobs.c,v 1.39 2009/12/13 04:36:48 deraadt Exp $ */
+/* $OpenBSD: jobs.c,v 1.40 2013/09/04 15:49:18 millert Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
- * 2012, 2013
+ * 2012, 2013, 2014
* 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/jobs.c,v 1.100 2013/07/26 20:33:23 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105 2014/10/03 12:32:48 tg Exp $");
#if HAVE_KILLPG
#define mksh_killpg killpg
@@ -225,6 +225,54 @@ proc_errorlevel(Proc *p)
}
}
+#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
+/* suspend the shell */
+void
+j_suspend(void)
+{
+ struct sigaction sa, osa;
+
+ /* Restore tty and pgrp. */
+ if (ttypgrp_ok) {
+ if (tty_hasstate)
+ mksh_tcset(tty_fd, &tty_state);
+ if (restore_ttypgrp >= 0) {
+ if (tcsetpgrp(tty_fd, restore_ttypgrp) < 0) {
+ warningf(false, "%s: %s %s: %s", "j_suspend",
+ "tcsetpgrp", "failed", cstrerror(errno));
+ } else if (setpgid(0, restore_ttypgrp) < 0) {
+ warningf(false, "%s: %s %s: %s", "j_suspend",
+ "setpgid", "failed", cstrerror(errno));
+ }
+ }
+ }
+
+ /* Suspend the shell. */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = SIG_DFL;
+ sigaction(SIGTSTP, &sa, &osa);
+ kill(0, SIGTSTP);
+
+ /* Back from suspend, reset signals, pgrp and tty. */
+ sigaction(SIGTSTP, &osa, NULL);
+ if (ttypgrp_ok) {
+ if (restore_ttypgrp >= 0) {
+ if (setpgid(0, kshpid) < 0) {
+ warningf(false, "%s: %s %s: %s", "j_suspend",
+ "setpgid", "failed", cstrerror(errno));
+ ttypgrp_ok = false;
+ } else if (tcsetpgrp(tty_fd, kshpid) < 0) {
+ warningf(false, "%s: %s %s: %s", "j_suspend",
+ "tcsetpgrp", "failed", cstrerror(errno));
+ ttypgrp_ok = false;
+ }
+ }
+ tty_init_state();
+ }
+}
+#endif
+
/* job cleanup before shell exit */
void
j_exit(void)
@@ -1222,6 +1270,15 @@ j_waitj(Job *j,
rv = vp->val.i;
p = p->next;
}
+ } else if (Flag(FPIPEFAIL) && (j->proc_list != NULL)) {
+ Proc *p = j->proc_list;
+ int i;
+
+ while (p != NULL) {
+ if ((i = proc_errorlevel(p)))
+ rv = i;
+ p = p->next;
+ }
}
if (!(flags & JW_ASYNCNOTIFY)
@@ -1281,7 +1338,11 @@ j_sigchld(int sig MKSH_A_UNUSED)
getrusage(RUSAGE_CHILDREN, &ru0);
do {
#ifndef MKSH_NOPROSPECTOFWORK
- pid = waitpid(-1, &status, (WNOHANG|WUNTRACED));
+ pid = waitpid(-1, &status, (WNOHANG |
+#if defined(WCONTINUED) && defined(WIFCONTINUED)
+ WCONTINUED |
+#endif
+ WUNTRACED));
#else
pid = wait(&status);
#endif
@@ -1320,6 +1381,13 @@ j_sigchld(int sig MKSH_A_UNUSED)
if (WIFSTOPPED(status))
p->state = PSTOPPED;
else
+#if defined(WCONTINUED) && defined(WIFCONTINUED)
+ if (WIFCONTINUED(status)) {
+ p->state = j->state = PRUNNING;
+ /* skip check_job(), no-op in this case */
+ continue;
+ } else
+#endif
#endif
if (WIFSIGNALED(status))
p->state = PSIGNALLED;
diff --git a/src/lex.c b/src/lex.c
index e58d8b8..9d39998 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: lex.c,v 1.47 2013/03/03 19:11:34 guenther Exp $ */
+/* $OpenBSD: lex.c,v 1.49 2013/12/17 16:37:06 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* 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/lex.c,v 1.188 2013/08/10 13:44:31 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193 2014/06/29 11:28:28 tg Exp $");
/*
* states while lexing word
@@ -159,9 +159,10 @@ getsc_r(int c)
state = statep->type; \
} while (/* CONSTCOND */ 0)
-#define PUSH_SRETRACE() do { \
+#define PUSH_SRETRACE(s) do { \
struct sretrace_info *ri; \
\
+ PUSH_STATE(s); \
statep->ls_start = Xsavepos(ws, wp); \
ri = alloc(sizeof(struct sretrace_info), ATEMP); \
Xinit(ri->xs, ri->xp, 64, ATEMP); \
@@ -176,6 +177,7 @@ getsc_r(int c)
dp = (void *)retrace_info; \
retrace_info = retrace_info->next; \
afree(dp, ATEMP); \
+ POP_STATE(); \
} while (/* CONSTCOND */ 0)
/**
@@ -404,9 +406,8 @@ yylex(int cf)
c = getsc();
if (c == '(') /*)*/ {
*wp++ = EXPRSUB;
- PUSH_STATE(SASPAREN);
+ PUSH_SRETRACE(SASPAREN);
statep->nparen = 2;
- PUSH_SRETRACE();
*retrace_info->xp++ = '(';
} else {
ungetsc(c);
@@ -650,7 +651,6 @@ yylex(int cf)
if (statep->nparen == 1) {
/* end of EXPRSUB */
POP_SRETRACE();
- POP_STATE();
if ((c2 = getsc()) == /*(*/ ')') {
cz = strlen(sp) - 2;
@@ -833,8 +833,7 @@ yylex(int cf)
} else if (c2 == '"') {
/* FALLTHROUGH */
case '"':
- state = statep->type = SHEREDQUOTE;
- PUSH_SRETRACE();
+ PUSH_SRETRACE(SHEREDQUOTE);
break;
}
ungetsc(c2);
@@ -1440,6 +1439,7 @@ getsc_line(Source *s)
alarm(0);
}
cp = Xstring(s->xs, xp);
+ rndpush(cp);
s->start = s->str = cp;
strip_nuls(Xstring(s->xs, xp), Xlength(s->xs, xp));
/* Note: if input is all nulls, this is not eof */
@@ -1521,9 +1521,10 @@ set_prompt(int to, Source *s)
int
pprompt(const char *cp, int ntruncate)
{
- int columns = 0, lines = 0;
- bool indelimit = false;
char delimiter = 0;
+ bool doprint = (ntruncate != -1);
+ bool indelimit = false;
+ int columns = 0, lines = 0;
/*
* Undocumented AT&T ksh feature:
@@ -1552,18 +1553,19 @@ pprompt(const char *cp, int ntruncate)
else if (UTFMODE && ((unsigned char)*cp > 0x7F)) {
const char *cp2;
columns += utf_widthadj(cp, &cp2);
- if (indelimit ||
- (ntruncate < (x_cols * lines + columns)))
+ if (doprint && (indelimit ||
+ (ntruncate < (x_cols * lines + columns))))
shf_write(cp, cp2 - cp, shl_out);
cp = cp2 - /* loop increment */ 1;
continue;
} else
columns++;
- if ((*cp != delimiter) &&
+ if (doprint && (*cp != delimiter) &&
(indelimit || (ntruncate < (x_cols * lines + columns))))
shf_putc(*cp, shl_out);
}
- shf_flush(shl_out);
+ if (doprint)
+ shf_flush(shl_out);
return (x_cols * lines + columns);
}
diff --git a/src/main.c b/src/main.c
index 291ab40..f12d9b9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,11 +1,11 @@
-/* $OpenBSD: main.c,v 1.52 2013/06/15 17:25:19 millert Exp $ */
-/* $OpenBSD: tty.c,v 1.9 2006/03/14 22:08:01 deraadt Exp $ */
-/* $OpenBSD: io.c,v 1.22 2006/03/17 16:30:13 millert Exp $ */
+/* $OpenBSD: main.c,v 1.54 2013/11/28 10:33:37 sobrado 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 $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@@ -34,7 +34,7 @@
#include <locale.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/main.c,v 1.269 2013/07/25 18:07:46 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/main.c,v 1.284 2014/10/03 17:19:27 tg Exp $");
extern char **environ;
@@ -48,7 +48,6 @@ extern char **environ;
static uint8_t isuc(const char *);
static int main_init(int, const char *[], Source **, struct block **);
-uint32_t chvt_rndsetup(const void *, size_t);
void chvt_reinit(void);
static void reclaim(void);
static void remove_temps(struct temp *);
@@ -64,7 +63,7 @@ static const char initsubs[] =
static const char *initcoms[] = {
Ttypeset, "-r", initvsn, NULL,
- Ttypeset, "-x", "HOME", "PATH", "RANDOM", "SHELL", NULL,
+ Ttypeset, "-x", "HOME", "PATH", "SHELL", NULL,
Ttypeset, "-i10", "COLUMNS", "LINES", "SECONDS", "TMOUT", NULL,
Talias,
"integer=typeset -i",
@@ -76,7 +75,6 @@ static const char *initcoms[] = {
/* not in Android for political reasons */
/* not in ARGE mksh due to no job control */
"stop=kill -STOP",
- "suspend=kill -STOP $$",
#endif
"autoload=typeset -fu",
"functions=typeset -f",
@@ -144,21 +142,6 @@ rndsetup(void)
return ((mksh_uari_t)h);
}
-uint32_t
-chvt_rndsetup(const void *bp, size_t sz)
-{
- register uint32_t h;
-
- NZATInit(h);
- /* variation through pid, ppid, and the works */
- NZATUpdateMem(h, &rndsetupstate, sizeof(rndsetupstate));
- /* some variation, some possibly entropy, depending on OE */
- NZATUpdateMem(h, bp, sz);
- NZAATFinish(h);
-
- return (h);
-}
-
void
chvt_reinit(void)
{
@@ -201,7 +184,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
int argi, i;
Source *s = NULL;
struct block *l;
- unsigned char restricted, errexit, utf_flag;
+ unsigned char restricted_shell, errexit, utf_flag;
char *cp;
const char *ccp, **wp;
struct tbl *vp;
@@ -247,6 +230,23 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
if (!*ccp)
ccp = empty_argv[0];
+ /*
+ * Turn on nohup by default. (AT&T ksh does not have a nohup
+ * option - it always sends the hup).
+ */
+ Flag(FNOHUP) = 1;
+
+ /*
+ * Turn on brace expansion by default. AT&T kshs that have
+ * alternation always have it on.
+ */
+ Flag(FBRACEEXPAND) = 1;
+
+ /*
+ * Turn on "set -x" inheritance by default.
+ */
+ Flag(FXTRACEREC) = 1;
+
/* define built-in commands and see if we were called as one */
ktinit(APERM, &builtins,
/* currently up to 51 builtins: 75% of 128 = 2^7 */
@@ -329,25 +329,6 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
/* setstr can't fail here */
setstr(vp, def_path, KSH_RETURN_ERROR);
- /*
- * Turn on nohup by default for now - will change to off
- * by default once people are aware of its existence
- * (AT&T ksh does not have a nohup option - it always sends
- * the hup).
- */
- Flag(FNOHUP) = 1;
-
- /*
- * Turn on brace expansion by default. AT&T kshs that have
- * alternation always have it on.
- */
- Flag(FBRACEEXPAND) = 1;
-
- /*
- * Turn on "set -x" inheritance by default.
- */
- Flag(FXTRACEREC) = 1;
-
#ifndef MKSH_NO_CMDLINE_EDITING
/*
* Set edit mode to emacs by default, may be overridden
@@ -361,9 +342,14 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
#endif
/* import environment */
- if (environ != NULL)
- for (wp = (const char **)environ; *wp != NULL; wp++)
+ if (environ != NULL) {
+ wp = (const char **)environ;
+ while (*wp != NULL) {
+ rndpush(*wp);
typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
+ ++wp;
+ }
+ }
/* for security */
typeset(initifs, 0, 0, 0, 0);
@@ -421,7 +407,11 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
setint_n((vp_pipest = global("PIPESTATUS")), 0, 10);
/* Set this before parsing arguments */
- Flag(FPRIVILEGED) = kshuid != ksheuid || kshgid != kshegid;
+ Flag(FPRIVILEGED) = (
+#if HAVE_ISSETUGID
+ issetugid() ||
+#endif
+ kshuid != ksheuid || kshgid != kshegid) ? 2 : 0;
/* this to note if monitor is set on command line (see below) */
#ifndef MKSH_UNEMPLOYED
@@ -436,44 +426,6 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
return (1);
}
-#if defined(DEBUG) && !defined(MKSH_LEGACY_MODE)
- /* test wraparound of arithmetic types */
- {
- volatile long xl;
- volatile unsigned long xul;
- volatile int xi;
- volatile unsigned int xui;
- volatile mksh_ari_t xa;
- volatile mksh_uari_t xua, xua2;
- volatile uint8_t xc;
-
- xa = 2147483647;
- xua = 2147483647;
- ++xa;
- ++xua;
- xua2 = xa;
- xl = xa;
- xul = xua;
- xa = 0;
- xua = 0;
- --xa;
- --xua;
- xi = xa;
- xui = xua;
- xa = -1;
- xua = xa;
- ++xa;
- ++xua;
- xc = 0;
- --xc;
- if ((xua2 != 2147483648UL) ||
- (xl != (-2147483647L-1)) || (xul != 2147483648UL) ||
- (xi != -1) || (xui != 4294967295U) ||
- (xa != 0) || (xua != 0) || (xc != 255))
- errorf("integer wraparound test failed");
- }
-#endif
-
/* process this later only, default to off (hysterical raisins) */
utf_flag = UTFMODE;
UTFMODE = 0;
@@ -485,7 +437,6 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
s = pushs(SSTRINGCMDLINE, ATEMP);
if (!(s->start = s->str = argv[argi++]))
errorf("%s %s", "-c", "requires an argument");
-#if !defined(MKSH_SMALL)
while (*s->str) {
if (*s->str != ' ' && ctype(*s->str, C_QUOTE))
break;
@@ -494,7 +445,6 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
if (!*s->str)
s->flags |= SF_MAYEXEC;
s->str = s->start;
-#endif
#ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
/* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */
if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--"))
@@ -543,12 +493,14 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
#ifndef MKSH_ASSUME_UTF8
/* auto-detect from locale or environment */
utf_flag = 4;
-#elif MKSH_ASSUME_UTF8
+#else /* this may not be an #elif */
+#if MKSH_ASSUME_UTF8
utf_flag = 1;
#else
/* always disable UTF-8 (for interactive) */
utf_flag = 0;
#endif
+#endif
}
#ifndef MKSH_NO_CMDLINE_EDITING
x_init();
@@ -625,7 +577,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
}
/* Disable during .profile/ENV reading */
- restricted = Flag(FRESTRICTED);
+ restricted_shell = Flag(FRESTRICTED);
Flag(FRESTRICTED) = 0;
errexit = Flag(FERREXIT);
Flag(FERREXIT) = 0;
@@ -637,25 +589,25 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
if (!current_wd[0] && Flag(FTALKING))
warningf(false, "can't determine current directory");
- if (Flag(FLOGIN)) {
+ if (Flag(FLOGIN))
include(MKSH_SYSTEM_PROFILE, 0, NULL, true);
- if (!Flag(FPRIVILEGED))
- include(substitute("$HOME/.profile", 0), 0,
- NULL, true);
- }
- if (Flag(FPRIVILEGED))
+ if (!Flag(FPRIVILEGED)) {
+ if (Flag(FLOGIN))
+ include(substitute("$HOME/.profile", 0), 0, NULL, true);
+ if (Flag(FTALKING)) {
+ cp = substitute(substitute("${ENV:-" MKSHRC_PATH "}",
+ 0), DOTILDE);
+ if (cp[0] != '\0')
+ include(cp, 0, NULL, true);
+ }
+ } else {
include(MKSH_SUID_PROFILE, 0, NULL, true);
- else if (Flag(FTALKING)) {
- char *env_file;
-
- /* include $ENV */
- env_file = substitute(substitute("${ENV:-" MKSHRC_PATH "}", 0),
- DOTILDE);
- if (*env_file != '\0')
- include(env_file, 0, NULL, true);
+ /* turn off -p if not set explicitly */
+ if (Flag(FPRIVILEGED) != 1)
+ change_flag(FPRIVILEGED, OF_INTERNAL, false);
}
- if (restricted) {
+ if (restricted_shell) {
shcomexec(restr_com);
/* After typeset command... */
Flag(FRESTRICTED) = 1;
@@ -873,11 +825,8 @@ shell(Source * volatile s, volatile bool toplevel)
unwind(LEXIT);
break;
}
- }
-#if !defined(MKSH_SMALL)
- else if ((s->flags & SF_MAYEXEC) && t->type == TCOM)
+ } else if ((s->flags & SF_MAYEXEC) && t->type == TCOM)
t->u.evalflags |= DOTCOMEXEC;
-#endif
if (!Flag(FNOEXEC) || (s->flags & SF_TTY))
exstat = execute(t, 0, NULL) & 0xFF;
@@ -1659,7 +1608,8 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist)
} while (len < 5);
/* cyclically attempt to open a temporary file */
- while ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR, 0600)) < 0) {
+ while ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR | O_BINARY,
+ 0600)) < 0) {
if (errno != EEXIST)
goto maketemp_out;
/* count down from z to a then from 9 to 0 */
@@ -1921,9 +1871,10 @@ x_mkraw(int fd, mksh_ttyst *ocb, bool forread)
cb = *ocb;
if (forread) {
+ cb.c_iflag &= ~(ISTRIP);
cb.c_lflag &= ~(ICANON) | ECHO;
} else {
- cb.c_iflag &= ~(INLCR | ICRNL);
+ cb.c_iflag &= ~(INLCR | ICRNL | ISTRIP);
cb.c_lflag &= ~(ISIG | ICANON | ECHO);
}
#if defined(VLNEXT) && defined(_POSIX_VDISABLE)
diff --git a/src/mirhash.h b/src/mirhash.h
new file mode 100644
index 0000000..05729bc
--- /dev/null
+++ b/src/mirhash.h
@@ -0,0 +1,224 @@
+/*-
+ * Copyright © 2011, 2014
+ * Thorsten Glaser <tg@mirbsd.org>
+ *
+ * Provided that these terms and disclaimer and all copyright notices
+ * are retained or reproduced in an accompanying document, permission
+ * is granted to deal in this work without restriction, including un‐
+ * limited rights to use, publicly perform, distribute, sell, modify,
+ * merge, give away, or sublicence.
+ *
+ * This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
+ * the utmost extent permitted by applicable law, neither express nor
+ * implied; without malicious intent or gross negligence. In no event
+ * may a licensor, author or contributor be held liable for indirect,
+ * direct, other damage, loss, or other issues arising in any way out
+ * of dealing in the work, even if advised of the possibility of such
+ * damage or existence of a defect, except proven that it results out
+ * of said person’s immediate fault when using the work as intended.
+ *-
+ * This file provides BAFH (Better Avalanche for the Jenkins Hash) as
+ * inline macro bodies that operate on “register uint32_t” variables,
+ * with variants that use their local intermediate registers.
+ *
+ * Usage note for BAFH with entropy distribution: input up to 4 bytes
+ * is best combined into a 32-bit unsigned integer, which is then run
+ * through BAFHFinish_reg for mixing and then used as context instead
+ * of 0. Longer input should be handled the same: take the first four
+ * bytes as IV after mixing then add subsequent bytes the same way.
+ * This needs counting input bytes and is endian-dependent, thus not,
+ * for speed reasons, specified for the regular stable hash, but very
+ * much recommended if the actual output value may differ across runs
+ * (so is using a random value instead of 0 for the IV).
+ *-
+ * Little quote gem:
+ * We are looking into it. Changing the core
+ * hash function in PHP isn't a trivial change
+ * and will take us some time.
+ * -- Rasmus Lerdorf
+ */
+
+#ifndef SYSKERN_MIRHASH_H
+#define SYSKERN_MIRHASH_H 1
+#define SYSKERN_MIRHASH_BAFH
+
+#include <sys/types.h>
+
+__RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.3 2014/10/02 19:34:06 tg Exp $");
+
+/*-
+ * BAFH itself is defined by the following primitives:
+ *
+ * • BAFHInit(ctx) initialises the hash context, which consists of a
+ * sole 32-bit unsigned integer (ideally in a register), to 0.
+ * It is possible to use any initial value out of [0; 2³²[ – which
+ * is, in fact, recommended if using BAFH for entropy distribution
+ * – but for a regular stable hash, the IV 0 is needed.
+ *
+ * • BAFHUpdateOctet(ctx,val) compresses the unsigned 8-bit quantity
+ * into the hash context. The algorithm used is Jenkins’ one-at-a-
+ * time, except that an additional constant 1 is added so that, if
+ * the context is (still) zero, adding a NUL byte is not ignored.
+ *
+ * • BAFHror(eax,cl) evaluates to the unsigned 32-bit integer “eax”,
+ * rotated right by “cl” ∈ [0;31]; no casting, be careful!
+ *
+ * • BAFHFinish(ctx) avalanches the context around so every sub-byte
+ * depends on all input octets; afterwards, the context variable’s
+ * value is the hash output. BAFH does not use any padding, nor is
+ * the input length added; this is due to the common use case (for
+ * quick entropy distribution and use with a hashtable).
+ * Warning: BAFHFinish uses the MixColumn algorithm of AES – which
+ * is reversible (to avoid introducing funnels and reducing entro‐
+ * py), so blinding may need to be employed for some uses, e.g. in
+ * mksh, after a fork.
+ *
+ * The BAFHUpdateOctet and BAFHFinish are available in two flavours:
+ * suffixed with _reg (assumes the context is in a register) or _mem
+ * (which doesn’t).
+ *
+ * The following high-level macros (with _reg and _mem variants) are
+ * available:
+ *
+ * • BAFHUpdateMem(ctx,buf,len) adds a memory block to a context.
+ * • BAFHUpdateStr(ctx,buf) is equivalent to using len=strlen(buf).
+ * • BAFHHostMem(ctx,buf,len) calculates the hash of the memory buf‐
+ * fer using the first 4 octets (mixed) for IV, as outlined above;
+ * the result is endian-dependent; “ctx” assumed to be a register.
+ * • BAFHHostStr(ctx,buf) does the same for C strings.
+ *
+ * All macros may use ctx multiple times in their expansion, but all
+ * other arguments are always evaluated at most once.
+ *
+ * To stay portable, never use the BAFHHost*() macros (these are for
+ * host-local entropy shuffling), and encode numbers using ULEB128.
+ */
+
+#define BAFHInit(h) do { \
+ (h) = 0; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHUpdateOctet_reg(h,b) do { \
+ (h) += (uint8_t)(b); \
+ ++(h); \
+ (h) += (h) << 10; \
+ (h) ^= (h) >> 6; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHUpdateOctet_mem(m,b) do { \
+ register uint32_t BAFH_h = (m); \
+ \
+ BAFHUpdateOctet_reg(BAFH_h, (b)); \
+ (m) = BAFH_h; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHror(eax,cl) (((eax) >> (cl)) | ((eax) << (32 - (cl))))
+
+#define BAFHFinish_reg(h) do { \
+ register uint32_t BAFHFinish_v; \
+ \
+ BAFHFinish_v = ((h) >> 7) & 0x01010101U; \
+ BAFHFinish_v += BAFHFinish_v << 1; \
+ BAFHFinish_v += BAFHFinish_v << 3; \
+ BAFHFinish_v ^= ((h) << 1) & 0xFEFEFEFEU; \
+ \
+ BAFHFinish_v ^= BAFHror(BAFHFinish_v, 8); \
+ BAFHFinish_v ^= ((h) = BAFHror((h), 8)); \
+ BAFHFinish_v ^= ((h) = BAFHror((h), 8)); \
+ (h) = BAFHror((h), 8) ^ BAFHFinish_v; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHFinish_mem(m) do { \
+ register uint32_t BAFHFinish_v, BAFH_h = (m); \
+ \
+ BAFHFinish_v = (BAFH_h >> 7) & 0x01010101U; \
+ BAFHFinish_v += BAFHFinish_v << 1; \
+ BAFHFinish_v += BAFHFinish_v << 3; \
+ BAFHFinish_v ^= (BAFH_h << 1) & 0xFEFEFEFEU; \
+ \
+ BAFHFinish_v ^= BAFHror(BAFHFinish_v, 8); \
+ BAFHFinish_v ^= (BAFH_h = BAFHror(BAFH_h, 8)); \
+ BAFHFinish_v ^= (BAFH_h = BAFHror(BAFH_h, 8)); \
+ (m) = BAFHror(BAFH_h, 8) ^ BAFHFinish_v; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHUpdateMem_reg(h,p,z) do { \
+ register const uint8_t *BAFHUpdate_p; \
+ register size_t BAFHUpdate_z = (z); \
+ \
+ BAFHUpdate_p = (const void *)(p); \
+ while (BAFHUpdate_z--) \
+ BAFHUpdateOctet_reg((h), *BAFHUpdate_p++); \
+} while (/* CONSTCOND */ 0)
+
+/* meh should have named them _r/m but that’s not valid C */
+#define BAFHUpdateMem_mem(m,p,z) do { \
+ register uint32_t BAFH_h = (m); \
+ \
+ BAFHUpdateMem_reg(BAFH_h, (p), (z)); \
+ (m) = BAFH_h; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHUpdateStr_reg(h,s) do { \
+ register const uint8_t *BAFHUpdate_s; \
+ register uint8_t BAFHUpdate_c; \
+ \
+ BAFHUpdate_s = (const void *)(s); \
+ while ((BAFHUpdate_c = *BAFHUpdate_s++) != 0) \
+ BAFHUpdateOctet_reg((h), BAFHUpdate_c); \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHUpdateStr_mem(m,s) do { \
+ register uint32_t BAFH_h = (m); \
+ \
+ BAFHUpdateStr_reg(BAFH_h, (s)); \
+ (m) = BAFH_h; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHHostMem(h,p,z) do { \
+ register const uint8_t *BAFHUpdate_p; \
+ register size_t BAFHUpdate_z = (z); \
+ size_t BAFHHost_z; \
+ union { \
+ uint8_t as_u8[4]; \
+ uint32_t as_u32; \
+ } BAFHHost_v; \
+ \
+ BAFHUpdate_p = (const void *)(p); \
+ BAFHHost_v.as_u32 = 0; \
+ BAFHHost_z = BAFHUpdate_z < 4 ? BAFHUpdate_z : 4; \
+ memcpy(BAFHHost_v.as_u8, BAFHUpdate_p, BAFHHost_z); \
+ BAFHUpdate_p += BAFHHost_z; \
+ BAFHUpdate_z -= BAFHHost_z; \
+ (h) = BAFHHost_v.as_u32; \
+ BAFHFinish_reg(h); \
+ while (BAFHUpdate_z--) \
+ BAFHUpdateOctet_reg((h), *BAFHUpdate_p++); \
+ BAFHFinish_reg(h); \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHHostStr(h,s) do { \
+ register const uint8_t *BAFHUpdate_s; \
+ register uint8_t BAFHUpdate_c; \
+ union { \
+ uint8_t as_u8[4]; \
+ uint32_t as_u32; \
+ } BAFHHost_v; \
+ \
+ BAFHUpdate_s = (const void *)(s); \
+ if ((BAFHHost_v.as_u8[0] = *BAFHUpdate_s) != 0) \
+ ++BAFHUpdate_s; \
+ if ((BAFHHost_v.as_u8[1] = *BAFHUpdate_s) != 0) \
+ ++BAFHUpdate_s; \
+ if ((BAFHHost_v.as_u8[2] = *BAFHUpdate_s) != 0) \
+ ++BAFHUpdate_s; \
+ if ((BAFHHost_v.as_u8[3] = *BAFHUpdate_s) != 0) \
+ ++BAFHUpdate_s; \
+ (h) = BAFHHost_v.as_u32; \
+ BAFHFinish_reg(h); \
+ while ((BAFHUpdate_c = *BAFHUpdate_s++) != 0) \
+ BAFHUpdateOctet_reg((h), BAFHUpdate_c); \
+ BAFHFinish_reg(h); \
+} while (/* CONSTCOND */ 0)
+
+#endif
diff --git a/src/misc.c b/src/misc.c
index adf4bc4..82d47d6 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1,9 +1,9 @@
-/* $OpenBSD: misc.c,v 1.37 2009/04/19 20:34:05 sthen Exp $ */
+/* $OpenBSD: misc.c,v 1.38 2013/11/28 10:33:37 sobrado 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
+ * 2011, 2012, 2013, 2014
* 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.214 2013/08/11 14:57:09 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219 2014/01/05 21:57:27 tg Exp $");
#define KSH_CHVT_FLAG
#ifdef MKSH_SMALL
@@ -49,10 +49,11 @@ __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.214 2013/08/11 14:57:09 tg Exp $");
unsigned char chtypes[UCHAR_MAX + 1];
static const unsigned char *pat_scan(const unsigned char *,
- const unsigned char *, bool);
+ const unsigned char *, bool) MKSH_A_PURE;
static int do_gmatch(const unsigned char *, const unsigned char *,
- const unsigned char *, const unsigned char *);
-static const unsigned char *cclass(const unsigned char *, unsigned char);
+ const unsigned char *, const unsigned char *) MKSH_A_PURE;
+static const unsigned char *cclass(const unsigned char *, unsigned char)
+ MKSH_A_PURE;
#ifdef KSH_CHVT_CODE
static void chvt(const Getopt *);
#endif
@@ -125,7 +126,7 @@ Xcheck_grow(XString *xsp, const char *xp, size_t more)
#define SHFLAGS_DEFNS
-#include "sh_flags.h"
+#include "sh_flags.gen"
#define OFC(i) (options[i][-2])
#define OFF(i) (((const unsigned char *)options[i])[-1])
@@ -133,7 +134,7 @@ Xcheck_grow(XString *xsp, const char *xp, size_t more)
const char * const options[] = {
#define SHFLAGS_ITEMS
-#include "sh_flags.h"
+#include "sh_flags.gen"
};
/*
@@ -271,6 +272,7 @@ change_flag(enum sh_flag f, int what, bool newset)
/*XXX this can probably be optimised */
kshegid = kshgid = getgid();
+ ksheuid = kshuid = getuid();
#if HAVE_SETRESUGID
DO_SETUID(setresgid, (kshegid, kshegid, kshegid));
#if HAVE_SETGROUPS
@@ -278,9 +280,8 @@ change_flag(enum sh_flag f, int what, bool newset)
setgroups(1, &kshegid);
#endif
DO_SETUID(setresuid, (ksheuid, ksheuid, ksheuid));
-#else
+#else /* !HAVE_SETRESUGID */
/* seteuid, setegid, setgid don't EAGAIN on Linux */
- ksheuid = kshuid = getuid();
#ifndef MKSH__NO_SETEUGID
seteuid(ksheuid);
#endif
@@ -289,7 +290,7 @@ change_flag(enum sh_flag f, int what, bool newset)
setegid(kshegid);
#endif
setgid(kshegid);
-#endif
+#endif /* !HAVE_SETRESUGID */
} else if ((f == FPOSIX || f == FSH) && newval) {
/* Turning on -o posix or -o sh? */
Flag(FBRACEEXPAND) = 0;
@@ -341,10 +342,20 @@ parse_args(const char **argv,
int what,
bool *setargsp)
{
- static char cmd_opts[NELEM(options) + 5]; /* o:T:\0 */
- static char set_opts[NELEM(options) + 6]; /* A:o;s\0 */
+ static const char cmd_opts[] =
+#define SHFLAGS_NOT_SET
+#define SHFLAGS_OPTCS
+#include "sh_flags.gen"
+#undef SHFLAGS_NOT_SET
+ ;
+ static const char set_opts[] =
+#define SHFLAGS_NOT_CMD
+#define SHFLAGS_OPTCS
+#include "sh_flags.gen"
+#undef SHFLAGS_NOT_CMD
+ ;
bool set;
- char *opts;
+ const char *opts;
const char *array = NULL;
Getopt go;
size_t i;
@@ -352,36 +363,6 @@ parse_args(const char **argv,
bool sortargs = false;
bool fcompatseen = false;
- /* First call? Build option strings... */
- if (cmd_opts[0] == '\0') {
- char ch, *p = cmd_opts, *q = set_opts;
-
- /* see cmd_opts[] declaration */
- *p++ = 'o';
- *p++ = ':';
-#ifdef KSH_CHVT_FLAG
- *p++ = 'T';
- *p++ = ':';
-#endif
- /* see set_opts[] declaration */
- *q++ = 'A';
- *q++ = ':';
- *q++ = 'o';
- *q++ = ';';
- *q++ = 's';
-
- for (i = 0; i < NELEM(options); i++) {
- if ((ch = OFC(i))) {
- if (OFF(i) & OF_CMDLINE)
- *p++ = ch;
- if (OFF(i) & OF_SET)
- *q++ = ch;
- }
- }
- *p = '\0';
- *q = '\0';
- }
-
if (what == OF_CMDLINE) {
const char *p = argv[0], *q;
/*
@@ -1972,7 +1953,6 @@ c_cd(const char **wp)
#ifdef KSH_CHVT_CODE
-extern uint32_t chvt_rndsetup(const void *, size_t);
extern void chvt_reinit(void);
static void
@@ -2016,9 +1996,9 @@ chvt(const Getopt *go)
#endif
}
}
- if ((fd = open(dv, O_RDWR)) < 0) {
+ if ((fd = open(dv, O_RDWR | O_BINARY)) < 0) {
sleep(1);
- if ((fd = open(dv, O_RDWR)) < 0) {
+ if ((fd = open(dv, O_RDWR | O_BINARY)) < 0) {
errorf("%s: %s %s", "chvt", "can't open", dv);
}
}
diff --git a/src/mksh.1 b/src/mksh.1
index 621aa97..480184e 100644
--- a/src/mksh.1
+++ b/src/mksh.1
@@ -1,8 +1,8 @@
-.\" $MirOS: src/bin/mksh/mksh.1,v 1.320 2013/08/10 14:11:39 tg Exp $
-.\" $OpenBSD: ksh.1,v 1.147 2013/06/13 19:43:09 millert Exp $
+.\" $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 $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-.\" 2010, 2011, 2012, 2013
+.\" 2010, 2011, 2012, 2013, 2014
.\" Thorsten Glaser <tg@mirbsd.org>
.\"
.\" Provided that these terms and disclaimer and all copyright notices
@@ -74,7 +74,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always.
.\"
-.Dd $Mdocdate: August 10 2013 $
+.Dd $Mdocdate: October 7 2014 $
.\"
.\" Check which macro package we use, and do other -mdoc setup.
.\"
@@ -208,7 +208,7 @@ will execute the command(s) contained in
.Ar string .
.It Fl i
Interactive shell.
-A shell is
+A shell that reads commands from standard input is
.Dq interactive
if this
option is used or if both standard input and standard error are attached
@@ -247,8 +247,7 @@ below.
Privileged shell.
A shell is
.Dq privileged
-if this option is used
-or if the real user ID or group ID does not match the
+if the real user ID or group ID does not match the
effective user ID or group ID (see
.Xr getuid 2
and
@@ -257,6 +256,9 @@ Clearing the privileged option causes the shell to set
its effective user ID (group ID) to its real user ID (group ID).
For further implications, see
.Sx Startup files .
+If the shell is privileged and this flag is not explicitly set, the
+.Dq privileged
+option is cleared automatically after processing the startup files.
.It Fl r
Restricted shell.
A shell is
@@ -366,6 +368,9 @@ parameter after subjecting it to parameter, command, arithmetic and tilde
substitution; if unset or empty, the user mkshrc profile is processed;
otherwise, if a file whose name is the substitution result exists,
it is processed; non-existence is silently ignored.
+A privileged shell then drops privileges if neither was the
+.Fl p
+option given on the command line nor set during execution of the startup files.
.Ss Command syntax
The shell begins parsing its input by removing any backslash-newline
combinations, then breaking it into
@@ -955,7 +960,7 @@ The second operand of the
.Sq !=
and
.Sq =
-expressions are patterns (e.g. the comparison
+expressions are a subset of patterns (e.g. the comparison
.Ic \&[[ foobar = f*r ]]
succeeds).
This even works indirectly:
@@ -967,6 +972,7 @@ $ [[ $bar = \&"$baz" ]]; echo $?
.Pp
Perhaps surprisingly, the first comparison succeeds,
whereas the second doesn't.
+This does not apply to all extglob metacharacters, currently.
.El
.El
.Ss Quoting
@@ -1123,7 +1129,6 @@ nameref=\*(aqtypeset \-n\*(aq
nohup=\*(aqnohup \*(aq
r=\*(aqfc \-e \-\*(aq
stop=\*(aqkill \-STOP\*(aq
-suspend=\*(aqkill \-STOP $$\*(aq
type=\*(aqwhence \-v\*(aq
.Ed
.Pp
@@ -1227,10 +1232,8 @@ whitespace octets, in combination with zero or one
whitespace octets, delimit a field.
As a special case, leading and trailing
.Ev IFS
-whitespace and trailing
-.Ev IFS
-non-whitespace are stripped (i.e. no leading or trailing empty field
-is created by it); leading
+whitespace is stripped (i.e. no leading or trailing empty field
+is created by it); leading or trailing
.Pf non- Ev IFS
whitespace does create an empty field.
.Pp
@@ -1685,17 +1688,10 @@ Currently,
must start with a space, opening parenthesis or digit to be recognised.
Cannot be applied to a vector.
.Pp
-.It Xo
-.Pf ${ Ar name
-.Pf @# Ns Oo Ar seed Oc Ns }
-.Xc
-The internal hash of the expansion of
-.Ar name ,
-with an optional (defaulting to zero)
-.Op Ar seed .
-At the moment, this is NZAAT (a 32-bit hash based on
-Bob Jenkins' one-at-a-time hash), but this is not set.
-This is the hash the shell uses internally for its associative arrays.
+.It Pf ${ Ns Ar name Ns @#}
+The hash (using the BAFH algorithm) of the expansion of
+.Ar name .
+This is also used internally for the shell's hashtables.
.Pp
.It Pf ${ Ns Ar name Ns @Q}
A quoted expression safe for re-entry, whose value is the value of the
@@ -1879,6 +1875,9 @@ This is different from
.It Ev HISTSIZE
The number of commands normally stored for history.
The default is 2047.
+Do not set this value to insanely high values such as 1000000000 because
+.Nm
+can then not allocate enough memory for the history and will not start.
.It Ev HOME
The default directory for the
.Ic cd
@@ -2037,7 +2036,7 @@ in reverse video
in the prompt string:
.Bd -literal -offset indent
x=$(print \e\e001)
-PS1="$x$(print \e\er)$x$(tput smso)$x\e$PWD$x$(tput rmso)$x\*(Gt "
+PS1="$x$(print \e\er)$x$(tput so)$x\e$PWD$x$(tput se)$x\*(Gt "
.Ed
.Pp
Due to a strong suggestion from David G. Korn,
@@ -2531,6 +2530,12 @@ command, inside $((..)) expressions, inside array references (e.g.\&
as numeric arguments to the
.Ic test
command, and as the value of an assignment to an integer parameter.
+.Em Warning :
+This also affects implicit conversion to integer, for example as done by the
+.Ic let
+command.
+.Em Never
+use unchecked user input, e.g. from the environment, in arithmetics!
.Pp
Expressions are calculated using signed arithmetic and the
.Vt mksh_ari_t
@@ -2592,7 +2597,7 @@ in all forms of arithmetic expressions, except as numeric arguments to the
built-in command.
Prefixing numbers with a sole digit zero
.Pq Sq 0
-leads to the shell interpreting it as base-8 integer in
+leads to the shell interpreting it as base-8 (octal) integer in
.Ic posix
mode
.Em only ;
@@ -2699,7 +2704,7 @@ Not equal; the result is 0 if both arguments are equal, 1 if not.
Less than; the result is 1 if the left argument is less than the right, 0 if
not.
.It \*(Lt= \*(Gt \*(Gt=
-Less than or equal, greater than or equal, greater than.
+Less than or equal, greater than, greater than or equal.
See
.Ic \*(Lt .
.It \*(Lt\*(Lt\*(Lt \*(Gt\*(Gt\*(Gt
@@ -2713,8 +2718,15 @@ Shift left (right); the result is the left argument with its bits shifted left
.It + \- * /
Addition, subtraction, multiplication, and division.
.It %
-Remainder; the result is the remainder of the division of the left argument by
-the right.
+Remainder; the result is the symmetric remainder of the division of the left
+argument by the right.
+To get the mathematical modulus of
+.Dq a Ic mod No b ,
+use the formula
+.Do
+.Pq a % b + b
+.No % b
+.Dc .
.It Xo
.Sm off
.Aq Ar arg1 ?
@@ -2953,8 +2965,9 @@ Builtins that are not special:
.Ic false , fc , fg , getopts ,
.Ic jobs , kill , let , mknod ,
.Ic print , pwd , read , realpath ,
-.Ic rename , sleep , test , true ,
-.Ic ulimit , umask , unalias , whence
+.Ic rename , sleep , suspend , test ,
+.Ic true , ulimit , umask , unalias ,
+.Ic whence
.Pp
Once the type of command has been determined, any command-line parameter
assignments are performed and exported for the duration of the command.
@@ -3411,6 +3424,7 @@ and
.Ar last
select commands from the history.
Commands can be selected by history number
+(negative numbers go backwards from the current, most recent, line)
or a string specifying the most recent command starting with that string.
The
.Fl l
@@ -3623,7 +3637,7 @@ Since expressions may need to be quoted,
is syntactic sugar for
.No let \&" Ns Ar expr Ns \&" .
.Pp
-.It let]
+.It Ic let]
Internally used alias for
.Ic let .
.Pp
@@ -4036,6 +4050,12 @@ Only used if job control is enabled
.It Fl C \*(Ba Fl o Ic noclobber
Prevent \*(Gt redirection from overwriting existing files.
Instead, \*(Gt\*(Ba must be used to force an overwrite.
+Note that this is not safe to use for creation of temporary files or
+lockfiles due to a TOCTOU in a check allowing one to redirect output to
+.Pa /dev/null
+or other device files even in
+.Ic noclobber
+mode.
.It Fl e \*(Ba Fl o Ic errexit
Exit (after executing the
.Dv ERR
@@ -4242,6 +4262,9 @@ mode.
Enable
.Xr vi 1 Ns -like
command-line editing (interactive shells only).
+See
+.Sx Vi editing mode
+for documentation and limitations.
.It Fl o Ic vi\-esccomplete
In vi command-line editing, do command and file name completion when escape
(\*(ha[) is entered in command mode.
@@ -4315,6 +4338,16 @@ and
.Nm mksh ,
this is implemented as a shell alias instead of a builtin.
.Pp
+.It Ic suspend
+Stops the shell as if it had received the suspend character from
+the terminal.
+It is not possible to suspend a login shell unless the parent process
+is a member of the same terminal session but is a member of a different
+process group.
+As a general rule, if the shell was started by another shell or via
+.Xr su 1 ,
+it can be suspended.
+.Pp
.It Ic test Ar expression
.It Ic \&[ Ar expression Ic \&]
.Ic test
@@ -4878,7 +4911,7 @@ unless they are also given on the same command line.
.Pp
.It Xo
.Ic ulimit
-.Op Fl aBCcdefHiLlMmnOPpqrSsTtVvw
+.Op Fl aBCcdefHilMmnOPpqrSsTtVvw
.Op Ar value
.Xc
Display or set process limits.
@@ -4929,8 +4962,6 @@ Set the hard limit only (the default is to set both hard and soft limits).
.It Fl i Ar n
Set the number of pending signals to
.Ar n .
-.It Fl L Ar n
-Control flocks; documentation is missing.
.It Fl l Ar n
Impose a limit of
.Ar n
@@ -5673,6 +5704,7 @@ replaces the inserted text string with the next previously killed text string.
.Ss Vi editing mode
.Em Note:
The vi command-line editing mode is orphaned, yet still functional.
+It is 8-bit clean but specifically does not support UTF-8 or MBCS.
.Pp
The vi command-line editor in
.Nm
@@ -6307,15 +6339,15 @@ contains the system and suid profile.
.%A Stephen G. Kochan
.%A Patrick H. Wood
.%B "\\*(tNUNIX\\*(sP Shell Programming"
-.%V "Revised Edition"
-.%D 1990
-.%I "Hayden"
-.%P "xi\ +\ 490 pages"
-.%O "ISBN 978\-0\-672\-48448\-3 (0\-672\-48448\-X)"
+.%V "3rd Edition"
+.%D 2003
+.%I "Sams"
+.%P "xiii\ +\ 437 pages"
+.%O "ISBN 978\-0\-672\-32490\-1 (0\-672\-32490\-3)"
.Re
.Rs
.%A "IEEE Inc."
-.%B "\\*(tNIEEE\\*(sP Standard for Information Technology \*(en Portable Operating System Interface (POSIX)"
+.%T "\\*(tNIEEE\\*(sP Standard for Information Technology \*(en Portable Operating System Interface (POSIX)"
.%V "Part 2: Shell and Utilities"
.%D 1993
.%I "IEEE Press"
@@ -6348,24 +6380,35 @@ contains the system and suid profile.
.%O "ISBN 978\-0\-201\-56324\-5 (0\-201\-56324\-X)"
.Re
.Sh AUTHORS
+.An -nosplit
.Nm "The MirBSD Korn Shell"
is developed by
.An Thorsten Glaser Aq tg@mirbsd.org
and currently maintained as part of The MirOS Project.
-This shell is based upon the Public Domain Korn SHell.
-The developer of mksh recognises the efforts of the pdksh authors,
-who had dedicated their work into Public Domain, our users, and
-all contributors, such as the Debian and OpenBSD projects.
-.\"
-.\" Charles Forsyth, author of the (Public Domain) Bourne Shell clone,
-.\" which mksh is derived from, agreed to the following:
-.\"
-.\" In countries where the Public Domain status of the work may not be
-.\" valid, its primary author hereby grants a copyright licence to the
-.\" general public to deal in the work without restriction and permis-
-.\" sion to sublicence derivates under the terms of any (OSI approved)
-.\" Open Source licence.
-.\"
+This shell is based on the public domain 7th edition Bourne shell clone by
+.An Charles Forsyth ,
+who kindly agreed to, in countries where the Public Domain status of the work
+may not be valid, grant a copyright licence to the general public to deal in
+the work without restriction and permission to sublicence derivates under the
+terms of any (OSI approved) Open Source licence,
+and parts of the BRL shell by
+.An Doug A. Gwyn ,
+.An Doug Kingston ,
+.An Ron Natalie ,
+.An Arnold Robbins ,
+.An Lou Salkind ,
+and others.
+The first release of
+.Nm pdksh
+was created by
+.An Eric Gisin ,
+and it was subsequently maintained by
+.An John R. MacMillan Aq Mt change!john@sq.sq.com ,
+.An Simon J. Gerraty Aq Mt sjg@zen.void.oz.au ,
+and
+.An Michael Rendell Aq Mt michael@cs.mun.ca .
+The effort of several projects, such as Debian and OpenBSD, and other
+contributors including our users, to improve the shell is appreciated.
See the documentation, CVS, and web site for details.
.Pp
The BSD daemon is Copyright \(co Marshall Kirk McKusick.
@@ -6407,8 +6450,8 @@ foo \*(Ba bar \*(Ba& read \-p baz # will, however, do so
.Pp
.Nm mksh
provides a consistent set of 32-bit integer arithmetics, both signed
-and unsigned, with defined wraparound and sign of the result of a modulo
-operation, even (defying POSIX) on 64-bit systems.
+and unsigned, with defined wraparound and sign of the result of a
+remainder operation, even (defying POSIX) on 64-bit systems.
If you require 64-bit integer arithmetics, use
.Nm lksh Pq legacy mksh
instead, but be aware that, in POSIX, it's legal for the OS to make
@@ -6425,7 +6468,7 @@ $ /bin/sleep 666 && echo fubar
.Ed
.Pp
This document attempts to describe
-.Nm mksh\ R48
+.Nm mksh\ R50
and up,
compiled without any options impacting functionality, such as
.Dv MKSH_SMALL ,
diff --git a/src/rlimits.gen b/src/rlimits.gen
new file mode 100644
index 0000000..ef71dab
--- /dev/null
+++ b/src/rlimits.gen
@@ -0,0 +1,174 @@
+#ifndef RLIMITS_OPTCS
+#if defined(RLIMITS_DEFNS)
+__RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.1 2013/11/17 22:21:18 tg Exp $");
+struct limits {
+ /* limit resource */
+ int resource;
+ /* multiply by to get rlim_{cur,max} values */
+ unsigned int factor;
+ /* getopts char */
+ char optchar;
+ /* limit name */
+ char name[1];
+};
+#define FN(lname,lid,lfac,lopt) static const struct { int resource; unsigned int factor; char optchar; char name[sizeof(lname)]; } rlimits_ ## lid = { lid, lfac, lopt, lname };
+#elif defined(RLIMITS_ITEMS)
+#define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
+#endif
+#ifndef F0
+#define F0 FN
+#endif
+#ifdef RLIMIT_CPU
+FN("time(cpu-seconds)", RLIMIT_CPU, 1, 't')
+#endif
+#ifdef RLIMIT_FSIZE
+FN("file(blocks)", RLIMIT_FSIZE, 512, 'f')
+#endif
+#ifdef RLIMIT_CORE
+FN("coredump(blocks)", RLIMIT_CORE, 512, 'c')
+#endif
+#ifdef RLIMIT_DATA
+FN("data(KiB)", RLIMIT_DATA, 1024, 'd')
+#endif
+#ifdef RLIMIT_STACK
+FN("stack(KiB)", RLIMIT_STACK, 1024, 's')
+#endif
+#ifdef RLIMIT_MEMLOCK
+FN("lockedmem(KiB)", RLIMIT_MEMLOCK, 1024, 'l')
+#endif
+#ifdef RLIMIT_NOFILE
+FN("nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n')
+#endif
+#ifdef RLIMIT_NPROC
+FN("processes", RLIMIT_NPROC, 1, 'p')
+#endif
+#ifdef RLIMIT_SWAP
+FN("swap(KiB)", RLIMIT_SWAP, 1024, 'w')
+#endif
+#ifdef RLIMIT_TIME
+FN("humantime(seconds)", RLIMIT_TIME, 1, 'T')
+#endif
+#ifdef RLIMIT_NOVMON
+FN("vnodemonitors", RLIMIT_NOVMON, 1, 'V')
+#endif
+#ifdef RLIMIT_SIGPENDING
+FN("sigpending", RLIMIT_SIGPENDING, 1, 'i')
+#endif
+#ifdef RLIMIT_MSGQUEUE
+FN("msgqueue(bytes)", RLIMIT_MSGQUEUE, 1, 'q')
+#endif
+#ifdef RLIMIT_AIO_MEM
+FN("AIOlockedmem(KiB)", RLIMIT_AIO_MEM, 1024, 'M')
+#endif
+#ifdef RLIMIT_AIO_OPS
+FN("AIOoperations", RLIMIT_AIO_OPS, 1, 'O')
+#endif
+#ifdef RLIMIT_TCACHE
+FN("cachedthreads", RLIMIT_TCACHE, 1, 'C')
+#endif
+#ifdef RLIMIT_SBSIZE
+FN("sockbufsiz(KiB)", RLIMIT_SBSIZE, 1024, 'B')
+#endif
+#ifdef RLIMIT_PTHREAD
+FN("threadsperprocess", RLIMIT_PTHREAD, 1, 'P')
+#endif
+#ifdef RLIMIT_NICE
+FN("maxnice", RLIMIT_NICE, 1, 'e')
+#endif
+#ifdef RLIMIT_RTPRIO
+FN("maxrtprio", RLIMIT_RTPRIO, 1, 'r')
+#endif
+#ifdef ULIMIT_M_IS_RSS
+FN("resident-set(KiB)", RLIMIT_RSS, 1024, 'm')
+#endif
+#ifdef ULIMIT_M_IS_VMEM
+FN("memory(KiB)", RLIMIT_VMEM, 1024, 'm')
+#endif
+#ifdef ULIMIT_V_IS_VMEM
+FN("virtual-memory(KiB)", RLIMIT_VMEM, 1024, 'v')
+#endif
+#ifdef ULIMIT_V_IS_AS
+FN("address-space(KiB)", RLIMIT_AS, 1024, 'v')
+#endif
+#undef F0
+#undef FN
+#undef RLIMITS_DEFNS
+#undef RLIMITS_ITEMS
+#else
+"a"
+#ifdef RLIMIT_SBSIZE
+"B"
+#endif
+#ifdef RLIMIT_TCACHE
+"C"
+#endif
+#ifdef RLIMIT_CORE
+"c"
+#endif
+#ifdef RLIMIT_DATA
+"d"
+#endif
+#ifdef RLIMIT_NICE
+"e"
+#endif
+#ifdef RLIMIT_FSIZE
+"f"
+#endif
+"H"
+#ifdef RLIMIT_SIGPENDING
+"i"
+#endif
+#ifdef RLIMIT_MEMLOCK
+"l"
+#endif
+#ifdef RLIMIT_AIO_MEM
+"M"
+#endif
+#ifdef ULIMIT_M_IS_RSS
+"m"
+#endif
+#ifdef ULIMIT_M_IS_VMEM
+"m"
+#endif
+#ifdef RLIMIT_NOFILE
+"n"
+#endif
+#ifdef RLIMIT_AIO_OPS
+"O"
+#endif
+#ifdef RLIMIT_PTHREAD
+"P"
+#endif
+#ifdef RLIMIT_NPROC
+"p"
+#endif
+#ifdef RLIMIT_MSGQUEUE
+"q"
+#endif
+#ifdef RLIMIT_RTPRIO
+"r"
+#endif
+"S"
+#ifdef RLIMIT_STACK
+"s"
+#endif
+#ifdef RLIMIT_TIME
+"T"
+#endif
+#ifdef RLIMIT_CPU
+"t"
+#endif
+#ifdef RLIMIT_NOVMON
+"V"
+#endif
+#ifdef ULIMIT_V_IS_AS
+"v"
+#endif
+#ifdef ULIMIT_V_IS_VMEM
+"v"
+#endif
+#ifdef RLIMIT_SWAP
+"w"
+#endif
+#undef RLIMITS_OPTCS
+#endif
diff --git a/src/rlimits.opt b/src/rlimits.opt
new file mode 100644
index 0000000..6c3908b
--- /dev/null
+++ b/src/rlimits.opt
@@ -0,0 +1,96 @@
+@RLIMITS_DEFNS
+__RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.1 2013/11/17 22:21:18 tg Exp $");
+struct limits {
+ /* limit resource */
+ int resource;
+ /* multiply by to get rlim_{cur,max} values */
+ unsigned int factor;
+ /* getopts char */
+ char optchar;
+ /* limit name */
+ char name[1];
+};
+#define FN(lname,lid,lfac,lopt) static const struct { int resource; unsigned int factor; char optchar; char name[sizeof(lname)]; } rlimits_ ## lid = { lid, lfac, lopt, lname };
+@RLIMITS_ITEMS
+#define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
+@@
+
+/* generic options for the ulimit builtin */
+
+<a|
+<H|
+<S|
+
+/* do not use options -H, -S or -a or change the order */
+
+>t|RLIMIT_CPU
+FN("time(cpu-seconds)", RLIMIT_CPU, 1
+
+>f|RLIMIT_FSIZE
+FN("file(blocks)", RLIMIT_FSIZE, 512
+
+>c|RLIMIT_CORE
+FN("coredump(blocks)", RLIMIT_CORE, 512
+
+>d|RLIMIT_DATA
+FN("data(KiB)", RLIMIT_DATA, 1024
+
+>s|RLIMIT_STACK
+FN("stack(KiB)", RLIMIT_STACK, 1024
+
+>l|RLIMIT_MEMLOCK
+FN("lockedmem(KiB)", RLIMIT_MEMLOCK, 1024
+
+>n|RLIMIT_NOFILE
+FN("nofiles(descriptors)", RLIMIT_NOFILE, 1
+
+>p|RLIMIT_NPROC
+FN("processes", RLIMIT_NPROC, 1
+
+>w|RLIMIT_SWAP
+FN("swap(KiB)", RLIMIT_SWAP, 1024
+
+>T|RLIMIT_TIME
+FN("humantime(seconds)", RLIMIT_TIME, 1
+
+>V|RLIMIT_NOVMON
+FN("vnodemonitors", RLIMIT_NOVMON, 1
+
+>i|RLIMIT_SIGPENDING
+FN("sigpending", RLIMIT_SIGPENDING, 1
+
+>q|RLIMIT_MSGQUEUE
+FN("msgqueue(bytes)", RLIMIT_MSGQUEUE, 1
+
+>M|RLIMIT_AIO_MEM
+FN("AIOlockedmem(KiB)", RLIMIT_AIO_MEM, 1024
+
+>O|RLIMIT_AIO_OPS
+FN("AIOoperations", RLIMIT_AIO_OPS, 1
+
+>C|RLIMIT_TCACHE
+FN("cachedthreads", RLIMIT_TCACHE, 1
+
+>B|RLIMIT_SBSIZE
+FN("sockbufsiz(KiB)", RLIMIT_SBSIZE, 1024
+
+>P|RLIMIT_PTHREAD
+FN("threadsperprocess", RLIMIT_PTHREAD, 1
+
+>e|RLIMIT_NICE
+FN("maxnice", RLIMIT_NICE, 1
+
+>r|RLIMIT_RTPRIO
+FN("maxrtprio", RLIMIT_RTPRIO, 1
+
+>m|ULIMIT_M_IS_RSS
+FN("resident-set(KiB)", RLIMIT_RSS, 1024
+>m|ULIMIT_M_IS_VMEM
+FN("memory(KiB)", RLIMIT_VMEM, 1024
+
+>v|ULIMIT_V_IS_VMEM
+FN("virtual-memory(KiB)", RLIMIT_VMEM, 1024
+>v|ULIMIT_V_IS_AS
+FN("address-space(KiB)", RLIMIT_AS, 1024
+
+|RLIMITS_OPTCS
diff --git a/src/sh.h b/src/sh.h
index 5a95190..b3d1c0b 100644
--- a/src/sh.h
+++ b/src/sh.h
@@ -1,16 +1,16 @@
-/* $OpenBSD: sh.h,v 1.31 2012/09/10 01:25:30 tedu Exp $ */
+/* $OpenBSD: sh.h,v 1.33 2013/12/18 13:53:12 millert Exp $ */
/* $OpenBSD: shf.h,v 1.6 2005/12/11 18:53:51 deraadt Exp $ */
/* $OpenBSD: table.h,v 1.8 2012/02/19 07:52:30 otto Exp $ */
/* $OpenBSD: tree.h,v 1.10 2005/03/28 21:28:22 deraadt Exp $ */
/* $OpenBSD: expand.h,v 1.6 2005/03/30 17:16:37 deraadt Exp $ */
/* $OpenBSD: lex.h,v 1.13 2013/03/03 19:11:34 guenther Exp $ */
-/* $OpenBSD: proto.h,v 1.34 2012/06/27 07:17:19 otto Exp $ */
+/* $OpenBSD: proto.h,v 1.35 2013/09/04 15:49:19 millert Exp $ */
/* $OpenBSD: c_test.h,v 1.4 2004/12/20 11:34:26 otto Exp $ */
/* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */
/*-
* Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@@ -108,12 +108,12 @@
#undef __attribute__
#if HAVE_ATTRIBUTE_BOUNDED
-#define MKSH_A_BOUNDED(x,y,z) __attribute__((__bounded__ (x, y, z)))
+#define MKSH_A_BOUNDED(x,y,z) __attribute__((__bounded__(x, y, z)))
#else
#define MKSH_A_BOUNDED(x,y,z) /* nothing */
#endif
#if HAVE_ATTRIBUTE_FORMAT
-#define MKSH_A_FORMAT(x,y,z) __attribute__((__format__ (x, y, z)))
+#define MKSH_A_FORMAT(x,y,z) __attribute__((__format__(x, y, z)))
#else
#define MKSH_A_FORMAT(x,y,z) /* nothing */
#endif
@@ -122,6 +122,11 @@
#else
#define MKSH_A_NORETURN /* nothing */
#endif
+#if HAVE_ATTRIBUTE_PURE
+#define MKSH_A_PURE __attribute__((__pure__))
+#else
+#define MKSH_A_PURE /* nothing */
+#endif
#if HAVE_ATTRIBUTE_UNUSED
#define MKSH_A_UNUSED __attribute__((__unused__))
#else
@@ -164,9 +169,9 @@
#endif
#ifdef EXTERN
-__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.667 2013/08/14 20:26:19 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.697 2014/10/07 15:22:17 tg Exp $");
#endif
-#define MKSH_VERSION "R48 2013/08/14"
+#define MKSH_VERSION "R50 2014/10/07"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
@@ -298,7 +303,7 @@ struct rusage {
#define ksh_isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
#define ksh_tolower(c) (((c) >= 'A') && ((c) <= 'Z') ? (c) - 'A' + 'a' : (c))
#define ksh_toupper(c) (((c) >= 'a') && ((c) <= 'z') ? (c) - 'a' + 'A' : (c))
-#define ksh_isdash(s) (((s) != NULL) && ((s)[0] == '-') && ((s)[1] == '\0'))
+#define ksh_isdash(s) (((s)[0] == '-') && ((s)[1] == '\0'))
#define ksh_isspace(c) ((((c) >= 0x09) && ((c) <= 0x0D)) || ((c) == 0x20))
#define ksh_min(x,y) ((x) < (y) ? (x) : (y))
#define ksh_max(x,y) ((x) > (y) ? (x) : (y))
@@ -337,7 +342,17 @@ struct rusage {
#define NSIG (SIGMAX+1)
#elif defined(_SIGMAX)
#define NSIG (_SIGMAX+1)
+#else
+# error Please have your platform define NSIG.
+#define NSIG 64
+#endif
#endif
+
+/* get rid of this (and awk/printf(1) in Build.sh) later */
+#if (NSIG < 1)
+# error Your NSIG value is not positive.
+#unset NSIG
+#define NSIG 64
#endif
@@ -396,6 +411,10 @@ extern int __cdecl setegid(gid_t);
#endif
#endif
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
#ifdef MKSH__NO_SYMLINK
#undef S_ISLNK
#define S_ISLNK(m) (/* CONSTCOND */ 0)
@@ -414,12 +433,8 @@ extern int __cdecl setegid(gid_t);
#define mksh_tcset(fd,st) ioctl((fd), TCSETAW, (st))
#endif
-/* remove redundancies */
-
-#if defined(MirBSD) && (MirBSD >= 0x0AB3) && !defined(MKSH_OPTSTATIC)
-#define MKSH_mirbsd_wcwidth
-#define utf_wcwidth(i) wcwidth((__WCHAR_TYPE__)i)
-extern int wcwidth(__WCHAR_TYPE__);
+#ifndef ISTRIP
+#define ISTRIP 0
#endif
@@ -518,7 +533,7 @@ char *ucstrstr(char *, const char *);
#define mkssert(e) do { } while (/* CONSTCOND */ 0)
#endif
-#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 481)
+#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 504)
#error Must run Build.sh to compile this.
extern void thiswillneverbedefinedIhope(void);
int
@@ -660,7 +675,7 @@ EXTERN Area aperm; /* permanent object space */
*/
enum sh_flag {
#define SHFLAGS_ENUMS
-#include "sh_flags.h"
+#include "sh_flags.gen"
FNFLAGS /* (place holder: how many flags are there) */
};
@@ -1163,11 +1178,11 @@ EXTERN struct tbl vtemp;
#define arrayindex(vp) ((unsigned long)((vp)->flag & AINDEX ? \
(vp)->ua.index : 0))
-EXTERN enum {
+enum namerefflag {
SRF_NOP,
SRF_ENABLE,
SRF_DISABLE
-} set_refflag E_INIT(SRF_NOP);
+};
/* command types */
#define CNONE 0 /* undefined */
@@ -1380,22 +1395,8 @@ struct ioword {
#define DOTEMP BIT(8) /* dito: in word part of ${..[%#=?]..} */
#define DOVACHECK BIT(9) /* var assign check (for typeset, set, etc) */
#define DOMARKDIRS BIT(10) /* force markdirs behaviour */
-#if !defined(MKSH_SMALL)
#define DOTCOMEXEC BIT(11) /* not an eval flag, used by sh -c hack */
-#endif
-
-/*
- * The arguments of [[ .. ]] expressions are kept in t->args[] and flags
- * indicating how the arguments have been munged are kept in t->vars[].
- * The contents of t->vars[] are stuffed strings (so they can be treated
- * like all other t->vars[]) in which the second character is the one that
- * is examined. The DB_* defines are the values for these second characters.
- */
-#define DB_NORM 1 /* normal argument */
-#define DB_OR 2 /* || -> -o conversion */
-#define DB_AND 3 /* && -> -a conversion */
-#define DB_BE 4 /* an inserted -BE */
-#define DB_PAT 5 /* a pattern argument */
+#define DOASNFIELD BIT(12) /* is assignment, change field handling */
#define X_EXTRA 20 /* this many extra bytes in X string */
@@ -1426,7 +1427,7 @@ typedef char *XStringP;
#define XcheckN(xs, xp, n) do { \
ssize_t more = ((xp) + (n)) - (xs).end; \
if (more > 0) \
- (xp) = Xcheck_grow(&(xs), (xp), more); \
+ (xp) = Xcheck_grow(&(xs), (xp), (size_t)more); \
} while (/* CONSTCOND */ 0)
/* check for overflow, expand string */
@@ -1526,9 +1527,7 @@ struct source {
#define SF_ALIASEND BIT(2) /* faking space at end of alias */
#define SF_TTY BIT(3) /* type == SSTDIN & it is a tty */
#define SF_HASALIAS BIT(4) /* u.tblp valid (SALIAS, SEOF) */
-#if !defined(MKSH_SMALL)
#define SF_MAYEXEC BIT(5) /* special sh -c optimisation hack */
-#endif
typedef union {
int i;
@@ -1587,6 +1586,7 @@ typedef union {
#undef CTRL
#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
#define UNCTRL(x) ((x) ^ 0x40) /* ASCII */
+#define ISCTRL(x) (((signed char)((uint8_t)(x) + 1)) < 33)
#define IDENT 64
@@ -1614,48 +1614,6 @@ EXTERN struct timeval j_usrtime, j_systime;
} while (/* CONSTCOND */ 0)
-/* NZAAT hash based on Bob Jenkins' one-at-a-time hash */
-
-/* From: src/kern/include/nzat.h,v 1.2 2011/07/18 00:35:40 tg Exp $ */
-
-#define NZATInit(h) do { \
- (h) = 0; \
-} while (/* CONSTCOND */ 0)
-
-#define NZATUpdateByte(h,b) do { \
- (h) += (uint8_t)(b); \
- ++(h); \
- (h) += (h) << 10; \
- (h) ^= (h) >> 6; \
-} while (/* CONSTCOND */ 0)
-
-#define NZATUpdateMem(h,p,z) do { \
- register const uint8_t *NZATUpdateMem_p; \
- register size_t NZATUpdateMem_z = (z); \
- \
- NZATUpdateMem_p = (const void *)(p); \
- while (NZATUpdateMem_z--) \
- NZATUpdateByte((h), *NZATUpdateMem_p++); \
-} while (/* CONSTCOND */ 0)
-
-#define NZATUpdateString(h,s) do { \
- register const char *NZATUpdateString_s; \
- register uint8_t NZATUpdateString_c; \
- \
- NZATUpdateString_s = (const void *)(s); \
- while ((NZATUpdateString_c = *NZATUpdateString_s++)) \
- NZATUpdateByte((h), NZATUpdateString_c); \
-} while (/* CONSTCOND */ 0)
-
-#define NZAATFinish(h) do { \
- (h) += (h) << 10; \
- (h) ^= (h) >> 6; \
- (h) += (h) << 3; \
- (h) ^= (h) >> 11; \
- (h) += (h) << 15; \
-} while (/* CONSTCOND */ 0)
-
-
/* lalloc.c */
void ainit(Area *);
void afreeall(Area *);
@@ -1706,12 +1664,10 @@ int v_evaluate(struct tbl *, const char *, volatile int, bool);
size_t utf_mbtowc(unsigned int *, const char *);
size_t utf_wctomb(char *, unsigned int);
int utf_widthadj(const char *, const char **);
-size_t utf_mbswidth(const char *);
-const char *utf_skipcols(const char *, int);
-size_t utf_ptradj(const char *);
-#ifndef MKSH_mirbsd_wcwidth
-int utf_wcwidth(unsigned int);
-#endif
+size_t utf_mbswidth(const char *) MKSH_A_PURE;
+const char *utf_skipcols(const char *, int) MKSH_A_PURE;
+size_t utf_ptradj(const char *) MKSH_A_PURE;
+int utf_wcwidth(unsigned int) MKSH_A_PURE;
int ksh_access(const char *, int);
struct tbl *tempvar(void);
/* funcs.c */
@@ -1779,10 +1735,10 @@ void sethistsize(mksh_ari_t);
void sethistfile(const char *);
#endif
#if !defined(MKSH_NO_CMDLINE_EDITING) && !MKSH_S_NOVI
-char **histpos(void);
+char **histpos(void) MKSH_A_PURE;
int histnum(int);
#endif
-int findhist(int, int, const char *, int);
+int findhist(int, int, const char *, bool) MKSH_A_PURE;
char **hist_get_newest(bool);
void inittraps(void);
void alarm_init(void);
@@ -1818,6 +1774,9 @@ int j_kill(const char *, int);
#ifndef MKSH_UNEMPLOYED
int j_resume(const char *, int);
#endif
+#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
+void j_suspend(void);
+#endif
int j_jobs(const char *, int, int);
void j_notify(void);
pid_t j_async(void);
@@ -1895,15 +1854,15 @@ void DF(const char *, ...)
/* misc.c */
void setctypes(const char *, int);
void initctypes(void);
-size_t option(const char *);
+size_t option(const char *) MKSH_A_PURE;
char *getoptions(void);
void change_flag(enum sh_flag, int, bool);
void change_xtrace(unsigned char, bool);
int parse_args(const char **, int, bool *);
int getn(const char *, int *);
int gmatchx(const char *, const char *, bool);
-int has_globbing(const char *, const char *);
-int xstrcmp(const void *, const void *);
+int has_globbing(const char *, const char *) MKSH_A_PURE;
+int xstrcmp(const void *, const void *) MKSH_A_PURE;
void ksh_getopt_reset(Getopt *, int);
int ksh_getopt(const char **, Getopt *, const char *);
void print_value_quoted(struct shf *, const char *);
@@ -1995,19 +1954,21 @@ void setint(struct tbl *, mksh_ari_t);
void setint_n(struct tbl *, mksh_ari_t, int);
struct tbl *typeset(const char *, uint32_t, uint32_t, int, int);
void unset(struct tbl *, int);
-const char *skip_varname(const char *, int);
-const char *skip_wdvarname(const char *, bool);
-int is_wdvarname(const char *, bool);
-int is_wdvarassign(const char *);
+const char *skip_varname(const char *, bool) MKSH_A_PURE;
+const char *skip_wdvarname(const char *, bool) MKSH_A_PURE;
+int is_wdvarname(const char *, bool) MKSH_A_PURE;
+int is_wdvarassign(const char *) MKSH_A_PURE;
struct tbl *arraysearch(struct tbl *, uint32_t);
char **makenv(void);
void change_winsz(void);
-size_t array_ref_len(const char *);
+size_t array_ref_len(const char *) MKSH_A_PURE;
char *arrayname(const char *);
mksh_uari_t set_array(const char *, bool, const char **);
-uint32_t hash(const void *);
+uint32_t hash(const void *) MKSH_A_PURE;
+uint32_t chvt_rndsetup(const void *, size_t) MKSH_A_PURE;
mksh_ari_t rndget(void);
void rndset(unsigned long);
+void rndpush(const void *);
enum Test_op {
/* non-operator */
@@ -2058,10 +2019,11 @@ typedef struct test_env {
extern const char * const dbtest_tokens[];
-Test_op test_isop(Test_meta, const char *);
+Test_op test_isop(Test_meta, const char *) MKSH_A_PURE;
int test_eval(Test_env *, Test_op, const char *, const char *, bool);
int test_parse(Test_env *);
+/* tty_fd is not opened O_BINARY, it's thus never read/written */
EXTERN int tty_fd E_INIT(-1); /* dup'd tty file descriptor */
EXTERN bool tty_devtty; /* true if tty_fd is from /dev/tty */
EXTERN mksh_ttyst tty_state; /* saved tty state */
diff --git a/src/sh_flags.gen b/src/sh_flags.gen
new file mode 100644
index 0000000..cff2e87
--- /dev/null
+++ b/src/sh_flags.gen
@@ -0,0 +1,136 @@
+#ifndef SHFLAGS_OPTCS
+#if defined(SHFLAGS_DEFNS)
+__RCSID("$MirOS: src/bin/mksh/sh_flags.opt,v 1.2 2014/06/09 12:28:19 tg Exp $");
+#define FN(sname,cname,flags,ochar) static const struct { /* character flag (if any) */ char c; /* OF_* */ unsigned char optflags; /* long name of option */ char name[sizeof(sname)]; } shoptione_ ## cname = { ochar, flags, sname };
+#elif defined(SHFLAGS_ENUMS)
+#define FN(sname,cname,flags,ochar) cname,
+#define F0(sname,cname,flags,ochar) cname = 0,
+#elif defined(SHFLAGS_ITEMS)
+#define FN(sname,cname,flags,ochar) ((const char *)(&shoptione_ ## cname)) + 2,
+#endif
+#ifndef F0
+#define F0 FN
+#endif
+F0("allexport", FEXPORT, OF_ANY, 'a')
+#if HAVE_NICE
+FN("bgnice", FBGNICE, OF_ANY, 0)
+#endif
+FN("braceexpand", FBRACEEXPAND, OF_ANY, 0)
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("emacs", FEMACS, OF_ANY, 0)
+#endif
+FN("errexit", FERREXIT, OF_ANY, 'e')
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("gmacs", FGMACS, OF_ANY, 0)
+#endif
+FN("ignoreeof", FIGNOREEOF, OF_ANY, 0)
+FN("inherit-xtrace", FXTRACEREC, OF_ANY, 0)
+#ifndef SHFLAGS_NOT_CMD
+FN("interactive", FTALKING, OF_CMDLINE, 'i')
+#endif
+FN("keyword", FKEYWORD, OF_ANY, 'k')
+#ifndef SHFLAGS_NOT_CMD
+FN("login", FLOGIN, OF_CMDLINE, 'l')
+#endif
+FN("markdirs", FMARKDIRS, OF_ANY, 'X')
+#ifndef MKSH_UNEMPLOYED
+FN("monitor", FMONITOR, OF_ANY, 'm')
+#endif
+FN("noclobber", FNOCLOBBER, OF_ANY, 'C')
+FN("noexec", FNOEXEC, OF_ANY, 'n')
+FN("noglob", FNOGLOB, OF_ANY, 'f')
+FN("nohup", FNOHUP, OF_ANY, 0)
+FN("nolog", FNOLOG, OF_ANY, 0)
+#ifndef MKSH_UNEMPLOYED
+FN("notify", FNOTIFY, OF_ANY, 'b')
+#endif
+FN("nounset", FNOUNSET, OF_ANY, 'u')
+FN("physical", FPHYSICAL, OF_ANY, 0)
+FN("pipefail", FPIPEFAIL, OF_ANY, 0)
+FN("posix", FPOSIX, OF_ANY, 0)
+FN("privileged", FPRIVILEGED, OF_ANY, 'p')
+#ifndef SHFLAGS_NOT_CMD
+FN("restricted", FRESTRICTED, OF_CMDLINE, 'r')
+#endif
+FN("sh", FSH, OF_ANY, 0)
+#ifndef SHFLAGS_NOT_CMD
+FN("stdin", FSTDIN, OF_CMDLINE, 's')
+#endif
+FN("trackall", FTRACKALL, OF_ANY, 'h')
+FN("utf8-mode", FUNICODE, OF_ANY, 'U')
+FN("verbose", FVERBOSE, OF_ANY, 'v')
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi", FVI, OF_ANY, 0)
+#endif
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi-esccomplete", FVIESCCOMPLETE, OF_ANY, 0)
+#endif
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi-tabcomplete", FVITABCOMPLETE, OF_ANY, 0)
+#endif
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("viraw", FVIRAW, OF_ANY, 0)
+#endif
+FN("xtrace", FXTRACE, OF_ANY, 'x')
+#ifndef SHFLAGS_NOT_CMD
+FN("", FCOMMAND, OF_CMDLINE, 'c')
+#endif
+FN("", FAS_BUILTIN, OF_INTERNAL, 0)
+FN("", FTALKING_I, OF_INTERNAL, 0)
+#undef F0
+#undef FN
+#undef SHFLAGS_DEFNS
+#undef SHFLAGS_ENUMS
+#undef SHFLAGS_ITEMS
+#else
+#ifndef SHFLAGS_NOT_SET
+"A:"
+#endif
+"a"
+#ifndef MKSH_UNEMPLOYED
+"b"
+#endif
+"C"
+#ifndef SHFLAGS_NOT_CMD
+"c"
+#endif
+"e"
+"f"
+"h"
+#ifndef SHFLAGS_NOT_CMD
+"i"
+#endif
+"k"
+#ifndef SHFLAGS_NOT_CMD
+"l"
+#endif
+#ifndef MKSH_UNEMPLOYED
+"m"
+#endif
+"n"
+#ifndef SHFLAGS_NOT_CMD
+"o:"
+#endif
+#ifndef SHFLAGS_NOT_SET
+"o;"
+#endif
+"p"
+#ifndef SHFLAGS_NOT_CMD
+"r"
+#endif
+#ifndef SHFLAGS_NOT_CMD
+"s"
+#endif
+#ifndef SHFLAGS_NOT_SET
+"s"
+#endif
+#ifndef SHFLAGS_NOT_CMD
+"T:"
+#endif
+"U"
+"u"
+"v"
+"X"
+"x"
+#undef SHFLAGS_OPTCS
+#endif
diff --git a/src/sh_flags.h b/src/sh_flags.h
deleted file mode 100644
index 3e4cf56..0000000
--- a/src/sh_flags.h
+++ /dev/null
@@ -1,166 +0,0 @@
-#if defined(SHFLAGS_DEFNS)
-__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.16 2013/08/11 14:57:11 tg Exp $");
-#define FN(sname,cname,ochar,flags) \
- static const struct { \
- /* character flag (if any) */ \
- char c; \
- /* OF_* */ \
- unsigned char optflags; \
- /* long name of option */ \
- char name[sizeof(sname)]; \
- } shoptione_ ## cname = { \
- ochar, flags, sname \
- };
-#elif defined(SHFLAGS_ENUMS)
-#define FN(sname,cname,ochar,flags) cname,
-#define F0(sname,cname,ochar,flags) cname = 0,
-#elif defined(SHFLAGS_ITEMS)
-#define FN(sname,cname,ochar,flags) \
- ((const char *)(&shoptione_ ## cname)) + 2,
-#endif
-
-#ifndef F0
-#define F0 FN
-#endif
-
-/*
- * special cases (see parse_args()): -A, -o, -s
- *
- * options are sorted by their longnames
- */
-
-/* -a all new parameters are created with the export attribute */
-F0("allexport", FEXPORT, 'a', OF_ANY)
-
-#if HAVE_NICE
-/* ./. bgnice */
-FN("bgnice", FBGNICE, 0, OF_ANY)
-#endif
-
-/* ./. enable {} globbing (non-standard) */
-FN("braceexpand", FBRACEEXPAND, 0, OF_ANY)
-
-#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
-/* ./. Emacs command line editing mode */
-FN("emacs", FEMACS, 0, OF_ANY)
-#endif
-
-/* -e quit on error */
-FN("errexit", FERREXIT, 'e', OF_ANY)
-
-#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
-/* ./. Emacs command line editing mode, gmacs variant */
-FN("gmacs", FGMACS, 0, OF_ANY)
-#endif
-
-/* ./. reading EOF does not exit */
-FN("ignoreeof", FIGNOREEOF, 0, OF_ANY)
-
-/* ./. inherit -x flag */
-FN("inherit-xtrace", FXTRACEREC, 0, OF_ANY)
-
-/* -i interactive shell */
-FN("interactive", FTALKING, 'i', OF_CMDLINE)
-
-/* -k name=value are recognised anywhere */
-FN("keyword", FKEYWORD, 'k', OF_ANY)
-
-/* -l login shell */
-FN("login", FLOGIN, 'l', OF_CMDLINE)
-
-/* -X mark dirs with / in file name completion */
-FN("markdirs", FMARKDIRS, 'X', OF_ANY)
-
-#ifndef MKSH_UNEMPLOYED
-/* -m job control monitoring */
-FN("monitor", FMONITOR, 'm', OF_ANY)
-#endif
-
-/* -C don't overwrite existing files */
-FN("noclobber", FNOCLOBBER, 'C', OF_ANY)
-
-/* -n don't execute any commands */
-FN("noexec", FNOEXEC, 'n', OF_ANY)
-
-/* -f don't do file globbing */
-FN("noglob", FNOGLOB, 'f', OF_ANY)
-
-/* ./. don't kill running jobs when login shell exits */
-FN("nohup", FNOHUP, 0, OF_ANY)
-
-/* ./. don't save functions in history (no effect) */
-FN("nolog", FNOLOG, 0, OF_ANY)
-
-#ifndef MKSH_UNEMPLOYED
-/* -b asynchronous job completion notification */
-FN("notify", FNOTIFY, 'b', OF_ANY)
-#endif
-
-/* -u using an unset variable is an error */
-FN("nounset", FNOUNSET, 'u', OF_ANY)
-
-/* ./. don't do logical cds/pwds (non-standard) */
-FN("physical", FPHYSICAL, 0, OF_ANY)
-
-/* ./. errorlevel of a pipeline is the rightmost nonzero value */
-FN("pipefail", FPIPEFAIL, 0, OF_ANY)
-
-/* ./. adhere more closely to POSIX even when undesirable */
-FN("posix", FPOSIX, 0, OF_ANY)
-
-/* -p use suid_profile; privileged shell */
-FN("privileged", FPRIVILEGED, 'p', OF_ANY)
-
-/* -r restricted shell */
-FN("restricted", FRESTRICTED, 'r', OF_CMDLINE)
-
-/* ./. kludge mode for better compat with traditional sh (OS-specific) */
-FN("sh", FSH, 0, OF_ANY)
-
-/* -s (invocation) parse stdin (pseudo non-standard) */
-FN("stdin", FSTDIN, 's', OF_CMDLINE)
-
-/* -h create tracked aliases for all commands */
-FN("trackall", FTRACKALL, 'h', OF_ANY)
-
-/* -U enable UTF-8 processing (non-standard) */
-FN("utf8-mode", FUNICODE, 'U', OF_ANY)
-
-/* -v echo input */
-FN("verbose", FVERBOSE, 'v', OF_ANY)
-
-#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
-/* ./. Vi command line editing mode */
-FN("vi", FVI, 0, OF_ANY)
-
-/* ./. enable ESC as file name completion character (non-standard) */
-FN("vi-esccomplete", FVIESCCOMPLETE, 0, OF_ANY)
-
-/* ./. enable Tab as file name completion character (non-standard) */
-FN("vi-tabcomplete", FVITABCOMPLETE, 0, OF_ANY)
-
-/* ./. always read in raw mode (no effect) */
-FN("viraw", FVIRAW, 0, OF_ANY)
-#endif
-
-/* -x execution trace (display commands as they are run) */
-FN("xtrace", FXTRACE, 'x', OF_ANY)
-
-/* -c (invocation) execute specified command */
-FN("", FCOMMAND, 'c', OF_CMDLINE)
-
-/*
- * anonymous flags: used internally by shell only (not visible to user)
- */
-
-/* ./. direct builtin call (divined from argv[0] multi-call binary) */
-FN("", FAS_BUILTIN, 0, OF_INTERNAL)
-
-/* ./. (internal) initial shell was interactive */
-FN("", FTALKING_I, 0, OF_INTERNAL)
-
-#undef FN
-#undef F0
-#undef SHFLAGS_DEFNS
-#undef SHFLAGS_ENUMS
-#undef SHFLAGS_ITEMS
diff --git a/src/sh_flags.opt b/src/sh_flags.opt
new file mode 100644
index 0000000..99e4a22
--- /dev/null
+++ b/src/sh_flags.opt
@@ -0,0 +1,179 @@
+@SHFLAGS_DEFNS
+__RCSID("$MirOS: src/bin/mksh/sh_flags.opt,v 1.2 2014/06/09 12:28:19 tg Exp $");
+#define FN(sname,cname,flags,ochar) static const struct { /* character flag (if any) */ char c; /* OF_* */ unsigned char optflags; /* long name of option */ char name[sizeof(sname)]; } shoptione_ ## cname = { ochar, flags, sname };
+@SHFLAGS_ENUMS
+#define FN(sname,cname,flags,ochar) cname,
+#define F0(sname,cname,flags,ochar) cname = 0,
+@SHFLAGS_ITEMS
+#define FN(sname,cname,flags,ochar) ((const char *)(&shoptione_ ## cname)) + 2,
+@@
+
+/* special cases */
+
+<o:|!SHFLAGS_NOT_CMD
+<T:|!SHFLAGS_NOT_CMD
+<A:|!SHFLAGS_NOT_SET
+<o;|!SHFLAGS_NOT_SET
+<s|!SHFLAGS_NOT_SET
+
+/*
+ * options are sorted by their longnames
+ */
+
+/* -a all new parameters are created with the export attribute */
+>a|
+F0("allexport", FEXPORT, OF_ANY
+
+/* ./. bgnice */
+>| HAVE_NICE
+FN("bgnice", FBGNICE, OF_ANY
+
+/* ./. enable {} globbing (non-standard) */
+>|
+FN("braceexpand", FBRACEEXPAND, OF_ANY
+
+/* ./. Emacs command line editing mode */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("emacs", FEMACS, OF_ANY
+
+/* -e quit on error */
+>e|
+FN("errexit", FERREXIT, OF_ANY
+
+/* ./. Emacs command line editing mode, gmacs variant */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("gmacs", FGMACS, OF_ANY
+
+/* ./. reading EOF does not exit */
+>|
+FN("ignoreeof", FIGNOREEOF, OF_ANY
+
+/* ./. inherit -x flag */
+>|
+FN("inherit-xtrace", FXTRACEREC, OF_ANY
+
+/* -i interactive shell */
+>i|!SHFLAGS_NOT_CMD
+FN("interactive", FTALKING, OF_CMDLINE
+
+/* -k name=value are recognised anywhere */
+>k|
+FN("keyword", FKEYWORD, OF_ANY
+
+/* -l login shell */
+>l|!SHFLAGS_NOT_CMD
+FN("login", FLOGIN, OF_CMDLINE
+
+/* -X mark dirs with / in file name completion */
+>X|
+FN("markdirs", FMARKDIRS, OF_ANY
+
+/* -m job control monitoring */
+>m|!MKSH_UNEMPLOYED
+FN("monitor", FMONITOR, OF_ANY
+
+/* -C don't overwrite existing files */
+>C|
+FN("noclobber", FNOCLOBBER, OF_ANY
+
+/* -n don't execute any commands */
+>n|
+FN("noexec", FNOEXEC, OF_ANY
+
+/* -f don't do file globbing */
+>f|
+FN("noglob", FNOGLOB, OF_ANY
+
+/* ./. don't kill running jobs when login shell exits */
+>|
+FN("nohup", FNOHUP, OF_ANY
+
+/* ./. don't save functions in history (no effect) */
+>|
+FN("nolog", FNOLOG, OF_ANY
+
+/* -b asynchronous job completion notification */
+>b|!MKSH_UNEMPLOYED
+FN("notify", FNOTIFY, OF_ANY
+
+/* -u using an unset variable is an error */
+>u|
+FN("nounset", FNOUNSET, OF_ANY
+
+/* ./. don't do logical cds/pwds (non-standard) */
+>|
+FN("physical", FPHYSICAL, OF_ANY
+
+/* ./. errorlevel of a pipeline is the rightmost nonzero value */
+>|
+FN("pipefail", FPIPEFAIL, OF_ANY
+
+/* ./. adhere more closely to POSIX even when undesirable */
+>|
+FN("posix", FPOSIX, OF_ANY
+
+/* -p privileged shell (suid) */
+>p|
+FN("privileged", FPRIVILEGED, OF_ANY
+
+/* -r restricted shell */
+>r|!SHFLAGS_NOT_CMD
+FN("restricted", FRESTRICTED, OF_CMDLINE
+
+/* ./. kludge mode for better compat with traditional sh (OS-specific) */
+>|
+FN("sh", FSH, OF_ANY
+
+/* -s (invocation) parse stdin (pseudo non-standard) */
+>s|!SHFLAGS_NOT_CMD
+FN("stdin", FSTDIN, OF_CMDLINE
+
+/* -h create tracked aliases for all commands */
+>h|
+FN("trackall", FTRACKALL, OF_ANY
+
+/* -U enable UTF-8 processing (non-standard) */
+>U|
+FN("utf8-mode", FUNICODE, OF_ANY
+
+/* -v echo input */
+>v|
+FN("verbose", FVERBOSE, OF_ANY
+
+/* ./. Vi command line editing mode */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi", FVI, OF_ANY
+
+/* ./. enable ESC as file name completion character (non-standard) */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi-esccomplete", FVIESCCOMPLETE, OF_ANY
+
+/* ./. enable Tab as file name completion character (non-standard) */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi-tabcomplete", FVITABCOMPLETE, OF_ANY
+
+/* ./. always read in raw mode (no effect) */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("viraw", FVIRAW, OF_ANY
+
+/* -x execution trace (display commands as they are run) */
+>x|
+FN("xtrace", FXTRACE, OF_ANY
+
+/* -c (invocation) execute specified command */
+>c|!SHFLAGS_NOT_CMD
+FN("", FCOMMAND, OF_CMDLINE
+
+/*
+ * anonymous flags: used internally by shell only (not visible to user
+ */
+
+/* ./. direct builtin call (divined from argv[0] multi-call binary) */
+>|
+FN("", FAS_BUILTIN, OF_INTERNAL
+
+/* ./. (internal) initial shell was interactive */
+>|
+FN("", FTALKING_I, OF_INTERNAL
+
+|SHFLAGS_OPTCS
diff --git a/src/shf.c b/src/shf.c
index e8ec14a..33e89bd 100644
--- a/src/shf.c
+++ b/src/shf.c
@@ -25,7 +25,7 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.61 2013/07/21 18:36:03 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.62 2013/10/09 11:59:30 tg Exp $");
/* flags to shf_emptybuf() */
#define EB_READSW 0x01 /* about to switch to reading */
@@ -62,7 +62,7 @@ shf_open(const char *name, int oflags, int mode, int sflags)
shf->flags = SHF_ALLOCS;
/* Rest filled in by reopen. */
- fd = open(name, oflags, mode);
+ fd = open(name, oflags | O_BINARY, mode);
if (fd < 0) {
eno = errno;
afree(shf, shf->areap);
diff --git a/src/signames.inc b/src/signames.inc
new file mode 100644
index 0000000..07811fd
--- /dev/null
+++ b/src/signames.inc
@@ -0,0 +1,31 @@
+ { "ABRT", 6 },
+ { "FPE", 8 },
+ { "ILL", 4 },
+ { "INT", 2 },
+ { "SEGV", 11 },
+ { "TERM", 15 },
+ { "ALRM", 14 },
+ { "BUS", 7 },
+ { "CHLD", 17 },
+ { "CONT", 18 },
+ { "HUP", 1 },
+ { "KILL", 9 },
+ { "PIPE", 13 },
+ { "QUIT", 3 },
+ { "STOP", 19 },
+ { "TSTP", 20 },
+ { "TTIN", 21 },
+ { "TTOU", 22 },
+ { "USR1", 10 },
+ { "USR2", 12 },
+ { "POLL", 29 },
+ { "PROF", 27 },
+ { "SYS", 31 },
+ { "TRAP", 5 },
+ { "URG", 23 },
+ { "VTALRM", 26 },
+ { "XCPU", 24 },
+ { "XFSZ", 25 },
+ { "WINCH", 28 },
+ { "PWR", 30 },
+ { "STKFLT", 16 },
diff --git a/src/strlcpy.c b/src/strlcpy.c
index 53f9130..c0ebfd5 100644
--- a/src/strlcpy.c
+++ b/src/strlcpy.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2006, 2008, 2009
+ * Copyright (c) 2006, 2008, 2009, 2013
* Thorsten Glaser <tg@mirbsd.org>
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
@@ -18,13 +18,14 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/strlcpy.c,v 1.7 2009/06/10 18:12:50 tg Rel $");
+__RCSID("$MirOS: src/bin/mksh/strlcpy.c,v 1.8 2013/11/05 22:10:15 tg Exp $");
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
+#undef strlcpy
size_t
strlcpy(char *dst, const char *src, size_t siz)
{
diff --git a/src/syn.c b/src/syn.c
index 5c07d51..6a544df 100644
--- a/src/syn.c
+++ b/src/syn.c
@@ -2,7 +2,7 @@
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* 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/syn.c,v 1.92 2013/06/03 22:28:17 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94 2014/01/05 21:57:29 tg Exp $");
struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */
@@ -59,7 +59,7 @@ static void syntaxerr(const char *) MKSH_A_NORETURN;
static void nesting_push(struct nesting_state *, int);
static void nesting_pop(struct nesting_state *);
static int assign_command(const char *);
-static int inalias(struct source *);
+static int inalias(struct source *) MKSH_A_PURE;
static Test_op dbtestp_isa(Test_env *, Test_meta);
static const char *dbtestp_getopnd(Test_env *, Test_op, bool);
static int dbtestp_eval(Test_env *, Test_op, const char *,
@@ -976,7 +976,7 @@ static Test_op
dbtestp_isa(Test_env *te, Test_meta meta)
{
int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN));
- int uqword;
+ bool uqword;
char *save = NULL;
Test_op ret = TO_NONOP;
diff --git a/src/tree.c b/src/tree.c
index dcbd7a1..8026f8b 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -23,7 +23,7 @@
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.71 2013/07/26 20:33:24 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.72 2013/09/24 20:19:45 tg Exp $");
#define INDENT 8
@@ -778,15 +778,16 @@ vistree(char *dst, size_t sz, struct op *t)
if (--sz == 0 || (c = (unsigned char)(*cp++)) == 0)
/* NUL or not enough free space */
goto vist_out;
- if ((c & 0x60) == 0 || (c & 0x7F) == 0x7F) {
+ if (ISCTRL(c & 0x7F)) {
/* C0 or C1 control character or DEL */
if (--sz == 0)
/* not enough free space for two chars */
goto vist_out;
*dst++ = (c & 0x80) ? '$' : '^';
- c = (c & 0x7F) ^ 0x40;
+ c = UNCTRL(c & 0x7F);
} else if (UTFMODE && c > 0x7F) {
/* better not try to display broken multibyte chars */
+ /* also go easy on the Unicode: no U+FFFD here */
c = '?';
}
*dst++ = c;
@@ -801,10 +802,10 @@ vistree(char *dst, size_t sz, struct op *t)
void
dumpchar(struct shf *shf, int c)
{
- if (((c & 0x60) == 0) || ((c & 0x7F) == 0x7F)) {
+ if (ISCTRL(c & 0x7F)) {
/* C0 or C1 control character or DEL */
shf_putc((c & 0x80) ? '$' : '^', shf);
- c = (c & 0x7F) ^ 0x40;
+ c = UNCTRL(c & 0x7F);
}
shf_putc(c, shf);
}
diff --git a/src/var.c b/src/var.c
index ba8fd82..9f05ec1 100644
--- a/src/var.c
+++ b/src/var.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: var.c,v 1.35 2013/04/05 01:31:30 tedu Exp $ */
+/* $OpenBSD: var.c,v 1.38 2013/12/20 17:53:09 zhuk Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@@ -22,12 +22,13 @@
*/
#include "sh.h"
+#include "mirhash.h"
#if defined(__OpenBSD__)
#include <sys/sysctl.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/var.c,v 1.173 2013/05/31 22:47:14 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183 2014/10/04 11:47:19 tg Exp $");
/*-
* Variables
@@ -40,7 +41,9 @@ __RCSID("$MirOS: src/bin/mksh/var.c,v 1.173 2013/05/31 22:47:14 tg Exp $");
*/
static struct table specials;
-static uint32_t lcg_state = 5381;
+static uint32_t lcg_state = 5381, qh_state = 4711;
+/* may only be set by typeset() just before call to array_index_calc() */
+static enum namerefflag innermost_refflag = SRF_NOP;
static char *formatstr(struct tbl *, const char *);
static void exportprep(struct tbl *, const char *);
@@ -164,7 +167,8 @@ varsearch(struct block *l, struct tbl **vpp, const char *vn, uint32_t h)
/*
* Used to calculate an array index for global()/local(). Sets *arrayp
* to true if this is an array, sets *valp to the array index, returns
- * the basename of the array.
+ * the basename of the array. May only be called from global()/local()
+ * and must be their first callee.
*/
static const char *
array_index_calc(const char *n, bool *arrayp, uint32_t *valp)
@@ -176,7 +180,7 @@ array_index_calc(const char *n, bool *arrayp, uint32_t *valp)
*arrayp = false;
redo_from_ref:
p = skip_varname(n, false);
- if (set_refflag == SRF_NOP && (p != n) && ksh_isalphx(n[0])) {
+ if (innermost_refflag == SRF_NOP && (p != n) && ksh_isalphx(n[0])) {
struct tbl *vp;
char *vn;
@@ -184,8 +188,8 @@ array_index_calc(const char *n, bool *arrayp, uint32_t *valp)
/* check if this is a reference */
varsearch(e->loc, &vp, vn, hash(vn));
afree(vn, ATEMP);
- if (vp && (vp->flag & (DEFINED|ASSOC|ARRAY)) ==
- (DEFINED|ASSOC)) {
+ if (vp && (vp->flag & (DEFINED | ASSOC | ARRAY)) ==
+ (DEFINED | ASSOC)) {
char *cp;
/* gotcha! */
@@ -195,6 +199,7 @@ array_index_calc(const char *n, bool *arrayp, uint32_t *valp)
goto redo_from_ref;
}
}
+ innermost_refflag = SRF_NOP;
if (p != n && *p == '[' && (len = array_ref_len(p))) {
char *sub, *tmp;
@@ -225,10 +230,13 @@ global(const char *n)
bool array;
uint32_t h, val;
- /* Check to see if this is an array */
+ /*
+ * check to see if this is an array;
+ * dereference namerefs; must come first
+ */
n = array_index_calc(n, &array, &val);
h = hash(n);
- c = n[0];
+ c = (unsigned char)n[0];
if (!ksh_isalphx(c)) {
if (array)
errorf("bad substitution");
@@ -238,9 +246,7 @@ global(const char *n)
vp->areap = ATEMP;
*vp->name = c;
if (ksh_isdigit(c)) {
- for (c = 0; ksh_isdigit(*n); n++)
- c = c*10 + *n-'0';
- if (c <= l->argc)
+ if (getn(n, &c) && (c <= l->argc))
/* setstr can't fail here */
setstr(vp, l->argv[c], KSH_RETURN_ERROR);
vp->flag |= RDONLY;
@@ -297,7 +303,10 @@ local(const char *n, bool copy)
bool array;
uint32_t h, val;
- /* check to see if this is an array */
+ /*
+ * check to see if this is an array;
+ * dereference namerefs; must come first
+ */
n = array_index_calc(n, &array, &val);
mkssert(n != NULL);
h = hash(n);
@@ -500,7 +509,7 @@ getint(struct tbl *vp, mksh_ari_u *nump, bool arith)
base = 8;
have_base = true;
}
- while ((c = *s++)) {
+ while ((c = (unsigned char)*s++)) {
if (c == '-') {
neg = true;
continue;
@@ -702,6 +711,16 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
const char *val;
size_t len;
bool vappend = false;
+ enum namerefflag new_refflag = SRF_NOP;
+
+ if ((set & (ARRAY | ASSOC)) == ASSOC) {
+ new_refflag = SRF_ENABLE;
+ set &= ~(ARRAY | ASSOC);
+ }
+ if ((clr & (ARRAY | ASSOC)) == ASSOC) {
+ new_refflag = SRF_DISABLE;
+ clr &= ~(ARRAY | ASSOC);
+ }
/* check for valid variable name, search for value */
val = skip_varname(var, false);
@@ -710,7 +729,7 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
return (NULL);
}
if (*val == '[') {
- if (set_refflag != SRF_NOP)
+ if (new_refflag != SRF_NOP)
errorf("%s: %s", var,
"reference variable can't be an array");
len = array_ref_len(val);
@@ -732,18 +751,18 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
}
val += len;
}
- if (val[0] == '=' || (val[0] == '+' && val[1] == '=')) {
+ if (val[0] == '=') {
strndupx(tvar, var, val - var, ATEMP);
- if (*val++ == '+') {
- ++val;
- vappend = true;
- }
- } else if ((val[0] != '\0') || (set & IMPORT)) {
- /*
- * must have a = when setting a variable by importing
- * the original environment, otherwise be empty; we
- * also end up here when a variable name was invalid
- */
+ ++val;
+ } else if (set & IMPORT) {
+ /* environment invalid variable name or no assignment */
+ return (NULL);
+ } else if (val[0] == '+' && val[1] == '=') {
+ strndupx(tvar, var, val - var, ATEMP);
+ val += 2;
+ vappend = true;
+ } else if (val[0] != '\0') {
+ /* other invalid variable names (not from environment) */
return (NULL);
} else {
/* just varname with no value part nor equals sign */
@@ -756,18 +775,49 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
tvar[len - 3] = '\0';
}
- if (set_refflag == SRF_ENABLE) {
- const char *qval;
+ if (new_refflag == SRF_ENABLE) {
+ const char *qval, *ccp;
/* bail out on 'nameref foo+=bar' */
if (vappend)
- errorfz();
+ errorf("appending not allowed for nameref");
/* find value if variable already exists */
if ((qval = val) == NULL) {
varsearch(e->loc, &vp, tvar, hash(tvar));
- if (vp != NULL)
- qval = str_val(vp);
+ if (vp == NULL)
+ goto nameref_empty;
+ qval = str_val(vp);
}
+ /* check target value for being a valid variable name */
+ ccp = skip_varname(qval, false);
+ if (ccp == qval) {
+ if (ksh_isdigit(qval[0])) {
+ int c;
+
+ if (getn(qval, &c))
+ goto nameref_rhs_checked;
+ } else if (qval[1] == '\0') switch (qval[0]) {
+ case '$':
+ case '!':
+ case '?':
+ case '#':
+ case '-':
+ goto nameref_rhs_checked;
+ }
+ nameref_empty:
+ errorf("%s: %s", var, "empty nameref target");
+ }
+ len = (*ccp == '[') ? array_ref_len(ccp) : 0;
+ if (ccp[len]) {
+ /*
+ * works for cases "no array", "valid array with
+ * junk after it" and "invalid array"; in the
+ * latter case, len is also 0 and points to '['
+ */
+ errorf("%s: %s", qval,
+ "nameref target not a valid parameter name");
+ }
+ nameref_rhs_checked:
/* prevent nameref loops */
while (qval) {
if (!strcmp(qval, tvar))
@@ -775,7 +825,7 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
"expression recurses on parameter");
varsearch(e->loc, &vp, qval, hash(qval));
qval = NULL;
- if (vp && ((vp->flag & (ARRAY|ASSOC)) == ASSOC))
+ if (vp && ((vp->flag & (ARRAY | ASSOC)) == ASSOC))
qval = str_val(vp);
}
}
@@ -785,11 +835,12 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
strcmp(tvar, "ENV") == 0 || strcmp(tvar, "SHELL") == 0))
errorf("%s: %s", tvar, "restricted");
- vp = (set&LOCAL) ? local(tvar, tobool(set & LOCAL_COPY)) :
+ innermost_refflag = new_refflag;
+ vp = (set & LOCAL) ? local(tvar, tobool(set & LOCAL_COPY)) :
global(tvar);
- if (set_refflag == SRF_DISABLE && (vp->flag & (ARRAY|ASSOC)) == ASSOC)
+ if (new_refflag == SRF_DISABLE && (vp->flag & (ARRAY|ASSOC)) == ASSOC)
vp->flag &= ~ASSOC;
- else if (set_refflag == SRF_ENABLE) {
+ else if (new_refflag == SRF_ENABLE) {
if (vp->flag & ARRAY) {
struct tbl *a, *tmp;
@@ -809,14 +860,14 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
set &= ~(LOCAL|LOCAL_COPY);
- vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp;
+ vpbase = (vp->flag & ARRAY) ? global(arrayname(tvar)) : vp;
/*
* only allow export flag to be set; AT&T ksh allows any
* attribute to be changed which means it can be truncated or
* modified (-L/-R/-Z/-i)
*/
- if ((vpbase->flag&RDONLY) &&
+ if ((vpbase->flag & RDONLY) &&
(val || clr || (set & ~EXPORT)))
/* XXX check calls - is error here ok by POSIX? */
errorfx(2, "read-only: %s", tvar);
@@ -960,7 +1011,7 @@ unset(struct tbl *vp, int flags)
* the terminating NUL if whole string is legal).
*/
const char *
-skip_varname(const char *s, int aok)
+skip_varname(const char *s, bool aok)
{
size_t alen;
@@ -1338,7 +1389,7 @@ arraysearch(struct tbl *vp, uint32_t val)
struct tbl *prev, *curr, *news;
size_t len;
- vp->flag = (vp->flag | (ARRAY|DEFINED)) & ~ASSOC;
+ vp->flag = (vp->flag | (ARRAY | DEFINED)) & ~ASSOC;
/* the table entry is always [0] */
if (val == 0)
return (vp);
@@ -1378,6 +1429,8 @@ arraysearch(struct tbl *vp, uint32_t val)
* Return the length of an array reference (eg, [1+2]) - cp is assumed
* to point to the open bracket. Returns 0 if there is no matching
* closing bracket.
+ *
+ * XXX this should parse the actual arithmetic syntax
*/
size_t
array_ref_len(const char *cp)
@@ -1458,6 +1511,7 @@ set_array(const char *var, bool reset, const char **vals)
afree(cp, ATEMP);
}
while ((ccp = vals[i])) {
+#if 0 /* temporarily taken out due to regression */
if (*ccp == '[') {
int level = 0;
@@ -1478,6 +1532,7 @@ set_array(const char *var, bool reset, const char **vals)
} else
ccp = vals[i];
}
+#endif
vq = arraysearch(vp, j);
/* would be nice to deal with errors here... (see above) */
@@ -1492,6 +1547,11 @@ set_array(const char *var, bool reset, const char **vals)
void
change_winsz(void)
{
+ struct timeval tv;
+
+ mksh_TIME(tv);
+ BAFHUpdateMem_mem(qh_state, &tv, sizeof(tv));
+
#ifdef TIOCGWINSZ
/* check if window size has changed */
if (tty_init_fd() < 2) {
@@ -1522,9 +1582,28 @@ hash(const void *s)
{
register uint32_t h;
- NZATInit(h);
- NZATUpdateString(h, s);
- NZAATFinish(h);
+ BAFHInit(h);
+ BAFHUpdateStr_reg(h, s);
+ BAFHFinish_reg(h);
+ return (h);
+}
+
+uint32_t
+chvt_rndsetup(const void *bp, size_t sz)
+{
+ register uint32_t h;
+
+ /* use LCG as seed but try to get them to deviate immediately */
+ h = lcg_state;
+ (void)rndget();
+ BAFHFinish_reg(h);
+ /* variation through pid, ppid, and the works */
+ BAFHUpdateMem_reg(h, &rndsetupstate, sizeof(rndsetupstate));
+ /* some variation, some possibly entropy, depending on OE */
+ BAFHUpdateMem_reg(h, bp, sz);
+ /* mix them all up */
+ BAFHFinish_reg(h);
+
return (h);
}
@@ -1542,28 +1621,67 @@ void
rndset(unsigned long v)
{
register uint32_t h;
+#if defined(arc4random_pushb_fast) || defined(MKSH_A4PB)
+ register uint32_t t;
+#endif
+ struct {
+ struct timeval tv;
+ void *sp;
+ uint32_t qh;
+ pid_t pp;
+ short r;
+ } z;
+
+#ifdef DEBUG
+ /* clear the allocated space, for valgrind */
+ memset(&z, 0, sizeof(z));
+#endif
+
+ h = lcg_state;
+ BAFHFinish_reg(h);
+ BAFHUpdateMem_reg(h, &v, sizeof(v));
- NZATInit(h);
- NZATUpdateMem(h, &lcg_state, sizeof(lcg_state));
- NZATUpdateMem(h, &v, sizeof(v));
+ mksh_TIME(z.tv);
+ z.sp = &lcg_state;
+ z.pp = procpid;
+ z.r = (short)rndget();
#if defined(arc4random_pushb_fast) || defined(MKSH_A4PB)
+ t = qh_state;
+ BAFHFinish_reg(t);
+ z.qh = (t & 0xFFFF8000) | rndget();
+ lcg_state = (t << 15) | rndget();
/*
* either we have very chap entropy get and push available,
* with malloc() pulling in this code already anyway, or the
* user requested us to use the old functions
*/
- lcg_state = h;
- NZAATFinish(lcg_state);
+ t = h;
+ BAFHUpdateMem_reg(t, &lcg_state, sizeof(lcg_state));
+ BAFHFinish_reg(t);
+ lcg_state = t;
#if defined(arc4random_pushb_fast)
arc4random_pushb_fast(&lcg_state, sizeof(lcg_state));
lcg_state = arc4random();
#else
lcg_state = arc4random_pushb(&lcg_state, sizeof(lcg_state));
#endif
- NZATUpdateMem(h, &lcg_state, sizeof(lcg_state));
+ BAFHUpdateMem_reg(h, &lcg_state, sizeof(lcg_state));
+#else
+ z.qh = qh_state;
#endif
- NZAATFinish(h);
+ BAFHUpdateMem_reg(h, &z, sizeof(z));
+ BAFHFinish_reg(h);
lcg_state = h;
}
+
+void
+rndpush(const void *s)
+{
+ register uint32_t h = qh_state;
+
+ BAFHUpdateStr_reg(h, s);
+ BAFHUpdateOctet_reg(h, 0);
+ qh_state = h;
+}