OSDN Git Service

Upgrade to mksh 50.
authorElliott Hughes <enh@google.com>
Thu, 7 Aug 2014 19:59:26 +0000 (12:59 -0700)
committerElliott Hughes <enh@google.com>
Mon, 6 Oct 2014 20:44:21 +0000 (13:44 -0700)
Bug: 16569301
Bug: 17814343

(cherry picked from commit 737fdce098f804459a925438e48dd711c31bbc9e)

Change-Id: I7e8a142bec5f553f9e1a2568245582fe8fa14314

31 files changed:
Android.mk
Makefrag.inc [new file with mode: 0644]
mkmf.sh
src/Build.sh
src/check.pl
src/check.t
src/dot.mkshrc
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/mirhash.h [new file with mode: 0644]
src/misc.c
src/mksh.1
src/rlimits.gen [new file with mode: 0644]
src/rlimits.opt [new file with mode: 0644]
src/sh.h
src/sh_flags.gen [new file with mode: 0644]
src/sh_flags.h [deleted file]
src/sh_flags.opt [new file with mode: 0644]
src/shf.c
src/signames.inc [new file with mode: 0644]
src/strlcpy.c
src/syn.c
src/tree.c
src/var.c

index 9989f67..8f910a1 100644 (file)
@@ -20,7 +20,8 @@ include $(BUILD_PREBUILT)
 
 include $(CLEAR_VARS)
 
 
 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 \
 
 # mksh source files
 LOCAL_SRC_FILES:=      src/lalloc.c src/edit.c src/eval.c src/exec.c \
@@ -41,7 +42,9 @@ LOCAL_CFLAGS:=                -DMKSHRC_PATH=\"/system/etc/mkshrc\" \
                -DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH \
                -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN \
                -DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 \
                -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_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_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 \
@@ -54,14 +57,16 @@ LOCAL_CFLAGS:=              -DMKSHRC_PATH=\"/system/etc/mkshrc\" \
                -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_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_GETRUSAGE=1 \
+               -DHAVE_GETSID=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_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
+               -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=501
 
 # check_categories= shell:legacy-no int:32 android convfds no-histfile
 
 
 # check_categories= shell:legacy-no int:32 android convfds no-histfile
 
diff --git a/Makefrag.inc b/Makefrag.inc
new file mode 100644 (file)
index 0000000..403281f
--- /dev/null
@@ -0,0 +1,40 @@
+# Makefile fragment for building mksh R50 2014/06/29
+
+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/lmp-dev/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gcc
+CFLAGS=                 -fno-exceptions -Wno-multichar -msoft-float -fpic -fPIE -ffunction-sections -fdata-sections -funwind-tables -fstack-protector -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 -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 -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -Wno-deprecated-declarations -fno-asynchronous-unwind-tables -fwrapv
+CPPFLAGS=      -I. -I'../src'  -I/huge-ssd/lmp-dev/libnativehelper/include/nativehelper -isystem /huge-ssd/lmp-dev/system/core/include -isystem /huge-ssd/lmp-dev/hardware/libhardware/include -isystem /huge-ssd/lmp-dev/hardware/libhardware_legacy/include -isystem /huge-ssd/lmp-dev/hardware/ril/include -isystem /huge-ssd/lmp-dev/libnativehelper/include -isystem /huge-ssd/lmp-dev/frameworks/native/include -isystem /huge-ssd/lmp-dev/frameworks/native/opengl/include -isystem /huge-ssd/lmp-dev/frameworks/av/include -isystem /huge-ssd/lmp-dev/frameworks/base/include -isystem /huge-ssd/lmp-dev/external/skia/include -isystem /huge-ssd/lmp-dev/out/target/product/hammerhead/obj/include -isystem /huge-ssd/lmp-dev/bionic/libc/arch-arm/include -isystem /huge-ssd/lmp-dev/bionic/libc/include -isystem /huge-ssd/lmp-dev/bionic/libstdc++/include -isystem /huge-ssd/lmp-dev/bionic/libc/kernel/uapi -isystem /huge-ssd/lmp-dev/bionic/libc/kernel/uapi/asm-arm -isystem /huge-ssd/lmp-dev/bionic/libm/include -isystem /huge-ssd/lmp-dev/bionic/libm/include/arm -isystem /huge-ssd/lmp-dev/bionic/libthread_db/include -D_FORTIFY_SOURCE=2 -include /huge-ssd/lmp-dev/build/core/combo/include/arch/linux-arm/AndroidConfig.h -I/huge-ssd/lmp-dev/build/core/combo/include/arch/linux-arm/ -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_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=501
+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,--icf=safe -Wl,--fix-cortex-a8 -Wl,--no-undefined /huge-ssd/lmp-dev/out/target/product/hammerhead/obj/lib/crtbegin_dynamic.o
+LIBS=           -L/huge-ssd/lmp-dev/out/target/product/hammerhead/obj/lib -Wl,-rpath-link=/huge-ssd/lmp-dev/out/target/product/hammerhead/obj/lib -Wl,--no-whole-archive /huge-ssd/lmp-dev/out/target/product/hammerhead/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a -lc /huge-ssd/lmp-dev/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/../lib/gcc/arm-linux-androideabi/4.8/armv7-a/libgcc.a /huge-ssd/lmp-dev/out/target/product/hammerhead/obj/lib/crtend_android.o
+
+.depend $(OBJS_BP): rlimits.gen sh_flags.gen
+rlimits.gen: ../src/Build.sh ../src/rlimits.opt
+                       srcfile=../src/rlimits.opt; BUILDSH_RUN_GENOPT=1; . ../src/Build.sh
+sh_flags.gen: ../src/Build.sh ../src/sh_flags.opt
+                       srcfile=../src/sh_flags.opt; BUILDSH_RUN_GENOPT=1; . ../src/Build.sh
+
+# not BSD make only:
+#VPATH=                ../src
+#all: $(PROG)
+#$(PROG): $(OBJS_BP)
+#      $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS_BP) $(LIBS)
+#$(OBJS_BP): $(SRCS_FP) $(NONSRCS)
+#.c.o:
+#      $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+# for all make variants:
+#REGRESS_FLAGS=        -f
+#regress:
+#      ./test.sh $(REGRESS_FLAGS)
+check_categories= shell:legacy-no int:32 android convfds no-histfile
+
+# for BSD make only:
+#.PATH: ../src
+#.include <bsd.prog.mk>
diff --git a/mkmf.sh b/mkmf.sh
index f819e0d..193dae2 100644 (file)
--- a/mkmf.sh
+++ b/mkmf.sh
@@ -49,10 +49,10 @@ 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.)
 # 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=$aospdir/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin/arm-linux-androideabi-gcc
+CC=$aospdir/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gcc
 addvar CPPFLAGS \
     -I$aospdir/libnativehelper/include/nativehelper \
     -isystem $aospdir/system/core/include \
 addvar CPPFLAGS \
     -I$aospdir/libnativehelper/include/nativehelper \
     -isystem $aospdir/system/core/include \
@@ -65,7 +65,7 @@ addvar CPPFLAGS \
     -isystem $aospdir/frameworks/av/include \
     -isystem $aospdir/frameworks/base/include \
     -isystem $aospdir/external/skia/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 $ANDROID_PRODUCT_OUT/obj/include \
     -isystem $aospdir/bionic/libc/arch-arm/include \
     -isystem $aospdir/bionic/libc/include \
     -isystem $aospdir/bionic/libstdc++/include \
     -isystem $aospdir/bionic/libc/arch-arm/include \
     -isystem $aospdir/bionic/libc/include \
     -isystem $aospdir/bionic/libstdc++/include \
@@ -134,15 +134,15 @@ addvar LDFLAGS \
     -Wl,--icf=safe \
     -Wl,--fix-cortex-a8 \
     -Wl,--no-undefined \
     -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 \
 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 \
     -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 \
     -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
+    $aospdir/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/../lib/gcc/arm-linux-androideabi/4.8/armv7-a/libgcc.a \
+    $ANDROID_PRODUCT_OUT/obj/lib/crtend_android.o
 
 
 ### Flags used by test builds
 
 
 ### Flags used by test builds
index 45af9dd..8ef6cb6 100644 (file)
@@ -1,8 +1,8 @@
 #!/bin/sh
 #!/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.662 2014/06/29 10:56:08 tg Exp $'
 #-
 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 #-
 # 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
 #      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
 
 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
 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
 
        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 "$@"
 v() {
        $e "$*"
        eval "$@"
@@ -66,18 +219,12 @@ vq() {
 rmf() {
        for _f in "$@"; do
                case $_f in
 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
 }
 
                *) rm -f "$_f" ;;
                esac
        done
 }
 
-allu=QWERTYUIOPASDFGHJKLZXCVBNM
-alll=qwertyuiopasdfghjklzxcvbnm
-alln=0123456789
-alls=______________________________________________________________
-nl='
-'
 tcfn=no
 bi=
 ui=
 tcfn=no
 bi=
 ui=
