OSDN Git Service

Upgrade to mksh 50f.
authorElliott Hughes <enh@google.com>
Tue, 21 Apr 2015 20:39:18 +0000 (13:39 -0700)
committerElliott Hughes <enh@google.com>
Tue, 21 Apr 2015 20:39:18 +0000 (13:39 -0700)
Bug: http://b/20101805
Change-Id: Ic311851b31217517f6c201b5ec68a0668577eddf

21 files changed:
Android.mk
Makefrag.inc
src/Build.sh
src/check.pl
src/check.t
src/dot.mkshrc
src/edit.c
src/eval.c
src/exec.c
src/funcs.c
src/histrap.c
src/jobs.c
src/lex.c
src/lksh.1
src/main.c
src/misc.c
src/mksh.1
src/sh.h
src/syn.c
src/tree.c
src/var.c

index e208225..a78409f 100644 (file)
@@ -79,6 +79,6 @@ LOCAL_CFLAGS += \
     -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 \
     -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \
     -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 \
-    -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=505
+    -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=506
 
 include $(BUILD_EXECUTABLE)
index c5d5f6d..9c3632b 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile fragment for building mksh R50 2015/03/01
+# Makefile fragment for building mksh R50 2015/04/19
 
 PROG=          mksh
 MAN=           mksh.1
@@ -10,7 +10,7 @@ NONSRCS_INST= dot.mkshrc $(MAN)
 NONSRCS_NOINST=        Build.sh Makefile Rebuild.sh check.pl check.t test.sh
 CC=            /huge-ssd/aosp-arm64/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/*-gcc
 CFLAGS=                 -fno-exceptions -Wno-multichar -fpic -fPIE -ffunction-sections -fdata-sections -funwind-tables -fstack-protector -Wa,--noexecstack -Werror=format-security -fno-short-enums -Wno-unused-but-set-variable -fno-builtin-sin -fno-strict-volatile-bitfields -Wno-psabi -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -g -Wstrict-aliasing=2 -fgcse-after-reload -frerun-cse-after-loop -frename-registers -Os -fomit-frame-pointer -fno-strict-aliasing -Wno-deprecated-declarations -fno-asynchronous-unwind-tables -fstack-protector-strong -fwrapv
-CPPFLAGS=      -I. -I'../src'  -isystem /huge-ssd/aosp-arm64/bionic/libc/arch-arm64/include -isystem /huge-ssd/aosp-arm64/bionic/libc/include -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi/asm-arm64 -isystem /huge-ssd/aosp-arm64/bionic/libm/include -isystem /huge-ssd/aosp-arm64/bionic/libm/include/arm64 -D_FORTIFY_SOURCE=2 -include /huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/AndroidConfig.h -I/huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/ -DANDROID -DNDEBUG -UDEBUG -DDEBUG_LEAKS -DMKSH_ASSUME_UTF8 -DMKSH_CONSERVATIVE_FDS -DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN -DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 -DHAVE_ATTRIBUTE_NORETURN=1 -DHAVE_ATTRIBUTE_PURE=1 -DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 -DHAVE_SYS_TIME_H=1 -DHAVE_TIME_H=1 -DHAVE_BOTH_TIME_H=1 -DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 -DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 -DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 -DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 -DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 -DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_ERRLIST=0 -DHAVE_SYS_SIGNAME=1 -DHAVE_SYS_SIGLIST=1 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 -DHAVE_GETRUSAGE=1 -DHAVE_GETSID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_ISSETUGID=0 -DHAVE_KILLPG=1 -DHAVE_MEMMOVE=1 -DHAVE_MKNOD=0 -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=0 -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=505
+CPPFLAGS=      -I. -I'../src'  -isystem /huge-ssd/aosp-arm64/bionic/libc/arch-arm64/include -isystem /huge-ssd/aosp-arm64/bionic/libc/include -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi -isystem /huge-ssd/aosp-arm64/bionic/libc/kernel/uapi/asm-arm64 -isystem /huge-ssd/aosp-arm64/bionic/libm/include -isystem /huge-ssd/aosp-arm64/bionic/libm/include/arm64 -D_FORTIFY_SOURCE=2 -include /huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/AndroidConfig.h -I/huge-ssd/aosp-arm64/build/core/combo/include/arch/linux-arm64/ -DANDROID -DNDEBUG -UDEBUG -DDEBUG_LEAKS -DMKSH_ASSUME_UTF8 -DMKSH_CONSERVATIVE_FDS -DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN -DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 -DHAVE_ATTRIBUTE_NORETURN=1 -DHAVE_ATTRIBUTE_PURE=1 -DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 -DHAVE_SYS_TIME_H=1 -DHAVE_TIME_H=1 -DHAVE_BOTH_TIME_H=1 -DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 -DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 -DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 -DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 -DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 -DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_ERRLIST=0 -DHAVE_SYS_SIGNAME=1 -DHAVE_SYS_SIGLIST=1 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 -DHAVE_GETRUSAGE=1 -DHAVE_GETSID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_ISSETUGID=0 -DHAVE_KILLPG=1 -DHAVE_MEMMOVE=1 -DHAVE_MKNOD=0 -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=0 -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=506
 LDFLAGS=        -nostdlib -Bdynamic -fPIE -pie -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined /huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib/crtbegin_dynamic.o
 LIBS=           -L/huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib -Wl,-rpath-link=/huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib -Wl,--no-whole-archive /huge-ssd/aosp-arm64/out/target/product/flounder/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a -lc /huge-ssd/aosp-arm64/out/target/product/flounder/obj/lib/crtend_android.o
 
index 5c90eb8..70c1d24 100644 (file)
@@ -1,9 +1,9 @@
 #!/bin/sh
-srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669.2.2 2015/03/01 15:42:50 tg Exp $'
+srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669.2.4 2015/04/19 19:18:08 tg Exp $'
 #-
 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-#              2011, 2012, 2013, 2014
-#      Thorsten Glaser <tg@mirbsd.org>
+#              2011, 2012, 2013, 2014, 2015
+#      Thorsten “mirabilos” Glaser <tg@mirbsd.org>
 #
 # Provided that these terms and disclaimer and all copyright notices
 # are retained or reproduced in an accompanying document, permission
@@ -1692,6 +1692,7 @@ if test 0 = $HAVE_CAN_LFS_SUS; then
        ac_testn can_lfs_aix '!' can_lfs 0 "... with -D_LARGE_FILES=1" <lft.c
        test 1 = $HAVE_CAN_LFS_AIX || CPPFLAGS=$save_CPPFLAGS
 fi
+rm -f lft.c
 rmf lft*       # end of large file support test
 
 #
@@ -1780,12 +1781,12 @@ else
        HAVE_LINK_WORKS=x
        ac_testinit link_works '' 'checking if the final link command may succeed'
        fv=1
-       cat >conftest.c <<-'EOF'
+       cat >conftest.c <<-EOF
                #define EXTERN
                #define MKSH_INCLUDES_ONLY
                #include "sh.h"
-               __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.669.2.2 2015/03/01 15:42:50 tg Exp $");
-               int main(void) { printf("Hello, World!\n"); return (isatty(0)); }
+               __RCSID("$srcversion");
+               int main(void) { printf("Hello, World!\\n"); return (isatty(0)); }
 EOF
        case $cm in
        llvm)
@@ -2150,9 +2151,9 @@ cta(uari_has_32_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4
 cta(uari_wrap_32_bit,
     (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3) >
     (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 4));
-#define NUM 21
+#define NUM 22
 #else
-#define NUM 15
+#define NUM 16
 #endif
 /* these are always required */
 cta(ari_is_signed, (mksh_ari_t)-1 < (mksh_ari_t)0);
@@ -2165,6 +2166,7 @@ cta(sizet_voidptr_same_size, sizeof(size_t) == sizeof(void *));
 cta(sizet_funcptr_same_size, sizeof(size_t) == sizeof(void (*)(void)));
 /* our formatting routines assume this */
 cta(ptr_fits_in_long, sizeof(size_t) <= sizeof(long));
+cta(ari_fits_in_long, sizeof(mksh_ari_t) <= sizeof(long));
 /* for struct alignment people */
                char padding[64 - NUM];
        };
@@ -2325,7 +2327,7 @@ addsrcs '!' HAVE_STRLCPY strlcpy.c
 addsrcs USE_PRINTF_BUILTIN printf.c
 test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
 test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
-add_cppflags -DMKSH_BUILD_R=505
+add_cppflags -DMKSH_BUILD_R=506
 
 $e $bi$me: Finished configuration testing, now producing output.$ao
 
index d688509..ce45773 100644 (file)
@@ -1,8 +1,8 @@
-# $MirOS: src/bin/mksh/check.pl,v 1.37 2014/08/19 07:43:32 tg Exp $
+# $MirOS: src/bin/mksh/check.pl,v 1.37.2.1 2015/04/12 22:32:16 tg Exp $
 # $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $
 #-
 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
-#              2012, 2013, 2014
+#              2012, 2013, 2014, 2015
 #      Thorsten Glaser <tg@mirbsd.org>
 #
 # Provided that these terms and disclaimer and all copyright notices
@@ -568,7 +568,7 @@ run_test
        }
        push(@argv, $temps) if defined $test{'script'};
 
-       #XXX realpathise, use which/whence -p, or sth. like that
+       #XXX realpathise, use command -v/whence -p/which, or sth. like that
        #XXX if !$program_kludge, we get by with not doing it for now tho
        $new_env{'__progname'} = $argv[0];
 
index cd7c50d..1d59d38 100644 (file)
@@ -1,4 +1,4 @@
-# $MirOS: src/bin/mksh/check.t,v 1.667.2.3 2015/03/01 15:42:51 tg Exp $
+# $MirOS: src/bin/mksh/check.t,v 1.667.2.7 2015/04/19 19:18:10 tg Exp $
 # -*- mode: sh -*-
 #-
 # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@@ -30,7 +30,7 @@
 # (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
 
 expected-stdout:
