diff options
author | Ricardo Cerqueira <ricardo@cyngn.com> | 2015-03-10 11:58:49 +0000 |
---|---|---|
committer | Ricardo Cerqueira <ricardo@cyngn.com> | 2015-03-10 11:58:49 +0000 |
commit | 82aac8e655414ee400ff0534637c43b1c90cadae (patch) | |
tree | 1a2669dfad137eef21bc0cdf1da774183c162b24 | |
parent | 13346b7ef17b94819ef9f85fe38e07a5ade145d1 (diff) | |
parent | ae04631768fefc45c2d18865ec88872853421a52 (diff) | |
download | android_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 |
Merge tag 'android-5.1.0_r1' into HEADstaging/cm-12.1stable/cm-12.1-YOG7Dstable/cm-12.1-YOG4Pstable/cm-12.1-YOG3Ccm-12.1
Android 5.1.0 release 1
-rw-r--r-- | Android.mk | 112 | ||||
-rw-r--r-- | Makefrag.inc | 40 | ||||
-rw-r--r-- | mkmf.sh | 52 | ||||
-rw-r--r-- | src/Build.sh | 356 | ||||
-rw-r--r-- | src/check.pl | 45 | ||||
-rw-r--r-- | src/check.t | 556 | ||||
-rw-r--r-- | src/dot.mkshrc | 85 | ||||
-rw-r--r-- | src/edit.c | 144 | ||||
-rw-r--r-- | src/eval.c | 136 | ||||
-rw-r--r-- | src/exec.c | 33 | ||||
-rw-r--r-- | src/expr.c | 40 | ||||
-rw-r--r-- | src/funcs.c | 287 | ||||
-rw-r--r-- | src/histrap.c | 14 | ||||
-rw-r--r-- | src/jobs.c | 76 | ||||
-rw-r--r-- | src/lex.c | 32 | ||||
-rw-r--r-- | src/main.c | 169 | ||||
-rw-r--r-- | src/mirhash.h | 224 | ||||
-rw-r--r-- | src/misc.c | 74 | ||||
-rw-r--r-- | src/mksh.1 | 159 | ||||
-rw-r--r-- | src/rlimits.gen | 174 | ||||
-rw-r--r-- | src/rlimits.opt | 96 | ||||
-rw-r--r-- | src/sh.h | 154 | ||||
-rw-r--r-- | src/sh_flags.gen | 136 | ||||
-rw-r--r-- | src/sh_flags.h | 166 | ||||
-rw-r--r-- | src/sh_flags.opt | 179 | ||||
-rw-r--r-- | src/shf.c | 4 | ||||
-rw-r--r-- | src/signames.inc | 31 | ||||
-rw-r--r-- | src/strlcpy.c | 5 | ||||
-rw-r--r-- | src/syn.c | 8 | ||||
-rw-r--r-- | src/tree.c | 11 | ||||
-rw-r--r-- | src/var.c | 218 |
31 files changed, 2627 insertions, 1189 deletions
@@ -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> @@ -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 @@ -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); } @@ -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); @@ -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) @@ -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) { @@ -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; @@ -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); } @@ -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 @@ -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); } } @@ -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 @@ -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 @@ -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) { @@ -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; @@ -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); } @@ -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; +} |