Upgrade to mksh 50e.

Change-Id: I341673d83c67f83761aa02c8372da6bbc419286f
This commit is contained in:
Elliott Hughes 2015-03-10 22:22:24 -07:00
parent 948ca12d46
commit 50012061ca
22 changed files with 889 additions and 479 deletions

View file

@ -45,7 +45,7 @@ LOCAL_CFLAGS += \
-Wno-deprecated-declarations \
-fno-asynchronous-unwind-tables \
-fno-strict-aliasing \
-fstack-protector -fwrapv \
-fstack-protector-strong -fwrapv \
# ...and CPPFLAGS.
LOCAL_CFLAGS += \
@ -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=504
-DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=505
include $(BUILD_EXECUTABLE)

View file

@ -1,4 +1,4 @@
# Makefile fragment for building mksh R50 2014/10/03
# Makefile fragment for building mksh R50 2015/03/01
PROG= mksh
MAN= mksh.1
@ -8,11 +8,11 @@ OBJS_BP= lalloc.o eval.o exec.o expr.o funcs.o histrap.o jobs.o lex.o main.o mi
INDSRCS= emacsfn.h rlimits.opt sh.h sh_flags.opt var_spec.h
NONSRCS_INST= dot.mkshrc $(MAN)
NONSRCS_NOINST= Build.sh Makefile Rebuild.sh check.pl check.t test.sh
CC= /huge-ssd/aosp-x86_64/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8/bin/*-gcc
CFLAGS= -fno-exceptions -Wno-multichar -fpic -fPIE -ffunction-sections -fdata-sections -funwind-tables -fstack-protector -Wa,--noexecstack -Werror=format-security -fno-short-enums -Wno-unused-but-set-variable -fno-builtin-sin -fno-strict-volatile-bitfields -Wno-psabi -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -g -Wstrict-aliasing=2 -fgcse-after-reload -frerun-cse-after-loop -frename-registers -Os -fomit-frame-pointer -fno-strict-aliasing -Wno-deprecated-declarations -fno-asynchronous-unwind-tables -fwrapv
CPPFLAGS= -I. -I'../src' -isystem /huge-ssd/aosp-x86_64/bionic/libc/arch-x86/include -isystem /huge-ssd/aosp-x86_64/bionic/libc/include -isystem /huge-ssd/aosp-x86_64/bionic/libc/kernel/uapi -isystem /huge-ssd/aosp-x86_64/bionic/libc/kernel/uapi/asm-x86 -isystem /huge-ssd/aosp-x86_64/bionic/libm/include -isystem /huge-ssd/aosp-x86_64/bionic/libm/include/x86 -D_FORTIFY_SOURCE=2 -I/huge-ssd/aosp-x86_64/build/core/combo/include/arch/linux-x86/ -DANDROID -DNDEBUG -UDEBUG -DDEBUG_LEAKS -DMKSH_ASSUME_UTF8 -DMKSH_CONSERVATIVE_FDS -DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN -DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 -DHAVE_ATTRIBUTE_NORETURN=1 -DHAVE_ATTRIBUTE_PURE=1 -DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 -DHAVE_SYS_TIME_H=1 -DHAVE_TIME_H=1 -DHAVE_BOTH_TIME_H=1 -DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 -DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 -DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 -DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 -DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 -DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_ERRLIST=0 -DHAVE_SYS_SIGNAME=1 -DHAVE_SYS_SIGLIST=1 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 -DHAVE_GETRUSAGE=1 -DHAVE_GETSID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_ISSETUGID=0 -DHAVE_KILLPG=1 -DHAVE_MEMMOVE=1 -DHAVE_MKNOD=0 -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=0 -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=503
LDFLAGS= -nostdlib -Bdynamic -fPIE -pie -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined /huge-ssd/aosp-x86_64/out/target/product/generic_x86_64/obj/lib/crtbegin_dynamic.o
LIBS= -L/huge-ssd/aosp-x86_64/out/target/product/generic_x86_64/obj/lib -Wl,-rpath-link=/huge-ssd/aosp-x86_64/out/target/product/generic_x86_64/obj/lib -Wl,--no-whole-archive /huge-ssd/aosp-x86_64/out/target/product/generic_x86_64/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a -lc /huge-ssd/aosp-x86_64/out/target/product/generic_x86_64/obj/lib/crtend_android.o
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
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
.depend $(OBJS_BP): rlimits.gen sh_flags.gen
rlimits.gen: ../src/Build.sh ../src/rlimits.opt

4
mkshrc
View file

@ -31,7 +31,7 @@ function hd {
local dasc line i
cat "$@" | { set +U; if read -arN -1 line; then
typeset -i1 line
typeset -i1 'line[*]'
i=0
while (( i < ${#line[*]} )); do
hv=${line[i++]}
@ -60,7 +60,7 @@ function setenv {
eval export "\"$1\""'="$2"'
}
for p in ~/.bin; do
for p in ~/bin; do
[[ -d $p/. ]] || continue
[[ :$PATH: = *:$p:* ]] || PATH=$p:$PATH
done

View file

@ -1,5 +1,5 @@
#!/bin/sh
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669 2014/10/07 15:22:12 tg Exp $'
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.669.2.2 2015/03/01 15:42:50 tg Exp $'
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014
@ -1700,22 +1700,22 @@ rmf lft* # end of large file support test
ac_test can_inttypes '!' stdint_h 1 "for standard 32-bit integer types" <<-'EOF'
#include <sys/types.h>
#include <stddef.h>
int main(int ac, char **av) { return ((uint32_t)(ptrdiff_t)*av + (int32_t)ac); }
int main(int ac, char **av) { return ((uint32_t)(size_t)*av + (int32_t)ac); }
EOF
ac_test can_ucbints '!' can_inttypes 1 "for UCB 32-bit integer types" <<-'EOF'
#include <sys/types.h>
#include <stddef.h>
int main(int ac, char **av) { return ((u_int32_t)(ptrdiff_t)*av + (int32_t)ac); }
int main(int ac, char **av) { return ((u_int32_t)(size_t)*av + (int32_t)ac); }
EOF
ac_test can_int8type '!' stdint_h 1 "for standard 8-bit integer type" <<-'EOF'
#include <sys/types.h>
#include <stddef.h>
int main(int ac, char **av) { return ((uint8_t)(ptrdiff_t)av[ac]); }
int main(int ac, char **av) { return ((uint8_t)(size_t)av[ac]); }
EOF
ac_test can_ucbint8 '!' can_int8type 1 "for UCB 8-bit integer type" <<-'EOF'
#include <sys/types.h>
#include <stddef.h>
int main(int ac, char **av) { return ((u_int8_t)(ptrdiff_t)av[ac]); }
int main(int ac, char **av) { return ((u_int8_t)(size_t)av[ac]); }
EOF
ac_test rlim_t <<-'EOF'
@ -1784,7 +1784,7 @@ else
#define EXTERN
#define MKSH_INCLUDES_ONLY
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.669 2014/10/07 15:22:12 tg Exp $");
__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)); }
EOF
case $cm in
@ -1969,13 +1969,13 @@ EOF
ac_test setlocale_ctype '' 'setlocale(LC_CTYPE, "")' <<-'EOF'
#include <locale.h>
#include <stddef.h>
int main(void) { return ((int)(ptrdiff_t)(void *)setlocale(LC_CTYPE, "")); }
int main(void) { return ((int)(size_t)(void *)setlocale(LC_CTYPE, "")); }
EOF
ac_test langinfo_codeset setlocale_ctype 0 'nl_langinfo(CODESET)' <<-'EOF'
#include <langinfo.h>
#include <stddef.h>
int main(void) { return ((int)(ptrdiff_t)(void *)nl_langinfo(CODESET)); }
int main(void) { return ((int)(size_t)(void *)nl_langinfo(CODESET)); }
EOF
ac_test select <<-'EOF'
@ -2150,9 +2150,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 22
#define NUM 21
#else
#define NUM 16
#define NUM 15
#endif
/* these are always required */
cta(ari_is_signed, (mksh_ari_t)-1 < (mksh_ari_t)0);
@ -2161,11 +2161,10 @@ cta(uari_is_unsigned, (mksh_uari_t)-1 > (mksh_uari_t)0);
cta(ari_size_no_matter_of_signedness, sizeof(mksh_ari_t) == sizeof(mksh_uari_t));
cta(sizet_size_no_matter_of_signedness, sizeof(ssize_t) == sizeof(size_t));
cta(ptrdifft_sizet_same_size, sizeof(ptrdiff_t) == sizeof(size_t));
cta(ptrdifft_voidptr_same_size, sizeof(ptrdiff_t) == sizeof(void *));
cta(ptrdifft_funcptr_same_size, sizeof(ptrdiff_t) == sizeof(void (*)(void)));
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(ptrdiff_t) <= sizeof(long));
cta(ptr_fits_in_long, sizeof(size_t) <= sizeof(long));
/* for struct alignment people */
char padding[64 - NUM];
};
@ -2264,6 +2263,11 @@ mksh_cfg= NSIG
;' >conftest.c
# GNU sed 2.03 segfaults when optimising this to sed -n
NSIG=`vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \
grep -v '^#' | \
sed '/mksh_cfg.*= *$/{
N
s/\n/ /
}' | \
grep '^ *mksh_cfg *=' | \
sed 's/^ *mksh_cfg *=[ ]*\([()0-9x+-][()0-9x+ -]*\).*$/\1/'`
case $NSIG in
@ -2295,6 +2299,11 @@ mksh_cfg= NSIG
echo ';' >>conftest.c
# GNU sed 2.03 croaks on optimising this, too
vq "$CPP $CFLAGS $CPPFLAGS $NOWARN conftest.c" | \
grep -v '^#' | \
sed '/mksh_cfg.*= *$/{
N
s/\n/ /
}' | \
grep '^ *mksh_cfg *=' | \
sed 's/^ *mksh_cfg *=[ ]*\([0-9][0-9x]*\).*$/:\1 '$name/
done | sed -n '/^:[^ ]/s/^://p' | while read nr name; do
@ -2316,7 +2325,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=504
add_cppflags -DMKSH_BUILD_R=505
$e $bi$me: Finished configuration testing, now producing output.$ao
@ -2431,9 +2440,12 @@ llvm)
;;
esac
echo ": # work around NeXTstep bug" >Rebuild.sh
for file in "$srcdir"/*.opt; do
cd "$srcdir"
optfiles=`echo *.opt`
cd "$curdir"
for file in $optfiles; do
echo "echo + Running genopt on '$file'..."
echo "(srcfile='$file'; BUILDSH_RUN_GENOPT=1; . '$srcdir/Build.sh')"
echo "(srcfile='$srcdir/$file'; BUILDSH_RUN_GENOPT=1; . '$srcdir/Build.sh')"
done >>Rebuild.sh
echo set -x >>Rebuild.sh
for file in $SRCS; do
@ -2467,11 +2479,11 @@ if test $cm = makefile; then
extras='emacsfn.h rlimits.opt sh.h sh_flags.opt var_spec.h'
test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc"
gens= genq=
for file in "$srcdir"/*.opt; do
for file in $optfiles; do
genf=`basename "$file" | sed 's/.opt$/.gen/'`
gens="$gens $genf"
genq="$genq$nl$genf: $srcdir/Build.sh $file
srcfile=$file; BUILDSH_RUN_GENOPT=1; . $srcdir/Build.sh"
genq="$genq$nl$genf: $srcdir/Build.sh $srcdir/$file
srcfile=$srcdir/$file; BUILDSH_RUN_GENOPT=1; . $srcdir/Build.sh"
done
cat >Makefrag.inc <<EOF
# Makefile fragment for building mksh $dstversion
@ -2515,9 +2527,9 @@ EOF
$e Generated Makefrag.inc successfully.
exit 0
fi
for file in "$srcdir"/*.opt; do
for file in $optfiles; do
$e "+ Running genopt on '$file'..."
do_genopt "$file" || exit 1
do_genopt "$srcdir/$file" || exit 1
done
if test $cm = combine; then
objs="-o $mkshexe"

View file

@ -1,8 +1,8 @@
# $MirOS: src/bin/mksh/check.t,v 1.661 2014/10/07 15:22:14 tg Exp $
# OpenBSD src/regress/bin/ksh updated: 2013/12/02 20:39:44
# $MirOS: src/bin/mksh/check.t,v 1.667.2.3 2015/03/01 15:42:51 tg Exp $
# -*- mode: sh -*-
#-
# Copyright © 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
@ -24,10 +24,13 @@
# http://www.research.att.com/~gsf/public/ifs.sh
#
# More testsuites at:
# http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
# http://svnweb.freebsd.org/base/head/bin/test/tests/legacy_test.sh?view=co&content-type=text%2Fplain
#
# Integrated testsuites from:
# (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 2014/10/07
@(#)MIRBSD KSH R50 2015/03/01
description:
Check version of shell.
stdin:
@ -36,7 +39,7 @@ name: KSH_VERSION
category: shell:legacy-no
---
expected-stdout:
@(#)LEGACY KSH R50 2014/10/07
@(#)LEGACY KSH R50 2015/03/01
description:
Check version of legacy shell.
stdin:
@ -2359,6 +2362,14 @@ stdin:
expected-stdout:
baz
---
name: heredoc-9f
description:
Check long here strings
stdin:
cat <<< "$( : )aa"
expected-stdout:
aa
---
name: heredoc-10
description:
Check direct here document assignment
@ -2389,6 +2400,14 @@ stdin:
vf=<<<$'=f $x \x40='
# now check
print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} ve={$ve} vf={$vf} |"
# check append
v=<<-EOF
vapp1
EOF
v+=<<-EOF
vapp2
EOF
print -r -- "| ${v//$'\n'/^} |"
expected-stdout:
function foo {
vc=<<-EOF
@ -2404,6 +2423,7 @@ expected-stdout:
} ve={=e $x \x40=
} vf={=f $x @=
} |
| vapp1^vapp2^ |
---
name: heredoc-11
description:
@ -2433,6 +2453,14 @@ stdin:
eval "$fnd"
foo
print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} |"
# check append
v=<<-
vapp1
<<
v+=<<-''
vapp2
print -r -- "| ${v//$'\n'/^} |"
expected-stdout:
function foo {
vc=<<-
@ -2450,6 +2478,52 @@ expected-stdout:
} vc={=c u \x40=
} vd={=d $x \x40=
} |
| vapp1^vapp2^ |
---
name: heredoc-12
description:
Check here documents can use $* and $@; note shells vary:
pdksh 5.2.14 acts the same
dash has 1 and 2 the same but 3 lacks the space
ksh93, bash4 differ in 2 by using space ipv colon
stdin:
set -- a b
nl='
'
IFS=" $nl"; n=1
cat <<EOF
$n foo $* foo
$n bar "$*" bar
$n baz $@ baz
$n bla "$@" bla
EOF
IFS=":"; n=2
cat <<EOF
$n foo $* foo
$n bar "$*" bar
$n baz $@ baz
$n bla "$@" bla
EOF
IFS=; n=3
cat <<EOF
$n foo $* foo
$n bar "$*" bar
$n baz $@ baz
$n bla "$@" bla
EOF
expected-stdout:
1 foo a b foo
1 bar "a b" bar
1 baz a b baz
1 bla "a b" bla
2 foo a:b foo
2 bar "a:b" bar
2 baz a:b baz
2 bla "a:b" bla
3 foo a b foo
3 bar "a b" bar
3 baz a b baz
3 bla "a b" bla
---
name: heredoc-comsub-1
description:
@ -3585,23 +3659,23 @@ name: IFS-space-1
description:
Simple test, default IFS
stdin:
showargs() { for i; do echo -n " <$i>"; done; echo; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
set -- A B C
showargs 1 $*
showargs 2 "$*"
showargs 3 $@
showargs 4 "$@"
expected-stdout:
<1> <A> <B> <C>
<2> <A B C>
<3> <A> <B> <C>
<4> <A> <B> <C>
<1> <A> <B> <C> .
<2> <A B C> .
<3> <A> <B> <C> .
<4> <A> <B> <C> .
---
name: IFS-colon-1
description:
Simple test, IFS=:
stdin:
showargs() { for i; do echo -n " <$i>"; done; echo; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS=:
set -- A B C
showargs 1 $*
@ -3609,16 +3683,16 @@ stdin:
showargs 3 $@
showargs 4 "$@"
expected-stdout:
<1> <A> <B> <C>
<2> <A:B:C>
<3> <A> <B> <C>
<4> <A> <B> <C>
<1> <A> <B> <C> .
<2> <A:B:C> .
<3> <A> <B> <C> .
<4> <A> <B> <C> .
---
name: IFS-null-1
description:
Simple test, IFS=""
stdin:
showargs() { for i; do echo -n " <$i>"; done; echo; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS=""
set -- A B C
showargs 1 $*
@ -3626,16 +3700,16 @@ stdin:
showargs 3 $@
showargs 4 "$@"
expected-stdout:
<1> <A> <B> <C>
<2> <ABC>
<3> <A> <B> <C>
<4> <A> <B> <C>
<1> <A> <B> <C> .
<2> <ABC> .
<3> <A> <B> <C> .
<4> <A> <B> <C> .
---
name: IFS-space-colon-1
description:
Simple test, IFS=<white-space>:
stdin:
showargs() { for i; do echo -n " <$i>"; done; echo; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="$IFS:"
set --
showargs 1 $*
@ -3644,52 +3718,52 @@ stdin:
showargs 4 "$@"
showargs 5 : "$@"
expected-stdout:
<1>
<2> <>
<3>
<4>
<5> <:>
<1> .
<2> <> .
<3> .
<4> .
<5> <:> .
---
name: IFS-space-colon-2
description:
Simple test, IFS=<white-space>:
AT&T ksh fails this, POSIX says the test is correct.
stdin:
showargs() { for i; do echo -n " <$i>"; done; echo; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="$IFS:"
set --
showargs :"$@"
expected-stdout:
<:>
<:> .
---
name: IFS-space-colon-4
description:
Simple test, IFS=<white-space>:
stdin:
showargs() { for i; do echo -n " <$i>"; done; echo; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="$IFS:"
set --
showargs "$@$@"
expected-stdout:
.
---
name: IFS-space-colon-5
description:
Simple test, IFS=<white-space>:
Don't know what POSIX thinks of this. AT&T ksh does not do this.
stdin:
showargs() { for i; do echo -n " <$i>"; done; echo; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="$IFS:"
set --
showargs "${@:-}"
expected-stdout:
<>
<> .
---
name: IFS-subst-1
description:
Simple test, IFS=<white-space>:
stdin:
showargs() { for i; do echo -n " <$i>"; done; echo; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="$IFS:"
x=":b: :"
echo -n '1:'; for i in $x ; do echo -n " [$i]" ; done ; echo
@ -3711,53 +3785,80 @@ stdin:
expected-stdout:
1: [] [b] []
2: [:b::]
<3> <> <b> <>
<4> <:b::>
<3> <> <b> <> .
<4> <:b::> .
5: [a] [b]
<6> <a> <b>
<6> <a> <b> .
7: [a] [] [c]
<8> <a> <> <c>
<8> <a> <> <c> .
9: [h] [ith] [ere]
<10> <h> <ith> <ere>
<11> <h:ith:ere>
<10> <h> <ith> <ere> .
<11> <h:ith:ere> .
12: [A] [B] [] [D]
<13> <A> <B> <> <D>
<13> <A> <B> <> <D> .
---
name: IFS-subst-2
description:
Check leading whitespace after trim does not make a field
stdin:
showargs() { for i; do echo -n " <$i>"; done; echo; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
x="X 1 2"
showargs 1 shift ${x#X}
expected-stdout:
<1> <shift> <1> <2>
<1> <shift> <1> <2> .
---
name: IFS-subst-3
name: IFS-subst-3-arr
description:
Check leading IFS non-whitespace after trim does make a field
but leading IFS whitespace does not, nor empty replacements
stdin:
showargs() { for i; do echo -n " <$i>"; done; echo; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
showargs 0 ${-+}
IFS=:
showargs 1 ${-+:foo:bar}
IFS=' '
showargs 2 ${-+ foo bar}
expected-stdout:
<0>
<1> <> <foo> <bar>
<2> <foo> <bar>
<0> .
<1> <> <foo> <bar> .
<2> <foo> <bar> .
---
name: IFS-subst-3-ass
description:
Check non-field semantics
stdin:
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
showargs 0 x=${-+}
IFS=:
showargs 1 x=${-+:foo:bar}
IFS=' '
showargs 2 x=${-+ foo bar}
expected-stdout:
<0> <x=> .
<1> <x=> <foo> <bar> .
<2> <x=> <foo> <bar> .
---
name: IFS-subst-3-lcl
description:
Check non-field semantics, smaller corner case (LP#1381965)
stdin:
set -x
local regex=${2:-}
exit 1
expected-exit: e != 0
expected-stderr-pattern:
/regex=/
---
name: IFS-subst-4-1
description:
reported by mikeserv
stdin:
pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a
IFS= ; q="$*" ; nq=$*
printf '<%s>\n' "$*" $* "$q" "$nq"
pfn "$*" $* "$q" "$nq"
[ "$q" = "$nq" ] && echo =true || echo =false
expected-stdout:
<spacedivdedargument
@ -3776,11 +3877,12 @@ name: IFS-subst-4-2
description:
extended testsuite based on problem by mikeserv
stdin:
pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a
IFS= ; q="$@" ; nq=$@
printf '<%s>\n' "$*" $* "$q" "$nq"
pfn "$*" $* "$q" "$nq"
[ "$q" = "$nq" ] && echo =true || echo =false
expected-stdout:
<spacedivdedargument
@ -3799,6 +3901,7 @@ name: IFS-subst-4-3
description:
extended testsuite based on problem by mikeserv
stdin:
pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a; IFS=
@ -3806,14 +3909,14 @@ stdin:
nqs=$*
qk="$@"
nqk=$@
printf '= qs '; printf '<%s>\n' "$qs"
printf '=nqs '; printf '<%s>\n' "$nqs"
printf '= qk '; printf '<%s>\n' "$qk"
printf '=nqk '; printf '<%s>\n' "$nqk"
printf '~ qs '; printf '<%s>\n' "$*"
printf '~nqs '; printf '<%s>\n' $*
printf '~ qk '; printf '<%s>\n' "$@"
printf '~nqk '; printf '<%s>\n' $@
print -nr -- '= qs '; pfn "$qs"
print -nr -- '=nqs '; pfn "$nqs"
print -nr -- '= qk '; pfn "$qk"
print -nr -- '=nqk '; pfn "$nqk"
print -nr -- '~ qs '; pfn "$*"
print -nr -- '~nqs '; pfn $*
print -nr -- '~ qk '; pfn "$@"
print -nr -- '~nqk '; pfn $@
expected-stdout:
= qs <spacedivdedargument
here>
@ -3842,21 +3945,22 @@ name: IFS-subst-4-4
description:
extended testsuite based on problem by mikeserv
stdin:
pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a; IFS=
qs="$*"
printf '= qs '; printf '<%s>\n' "$qs"
printf '~ qs '; printf '<%s>\n' "$*"
print -nr -- '= qs '; pfn "$qs"
print -nr -- '~ qs '; pfn "$*"
nqs=$*
printf '=nqs '; printf '<%s>\n' "$nqs"
printf '~nqs '; printf '<%s>\n' $*
print -nr -- '=nqs '; pfn "$nqs"
print -nr -- '~nqs '; pfn $*
qk="$@"
printf '= qk '; printf '<%s>\n' "$qk"
printf '~ qk '; printf '<%s>\n' "$@"
print -nr -- '= qk '; pfn "$qk"
print -nr -- '~ qk '; pfn "$@"
nqk=$@
printf '=nqk '; printf '<%s>\n' "$nqk"
printf '~nqk '; printf '<%s>\n' $@
print -nr -- '=nqk '; pfn "$nqk"
print -nr -- '~nqk '; pfn $@
expected-stdout:
= qs <spacedivdedargument
here>
@ -3885,22 +3989,23 @@ name: IFS-subst-4-4p
description:
extended testsuite based on problem by mikeserv
stdin:
pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a; IFS=
unset v
qs=${v:-"$*"}
printf '= qs '; printf '<%s>\n' "$qs"
printf '~ qs '; printf '<%s>\n' ${v:-"$*"}
print -nr -- '= qs '; pfn "$qs"
print -nr -- '~ qs '; pfn ${v:-"$*"}
nqs=${v:-$*}
printf '=nqs '; printf '<%s>\n' "$nqs"
printf '~nqs '; printf '<%s>\n' ${v:-$*}
print -nr -- '=nqs '; pfn "$nqs"
print -nr -- '~nqs '; pfn ${v:-$*}
qk=${v:-"$@"}
printf '= qk '; printf '<%s>\n' "$qk"
printf '~ qk '; printf '<%s>\n' ${v:-"$@"}
print -nr -- '= qk '; pfn "$qk"
print -nr -- '~ qk '; pfn ${v:-"$@"}
nqk=${v:-$@}
printf '=nqk '; printf '<%s>\n' "$nqk"
printf '~nqk '; printf '<%s>\n' ${v:-$@}
print -nr -- '=nqk '; pfn "$nqk"
print -nr -- '~nqk '; pfn ${v:-$@}
expected-stdout:
= qs <spacedivdedargument
here>
@ -3929,21 +4034,22 @@ name: IFS-subst-4-5
description:
extended testsuite based on problem by mikeserv
stdin:
pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a; IFS=,
qs="$*"
printf '= qs '; printf '<%s>\n' "$qs"
printf '~ qs '; printf '<%s>\n' "$*"
print -nr -- '= qs '; pfn "$qs"
print -nr -- '~ qs '; pfn "$*"
nqs=$*
printf '=nqs '; printf '<%s>\n' "$nqs"
printf '~nqs '; printf '<%s>\n' $*
print -nr -- '=nqs '; pfn "$nqs"
print -nr -- '~nqs '; pfn $*
qk="$@"
printf '= qk '; printf '<%s>\n' "$qk"
printf '~ qk '; printf '<%s>\n' "$@"
print -nr -- '= qk '; pfn "$qk"
print -nr -- '~ qk '; pfn "$@"
nqk=$@
printf '=nqk '; printf '<%s>\n' "$nqk"
printf '~nqk '; printf '<%s>\n' $@
print -nr -- '=nqk '; pfn "$nqk"
print -nr -- '~nqk '; pfn $@
expected-stdout:
= qs <space,divded,argument
here>
@ -3972,22 +4078,23 @@ name: IFS-subst-4-5p
description:
extended testsuite based on problem by mikeserv
stdin:
pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; }
a='space divded argument
here'
IFS=\ ; set -- $a; IFS=,
unset v
qs=${v:-"$*"}
printf '= qs '; printf '<%s>\n' "$qs"
printf '~ qs '; printf '<%s>\n' ${v:-"$*"}
print -nr -- '= qs '; pfn "$qs"
print -nr -- '~ qs '; pfn ${v:-"$*"}
nqs=${v:-$*}
printf '=nqs '; printf '<%s>\n' "$nqs"
printf '~nqs '; printf '<%s>\n' ${v:-$*}
print -nr -- '=nqs '; pfn "$nqs"
print -nr -- '~nqs '; pfn ${v:-$*}
qk=${v:-"$@"}
printf '= qk '; printf '<%s>\n' "$qk"
printf '~ qk '; printf '<%s>\n' ${v:-"$@"}
print -nr -- '= qk '; pfn "$qk"
print -nr -- '~ qk '; pfn ${v:-"$@"}
nqk=${v:-$@}
printf '=nqk '; printf '<%s>\n' "$nqk"
printf '~nqk '; printf '<%s>\n' ${v:-$@}
print -nr -- '=nqk '; pfn "$nqk"
print -nr -- '~nqk '; pfn ${v:-$@}
expected-stdout:
= qs <space,divded,argument
here>
@ -4026,38 +4133,55 @@ description:
'emulate sh' zsh has extra fields in
- a5ins (IFS_NWS unquoted $*)
- b5ins, matching mkshs
!!WARNING!! more to come: http://austingroupbugs.net/view.php?id=888
stdin:
"$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=; set -- "" 2 ""; pfb $*; x=$*; pfn "$x"'
echo '=a1zns'
"$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=; set -- "" 2 ""; pfb "$*"; x="$*"; pfn "$x"'
echo '=a2zqs'
"$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=; set -- "" 2 ""; pfb $@; x=$@; pfn "$x"'
echo '=a3zna'
"$__progname" -c 'IFS=; set -- "" 2 ""; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=; set -- "" 2 ""; pfb "$@"; x="$@"; pfn "$x"'
echo '=a4zqa'
"$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=,; set -- "" 2 ""; pfb $*; x=$*; pfn "$x"'
echo '=a5ins'
"$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=,; set -- "" 2 ""; pfb "$*"; x="$*"; pfn "$x"'
echo '=a6iqs'
"$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=,; set -- "" 2 ""; pfb $@; x=$@; pfn "$x"'
echo '=a7ina'
"$__progname" -c 'IFS=,; set -- "" 2 ""; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=,; set -- "" 2 ""; pfb "$@"; x="$@"; pfn "$x"'
echo '=a8iqa'
"$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=; set -- A B "" "" C; pfb $*; x=$*; pfn "$x"'
echo '=b1zns'
"$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=; set -- A B "" "" C; pfb "$*"; x="$*"; pfn "$x"'
echo '=b2zqs'
"$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=; set -- A B "" "" C; pfb $@; x=$@; pfn "$x"'
echo '=b3zna'
"$__progname" -c 'IFS=; set -- A B "" "" C; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=; set -- A B "" "" C; pfb "$@"; x="$@"; pfn "$x"'
echo '=b4zqa'
"$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" $*; x=$*; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=,; set -- A B "" "" C; pfb $*; x=$*; pfn "$x"'
echo '=b5ins'
"$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" "$*"; x="$*"; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=,; set -- A B "" "" C; pfb "$*"; x="$*"; pfn "$x"'
echo '=b6iqs'
"$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" $@; x=$@; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=,; set -- A B "" "" C; pfb $@; x=$@; pfn "$x"'
echo '=b7ina'
"$__progname" -c 'IFS=,; set -- A B "" "" C; printf "[%s]\n" "$@"; x="$@"; printf "<%s>\n" "$x"'
"$__progname" -c 'pfb() { for s_arg in "$@"; do print -r -- "[$s_arg]"; done; }; pfn() { for s_arg in "$@"; do print -r -- "<$s_arg>"; done; };
IFS=,; set -- A B "" "" C; pfb "$@"; x="$@"; pfn "$x"'
echo '=b8iqa'
expected-stdout:
[2]
@ -4133,13 +4257,69 @@ expected-stdout:
<A B C>
=b8iqa
---
name: IFS-subst-6
description:
Regression wrt. vector expansion in trim
stdin:
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS=
x=abc
set -- a b
showargs ${x#$*}
expected-stdout:
<c> .
---
name: IFS-subst-7
description:
ksh93 bug wrt. vector expansion in trim
stdin:
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS="*"
a=abcd
set -- '' c
showargs "$*" ${a##"$*"}
expected-stdout:
<*c> <abcd> .
---
name: IFS-subst-8
description:
http://austingroupbugs.net/view.php?id=221
stdin:
n() { echo "$#"; }; n "${foo-$@}"
expected-stdout:
1
---
name: IFS-subst-9
description:
Scalar context for $*/$@ in [[ and case
stdin:
"$__progname" -c 'IFS=; set a b; [[ $* = "$1$2" ]]; echo 1 $?' sh a b
"$__progname" -c 'IFS=; [[ $* = ab ]]; echo 2 "$?"' sh a b
"$__progname" -c 'IFS=; [[ "$*" = ab ]]; echo 3 "$?"' sh a b
"$__progname" -c 'IFS=; [[ $* = a ]]; echo 4 "$?"' sh a b
"$__progname" -c 'IFS=; [[ "$*" = a ]]; echo 5 "$?"' sh a b
"$__progname" -c 'IFS=; [[ "$@" = a ]]; echo 6 "$?"' sh a b
"$__progname" -c 'IFS=; case "$@" in a) echo 7 a;; ab) echo 7 b;; a\ b) echo 7 ok;; esac' sh a b
"$__progname" -c 'IFS=; case $* in a) echo 8 a;; ab) echo 8 ok;; esac' sh a b
"$__progname" -c 'pfsp() { for s_arg in "$@"; do print -nr -- "<$s_arg> "; done; print .; }; IFS=; star=$* at="$@"; pfsp 9 "$star" "$at"' sh a b
expected-stdout:
1 0
2 0
3 0
4 1
5 1
6 1
7 ok
8 ok
<9> <ab> <a b> .
---
name: IFS-arith-1
description:
http://austingroupbugs.net/view.php?id=832
stdin:
${ZSH_VERSION+false} || emulate sh
${BASH_VERSION+set -o posix}
showargs() { for x in "$@"; do echo -n "<$x> "; done; echo .; }
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
IFS=0
showargs $((1230456))
expected-stdout:
@ -7063,6 +7243,7 @@ description:
XXX if the OS can already execute them, we lose
note: cygwin execve(2) doesn't return to us with ENOEXEC, we lose
note: Ultrix perl5 t4 returns 65280 (exit-code 255) and no text
XXX fails when LD_PRELOAD is set with -e and Perl chokes it (ASan)
need-pass: no
category: !os:cygwin,!os:msys,!os:ultrix,!os:uwin-nt,!smksh
env-setup: !FOO=BAR!
@ -8013,6 +8194,66 @@ expected-stdout:
.fnr:f:
.f2r:f:
---
name: unset-fnc-local-ksh
description:
Check that unset removes a previous local
(ksh93 syntax compatible version); apparently,
there are shells which fail this?
stdin:
function f {
echo f0: $x
typeset x
echo f1: $x
x=fa
echo f2: $x
unset x
echo f3: $x
x=fb
echo f4: $x
}
x=o
echo before: $x
f
echo after: $x
expected-stdout:
before: o
f0: o
f1:
f2: fa
f3: o
f4: fb
after: fb
---
name: unset-fnc-local-sh
description:
Check that unset removes a previous local
(Debian Policy §10.4 sh version); apparently,
there are shells which fail this?
stdin:
f() {
echo f0: $x
local x
echo f1: $x
x=fa
echo f2: $x
unset x
echo f3: $x
x=fb
echo f4: $x
}
x=o
echo before: $x
f
echo after: $x
expected-stdout:
before: o
f0: o
f1:
f2: fa
f3: o
f4: fb
after: fb
---
name: varexpand-substr-1
description:
Check if bash-style substring expansion works
@ -8172,13 +8413,21 @@ name: varexpand-null-1
description:
Ensure empty strings expand emptily
stdin:
print x ${a} ${b} y
print z ${a#?} ${b%?} w
print v ${a=} ${b/c/d} u
print s ${a} . ${b} S
print t ${a#?} . ${b%?} T
print r ${a=} . ${b/c/d} R
print q
print s "${a}" . "${b}" S
print t "${a#?}" . "${b%?}" T
print r "${a=}" . "${b/c/d}" R
expected-stdout:
x y
z w
v u
s . S
t . T
r . R
q
s . S
t . T
r . R
---
name: varexpand-null-2
description:
@ -8194,13 +8443,41 @@ expected-stdout:
name: varexpand-null-3
description:
Ensure concatenating behaviour matches other shells
although the line 2<> is probably wrong? XNULLSUB case.
stdin:
x=; printf "1<%s>\n" "$x$@"
set A; printf "2<%s>\n" "${@:+}"
showargs() { for s_arg in "$@"; do echo -n "<$s_arg> "; done; echo .; }
x=; showargs 1 "$x"$@
set A; showargs 2 "${@:+}"
n() { echo "$#"; }
unset e
set -- a b
n """$@"
n "$@"
n "$@"""
n "$e""$@"
n "$@"
n "$@""$e"
set --
n """$@"
n "$@"
n "$@"""
n "$e""$@"
n "$@"
n "$@""$e"
expected-stdout:
1<>
2<>
<1> <> .
<2> <> .
2
2
2
2
2
2
1
0
1
1
0
1
---
name: print-funny-chars
description:
@ -10921,6 +11198,7 @@ stdin:
(mypid=$$; try mypid)
echo =15
) 2>&1 | sed -e 's/^[^]]*]//' -e 's/^[^:]*: *//'
exit ${PIPESTATUS[0]}
expected-stdout:
y
=1
@ -11655,3 +11933,26 @@ expected-stdout:
expected-stderr-pattern:
/.*/
---
name: xtrace-2
description:
Check that "set -x" is off during PS4 expansion
stdin:
f() {
print -n "(f1:$-)"
set -x
print -n "(f2:$-)"
}
PS4='[(p:$-)$(f)] '
print "(o0:$-)"
set -x -o inherit-xtrace
print "(o1:$-)"
set +x
print "(o2:$-)"
expected-stdout:
(o0:sh)
(o1:shx)
(o2:sh)
expected-stderr:
[(p:sh)(f1:sh)(f2:sh)] print '(o1:shx)'
[(p:sh)(f1:sh)(f2:sh)] set +x
---

View file

@ -1,8 +1,8 @@
# $Id$
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89 2014/07/28 21:45:44 tg Exp $
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.89.2.1 2015/01/11 22:39:44 tg Exp $
#-
# Copyright (c) 2002, 2003, 2004, 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
@ -67,7 +67,7 @@ else
local dasc line i
cat "$@" | { set +U; if read -arN -1 line; then
typeset -i1 line
typeset -i1 'line[*]'
i=0
while (( i < ${#line[*]} )); do
hv=${line[i++]}
@ -263,9 +263,8 @@ function smores {
# base64 encoder and decoder, RFC compliant, NUL safe
function Lb64decode {
[[ -o utf8-mode ]]; local u=$?
[[ -o utf8-mode ]]; local u=$? c s="$*" t
set +U
local c s="$*" t=
[[ -n $s ]] || { s=$(cat; print x); s=${s%x}; }
local -i i=0 j=0 n=${#s} p=0 v x
local -i16 o
@ -302,9 +301,8 @@ function Lb64decode {
set -A Lb64encode_code -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
function Lb64encode {
[[ -o utf8-mode ]]; local u=$?
[[ -o utf8-mode ]]; local u=$? c s t
set +U
local c s t
if (( $# )); then
read -raN-1 s <<<"$*"
unset s[${#s[*]}-1]
@ -342,9 +340,8 @@ function Lbafh_init {
Lbafh_v=0
}
function Lbafh_add {
[[ -o utf8-mode ]]; local u=$?
[[ -o utf8-mode ]]; local u=$? s
set +U
local s
if (( $# )); then
read -raN-1 s <<<"$*"
unset s[${#s[*]}-1]

View file

@ -1,6 +1,6 @@
/* $OpenBSD: edit.c,v 1.39 2013/12/17 16:37:05 deraadt Exp $ */
/* $OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $ */
/* $OpenBSD: emacs.c,v 1.48 2013/12/17 16:37:05 deraadt Exp $ */
/* $OpenBSD: emacs.c,v 1.49 2015/02/16 01:44:41 tedu 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 2014/07/13 11:34:28 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.276.2.3 2015/03/01 15:42:56 tg Exp $");
/*
* in later versions we might use libtermcap for this, but since external
@ -327,7 +327,7 @@ x_glob_hlp_tilde_and_rem_qchar(char *s, bool magic_flag)
/* ok, so split into "~foo"/"bar" or "~"/"baz" */
*cp++ = 0;
/* try to expand the tilde */
if (!(dp = tilde(s + 1))) {
if (!(dp = do_tilde(s + 1))) {
/* nope, revert damage */
*--cp = '/';
} else {
@ -592,8 +592,6 @@ x_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp,
char **words = NULL;
bool is_command;
mkssert(buf != NULL);
len = x_locate_word(buf, buflen, pos, startp, &is_command);
if (!((*flagsp) & XCF_COMMAND))
is_command = false;
@ -1009,7 +1007,6 @@ enum emacs_funcs {
static const struct x_ftab x_ftab[] = {
#define EMACSFN_ITEMS
#include "emacsfn.h"
{ 0, NULL, 0 }
};
static struct x_defbindings const x_defbindings[] = {
@ -2240,7 +2237,6 @@ x_push(int nchars)
{
char *cp;
mkssert(xcp != NULL);
strndupx(cp, xcp, nchars, AEDIT);
if (killstack[killsp])
afree(killstack[killsp], AEDIT);
@ -2455,8 +2451,7 @@ x_bind(const char *a1, const char *a2,
/* List function names */
if (list) {
for (f = 0; f < NELEM(x_ftab); f++)
if (x_ftab[f].xf_name &&
!(x_ftab[f].xf_flags & XF_NOBIND))
if (!(x_ftab[f].xf_flags & XF_NOBIND))
shprintf("%s\n", x_ftab[f].xf_name);
return (0);
}
@ -2517,8 +2512,7 @@ x_bind(const char *a1, const char *a2,
#endif
} else {
for (f = 0; f < NELEM(x_ftab); f++)
if (x_ftab[f].xf_name &&
strcmp(x_ftab[f].xf_name, a2) == 0)
if (!strcmp(x_ftab[f].xf_name, a2))
break;
if (f == NELEM(x_ftab) || x_ftab[f].xf_flags & XF_NOBIND) {
bi_errorf("%s: %s %s", a2, "no such", Tfunction);

View file

@ -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/eval.c,v 1.153 2014/10/07 15:22:16 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.158.2.4 2015/03/01 15:42:58 tg Exp $");
/*
* string expansion
@ -59,10 +59,11 @@ typedef struct {
#define XSUBMID 6 /* middle of expanding ${} */
/* States used for field splitting */
#define IFS_WORD 0 /* word has chars (or quotes) */
#define IFS_WORD 0 /* word has chars (or quotes except "$@") */
#define IFS_WS 1 /* have seen IFS white-space */
#define IFS_NWS 2 /* have seen IFS non-white-space */
#define IFS_IWS 3 /* begin of word, ignore IFS WS */
#define IFS_QUOTE 4 /* beg.w/quote, become IFS_WORD unless "$@" */
static int varsub(Expand *, const char *, const char *, int *, int *);
static int comsub(Expand *, const char *, int);
@ -70,7 +71,7 @@ static char *valsub(struct op *, Area *);
static char *trimsub(char *, char *, int);
static void glob(char *, XPtrV *, bool);
static void globit(XString *, char **, char *, XPtrV *, int);
static const char *maybe_expand_tilde(const char *, XString *, char **, int);
static const char *maybe_expand_tilde(const char *, XString *, char **, bool);
#ifndef MKSH_NOPWNAM
static char *homedir(char *);
#endif
@ -237,7 +238,7 @@ expand(
/* record number of trailing newlines in COMSUB */
int newlines = 0;
bool saw_eq, make_magic;
int tilde_ok;
unsigned int tilde_ok;
size_t len;
char *cp;
@ -246,7 +247,7 @@ expand(
/* for alias, readonly, set, typeset commands */
if ((f & DOVACHECK) && is_wdvarassign(ccp)) {
f &= ~(DOVACHECK | DOBLANK | DOGLOB | DOTILDE);
f |= DOASNTILDE | DOASNFIELD;
f |= DOASNTILDE | DOSCALAR;
}
if (Flag(FNOGLOB))
f &= ~DOGLOB;
@ -290,7 +291,17 @@ expand(
c = *sp++;
break;
case OQUOTE:
word = IFS_WORD;
switch (word) {
case IFS_QUOTE:
/* """something */
word = IFS_WORD;
break;
case IFS_WORD:
break;
default:
word = IFS_QUOTE;
break;
}
tilde_ok = 0;
quote = 1;
continue;
@ -383,6 +394,8 @@ expand(
if (f & DOBLANK)
doblank++;
tilde_ok = 0;
if (word == IFS_QUOTE && type != XNULLSUB)
word = IFS_WORD;
if (type == XBASE) {
/* expand? */
if (!st->next) {
@ -516,7 +529,6 @@ expand(
/* check for special cases */
d = str_val(st->var);
mkssert(d != NULL);
switch (*pat) {
case '#':
/* anchor at begin */
@ -622,7 +634,7 @@ expand(
case '%':
/* ! DOBLANK,DOBRACE,DOTILDE */
f = (f & DONTRUNCOMMAND) |
DOPAT | DOTEMP;
DOPAT | DOTEMP | DOSCALAR;
st->quotew = quote = 0;
/*
* Prepend open pattern (so |
@ -631,7 +643,7 @@ expand(
*/
if (!Flag(FSH)) {
*dp++ = MAGIC;
*dp++ = '@' | 0x80;
*dp++ = 0x80 | '@';
}
break;
case '=':
@ -664,7 +676,11 @@ expand(
f |= DOTEMP;
/* FALLTHROUGH */
default:
word = quote ? IFS_WORD : IFS_IWS;
/* '-' '+' '?' */
if (quote)
word = IFS_WORD;
else if (dp == Xstring(ds, dp))
word = IFS_IWS;
/* Enable tilde expansion */
tilde_ok = 1;
f |= DOTILDE;
@ -704,10 +720,16 @@ expand(
x.str = trimsub(str_val(st->var),
dp, st->stype);
if (x.str[0] != '\0') {
word = IFS_WS;
word = IFS_IWS;
type = XSUB;
} else
type = quote ? XSUB : XNULLSUB;
} else if (quote) {
word = IFS_WORD;
type = XSUB;
} else {
if (dp == Xstring(ds, dp))
word = IFS_IWS;
type = XNULLSUB;
}
if (f & DOBLANK)
doblank++;
st = st->prev;
@ -743,7 +765,7 @@ expand(
if (f & DOBLANK)
doblank++;
st = st->prev;
word = quote || (!*x.str && (f & DOASNFIELD)) ? IFS_WORD : IFS_WS;
word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS;
continue;
case '?': {
char *s = Xrestpos(ds, dp, st->base);
@ -759,11 +781,12 @@ expand(
case 0x100 | 'Q':
dp = Xrestpos(ds, dp, st->base);
type = XSUB;
word = quote || (!*x.str && (f & DOASNFIELD)) ? IFS_WORD : IFS_WS;
word = quote || (!*x.str && (f & DOSCALAR)) ? IFS_WORD : IFS_IWS;
if (f & DOBLANK)
doblank++;
st = st->prev;
continue;
/* default: '-' '+' */
}
st = st->prev;
type = XBASE;
@ -799,8 +822,8 @@ expand(
type = XBASE;
if (f & DOBLANK) {
doblank--;
if (dp == Xstring(ds, dp))
word = IFS_WS;
if (dp == Xstring(ds, dp) && word != IFS_WORD)
word = IFS_IWS;
}
continue;
@ -834,15 +857,20 @@ expand(
continue;
}
c = ifs0;
if ((f & DOASNFIELD)) {
/* assignment, do not field-split */
if ((f & DOHEREDOC)) {
/* pseudo-field-split reliably */
if (c == 0)
c = ' ';
break;
}
if ((f & DOSCALAR)) {
/* do not field-split */
if (x.split) {
c = ' ';
break;
}
if (c == 0) {
if (c == 0)
continue;
}
}
if (c == 0) {
if (quote && !x.split)
@ -867,7 +895,7 @@ expand(
/* $(<...) failed */
subst_exstat = 1;
/* fake EOF */
c = EOF;
c = -1;
} else if (newlines) {
/* spit out saved NLs */
c = '\n';
@ -877,13 +905,13 @@ expand(
if (c == '\n')
/* save newlines */
newlines++;
if (newlines && c != EOF) {
if (newlines && c != -1) {
shf_ungetc(c, x.u.shf);
c = '\n';
--newlines;
}
}
if (c == EOF) {
if (c == -1) {
newlines = 0;
if (x.u.shf)
shf_close(x.u.shf);
@ -911,7 +939,7 @@ expand(
* IFS_IWS -/WS w/NWS -
* (w means generate a word)
*/
if ((word == IFS_WORD) || (c &&
if ((word == IFS_WORD) || (word == IFS_QUOTE) || (c &&
(word == IFS_IWS || word == IFS_NWS) &&
!ctype(c, C_IFSWS))) {
emit_word:
@ -1023,7 +1051,7 @@ expand(
tcp = maybe_expand_tilde(sp,
&ds, &tdp,
f & DOASNTILDE);
tobool(f & DOASNTILDE));
if (tcp) {
if (dp != tdp)
word = IFS_WORD;
@ -1659,7 +1687,7 @@ debunk(char *dp, const char *sp, size_t dlen)
* past the name, otherwise returns 0.
*/
static const char *
maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign)
maybe_expand_tilde(const char *p, XString *dsp, char **dpp, bool isassign)
{
XString ts;
char *dp = *dpp;
@ -1676,7 +1704,7 @@ maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign)
}
*tp = '\0';
r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ?
tilde(Xstring(ts, tp)) : NULL;
do_tilde(Xstring(ts, tp)) : NULL;
Xfree(ts, tp);
if (r) {
while (*r) {
@ -1698,7 +1726,7 @@ maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign)
*/
char *
tilde(char *cp)
do_tilde(char *cp)
{
char *dp = null;
@ -1745,28 +1773,30 @@ homedir(char *name)
static void
alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
{
int count = 0;
unsigned int count = 0;
char *brace_start, *brace_end, *comma = NULL;
char *field_start;
char *p;
char *p = exp_start;
/* search for open brace */
for (p = exp_start; (p = strchr(p, MAGIC)) && p[1] != '{' /*}*/; p += 2)
;
while ((p = strchr(p, MAGIC)) && p[1] != '{' /*}*/)
p += 2;
brace_start = p;
/* find matching close brace, if any */
if (p) {
comma = NULL;
count = 1;
for (p += 2; *p && count; p++) {
if (ISMAGIC(*p)) {
if (*++p == '{' /*}*/)
count++;
p += 2;
while (*p && count) {
if (ISMAGIC(*p++)) {
if (*p == '{' /*}*/)
++count;
else if (*p == /*{*/ '}')
--count;
else if (*p == ',' && count == 1)
comma = p;
++p;
}
}
}
@ -1795,7 +1825,7 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
for (p = brace_start + 2; p != brace_end; p++) {
if (ISMAGIC(*p)) {
if (*++p == '{' /*}*/)
count++;
++count;
else if ((*p == /*{*/ '}' && --count == 0) ||
(*p == ',' && count == 1)) {
char *news;

View file

@ -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/exec.c,v 1.133 2014/10/03 17:32:11 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.137.2.2 2015/03/01 15:42:59 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
@ -32,7 +32,7 @@ __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.133 2014/10/03 17:32:11 tg Exp $");
static int comexec(struct op *, struct tbl * volatile, const char **,
int volatile, volatile int *);
static void scriptexec(struct op *, const char **) MKSH_A_NORETURN;
static int call_builtin(struct tbl *, const char **, const char *);
static int call_builtin(struct tbl *, const char **, const char *, bool);
static int iosetup(struct ioword *, struct tbl *);
static int herein(struct ioword *, char **);
static const char *do_selectargs(const char **, bool);
@ -81,6 +81,8 @@ execute(struct op * volatile t,
/* we want to run an executable, do some variance checks */
if (t->type == TCOM) {
/* check if this is 'var=<<EOF' */
/*XXX this is broken, dont use! */
/*XXX https://bugs.launchpad.net/mksh/+bug/1380389 */
if (
/* we have zero arguments, i.e. no programme to run */
t->args[0] == NULL &&
@ -94,20 +96,23 @@ execute(struct op * volatile t,
/* 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=") */
ccp[0] == CHAR && ccp[1] == '=' && ccp[2] == EOS &&
ccp[0] == CHAR && ((ccp[1] == '=' && ccp[2] == EOS) ||
/* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR &&
ccp[3] == '=' && ccp[4] == EOS)) &&
/* plus we can have a here document content */
herein(t->ioact[0], &cp) == 0 && cp && *cp) {
char *sp = cp, *dp;
size_t n = ccp - t->vars[0] + 2, z;
size_t n = ccp - t->vars[0] + (ccp[1] == '+' ? 4 : 2);
size_t z;
/* drop redirection (will be garbage collected) */
t->ioact = NULL;
/* set variable to its expanded value */
z = strlen(cp) + 1;
if (notoktomul(z, 2) || notoktoadd(z * 2, n))
z = strlen(cp);
if (notoktomul(z, 2) || notoktoadd(z * 2, n + 1))
internal_errorf(Toomem, (size_t)-1);
dp = alloc(z * 2 + n, ATEMP);
dp = alloc(z * 2 + n + 1, APERM);
memcpy(dp, t->vars[0], n);
t->vars[0] = dp;
dp += n;
@ -398,7 +403,7 @@ execute(struct op * volatile t,
case TCASE:
i = 0;
ccp = evalstr(t->str, DOTILDE);
ccp = evalstr(t->str, DOTILDE | DOSCALAR);
for (t = t->left; t != NULL && t->type == TPAT; t = t->right) {
for (ap = (const char **)t->vars; *ap; ap++) {
if (i || ((s = evalstr(*ap, DOTILDE|DOPAT)) &&
@ -441,7 +446,6 @@ execute(struct op * volatile t,
case TEXEC:
/* an eval'd TCOM */
s = t->args[0];
up = makenv();
restoresigs();
cleanup_proc_env();
@ -455,7 +459,7 @@ execute(struct op * volatile t,
if (rv == ENOEXEC)
scriptexec(t, (const char **)up);
else
errorf("%s: %s", s, cstrerror(rv));
errorf("%s: %s", t->str, cstrerror(rv));
}
Break:
exstat = rv & 0xFF;
@ -500,18 +504,21 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
/* Must be static (XXX but why?) */
static struct op texec;
int type_flags;
bool keepasn_ok;
bool resetspec;
int fcflags = FC_BI|FC_FUNC|FC_PATH;
bool bourne_function_call = false;
struct block *l_expand, *l_assign;
int optc;
const char *exec_argv0 = NULL;
bool exec_clrenv = false;
/*
* snag the last argument for $_ XXX not the same as AT&T ksh,
* which only seems to set $_ after a newline (but not in
* functions/dot scripts, but in interactive and script) -
* perhaps save last arg here and set it in shell()?.
*/
/* snag the last argument for $_ */
if (Flag(FTALKING) && *(lastp = ap)) {
/*
* XXX not the same as AT&T ksh, which only seems to set $_
* after a newline (but not in functions/dot scripts, but in
* interactive and script) - perhaps save last arg here and
* set it in shell()?.
*/
while (*++lastp)
;
/* setstr() can't fail here */
@ -532,7 +539,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
* FOO=bar command FOO is neither kept nor exported
* PATH=... foobar use new PATH in foobar search
*/
keepasn_ok = true;
resetspec = false;
while (tp && tp->type == CSHELL) {
/* undo effects of command */
fcflags = FC_BI|FC_FUNC|FC_PATH;
@ -548,10 +555,25 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
} else if (tp->val.f == c_exec) {
if (ap[1] == NULL)
break;
ap++;
ksh_getopt_reset(&builtin_opt, GF_ERROR);
while ((optc = ksh_getopt(ap, &builtin_opt, "a:c")) != -1)
switch (optc) {
case 'a':
exec_argv0 = builtin_opt.optarg;
break;
case 'c':
exec_clrenv = true;
/* ensure we can actually do this */
resetspec = true;
break;
default:
rv = 2;
goto Leave;
}
ap += builtin_opt.optind;
flags |= XEXEC;
} else if (tp->val.f == c_command) {
int optc, saw_p = 0;
bool saw_p = false;
/*
* Ugly dealing with options in two places (here
@ -559,8 +581,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
*/
ksh_getopt_reset(&builtin_opt, 0);
while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) == 'p')
saw_p = 1;
if (optc != EOF)
saw_p = true;
if (optc != -1)
/* command -vV or something */
break;
/* don't look for functions */
@ -579,7 +601,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
* POSIX says special builtins lose their status
* if accessed using command.
*/
keepasn_ok = false;
resetspec = true;
if (!ap[0]) {
/* ensure command with no args exits with 0 */
subst_exstat = 0;
@ -614,20 +636,21 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
if (t->u.evalflags & DOTCOMEXEC)
flags |= XEXEC;
l_expand = e->loc;
if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN))))
if (!resetspec && (!ap[0] || (tp && (tp->flag & KEEPASN))))
type_flags = 0;
else {
/* create new variable/function block */
newblock();
/* ksh functions don't keep assignments, POSIX functions do. */
if (keepasn_ok && tp && tp->type == CFUNC &&
!(tp->flag & FKSH)) {
bourne_function_call = true;
if (!resetspec && tp && tp->type == CFUNC &&
!(tp->flag & FKSH))
type_flags = EXPORT;
} else
else
type_flags = LOCAL|LOCAL_COPY|EXPORT;
}
l_assign = e->loc;
if (exec_clrenv)
l_assign->flags |= BF_STOPENV;
if (Flag(FEXPORT))
type_flags |= EXPORT;
if (Flag(FXTRACE))
@ -635,7 +658,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
for (i = 0; t->vars[i]; i++) {
/* do NOT lookup in the new var/fn block just created */
e->loc = l_expand;
cp = evalstr(t->vars[i], DOASNTILDE | DOASNFIELD);
cp = evalstr(t->vars[i], DOASNTILDE | DOSCALAR);
e->loc = l_assign;
if (Flag(FXTRACE)) {
const char *ccp;
@ -651,8 +674,6 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
}
/* but assign in there as usual */
typeset(cp, type_flags, 0, 0, 0);
if (bourne_function_call && !(type_flags & EXPORT))
typeset(cp, LOCAL | LOCAL_COPY | EXPORT, 0, 0, 0);
}
if (Flag(FXTRACE)) {
@ -684,8 +705,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
/* shell built-in */
case CSHELL:
rv = call_builtin(tp, (const char **)ap, null);
if (!keepasn_ok && tp->val.f == c_shift) {
rv = call_builtin(tp, (const char **)ap, null, resetspec);
if (resetspec && tp->val.f == c_shift) {
l_expand->argc = l_assign->argc;
l_expand->argv = l_assign->argv;
}
@ -810,14 +831,24 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
break;
}
/* set $_ to programme's full path */
/* set $_ to program's full path */
/* setstr() can't fail here */
setstr(typeset("_", LOCAL | EXPORT, 0, INTEGER, 0),
tp->val.s, KSH_RETURN_ERROR);
if (flags&XEXEC) {
/* to fork, we set up a TEXEC node and call execute */
texec.type = TEXEC;
/* for vistree/dumptree */
texec.left = t;
texec.str = tp->val.s;
texec.args = ap;
/* in this case we do not fork, of course */
if (flags & XEXEC) {
if (exec_argv0)
texec.args[0] = exec_argv0;
j_exit();
if (!(flags&XBGND)
if (!(flags & XBGND)
#ifndef MKSH_UNEMPLOYED
|| Flag(FMONITOR)
#endif
@ -827,12 +858,6 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
}
}
/* to fork we set up a TEXEC node and call execute */
texec.type = TEXEC;
/* for tprint */
texec.left = t;
texec.str = tp->val.s;
texec.args = ap;
rv = exchild(&texec, flags, xerrok, -1);
break;
}
@ -849,10 +874,8 @@ scriptexec(struct op *tp, const char **ap)
{
const char *sh;
#ifndef MKSH_SMALL
unsigned char *cp;
/* 64 == MAXINTERP in MirBSD <sys/param.h> */
char buf[64];
int fd;
unsigned char buf[68];
#endif
union mksh_ccphack args, cap;
@ -866,33 +889,35 @@ scriptexec(struct op *tp, const char **ap)
#ifndef MKSH_SMALL
if ((fd = open(tp->str, O_RDONLY | O_BINARY)) >= 0) {
/* read first MAXINTERP octets from file */
if (read(fd, buf, sizeof(buf)) <= 0)
/* read error -> no good */
buf[0] = '\0';
unsigned char *cp;
unsigned short m;
ssize_t n;
/* read first couple of octets from file */
n = read(fd, buf, sizeof(buf) - 1);
close(fd);
/* read error or short read? */
if (n < 5)
goto nomagic;
/* terminate buffer */
buf[n] = '\0';
/* skip UTF-8 Byte Order Mark, if present */
cp = (unsigned char *)buf;
if ((cp[0] == 0xEF) && (cp[1] == 0xBB) && (cp[2] == 0xBF))
cp += 3;
/* save begin of shebang for later */
fd = (char *)cp - buf; /* either 0 or (if BOM) 3 */
cp = buf + (n = ((buf[0] == 0xEF) && (buf[1] == 0xBB) &&
(buf[2] == 0xBF)) ? 3 : 0);
/* scan for newline (or CR) or NUL _before_ end of buffer */
while ((size_t)((char *)cp - buf) < sizeof(buf))
if (*cp == '\0' || *cp == '\n' || *cp == '\r') {
*cp = '\0';
break;
} else
++cp;
/* scan for newline or NUL (end of buffer) */
while (*cp && *cp != '\n')
++cp;
/* if the shebang line is longer than MAXINTERP, bail out */
if ((size_t)((char *)cp - buf) >= sizeof(buf))
if (!*cp)
goto noshebang;
/* replace newline by NUL */
*cp = '\0';
/* restore begin of shebang position (buf+0 or buf+3) */
cp = (unsigned char *)(buf + fd);
/* bail out if read error (above) or no shebang */
cp = buf + n;
/* bail out if no shebang magic found */
if ((cp[0] != '#') || (cp[1] != '!'))
goto noshebang;
@ -918,22 +943,24 @@ scriptexec(struct op *tp, const char **ap)
if (*cp)
*tp->args-- = (char *)cp;
}
goto nomagic;
noshebang:
if (buf[0] == 0x7F && buf[1] == 'E' && buf[2] == 'L' &&
buf[3] == 'F')
m = buf[0] << 8 | buf[1];
if (m == 0x7F45 && buf[2] == 'L' && buf[3] == 'F')
errorf("%s: not executable: %d-bit ELF file", tp->str,
32 * ((uint8_t)buf[4]));
fd = buf[0] << 8 | buf[1];
if ((fd == /* OMAGIC */ 0407) ||
(fd == /* NMAGIC */ 0410) ||
(fd == /* ZMAGIC */ 0413) ||
(fd == /* QMAGIC */ 0314) ||
(fd == /* ECOFF_I386 */ 0x4C01) ||
(fd == /* ECOFF_M68K */ 0x0150 || fd == 0x5001) ||
(fd == /* ECOFF_SH */ 0x0500 || fd == 0x0005) ||
(fd == /* "MZ" */ 0x4D5A) ||
(fd == /* gzip */ 0x1F8B))
errorf("%s: not executable: magic %04X", tp->str, fd);
32 * buf[4]);
if ((m == /* OMAGIC */ 0407) ||
(m == /* NMAGIC */ 0410) ||
(m == /* ZMAGIC */ 0413) ||
(m == /* QMAGIC */ 0314) ||
(m == /* ECOFF_I386 */ 0x4C01) ||
(m == /* ECOFF_M68K */ 0x0150 || m == 0x5001) ||
(m == /* ECOFF_SH */ 0x0500 || m == 0x0005) ||
(m == /* "MZ" */ 0x4D5A) ||
(m == /* gzip */ 0x1F8B) || (m == /* .Z */ 0x1F9D))
errorf("%s: not executable: magic %04X", tp->str, m);
nomagic:
;
}
#endif
args.ro = tp->args;
@ -952,7 +979,7 @@ shcomexec(const char **wp)
struct tbl *tp;
tp = ktsearch(&builtins, *wp, hash(*wp));
return (call_builtin(tp, wp, "shcomexec"));
return (call_builtin(tp, wp, "shcomexec", false));
}
/*
@ -1001,8 +1028,6 @@ define(const char *name, struct op *t)
while (/* CONSTCOND */ 1) {
tp = findfunc(name, nhash, true);
/* because findfunc:create=true */
mkssert(tp != NULL);
if (tp->flag & ISSET)
was_set = true;
@ -1265,22 +1290,22 @@ search_path(const char *name, const char *lpath,
}
static int
call_builtin(struct tbl *tp, const char **wp, const char *where)
call_builtin(struct tbl *tp, const char **wp, const char *where, bool resetspec)
{
int rv;
if (!tp)
internal_errorf("%s: %s", where, wp[0]);
builtin_argv0 = wp[0];
builtin_flag = tp->flag;
builtin_spec = tobool(!resetspec && (tp->flag & SPEC_BI));
shf_reopen(1, SHF_WR, shl_stdout);
shl_stdout_ok = true;
ksh_getopt_reset(&builtin_opt, GF_ERROR);
rv = (*tp->val.f)(wp);
shf_flush(shl_stdout);
shl_stdout_ok = false;
builtin_flag = 0;
builtin_argv0 = NULL;
builtin_spec = false;
return (rv);
}
@ -1467,7 +1492,7 @@ hereinval(const char *content, int sub, char **resbuf, struct shf *shf)
if (yylex(sub) != LWORD)
internal_errorf("%s: %s", "herein", "yylex");
source = osource;
ccp = evalstr(yylval.cp, 0);
ccp = evalstr(yylval.cp, DOSCALAR | DOHEREDOC);
}
if (resbuf == NULL)
@ -1487,7 +1512,7 @@ herein(struct ioword *iop, char **resbuf)
struct temp *h;
int i;
/* ksh -c 'cat << EOF' can cause this... */
/* ksh -c 'cat <<EOF' can cause this... */
if (iop->heredoc == NULL) {
warningf(true, "%s missing", "here document");
/* special to iosetup(): don't print error */
@ -1522,7 +1547,7 @@ herein(struct ioword *iop, char **resbuf)
return (-2);
}
if (shf_close(shf) == EOF) {
if (shf_close(shf) == -1) {
i = errno;
close(fd);
warningf(true, "can't %s temporary file %s: %s",
@ -1559,7 +1584,8 @@ do_selectargs(const char **ap, bool print_menu)
if (print_menu || !*str_val(global("REPLY")))
pr_menu(ap);
shellf("%s", str_val(global("PS3")));
if (call_builtin(findcom("read", FC_BI), read_args, Tselect))
if (call_builtin(findcom("read", FC_BI), read_args, Tselect,
false))
return (NULL);
s = str_val(global("REPLY"));
if (*s && getn(s, &i))
@ -1709,6 +1735,7 @@ static const char *
dbteste_getopnd(Test_env *te, Test_op op, bool do_eval)
{
const char *s = *te->pos.wp;
int flags = DOTILDE | DOSCALAR;
if (!s)
return (NULL);
@ -1719,11 +1746,9 @@ dbteste_getopnd(Test_env *te, Test_op op, bool do_eval)
return (null);
if (op == TO_STEQL || op == TO_STNEQ)
s = evalstr(s, DOTILDE | DOPAT);
else
s = evalstr(s, DOTILDE);
flags |= DOPAT;
return (s);
return (evalstr(s, flags));
}
static void

View file

@ -1,4 +1,4 @@
/* $OpenBSD: expr.c,v 1.23 2013/12/17 16:37:06 deraadt Exp $ */
/* $OpenBSD: expr.c,v 1.24 2014/12/08 14:26:31 otto Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.76 2014/06/24 19:53:19 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.76.2.1 2015/01/25 15:44:05 tg Exp $");
/* the order of these enums is constrained by the order of opinfo[] */
enum token {

View file

@ -5,7 +5,7 @@
/*-
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
* 2010, 2011, 2012, 2013, 2014
* 2010, 2011, 2012, 2013, 2014, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@ -38,7 +38,7 @@
#endif
#endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.258 2014/09/03 19:55:51 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.259.2.2 2015/01/25 15:35:44 tg Exp $");
#if HAVE_KILLPG
/*
@ -550,7 +550,7 @@ c_whence(const char **wp)
if (vflag || (tp->type != CALIAS && tp->type != CEXEC &&
tp->type != CTALIAS))
shf_puts(id, shl_stdout);
if (vflag)
if (vflag) {
switch (tp->type) {
case CKEYWD:
case CALIAS:
@ -559,11 +559,20 @@ c_whence(const char **wp)
shf_puts(" is a", shl_stdout);
break;
}
switch (tp->type) {
case CKEYWD:
case CSHELL:
case CTALIAS:
case CEXEC:
shf_putc(' ', shl_stdout);
break;
}
}
switch (tp->type) {
case CKEYWD:
if (vflag)
shf_puts(" reserved word", shl_stdout);
shf_puts("reserved word", shl_stdout);
break;
case CALIAS:
if (vflag)
@ -590,16 +599,17 @@ c_whence(const char **wp)
}
break;
case CSHELL:
if (vflag)
shprintf("%s %s %s",
(tp->flag & SPEC_BI) ? " special" : null,
"shell", Tbuiltin);
if (vflag) {
if (tp->flag & SPEC_BI)
shf_puts("special ", shl_stdout);
shprintf("%s %s", "shell", Tbuiltin);
}
break;
case CTALIAS:
case CEXEC:
if (tp->flag & ISSET) {
if (vflag) {
shf_puts(" is ", shl_stdout);
shf_puts("is ", shl_stdout);
if (tp->type == CTALIAS)
shprintf("a tracked %s%s for ",
(tp->flag & EXPORT) ?
@ -609,12 +619,12 @@ c_whence(const char **wp)
shf_puts(tp->val.s, shl_stdout);
} else {
if (vflag)
shprintf(" %s\n", "not found");
shf_puts("not found", shl_stdout);
rv = 1;
}
break;
default:
shprintf("%s is *GOK*", id);
shf_puts(" is *GOK*", shl_stdout);
break;
}
if (vflag || !rv)
@ -1587,12 +1597,16 @@ c_shift(const char **wp)
return (1);
arg = wp[builtin_opt.optind];
if (arg) {
evaluate(arg, &val, KSH_UNWIND_ERROR, false);
n = val;
} else
if (!arg)
n = 1;
if (n < 0) {
else if (!evaluate(arg, &val, KSH_RETURN_ERROR, false)) {
/* error already printed */
bi_errorfz();
return (1);
} else if (!(n = val)) {
/* nothing to do */
return (0);
} else if (n < 0) {
bi_errorf("%s: %s", arg, "bad number");
return (1);
}
@ -1813,7 +1827,7 @@ c_read(const char **wp)
char *cp, *allocd = NULL, *xp;
const char *ccp;
XString xs;
ptrdiff_t xsave = 0;
size_t xsave = 0;
mksh_ttyst tios;
bool restore_tios = false;
#if HAVE_SELECT
@ -2417,9 +2431,8 @@ c_set(const char **wp)
return (c_typeset(args));
}
argi = parse_args(wp, OF_SET, &setargs);
if (argi < 0)
return (1);
if ((argi = parse_args(wp, OF_SET, &setargs)) < 0)
return (2);
/* set $# and $* */
if (setargs) {
wp += argi - 1;
@ -2794,8 +2807,6 @@ c_test(const char **wp)
for (argc = 0; wp[argc]; argc++)
;
mkssert(argc > 0);
mkssert(wp[0] != NULL);
if (strcmp(wp[0], "[") == 0) {
if (strcmp(wp[--argc], "]") != 0) {

View file

@ -1,9 +1,9 @@
/* $OpenBSD: history.c,v 1.39 2010/05/19 17:36:08 jasper Exp $ */
/* $OpenBSD: history.c,v 1.40 2014/11/20 15:22:39 tedu Exp $ */
/* $OpenBSD: trap.c,v 1.23 2010/05/19 17:36:08 jasper Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2014
* 2011, 2012, 2014, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@ -27,7 +27,7 @@
#include <sys/file.h>
#endif
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134 2014/06/09 13:25:53 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134.2.3 2015/03/01 15:43:00 tg Exp $");
Trap sigtraps[NSIG + 1];
static struct sigaction Sigact_ign;
@ -303,7 +303,7 @@ c_fc(const char **wp)
for (hp = rflag ? hlast : hfirst;
hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1)
shf_fprintf(shf, "%s\n", *hp);
if (shf_close(shf) == EOF) {
if (shf_close(shf) == -1) {
bi_errorf("can't %s temporary file %s: %s",
"write", tf->tffn, cstrerror(errno));
return (1);
@ -423,14 +423,14 @@ hist_get(const char *str, bool approx, bool allow_cur)
if (getn(str, &n)) {
hp = histptr + (n < 0 ? n : (n - hist_source->line));
if ((ptrdiff_t)hp < (ptrdiff_t)history) {
if ((size_t)hp < (size_t)history) {
if (approx)
hp = hist_get_oldest();
else {
bi_errorf("%s: %s", str, Tnot_in_history);
hp = NULL;
}
} else if ((ptrdiff_t)hp > (ptrdiff_t)histptr) {
} else if ((size_t)hp > (size_t)histptr) {
if (approx)
hp = hist_get_newest(allow_cur);
else {
@ -634,7 +634,6 @@ histsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
char **hp;
char *c, *cp;
mkssert(cmd != NULL);
strdupx(c, cmd, APERM);
if ((cp = strchr(c, '\n')) != NULL)
*cp = '\0';

View file

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105 2014/10/03 12:32:48 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.105.2.1 2015/01/25 15:44:06 tg Exp $");
#if HAVE_KILLPG
#define mksh_killpg killpg
@ -1047,7 +1047,7 @@ j_async(void)
static void
j_set_async(Job *j)
{
Job *jl, *oldest;
Job *jl, *oldest;
if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE)
remove_job(async_job, "async");
@ -1084,7 +1084,7 @@ j_set_async(Job *j)
static void
j_startjob(Job *j)
{
Proc *p;
Proc *p;
j->flags |= JF_STARTED;
for (p = j->proc_list; p->next; p = p->next)
@ -1421,8 +1421,8 @@ j_sigchld(int sig MKSH_A_UNUSED)
static void
check_job(Job *j)
{
int jstate;
Proc *p;
int jstate;
Proc *p;
/* XXX debugging (nasty - interrupt routine using shl_out) */
if (!(j->flags & JF_STARTED)) {
@ -1524,14 +1524,14 @@ check_job(Job *j)
static void
j_print(Job *j, int how, struct shf *shf)
{
Proc *p;
int state;
int status;
int coredumped;
char jobchar = ' ';
char buf[64];
Proc *p;
int state;
int status;
int coredumped;
char jobchar = ' ';
char buf[64];
const char *filler;
int output = 0;
int output = 0;
if (how == JP_PGRP) {
/*
@ -1737,8 +1737,8 @@ static Proc *free_procs;
static Job *
new_job(void)
{
int i;
Job *newj, *j;
int i;
Job *newj, *j;
if (free_jobs != NULL) {
newj = free_jobs;
@ -1766,7 +1766,7 @@ new_job(void)
static Proc *
new_proc(void)
{
Proc *p;
Proc *p;
if (free_procs != NULL) {
p = free_procs;
@ -1786,10 +1786,9 @@ new_proc(void)
static void
remove_job(Job *j, const char *where)
{
Proc *p, *tmp;
Job **prev, *curr;
Proc *p, *tmp;
Job **prev, *curr;
mkssert(j != NULL);
prev = &job_list;
curr = job_list;
while (curr && curr != j) {
@ -1830,9 +1829,8 @@ remove_job(Job *j, const char *where)
static void
put_job(Job *j, int where)
{
Job **prev, *curr;
Job **prev, *curr;
mkssert(j != NULL);
/* Remove job from list (if there) */
prev = &job_list;
curr = job_list;
@ -1869,8 +1867,8 @@ put_job(Job *j, int where)
static int
kill_job(Job *j, int sig)
{
Proc *p;
int rval = 0;
Proc *p;
int rval = 0;
for (p = j->proc_list; p != NULL; p = p->next)
if (p->pid != 0)

View file

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2009, 2010, 2011, 2013
* Copyright (c) 2009, 2010, 2011, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@ -20,7 +20,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20 2013/06/03 22:28:33 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20.2.1 2015/01/25 15:35:47 tg Exp $");
/* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */
#if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0)
@ -29,7 +29,7 @@ __RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.20 2013/06/03 22:28:33 tg Exp $");
#define remalloc(p,n) realloc_osi((p), (n))
#endif
#define ALLOC_ISUNALIGNED(p) (((ptrdiff_t)(p)) % ALLOC_SIZE)
#define ALLOC_ISUNALIGNED(p) (((size_t)(p)) % ALLOC_SIZE)
static ALLOC_ITEM *findptr(ALLOC_ITEM **, char *, Area *);

View file

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193 2014/06/29 11:28:28 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193.2.1 2015/01/11 22:39:50 tg Exp $");
/*
* states while lexing word
@ -854,7 +854,7 @@ yylex(int cf)
*dp = '\0';
/* store the quoted string */
*wp++ = OQUOTE;
XcheckN(ws, wp, (dp - sp));
XcheckN(ws, wp, (dp - sp) * 2);
dp = sp;
while ((c = *dp++)) {
if (c == '\\') {
@ -1027,17 +1027,24 @@ yylex(int cf)
/* copy word to unprefixed string ident */
sp = yylval.cp;
dp = ident;
if ((cf & HEREDELIM) && (sp[1] == '<'))
while ((dp - ident) < IDENT) {
if ((c = *sp++) == CHAR)
*dp++ = *sp++;
else if ((c != OQUOTE) && (c != CQUOTE))
break;
if ((cf & HEREDELIM) && (sp[1] == '<')) {
herestringloop:
switch ((c = *sp++)) {
case CHAR:
++sp;
/* FALLTHROUGH */
case OQUOTE:
case CQUOTE:
goto herestringloop;
default:
break;
}
else
/* dummy value */
*dp++ = 'x';
} else
while ((dp - ident) < IDENT && (c = *sp++) == CHAR)
*dp++ = *sp++;
/* Make sure the ident array stays '\0' padded */
/* make sure the ident array stays NUL padded */
memset(dp, 0, (ident + IDENT) - dp + 1);
if (c != EOS)
/* word is not unquoted */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: main.c,v 1.54 2013/11/28 10:33:37 sobrado Exp $ */
/* $OpenBSD: main.c,v 1.55 2015/02/09 09:09:30 jsg Exp $ */
/* $OpenBSD: tty.c,v 1.10 2014/08/10 02:44:26 guenther Exp $ */
/* $OpenBSD: io.c,v 1.25 2014/08/11 20:28:47 guenther Exp $ */
/* $OpenBSD: table.c,v 1.15 2012/02/19 07:52:30 otto Exp $ */
@ -34,7 +34,7 @@
#include <locale.h>
#endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.284 2014/10/03 17:19:27 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.285.2.2 2015/03/01 15:43:01 tg Exp $");
extern char **environ;
@ -892,6 +892,13 @@ unwind(int i)
/* FALLTHROUGH */
default:
quitenv(NULL);
/*
* quitenv() may have reclaimed the memory
* used by source which will end badly when
* we jump to a function that expects it to
* be valid
*/
source = NULL;
}
}
}
@ -1014,8 +1021,6 @@ cleanup_parents_env(void)
struct env *ep;
int fd;
mkssert(e != NULL);
/*
* Don't clean up temporary files - parent will probably need them.
* Also, can't easily reclaim memory since variables, etc. could be
@ -1244,7 +1249,7 @@ bi_errorf(const char *fmt, ...)
* non-interactive shells to exit.
* XXX odd use of KEEPASN; also may not want LERROR here
*/
if (builtin_flag & SPEC_BI) {
if (builtin_spec) {
builtin_argv0 = NULL;
unwind(LERROR);
}

View file

@ -1,9 +1,9 @@
/* $OpenBSD: misc.c,v 1.38 2013/11/28 10:33:37 sobrado Exp $ */
/* $OpenBSD: misc.c,v 1.39 2015/01/16 06:39:32 deraadt Exp $ */
/* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014
* 2011, 2012, 2013, 2014, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@ -30,7 +30,7 @@
#include <grp.h>
#endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219 2014/01/05 21:57:27 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219.2.2 2015/03/01 15:43:02 tg Exp $");
#define KSH_CHVT_FLAG
#ifdef MKSH_SMALL
@ -281,15 +281,15 @@ change_flag(enum sh_flag f, int what, bool newset)
#endif
DO_SETUID(setresuid, (ksheuid, ksheuid, ksheuid));
#else /* !HAVE_SETRESUGID */
/* seteuid, setegid, setgid don't EAGAIN on Linux */
#ifndef MKSH__NO_SETEUGID
seteuid(ksheuid);
#endif
DO_SETUID(setuid, (ksheuid));
/* setgid, setegid, seteuid don't EAGAIN on Linux */
setgid(kshegid);
#ifndef MKSH__NO_SETEUGID
setegid(kshegid);
#endif
setgid(kshegid);
DO_SETUID(setuid, (ksheuid));
#ifndef MKSH__NO_SETEUGID
seteuid(ksheuid);
#endif
#endif /* !HAVE_SETRESUGID */
} else if ((f == FPOSIX || f == FSH) && newval) {
/* Turning on -o posix or -o sh? */
@ -304,6 +304,11 @@ change_flag(enum sh_flag f, int what, bool newset)
void
change_xtrace(unsigned char newval, bool dosnapshot)
{
static bool in_xtrace;
if (in_xtrace)
return;
if (!dosnapshot && newval == Flag(FXTRACE))
return;
@ -328,8 +333,13 @@ change_xtrace(unsigned char newval, bool dosnapshot)
shl_xtrace->fd = 2;
changed_xtrace:
if ((Flag(FXTRACE) = newval) == 2)
if ((Flag(FXTRACE) = newval) == 2) {
in_xtrace = true;
Flag(FXTRACE) = 0;
shf_puts(substitute(str_val(global("PS4")), 0), shl_xtrace);
Flag(FXTRACE) = 2;
in_xtrace = false;
}
}
/*
@ -485,7 +495,6 @@ parse_args(const char **argv,
if (arrayset) {
const char *ccp = NULL;
mkssert(array != NULL);
if (*array)
ccp = skip_varname(array, false);
if (!ccp || !(!ccp[0] || (ccp[0] == '+' && !ccp[1]))) {
@ -1384,8 +1393,7 @@ do_realpath(const char *upath)
{
char *xp, *ip, *tp, *ipath, *ldest = NULL;
XString xs;
ptrdiff_t pos;
size_t len;
size_t pos, len;
int llen;
struct stat sb;
#ifdef MKSH__NO_PATH_MAX

View file

@ -1,9 +1,9 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.344 2014/10/07 15:30:12 tg Exp $
.\" $OpenBSD: ksh.1,v 1.153 2014/08/17 07:15:41 jmc Exp $
.\" $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 $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
.\" 2010, 2011, 2012, 2013, 2014
.\" Thorsten Glaser <tg@mirbsd.org>
.\" 2010, 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
@ -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: October 7 2014 $
.Dd $Mdocdate: March 1 2015 $
.\"
.\" Check which macro package we use, and do other -mdoc setup.
.\"
@ -673,11 +673,11 @@ are reserved words, not meta-characters.
.It Xo case Ar word No in
.Oo Op \&(
.Ar pattern
.Op \*(Ba Ar pat
.Op \*(Ba Ar pattern
.No ... Ns )
.Ar list
.Op ;; \*(Ba ;&\& \*(Ba ;\*(Ba\ \&
.Oc ... esac
.Ic terminator
.Oc No ... esac
.Xc
The
.Ic case
@ -707,9 +707,11 @@ For historical reasons, open and close braces may be used instead of
and
.Ic esac
e.g.\&
.Ic case $foo { *) echo bar;; } .
.Ic case $foo { *) echo bar ;; } .
.Pp
The list terminators are:
The list
.Ic terminator Ns s
are:
.Bl -tag -width 4n
.It Ql ;;
Terminate after the list.
@ -2923,6 +2925,10 @@ trapped) will have their default effect in a function.
.It
The EXIT trap, if set in a function, will be executed after the function
returns.
.It
Shell options
.Pq Ic set Fl o
have local scope, i.e. changes inside a function are reset upon its exit.
.El
.Ss Command execution
After evaluation of command-line arguments, redirections, and parameter
@ -3370,9 +3376,25 @@ string which the shell then parses and executes in the current environment.
.Pp
.It Xo
.Ic exec
.Op Fl a Ar argv0
.Op Fl c
.Op Ar command Op Ar arg ...
.Xc
The command is executed without forking, replacing the shell process.
This is currently absolute, i.e.\&
.Ic exec
never returns, even if the
.Ar command
is not found.
The
.Fl a
option permits setting a different
.Li argv[0]
value, and
.Fl c
clears the environment before executing the child process, except for the
.Ev _
variable and direct assignments.
.Pp
If no command is given except for I/O redirection, the I/O redirection is
permanent and the shell is
@ -6457,6 +6479,17 @@ If you require 64-bit integer arithmetics, use
instead, but be aware that, in POSIX, it's legal for the OS to make
.Li print $((2147483647 + 1))
delete all files on your system, as it's Undefined Behaviour.
.Pp
.Nm mksh
provides a consistent, clear interface normally.
This may deviate from POSIX in optional or opinionated places, such
as whether leading-digit-zero numbers should be interpreted as octal.
.Ic set \-o posix
will cause the shell (either
.Nm mksh
or
.Nm lksh )
to behave more like the standard expects.
.Sh BUGS
Suspending (using \*(haZ) pipelines like the one below will only suspend
the currently running part of the pipeline; in this example,
@ -6468,16 +6501,19 @@ $ /bin/sleep 666 && echo fubar
.Ed
.Pp
This document attempts to describe
.Nm mksh\ R50
.Nm mksh\ R50e
and up,
compiled without any options impacting functionality, such as
.Dv MKSH_SMALL ,
when not called as
.Pa /bin/sh
which, on some systems only, enables
.Ic set \-o posix
or
.Ic set \-o sh
automatically (whose behaviour differs across targets),
for an operating environment supporting all of its advanced needs.
.Pp
Please report bugs in
.Nm
to the

View file

@ -10,7 +10,7 @@
/*-
* Copyright © 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
@ -169,9 +169,9 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.697 2014/10/07 15:22:17 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.701.2.4 2015/03/01 15:43:05 tg Exp $");
#endif
#define MKSH_VERSION "R50 2014/10/07"
#define MKSH_VERSION "R50 2015/03/01"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
@ -312,9 +312,13 @@ struct rusage {
#undef PATH_MAX
#else
#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif
#endif
#ifndef SIZE_MAX
#ifdef SIZE_T_MAX
#define SIZE_MAX SIZE_T_MAX
@ -533,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 != 504)
#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 505)
#error Must run Build.sh to compile this.
extern void thiswillneverbedefinedIhope(void);
int
@ -992,8 +996,8 @@ EXTERN sigset_t sm_default, sm_sigchld;
/* name of called builtin function (used by error functions) */
EXTERN const char *builtin_argv0;
/* flags of called builtin (SPEC_BI, etc.) */
EXTERN uint32_t builtin_flag;
/* is called builtin SPEC_BI? */
EXTERN bool builtin_spec;
/* current working directory */
EXTERN char *current_wd;
@ -1233,6 +1237,7 @@ struct block {
/* Values for struct block.flags */
#define BF_DOGETOPTS BIT(0) /* save/restore getopts state */
#define BF_STOPENV BIT(1) /* do not export further */
/*
* Used by ktwalk() and ktnext() routines.
@ -1396,7 +1401,8 @@ struct ioword {
#define DOVACHECK BIT(9) /* var assign check (for typeset, set, etc) */
#define DOMARKDIRS BIT(10) /* force markdirs behaviour */
#define DOTCOMEXEC BIT(11) /* not an eval flag, used by sh -c hack */
#define DOASNFIELD BIT(12) /* is assignment, change field handling */
#define DOSCALAR BIT(12) /* change field handling to non-list context */
#define DOHEREDOC BIT(13) /* change scalar handling to heredoc body */
#define X_EXTRA 20 /* this many extra bytes in X string */
@ -1645,7 +1651,7 @@ char *evalonestr(const char *cp, int);
char *debunk(char *, const char *, size_t);
void expand(const char *, XPtrV *, int);
int glob_str(char *, XPtrV *, bool);
char *tilde(char *);
char *do_tilde(char *);
/* exec.c */
int execute(struct op * volatile, volatile int, volatile int * volatile);
int shcomexec(const char **);

113
src/shf.c
View file

@ -2,7 +2,7 @@
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
* 2012, 2013
* 2012, 2013, 2015
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@ -25,7 +25,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.62 2013/10/09 11:59:30 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.62.2.2 2015/03/01 15:43:07 tg Exp $");
/* flags to shf_emptybuf() */
#define EB_READSW 0x01 /* about to switch to reading */
@ -232,7 +232,7 @@ shf_close(struct shf *shf)
if (shf->fd >= 0) {
ret = shf_flush(shf);
if (close(shf->fd) < 0)
ret = EOF;
ret = -1;
}
if (shf->flags & SHF_ALLOCS)
afree(shf, shf->areap);
@ -251,7 +251,7 @@ shf_fdclose(struct shf *shf)
if (shf->fd >= 0) {
ret = shf_flush(shf);
if (close(shf->fd) < 0)
ret = EOF;
ret = -1;
shf->rnleft = 0;
shf->rp = shf->buf;
shf->wnleft = 0;
@ -283,20 +283,20 @@ shf_sclose(struct shf *shf)
/*
* Un-read what has been read but not examined, or write what has been
* buffered. Returns 0 for success, EOF for (write) error.
* buffered. Returns 0 for success, -1 for (write) error.
*/
int
shf_flush(struct shf *shf)
{
if (shf->flags & SHF_STRING)
return ((shf->flags & SHF_WR) ? EOF : 0);
return ((shf->flags & SHF_WR) ? -1 : 0);
if (shf->fd < 0)
internal_errorf("%s: %s", "shf_flush", "no fd");
if (shf->flags & SHF_ERROR) {
errno = shf->errnosv;
return (EOF);
return (-1);
}
if (shf->flags & SHF_READING) {
@ -315,7 +315,7 @@ shf_flush(struct shf *shf)
/*
* Write out any buffered data. If currently reading, flushes the read
* buffer. Returns 0 for success, EOF for (write) error.
* buffer. Returns 0 for success, -1 for (write) error.
*/
static int
shf_emptybuf(struct shf *shf, int flags)
@ -327,7 +327,7 @@ shf_emptybuf(struct shf *shf, int flags)
if (shf->flags & SHF_ERROR) {
errno = shf->errnosv;
return (EOF);
return (-1);
}
if (shf->flags & SHF_READING) {
@ -347,7 +347,7 @@ shf_emptybuf(struct shf *shf, int flags)
*/
if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) ||
!(shf->flags & SHF_ALLOCB))
return (EOF);
return (-1);
/* allocate more space for buffer */
nbuf = aresize2(shf->buf, 2, shf->wbsize, shf->areap);
shf->rp = nbuf + (shf->rp - shf->buf);
@ -379,7 +379,7 @@ shf_emptybuf(struct shf *shf, int flags)
ntowrite);
shf->wp = shf->buf + ntowrite;
}
return (EOF);
return (-1);
}
buf += n;
ntowrite -= n;
@ -399,7 +399,7 @@ shf_emptybuf(struct shf *shf, int flags)
return (ret);
}
/* Fill up a read buffer. Returns EOF for a read error, 0 otherwise. */
/* Fill up a read buffer. Returns -1 for a read error, 0 otherwise. */
static int
shf_fillbuf(struct shf *shf)
{
@ -414,11 +414,11 @@ shf_fillbuf(struct shf *shf)
if (shf->flags & (SHF_EOF | SHF_ERROR)) {
if (shf->flags & SHF_ERROR)
errno = shf->errnosv;
return (EOF);
return (-1);
}
if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
return (EOF);
if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1)
return (-1);
shf->flags |= SHF_READING;
@ -434,7 +434,7 @@ shf_fillbuf(struct shf *shf)
shf->errnosv = errno;
shf->rnleft = 0;
shf->rp = shf->buf;
return (EOF);
return (-1);
}
if ((shf->rnleft = n) == 0)
shf->flags |= SHF_EOF;
@ -443,7 +443,7 @@ shf_fillbuf(struct shf *shf)
/*
* Read a buffer from shf. Returns the number of bytes read into buf, if
* no bytes were read, returns 0 if end of file was seen, EOF if a read
* no bytes were read, returns 0 if end of file was seen, -1 if a read
* error occurred.
*/
ssize_t
@ -459,7 +459,7 @@ shf_read(char *buf, ssize_t bsize, struct shf *shf)
while (bsize > 0) {
if (shf->rnleft == 0 &&
(shf_fillbuf(shf) == EOF || shf->rnleft == 0))
(shf_fillbuf(shf) == -1 || shf->rnleft == 0))
break;
ncopy = shf->rnleft;
if (ncopy > bsize)
@ -471,12 +471,12 @@ shf_read(char *buf, ssize_t bsize, struct shf *shf)
shf->rnleft -= ncopy;
}
/* Note: fread(3S) returns 0 for errors - this doesn't */
return (orig_bsize == bsize ? (shf_error(shf) ? EOF : 0) :
return (orig_bsize == bsize ? (shf_error(shf) ? -1 : 0) :
orig_bsize - bsize);
}
/*
* Read up to a newline or EOF. The newline is put in buf; buf is always
* Read up to a newline or -1. The newline is put in buf; buf is always
* NUL terminated. Returns NULL on read error or if nothing was read
* before end of file, returns a pointer to the NUL byte in buf
* otherwise.
@ -498,7 +498,7 @@ shf_getse(char *buf, ssize_t bsize, struct shf *shf)
--bsize;
do {
if (shf->rnleft == 0) {
if (shf_fillbuf(shf) == EOF)
if (shf_fillbuf(shf) == -1)
return (NULL);
if (shf->rnleft == 0) {
*buf = '\0';
@ -520,22 +520,22 @@ shf_getse(char *buf, ssize_t bsize, struct shf *shf)
return (buf);
}
/* Returns the char read. Returns EOF for error and end of file. */
/* Returns the char read. Returns -1 for error and end of file. */
int
shf_getchar(struct shf *shf)
{
if (!(shf->flags & SHF_RD))
internal_errorf("%s: flags 0x%X", "shf_getchar", shf->flags);
if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
return (EOF);
if (shf->rnleft == 0 && (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
return (-1);
--shf->rnleft;
return (*shf->rp++);
}
/*
* Put a character back in the input stream. Returns the character if
* successful, EOF if there is no room.
* successful, -1 if there is no room.
*/
int
shf_ungetc(int c, struct shf *shf)
@ -543,12 +543,12 @@ shf_ungetc(int c, struct shf *shf)
if (!(shf->flags & SHF_RD))
internal_errorf("%s: flags 0x%X", "shf_ungetc", shf->flags);
if ((shf->flags & SHF_ERROR) || c == EOF ||
if ((shf->flags & SHF_ERROR) || c == -1 ||
(shf->rp == shf->buf && shf->rnleft))
return (EOF);
return (-1);
if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF)
return (EOF);
if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1)
return (-1);
if (shf->rp == shf->buf)
shf->rp = shf->buf + shf->rbsize;
@ -558,7 +558,7 @@ shf_ungetc(int c, struct shf *shf)
* we don't want to modify a string.
*/
if ((int)(shf->rp[-1]) != c)
return (EOF);
return (-1);
shf->flags &= ~SHF_EOF;
shf->rp--;
shf->rnleft++;
@ -571,7 +571,7 @@ shf_ungetc(int c, struct shf *shf)
}
/*
* Write a character. Returns the character if successful, EOF if the
* Write a character. Returns the character if successful, -1 if the
* char could not be written.
*/
int
@ -580,8 +580,8 @@ shf_putchar(int c, struct shf *shf)
if (!(shf->flags & SHF_WR))
internal_errorf("%s: flags 0x%X", "shf_putchar", shf->flags);
if (c == EOF)
return (EOF);
if (c == -1)
return (-1);
if (shf->flags & SHF_UNBUF) {
unsigned char cc = (unsigned char)c;
@ -591,7 +591,7 @@ shf_putchar(int c, struct shf *shf)
internal_errorf("%s: %s", "shf_putchar", "no fd");
if (shf->flags & SHF_ERROR) {
errno = shf->errnosv;
return (EOF);
return (-1);
}
while ((n = write(shf->fd, &cc, 1)) != 1)
if (n < 0) {
@ -600,12 +600,12 @@ shf_putchar(int c, struct shf *shf)
continue;
shf->flags |= SHF_ERROR;
shf->errnosv = errno;
return (EOF);
return (-1);
}
} else {
/* Flush deals with strings and sticky errors */
if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF)
return (EOF);
if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == -1)
return (-1);
shf->wnleft--;
*shf->wp++ = c;
}
@ -614,19 +614,19 @@ shf_putchar(int c, struct shf *shf)
}
/*
* Write a string. Returns the length of the string if successful, EOF
* Write a string. Returns the length of the string if successful, -1
* if the string could not be written.
*/
ssize_t
shf_puts(const char *s, struct shf *shf)
{
if (!s)
return (EOF);
return (-1);
return (shf_write(s, strlen(s), shf));
}
/* Write a buffer. Returns nbytes if successful, EOF if there is an error. */
/* Write a buffer. Returns nbytes if successful, -1 if there is an error. */
ssize_t
shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
{
@ -653,13 +653,13 @@ shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
if (shf->flags & SHF_STRING) {
/* resize buffer until there's enough space left */
while (nbytes > shf->wnleft)
if (shf_emptybuf(shf, EB_GROW) == EOF)
return (EOF);
if (shf_emptybuf(shf, EB_GROW) == -1)
return (-1);
/* then write everything into the buffer */
} else {
/* flush deals with sticky errors */
if (shf_emptybuf(shf, EB_GROW) == EOF)
return (EOF);
if (shf_emptybuf(shf, EB_GROW) == -1)
return (-1);
/* write chunks larger than window size directly */
if (nbytes > shf->wbsize) {
ncopy = nbytes;
@ -679,7 +679,7 @@ shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
* Note: fwrite(3) returns 0
* for errors - this doesn't
*/
return (EOF);
return (-1);
}
buf += n;
ncopy -= n;
@ -767,12 +767,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
ssize_t field, precision, len;
unsigned long lnum;
/* %#o produces the longest output */
char numbuf[(8 * sizeof(long) + 2) / 3 + 1
#ifdef DEBUG
/* a NUL for LLVM/Clang scan-build */
+ 1
#endif
];
char numbuf[(8 * sizeof(long) + 2) / 3 + 1];
/* this stuff for dealing with the buffer */
ssize_t nwritten = 0;
@ -910,16 +905,6 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
integral:
flags |= FL_NUMBER;
cp = numbuf + sizeof(numbuf);
#ifdef DEBUG
/*
* this is necessary so Clang 3.2 realises
* utf_skipcols/shf_putc in the output loop
* terminate; these values are always ASCII
* so an out-of-bounds access cannot happen
* but Clang doesn't know that
*/
*--cp = '\0';
#endif
switch (c) {
case 'd':
@ -971,10 +956,6 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
}
}
len = numbuf + sizeof(numbuf) - (s = cp);
#ifdef DEBUG
/* see above comment for Clang 3.2 */
--len;
#endif
if (flags & FL_DOT) {
if (precision > len) {
field = precision;
@ -1068,7 +1049,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
}
}
return (shf_error(shf) ? EOF : nwritten);
return (shf_error(shf) ? -1 : nwritten);
}
#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)

View file

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94 2014/01/05 21:57:29 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94.2.1 2015/01/25 15:35:54 tg Exp $");
struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */
@ -196,10 +196,11 @@ synio(int cf)
musthave(LWORD, ishere ? HEREDELIM : 0);
if (ishere) {
iop->delim = yylval.cp;
if (*ident != 0)
if (*ident != 0) {
/* unquoted */
gotnulldelim:
iop->flag |= IOEVAL;
}
if (herep > &heres[HERES - 1])
yyerror("too many %ss\n", "<<");
*herep++ = iop;

View file

@ -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
@ -28,7 +28,7 @@
#include <sys/sysctl.h>
#endif
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183 2014/10/04 11:47:19 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.183.2.2 2015/03/01 15:43:07 tg Exp $");
/*-
* Variables
@ -308,7 +308,6 @@ local(const char *n, bool copy)
* dereference namerefs; must come first
*/
n = array_index_calc(n, &array, &val);
mkssert(n != NULL);
h = hash(n);
if (!ksh_isalphx(*n)) {
vp = &vtemp;
@ -679,8 +678,6 @@ exportprep(struct tbl *vp, const char *val)
char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
size_t namelen, vallen;
mkssert(val != NULL);
namelen = strlen(vp->name);
vallen = strlen(val) + 1;
@ -1114,6 +1111,8 @@ makenv(void)
}
XPput(denv, vp->val.s);
}
if (l->flags & BF_STOPENV)
break;
}
XPput(denv, NULL);
return ((char **)XPclose(denv));