@@ -193,8 +340,9 @@ ac_testn() {
 ac_ifcpp() {
        expr=$1; shift
        ac_testn "$@" <<-EOF
 ac_ifcpp() {
        expr=$1; shift
        ac_testn "$@" <<-EOF
+               #include <unistd.h>
                extern int thiswillneverbedefinedIhope(void);
                extern int thiswillneverbedefinedIhope(void);
-               int main(void) { return (
+               int main(void) { return (isatty(0) +
                #$expr
                    0
                #else
                #$expr
                    0
                #else
@@ -251,7 +399,8 @@ ac_flags() {
        else
                ac_testn can_$vn '' "$ft" <<-'EOF'
                        /* evil apo'stroph in comment test */
        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`
                EOF
        fi
        eval fv=\$HAVE_CAN_`upper $vn`
@@ -291,19 +440,14 @@ ac_header() {
                esac
        done
        echo "#include <$hf>" >>x
                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() {
        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
        if test x"$1" = x"!"; then
                fr=0
                shift
@@ -311,13 +455,6 @@ addsrcs() {
                fr=1
        fi
        eval i=\$$1
                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" ;;
        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
 add_cppflags -DMKSH_BUILDSH
 
 e=echo
@@ -336,6 +485,7 @@ eq=0
 pm=0
 cm=normal
 optflags=-std-compile-opts
 pm=0
 cm=normal
 optflags=-std-compile-opts
+check_categories=
 last=
 tfn=
 legacy=0
 last=
 tfn=
 legacy=0
@@ -362,6 +512,10 @@ do
        :-c)
                last=c
                ;;
        :-c)
                last=c
                ;;
+       :-G)
+               echo "$me: Do not call me with '-G'!" >&2
+               exit 1
+               ;;
        :-g)
                # checker, debug, valgrind build
                add_cppflags -DDEBUG
        :-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
        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"
     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=
 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
 
 # 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"
        ;;
 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 '|' "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"
        ;;
 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
 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"
 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
        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
                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
                ;;
        *)
                EOF
                ;;
        *)
@@ -1193,7 +1357,8 @@ kencc|tcc|tendra)
        ;;
 sunpro)
        cat >x <<-'EOF'
        ;;
 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) { }
                #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
        # 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 ;;
        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)
        #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) {
                /*
        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, ...)
        #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
        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
        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
 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
        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'
        #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
        /* 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";
        static const char fnord[] __attribute__((__used__)) = "42";
-       int main(void) { return (0); }
+       int main(void) { return (isatty(0)); }
        #endif
 EOF
 
        #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>
        #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
 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>
 # Environment: definitions
 #
 echo '#include <sys/types.h>
+#include <unistd.h>
 /* check that off_t can represent 2^63-1 correctly, thx FSF */
 /* 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 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
 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>
        #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
 EOF
 
 # only testn: added later below
@@ -1598,8 +1784,8 @@ else
                #define EXTERN
                #define MKSH_INCLUDES_ONLY
                #include "sh.h"
                #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.662 2014/06/29 10:56:08 tg Exp $");
+               int main(void) { printf("Hello, World!\n"); return (isatty(0)); }
 EOF
        case $cm in
        llvm)
 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[];
 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[];
 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
 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}[];
        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}[];
        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
        EOF
        eval uwhat_v=\$HAVE__SYS_SIG$uwhat
        if test 1 = "$uwhat_v"; then
@@ -1703,6 +1893,11 @@ ac_test getrusage <<-'EOF'
        }
 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"
 ac_test gettimeofday <<-'EOF'
        #define MKSH_INCLUDES_ONLY
        #include "sh.h"
@@ -1722,7 +1917,7 @@ ac_test memmove <<-'EOF'
        #include <strings.h>
        #endif
        int main(int ac, char *av[]) {
        #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
 
        }
 EOF
 
@@ -1894,12 +2089,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"
 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"
 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
 
 #
 EOF
 
 #
@@ -1970,7 +2165,7 @@ cta(ptr_fits_in_long, sizeof(ptrdiff_t) <= sizeof(long));
                char padding[64 - NUM];
        };
 char ctasserts_dblcheck[sizeof(struct ctasserts) == 64 ? 1 : -1];
                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
 EOF
 CFLAGS=$save_CFLAGS
 eval test 1 = \$HAVE_COMPILE_TIME_ASSERTS_$$ || exit 1
@@ -2054,6 +2249,9 @@ if test 0 = $HAVE_SYS_SIGNAME; then
 #define NSIG (SIGMAX+1)
 #elif defined(_SIGMAX)
 #define NSIG (_SIGMAX+1)
 #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
 #endif
 #endif
 int
@@ -2072,9 +2270,9 @@ 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 ... "
        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"
        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]*[  ]' | \
        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 +2306,11 @@ mksh_cfg= NSIG
        $e done.
 fi
 
        $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"
 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=501
 
 $e $bi$me: Finished configuration testing, now producing output.$ao
 
 
 $e $bi$me: Finished configuration testing, now producing output.$ao
 
@@ -2175,6 +2372,10 @@ cat >test.sh <<-EOF
        fi
        (( vflag )) && args[\${#args[*]}]=-v
        (( xflag )) && args[\${#args[*]}]=-x    # force usage by synerr
        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"
        print Testing mksh for conformance:
        fgrep -e MirOS: -e MIRBSD "\$sflag"
        print "This shell is actually:\\n\\t\$KSH_VERSION"
@@ -2224,6 +2425,10 @@ llvm)
        ;;
 esac
 echo ": # work around NeXTstep bug" >Rebuild.sh
        ;;
 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./'`
 echo set -x >>Rebuild.sh
 for file in $SRCS; do
        op=`echo x"$file" | sed 's/^x\(.*\)\.c$/\1./'`
@@ -2253,8 +2458,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
 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"
        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
 
        cat >Makefrag.inc <<EOF
 # Makefile fragment for building mksh $dstversion
 
@@ -2272,6 +2484,8 @@ CPPFLAGS= $CPPFLAGS
 LDFLAGS=       $LDFLAGS
 LIBS=          $LIBS
 
 LDFLAGS=       $LDFLAGS
 LIBS=          $LIBS
 
+.depend \$(OBJS_BP):$gens$genq
+
 # not BSD make only:
 #VPATH=                $srcdir
 #all: \$(PROG)
 # not BSD make only:
 #VPATH=                $srcdir
 #all: \$(PROG)
@@ -2295,6 +2509,10 @@ EOF
        $e Generated Makefrag.inc successfully.
        exit 0
 fi
        $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
 if test $cm = combine; then
        objs="-o $mkshexe"
        for file in $SRCS; do
index ecd8f8d..e71564d 100644 (file)
@@ -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.36 2014/06/09 13:25:50 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,
 #-
 # 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
 #      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 Getopt::Std;
 use Config;
-use File::Temp qw/ :mktemp /;
 
 $os = defined $^O ? $^O : 'unknown';
 
 
 $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;
 $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;
 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 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"
 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
 $| = 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;
 
 if (-d $test_set) {
     $file_prefix_skip = length($test_set) + 1;
@@ -365,6 +373,7 @@ cleanup_exit
     unlink($tempi, $tempo, $tempe, $temps);
     &scrub_dir($tempdir) if defined $tempdir;
     rmdir($tempdir) if defined $tempdir;
     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';
 
     if ($sig) {
        $SIG{$sig} = 'DEFAULT';
@@ -903,7 +912,7 @@ eval_exit
     } else {
        $expr = $expect;
        $expr =~ s/\b([wse])\b/\$$1/g;
     } 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 '') {
     }
     $w = eval $expr;
     if ($@ ne '') {
@@ -923,12 +932,13 @@ read_test
     %test = ();
     %cnt = ();
     while (<$in>) {
     %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*$/) {
        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);
            return undef;
        }
        ($field, $val) = ($1, $2);
@@ -1154,7 +1164,7 @@ read_test
                print STDERR "$prog:$test{':long-name'}: expected-exit value $val not in 0..255\n";
                return undef;
            }
                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;
        }
            print STDERR "$prog:$test{':long-name'}: bad expected-exit expression: $val\n";
            return undef;
        }
index 8df826f..6db4f3a 100644 (file)
@@ -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.654 2014/06/29 11:28:26 tg Exp $
+# OpenBSD src/regress/bin/ksh updated: 2013/12/02 20:39:44
 #-
 # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 #-
 # 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
 #      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:
 # 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/06/29
 description:
        Check version of shell.
 stdin:
 description:
        Check version of shell.
 stdin:
@@ -40,7 +36,7 @@ name: KSH_VERSION
 category: shell:legacy-no
 ---
 expected-stdout:
 category: shell:legacy-no
 ---
 expected-stdout:
-       @(#)LEGACY KSH R48 2013/08/14
+       @(#)LEGACY KSH R50 2014/06/29
 description:
        Check version of legacy shell.
 stdin:
 description:
        Check version of legacy shell.
 stdin:
@@ -74,6 +70,18 @@ stdin:
 expected-stdout:
        <fnord>
 ---
 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)
 name: selftest-env
 description:
        Just output the environment variables set (always fails)
@@ -1640,6 +1648,14 @@ expected-stdout:
        1=02.
        2=02.
 ---
        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
 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]*
        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
 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:
 ---
 name: glob-range-2
 description:
@@ -2126,6 +2148,18 @@ stdin:
 expected-stdout:
        -bc abc bbc cbc ebc
 ---
 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.
 name: heredoc-1
 description:
        Check ordering/content of redundent here documents.
@@ -3689,6 +3723,28 @@ expected-stdout:
        12: [A] [B] [] [D]
         <13> <A> <B> <> <D>
 ---
        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-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)
 name: integer-base-err-1
 description:
        Can't have 0 base (causes shell to exit)
@@ -4806,11 +4862,12 @@ description:
        them exit 0. The POSIX behaviour is needed by BSD make.
 stdin:
        set -e
        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
        echo $?
 expected-stdout:
        
        0
+expected-stderr-pattern: /this-file-does-not-exist/
 ---
 name: regression-40
 description:
 ---
 name: regression-40
 description:
@@ -5426,6 +5483,18 @@ expected-stdout:
 expected-stderr-pattern:
        /read-only/
 ---
 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
 name: syntax-1
 description:
        Check that lone ampersand is a syntax error
@@ -6444,6 +6513,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 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 .
 expected-stdout:
        1 42 .
        2 0 .
@@ -6453,6 +6523,7 @@ expected-stdout:
        6 1 .
        7 42 .
        8 0 .
        6 1 .
        7 42 .
        8 0 .
+       9 42 .
 ---
 name: persist-history-1
 description:
 ---
 name: persist-history-1
 description:
@@ -6733,7 +6804,6 @@ expected-stdout:
        r='fc -e -'
        source='PATH=$PATH:. command .'
        stop='kill -STOP'
        r='fc -e -'
        source='PATH=$PATH:. command .'
        stop='kill -STOP'
-       suspend='kill -STOP $$'
        type='whence -v'
 ---
 name: aliases-1-hartz4
        type='whence -v'
 ---
 name: aliases-1-hartz4
@@ -6802,7 +6872,6 @@ expected-stdout:
        r='fc -e -'
        source='PATH=$PATH:. command .'
        stop='kill -STOP'
        r='fc -e -'
        source='PATH=$PATH:. command .'
        stop='kill -STOP'
-       suspend='kill -STOP $$'
        type='whence -v'
 ---
 name: aliases-3b
        type='whence -v'
 ---
 name: aliases-3b
@@ -6826,7 +6895,6 @@ expected-stdout:
        r='fc -e -'
        source='PATH=$PATH:. command .'
        stop='kill -STOP'
        r='fc -e -'
        source='PATH=$PATH:. command .'
        stop='kill -STOP'
-       suspend='kill -STOP $$'
        type='whence -v'
 ---
 name: aliases-2b-hartz4
        type='whence -v'
 ---
 name: aliases-2b-hartz4
@@ -7000,12 +7068,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]}|"
        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:
 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
 ---
 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)
 stdin:
        v="c d"
        foo=([1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b)
@@ -7013,10 +7088,17 @@ stdin:
        x=([128]=foo bar baz)
        echo k= ${!x[*]} .
        echo v= ${x[*]} .
        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 .
 expected-stdout:
        5|a|$v|c d||$v|b|
        k= 128 129 130 .
        v= foo bar baz .
+       <><blah>
 ---
 name: arrays-6
 description:
 ---
 name: arrays-6
 description:
@@ -7078,15 +7160,15 @@ stdin:
        echo !arz[0]: ${!arz[0]}
        echo !arz[1]: ${!arz[1]}
 expected-stdout:
        echo !arz[0]: ${!arz[0]}
        echo !arz[1]: ${!arz[1]}
 expected-stdout:
-       !arz: 0
-       !arz[0]:
-       !arz[1]:
        !arz: arz
        !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:
 ---
 name: arrays-8
 description:
@@ -7177,11 +7259,11 @@ description:
 stdin:
        unset foo; foo=(bar); foo+=(baz); echo 1 ${!foo[*]} : ${foo[*]} .
        unset foo; foo=(foo bar); foo+=(baz); echo 2 ${!foo[*]} : ${foo[*]} .
 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 .
 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:
 ---
 name: arrays-9b
 description:
@@ -7660,14 +7742,9 @@ stdin:
        typeset -i8 foo=10
        bar=baz
        unset baz
        typeset -i8 foo=10
        bar=baz
        unset baz
-       bla=foo
        print ${foo@#} ${bar@#} ${baz@#} .
        print ${foo@#} ${bar@#} ${baz@#} .
-       print ${foo@#123} ${bar@#456} ${baz@#789} .
-       print ${foo@#bla} ${bar@#bar} ${baz@#OPTIND} .
 expected-stdout:
 expected-stdout:
-       D50219A0 20E5DB5B 00000000 .
-       554A1C76 004A212E CB209562 .
-       6B21CF91 20E5DB5B 124EA49D .
+       9B15FBFB CFBDD32B 00000000 .
 ---
 name: varexpand-special-quote
 description:
 ---
 name: varexpand-special-quote
 description:
@@ -8772,7 +8849,7 @@ expected-stdout:
 ---
 name: oksh-eval
 description:
 ---
 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
 stdin:
        a=
        for n in ${a#*=}; do echo 1hu ${n} .; done
@@ -8932,8 +9009,7 @@ stdin:
 ---
 name: oksh-varfunction-mod1
 description:
 ---
 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,
                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 +9017,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.
        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"'\'\"\'\; \
 stdin:
        print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
            'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
@@ -10502,7 +10577,7 @@ expected-stdout:
        ir2: ir2
        s1: ir2=ind
        s2: typeset -n ir2
        ir2: ir2
        s1: ir2=ind
        s2: typeset -n ir2
-       !ind[1]: 1
+       !ind[1]: blub[1]
        !ir2: ir2
        ind[1]: e2
        ir2: e3
        !ir2: ir2
        ind[1]: e2
        ir2: e3
index cbd13ed..99cc9a1 100644 (file)
@@ -1,8 +1,8 @@
 # $Id$
 # $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.88 2014/01/11 18:09:39 tg Exp $
 #-
 # Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
 #-
 # 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
 #      Thorsten Glaser <tg@mirbsd.org>
 #
 # Provided that these terms and disclaimer and all copyright notices
@@ -105,14 +105,14 @@ function chpwd {
 }
 chpwd .
 function cd {
 }
 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
        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"
                return 1
        fi
        cd "$t"
@@ -333,9 +333,12 @@ function Lb64encode {
        (( u )) || set -U
 }
 
        (( 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
        [[ -o utf8-mode ]]; local u=$?
        set +U
        local s
@@ -348,37 +351,20 @@ function Lnzathash_add {
        local -i i=0 n=${#s[*]}
 
        while (( i < n )); do
        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
 }
        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
 }
 
 # strip comments (and leading/trailing whitespace if IFS is set) from
index 675e7ed..2459db7 100644 (file)
@@ -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: 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,
 
 /*-
  * 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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -28,7 +28,7 @@
 
 #ifndef MKSH_NO_CMDLINE_EDITING
 
 
 #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.275 2014/01/05 21:57:24 tg Exp $");
 
 /*
  * in later versions we might use libtermcap for this, but since external
 
 /*
  * 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_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
 #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;
                                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);
                                }
                        }
                                        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 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_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);
 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);
 #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;
 
 
 static int unget_char = -1;
 
@@ -1167,16 +1167,17 @@ x_e_getmbc(char *sbuf)
 }
 
 static void
 }
 
 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;
        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_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;
        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)
 {
 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));
 
        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 == '\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);
                /* control unsigned char */
                return (2);
        return (1);
@@ -1632,19 +1633,6 @@ x_zots(char *str)
 }
 
 static void
 }
 
 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;
 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)++;
                /* 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)++;
                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)
 {
 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();
        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 -- should handle \^ escape? */
                if (*cp == '^') {
                        cp++;
+                       /*XXX or ^^ escape? this is ugly. */
                        if (*cp >= '?')
                                /* includes '?'; ASCII */
                                *op++ = CTRL(*cp);
                        if (*cp >= '?')
                                /* includes '?'; ASCII */
                                *op++ = CTRL(*cp);
@@ -2398,7 +2390,7 @@ x_mapout2(int c, char **buf)
 {
        char *p = *buf;
 
 {
        char *p = *buf;
 
-       if (c < ' ' || c == 0x7f) {
+       if (ISCTRL(c)) {
                *p++ = '^';
                *p++ = UNCTRL(c);
        } else
                *p++ = '^';
                *p++ = UNCTRL(c);
        } else
@@ -3341,8 +3333,6 @@ x_mode(bool onoff)
 #if !MKSH_S_NOVI
 /* +++ vi editing mode +++ */
 
 #if !MKSH_S_NOVI
 /* +++ vi editing mode +++ */
 
-#define Ctrl(c)                (c&0x1f)
-
 struct edstate {
        char *cbuf;
        ssize_t winleft;
 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 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);
 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 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);
 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);
 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;
 
        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))) {
        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) {
        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? */
                        /* end of current macro? */
                        if (!c) {
                                /* more macros left to finish? */
@@ -3618,7 +3609,7 @@ vi_hook(int ch)
 
        case VNORMAL:
                if (insert != 0) {
 
        case VNORMAL:
                if (insert != 0) {
-                       if (ch == Ctrl('v')) {
+                       if (ch == CTRL('v')) {
                                state = VLIT;
                                ch = '^';
                        }
                                state = VLIT;
                                ch = '^';
                        }
@@ -3730,7 +3721,7 @@ vi_hook(int ch)
                break;
 
        case VXCH:
                break;
 
        case VXCH:
-               if (ch == Ctrl('['))
+               if (ch == CTRL('['))
                        state = VNORMAL;
                else {
                        curcmd[cmdlen++] = ch;
                        state = VNORMAL;
                else {
                        curcmd[cmdlen++] = ch;
@@ -3739,7 +3730,7 @@ vi_hook(int ch)
                break;
 
        case VSEARCH:
                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) {
                        restore_cbuf();
                        /* Repeat last search? */
                        if (srchlen == 0) {
@@ -3754,10 +3745,10 @@ vi_hook(int ch)
                                memcpy(srchpat, locpat, srchlen + 1);
                        }
                        state = VCMD;
                                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--;
                        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);
                                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) {
                        refresh(0);
                        return (0);
                } else if (ch == edchars.werase) {
-                       int i, n = srchlen;
+                       unsigned int i, n;
                        struct edstate new_es, *save_es;
 
                        struct edstate new_es, *save_es;
 
-                       new_es.cursor = n;
+                       new_es.cursor = srchlen;
                        new_es.cbuf = locpat;
 
                        save_es = es;
                        new_es.cbuf = locpat;
 
                        save_es = es;
@@ -3783,9 +3774,10 @@ vi_hook(int ch)
                        n = backword(1);
                        es = save_es;
 
                        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);
                        es->cursor = es->linelen;
                        refresh(0);
                        return (0);
@@ -3794,12 +3786,12 @@ vi_hook(int ch)
                                vi_error();
                        else {
                                locpat[srchlen++] = 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++] = '^';
                                        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();
                                } else {
                                        if (es->linelen >= es->cbufsize)
                                                vi_error();
@@ -3910,7 +3902,7 @@ nextstate(int ch)
                return (VXCH);
        else if (ch == '.')
                return (VREDO);
                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);
                return (VVERSION);
        else if (is_cmd(ch))
                return (VCMD);
@@ -3923,7 +3915,7 @@ vi_insert(int ch)
 {
        int tcursor;
 
 {
        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();
                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)
         */
         * 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':
                saved_inslen = 0;
        switch (ch) {
        case '\0':
@@ -3990,7 +3982,7 @@ vi_insert(int ch)
        case '\n':
                return (1);
 
        case '\n':
                return (1);
 
-       case Ctrl('['):
+       case CTRL('['):
                expanded = NONE;
                if (first_insert) {
                        first_insert = false;
                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 */
                        return (redo_insert(lastac - 1));
 
        /* { Begin nonstandard vi commands */
-       case Ctrl('x'):
+       case CTRL('x'):
                expand_word(0);
                break;
 
                expand_word(0);
                break;
 
-       case Ctrl('f'):
+       case CTRL('f'):
                complete_word(0, 0);
                break;
 
                complete_word(0, 0);
                break;
 
-       case Ctrl('e'):
+       case CTRL('e'):
                print_expansions(es, 0);
                break;
 
                print_expansions(es, 0);
                break;
 
-       case Ctrl('i'):
+       case CTRL('i'):
                if (Flag(FVITABCOMPLETE)) {
                        complete_word(0, 0);
                        break;
                if (Flag(FVITABCOMPLETE)) {
                        complete_word(0, 0);
                        break;
@@ -4075,8 +4067,8 @@ vi_cmd(int argcnt, const char *cmd)
                }
                switch (*cmd) {
 
                }
                switch (*cmd) {
 
-               case Ctrl('l'):
-               case Ctrl('r'):
+               case CTRL('l'):
+               case CTRL('r'):
                        redraw_line(true);
                        break;
 
                        redraw_line(true);
                        break;
 
@@ -4263,7 +4255,7 @@ vi_cmd(int argcnt, const char *cmd)
 
                case 'j':
                case '+':
 
                case 'j':
                case '+':
-               case Ctrl('n'):
+               case CTRL('n'):
                        if (grabhist(modified, hnum + argcnt) < 0)
                                return (-1);
                        else {
                        if (grabhist(modified, hnum + argcnt) < 0)
                                return (-1);
                        else {
@@ -4274,7 +4266,7 @@ vi_cmd(int argcnt, const char *cmd)
 
                case 'k':
                case '-':
 
                case 'k':
                case '-':
-               case Ctrl('p'):
+               case CTRL('p'):
                        if (grabhist(modified, hnum - argcnt) < 0)
                                return (-1);
                        else {
                        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 */
                /* AT&T ksh */
                case '=':
                /* Nonstandard vi/ksh */
-               case Ctrl('e'):
+               case CTRL('e'):
                        print_expansions(es, 1);
                        break;
 
 
                /* Nonstandard vi/ksh */
                        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 */
                        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 */
                        if (!Flag(FVIESCCOMPLETE))
                                return (-1);
                /* AT&T ksh */
                case '\\':
                /* Nonstandard vi/ksh */
-               case Ctrl('f'):
+               case CTRL('f'):
                        complete_word(1, argcnt);
                        break;
 
                        complete_word(1, argcnt);
                        break;
 
@@ -4533,7 +4525,7 @@ vi_cmd(int argcnt, const char *cmd)
                /* AT&T ksh */
                case '*':
                /* Nonstandard vi/ksh */
                /* AT&T ksh */
                case '*':
                /* Nonstandard vi/ksh */
-               case Ctrl('x'):
+               case CTRL('x'):
                        expand_word(1);
                        break;
 
                        expand_word(1);
                        break;
 
@@ -4612,7 +4604,7 @@ domove(int argcnt, const char *cmd, int sub)
                break;
 
        case 'h':
                break;
 
        case 'h':
-       case Ctrl('h'):
+       case CTRL('h'):
                if (!sub && es->cursor == 0)
                        return (-1);
                ncursor = es->cursor - argcnt;
                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;
 {
        char *hptr;
        int hist;
-       int anchored;
+       bool anchored;
 
        if ((start == 0 && fwd == 0) || (start >= hlast - 1 && fwd == 1))
                return (-1);
 
        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--;
                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) {
        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
 }
 
 static int
-newcol(int ch, int col)
+newcol(unsigned char ch, int col)
 {
        if (ch == '\t')
                return ((col | 7) + 1);
 {
        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) {
                                *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++ = '^';
                                if (++col < winwidth) {
-                                       *twb1++ = ch ^ '@';
+                                       *twb1++ = UNCTRL(ch);
                                        col++;
                                }
                        } else {
                                        col++;
                                }
                        } else {
@@ -5433,9 +5425,9 @@ print_expansions(struct edstate *est, int cmd MKSH_A_UNUSED)
 static void
 x_vi_zotc(int c)
 {
 static void
 x_vi_zotc(int c)
 {
-       if (c < ' ' || c == 0x7f) {
+       if (ISCTRL(c)) {
                x_putc('^');
                x_putc('^');
-               c ^= '@';
+               c = UNCTRL(c);
        }
        x_putc(c);
 }
        }
        x_putc(c);
 }
index b6ff1dc..62a2fad 100644 (file)
@@ -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,
 
 /*-
  * 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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
 
 #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.150 2014/06/09 11:16:07 tg Exp $");
 
 /*
  * string expansion
 
 /*
  * string expansion
@@ -74,7 +74,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 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 */
 static void utfincptr(const char *, mksh_ari_t *);
 
 /* UTFMODE functions */
@@ -324,9 +324,9 @@ expand(
                                }
                                continue;
                        case EXPRSUB:
                                }
                                continue;
                        case EXPRSUB:
-                               word = IFS_WORD;
                                tilde_ok = 0;
                                if (f & DONTRUNCOMMAND) {
                                tilde_ok = 0;
                                if (f & DONTRUNCOMMAND) {
+                                       word = IFS_WORD;
                                        *dp++ = '$'; *dp++ = '('; *dp++ = '(';
                                        while (*sp != '\0') {
                                                Xcheck(ds, dp);
                                        *dp++ = '$'; *dp++ = '('; *dp++ = '(';
                                        while (*sp != '\0') {
                                                Xcheck(ds, dp);
@@ -343,11 +343,10 @@ expand(
                                        v_evaluate(&v, substitute(sp, 0),
                                            KSH_UNWIND_ERROR, true);
                                        sp = strnul(sp) + 1;
                                        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: {
                                }
                                continue;
                        case OSUBST: {
@@ -412,27 +411,10 @@ expand(
                                        if (stype)
                                                sp += slen;
                                        switch (stype & 0x17F) {
                                        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",
                                                x.str = shf_smprintf("%08X",
-                                                   (unsigned int)h);
+                                                   (unsigned int)hash(str_val(st->var)));
                                                break;
                                                break;
-                                       }
                                        case 0x100 | 'Q': {
                                                struct shf shf;
 
                                        case 0x100 | 'Q': {
                                                struct shf shf;
 
@@ -700,7 +682,7 @@ expand(
                                *dp = '\0';
                                quote = st->quotep;
                                f = st->f;
                                *dp = '\0';
                                quote = st->quotep;
                                f = st->f;
-                               if (f&DOBLANK)
+                               if (f & DOBLANK)
                                        doblank--;
                                switch (st->stype & 0x17F) {
                                case '#':
                                        doblank--;
                                switch (st->stype & 0x17F) {
                                case '#':
@@ -719,11 +701,12 @@ expand(
                                         */
                                        x.str = trimsub(str_val(st->var),
                                                dp, st->stype);
                                         */
                                        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;
                                                type = XSUB;
-                                       else
-                                               type = XNULLSUB;
-                                       if (f&DOBLANK)
+                                       else
+                                               type = quote ? XSUB : XNULLSUB;
+                                       if (f & DOBLANK)
                                                doblank++;
                                        st = st->prev;
                                        continue;
                                                doblank++;
                                        st = st->prev;
                                        continue;
@@ -755,7 +738,7 @@ expand(
                                            dp, len), KSH_UNWIND_ERROR);
                                        x.str = str_val(st->var);
                                        type = XSUB;
                                            dp, len), KSH_UNWIND_ERROR);
                                        x.str = str_val(st->var);
                                        type = XSUB;
-                                       if (f&DOBLANK)
+                                       if (f & DOBLANK)
                                                doblank++;
                                        st = st->prev;
                                        continue;
                                                doblank++;
                                        st = st->prev;
                                        continue;
@@ -773,7 +756,7 @@ expand(
                                case 0x100 | 'Q':
                                        dp = Xrestpos(ds, dp, st->base);
                                        type = XSUB;
                                case 0x100 | 'Q':
                                        dp = Xrestpos(ds, dp, st->base);
                                        type = XSUB;
-                                       if (f&DOBLANK)
+                                       if (f & DOBLANK)
                                                doblank++;
                                        st = st->prev;
                                        continue;
                                                doblank++;
                                        st = st->prev;
                                        continue;
@@ -810,12 +793,14 @@ expand(
                         * other stuff inside the quotes).
                         */
                        type = XBASE;
                         * other stuff inside the quotes).
                         */
                        type = XBASE;
-                       if (f&DOBLANK) {
+                       if (f & DOBLANK) {
                                doblank--;
                                /*
                                doblank--;
                                /*
-                                * not really correct: x=; "$x$@" should
-                                * generate a null argument and
-                                * set A; "${@:+}" shouldn't.
+                                * XXX not really correct:
+                                *      x=; "$x$@"
+                                * should generate a null argument and
+                                *      set A; "${@:+}"
+                                * shouldn't.
                                 */
                                if (dp == Xstring(ds, dp))
                                        word = IFS_WS;
                                 */
                                if (dp == Xstring(ds, dp))
                                        word = IFS_WS;
@@ -826,7 +811,7 @@ expand(
                case XSUBMID:
                        if ((c = *x.str++) == 0) {
                                type = XBASE;
                case XSUBMID:
                        if ((c = *x.str++) == 0) {
                                type = XBASE;
-                               if (f&DOBLANK)
+                               if (f & DOBLANK)
                                        doblank--;
                                continue;
                        }
                                        doblank--;
                                continue;
                        }
@@ -847,7 +832,7 @@ expand(
                                        word = IFS_WORD;
                                if ((x.str = *x.u.strv++) == NULL) {
                                        type = XBASE;
                                        word = IFS_WORD;
                                if ((x.str = *x.u.strv++) == NULL) {
                                        type = XBASE;
-                                       if (f&DOBLANK)
+                                       if (f & DOBLANK)
                                                doblank--;
                                        continue;
                                }
                                                doblank--;
                                        continue;
                                }
@@ -896,7 +881,7 @@ expand(
                                if (x.split)
                                        subst_exstat = waitlast();
                                type = XBASE;
                                if (x.split)
                                        subst_exstat = waitlast();
                                type = XBASE;
-                               if (f&DOBLANK)
+                               if (f & DOBLANK)
                                        doblank--;
                                continue;
                        }
                                        doblank--;
                                continue;
                        }
@@ -1269,17 +1254,12 @@ varsub(Expand *xp, const char *sp, const char *word,
                        if (*sp == '!' && sp[1]) {
                                ++sp;
                                xp->var = global(sp);
                        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
                                else
-                                       /* ksh93 compat */
-                                       xp->str = "0";
+                                       xp->str = xp->var->name;
                        } else {
                                xp->var = global(sp);
                                xp->str = str_val(xp->var);
                        } else {
                                xp->var = global(sp);
                                xp->str = str_val(xp->var);
index 50ec9ca..70ef83d 100644 (file)
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 
 /*-
  * 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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
 
 #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.132 2014/06/24 18:38:31 tg Exp $");
 
 #ifndef MKSH_DEFAULT_EXECSHELL
 #define MKSH_DEFAULT_EXECSHELL "/bin/sh"
 
 #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 |
        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;
        }
 
                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
                                /* go on, use the builtin */
                                break;
 #endif
-#if !defined(MKSH_SMALL)
                } else if (tp->val.f == c_trap) {
                        t->u.evalflags &= ~DOTCOMEXEC;
                        break;
                } else if (tp->val.f == c_trap) {
                        t->u.evalflags &= ~DOTCOMEXEC;
                        break;
-#endif
                } else
                        break;
                tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC));
        }
                } else
                        break;
                tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC));
        }
-#if !defined(MKSH_SMALL)
        if (t->u.evalflags & DOTCOMEXEC)
                flags |= XEXEC;
        if (t->u.evalflags & DOTCOMEXEC)
                flags |= XEXEC;
-#endif
        l_expand = e->loc;
        if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN))))
                type_flags = 0;
        l_expand = e->loc;
        if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN))))
                type_flags = 0;
@@ -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))
                /* 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)) {
        }
 
        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 */
 
                /* 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) {
                    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
        *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 */
                /* 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 */
                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 (*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) */
                        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:
                                *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) ||
                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 == /* 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);
                    (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);
                }
                        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 */
        }
        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);
         * 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));
                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;
 dbteste_isa(Test_env *te, Test_meta meta)
 {
        Test_op ret = TO_NONOP;
-       int uqword;
+       bool uqword;
        const char *p;
 
        if (!*te->pos.wp)
        const char *p;
 
        if (!*te->pos.wp)
index e91c0da..057666e 100644 (file)
@@ -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,
 
 /*-
  * 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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
 
 #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 {
 
 /* 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);
 }
 
        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;
 
 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,
 };
 
 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[] = {
  */
 
 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 },
        { 0x05C1, 0x05C2 },
        { 0x05C4, 0x05C5 },
        { 0x05C7, 0x05C7 },
-       { 0x0600, 0x0604 },
+       { 0x0600, 0x0605 },
        { 0x0610, 0x061A },
        { 0x0610, 0x061A },
+       { 0x061C, 0x061C },
        { 0x064B, 0x065F },
        { 0x0670, 0x0670 },
        { 0x06D6, 0x06DD },
        { 0x064B, 0x065F },
        { 0x0670, 0x0670 },
        { 0x06D6, 0x06DD },
@@ -958,8 +958,7 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
        { 0x0825, 0x0827 },
        { 0x0829, 0x082D },
        { 0x0859, 0x085B },
        { 0x0825, 0x0827 },
        { 0x0829, 0x082D },
        { 0x0859, 0x085B },
-       { 0x08E4, 0x08FE },
-       { 0x0900, 0x0902 },
+       { 0x08E4, 0x0902 },
        { 0x093A, 0x093A },
        { 0x093C, 0x093C },
        { 0x0941, 0x0948 },
        { 0x093A, 0x093A },
        { 0x093C, 0x093C },
        { 0x0941, 0x0948 },
@@ -995,16 +994,19 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
        { 0x0B82, 0x0B82 },
        { 0x0BC0, 0x0BC0 },
        { 0x0BCD, 0x0BCD },
        { 0x0B82, 0x0B82 },
        { 0x0BC0, 0x0BC0 },
        { 0x0BCD, 0x0BCD },
+       { 0x0C00, 0x0C00 },
        { 0x0C3E, 0x0C40 },
        { 0x0C46, 0x0C48 },
        { 0x0C4A, 0x0C4D },
        { 0x0C55, 0x0C56 },
        { 0x0C62, 0x0C63 },
        { 0x0C3E, 0x0C40 },
        { 0x0C46, 0x0C48 },
        { 0x0C4A, 0x0C4D },
        { 0x0C55, 0x0C56 },
        { 0x0C62, 0x0C63 },
+       { 0x0C81, 0x0C81 },
        { 0x0CBC, 0x0CBC },
        { 0x0CBF, 0x0CBF },
        { 0x0CC6, 0x0CC6 },
        { 0x0CCC, 0x0CCD },
        { 0x0CE2, 0x0CE3 },
        { 0x0CBC, 0x0CBC },
        { 0x0CBF, 0x0CBF },
        { 0x0CC6, 0x0CC6 },
        { 0x0CCC, 0x0CCD },
        { 0x0CE2, 0x0CE3 },
+       { 0x0D01, 0x0D01 },
        { 0x0D41, 0x0D44 },
        { 0x0D4D, 0x0D4D },
        { 0x0D62, 0x0D63 },
        { 0x0D41, 0x0D44 },
        { 0x0D4D, 0x0D4D },
        { 0x0D62, 0x0D63 },
@@ -1050,13 +1052,14 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
        { 0x17C6, 0x17C6 },
        { 0x17C9, 0x17D3 },
        { 0x17DD, 0x17DD },
        { 0x17C6, 0x17C6 },
        { 0x17C9, 0x17D3 },
        { 0x17DD, 0x17DD },
-       { 0x180B, 0x180D },
+       { 0x180B, 0x180E },
        { 0x18A9, 0x18A9 },
        { 0x1920, 0x1922 },
        { 0x1927, 0x1928 },
        { 0x1932, 0x1932 },
        { 0x1939, 0x193B },
        { 0x1A17, 0x1A18 },
        { 0x18A9, 0x18A9 },
        { 0x1920, 0x1922 },
        { 0x1927, 0x1928 },
        { 0x1932, 0x1932 },
        { 0x1939, 0x193B },
        { 0x1A17, 0x1A18 },
+       { 0x1A1B, 0x1A1B },
        { 0x1A56, 0x1A56 },
        { 0x1A58, 0x1A5E },
        { 0x1A60, 0x1A60 },
        { 0x1A56, 0x1A56 },
        { 0x1A58, 0x1A5E },
        { 0x1A60, 0x1A60 },
@@ -1064,6 +1067,7 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
        { 0x1A65, 0x1A6C },
        { 0x1A73, 0x1A7C },
        { 0x1A7F, 0x1A7F },
        { 0x1A65, 0x1A6C },
        { 0x1A73, 0x1A7C },
        { 0x1A7F, 0x1A7F },
+       { 0x1AB0, 0x1ABE },
        { 0x1B00, 0x1B03 },
        { 0x1B34, 0x1B34 },
        { 0x1B36, 0x1B3A },
        { 0x1B00, 0x1B03 },
        { 0x1B34, 0x1B34 },
        { 0x1B36, 0x1B3A },
@@ -1073,7 +1077,7 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
        { 0x1B80, 0x1B81 },
        { 0x1BA2, 0x1BA5 },
        { 0x1BA8, 0x1BA9 },
        { 0x1B80, 0x1B81 },
        { 0x1BA2, 0x1BA5 },
        { 0x1BA8, 0x1BA9 },
-       { 0x1BAB, 0x1BAB },
+       { 0x1BAB, 0x1BAD },
        { 0x1BE6, 0x1BE6 },
        { 0x1BE8, 0x1BE9 },
        { 0x1BED, 0x1BED },
        { 0x1BE6, 0x1BE6 },
        { 0x1BE8, 0x1BE9 },
        { 0x1BED, 0x1BED },
@@ -1085,12 +1089,13 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
        { 0x1CE2, 0x1CE8 },
        { 0x1CED, 0x1CED },
        { 0x1CF4, 0x1CF4 },
        { 0x1CE2, 0x1CE8 },
        { 0x1CED, 0x1CED },
        { 0x1CF4, 0x1CF4 },
-       { 0x1DC0, 0x1DE6 },
+       { 0x1CF8, 0x1CF9 },
+       { 0x1DC0, 0x1DF5 },
        { 0x1DFC, 0x1DFF },
        { 0x200B, 0x200F },
        { 0x202A, 0x202E },
        { 0x2060, 0x2064 },
        { 0x1DFC, 0x1DFF },
        { 0x200B, 0x200F },
        { 0x202A, 0x202E },
        { 0x2060, 0x2064 },
-       { 0x206A, 0x206F },
+       { 0x2066, 0x206F },
        { 0x20D0, 0x20F0 },
        { 0x2CEF, 0x2CF1 },
        { 0x2D7F, 0x2D7F },
        { 0x20D0, 0x20F0 },
        { 0x2CEF, 0x2CF1 },
        { 0x2D7F, 0x2D7F },
@@ -1113,11 +1118,13 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
        { 0xA9B3, 0xA9B3 },
        { 0xA9B6, 0xA9B9 },
        { 0xA9BC, 0xA9BC },
        { 0xA9B3, 0xA9B3 },
        { 0xA9B6, 0xA9B9 },
        { 0xA9BC, 0xA9BC },
+       { 0xA9E5, 0xA9E5 },
        { 0xAA29, 0xAA2E },
        { 0xAA31, 0xAA32 },
        { 0xAA35, 0xAA36 },
        { 0xAA43, 0xAA43 },
        { 0xAA4C, 0xAA4C },
        { 0xAA29, 0xAA2E },
        { 0xAA31, 0xAA32 },
        { 0xAA35, 0xAA36 },
        { 0xAA43, 0xAA43 },
        { 0xAA4C, 0xAA4C },
+       { 0xAA7C, 0xAA7C },
        { 0xAAB0, 0xAAB0 },
        { 0xAAB2, 0xAAB4 },
        { 0xAAB7, 0xAAB8 },
        { 0xAAB0, 0xAAB0 },
        { 0xAAB2, 0xAAB4 },
        { 0xAAB7, 0xAAB8 },
@@ -1130,7 +1137,7 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
        { 0xABED, 0xABED },
        { 0xFB1E, 0xFB1E },
        { 0xFE00, 0xFE0F },
        { 0xABED, 0xABED },
        { 0xFB1E, 0xFB1E },
        { 0xFE00, 0xFE0F },
-       { 0xFE20, 0xFE26 },
+       { 0xFE20, 0xFE2D },
        { 0xFEFF, 0xFEFF },
        { 0xFFF9, 0xFFFB }
 };
        { 0xFEFF, 0xFEFF },
        { 0xFFF9, 0xFFFB }
 };
@@ -1188,4 +1195,3 @@ utf_wcwidth(unsigned int wc)
                return (2);
        return (1);
 }
                return (2);
        return (1);
 }
-#endif
index 53ab789..77d9494 100644 (file)
@@ -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.44 2013/09/04 15:49:18 millert Exp $       */
 /*     $OpenBSD: c_test.c,v 1.18 2009/03/01 20:11:06 otto 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,
 
 /*-
  * 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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -38,7 +38,7 @@
 #endif
 #endif
 
 #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.256 2014/06/09 13:25:52 tg Exp $");
 
 #if HAVE_KILLPG
 /*
 
 #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
 
 #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)
 /* 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},
        {"*=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},
        {"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;
        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) {
 
 
        switch (**wp) {
 
@@ -721,7 +729,7 @@ c_typeset(const char **wp)
                        flag = LCASEV;
                        break;
                case 'n':
                        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 */
                            SRF_DISABLE : SRF_ENABLE;
                        break;
                /* export, readonly: POSIX -p flag */
@@ -745,8 +753,6 @@ c_typeset(const char **wp)
                        flag = EXPORT;
                        break;
                case '?':
                        flag = EXPORT;
                        break;
                case '?':
- errout:
-                       set_refflag = SRF_NOP;
                        return (1);
                }
                if (builtin_opt.info & GI_PLUS) {
                        return (1);
                }
                if (builtin_opt.info & GI_PLUS) {
@@ -761,10 +767,10 @@ c_typeset(const char **wp)
        }
 
        if (fieldstr && !bi_getn(fieldstr, &field))
        }
 
        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);
        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] &&
        }
 
        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)) ||
        }
 
        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");
                bi_errorf("only -t, -u and -x options may be used with -f");