-       @(#)MIRBSD KSH R50 2015/03/01
+       @(#)MIRBSD KSH R50 2015/04/19
 description:
        Check version of shell.
 stdin:
@@ -39,7 +39,7 @@ name: KSH_VERSION
 category: shell:legacy-no
 ---
 expected-stdout:
-       @(#)LEGACY KSH R50 2015/03/01
+       @(#)LEGACY KSH R50 2015/04/19
 description:
        Check version of legacy shell.
 stdin:
@@ -257,6 +257,19 @@ stdin:
 expected-stdout:
        hello world
 ---
+name: alias-11
+description:
+       Check that special argument handling still applies with escaped aliases
+stdin:
+       alias local='\typeset'
+       function foo {
+               local x=$1 y=z
+               print -r -- "$x,$y"
+       }
+       foo 'bar - baz'
+expected-stdout:
+       bar - baz,z
+---
 name: arith-lazy-1
 description:
        Check that only one side of ternary operator is evaluated
@@ -4832,6 +4845,66 @@ expected-stdout:
        1a:
        2: x[A B]
 ---
+name: read-IFS-2
+description:
+       Complex tests, IFS either colon (IFS-NWS) or backslash (tricky)
+stdin:
+       n=0
+       showargs() { print -nr "$1"; shift; for s_arg in "$@"; do print -nr -- " [$s_arg]"; done; print; }
+       (IFS=\\ a=\<\\\>; showargs 3 $a)
+       (IFS=: b=\<:\>; showargs 4 $b)
+       print -r '<\>' | (IFS=\\ read f g; showargs 5 "$f" "$g")
+       print -r '<\\>' | (IFS=\\ read f g; showargs 6 "$f" "$g")
+       print '<\\\n>' | (IFS=\\ read f g; showargs 7 "$f" "$g")
+       print -r '<\>' | (IFS=\\ read f; showargs 8 "$f")
+       print -r '<\\>' | (IFS=\\ read f; showargs 9 "$f")
+       print '<\\\n>' | (IFS=\\ read f; showargs 10 "$f")
+       print -r '<\>' | (IFS=\\ read -r f g; showargs 11 "$f" "$g")
+       print -r '<\\>' | (IFS=\\ read -r f g; showargs 12 "$f" "$g")
+       print '<\\\n>' | (IFS=\\ read -r f g; showargs 13 "$f" "$g")
+       print -r '<\>' | (IFS=\\ read -r f; showargs 14 "$f")
+       print -r '<\\>' | (IFS=\\ read -r f; showargs 15 "$f")
+       print '<\\\n>' | (IFS=\\ read -r f; showargs 16 "$f")
+       print -r '<:>' | (IFS=: read f g; showargs 17 "$f" "$g")
+       print -r '<::>' | (IFS=: read f g; showargs 18 "$f" "$g")
+       print '<:\n>' | (IFS=: read f g; showargs 19 "$f" "$g")
+       print -r '<:>' | (IFS=: read f; showargs 20 "$f")
+       print -r '<::>' | (IFS=: read f; showargs 21 "$f")
+       print '<:\n>' | (IFS=: read f; showargs 22 "$f")
+       print -r '<:>' | (IFS=: read -r f g; showargs 23 "$f" "$g")
+       print -r '<::>' | (IFS=: read -r f g; showargs 24 "$f" "$g")
+       print '<:\n>' | (IFS=: read -r f g; showargs 25 "$f" "$g")
+       print -r '<:>' | (IFS=: read -r f; showargs 26 "$f")
+       print -r '<::>' | (IFS=: read -r f; showargs 27 "$f")
+       print '<:\n>' | (IFS=: read -r f; showargs 28 "$f")
+expected-stdout:
+       3 [<] [>]
+       4 [<] [>]
+       5 [<] [>]
+       6 [<] [>]
+       7 [<>] []
+       8 [<>]
+       9 [<\>]
+       10 [<>]
+       11 [<] [>]
+       12 [<] [\>]
+       13 [<] []
+       14 [<\>]
+       15 [<\\>]
+       16 [<]
+       17 [<] [>]
+       18 [<] [:>]
+       19 [<] []
+       20 [<:>]
+       21 [<::>]
+       22 [<]
+       23 [<] [>]
+       24 [<] [:>]
+       25 [<] []
+       26 [<:>]
+       27 [<::>]
+       28 [<]
+---
 name: read-ksh-1
 description:
        If no var specified, REPLY is used
@@ -8517,6 +8590,50 @@ expected-stdout:
        {220->> Bitte keine Werbung einwerfen! <<\r\r}
        {220 Who do you wanna pretend to be today?\r}
 ---
+name: print-crlf
+description:
+       Check that CR+LF is shown and read as-is
+stdin:
+       cat >foo <<-'EOF'
+               x='bar\r
+               ' #\r
+               if test x"$KSH_VERSION" = x""; then #\r
+                       printf '<%s>' "$x" #\r
+               else #\r
+                       print -nr -- "<$x>" #\r
+               fi #\r
+       EOF
+       echo "[$("$__progname" foo)]"
+       "$__progname" foo | while IFS= read -r line; do
+               print -r -- "{$line}"
+       done
+expected-stdout:
+       [<bar\r
+       >]
+       {<bar\r}
+---
+name: print-lf
+description:
+       Check that LF-only is shown and read as-is
+stdin:
+       cat >foo <<-'EOF'
+               x='bar
+               ' #
+               if test x"$KSH_VERSION" = x""; then #
+                       printf '<%s>' "$x" #
+               else #
+                       print -nr -- "<$x>" #
+               fi #
+       EOF
+       echo "[$("$__progname" foo)]"
+       "$__progname" foo | while IFS= read -r line; do
+               print -r -- "{$line}"
+       done
+expected-stdout:
+       [<bar
+       >]
+       {<bar}
+---
 name: print-nul-chars
 description:
        Check handling of NUL characters for print and COMSUB
@@ -8713,28 +8830,46 @@ expected-exit: e != 0
 expected-stderr-pattern:
        /\.: missing argument.*\n.*\.: missing argument/
 ---
-name: alias-function-no-conflict
+name: alias-function-no-conflict-legacy
 description:
-       make aliases not conflict with functions
-       note: for ksh-like functions, the order of preference is
-       different; bash outputs baz instead of bar in line 2 below
+       make aliases not conflict with functions, legacy version:
+       undefine these aliases upon definition of the function
+       note: for ksh functions, the order of preference differs in GNU bash
 stdin:
+       # POSIX function overrides and removes alias
        alias foo='echo bar'
+       foo
        foo() {
                echo baz
        }
+       foo
+       unset -f foo
+       foo 2>/dev/null || echo rab
+       # alias overrides ksh function
        alias korn='echo bar'
+       korn
        function korn {
                echo baz
        }
-       foo
        korn
-       unset -f foo
-       foo 2>/dev/null || echo rab
+       # alias temporarily overrides POSIX function
+       bla() {
+               echo bfn
+       }
+       bla
+       alias bla='echo bal'
+       bla
+       unalias bla
+       bla
 expected-stdout:
-       baz
        bar
+       baz
        rab
+       bar
+       bar
+       bfn
+       bal
+       bfn
 ---
 name: bash-function-parens
 description:
@@ -8746,12 +8881,13 @@ stdin:
                echo "$1 {"
                echo '  echo "bar='\''$0'\'\"
                echo '}'
-               echo ${2:-foo}
+               print -r -- "${2:-foo}"
        }
        mk 'function foo' >f-korn
        mk 'foo ()' >f-dash
        mk 'function foo ()' >f-bash
-       mk 'function stop ()' stop >f-stop
+       # pre-R51 can do without a backslash in front of the second stop
+       mk 'function stop ()' 'stop' >f-stop
        print '#!'"$__progname"'\nprint -r -- "${0%/f-argh}"' >f-argh
        chmod +x f-*
        u=$(./f-argh)
@@ -9770,25 +9906,33 @@ description:
        Verify that file descriptors > 2 are private for Korn shells
        AT&T ksh93 does this still, which means we must keep it as well
 category: shell:legacy-no
-file-setup: file 644 "test.sh"
-       echo >&3 Fowl
 stdin:
-       exec 3>&1
-       "$__progname" test.sh
+       cat >cld <<-EOF
+               #!$__perlname
+               open(my \$fh, ">&", 9) or die "E: open \$!";
+               syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!";
+       EOF
+       chmod +x cld
+       exec 9>&1
+       ./cld
 expected-exit: e != 0
 expected-stderr-pattern:
-       /bad file descriptor/
+       /E: open /
 ---
 name: fd-cloexec-2
 description:
        Verify that file descriptors > 2 are not private for POSIX shells
        See Debian Bug #154540, Closes: #499139
-file-setup: file 644 "test.sh"
-       echo >&3 Fowl
 stdin:
-       test -n "$POSH_VERSION" || set -o sh
-       exec 3>&1
-       "$__progname" test.sh
+       cat >cld <<-EOF
+               #!$__perlname
+               open(my \$fh, ">&", 9) or die "E: open \$!";
+               syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!";
+       EOF
+       chmod +x cld
+       test -n "$POSH_VERSION" || set -o posix
+       exec 9>&1
+       ./cld
 expected-stdout:
        Fowl
 ---
@@ -9796,11 +9940,15 @@ name: fd-cloexec-3
 description:
        Verify that file descriptors > 2 are not private for LEGACY KSH
 category: shell:legacy-yes
-file-setup: file 644 "test.sh"
-       echo >&3 Fowl
 stdin:
-       exec 3>&1
-       "$__progname" test.sh
+       cat >cld <<-EOF
+               #!$__perlname
+               open(my \$fh, ">&", 9) or die "E: open \$!";
+               syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!";
+       EOF
+       chmod +x cld
+       exec 9>&1
+       ./cld
 expected-stdout:
        Fowl
 ---
@@ -11956,3 +12104,41 @@ expected-stderr:
        [(p:sh)(f1:sh)(f2:sh)] print '(o1:shx)'
        [(p:sh)(f1:sh)(f2:sh)] set +x
 ---
+name: fksh-flags-legacy
+description:
+       Check that even FKSH functions share the shell flags
+stdin:
+       [[ $KSH_VERSION = Version* ]] && set +B
+       foo() {
+               set +f
+               set -e
+               echo 2 "${-/s}" .
+       }
+       set -fh
+       echo 1 "${-/s}" .
+       foo
+       echo 3 "${-/s}" .
+expected-stdout:
+       1 fh .
+       2 eh .
+       3 eh .
+---
+name: fsh-flags
+description:
+       Check that !FKSH functions share the shell flags
+stdin:
+       [[ $KSH_VERSION = Version* ]] && set +B
+       foo() {
+               set +f
+               set -e
+               echo 2 "${-/s}" .
+       }
+       set -fh
+       echo 1 "${-/s}" .
+       foo
+       echo 3 "${-/s}" .
+expected-stdout:
+       1 fh .
+       2 eh .
+       3 eh .
+---
index 4878fd7..f65eaa7 100644 (file)
@@ -1,5 +1,5 @@
 # $Id$
-# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89.2.1 2015/01/11 22:39:44 tg Exp $
+# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89.2.3 2015/04/12 22:32:22 tg Exp $
 #-
 # Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
 #              2011, 2012, 2013, 2014, 2015
 #-
 # ${ENV:-~/.mkshrc}: mksh initialisation file for interactive shells
 
-# catch non-mksh (including lksh) trying to shell this file
-case $KSH_VERSION in
+# catch non-mksh (including lksh) trying to run this file
+case ${KSH_VERSION:-} in
 *MIRBSD\ KSH*) ;;
 *) return 0 ;;
 esac
 
-PS1='#'; (( USER_ID )) && PS1='$'; [[ ${HOSTNAME:=$(ulimit -c 0; hostname -s \
-    2>/dev/null)} = *([         ]|localhost) ]] && HOSTNAME=$(ulimit -c 0; hostname \
-    2>/dev/null); : ${EDITOR:=/bin/ed} ${HOSTNAME:=nil} ${TERM:=vt100}
-: ${MKSH:=$(whence -p mksh)}; PS4='[$EPOCHREALTIME] '; PS1=$'\001\r''${|
+PS1='#'; (( USER_ID )) && PS1='$'; : "${TERM:=vt100}${HOSTNAME:=$(ulimit -c \
+    0; hostname 2>/dev/null)}${EDITOR:=/bin/ed}${USER:=$(ulimit -c 0; id -un \
+    2>/dev/null || echo \?)}${MKSH:=$(whence -p mksh)}"
+HOSTNAME=${HOSTNAME%%*([        ]).*}; HOSTNAME=${HOSTNAME##*([         ])}
+[[ $HOSTNAME = ?(ip6-)localhost?(6) ]] && HOSTNAME=
+: "${HOSTNAME:=nil}${MKSH:=/bin/mksh}"; export EDITOR HOSTNAME MKSH TERM USER
+PS4='[$EPOCHREALTIME] '; PS1=$'\001\r''${|
        local e=$?
 
        (( e )) && REPLY+="$e|"
-       REPLY+=${USER:=$(ulimit -c 0; id -un 2>/dev/null || echo \?)}
-       REPLY+=@${HOSTNAME%%.*}:
+       REPLY+=${USER}@${HOSTNAME%%.*}:
 
        local d=${PWD:-?} p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~}
        local m=${%d} n p=...; (( m > 0 )) || m=${#d}
@@ -44,7 +46,7 @@ PS1='#'; (( USER_ID )) && PS1='$'; [[ ${HOSTNAME:=$(ulimit -c 0; hostname -s \
        REPLY+=$p$d
 
        return $e
-} '"$PS1 "; export EDITOR HOSTNAME MKSH TERM USER
+} '"$PS1 "
 alias ls=ls
 unalias ls
 alias l='ls -F'
@@ -52,10 +54,10 @@ alias la='l -a'
 alias ll='l -l'
 alias lo='l -alo'
 alias doch='sudo mksh -c "$(fc -ln -1)"'
-whence -p rot13 >/dev/null || alias rot13='tr \
+command -v rot13 >/dev/null || alias rot13='tr \
     abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \
     nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
-if whence -p hd >/dev/null; then :; elif whence -p hexdump >/dev/null; then
+if command -v hd >/dev/null; then :; elif command -v hexdump >/dev/null; then
        function hd {
                hexdump -e '"%08.8_ax  " 8/1 "%02X " " - " 8/1 "%02X "' \
                    -e '"  |" "%_p"' -e '"|\n"' "$@"
@@ -72,7 +74,8 @@ else
                        while (( i < ${#line[*]} )); do
                                hv=${line[i++]}
                                if (( (pos & 15) == 0 )); then
-                                       (( pos )) && print -r -- "$dasc|"
+                                       (( pos )) && \
+                                           print -r -- "$dasc|"
                                        print -n "${pos#16#}  "
                                        dasc=' |'
                                fi
@@ -82,11 +85,13 @@ else
                                else
                                        dasc+=${line[i-1]#1#}
                                fi
-                               (( (pos++ & 15) == 7 )) && print -n -- '- '
+                               (( (pos++ & 15) == 7 )) && \
+                                   print -n -- '- '
                        done
                        while (( pos & 15 )); do
                                print -n '   '
-                               (( (pos++ & 15) == 7 )) && print -n -- '- '
+                               (( (pos++ & 15) == 7 )) && \
+                                   print -n -- '- '
                        done
                        (( hv == 2147483647 )) || print -r -- "$dasc|"
                fi; }
@@ -95,10 +100,12 @@ fi
 
 # Berkeley C shell compatible dirs, popd, and pushd functions
 # Z shell compatible chpwd() hook, used to update DIRSTACK[0]
-DIRSTACKBASE=$(realpath ~/. 2>/dev/null || print -nr -- "${HOME:-/}")
+DIRSTACKBASE=$(realpath ~/. 2>/dev/null || \
+    print -nr -- "${HOME:-/}")
 set -A DIRSTACK
 function chpwd {
-       DIRSTACK[0]=$(realpath . 2>/dev/null || print -r -- "$PWD")
+       DIRSTACK[0]=$(realpath . 2>/dev/null || \
+           print -r -- "$PWD")
        [[ $DIRSTACKBASE = ?(*/) ]] || \
            DIRSTACK[0]=${DIRSTACK[0]/#$DIRSTACKBASE/~}
        :
index 9165ecd..4f9298c 100644 (file)
@@ -1,6 +1,6 @@
-/*     $OpenBSD: edit.c,v 1.39 2013/12/17 16:37:05 deraadt Exp $       */
+/*     $OpenBSD: edit.c,v 1.40 2015/03/12 10:20:30 sthen Exp $ */
 /*     $OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $       */
-/*     $OpenBSD: emacs.c,v 1.49 2015/02/16 01:44:41 tedu Exp $ */
+/*     $OpenBSD: emacs.c,v 1.50 2015/03/25 12:10:52 jca Exp $  */
 /*     $OpenBSD: vi.c,v 1.28 2013/12/18 16:45:46 deraadt Exp $ */
 
 /*-
@@ -28,7 +28,7 @@
 
 #ifndef MKSH_NO_CMDLINE_EDITING
 
-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276.2.3 2015/03/01 15:42:56 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276.2.5 2015/04/12 22:32:22 tg Exp $");
 
 /*
  * in later versions we might use libtermcap for this, but since external
index f9c189d..81240c5 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.158.2.4 2015/03/01 15:42:58 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.158.2.5 2015/04/12 22:32:24 tg Exp $");
 
 /*
  * string expansion
@@ -1353,7 +1353,7 @@ comsub(Expand *xp, const char *cp, int fn MKSH_A_UNUSED)
                struct ioword *io = *t->ioact;
                char *name;
 
-               if ((io->flag & IOTYPE) != IOREAD)
+               if ((io->ioflag & IOTYPE) != IOREAD)
                        errorf("%s: %s", "funny $() command",
                            snptreef(NULL, 32, "%R", io));
                shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0,
index 9b94aaf..f9eeb4c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: exec.c,v 1.50 2013/06/10 21:09:27 millert Exp $       */
+/*     $OpenBSD: exec.c,v 1.51 2015/04/18 18:28:36 deraadt Exp $       */
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.137.2.2 2015/03/01 15:42:59 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.137.2.4 2015/04/19 19:18:15 tg Exp $");
 
 #ifndef MKSH_DEFAULT_EXECSHELL
 #define MKSH_DEFAULT_EXECSHELL "/bin/sh"
@@ -92,7 +92,7 @@ execute(struct op * volatile t,
                    t->ioact != NULL && t->ioact[0] != NULL &&
                    t->ioact[1] == NULL &&
                    /* of type "here document" (or "here string") */
-                   (t->ioact[0]->flag & IOTYPE) == IOHERE &&
+                   (t->ioact[0]->ioflag & IOTYPE) == IOHERE &&
                    /* the variable assignment begins with a valid varname */
                    (ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
                    /* and has no right-hand side (i.e. "varname=") */
@@ -786,8 +786,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
 
                /*
                 * Were we deleted while executing? If so, free the
-                * execution tree. TODO: Unfortunately, the table entry
-                * is never re-used until the lookup table is expanded.
+                * execution tree.
                 */
                if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) {
                        if (tp->flag & ALLOC) {
@@ -1317,7 +1316,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
 {
        int u = -1;
        char *cp = iop->name;
-       int iotype = iop->flag & IOTYPE;
+       int iotype = iop->ioflag & IOTYPE;
        bool do_open = true, do_close = false;
        int flags = 0;
        struct ioword iotmp;
@@ -1329,7 +1328,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
        /* Used for tracing and error messages to print expanded cp */
        iotmp = *iop;
        iotmp.name = (iotype == IOHERE) ? NULL : cp;
-       iotmp.flag |= IONAMEXP;
+       iotmp.ioflag |= IONAMEXP;
 
        if (Flag(FXTRACE)) {
                change_xtrace(2, false);
@@ -1352,7 +1351,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
                 * The stat() is here to allow redirections to
                 * things like /dev/null without error.
                 */
-               if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB) &&
+               if (Flag(FNOCLOBBER) && !(iop->ioflag & IOCLOB) &&
                    (stat(cp, &statb) < 0 || S_ISREG(statb.st_mode)))
                        flags |= O_EXCL;
                break;
@@ -1377,7 +1376,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
                        u = 1009;
                        do_close = true;
                } else if ((u = check_fd(cp,
-                   X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK),
+                   X_OK | ((iop->ioflag & IORDUP) ? R_OK : W_OK),
                    &emsg)) < 0) {
                        char *sp;
 
@@ -1386,7 +1385,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
                        afree(sp, ATEMP);
                        return (-1);
                }
-               if (u == iop->unit)
+               if (u == (int)iop->unit)
                        /* "dup from" == "dup to" */
                        return (0);
                break;
@@ -1414,7 +1413,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
        /* Do not save if it has already been redirected (i.e. "cat >x >y"). */
        if (e->savefd[iop->unit] == 0) {
                /* If these are the same, it means unit was previously closed */
-               if (u == iop->unit)
+               if (u == (int)iop->unit)
                        e->savefd[iop->unit] = -1;
                else
                        /*
@@ -1429,7 +1428,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
 
        if (do_close)
                close(iop->unit);
-       else if (u != iop->unit) {
+       else if (u != (int)iop->unit) {
                if (ksh_dup2(u, iop->unit, true) < 0) {
                        int eno;
                        char *sp;
@@ -1451,7 +1450,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
                 * causes the shell to close its copies
                 */
                else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {
-                       if (iop->flag & IORDUP)
+                       if (iop->ioflag & IORDUP)
                                /* possible exec <&p */
                                coproc_read_close(u);
                        else
@@ -1520,7 +1519,7 @@ herein(struct ioword *iop, char **resbuf)
        }
 
        /* lexer substitution flags */
-       i = (iop->flag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;
+       i = (iop->ioflag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;
 
        /* skip all the fd setup if we just want the value */
        if (resbuf != NULL)
@@ -1587,9 +1586,9 @@ do_selectargs(const char **ap, bool print_menu)
                if (call_builtin(findcom("read", FC_BI), read_args, Tselect,
                    false))
                        return (NULL);
-               s = str_val(global("REPLY"));
-               if (*s && getn(s, &i))
-                       return ((i >= 1 && i <= argct) ? ap[i - 1] : null);
+               if (*(s = str_val(global("REPLY"))))
+                       return ((getn(s, &i) && i >= 1 && i <= argct) ?
+                           ap[i - 1] : null);
                print_menu = true;
        }
 }
index 9603aff..95187e6 100644 (file)
@@ -38,7 +38,7 @@
 #endif
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.259.2.2 2015/01/25 15:35:44 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.259.2.5 2015/04/19 19:18:16 tg Exp $");
 
 #if HAVE_KILLPG
 /*
@@ -778,7 +778,7 @@ c_typeset(const char **wp)
 
        if (fieldstr && !bi_getn(fieldstr, &field))
                return (1);
-       if (basestr && (!bi_getn(basestr, &base) || base < 1 || base > 36)) {
+       if (basestr && (!getn(basestr, &base) || base < 1 || base > 36)) {
                bi_errorf("%s: %s", "bad integer base", basestr);
                return (1);
        }
@@ -1817,9 +1817,10 @@ int
 c_read(const char **wp)
 {
 #define is_ifsws(c) (ctype((c), C_IFS) && ctype((c), C_IFSWS))
-       int c, fd = 0, rv = 0, lastparm = 0;
+       int c, fd = 0, rv = 0;
        bool savehist = false, intoarray = false, aschars = false;
        bool rawmode = false, expanding = false;
+       bool lastparmmode = false, lastparmused = false;
        enum { LINES, BYTES, UPTO, READALL } readmode = LINES;
        char delim = '\n';
        size_t bytesleft = 128, bytesread;
@@ -1855,7 +1856,7 @@ c_read(const char **wp)
                if (!bi_getn(builtin_opt.optarg, &c))
                        return (2);
                if (c == -1) {
-                       readmode = READALL;
+                       readmode = readmode == BYTES ? READALL : UPTO;
                        bytesleft = 1024;
                } else
                        bytesleft = (unsigned int)c;
@@ -2123,7 +2124,7 @@ c_read(const char **wp)
        }
 
        if (!intoarray && wp[1] == NULL)
-               lastparm = 1;
+               lastparmmode = true;
 
  c_read_splitlast:
        /* copy until IFS character */
@@ -2148,16 +2149,23 @@ c_read(const char **wp)
        }
        xsave = Xsavepos(xs, xp);
        /* copy word delimiter: IFSWS+IFS,IFSWS */
+       expanding = false;
        while (bytesread) {
                char ch;
 
                ch = *ccp;
                if (!ctype(ch, C_IFS))
                        break;
-               Xcheck(xs, xp);
-               Xput(xs, xp, ch);
+               if (lastparmmode && !expanding && !rawmode && ch == '\\') {
+                       expanding = true;
+               } else {
+                       Xcheck(xs, xp);
+                       Xput(xs, xp, ch);
+               }
                ++ccp;
                --bytesread;
+               if (expanding)
+                       continue;
                if (!ctype(ch, C_IFSWS))
                        break;
        }
@@ -2168,12 +2176,12 @@ c_read(const char **wp)
                --bytesread;
        }
        /* if no more parameters, rinse and repeat */
-       if (lastparm && bytesread) {
-               ++lastparm;
+       if (lastparmmode && bytesread) {
+               lastparmused = true;
                goto c_read_splitlast;
        }
        /* get rid of the delimiter unless we pack the rest */
-       if (lastparm < 2)
+       if (!lastparmused)
                xp = Xrestpos(xs, xp, xsave);
  c_read_gotword:
        Xput(xs, xp, '\0');
@@ -2321,13 +2329,9 @@ c_exitreturn(const char **wp)
                goto c_exitreturn_err;
        arg = wp[builtin_opt.optind];
 
-       if (arg) {
-               if (!getn(arg, &n)) {
-                       exstat = 1;
-                       warningf(true, "%s: %s", arg, "bad number");
-               } else
-                       exstat = n & 0xFF;
-       } else if (trap_exstat != -1)
+       if (arg)
+               exstat = bi_getn(arg, &n) ? (n & 0xFF) : 1;
+       else if (trap_exstat != -1)
                exstat = trap_exstat;
        if (wp[0][0] == 'r') {
                /* return */
index 6d2badf..0dfe1c2 100644 (file)
@@ -27,7 +27,7 @@
 #include <sys/file.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134.2.3 2015/03/01 15:43:00 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134.2.5 2015/04/19 19:18:18 tg Exp $");
 
 Trap sigtraps[NSIG + 1];
 static struct sigaction Sigact_ign;
@@ -275,8 +275,9 @@ c_fc(const char **wp)
                for (hp = rflag ? hlast : hfirst;
                    hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1) {
                        if (!nflag)
-                               shf_fprintf(shl_stdout, "%d",
-                                   hist_source->line - (int)(histptr - hp));
+                               shf_fprintf(shl_stdout, "%lu",
+                                   (unsigned long)hist_source->line -
+                                   (unsigned long)(histptr - hp));
                        shf_putc('\t', shl_stdout);
                        /* print multi-line commands correctly */
                        s = *hp;
@@ -563,7 +564,7 @@ sethistfile(const char *name)
                return;
 
        /* if the name is the same as the name we have */
-       if (hname && strcmp(hname, name) == 0)
+       if (hname && name && !strcmp(hname, name))
                return;
 
        /*
@@ -581,7 +582,8 @@ sethistfile(const char *name)
                hist_source->line = 0;
        }
 
-       hist_init(hist_source);
+       if (name)
+               hist_init(hist_source);
 }
 #endif
 
@@ -712,8 +714,10 @@ hist_init(Source *s)
        hist_source = s;
 
 #if HAVE_PERSISTENT_HISTORY
-       if ((hname = str_val(global("HISTFILE"))) == NULL)
+       if (((hname = str_val(global("HISTFILE"))) == NULL) || !*hname) {
+               hname = NULL;
                return;
+       }
        strdupx(hname, hname, APERM);
        hs = hist_init_first;
 
index d919c16..7a5b270 100644 (file)
@@ -1,8 +1,8 @@
-/*     $OpenBSD: jobs.c,v 1.40 2013/09/04 15:49:18 millert Exp $       */
+/*     $OpenBSD: jobs.c,v 1.41 2015/04/18 18:28:36 deraadt Exp $       */
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
- *              2012, 2013, 2014
+ *              2012, 2013, 2014, 2015
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105.2.1 2015/01/25 15:44:06 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105.2.2 2015/04/19 19:18:18 tg Exp $");
 
 #if HAVE_KILLPG
 #define mksh_killpg            killpg
@@ -1111,6 +1111,7 @@ j_waitj(Job *j,
     int flags,
     const char *where)
 {
+       Proc *p;
        int rv;
 #ifdef MKSH_NO_SIGSUSPEND
        sigset_t omask;
@@ -1238,9 +1239,10 @@ j_waitj(Job *j,
        j_systime = j->systime;
        rv = j->status;
 
-       if ((flags & JW_PIPEST) && (j->proc_list != NULL)) {
+       if (!(p = j->proc_list)) {
+               ;       /* nothing */
+       } else if (flags & JW_PIPEST) {
                uint32_t num = 0;
-               Proc *p = j->proc_list;
                struct tbl *vp;
 
                unset(vp_pipest, 1);
@@ -1270,15 +1272,13 @@ j_waitj(Job *j,
                                rv = vp->val.i;
                        p = p->next;
                }
-       } else if (Flag(FPIPEFAIL) && (j->proc_list != NULL)) {
-               Proc *p = j->proc_list;
-               int i;
+       } else if (Flag(FPIPEFAIL)) {
+               do {
+                       int i = proc_errorlevel(p);
 
-               while (p != NULL) {
-                       if ((i = proc_errorlevel(p)))
+                       if (i)
                                rv = i;
-                       p = p->next;
-               }
+               } while ((p = p->next));
        }
 
        if (!(flags & JW_ASYNCNOTIFY)
@@ -1644,8 +1644,7 @@ j_lookup(const char *cp, int *ecodep)
        size_t len;
        int job = 0;
 
-       if (ksh_isdigit(*cp)) {
-               getn(cp, &job);
+       if (ksh_isdigit(*cp) && getn(cp, &job)) {
                /* Look for last_proc->pid (what $! returns) first... */
                for (j = job_list; j != NULL; j = j->next)
                        if (j->last_proc && j->last_proc->pid == job)
@@ -1657,11 +1656,10 @@ j_lookup(const char *cp, int *ecodep)
                for (j = job_list; j != NULL; j = j->next)
                        if (j->pgrp && j->pgrp == job)
                                return (j);
-               if (ecodep)
-                       *ecodep = JL_NOSUCH;
-               return (NULL);
+               goto j_lookup_nosuch;
        }
        if (*cp != '%') {
+ j_lookup_invalid:
                if (ecodep)
                        *ecodep = JL_INVALID;
                return (NULL);
@@ -1681,7 +1679,8 @@ j_lookup(const char *cp, int *ecodep)
 
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
-               getn(cp, &job);
+               if (!getn(cp, &job))
+                       goto j_lookup_invalid;
                for (j = job_list; j != NULL; j = j->next)
                        if (j->job == job)
                                return (j);
@@ -1721,6 +1720,7 @@ j_lookup(const char *cp, int *ecodep)
                        return (last_match);
                break;
        }
+ j_lookup_nosuch:
        if (ecodep)
                *ecodep = JL_NOSUCH;
        return (NULL);
index 502284a..305f5a4 100644 (file)
--- a/src/lex.c
+++ b/src/lex.c
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *              2011, 2012, 2013, 2014
+ *              2011, 2012, 2013, 2014, 2015
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193.2.1 2015/01/11 22:39:50 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193.2.5 2015/04/19 19:18:19 tg Exp $");
 
 /*
  * states while lexing word
@@ -921,42 +921,41 @@ yylex(int cf)
                        if (!ksh_isdigit(dp[c2 + 1]))
                                goto no_iop;
                        iop->unit = (iop->unit * 10) + dp[c2 + 1] - '0';
+                       if (iop->unit >= FDBASE)
+                               goto no_iop;
                }
 
-               if (iop->unit >= FDBASE)
-                       goto no_iop;
-
                if (c == '&') {
                        if ((c2 = getsc()) != '>') {
                                ungetsc(c2);
                                goto no_iop;
                        }
                        c = c2;
-                       iop->flag = IOBASH;
+                       iop->ioflag = IOBASH;
                } else
-                       iop->flag = 0;
+                       iop->ioflag = 0;
 
                c2 = getsc();
                /* <<, >>, <> are ok, >< is not */
                if (c == c2 || (c == '<' && c2 == '>')) {
-                       iop->flag |= c == c2 ?
+                       iop->ioflag |= c == c2 ?
                            (c == '>' ? IOCAT : IOHERE) : IORDWR;
-                       if (iop->flag == IOHERE) {
+                       if (iop->ioflag == IOHERE) {
                                if ((c2 = getsc()) == '-') {
-                                       iop->flag |= IOSKIP;
+                                       iop->ioflag |= IOSKIP;
                                        c2 = getsc();
                                } else if (c2 == '<')
-                                       iop->flag |= IOHERESTR;
+                                       iop->ioflag |= IOHERESTR;
                                ungetsc(c2);
                                if (c2 == '\n')
-                                       iop->flag |= IONDELIM;
+                                       iop->ioflag |= IONDELIM;
                        }
                } else if (c2 == '&')
-                       iop->flag |= IODUP | (c == '<' ? IORDUP : 0);
+                       iop->ioflag |= IODUP | (c == '<' ? IORDUP : 0);
                else {
-                       iop->flag |= c == '>' ? IOWRITE : IOREAD;
+                       iop->ioflag |= c == '>' ? IOWRITE : IOREAD;
                        if (c == '>' && c2 == '|')
-                               iop->flag |= IOCLOB;
+                               iop->ioflag |= IOCLOB;
                        else
                                ungetsc(c2);
                }
@@ -1044,13 +1043,16 @@ yylex(int cf)
        } else
                while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
                        *dp++ = *sp++;
-       /* make sure the ident array stays NUL padded */
-       memset(dp, 0, (ident + IDENT) - dp + 1);
        if (c != EOS)
                /* word is not unquoted */
-               *ident = '\0';
+               dp = ident;
+       /* make sure the ident array stays NUL padded */
+       memset(dp, 0, (ident + IDENT) - dp + 1);
+
+       if (!(cf & (KEYWORD | ALIAS)))
+               return (LWORD);
 
-       if (*ident != '\0' && (cf & (KEYWORD | ALIAS))) {
+       if (*ident != '\0') {
                struct tbl *p;
                uint32_t h = hash(ident);
 
@@ -1077,8 +1079,7 @@ yylex(int cf)
                                 * pushed into an SREREAD) which is what
                                 * we want here anyway: find out whether
                                 * the alias name is followed by a POSIX
-                                * function definition (only the opening
-                                * parenthesis is checked though)
+                                * function definition
                                 */
                                ++cp;
                        /* prefer functions over aliases */
@@ -1106,6 +1107,11 @@ yylex(int cf)
                                goto Again;
                        }
                }
+       } else if (cf & ALIAS) {
+               /* retain typeset et al. even when quoted */
+               if (assign_command((dp = wdstrip(yylval.cp, 0))))
+                       strlcpy(ident, dp, sizeof(ident));
+               afree(dp, ATEMP);
        }
 
        return (LWORD);
@@ -1117,7 +1123,7 @@ gethere(bool iseof)
        struct ioword **p;
 
        for (p = heres; p < herep; p++)
-               if (iseof && !((*p)->flag & IOHERESTR))
+               if (iseof && !((*p)->ioflag & IOHERESTR))
                        /* only here strings at EOF */
                        return;
                else
@@ -1138,7 +1144,7 @@ readhere(struct ioword *iop)
        char *xp;
        int xpos;
 
-       if (iop->flag & IOHERESTR) {
+       if (iop->ioflag & IOHERESTR) {
                /* process the here string */
                iop->heredoc = xp = evalstr(iop->delim, DOBLANK);
                xpos = strlen(xp) - 1;
@@ -1147,9 +1153,9 @@ readhere(struct ioword *iop)
                return;
        }
 
-       eof = iop->flag & IONDELIM ? "<<" : evalstr(iop->delim, 0);
+       eof = iop->ioflag & IONDELIM ? "<<" : evalstr(iop->delim, 0);
 
-       if (!(iop->flag & IOEVAL))
+       if (!(iop->ioflag & IOEVAL))
                ignore_backslash_newline++;
 
        Xinit(xs, xp, 256, ATEMP);
@@ -1158,10 +1164,10 @@ readhere(struct ioword *iop)
        /* beginning of line */
        eofp = eof;
        xpos = Xsavepos(xs, xp);
-       if (iop->flag & IOSKIP) {
+       if (iop->ioflag & IOSKIP) {
                /* skip over leading tabs */
                while ((c = getsc()) == '\t')
-                       /* nothing */;
+                       ;       /* nothing */
                goto heredoc_parse_char;
        }
  heredoc_read_char:
@@ -1220,7 +1226,7 @@ readhere(struct ioword *iop)
        Xput(xs, xp, '\0');
        iop->heredoc = Xclose(xs, xp);
 
-       if (!(iop->flag & IOEVAL))
+       if (!(iop->ioflag & IOEVAL))
                ignore_backslash_newline--;
 }
 
@@ -1474,7 +1480,7 @@ getsc_line(Source *s)
 void
 set_prompt(int to, Source *s)
 {
-       cur_prompt = to;
+       cur_prompt = (uint8_t)to;
 
        switch (to) {
        /* command */
@@ -1497,8 +1503,8 @@ set_prompt(int to, Source *s)
                                if (*ps1 != '!' || *++ps1 == '!')
                                        shf_putchar(*ps1++, shf);
                                else
-                                       shf_fprintf(shf, "%d",
-                                               s ? s->line + 1 : 0);
+                                       shf_fprintf(shf, "%lu", s ?
+                                           (unsigned long)s->line + 1 : 0UL);
                        ps1 = shf_sclose(shf);
                        saved_atemp = ATEMP;
                        newenv(E_ERRH);
index 31dc6ff..fe6d59d 100644 (file)
@@ -1,6 +1,6 @@
-.\" $MirOS: src/bin/mksh/lksh.1,v 1.5 2013/05/22 18:18:06 tg Exp $
+.\" $MirOS: src/bin/mksh/lksh.1,v 1.5.2.1 2015/03/21 00:12:45 tg Exp $
 .\"-
-.\" Copyright (c) 2008, 2009, 2010, 2012, 2013
+.\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015
 .\"    Thorsten “mirabilos” Glaser <tg@mirbsd.org>
 .\"
 .\" Provided that these terms and disclaimer and all copyright notices
@@ -72,7 +72,7 @@
 .\" with -mandoc, it might implement .Mx itself, but we want to
 .\" use our own definition. And .Dd must come *first*, always.
 .\"
-.Dd $Mdocdate: May 22 2013 $
+.Dd $Mdocdate: March 21 2015 $
 .\"
 .\" Check which macro package we use, and do other -mdoc setup.
 .\"
@@ -175,7 +175,7 @@ instead of relying on legacy or idiotic POSIX-mandated behaviour,
 since the MirBSD Korn Shell scripting language is much more consistent.
 .Sh LEGACY MODE
 .Nm
-has the following differences from
+currently has the following differences from
 .Nm mksh :
 .Bl -bullet
 .It
@@ -195,6 +195,11 @@ as
 .Dq LEGACY KSH
 instead of
 .Dq MIRBSD KSH .
+Note that the rest of the version string is identical between
+the two shell flavours, and the behaviour and differences can
+change between versions; see the accompanying manual page
+.Xr mksh 1
+for the versions this document applies to.
 .It
 .Nm
 only offers the traditional ten file descriptors to scripts.
@@ -245,11 +250,17 @@ passes through the errorlevel from the
 .Xr getopt 1
 command.
 .It
-.Nm lksh ,
-unlike
+Unlike
 .At
 .Nm ksh ,
-does not keep file descriptors \*(Gt 2 private.
+.Nm mksh
+in
+.Fl o Ic posix
+or
+.Fl o Ic sh
+mode and
+.Nm lksh
+do not keep file descriptors \*(Gt 2 private from sub-processes.
 .El
 .Sh SEE ALSO
 .Xr mksh 1
index 59d0b1e..047aad1 100644 (file)
@@ -5,7 +5,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *              2011, 2012, 2013, 2014
+ *              2011, 2012, 2013, 2014, 2015
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -34,7 +34,7 @@
 #include <locale.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/main.c,v 1.285.2.2 2015/03/01 15:43:01 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/main.c,v 1.285.2.4 2015/04/19 19:18:20 tg Exp $");
 
 extern char **environ;
 
@@ -1286,8 +1286,9 @@ error_prefix(bool fileline)
            strcmp(source->file, kshname) != 0)
                shf_fprintf(shl_out, "%s: ", kshname + (*kshname == '-'));
        if (fileline && source && source->file != NULL) {
-               shf_fprintf(shl_out, "%s[%d]: ", source->file,
-                   source->errline > 0 ? source->errline : source->line);
+               shf_fprintf(shl_out, "%s[%lu]: ", source->file,
+                   (unsigned long)(source->errline ?
+                   source->errline : source->line));
                source->errline = 0;
        }
 }
@@ -1453,13 +1454,20 @@ closepipe(int *pv)
 int
 check_fd(const char *name, int mode, const char **emsgp)
 {
-       int fd, fl;
+       int fd = 0, fl;
 
        if (name[0] == 'p' && !name[1])
                return (coproc_getfd(mode, emsgp));
-       for (fd = 0; ksh_isdigit(*name); ++name)
+       while (ksh_isdigit(*name)) {
                fd = (fd * 10) + *name - '0';
-       if (*name || fd >= FDBASE) {
+               if (fd >= FDBASE) {
+                       if (emsgp)
+                               *emsgp = "file descriptor too large";
+                       return (-1);
+               }
+               ++name;
+       }
+       if (*name) {
                if (emsgp)
                        *emsgp = "illegal file descriptor name";
                return (-1);
index 7c8d114..74bafbe 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: misc.c,v 1.39 2015/01/16 06:39:32 deraadt Exp $       */
+/*     $OpenBSD: misc.c,v 1.40 2015/03/18 15:12:36 tedu Exp $  */
 /*     $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $       */
 
 /*-
@@ -30,7 +30,7 @@
 #include <grp.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219.2.2 2015/03/01 15:43:02 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219.2.3 2015/03/20 22:21:04 tg Exp $");
 
 #define KSH_CHVT_FLAG
 #ifdef MKSH_SMALL
@@ -1289,32 +1289,27 @@ print_columns(struct shf *shf, unsigned int n,
        afree(str, ATEMP);
 }
 
-/* Strip any nul bytes from buf - returns new length (nbytes - # of nuls) */
+/* strip all NUL bytes from buf; output is NUL-terminated if stripped */
 void
-strip_nuls(char *buf, int nbytes)
+strip_nuls(char *buf, size_t len)
 {
-       char *dst;
+       char *cp, *dp, *ep;
 
-       /*
-        * nbytes check because some systems (older FreeBSDs) have a
-        * buggy memchr()
-        */
-       if (nbytes && (dst = memchr(buf, '\0', nbytes))) {
-               char *end = buf + nbytes;
-               char *p, *q;
+       if (!len || !(dp = memchr(buf, '\0', len)))
+               return;
 
-               for (p = dst; p < end; p = q) {
-                       /* skip a block of nulls */
-                       while (++p < end && *p == '\0')
-                               ;
-                       /* find end of non-null block */
-                       if (!(q = memchr(p, '\0', end - p)))
-                               q = end;
-                       memmove(dst, p, q - p);
-                       dst += q - p;
-               }
-               *dst = '\0';
-       }
+       ep = buf + len;
+       cp = dp;
+
+ cp_has_nul_byte:
+       while (cp++ < ep && *cp == '\0')
+               ;       /* nothing */
+       while (cp < ep && *cp != '\0')
+               *dp++ = *cp++;
+       if (cp < ep)
+               goto cp_has_nul_byte;
+
+       *dp = '\0';
 }
 
 /*
index 5ad143c..5e41d13 100644 (file)
@@ -1,5 +1,5 @@
-.\" $MirOS: src/bin/mksh/mksh.1,v 1.344.2.3 2015/03/01 15:43:03 tg Exp $
-.\" $OpenBSD: ksh.1,v 1.156 2015/01/16 15:32:32 schwarze Exp $
+.\" $MirOS: src/bin/mksh/mksh.1,v 1.344.2.5 2015/04/12 22:32:30 tg Exp $
+.\" $OpenBSD: ksh.1,v 1.159 2015/03/25 12:10:52 jca Exp $
 .\"-
 .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
 .\"            2010, 2011, 2012, 2013, 2014, 2015
@@ -74,7 +74,7 @@
 .\" with -mandoc, it might implement .Mx itself, but we want to
 .\" use our own definition. And .Dd must come *first*, always.
 .\"
-.Dd $Mdocdate: March 1 2015 $
+.Dd $Mdocdate: April 12 2015 $
 .\"
 .\" Check which macro package we use, and do other -mdoc setup.
 .\"
@@ -1125,11 +1125,12 @@ functions=\*(aqtypeset \-f\*(aq
 hash=\*(aqalias \-t\*(aq
 history=\*(aqfc \-l\*(aq
 integer=\*(aqtypeset \-i\*(aq
-local=\*(aqtypeset\*(aq
+local=typeset
 login=\*(aqexec login\*(aq
 nameref=\*(aqtypeset \-n\*(aq
 nohup=\*(aqnohup \*(aq
 r=\*(aqfc \-e \-\*(aq
+source=\*(aqPATH=$PATH:. command .\*(aq
 stop=\*(aqkill \-STOP\*(aq
 type=\*(aqwhence \-v\*(aq
 .Ed
@@ -1203,7 +1204,7 @@ and
 .Ic return
 work, and in that
 .Ic exit
-terminates the parent shell.
+terminates the parent shell; shell options are shared.
 .Pp
 Another variant of substitution are the valsubs (value substitutions)
 .Pf ${\*(Ba\& Ns Ar command Ns \&;}
@@ -1254,10 +1255,8 @@ and
 .Sq D .
 Note that if the
 .Ev IFS
-parameter is set to the
-.Dv NULL
-string, no field splitting is done; if the parameter is unset, the default
-value of space, tab, and newline is used.
+parameter is set to the empty string, no field splitting is done;
+if it is unset, the default value of space, tab, and newline is used.
 .Pp
 Also, note that the field splitting applies only to the immediate result of
 the substitution.
@@ -1795,21 +1794,16 @@ word of the previous command.
 .It Ev BASHPID
 The PID of the shell or subshell.
 .It Ev CDPATH
-Search path for the
+Like
+.Ev PATH ,
+but used to resolve the argument to the
 .Ic cd
 built-in command.
-It works the same way as
-.Ev PATH
-for those directories not beginning with
-.Ql /
-in
-.Ic cd
-commands.
 Note that if
 .Ev CDPATH
 is set and does not contain
 .Sq \&.
-or contains an empty path, the current directory is not searched.
+or an empty string element, the current directory is not searched.
 Also, the
 .Ic cd
 built-in command will display the resulting directory when a match is found
@@ -1862,7 +1856,8 @@ See
 below for more information.
 .It Ev HISTFILE
 The name of the file used to store command history.
-When assigned to, history is loaded from the specified file.
+When assigned to or unset, the file is opened, history is truncated
+then loaded from the file; subsequent new lines are appended.
 Also, several invocations of the shell will share history if their
 .Ev HISTFILE
 parameters all point to the same file.
@@ -1870,7 +1865,7 @@ parameters all point to the same file.
 .Sy Note :
 If
 .Ev HISTFILE
-isn't set, no history file is used.
+is unset or empty, no history file is used.
 This is different from
 .At
 .Nm ksh .
@@ -6490,6 +6485,24 @@ will cause the shell (either
 or
 .Nm lksh )
 to behave more like the standard expects.
+.Pp
+For the purpose of
+.Tn POSIX ,
+.Nm mksh
+supports only the
+.Dq C
+locale.
+For users of UTF-8 locales, the following sh code makes the shell
+match the locale:
+.Bd -literal -offset indent
+case ${KSH_VERSION:\-} in
+*MIRBSD\ KSH*\*(Ba*LEGACY\ KSH*)
+       case ${LC_ALL:\-${LC_CTYPE:\-${LANG:\-}}} in
+       *[Uu][Tt][Ff]8*\*(Ba*[Uu][Tt][Ff]\-8*) set \-U ;;
+       *) set +U ;;
+       esac ;;
+esac
+.Ed
 .Sh BUGS
 Suspending (using \*(haZ) pipelines like the one below will only suspend
 the currently running part of the pipeline; in this example,
@@ -6500,9 +6513,22 @@ is immediately printed on suspension (but not later after an
 $ /bin/sleep 666 && echo fubar
 .Ed
 .Pp
+The truncation process involved when changing
+.Ev HISTFILE
+does not free old history entries (leaks memory) and leaks
+old entries into the new history if their line numbers are
+not overwritten by same-numer entries from the persistent
+history file; truncating the on-disc file to
+.Ev HISTSIZE
+lines has always been broken and prone to history file corruption
+when multiple shells are accessing the file; the rollover process
+for the in-memory portion of the history is slow, should use
+.Xr memmove 3 .
+.Pp
 This document attempts to describe
 .Nm mksh\ R50e
 and up,
+.\" with vendor patches from insert-your-name-here,
 compiled without any options impacting functionality, such as
 .Dv MKSH_SMALL ,
 when not called as
index d053ed2..91f8961 100644 (file)
--- a/src/sh.h
+++ b/src/sh.h
 #endif
 
 #ifdef EXTERN
-__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.701.2.4 2015/03/01 15:43:05 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.701.2.7 2015/04/19 19:18:21 tg Exp $");
 #endif
-#define MKSH_VERSION "R50 2015/03/01"
+#define MKSH_VERSION "R50 2015/04/19"
 
 /* arithmetic types: C implementation */
 #if !HAVE_CAN_INTTYPES
@@ -537,7 +537,7 @@ char *ucstrstr(char *, const char *);
 #define mkssert(e)     do { } while (/* CONSTCOND */ 0)
 #endif
 
-#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 505)
+#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 506)
 #error Must run Build.sh to compile this.
 extern void thiswillneverbedefinedIhope(void);
 int
@@ -1270,7 +1270,7 @@ EXTERN char *path;                /* copy of either PATH or def_path */
 EXTERN const char *def_path;   /* path to use if PATH not set */
 EXTERN char *tmpdir;           /* TMPDIR value */
 EXTERN const char *prompt;
-EXTERN int cur_prompt;         /* PS1 or PS2 */
+EXTERN uint8_t cur_prompt;     /* PS1 or PS2 */
 EXTERN int current_lineno;     /* LINENO value */
 
 /*
@@ -1347,11 +1347,11 @@ struct op {
  * IO redirection
  */
 struct ioword {
-       int     unit;           /* unit affected */
-       int     flag;           /* action (below) */
-       char    *name;          /* file name (unused if heredoc) */
-       char    *delim;         /* delimiter for <<,<<- */
-       char    *heredoc;       /* content of heredoc */
+       char *name;             /* filename (unused if heredoc) */
+       char *delim;            /* delimiter for <<, <<- */
+       char *heredoc;          /* content of heredoc */
+       unsigned short ioflag;  /* action (below) */
+       short unit;             /* unit (fd) affected */
 };
 
 /* ioword.flag - type of redirection */
@@ -1582,10 +1582,9 @@ typedef union {
 #define VARASN         BIT(5)  /* check for var=word */
 #define ARRAYVAR       BIT(6)  /* parse x[1 & 2] as one word */
 #define ESACONLY       BIT(7)  /* only accept esac keyword */
-#define CMDWORD                BIT(8)  /* parsing simple command (alias related) */
-#define HEREDELIM      BIT(9)  /* parsing <<,<<- delimiter */
-#define LQCHAR         BIT(10) /* source string contains QCHAR */
-#define HEREDOC        BIT(11) /* parsing a here document body */
+#define HEREDELIM      BIT(8)  /* parsing <<,<<- delimiter */
+#define LQCHAR         BIT(9)  /* source string contains QCHAR */
+#define HEREDOC        BIT(10) /* parsing a here document body */
 
 #define HERES          10      /* max number of << in line */
 
@@ -1876,7 +1875,8 @@ char *quote_value(const char *);
 void print_columns(struct shf *, unsigned int,
     char *(*)(char *, size_t, unsigned int, const void *),
     const void *, size_t, size_t, bool);
-void strip_nuls(char *, int);
+void strip_nuls(char *, size_t)
+    MKSH_A_BOUNDED(__string__, 1, 2);
 ssize_t blocking_read(int, char *, size_t)
     MKSH_A_BOUNDED(__buffer__, 2, 3);
 int reset_nonblock(int);
@@ -1923,6 +1923,7 @@ char *shf_smprintf(const char *, ...)
 ssize_t shf_vfprintf(struct shf *, const char *, va_list)
     MKSH_A_FORMAT(__printf__, 2, 0);
 /* syn.c */
+int assign_command(const char *);
 void initkeywords(void);
 struct op *compile(Source *, bool);
 bool parse_usec(const char *, struct timeval *);
index 0e6e677..67a8ed7 100644 (file)
--- a/src/syn.c
+++ b/src/syn.c
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- *              2011, 2012, 2013, 2014
+ *              2011, 2012, 2013, 2014, 2015
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94.2.1 2015/01/25 15:35:54 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94.2.3 2015/04/12 22:32:35 tg Exp $");
 
 struct nesting_state {
        int start_token;        /* token than began nesting (eg, FOR) */
@@ -58,7 +58,6 @@ static struct op *newtp(int);
 static void syntaxerr(const char *) MKSH_A_NORETURN;
 static void nesting_push(struct nesting_state *, int);
 static void nesting_pop(struct nesting_state *);
-static int assign_command(const char *);
 static int inalias(struct source *) MKSH_A_PURE;
 static Test_op dbtestp_isa(Test_env *, Test_meta);
 static const char *dbtestp_getopnd(Test_env *, Test_op, bool);
@@ -190,16 +189,16 @@ synio(int cf)
                return (NULL);
        ACCEPT;
        iop = yylval.iop;
-       if (iop->flag & IONDELIM)
+       if (iop->ioflag & IONDELIM)
                goto gotnulldelim;
-       ishere = (iop->flag & IOTYPE) == IOHERE;
+       ishere = (iop->ioflag & IOTYPE) == IOHERE;
        musthave(LWORD, ishere ? HEREDELIM : 0);
        if (ishere) {
                iop->delim = yylval.cp;
                if (*ident != 0) {
                        /* unquoted */
  gotnulldelim:
-                       iop->flag |= IOEVAL;
+                       iop->ioflag |= IOEVAL;
                }
                if (herep > &heres[HERES - 1])
                        yyerror("too many %ss\n", "<<");
@@ -207,7 +206,7 @@ synio(int cf)
        } else
                iop->name = yylval.cp;
 
-       if (iop->flag & IOBASH) {
+       if (iop->ioflag & IOBASH) {
                char *cp;
 
                nextiop = alloc(sizeof(*iop), ATEMP);
@@ -221,9 +220,9 @@ synio(int cf)
                *cp++ = '0' + (iop->unit % 10);
                *cp = EOS;
 
-               iop->flag &= ~IOBASH;
+               iop->ioflag &= ~IOBASH;
                nextiop->unit = 2;
-               nextiop->flag = IODUP;
+               nextiop->ioflag = IODUP;
                nextiop->delim = NULL;
                nextiop->heredoc = NULL;
        }
@@ -289,7 +288,7 @@ get_command(int cf)
                t->lineno = source->line;
                while (/* CONSTCOND */ 1) {
                        cf = (t->u.evalflags ? ARRAYVAR : 0) |
-                           (XPsize(args) == 0 ? sALIAS|VARASN : CMDWORD);
+                           (XPsize(args) == 0 ? sALIAS|VARASN : 0);
                        switch (tpeek(cf)) {
                        case REDIR:
                                while ((iop = synio(cf)) != NULL) {
@@ -927,7 +926,7 @@ compile(Source *s, bool skiputf8bom)
  *     a=a
  *     $
  */
-static int
+int
 assign_command(const char *s)
 {
        if (!*s)
@@ -997,9 +996,10 @@ dbtestp_isa(Test_env *te, Test_meta meta)
                ret = c == /*(*/ ')' ? TO_NONNULL : TO_NONOP;
        else if (meta == TM_UNOP || meta == TM_BINOP) {
                if (meta == TM_BINOP && c == REDIR &&
-                   (yylval.iop->flag == IOREAD || yylval.iop->flag == IOWRITE)) {
+                   (yylval.iop->ioflag == IOREAD ||
+                   yylval.iop->ioflag == IOWRITE)) {
                        ret = TO_NONNULL;
-                       save = wdcopy(yylval.iop->flag == IOREAD ?
+                       save = wdcopy(yylval.iop->ioflag == IOREAD ?
                            db_lthan : db_gthan, ATEMP);
                } else if (uqword && (ret = test_isop(meta, ident)))
                        save = yylval.cp;
index 8026f8b..3a79c15 100644 (file)
@@ -2,7 +2,7 @@
 
 /*-
  * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- *              2011, 2012, 2013
+ *              2011, 2012, 2013, 2015
  *     Thorsten Glaser <tg@mirbsd.org>
  *
  * Provided that these terms and disclaimer and all copyright notices
@@ -23,7 +23,7 @@
 
 #include "sh.h"
 
-__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.72 2013/09/24 20:19:45 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.72.2.1 2015/04/12 22:32:35 tg Exp $");
 
 #define INDENT 8
 
@@ -69,7 +69,7 @@ ptree(struct op *t, int indent, struct shf *shf)
                    t->ioact != NULL && t->ioact[0] != NULL &&
                    t->ioact[1] == NULL &&
                    /* of type "here document" (or "here string") */
-                   (t->ioact[0]->flag & IOTYPE) == IOHERE) {
+                   (t->ioact[0]->ioflag & IOTYPE) == IOHERE) {
                        fptreef(shf, indent, "%S", t->vars[0]);
                        break;
                }
@@ -221,12 +221,12 @@ ptree(struct op *t, int indent, struct shf *shf)
                        struct ioword *iop = *ioact++;
 
                        /* heredoc is NULL when tracing (set -x) */
-                       if ((iop->flag & (IOTYPE | IOHERESTR)) == IOHERE &&
+                       if ((iop->ioflag & (IOTYPE | IOHERESTR)) == IOHERE &&
                            iop->heredoc) {
                                shf_putc('\n', shf);
                                shf_puts(iop->heredoc, shf);
                                fptreef(shf, indent, "%s",
-                                   iop->flag & IONDELIM ? "<<" :
+                                   iop->ioflag & IONDELIM ? "<<" :
                                    evalstr(iop->delim, 0));
                                need_nl = true;
                        }
@@ -246,16 +246,16 @@ ptree(struct op *t, int indent, struct shf *shf)
 static void
 pioact(struct shf *shf, struct ioword *iop)
 {
-       int flag = iop->flag;
-       int type = flag & IOTYPE;
-       int expected;
+       unsigned short flag = iop->ioflag;
+       unsigned short type = flag & IOTYPE;
+       short expected;
 
        expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 :
            (type == IOCAT || type == IOWRITE) ? 1 :
            (type == IODUP && (iop->unit == !(flag & IORDUP))) ? iop->unit :
            iop->unit + 1;
        if (iop->unit != expected)
-               shf_fprintf(shf, "%d", iop->unit);
+               shf_fprintf(shf, "%d", (int)iop->unit);
 
        switch (type) {
        case IOREAD:
@@ -285,10 +285,10 @@ pioact(struct shf *shf, struct ioword *iop)
        if (type == IOHERE) {
                if (iop->delim)
                        wdvarput(shf, iop->delim, 0, WDS_TPUTS);
-               if (iop->flag & IOHERESTR)
+               if (flag & IOHERESTR)
                        shf_putc(' ', shf);
        } else if (iop->name) {
-               if (iop->flag & IONAMEXP)
+               if (flag & IONAMEXP)
                        print_value_quoted(shf, iop->name);
                else
                        wdvarput(shf, iop->name, 0, WDS_TPUTS);
@@ -910,9 +910,9 @@ dumpioact(struct shf *shf, struct op *t)
 
        shf_puts("{IOACT", shf);
        while ((iop = *ioact++) != NULL) {
-               int type = iop->flag & IOTYPE;
+               unsigned short type = iop->ioflag & IOTYPE;
 #define DT(x) case x: shf_puts(#x, shf); break;
-#define DB(x) if (iop->flag & x) shf_puts("|" #x, shf);
+#define DB(x) if (iop->ioflag & x) shf_puts("|" #x, shf);
 
                shf_putc(';', shf);
                switch (type) {
@@ -933,14 +933,14 @@ dumpioact(struct shf *shf, struct op *t)
                DB(IOBASH)
                DB(IOHERESTR)
                DB(IONDELIM)
-               shf_fprintf(shf, ",unit=%d", iop->unit);
+               shf_fprintf(shf, ",unit=%d", (int)iop->unit);
                if (iop->delim) {
                        shf_puts(",delim<", shf);
                        dumpwdvar(shf, iop->delim);
                        shf_putc('>', shf);
                }
                if (iop->name) {
-                       if (iop->flag & IONAMEXP) {
+                       if (iop->ioflag & IONAMEXP) {
                                shf_puts(",name=", shf);
                                print_value_quoted(shf, iop->name);
                        } else {
index 452b6e2..f4da69a 100644 (file)
--- a/src/var.c
+++ b/src/var.c
@@ -28,7 +28,7 @@
 #include <sys/sysctl.h>
 #endif
 
-__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183.2.2 2015/03/01 15:43:07 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183.2.4 2015/04/19 19:18:23 tg Exp $");
 
 /*-
  * Variables
@@ -481,41 +481,57 @@ setint(struct tbl *vq, mksh_ari_t n)
 static int
 getint(struct tbl *vp, mksh_ari_u *nump, bool arith)
 {
-       mksh_uari_t c, num, base;
+       mksh_uari_t c, num = 0, base = 10;
        const char *s;
        bool have_base = false, neg = false;
 
-       if (vp->flag&SPECIAL)
+       if (vp->flag & SPECIAL)
                getspec(vp);
        /* XXX is it possible for ISSET to be set and val.s to be NULL? */
-       if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL))
+       if (!(vp->flag & ISSET) || (!(vp->flag & INTEGER) && vp->val.s == NULL))
                return (-1);
-       if (vp->flag&INTEGER) {
+       if (vp->flag & INTEGER) {
                nump->i = vp->val.i;
                return (vp->type);
        }
        s = vp->val.s + vp->type;
-       base = 10;
-       num = 0;
-       if (arith && s[0] == '0' && (s[1] | 0x20) == 'x') {
-               s += 2;
-               base = 16;
-               have_base = true;
+
+       do {
+               c = (unsigned char)*s++;
+       } while (ksh_isspace(c));
+
+       switch (c) {
+       case '-':
+               neg = true;
+               /* FALLTHROUGH */
+       case '+':
+               c = (unsigned char)*s++;
+               break;
        }
-       if (Flag(FPOSIX) && arith && s[0] == '0' && ksh_isdigit(s[1]) &&
-           !(vp->flag & ZEROFIL)) {
-               /* interpret as octal (deprecated) */
-               base = 8;
-               have_base = true;
+
+       if (c == '0' && arith) {
+               if ((s[0] | 0x20) == 'x') {
+                       /* interpret as hexadecimal */
+                       base = 16;
+                       ++s;
+                       goto getint_c_style_base;
+               } else if (Flag(FPOSIX) && ksh_isdigit(s[0]) &&
+                   !(vp->flag & ZEROFIL)) {
+                       /* interpret as octal (deprecated) */
+                       base = 8;
+ getint_c_style_base:
+                       have_base = true;
+                       c = (unsigned char)*s++;
+               }
        }
-       while ((c = (unsigned char)*s++)) {
-               if (c == '-') {
-                       neg = true;
-                       continue;
-               } else if (c == '#') {
-                       if (have_base || num < 1 || num > 36)
+
+       do {
+               if (c == '#') {
+                       /* ksh-style base determination */
+                       if (have_base || num < 1)
                                return (-1);
                        if ((base = num) == 1) {
+                               /* mksh-specific extension */
                                unsigned int wc;
 
                                if (!UTFMODE)
@@ -530,22 +546,26 @@ getint(struct tbl *vp, mksh_ari_u *nump, bool arith)
                                        wc = 0xEF00 + *(const unsigned char *)s;
                                nump->u = (mksh_uari_t)wc;
                                return (1);
-                       }
+                       } else if (base > 36)
+                               return (-1);
                        num = 0;
                        have_base = true;
                        continue;
-               } else if (ksh_isdigit(c))
+               }
+               if (ksh_isdigit(c))
                        c -= '0';
-               else if (ksh_islower(c))
+               else {
+                       c |= 0x20;
+                       if (!ksh_islower(c))
+                               return (-1);
                        c -= 'a' - 10;
-               else if (ksh_isupper(c))
-                       c -= 'A' - 10;
-               else
-                       return (-1);
+               }
                if (c >= base)
                        return (-1);
+               /* handle overflow as truncation */
                num = num * base + c;
-       }
+       } while ((c = (unsigned char)*s++));
+
        if (neg)
                num = -num;
        nump->u = num;
@@ -1144,7 +1164,7 @@ unspecial(const char *name)
 }
 
 static time_t seconds;         /* time SECONDS last set */
-static int user_lineno;                /* what user set $LINENO to */
+static mksh_uari_t user_lineno;        /* what user set $LINENO to */
 
 static void
 getspec(struct tbl *vp)
@@ -1178,7 +1198,7 @@ getspec(struct tbl *vp)
                num.i = histsize;
                break;
        case V_LINENO:
-               num.i = current_lineno + user_lineno;
+               num.u = (mksh_uari_t)current_lineno + user_lineno;
                break;
        case V_LINES:
                num.i = x_lins;
@@ -1308,7 +1328,7 @@ setspec(struct tbl *vp)
                break;
        case V_LINENO:
                /* The -1 is because line numbering starts at 1. */
-               user_lineno = num.u - current_lineno - 1;
+               user_lineno = num.u - (mksh_uari_t)current_lineno - 1;
                break;
        case V_LINES:
                if (num.i >= MIN_LINS)
@@ -1350,6 +1370,11 @@ unsetspec(struct tbl *vp)
         */
 
        switch (special(vp->name)) {
+#if HAVE_PERSISTENT_HISTORY
+       case V_HISTFILE:
+               sethistfile(NULL);
+               return;
+#endif
        case V_IFS:
                setctypes(TC_IFSWS, C_IFS);
                ifs0 = ' ';