diff options
author | Elliott Hughes <enh@google.com> | 2015-04-22 19:51:32 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-04-22 19:51:33 +0000 |
commit | c87de5d0279a299eec916effc751961347ff5eeb (patch) | |
tree | 7cf80a0457be3e2dd1d98f8fddfa80e3b63f1174 | |
parent | d978a9edb72c818ae3aa2527496ce987f9ef555d (diff) | |
parent | b27ce95e41e941ad22b3dc392d8328251d3a057e (diff) | |
download | mksh-android-cts-6.0_r20.tar.gz |
Merge "Upgrade to mksh 50f."android-m-preview-1android-m-previewandroid-cts-6.0_r9android-cts-6.0_r8android-cts-6.0_r7android-cts-6.0_r6android-cts-6.0_r5android-cts-6.0_r4android-cts-6.0_r32android-cts-6.0_r31android-cts-6.0_r30android-cts-6.0_r3android-cts-6.0_r29android-cts-6.0_r28android-cts-6.0_r27android-cts-6.0_r26android-cts-6.0_r25android-cts-6.0_r24android-cts-6.0_r23android-cts-6.0_r22android-cts-6.0_r21android-cts-6.0_r20android-cts-6.0_r2android-cts-6.0_r19android-cts-6.0_r18android-cts-6.0_r17android-cts-6.0_r16android-cts-6.0_r15android-cts-6.0_r14android-cts-6.0_r13android-cts-6.0_r12android-cts-6.0_r1android-6.0.1_r9android-6.0.1_r81android-6.0.1_r80android-6.0.1_r8android-6.0.1_r79android-6.0.1_r78android-6.0.1_r77android-6.0.1_r74android-6.0.1_r73android-6.0.1_r72android-6.0.1_r70android-6.0.1_r7android-6.0.1_r69android-6.0.1_r68android-6.0.1_r67android-6.0.1_r66android-6.0.1_r65android-6.0.1_r63android-6.0.1_r62android-6.0.1_r61android-6.0.1_r60android-6.0.1_r59android-6.0.1_r58android-6.0.1_r57android-6.0.1_r56android-6.0.1_r55android-6.0.1_r54android-6.0.1_r53android-6.0.1_r52android-6.0.1_r51android-6.0.1_r50android-6.0.1_r5android-6.0.1_r49android-6.0.1_r48android-6.0.1_r47android-6.0.1_r46android-6.0.1_r45android-6.0.1_r43android-6.0.1_r42android-6.0.1_r41android-6.0.1_r40android-6.0.1_r4android-6.0.1_r33android-6.0.1_r32android-6.0.1_r31android-6.0.1_r30android-6.0.1_r3android-6.0.1_r28android-6.0.1_r27android-6.0.1_r26android-6.0.1_r25android-6.0.1_r24android-6.0.1_r22android-6.0.1_r21android-6.0.1_r20android-6.0.1_r18android-6.0.1_r17android-6.0.1_r16android-6.0.1_r13android-6.0.1_r12android-6.0.1_r11android-6.0.1_r10android-6.0.1_r1android-6.0.0_r7android-6.0.0_r6android-6.0.0_r5android-6.0.0_r41android-6.0.0_r4android-6.0.0_r3android-6.0.0_r26android-6.0.0_r25android-6.0.0_r24android-6.0.0_r23android-6.0.0_r2android-6.0.0_r13android-6.0.0_r12android-6.0.0_r11android-6.0.0_r1master-soongmarshmallow-releasemarshmallow-mr3-releasemarshmallow-mr2-releasemarshmallow-mr1-releasemarshmallow-mr1-devmarshmallow-dr1.6-releasemarshmallow-dr1.5-releasemarshmallow-dr1.5-devmarshmallow-dr-releasemarshmallow-dr-dragon-releasemarshmallow-dr-devmarshmallow-devmarshmallow-cts-release
-rw-r--r-- | Android.mk | 2 | ||||
-rw-r--r-- | Makefrag.inc | 4 | ||||
-rw-r--r-- | src/Build.sh | 20 | ||||
-rw-r--r-- | src/check.pl | 6 | ||||
-rw-r--r-- | src/check.t | 240 | ||||
-rw-r--r-- | src/dot.mkshrc | 41 | ||||
-rw-r--r-- | src/edit.c | 6 | ||||
-rw-r--r-- | src/eval.c | 4 | ||||
-rw-r--r-- | src/exec.c | 33 | ||||
-rw-r--r-- | src/funcs.c | 38 | ||||
-rw-r--r-- | src/histrap.c | 16 | ||||
-rw-r--r-- | src/jobs.c | 36 | ||||
-rw-r--r-- | src/lex.c | 68 | ||||
-rw-r--r-- | src/lksh.1 | 25 | ||||
-rw-r--r-- | src/main.c | 22 | ||||
-rw-r--r-- | src/misc.c | 43 | ||||
-rw-r--r-- | src/mksh.1 | 66 | ||||
-rw-r--r-- | src/sh.h | 29 | ||||
-rw-r--r-- | src/syn.c | 26 | ||||
-rw-r--r-- | src/tree.c | 30 | ||||
-rw-r--r-- | src/var.c | 91 |
21 files changed, 560 insertions, 286 deletions
@@ -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) diff --git a/Makefrag.inc b/Makefrag.inc index c5d5f6d..9c3632b 100644 --- a/Makefrag.inc +++ b/Makefrag.inc @@ -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 diff --git a/src/Build.sh b/src/Build.sh index 5c90eb8..70c1d24 100644 --- a/src/Build.sh +++ b/src/Build.sh @@ -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 diff --git a/src/check.pl b/src/check.pl index d688509..ce45773 100644 --- a/src/check.pl +++ b/src/check.pl @@ -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]; diff --git a/src/check.t b/src/check.t index cd7c50d..1d59d38 100644 --- a/src/check.t +++ b/src/check.t @@ -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! <<
} {220 Who do you wanna pretend to be today?
} --- +name: print-crlf +description: + Check that CR+LF 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-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 . +--- diff --git a/src/dot.mkshrc b/src/dot.mkshrc index 4878fd7..f65eaa7 100644 --- a/src/dot.mkshrc +++ b/src/dot.mkshrc @@ -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 @@ -22,21 +22,23 @@ #- # ${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/~} : @@ -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 @@ -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, @@ -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; } } diff --git a/src/funcs.c b/src/funcs.c index 9603aff..95187e6 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -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 */ diff --git a/src/histrap.c b/src/histrap.c index 6d2badf..0dfe1c2 100644 --- a/src/histrap.c +++ b/src/histrap.c @@ -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; @@ -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); @@ -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); @@ -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 @@ -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); @@ -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'; } /* @@ -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 @@ -169,9 +169,9 @@ #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 *); @@ -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; @@ -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 { @@ -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 = ' '; |