-               goto errout;
+               return (1);
        }
        if (wp[builtin_opt.optind]) {
                /*
        }
        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 |
                 * 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);
        }
                        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] &&
 
        /* 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");
                                }
                        } 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);
        }
 
                return (rv);
        }
 
-       set_refflag = SRF_NOP;
        /* list variables and attributes */
 
        /* no difference at this point.. */
        /* 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);
                        for (; wp[i]; i++) {
                                if (!bi_getn(wp[i], &n))
                                        return (1);
+#if (NSIG < 128)
                                if (n > 128 && n < 128 + NSIG)
                                        n -= 128;
                                if (n > 128 && n < 128 + NSIG)
                                        n -= 128;
+#endif
                                if (n > 0 && n < NSIG)
                                        shprintf("%s\n", sigtraps[n].name);
                                else
                                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
 
 #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
 /* 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
 
 #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)
 {
 
 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;
        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;
                switch (optc) {
                case 'H':
                        how = HARD;
@@ -3555,31 +3432,32 @@ c_ulimit(const char **wp)
                        all = true;
                        break;
                case '?':
                        all = true;
                        break;
                case '?':
-                       bi_errorf("usage: ulimit [-%s] [value]", opts);
+                       bi_errorf("usage: ulimit [-%s] [value]", rlimits_opts);
                        return (1);
                default:
                        what = optc;
                }
 
                        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);
                }
        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)
        }
        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);
 }
        }
        return (0);
 }
@@ -3611,7 +3489,11 @@ set_ulimit(const struct limits *l, const char *v, int how)
        }
 
        if (getrlimit(l->resource, &limit) < 0) {
        }
 
        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;
        }
                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;
                        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;
                                eno = errno;
                                bi_errorf("%s: %s", fn, cstrerror(eno));
                                rv = 1;
@@ -3761,14 +3643,12 @@ c_cat(const char **wp)
                                break;
                        while (n) {
                                w = write(STDOUT_FILENO, cp, n);
                                break;
                        while (n) {
                                w = write(STDOUT_FILENO, cp, n);
-                               eno = errno;
-                               /* give the user a chance to ^C out */
-                               intrcheck();
                                if (w == -1) {
                                if (w == -1) {
-                                       if (eno == EINTR)
+                                       if (errno == EINTR)
                                                /* interrupted, try again */
                                                continue;
                                        /* an error occured during writing */
                                                /* interrupted, try again */
                                                continue;
                                        /* an error occured during writing */
+                                       eno = errno;
                                        bi_errorf("%s: %s", "<stdout>",
                                            cstrerror(eno));
                                        rv = 1;
                                        bi_errorf("%s: %s", "<stdout>",
                                            cstrerror(eno));
                                        rv = 1;
@@ -3844,3 +3724,24 @@ c_sleep(const char **wp)
        return (rv);
 }
 #endif
        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
index 3b28f23..d15cc8d 100644 (file)
@@ -3,7 +3,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 
 /*-
  * 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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -27,7 +27,7 @@
 #include <sys/file.h>
 #endif
 
 #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;
 
 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 {
                        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)
 
                /* 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
  * 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;
 {
        char **hp;
        int maxhist = histptr - history;
@@ -720,7 +720,8 @@ hist_init(Source *s)
 
  retry:
        /* we have a file and are interactive */
 
  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);
                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 |
                        /* 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;
                        }
                                /* 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. */
        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) {
        for (i = 0; i <= NSIG; i++) {
                sigtraps[i].signal = i;
                if (i == ksh_SIGERR) {
index 3277c78..0216a34 100644 (file)
@@ -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,
 
 /*-
  * 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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
 
 #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.104 2014/06/10 22:17:09 tg Exp $");
 
 #if HAVE_KILLPG
 #define mksh_killpg            killpg
 
 #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)
 /* job cleanup before shell exit */
 void
 j_exit(void)
@@ -1222,6 +1270,15 @@ j_waitj(Job *j,
                                rv = vp->val.i;
                        p = p->next;
                }
                                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)
        }
 
        if (!(flags & JW_ASYNCNOTIFY)
@@ -1281,7 +1338,11 @@ j_sigchld(int sig MKSH_A_UNUSED)
        getrusage(RUSAGE_CHILDREN, &ru0);
        do {
 #ifndef MKSH_NOPROSPECTOFWORK
        getrusage(RUSAGE_CHILDREN, &ru0);
        do {
 #ifndef MKSH_NOPROSPECTOFWORK
-               pid = waitpid(-1, &status, (WNOHANG|WUNTRACED));
+               pid = waitpid(-1, &status, (WNOHANG |
+#ifdef WCONTINUED
+                   WCONTINUED |
+#endif
+                   WUNTRACED));
 #else
                pid = wait(&status);
 #endif
 #else
                pid = wait(&status);
 #endif
@@ -1320,6 +1381,13 @@ j_sigchld(int sig MKSH_A_UNUSED)
                if (WIFSTOPPED(status))
                        p->state = PSTOPPED;
                else
                if (WIFSTOPPED(status))
                        p->state = PSTOPPED;
                else
+#ifdef 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;
 #endif
                  if (WIFSIGNALED(status))
                        p->state = PSIGNALLED;
index e58d8b8..9d39998 100644 (file)
--- a/src/lex.c
+++ b/src/lex.c
@@ -1,8 +1,8 @@
-/*     $OpenBSD: lex.c,v 1.47 2013/03/03 19:11:34 guenther Exp $       */
+/*     $OpenBSD: lex.c,v 1.49 2013/12/17 16:37:06 deraadt Exp $        */
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 
 /*-
  * 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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
 
 #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
 
 /*
  * states while lexing word
@@ -159,9 +159,10 @@ getsc_r(int c)
        state = statep->type;                                   \
 } while (/* CONSTCOND */ 0)
 
        state = statep->type;                                   \
 } while (/* CONSTCOND */ 0)
 
-#define PUSH_SRETRACE()        do {                                    \
+#define PUSH_SRETRACE(s) do {                                  \
        struct sretrace_info *ri;                               \
                                                                \
        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);                       \
        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);                                       \
        dp = (void *)retrace_info;                              \
        retrace_info = retrace_info->next;                      \
        afree(dp, ATEMP);                                       \
+       POP_STATE();                                            \
 } while (/* CONSTCOND */ 0)
 
 /**
 } while (/* CONSTCOND */ 0)
 
 /**
@@ -404,9 +406,8 @@ yylex(int cf)
                                        c = getsc();
                                        if (c == '(') /*)*/ {
                                                *wp++ = EXPRSUB;
                                        c = getsc();
                                        if (c == '(') /*)*/ {
                                                *wp++ = EXPRSUB;
-                                               PUSH_STATE(SASPAREN);
+                                               PUSH_SRETRACE(SASPAREN);
                                                statep->nparen = 2;
                                                statep->nparen = 2;
-                                               PUSH_SRETRACE();
                                                *retrace_info->xp++ = '(';
                                        } else {
                                                ungetsc(c);
                                                *retrace_info->xp++ = '(';
                                        } else {
                                                ungetsc(c);
@@ -650,7 +651,6 @@ yylex(int cf)
                                if (statep->nparen == 1) {
                                        /* end of EXPRSUB */
                                        POP_SRETRACE();
                                if (statep->nparen == 1) {
                                        /* end of EXPRSUB */
                                        POP_SRETRACE();
-                                       POP_STATE();
 
                                        if ((c2 = getsc()) == /*(*/ ')') {
                                                cz = strlen(sp) - 2;
 
                                        if ((c2 = getsc()) == /*(*/ ')') {
                                                cz = strlen(sp) - 2;
@@ -833,8 +833,7 @@ yylex(int cf)
                                } else if (c2 == '"') {
                                        /* FALLTHROUGH */
                        case '"':
                                } else if (c2 == '"') {
                                        /* FALLTHROUGH */
                        case '"':
-                                       state = statep->type = SHEREDQUOTE;
-                                       PUSH_SRETRACE();
+                                       PUSH_SRETRACE(SHEREDQUOTE);
                                        break;
                                }
                                ungetsc(c2);
                                        break;
                                }
                                ungetsc(c2);
@@ -1440,6 +1439,7 @@ getsc_line(Source *s)
                alarm(0);
        }
        cp = Xstring(s->xs, xp);
                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 */
        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
 pprompt(const char *cp, int ntruncate)
 {
-       int columns = 0, lines = 0;
-       bool indelimit = false;
        char delimiter = 0;
        char delimiter = 0;
+       bool doprint = (ntruncate != -1);
+       bool indelimit = false;
+       int columns = 0, lines = 0;
 
        /*
         * Undocumented AT&T ksh feature:
 
        /*
         * 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);
                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++;
                                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);
        }
                    (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);
 }
 
        return (x_cols * lines + columns);
 }
 
index 291ab40..cc49349 100644 (file)
@@ -1,11 +1,11 @@
-/*     $OpenBSD: main.c,v 1.52 2013/06/15 17:25:19 millert Exp $       */
+/*     $OpenBSD: main.c,v 1.54 2013/11/28 10:33:37 sobrado Exp $       */
 /*     $OpenBSD: tty.c,v 1.9 2006/03/14 22:08:01 deraadt 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: io.c,v 1.23 2013/12/17 16:37:06 deraadt 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,
 /*     $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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -34,7 +34,7 @@
 #include <locale.h>
 #endif
 
 #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.280 2014/06/09 12:28:17 tg Exp $");
 
 extern char **environ;
 
 
 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 **);
 
 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 *);
 void chvt_reinit(void);
 static void reclaim(void);
 static void remove_temps(struct temp *);
@@ -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",
        /* 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",
 #endif
        "autoload=typeset -fu",
        "functions=typeset -f",
@@ -144,21 +142,6 @@ rndsetup(void)
        return ((mksh_uari_t)h);
 }
 
        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)
 {
 void
 chvt_reinit(void)
 {
@@ -247,6 +230,23 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
        if (!*ccp)
                ccp = empty_argv[0];
 
        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 */
        /* 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);
 
        /* 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
 #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 */
 #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);
                        typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
+                       ++wp;
+               }
+       }
 
        /* for security */
        typeset(initifs, 0, 0, 0, 0);
 
        /* for security */
        typeset(initifs, 0, 0, 0, 0);
@@ -421,7 +407,7 @@ 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 */
        setint_n((vp_pipest = global("PIPESTATUS")), 0, 10);
 
        /* Set this before parsing arguments */
-       Flag(FPRIVILEGED) = kshuid != ksheuid || kshgid != kshegid;
+       Flag(FPRIVILEGED) = (kshuid != ksheuid || kshgid != kshegid) ? 2 : 0;
 
        /* this to note if monitor is set on command line (see below) */
 #ifndef MKSH_UNEMPLOYED
 
        /* this to note if monitor is set on command line (see below) */
 #ifndef MKSH_UNEMPLOYED
@@ -436,44 +422,6 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
                        return (1);
        }
 
                        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;
        /* process this later only, default to off (hysterical raisins) */
        utf_flag = UTFMODE;
        UTFMODE = 0;
@@ -485,7 +433,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");
                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;
                while (*s->str) {
                        if (*s->str != ' ' && ctype(*s->str, C_QUOTE))
                                break;
@@ -494,7 +441,6 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
                if (!*s->str)
                        s->flags |= SF_MAYEXEC;
                s->str = s->start;
                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], "--"))
 #ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
                /* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */
                if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--"))
@@ -543,12 +489,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;
 #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
                        utf_flag = 1;
 #else
                        /* always disable UTF-8 (for interactive) */
                        utf_flag = 0;
 #endif
+#endif
                }
 #ifndef MKSH_NO_CMDLINE_EDITING
                x_init();
                }
 #ifndef MKSH_NO_CMDLINE_EDITING
                x_init();
@@ -637,22 +585,22 @@ 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 (!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);
                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);
                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) {
@@ -873,11 +821,8 @@ shell(Source * volatile s, volatile bool toplevel)
                                        unwind(LEXIT);
                                break;
                        }
                                        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;
                        t->u.evalflags |= DOTCOMEXEC;
-#endif
                if (!Flag(FNOEXEC) || (s->flags & SF_TTY))
                        exstat = execute(t, 0, NULL) & 0xFF;
 
                if (!Flag(FNOEXEC) || (s->flags & SF_TTY))
                        exstat = execute(t, 0, NULL) & 0xFF;
 
@@ -1659,7 +1604,8 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist)
        } while (len < 5);
 
        /* cyclically attempt to open a temporary file */
        } 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 */
                if (errno != EEXIST)
                        goto maketemp_out;
                /* count down from z to a then from 9 to 0 */
@@ -1921,9 +1867,10 @@ x_mkraw(int fd, mksh_ttyst *ocb, bool forread)
 
        cb = *ocb;
        if (forread) {
 
        cb = *ocb;
        if (forread) {
+               cb.c_iflag &= ~(ISTRIP);
                cb.c_lflag &= ~(ICANON) | ECHO;
        } else {
                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)
                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 (file)
index 0000000..481aac0
--- /dev/null
@@ -0,0 +1,218 @@
+/*-
+ * 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).
+ */
+
+#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.2 2014/06/29 11:48:05 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
index adf4bc4..82d47d6 100644 (file)
@@ -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,
 /*     $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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -30,7 +30,7 @@
 #include <grp.h>
 #endif
 
 #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
 
 #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 *,
 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 *,
 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
 #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
 
 
 #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])
 
 #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
 
 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();
 
                /*XXX this can probably be optimised */
                kshegid = kshgid = getgid();
+               ksheuid = kshuid = getuid();
 #if HAVE_SETRESUGID
                DO_SETUID(setresgid, (kshegid, kshegid, kshegid));
 #if HAVE_SETGROUPS
 #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));
                setgroups(1, &kshegid);
 #endif
                DO_SETUID(setresuid, (ksheuid, ksheuid, ksheuid));
-#else
+#else /* !HAVE_SETRESUGID */
                /* seteuid, setegid, setgid don't EAGAIN on Linux */
                /* seteuid, setegid, setgid don't EAGAIN on Linux */
-               ksheuid = kshuid = getuid();
 #ifndef MKSH__NO_SETEUGID
                seteuid(ksheuid);
 #endif
 #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);
                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;
        } 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)
 {
     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;
        bool set;
-       char *opts;
+       const char *opts;
        const char *array = NULL;
        Getopt go;
        size_t i;
        const char *array = NULL;
        Getopt go;
        size_t i;
@@ -352,36 +363,6 @@ parse_args(const char **argv,
        bool sortargs = false;
        bool fcompatseen = false;
 
        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;
                /*
        if (what == OF_CMDLINE) {
                const char *p = argv[0], *q;
                /*
@@ -1972,7 +1953,6 @@ c_cd(const char **wp)
 
 
 #ifdef KSH_CHVT_CODE
 
 
 #ifdef KSH_CHVT_CODE
-extern uint32_t chvt_rndsetup(const void *, size_t);
 extern void chvt_reinit(void);
 
 static void
 extern void chvt_reinit(void);
 
 static void
@@ -2016,9 +1996,9 @@ chvt(const Getopt *go)
 #endif
            }
        }
 #endif
            }
        }
-       if ((fd = open(dv, O_RDWR)) < 0) {
+       if ((fd = open(dv, O_RDWR | O_BINARY)) < 0) {
                sleep(1);
                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);
                }
        }
                        errorf("%s: %s %s", "chvt", "can't open", dv);
                }
        }
index 621aa97..19291ce 100644 (file)
@@ -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.336 2014/06/24 20:47:44 tg Exp $
+.\" $OpenBSD: ksh.1,v 1.152 2014/02/12 16:28:13 schwarze Exp $
 .\"-
 .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
 .\"-
 .\" 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
 .\"    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.
 .\"
 .\" 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: June 24 2014 $
 .\"
 .\" Check which macro package we use, and do other -mdoc setup.
 .\"
 .\"
 .\" Check which macro package we use, and do other -mdoc setup.
 .\"
@@ -247,8 +247,7 @@ below.
 Privileged shell.
 A shell is
 .Dq privileged
 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
 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 .
 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
 .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.
 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
 .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 =
 .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:
 .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.
 .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
 .El
 .El
 .Ss Quoting
@@ -1123,7 +1129,6 @@ nameref=\*(aqtypeset \-n\*(aq
 nohup=\*(aqnohup \*(aq
 r=\*(aqfc \-e \-\*(aq
 stop=\*(aqkill \-STOP\*(aq
 nohup=\*(aqnohup \*(aq
 r=\*(aqfc \-e \-\*(aq
 stop=\*(aqkill \-STOP\*(aq
-suspend=\*(aqkill \-STOP $$\*(aq
 type=\*(aqwhence \-v\*(aq
 .Ed
 .Pp
 type=\*(aqwhence \-v\*(aq
 .Ed
 .Pp
@@ -1685,17 +1690,10 @@ Currently,
 must start with a space, opening parenthesis or digit to be recognised.
 Cannot be applied to a vector.
 .Pp
 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
 .Pp
 .It Pf ${ Ns Ar name Ns @Q}
 A quoted expression safe for re-entry, whose value is the value of the
@@ -2037,7 +2035,7 @@ in reverse video
 in the prompt string:
 .Bd -literal -offset indent
 x=$(print \e\e001)
 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,
 .Ed
 .Pp
 Due to a strong suggestion from David G. Korn,
@@ -2592,7 +2590,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
 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 ;
 .Ic posix
 mode
 .Em only ;
@@ -2953,8 +2951,9 @@ Builtins that are not special:
 .Ic false , fc , fg , getopts ,
 .Ic jobs , kill , let , mknod ,
 .Ic print , pwd , read , realpath ,
 .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.
 .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 +3410,7 @@ and
 .Ar last
 select commands from the history.
 Commands can be selected by history number
 .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
 or a string specifying the most recent command starting with that string.
 The
 .Fl l
@@ -3623,7 +3623,7 @@ Since expressions may need to be quoted,
 is syntactic sugar for
 .No let \&" Ns Ar expr Ns \&" .
 .Pp
 is syntactic sugar for
 .No let \&" Ns Ar expr Ns \&" .
 .Pp
-.It let]
+.It Ic let]
 Internally used alias for
 .Ic let .
 .Pp
 Internally used alias for
 .Ic let .
 .Pp
@@ -4036,6 +4036,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.
 .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
 .It Fl e \*(Ba Fl o Ic errexit
 Exit (after executing the
 .Dv ERR
@@ -4242,6 +4248,9 @@ mode.
 Enable
 .Xr vi 1 Ns -like
 command-line editing (interactive shells only).
 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.
 .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 +4324,16 @@ and
 .Nm mksh ,
 this is implemented as a shell alias instead of a builtin.
 .Pp
 .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
 .It Ic test Ar expression
 .It Ic \&[ Ar expression Ic \&]
 .Ic test
@@ -4878,7 +4897,7 @@ unless they are also given on the same command line.
 .Pp
 .It Xo
 .Ic ulimit
 .Pp
 .It Xo
 .Ic ulimit
-.Op Fl aBCcdefHiLlMmnOPpqrSsTtVvw
+.Op Fl aBCcdefHilMmnOPpqrSsTtVvw
 .Op Ar value
 .Xc
 Display or set process limits.
 .Op Ar value
 .Xc
 Display or set process limits.
@@ -4929,8 +4948,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 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
 .It Fl l Ar n
 Impose a limit of
 .Ar n
@@ -5673,6 +5690,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.
 .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
 .Pp
 The vi command-line editor in
 .Nm
@@ -6307,15 +6325,15 @@ contains the system and suid profile.
 .%A Stephen G. Kochan
 .%A Patrick H. Wood
 .%B "\\*(tNUNIX\\*(sP Shell Programming"
 .%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."
 .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"
 .%V "Part 2: Shell and Utilities"
 .%D 1993
 .%I "IEEE Press"
@@ -6348,24 +6366,35 @@ contains the system and suid profile.
 .%O "ISBN 978\-0\-201\-56324\-5 (0\-201\-56324\-X)"
 .Re
 .Sh AUTHORS
 .%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.
 .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.
 See the documentation, CVS, and web site for details.
 .Pp
 The BSD daemon is Copyright \(co Marshall Kirk McKusick.
@@ -6425,7 +6454,7 @@ $ /bin/sleep 666 && echo fubar
 .Ed
 .Pp
 This document attempts to describe
 .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 ,
 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 (file)
index 0000000..ef71dab
--- /dev/null
@@ -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 (file)
index 0000000..6c3908b
--- /dev/null
@@ -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
index 5a95190..be716ab 100644 (file)
--- a/src/sh.h
+++ b/src/sh.h
@@ -1,16 +1,16 @@
-/*     $OpenBSD: sh.h,v 1.31 2012/09/10 01:25:30 tedu Exp $    */
+/*     $OpenBSD: sh.h,v 1.33 2013/12/18 13:53:12 millert Exp $ */
 /*     $OpenBSD: shf.h,v 1.6 2005/12/11 18:53:51 deraadt Exp $ */
 /*     $OpenBSD: table.h,v 1.8 2012/02/19 07:52:30 otto Exp $  */
 /*     $OpenBSD: tree.h,v 1.10 2005/03/28 21:28:22 deraadt Exp $       */
 /*     $OpenBSD: expand.h,v 1.6 2005/03/30 17:16:37 deraadt Exp $      */
 /*     $OpenBSD: lex.h,v 1.13 2013/03/03 19:11:34 guenther Exp $       */
 /*     $OpenBSD: 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,
 /*     $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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
 
 #undef __attribute__
 #if HAVE_ATTRIBUTE_BOUNDED
 
 #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
 #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
 #else
 #define MKSH_A_FORMAT(x,y,z)   /* nothing */
 #endif
 #else
 #define MKSH_A_NORETURN                /* nothing */
 #endif
 #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
 #if HAVE_ATTRIBUTE_UNUSED
 #define MKSH_A_UNUSED          __attribute__((__unused__))
 #else
 #endif
 
 #ifdef EXTERN
 #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.691 2014/06/29 11:28:28 tg Exp $");
 #endif
 #endif
-#define MKSH_VERSION "R48 2013/08/14"
+#define MKSH_VERSION "R50 2014/06/29"
 
 /* arithmetic types: C implementation */
 #if !HAVE_CAN_INTTYPES
 
 /* 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_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))
 #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)
 #define NSIG           (SIGMAX+1)
 #elif defined(_SIGMAX)
 #define NSIG           (_SIGMAX+1)
+#else
+# error Please have your platform define NSIG.
+#define NSIG           64
+#endif
 #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
 
 
 #endif
 
 
@@ -396,6 +411,10 @@ extern int __cdecl setegid(gid_t);
 #endif
 #endif
 
 #endif
 #endif
 
+#ifndef O_BINARY
+#define O_BINARY       0
+#endif
+
 #ifdef MKSH__NO_SYMLINK
 #undef S_ISLNK
 #define S_ISLNK(m)     (/* CONSTCOND */ 0)
 #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
 
 #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
 
 
 #endif
 
 
@@ -518,7 +533,7 @@ char *ucstrstr(char *, const char *);
 #define mkssert(e)     do { } while (/* CONSTCOND */ 0)
 #endif
 
 #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 != 501)
 #error Must run Build.sh to compile this.
 extern void thiswillneverbedefinedIhope(void);
 int
 #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
  */
 enum sh_flag {
 #define SHFLAGS_ENUMS
-#include "sh_flags.h"
+#include "sh_flags.gen"
        FNFLAGS         /* (place holder: how many flags are there) */
 };
 
        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))
 
 #define arrayindex(vp) ((unsigned long)((vp)->flag & AINDEX ? \
                            (vp)->ua.index : 0))
 
-EXTERN enum {
+enum namerefflag {
        SRF_NOP,
        SRF_ENABLE,
        SRF_DISABLE
        SRF_NOP,
        SRF_ENABLE,
        SRF_DISABLE
-} set_refflag E_INIT(SRF_NOP);
+};
 
 /* command types */
 #define CNONE          0       /* undefined */
 
 /* command types */
 #define CNONE          0       /* undefined */
@@ -1380,22 +1395,7 @@ 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 */
 #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 */
 #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 X_EXTRA        20      /* this many extra bytes in X string */
 
 
 #define X_EXTRA        20      /* this many extra bytes in X string */
 
@@ -1426,7 +1426,7 @@ typedef char *XStringP;
 #define XcheckN(xs, xp, n) do {                                        \
        ssize_t more = ((xp) + (n)) - (xs).end;                 \
        if (more > 0)                                           \
 #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 */
 } while (/* CONSTCOND */ 0)
 
 /* check for overflow, expand string */
@@ -1526,9 +1526,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) */
 #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 */
 #define SF_MAYEXEC     BIT(5)  /* special sh -c optimisation hack */
-#endif
 
 typedef union {
        int i;
 
 typedef union {
        int i;
@@ -1587,6 +1585,7 @@ typedef union {
 #undef CTRL
 #define        CTRL(x)         ((x) == '?' ? 0x7F : (x) & 0x1F)        /* ASCII */
 #define        UNCTRL(x)       ((x) ^ 0x40)                            /* ASCII */
 #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
 
 
 #define IDENT          64
 
@@ -1614,48 +1613,6 @@ EXTERN struct timeval j_usrtime, j_systime;
 } while (/* CONSTCOND */ 0)
 
 
 } 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 *);
 /* lalloc.c */
 void ainit(Area *);
 void afreeall(Area *);
@@ -1706,12 +1663,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_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 */
 int ksh_access(const char *, int);
 struct tbl *tempvar(void);
 /* funcs.c */
@@ -1779,10 +1734,10 @@ void sethistsize(mksh_ari_t);
 void sethistfile(const char *);
 #endif
 #if !defined(MKSH_NO_CMDLINE_EDITING) && !MKSH_S_NOVI
 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 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);
 char **hist_get_newest(bool);
 void inittraps(void);
 void alarm_init(void);
@@ -1818,6 +1773,9 @@ int j_kill(const char *, int);
 #ifndef MKSH_UNEMPLOYED
 int j_resume(const char *, int);
 #endif
 #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);
 int j_jobs(const char *, int, int);
 void j_notify(void);
 pid_t j_async(void);
@@ -1895,15 +1853,15 @@ void DF(const char *, ...)
 /* misc.c */
 void setctypes(const char *, int);
 void initctypes(void);
 /* 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);
 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 *);
 void ksh_getopt_reset(Getopt *, int);
 int ksh_getopt(const char **, Getopt *, const char *);
 void print_value_quoted(struct shf *, const char *);
@@ -1995,19 +1953,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);
 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);
 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 **);
 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);
 mksh_ari_t rndget(void);
 void rndset(unsigned long);
+void rndpush(const void *);
 
 enum Test_op {
        /* non-operator */
 
 enum Test_op {
        /* non-operator */
@@ -2058,10 +2018,11 @@ typedef struct test_env {
 
 extern const char * const dbtest_tokens[];
 
 
 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 *);
 
 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 */
 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 (file)
index 0000000..cff2e87
--- /dev/null
@@ -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 (file)
index 3e4cf56..0000000
+++ /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 (file)
index 0000000..99e4a22
--- /dev/null
@@ -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
index e8ec14a..33e89bd 100644 (file)
--- a/src/shf.c
+++ b/src/shf.c
@@ -25,7 +25,7 @@
 
 #include "sh.h"
 
 
 #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 */
 
 /* 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. */
 
        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);
        if (fd < 0) {
                eno = errno;
                afree(shf, shf->areap);
diff --git a/src/signames.inc b/src/signames.inc
new file mode 100644 (file)
index 0000000..07811fd
--- /dev/null
@@ -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 },
index 53f9130..c0ebfd5 100644 (file)
@@ -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>
  *
  *     Thorsten Glaser <tg@mirbsd.org>
  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  *
 
 #include "sh.h"
 
 
 #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.
  */
 
 /*
  * 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)
 {
 size_t
 strlcpy(char *dst, const char *src, size_t siz)
 {
index 5c07d51..6a544df 100644 (file)
--- a/src/syn.c
+++ b/src/syn.c
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009,
 
 /*-
  * 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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
 
 #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) */
 
 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 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 *,
 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));
 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;
 
        char *save = NULL;
        Test_op ret = TO_NONOP;
 
index dcbd7a1..8026f8b 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
 
 #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
 
 
 #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 (--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) ? '$' : '^';
                /* 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 */
        } 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;
                c = '?';
        }
        *dst++ = c;
@@ -801,10 +802,10 @@ vistree(char *dst, size_t sz, struct op *t)
 void
 dumpchar(struct shf *shf, int c)
 {
 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);
                /* C0 or C1 control character or DEL */
                shf_putc((c & 0x80) ? '$' : '^', shf);
-               c = (c & 0x7F) ^ 0x40;
+               c = UNCTRL(c & 0x7F);
        }
        shf_putc(c, shf);
 }
        }
        shf_putc(c, shf);
 }
index ba8fd82..ef114e1 100644 (file)
--- a/src/var.c
+++ b/src/var.c
@@ -1,8 +1,8 @@
-/*     $OpenBSD: var.c,v 1.35 2013/04/05 01:31:30 tedu Exp $   */
+/*     $OpenBSD: var.c,v 1.38 2013/12/20 17:53:09 zhuk Exp $   */
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 
 /*-
  * 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
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
  */
 
 #include "sh.h"
  */
 
 #include "sh.h"
+#include "mirhash.h"
 
 #if defined(__OpenBSD__)
 #include <sys/sysctl.h>
 #endif
 
 
 #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.180 2014/06/26 20:36:02 tg Exp $");
 
 /*-
  * Variables
 
 /*-
  * 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 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 *);
 
 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
 /*
  * 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)
  */
 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);
        *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;
 
                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);
                /* 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! */
                        char *cp;
 
                        /* gotcha! */
@@ -195,6 +199,7 @@ array_index_calc(const char *n, bool *arrayp, uint32_t *valp)
                        goto redo_from_ref;
                }
        }
                        goto redo_from_ref;
                }
        }
+       innermost_refflag = SRF_NOP;
 
        if (p != n && *p == '[' && (len = array_ref_len(p))) {
                char *sub, *tmp;
 
        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;
 
        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);
        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");
        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)) {
                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;
                                /* 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;
 
        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);
        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;
        }
                base = 8;
                have_base = true;
        }
-       while ((c = *s++)) {
+       while ((c = (unsigned char)*s++)) {
                if (c == '-') {
                        neg = true;
                        continue;
                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;
        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);
 
        /* 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 == '[') {
                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);
                        errorf("%s: %s", var,
                            "reference variable can't be an array");
                len = array_ref_len(val);
@@ -756,18 +775,32 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
                        tvar[len - 3] = '\0';
        }
 
                        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)
 
                /* 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);
                }
                /* find value if variable already exists */
                if ((qval = val) == NULL) {
                        varsearch(e->loc, &vp, tvar, hash(tvar));
                        if (vp != NULL)
                                qval = str_val(vp);
                }
+               /* check target value for being a valid variable name */
+               ccp = skip_varname(qval, false);
+               if (ccp == qval)
+                       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");
+               }
                /* prevent nameref loops */
                while (qval) {
                        if (!strcmp(qval, tvar))
                /* prevent nameref loops */
                while (qval) {
                        if (!strcmp(qval, tvar))
@@ -775,7 +808,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;
                                    "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);
                }
        }
                                qval = str_val(vp);
                }
        }
@@ -785,11 +818,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");
 
            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);
            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;
                vp->flag &= ~ASSOC;
-       else if (set_refflag == SRF_ENABLE) {
+       else if (new_refflag == SRF_ENABLE) {
                if (vp->flag & ARRAY) {
                        struct tbl *a, *tmp;
 
                if (vp->flag & ARRAY) {
                        struct tbl *a, *tmp;
 
@@ -809,14 +843,14 @@ typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
 
        set &= ~(LOCAL|LOCAL_COPY);
 
 
        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)
         */
 
        /*
         * 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);
            (val || clr || (set & ~EXPORT)))
                /* XXX check calls - is error here ok by POSIX? */
                errorfx(2, "read-only: %s", tvar);
@@ -960,7 +994,7 @@ unset(struct tbl *vp, int flags)
  * the terminating NUL if whole string is legal).
  */
 const char *
  * 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;
 
 {
        size_t alen;
 
@@ -1338,7 +1372,7 @@ arraysearch(struct tbl *vp, uint32_t val)
        struct tbl *prev, *curr, *news;
        size_t len;
 
        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);
        /* the table entry is always [0] */
        if (val == 0)
                return (vp);
@@ -1378,6 +1412,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.
  * 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)
  */
 size_t
 array_ref_len(const char *cp)
@@ -1458,6 +1494,7 @@ set_array(const char *var, bool reset, const char **vals)
                afree(cp, ATEMP);
        }
        while ((ccp = vals[i])) {
                afree(cp, ATEMP);
        }
        while ((ccp = vals[i])) {
+#if 0 /* temporarily taken out due to regression */
                if (*ccp == '[') {
                        int level = 0;
 
                if (*ccp == '[') {
                        int level = 0;
 
@@ -1478,6 +1515,7 @@ set_array(const char *var, bool reset, const char **vals)
                        } else
                                ccp = vals[i];
                }
                        } else
                                ccp = vals[i];
                }
+#endif
 
                vq = arraysearch(vp, j);
                /* would be nice to deal with errors here... (see above) */
 
                vq = arraysearch(vp, j);
                /* would be nice to deal with errors here... (see above) */
@@ -1492,6 +1530,11 @@ set_array(const char *var, bool reset, const char **vals)
 void
 change_winsz(void)
 {
 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) {
 #ifdef TIOCGWINSZ
        /* check if window size has changed */
        if (tty_init_fd() < 2) {
@@ -1522,9 +1565,28 @@ hash(const void *s)
 {
        register uint32_t h;
 
 {
        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);
 }
 
        return (h);
 }
 
@@ -1542,28 +1604,67 @@ void
 rndset(unsigned long v)
 {
        register uint32_t h;
 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
 
 
-       NZATInit(h);
-       NZATUpdateMem(h, &lcg_state, sizeof(lcg_state));
-       NZATUpdateMem(h, &v, sizeof(v));
+       h = lcg_state;
+       BAFHFinish_reg(h);
+       BAFHUpdateMem_reg(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)
 
 #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
         */
        /*
         * 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
 #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
 
 #endif
 
-       NZAATFinish(h);
+       BAFHUpdateMem_reg(h, &z, sizeof(z));
+       BAFHFinish_reg(h);
        lcg_state = 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;
+}