include $(CLEAR_VARS)
-LOCAL_MODULE:= sh
+LOCAL_MODULE := sh
+LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
# mksh source files
LOCAL_SRC_FILES:= src/lalloc.c src/edit.c src/eval.c src/exec.c \
-DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH \
-D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN \
-DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 \
- -DHAVE_ATTRIBUTE_NORETURN=1 -DHAVE_ATTRIBUTE_UNUSED=1 \
+ -DHAVE_ATTRIBUTE_NORETURN=1 \
+ -DHAVE_ATTRIBUTE_PURE=1 \
+ -DHAVE_ATTRIBUTE_UNUSED=1 \
-DHAVE_ATTRIBUTE_USED=1 -DHAVE_SYS_TIME_H=1 -DHAVE_TIME_H=1 \
-DHAVE_BOTH_TIME_H=1 -DHAVE_SYS_BSDTYPES_H=0 \
-DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 \
-DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 -DHAVE_RLIM_T=1 \
-DHAVE_SIG_T=1 -DHAVE_SYS_ERRLIST=0 -DHAVE_SYS_SIGNAME=1 \
-DHAVE_SYS_SIGLIST=1 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 \
- -DHAVE_GETRUSAGE=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_KILLPG=1 \
+ -DHAVE_GETRUSAGE=1 \
+ -DHAVE_GETSID=1 \
+ -DHAVE_GETTIMEOFDAY=1 -DHAVE_KILLPG=1 \
-DHAVE_MEMMOVE=1 -DHAVE_MKNOD=0 -DHAVE_MMAP=1 -DHAVE_NICE=1 \
-DHAVE_REVOKE=0 -DHAVE_SETLOCALE_CTYPE=0 \
-DHAVE_LANGINFO_CODESET=0 -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 \
-DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 \
-DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \
-DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 \
- -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=481
+ -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=501
# check_categories= shell:legacy-no int:32 android convfds no-histfile
--- /dev/null
+# Makefile fragment for building mksh R50 2014/06/29
+
+PROG= mksh
+MAN= mksh.1
+SRCS= lalloc.c eval.c exec.c expr.c funcs.c histrap.c jobs.c lex.c main.c misc.c shf.c syn.c tree.c var.c edit.c
+SRCS_FP= ../src/lalloc.c ../src/eval.c ../src/exec.c ../src/expr.c ../src/funcs.c ../src/histrap.c ../src/jobs.c ../src/lex.c ../src/main.c ../src/misc.c ../src/shf.c ../src/syn.c ../src/tree.c ../src/var.c ../src/edit.c
+OBJS_BP= lalloc.o eval.o exec.o expr.o funcs.o histrap.o jobs.o lex.o main.o misc.o shf.o syn.o tree.o var.o edit.o
+INDSRCS= emacsfn.h rlimits.opt sh.h sh_flags.opt var_spec.h
+NONSRCS_INST= dot.mkshrc $(MAN)
+NONSRCS_NOINST= Build.sh Makefile Rebuild.sh check.pl check.t test.sh
+CC= /huge-ssd/lmp-dev/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gcc
+CFLAGS= -fno-exceptions -Wno-multichar -msoft-float -fpic -fPIE -ffunction-sections -fdata-sections -funwind-tables -fstack-protector -Wa,--noexecstack -Werror=format-security -fno-short-enums -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -Wno-unused-but-set-variable -fno-builtin-sin -fno-strict-volatile-bitfields -Wno-psabi -mthumb-interwork -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -g -Wstrict-aliasing=2 -fgcse-after-reload -frerun-cse-after-loop -frename-registers -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -Wno-deprecated-declarations -fno-asynchronous-unwind-tables -fwrapv
+CPPFLAGS= -I. -I'../src' -I/huge-ssd/lmp-dev/libnativehelper/include/nativehelper -isystem /huge-ssd/lmp-dev/system/core/include -isystem /huge-ssd/lmp-dev/hardware/libhardware/include -isystem /huge-ssd/lmp-dev/hardware/libhardware_legacy/include -isystem /huge-ssd/lmp-dev/hardware/ril/include -isystem /huge-ssd/lmp-dev/libnativehelper/include -isystem /huge-ssd/lmp-dev/frameworks/native/include -isystem /huge-ssd/lmp-dev/frameworks/native/opengl/include -isystem /huge-ssd/lmp-dev/frameworks/av/include -isystem /huge-ssd/lmp-dev/frameworks/base/include -isystem /huge-ssd/lmp-dev/external/skia/include -isystem /huge-ssd/lmp-dev/out/target/product/hammerhead/obj/include -isystem /huge-ssd/lmp-dev/bionic/libc/arch-arm/include -isystem /huge-ssd/lmp-dev/bionic/libc/include -isystem /huge-ssd/lmp-dev/bionic/libstdc++/include -isystem /huge-ssd/lmp-dev/bionic/libc/kernel/uapi -isystem /huge-ssd/lmp-dev/bionic/libc/kernel/uapi/asm-arm -isystem /huge-ssd/lmp-dev/bionic/libm/include -isystem /huge-ssd/lmp-dev/bionic/libm/include/arm -isystem /huge-ssd/lmp-dev/bionic/libthread_db/include -D_FORTIFY_SOURCE=2 -include /huge-ssd/lmp-dev/build/core/combo/include/arch/linux-arm/AndroidConfig.h -I/huge-ssd/lmp-dev/build/core/combo/include/arch/linux-arm/ -DANDROID -DNDEBUG -UDEBUG -DDEBUG_LEAKS -DMKSH_ASSUME_UTF8 -DMKSH_CONSERVATIVE_FDS -DMKSH_DONT_EMIT_IDSTRING -DMKSH_NOPWNAM -DMKSH_BUILDSH -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN -DHAVE_ATTRIBUTE_BOUNDED=0 -DHAVE_ATTRIBUTE_FORMAT=1 -DHAVE_ATTRIBUTE_NORETURN=1 -DHAVE_ATTRIBUTE_PURE=1 -DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 -DHAVE_SYS_TIME_H=1 -DHAVE_TIME_H=1 -DHAVE_BOTH_TIME_H=1 -DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 -DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 -DHAVE_PATHS_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 -DHAVE_CAN_INTTYPES=1 -DHAVE_CAN_UCBINTS=1 -DHAVE_CAN_INT8TYPE=1 -DHAVE_CAN_UCBINT8=1 -DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_ERRLIST=0 -DHAVE_SYS_SIGNAME=1 -DHAVE_SYS_SIGLIST=1 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 -DHAVE_GETRUSAGE=1 -DHAVE_GETSID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_KILLPG=1 -DHAVE_MEMMOVE=1 -DHAVE_MKNOD=0 -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=0 -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRERROR=1 -DHAVE_STRSIGNAL=0 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 -DHAVE_SYS_ERRLIST_DECL=0 -DHAVE_SYS_SIGLIST_DECL=1 -DHAVE_PERSISTENT_HISTORY=0 -DMKSH_BUILD_R=501
+LDFLAGS= -nostdlib -Bdynamic -fPIE -pie -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--icf=safe -Wl,--fix-cortex-a8 -Wl,--no-undefined /huge-ssd/lmp-dev/out/target/product/hammerhead/obj/lib/crtbegin_dynamic.o
+LIBS= -L/huge-ssd/lmp-dev/out/target/product/hammerhead/obj/lib -Wl,-rpath-link=/huge-ssd/lmp-dev/out/target/product/hammerhead/obj/lib -Wl,--no-whole-archive /huge-ssd/lmp-dev/out/target/product/hammerhead/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a -lc /huge-ssd/lmp-dev/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/../lib/gcc/arm-linux-androideabi/4.8/armv7-a/libgcc.a /huge-ssd/lmp-dev/out/target/product/hammerhead/obj/lib/crtend_android.o
+
+.depend $(OBJS_BP): rlimits.gen sh_flags.gen
+rlimits.gen: ../src/Build.sh ../src/rlimits.opt
+ srcfile=../src/rlimits.opt; BUILDSH_RUN_GENOPT=1; . ../src/Build.sh
+sh_flags.gen: ../src/Build.sh ../src/sh_flags.opt
+ srcfile=../src/sh_flags.opt; BUILDSH_RUN_GENOPT=1; . ../src/Build.sh
+
+# not BSD make only:
+#VPATH= ../src
+#all: $(PROG)
+#$(PROG): $(OBJS_BP)
+# $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS_BP) $(LIBS)
+#$(OBJS_BP): $(SRCS_FP) $(NONSRCS)
+#.c.o:
+# $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+# for all make variants:
+#REGRESS_FLAGS= -f
+#regress:
+# ./test.sh $(REGRESS_FLAGS)
+check_categories= shell:legacy-no int:32 android convfds no-histfile
+
+# for BSD make only:
+#.PATH: ../src
+#.include <bsd.prog.mk>
# possible to the values used later. (You also must example the
# results gathered from Makefrag.inc to see they are the same
# across all Android platforms, or add appropriate ifdefs.)
-# Since we no longer use the NDK, the AOSP has to have been
-# built before using this script (targetting generic/emulator).
+# Since we no longer use the NDK, AOSP has to have been
+# built before using this script.
-CC=$aospdir/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin/arm-linux-androideabi-gcc
+CC=$aospdir/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gcc
addvar CPPFLAGS \
-I$aospdir/libnativehelper/include/nativehelper \
-isystem $aospdir/system/core/include \
-isystem $aospdir/frameworks/av/include \
-isystem $aospdir/frameworks/base/include \
-isystem $aospdir/external/skia/include \
- -isystem $aospdir/out/target/product/generic/obj/include \
+ -isystem $ANDROID_PRODUCT_OUT/obj/include \
-isystem $aospdir/bionic/libc/arch-arm/include \
-isystem $aospdir/bionic/libc/include \
-isystem $aospdir/bionic/libstdc++/include \
-Wl,--icf=safe \
-Wl,--fix-cortex-a8 \
-Wl,--no-undefined \
- $aospdir/out/target/product/generic/obj/lib/crtbegin_dynamic.o
+ $ANDROID_PRODUCT_OUT/obj/lib/crtbegin_dynamic.o
addvar LIBS \
- -L$aospdir/out/target/product/generic/obj/lib \
- -Wl,-rpath-link=$aospdir/out/target/product/generic/obj/lib \
+ -L$ANDROID_PRODUCT_OUT/obj/lib \
+ -Wl,-rpath-link=$ANDROID_PRODUCT_OUT/obj/lib \
-Wl,--no-whole-archive \
- $aospdir/out/target/product/generic/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a \
+ $ANDROID_PRODUCT_OUT/obj/STATIC_LIBRARIES/libcompiler_rt-extras_intermediates/libcompiler_rt-extras.a \
-lc \
- $aospdir/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin/../lib/gcc/arm-linux-androideabi/4.7/armv7-a/libgcc.a \
- $aospdir/out/target/product/generic/obj/lib/crtend_android.o
+ $aospdir/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/../lib/gcc/arm-linux-androideabi/4.8/armv7-a/libgcc.a \
+ $ANDROID_PRODUCT_OUT/obj/lib/crtend_android.o
### Flags used by test builds
#!/bin/sh
-srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.645 2013/08/10 13:44:25 tg Exp $'
+srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.662 2014/06/29 10:56:08 tg Exp $'
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013
+# 2011, 2012, 2013, 2014
# Thorsten Glaser <tg@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
LC_ALL=C
export LC_ALL
-echo "For the build logs, demonstrate that /dev/null and /dev/tty exist:"
-ls -l /dev/null /dev/tty
-
case $ZSH_VERSION:$VERSION in
:zsh*) ZSH_VERSION=2 ;;
esac
export PATH
fi
+nl='
+'
+safeIFS=' '
+safeIFS=" $safeIFS$nl"
+IFS=$safeIFS
+allu=QWERTYUIOPASDFGHJKLZXCVBNM
+alll=qwertyuiopasdfghjklzxcvbnm
+alln=0123456789
+alls=______________________________________________________________
+
+genopt_die() {
+ if test -n "$1"; then
+ echo >&2 "E: $*"
+ echo >&2 "E: in '$srcfile': '$line'"
+ else
+ echo >&2 "E: invalid input in '$srcfile': '$line'"
+ fi
+ rm -f "$bn.gen"
+ exit 1
+}
+
+genopt_soptc() {
+ optc=`echo "$line" | sed 's/^[<>]\(.\).*$/\1/'`
+ test x"$optc" = x'|' && return
+ optclo=`echo "$optc" | tr $allu $alll`
+ if test x"$optc" = x"$optclo"; then
+ islo=1
+ else
+ islo=0
+ fi
+ sym=`echo "$line" | sed 's/^[<>]/|/'`
+ o_str=$o_str$nl"<$optclo$islo$sym"
+}
+
+genopt_scond() {
+ case x$cond in
+ x)
+ cond=
+ ;;
+ x*' '*)
+ cond=`echo "$cond" | sed 's/^ //'`
+ cond="#if $cond"
+ ;;
+ x'!'*)
+ cond=`echo "$cond" | sed 's/^!//'`
+ cond="#ifndef $cond"
+ ;;
+ x*)
+ cond="#ifdef $cond"
+ ;;
+ esac
+}
+
+do_genopt() {
+ srcfile=$1
+ test -f "$srcfile" || genopt_die Source file \$srcfile not set.
+ bn=`basename "$srcfile" | sed 's/.opt$//'`
+ o_gen=
+ o_str=
+ o_sym=
+ ddefs=
+ state=0
+ exec <"$srcfile"
+ IFS=
+ while IFS= read line; do
+ IFS=$safeIFS
+ case $state:$line in
+ 2:'|'*)
+ # end of input
+ o_sym=`echo "$line" | sed 's/^.//'`
+ o_gen=$o_gen$nl"#undef F0"
+ o_gen=$o_gen$nl"#undef FN"
+ o_gen=$o_gen$ddefs
+ state=3
+ ;;
+ 1:@@)
+ # begin of data block
+ o_gen=$o_gen$nl"#endif"
+ o_gen=$o_gen$nl"#ifndef F0"
+ o_gen=$o_gen$nl"#define F0 FN"
+ o_gen=$o_gen$nl"#endif"
+ state=2
+ ;;
+ *:@@*)
+ genopt_die ;;
+ 0:@*|1:@*)
+ # begin of a definition block
+ sym=`echo "$line" | sed 's/^@//'`
+ if test $state = 0; then
+ o_gen=$o_gen$nl"#if defined($sym)"
+ else
+ o_gen=$o_gen$nl"#elif defined($sym)"
+ fi
+ ddefs="$ddefs$nl#undef $sym"
+ state=1
+ ;;
+ 0:*|3:*)
+ genopt_die ;;
+ 1:*)
+ # definition line
+ o_gen=$o_gen$nl$line
+ ;;
+ 2:'<'*'|'*)
+ genopt_soptc
+ ;;
+ 2:'>'*'|'*)
+ genopt_soptc
+ cond=`echo "$line" | sed 's/^[^|]*|//'`
+ genopt_scond
+ case $optc in
+ '|') optc=0 ;;
+ *) optc=\'$optc\' ;;
+ esac
+ IFS= read line || genopt_die Unexpected EOF
+ IFS=$safeIFS
+ test -n "$cond" && o_gen=$o_gen$nl"$cond"
+ o_gen=$o_gen$nl"$line, $optc)"
+ test -n "$cond" && o_gen=$o_gen$nl"#endif"
+ ;;
+ esac
+ done
+ case $state:$o_sym in
+ 3:) genopt_die Expected optc sym at EOF ;;
+ 3:*) ;;
+ *) genopt_die Missing EOF marker ;;
+ esac
+ echo "$o_str" | sort | while IFS='|' read x opts cond; do
+ IFS=$safeIFS
+ test -n "$x" || continue
+ genopt_scond
+ test -n "$cond" && echo "$cond"
+ echo "\"$opts\""
+ test -n "$cond" && echo "#endif"
+ done | {
+ echo "#ifndef $o_sym$o_gen"
+ echo "#else"
+ cat
+ echo "#undef $o_sym"
+ echo "#endif"
+ } >"$bn.gen"
+ IFS=$safeIFS
+ return 0
+}
+
+if test x"$BUILDSH_RUN_GENOPT" = x"1"; then
+ set x -G "$srcfile"
+ shift
+fi
+if test x"$1" = x"-G"; then
+ do_genopt "$2"
+ exit $?
+fi
+
+echo "For the build logs, demonstrate that /dev/null and /dev/tty exist:"
+ls -l /dev/null /dev/tty
+
v() {
$e "$*"
eval "$@"
rmf() {
for _f in "$@"; do
case $_f in
- Build.sh|check.pl|check.t|dot.mkshrc|*.c|*.h|*.ico|*.1) ;;
+ Build.sh|check.pl|check.t|dot.mkshrc|*.1|*.c|*.h|*.ico|*.opt) ;;
*) rm -f "$_f" ;;
esac
done
}
-allu=QWERTYUIOPASDFGHJKLZXCVBNM
-alll=qwertyuiopasdfghjklzxcvbnm
-alln=0123456789
-alls=______________________________________________________________
-nl='
-'
tcfn=no
bi=
ui=
ac_ifcpp() {
expr=$1; shift
ac_testn "$@" <<-EOF
+ #include <unistd.h>
extern int thiswillneverbedefinedIhope(void);
- int main(void) { return (
+ int main(void) { return (isatty(0) +
#$expr
0
#else
else
ac_testn can_$vn '' "$ft" <<-'EOF'
/* evil apo'stroph in comment test */
- int main(void) { return (0); }
+ #include <unistd.h>
+ int main(void) { return (isatty(0)); }
EOF
fi
eval fv=\$HAVE_CAN_`upper $vn`
esac
done
echo "#include <$hf>" >>x
- echo 'int main(void) { return (0); }' >>x
+ echo '#include <unistd.h>' >>x
+ echo 'int main(void) { return (isatty(0)); }' >>x
ac_testn "$hv" "" "<$hf>" <x
rmf x
test 1 = $na || ac_cppflags
}
addsrcs() {
- addsrcs_s=0
- if test x"$1" = x"-s"; then
- # optstatic
- addsrcs_s=1
- shift
- fi
if test x"$1" = x"!"; then
fr=0
shift
fr=1
fi
eval i=\$$1
- if test $addsrcs_s = 1; then
- if test -f "$2" || test -f "$srcdir/$2"; then
- # always add $2, since it exists
- fr=1
- i=1
- fi
- fi
test $fr = "$i" && case " $SRCS " in
*\ $2\ *) ;;
*) SRCS="$SRCS $2" ;;
}
-curdir=`pwd` srcdir=`dirname "$0" 2>/dev/null` check_categories=
-test -n "$srcdir" || srcdir=. # in case dirname does not exist
-dstversion=`sed -n '/define MKSH_VERSION/s/^.*"\([^"]*\)".*$/\1/p' $srcdir/sh.h`
+curdir=`pwd` srcdir=`dirname "$0" 2>/dev/null`
+case x$srcdir in
+x)
+ srcdir=.
+ ;;
+*\ *|*" "*|*"$nl"*)
+ echo >&2 Source directory should not contain space or tab or newline.
+ echo >&2 Errors may occur.
+ ;;
+*"'"*)
+ echo Source directory must not contain single quotes.
+ exit 1
+ ;;
+esac
+dstversion=`sed -n '/define MKSH_VERSION/s/^.*"\([^"]*\)".*$/\1/p' "$srcdir/sh.h"`
add_cppflags -DMKSH_BUILDSH
e=echo
pm=0
cm=normal
optflags=-std-compile-opts
+check_categories=
last=
tfn=
legacy=0
:-c)
last=c
;;
+ :-G)
+ echo "$me: Do not call me with '-G'!" >&2
+ exit 1
+ ;;
:-g)
# checker, debug, valgrind build
add_cppflags -DDEBUG
echo "$me: Error: ./$tfn is a directory!" >&2
exit 1
fi
-rmf a.exe* a.out* conftest.c *core core.* lft ${tfn}* no *.bc *.ll *.o \
+rmf a.exe* a.out* conftest.c *core core.* lft ${tfn}* no *.bc *.ll *.o *.gen \
Rebuild.sh signames.inc test.sh x vv.out
SRCS="lalloc.c eval.c exec.c expr.c funcs.c histrap.c jobs.c"
ccpc=-Wc,
ccpl=-Wl,
tsts=
-ccpr='|| for _f in ${tcfn}*; do case $_f in Build.sh|check.pl|check.t|dot.mkshrc|*.c|*.h|*.ico|*.1) ;; *) rm -f "$_f" ;; esac; done'
+ccpr='|| for _f in ${tcfn}*; do case $_f in Build.sh|check.pl|check.t|dot.mkshrc|*.1|*.c|*.h|*.ico|*.opt) ;; *) rm -f "$_f" ;; esac; done'
# Evil hack
if test x"$TARGET_OS" = x"Android"; then
;;
Darwin)
vv '|' "hwprefs machine_type os_type os_class >&2"
+ vv '|' "sw_vers >&2"
+ vv '|' "system_profiler SPSoftwareDataType SPHardwareDataType >&2"
+ vv '|' "/bin/sh --version >&2"
+ vv '|' "xcodebuild -version >&2"
vv '|' "uname -a >&2"
+ vv '|' "sysctl kern.version hw.machine hw.model hw.memsize hw.availcpu hw.cpufrequency hw.byteorder hw.cpu64bit_capable >&2"
;;
IRIX*)
vv '|' "uname -a >&2"
sed 's/^/[ /' x
eval `cat x`
rmf x vv.out
-echo 'int main(void) { return (0); }' >conftest.c
+cat >conftest.c <<'EOF'
+#include <unistd.h>
+int main(void) { return (isatty(0)); }
+EOF
case $ct in
ack)
# work around "the famous ACK const bug"
dec)
CFLAGS="$CFLAGS ${ccpl}-non_shared"
ac_testn can_delexe compiler_fails 0 'for the -non_shared linker option' <<-EOF
- int main(void) { return (0); }
+ #include <unistd.h>
+ int main(void) { return (isatty(0)); }
EOF
;;
dmc)
CFLAGS="$CFLAGS ${ccpl}/DELEXECUTABLE"
ac_testn can_delexe compiler_fails 0 'for the /DELEXECUTABLE linker option' <<-EOF
- int main(void) { return (0); }
+ #include <unistd.h>
+ int main(void) { return (isatty(0)); }
EOF
;;
*)
;;
sunpro)
cat >x <<-'EOF'
- int main(void) { return (0); }
+ #include <unistd.h>
+ int main(void) { return (isatty(0)); }
#define __IDSTRING_CONCAT(l,p) __LINTED__ ## l ## _ ## p
#define __IDSTRING_EXPAND(l,p) __IDSTRING_CONCAT(l,p)
#define pad void __IDSTRING_EXPAND(__LINE__,x)(void) { }
# mksh is not written in CFrustFrust!
ac_flags 1 no_eh_frame -fno-asynchronous-unwind-tables
ac_flags 1 fnostrictaliasing -fno-strict-aliasing
- ac_flags 1 fstackprotectorall -fstack-protector-all
+ ac_flags 1 fstackprotectorstrong -fstack-protector-strong
+ test 1 = $HAVE_CAN_FSTACKPROTECTORSTRONG || \
+ ac_flags 1 fstackprotectorall -fstack-protector-all
test $cm = dragonegg && case " $CC $CFLAGS $LDFLAGS " in
*\ -fplugin=*dragonegg*) ;;
*) ac_flags 1 fplugin_dragonegg -fplugin=dragonegg ;;
#include <string.h>
#undef __attribute__
int xcopy(const void *, void *, size_t)
- __attribute__((__bounded__ (__buffer__, 1, 3)))
- __attribute__((__bounded__ (__buffer__, 2, 3)));
+ __attribute__((__bounded__(__buffer__, 1, 3)))
+ __attribute__((__bounded__(__buffer__, 2, 3)));
int main(int ac, char *av[]) { return (xcopy(av[0], av[--ac], 1)); }
int xcopy(const void *s, void *d, size_t n) {
/*
#undef __attribute__
#undef fprintf
extern int fprintf(FILE *, const char *format, ...)
- __attribute__((__format__ (__printf__, 2, 3)));
+ __attribute__((__format__(__printf__, 2, 3)));
int main(int ac, char **av) { return (fprintf(stderr, "%s%d", *av, ac)); }
#endif
EOF
void fnord(void) { exit(0); }
#endif
EOF
+ac_test attribute_pure '' 'for __attribute__((__pure__))' <<-'EOF'
+ #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
+ extern int thiswillneverbedefinedIhope(void);
+ /* force a failure: TenDRA and gcc 1.42 have false positive here */
+ int main(void) { return (thiswillneverbedefinedIhope()); }
+ #else
+ #include <unistd.h>
+ #undef __attribute__
+ int foo(const char *) __attribute__((__pure__));
+ int main(int ac, char **av) { return (foo(av[ac - 1]) + isatty(0)); }
+ int foo(const char *s) { return ((int)s[0]); }
+ #endif
+EOF
ac_test attribute_unused '' 'for __attribute__((__unused__))' <<-'EOF'
#if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
extern int thiswillneverbedefinedIhope(void);
/* force a failure: TenDRA and gcc 1.42 have false positive here */
int main(void) { return (thiswillneverbedefinedIhope()); }
#else
+ #include <unistd.h>
+ #undef __attribute__
int main(int ac __attribute__((__unused__)), char **av
- __attribute__((__unused__))) { return (0); }
+ __attribute__((__unused__))) { return (isatty(0)); }
#endif
EOF
ac_test attribute_used '' 'for __attribute__((__used__))' <<-'EOF'
/* force a failure: TenDRA and gcc 1.42 have false positive here */
int main(void) { return (thiswillneverbedefinedIhope()); }
#else
+ #include <unistd.h>
+ #undef __attribute__
static const char fnord[] __attribute__((__used__)) = "42";
- int main(void) { return (0); }
+ int main(void) { return (isatty(0)); }
#endif
EOF
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
- int main(void) { struct tm tm; return ((int)sizeof(tm)); }
+ #include <unistd.h>
+ int main(void) { struct tm tm; return ((int)sizeof(tm) + isatty(0)); }
EOF
ac_header sys/bsdtypes.h
ac_header sys/file.h sys/types.h
# Environment: definitions
#
echo '#include <sys/types.h>
+#include <unistd.h>
/* check that off_t can represent 2^63-1 correctly, thx FSF */
-#define LARGE_OFF_T (((off_t)1 << 62) - 1 + ((off_t)1 << 62))
+#define LARGE_OFF_T ((((off_t)1 << 31) << 31) - 1 + (((off_t)1 << 31) << 31))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 &&
LARGE_OFF_T % 2147483647 == 1) ? 1 : -1];
-int main(void) { return (0); }' >lft.c
+int main(void) { return (isatty(0)); }' >lft.c
ac_testn can_lfs '' "for large file support" <lft.c
save_CPPFLAGS=$CPPFLAGS
add_cppflags -D_FILE_OFFSET_BITS=64
#include <sys/resource.h>
#endif
#include <unistd.h>
- int main(void) { return ((int)(rlim_t)0); }
+ int main(void) { return (((int)(rlim_t)0) + isatty(0)); }
EOF
# only testn: added later below
#define EXTERN
#define MKSH_INCLUDES_ONLY
#include "sh.h"
- __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.645 2013/08/10 13:44:25 tg Exp $");
- int main(void) { printf("Hello, World!\n"); return (0); }
+ __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.662 2014/06/29 10:56:08 tg Exp $");
+ int main(void) { printf("Hello, World!\n"); return (isatty(0)); }
EOF
case $cm in
llvm)
ac_testn sys_errlist '' "the sys_errlist[] array and sys_nerr" <<-'EOF'
extern const int sys_nerr;
extern const char * const sys_errlist[];
- int main(void) { return (*sys_errlist[sys_nerr - 1]); }
+ extern int isatty(int);
+ int main(void) { return (*sys_errlist[sys_nerr - 1] + isatty(0)); }
EOF
ac_testn _sys_errlist '!' sys_errlist 0 "the _sys_errlist[] array and _sys_nerr" <<-'EOF'
extern const int _sys_nerr;
extern const char * const _sys_errlist[];
- int main(void) { return (*_sys_errlist[_sys_nerr - 1]); }
+ extern int isatty(int);
+ int main(void) { return (*_sys_errlist[_sys_nerr - 1] + isatty(0)); }
EOF
if test 1 = "$HAVE__SYS_ERRLIST"; then
add_cppflags -Dsys_nerr=_sys_nerr
uwhat=`upper $what`
ac_testn sys_sig$what '' "the sys_sig${what}[] array" <<-EOF
extern const char * const sys_sig${what}[];
- int main(void) { return (sys_sig${what}[0][0]); }
+ extern int isatty(int);
+ int main(void) { return (sys_sig${what}[0][0] + isatty(0)); }
EOF
ac_testn _sys_sig$what '!' sys_sig$what 0 "the _sys_sig${what}[] array" <<-EOF
extern const char * const _sys_sig${what}[];
- int main(void) { return (_sys_sig${what}[0][0]); }
+ extern int isatty(int);
+ int main(void) { return (_sys_sig${what}[0][0] + isatty(0)); }
EOF
eval uwhat_v=\$HAVE__SYS_SIG$uwhat
if test 1 = "$uwhat_v"; then
}
EOF
+ac_test getsid <<-'EOF'
+ #include <unistd.h>
+ int main(void) { return ((int)getsid(0)); }
+EOF
+
ac_test gettimeofday <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
#include <strings.h>
#endif
int main(int ac, char *av[]) {
- return (*(int *)(void *)memmove(av[0], av[1], ac));
+ return (*(int *)(void *)memmove(av[0], av[1], (size_t)ac));
}
EOF
ac_test sys_errlist_decl sys_errlist 0 "for declaration of sys_errlist[] and sys_nerr" <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
- int main(void) { return (*sys_errlist[sys_nerr - 1]); }
+ int main(void) { return (*sys_errlist[sys_nerr - 1] + isatty(0)); }
EOF
ac_test sys_siglist_decl sys_siglist 0 'for declaration of sys_siglist[]' <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
- int main(void) { return (sys_siglist[0][0]); }
+ int main(void) { return (sys_siglist[0][0] + isatty(0)); }
EOF
#
char padding[64 - NUM];
};
char ctasserts_dblcheck[sizeof(struct ctasserts) == 64 ? 1 : -1];
- int main(void) { return (sizeof(ctasserts_dblcheck)); }
+ int main(void) { return (sizeof(ctasserts_dblcheck) + isatty(0)); }
EOF
CFLAGS=$save_CFLAGS
eval test 1 = \$HAVE_COMPILE_TIME_ASSERTS_$$ || exit 1
#define NSIG (SIGMAX+1)
#elif defined(_SIGMAX)
#define NSIG (_SIGMAX+1)
+#else
+/* XXX better error out, see sh.h */
+#define NSIG 64
#endif
#endif
int
test $printf = echo || test "`printf %d 42`" = 42 || printf=echo
test $printf = echo || NSIG=`printf %d "$NSIG" 2>/dev/null`
$printf "NSIG=$NSIG ... "
- sigs="INT SEGV ABRT KILL ALRM BUS CHLD CLD CONT DIL EMT FPE HUP ILL"
- sigs="$sigs INFO IO IOT LOST PIPE PROF PWR QUIT RESV SAK STOP SYS TERM"
- sigs="$sigs TRAP TSTP TTIN TTOU URG USR1 USR2 VTALRM WINCH XCPU XFSZ"
+ sigs="ABRT FPE ILL INT SEGV TERM ALRM BUS CHLD CONT HUP KILL PIPE QUIT"
+ sigs="$sigs STOP TSTP TTIN TTOU USR1 USR2 POLL PROF SYS TRAP URG VTALRM"
+ sigs="$sigs XCPU XFSZ INFO WINCH EMT IO DIL LOST PWR SAK CLD IOT RESV"
test 1 = $HAVE_CPP_DD && test $NSIG -gt 1 && sigs="$sigs "`vq \
"$CPP $CFLAGS $CPPFLAGS $NOWARN -dD conftest.c" | \
grep '[ ]SIG[A-Z0-9][A-Z0-9]*[ ]' | \
$e done.
fi
-addsrcs -s '!' HAVE_STRLCPY strlcpy.c
+addsrcs '!' HAVE_STRLCPY strlcpy.c
addsrcs USE_PRINTF_BUILTIN printf.c
test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
-test -n "$LDSTATIC" && add_cppflags -DMKSH_OPTSTATIC
-add_cppflags -DMKSH_BUILD_R=481
+add_cppflags -DMKSH_BUILD_R=501
$e $bi$me: Finished configuration testing, now producing output.$ao
fi
(( vflag )) && args[\${#args[*]}]=-v
(( xflag )) && args[\${#args[*]}]=-x # force usage by synerr
+ if [[ -n \$TMPDIR && -d \$TMPDIR/. ]]; then
+ args[\${#args[*]}]=-T
+ args[\${#args[*]}]=\$TMPDIR
+ fi
print Testing mksh for conformance:
fgrep -e MirOS: -e MIRBSD "\$sflag"
print "This shell is actually:\\n\\t\$KSH_VERSION"
;;
esac
echo ": # work around NeXTstep bug" >Rebuild.sh
+for file in "$srcdir"/*.opt; do
+ echo "echo + Running genopt on '$file'..."
+ echo "(srcfile='$file'; BUILDSH_RUN_GENOPT=1; . '$srcdir/Build.sh')"
+done >>Rebuild.sh
echo set -x >>Rebuild.sh
for file in $SRCS; do
op=`echo x"$file" | sed 's/^x\(.*\)\.c$/\1./'`
echo "$CC $CFLAGS $LDFLAGS -o \$tcfn $lobjs $LIBS $ccpr" >>Rebuild.sh
echo "test -f \$tcfn || exit 1; $SIZE \$tcfn" >>Rebuild.sh
if test $cm = makefile; then
- extras='emacsfn.h sh.h sh_flags.h var_spec.h'
+ extras='emacsfn.h rlimits.opt sh.h sh_flags.opt var_spec.h'
test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc"
+ gens= genq=
+ for file in "$srcdir"/*.opt; do
+ genf=`basename "$file" | sed 's/.opt$/.gen/'`
+ gens="$gens $genf"
+ genq="$genq$nl$genf: $srcdir/Build.sh $file
+ srcfile=$file; BUILDSH_RUN_GENOPT=1; . $srcdir/Build.sh"
+ done
cat >Makefrag.inc <<EOF
# Makefile fragment for building mksh $dstversion
LDFLAGS= $LDFLAGS
LIBS= $LIBS
+.depend \$(OBJS_BP):$gens$genq
+
# not BSD make only:
#VPATH= $srcdir
#all: \$(PROG)
$e Generated Makefrag.inc successfully.
exit 0
fi
+for file in "$srcdir"/*.opt; do
+ $e "+ Running genopt on '$file'..."
+ do_genopt "$file" || exit 1
+done
if test $cm = combine; then
objs="-o $mkshexe"
for file in $SRCS; do
-# $MirOS: src/bin/mksh/check.pl,v 1.32 2013/07/21 18:35:56 tg Exp $
-# $OpenBSD: th,v 1.16 2013/06/14 20:52:08 millert Exp $
+# $MirOS: src/bin/mksh/check.pl,v 1.36 2014/06/09 13:25:50 tg Exp $
+# $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
-# 2012, 2013
+# 2012, 2013, 2014
# Thorsten Glaser <tg@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
use Getopt::Std;
use Config;
-use File::Temp qw/ :mktemp /;
$os = defined $^O ? $^O : 'unknown';
$test_prog = $opt_p;
$verbose = defined $opt_v && $opt_v;
$test_set = $opt_s;
-$temp_dir = $opt_T || "/tmp";
+$temp_base = $opt_T || "/tmp";
if (defined $opt_t) {
die "$prog: bad -t argument (should be number > 0): $opt_t\n"
if $opt_t !~ /^\d+$/ || $opt_t <= 0;
die "$prog: couldn't get current working directory\n" if $pwd eq '';
die "$prog: couldn't cd to $pwd - $!\n" if !chdir($pwd);
+die "$prog: couldn't cd to $temp_base - $!\n" if !chdir($temp_base);
+die "$prog: couldn't get temporary directory base\n" unless -d '.';
+$temps = sprintf("chk%d-%d.", $$, time());
+$tempi = 0;
+until (mkdir(($tempdir = sprintf("%s%03d", $temps, $tempi)), 0700)) {
+ die "$prog: couldn't get temporary directory\n" if $tempi++ >= 999;
+}
+die "$prog: couldn't cd to $tempdir - $!\n" if !chdir($tempdir);
+chop($temp_dir = `pwd 2>/dev/null`);
+die "$prog: couldn't get temporary directory\n" if $temp_dir eq '';
+die "$prog: couldn't cd to $pwd - $!\n" if !chdir($pwd);
+
if (!$program_kludge) {
$test_prog = "$pwd/$test_prog" if substr($test_prog, 0, 1) ne '/';
die "$prog: $test_prog is not executable - bye\n"
$| = 1;
# Create temp files
-($fh, $temps) = mkstemp("${temp_dir}/rts.XXXXXXXX");
-close($fh);
-($fh, $tempi) = mkstemp("${temp_dir}/rti.XXXXXXXX");
-close($fh);
-($fh, $tempo) = mkstemp("${temp_dir}/rto.XXXXXXXX");
-close($fh);
-($fh, $tempe) = mkstemp("${temp_dir}/rte.XXXXXXXX");
-close($fh);
-$tempdir = mkdtemp("${temp_dir}/rtd.XXXXXXXX");
+$temps = "${temp_dir}/rts";
+$tempi = "${temp_dir}/rti";
+$tempo = "${temp_dir}/rto";
+$tempe = "${temp_dir}/rte";
+$tempdir = "${temp_dir}/rtd";
+mkdir($tempdir, 0700) or die "$prog: couldn't mkdir $tempdir - $!\n";
if (-d $test_set) {
$file_prefix_skip = length($test_set) + 1;
unlink($tempi, $tempo, $tempe, $temps);
&scrub_dir($tempdir) if defined $tempdir;
rmdir($tempdir) if defined $tempdir;
+ rmdir($temp_dir) if defined $temp_dir;
if ($sig) {
$SIG{$sig} = 'DEFAULT';
} else {
$expr = $expect;
$expr =~ s/\b([wse])\b/\$$1/g;
- $expr =~ s/\b(SIG[A-Z0-9]+)\b/&$1/g;
+ $expr =~ s/\b(SIG[A-Z][A-Z0-9]*)\b/&$1/g;
}
$w = eval $expr;
if ($@ ne '') {
%test = ();
%cnt = ();
while (<$in>) {
+ chop;
next if /^\s*$/;
next if /^ *#/;
last if /^\s*---\s*$/;
$start_lineno = $. if !defined $start_lineno;
if (!/^([-\w]+):\s*(|\S|\S.*\S)\s*$/) {
- print STDERR "$prog:$file:$.: unrecognised line\n";
+ print STDERR "$prog:$file:$.: unrecognised line \"$_\"\n";
return undef;
}
($field, $val) = ($1, $2);
print STDERR "$prog:$test{':long-name'}: expected-exit value $val not in 0..255\n";
return undef;
}
- } elsif ($val !~ /^([\s<>+-=*%\/&|!()]|\b[wse]\b|\bSIG[A-Z0-9]+\b)+$/) {
+ } elsif ($val !~ /^([\s<>+-=*%\/&|!()]|\b[wse]\b|\bSIG[A-Z][A-Z0-9]*\b)+$/) {
print STDERR "$prog:$test{':long-name'}: bad expected-exit expression: $val\n";
return undef;
}
-# $MirOS: src/bin/mksh/check.t,v 1.629 2013/08/14 20:26:15 tg Exp $
-# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
-# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
-# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
-# $OpenBSD: regress.t,v 1.15 2013/07/01 17:25:27 jca Exp $
-# $OpenBSD: obsd-regress.t,v 1.5 2013/07/01 17:25:27 jca Exp $
+# $MirOS: src/bin/mksh/check.t,v 1.654 2014/06/29 11:28:26 tg Exp $
+# OpenBSD src/regress/bin/ksh updated: 2013/12/02 20:39:44
#-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013
+# 2011, 2012, 2013, 2014
# Thorsten Glaser <tg@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
# http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
expected-stdout:
- @(#)MIRBSD KSH R48 2013/08/14
+ @(#)MIRBSD KSH R50 2014/06/29
description:
Check version of shell.
stdin:
category: shell:legacy-no
---
expected-stdout:
- @(#)LEGACY KSH R48 2013/08/14
+ @(#)LEGACY KSH R50 2014/06/29
description:
Check version of legacy shell.
stdin:
expected-stdout:
<fnord>
---
+name: selftest-exec
+description:
+ Ensure that the test run directory (default /tmp but can be changed
+ with check.pl flag -T or test.sh $TMPDIR) is not mounted noexec, as
+ we execute scripts from the scratch directory during several tests.
+stdin:
+ print '#!'"$__progname"'\necho tf' >lq
+ chmod +x lq
+ ./lq
+expected-stdout:
+ tf
+---
name: selftest-env
description:
Just output the environment variables set (always fails)
1=02.
2=02.
---
+name: expand-number-1
+description:
+ Check that positional arguments do not overflow
+stdin:
+ echo "1 ${12345678901234567890} ."
+expected-stdout:
+ 1 .
+---
name: eglob-bad-1
description:
Check that globbing isn't done when glob has syntax error
echo [!-ab]*
echo [!ab]*
echo []ab]*
+ :>'./!bc'
+ :>'./^bc'
+ echo [^ab]*
+ echo [!ab]*
expected-stdout:
-bc abc bbc
-bc abc bbc
cbc
-bc cbc
abc bbc
+ ^bc abc bbc
+ !bc -bc ^bc cbc
---
name: glob-range-2
description:
expected-stdout:
-bc abc bbc cbc ebc
---
+name: glob-trim-1
+description:
+ Check against a regression from fixing IFS-subst-2
+stdin:
+ x='#foo'
+ print -r "before='$x'"
+ x=${x%%#*}
+ print -r "after ='$x'"
+expected-stdout:
+ before='#foo'
+ after =''
+---
name: heredoc-1
description:
Check ordering/content of redundent here documents.
12: [A] [B] [] [D]
<13> <A> <B> <> <D>
---
+name: IFS-subst-2
+description:
+ Check leading whitespace after trim does not make a field
+stdin:
+ showargs() { for i; do echo -n " <$i>"; done; echo; }
+ x="X 1 2"
+ showargs 1 shift ${x#X}
+expected-stdout:
+ <1> <shift> <1> <2>
+---
+name: IFS-arith-1
+description:
+ http://austingroupbugs.net/view.php?id=832
+stdin:
+ ${ZSH_VERSION+false} || emulate sh
+ ${BASH_VERSION+set -o posix}
+ showargs() { for x in "$@"; do echo -n "<$x> "; done; echo .; }
+ IFS=0
+ showargs $((1230456))
+expected-stdout:
+ <123> <456> .
+---
name: integer-base-err-1
description:
Can't have 0 base (causes shell to exit)
them exit 0. The POSIX behaviour is needed by BSD make.
stdin:
set -e
- echo `false; echo hi`
+ echo `false; echo hi` $(<this-file-does-not-exist)
echo $?
expected-stdout:
0
+expected-stderr-pattern: /this-file-does-not-exist/
---
name: regression-40
description:
expected-stderr-pattern:
/read-only/
---
+name: readonly-4
+description:
+ Do not permit bypassing readonly for first array item
+stdin:
+ set -A arr -- foo bar
+ readonly arr
+ arr=baz
+ print -r -- "${arr[@]}"
+expected-exit: e != 0
+expected-stderr-pattern:
+ /read[ -]?only/
+---
name: syntax-1
description:
Check that lone ampersand is a syntax error
echo 6 "$("$__progname" -c '! (exit 23) | (exit 42) | :; echo $?')" .
echo 7 "$("$__progname" -o pipefail -c '(exit 23) | (exit 42) | :; echo $?')" .
echo 8 "$("$__progname" -o pipefail -c '! (exit 23) | (exit 42) | :; echo $?')" .
+ echo 9 "$("$__progname" -o pipefail -c 'x=$( (exit 23) | (exit 42) | :); echo $?')" .
expected-stdout:
1 42 .
2 0 .
6 1 .
7 42 .
8 0 .
+ 9 42 .
---
name: persist-history-1
description:
r='fc -e -'
source='PATH=$PATH:. command .'
stop='kill -STOP'
- suspend='kill -STOP $$'
type='whence -v'
---
name: aliases-1-hartz4
r='fc -e -'
source='PATH=$PATH:. command .'
stop='kill -STOP'
- suspend='kill -STOP $$'
type='whence -v'
---
name: aliases-3b
r='fc -e -'
source='PATH=$PATH:. command .'
stop='kill -STOP'
- suspend='kill -STOP $$'
type='whence -v'
---
name: aliases-2b-hartz4
v="c d"
set -A foo -- [1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b
echo "${#foo[*]}|${foo[0]}|${foo[1]}|${foo[2]}|${foo[3]}|${foo[4]}|${foo[5]}|"
+ # we don't want this at all:
+ # 5|a|$v|c d||$v|b|
+ set -A arr "[5]=meh"
+ echo "<${arr[0]}><${arr[5]}>"
expected-stdout:
- 5|a|$v|c d||$v|b|
+ 5|[1]=$v|[2]=c d|[4]=$v|[0]=a|[5]=b||
+ <[5]=meh><>
---
name: arrays-5
description:
Check if bash-style arrays with specified indices work as expected
+ (taken out temporarily to fix arrays-4; see also arrays-9a comment)
+category: disabled
stdin:
v="c d"
foo=([1]=\$v [2]="$v" [4]='$v' [0]=a [5]=b)
x=([128]=foo bar baz)
echo k= ${!x[*]} .
echo v= ${x[*]} .
+ # Check that we do not break this by globbing
+ :>b=blah
+ bleh=5
+ typeset -a arr
+ arr+=([bleh]=blah)
+ echo "<${arr[0]}><${arr[5]}>"
expected-stdout:
5|a|$v|c d||$v|b|
k= 128 129 130 .
v= foo bar baz .
+ <><blah>
---
name: arrays-6
description:
echo !arz[0]: ${!arz[0]}
echo !arz[1]: ${!arz[1]}
expected-stdout:
- !arz: 0
- !arz[0]:
- !arz[1]:
!arz: arz
- !arz[0]: 0
- !arz[1]:
- !arz: 0
- !arz[0]:
- !arz[1]:
+ !arz[0]: arz[0]
+ !arz[1]: arz[1]
+ !arz: arz
+ !arz[0]: arz[0]
+ !arz[1]: arz[1]
+ !arz: arz
+ !arz[0]: arz[0]
+ !arz[1]: arz[1]
---
name: arrays-8
description:
stdin:
unset foo; foo=(bar); foo+=(baz); echo 1 ${!foo[*]} : ${foo[*]} .
unset foo; foo=(foo bar); foo+=(baz); echo 2 ${!foo[*]} : ${foo[*]} .
- unset foo; foo=([2]=foo [0]=bar); foo+=(baz [5]=quux); echo 3 ${!foo[*]} : ${foo[*]} .
+# unset foo; foo=([2]=foo [0]=bar); foo+=(baz [5]=quux); echo 3 ${!foo[*]} : ${foo[*]} .
expected-stdout:
1 0 1 : bar baz .
2 0 1 2 : foo bar baz .
- 3 0 2 3 5 : bar foo baz quux .
+# 3 0 2 3 5 : bar foo baz quux .
---
name: arrays-9b
description:
typeset -i8 foo=10
bar=baz
unset baz
- bla=foo
print ${foo@#} ${bar@#} ${baz@#} .
- print ${foo@#123} ${bar@#456} ${baz@#789} .
- print ${foo@#bla} ${bar@#bar} ${baz@#OPTIND} .
expected-stdout:
- D50219A0 20E5DB5B 00000000 .
- 554A1C76 004A212E CB209562 .
- 6B21CF91 20E5DB5B 124EA49D .
+ 9B15FBFB CFBDD32B 00000000 .
---
name: varexpand-special-quote
description:
---
name: oksh-eval
description:
- $OpenBSD: eval.sh,v 1.1 2010/03/24 08:29:44 fgsch Exp $
+ Check expansions.
stdin:
a=
for n in ${a#*=}; do echo 1hu ${n} .; done
---
name: oksh-varfunction-mod1
description:
- $OpenBSD: varfunction.sh,v 1.1 2003/12/15 05:28:40 otto Exp $
- Calling
+ (Inspired by PR 2450 on OpenBSD.) Calling
FOO=bar f
where f is a ksh style function, should not set FOO in the current
env. If f is a Bourne style function, FOO should be set. Furthermore,
from oksh, setting FOO in the function itself must change the value in
setting FOO in the function itself should not change the value in
global environment.
- Inspired by PR 2450.
stdin:
print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
ir2: ir2
s1: ir2=ind
s2: typeset -n ir2
- !ind[1]: 1
+ !ind[1]: blub[1]
!ir2: ir2
ind[1]: e2
ir2: e3
# $Id$
-# $MirOS: src/bin/mksh/dot.mkshrc,v 1.84 2013/08/10 13:43:50 tg Exp $
+# $MirOS: src/bin/mksh/dot.mkshrc,v 1.88 2014/01/11 18:09:39 tg Exp $
#-
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013
+# 2011, 2012, 2013, 2014
# Thorsten Glaser <tg@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
}
chpwd .
function cd {
- builtin cd "$@"
+ builtin cd "$@" || return $?
chpwd "$@"
}
function cd_csh {
local d t=${1/#~/$DIRSTACKBASE}
if ! d=$(builtin cd "$t" 2>&1); then
- print -u2 "${1}: ${d##*$t - }."
+ print -u2 "${1}: ${d##*cd: $t: }."
return 1
fi
cd "$t"
(( u )) || set -U
}
-# mksh NUL counting, never zero
-typeset -Z11 -Uui16 Lnzathash_v
-function Lnzathash_add {
+# Better Avalanche for the Jenkins Hash
+typeset -Z11 -Uui16 Lbafh_v
+function Lbafh_init {
+ Lbafh_v=0
+}
+function Lbafh_add {
[[ -o utf8-mode ]]; local u=$?
set +U
local s
local -i i=0 n=${#s[*]}
while (( i < n )); do
- ((# Lnzathash_v = (Lnzathash_v + s[i++] + 1) * 1025 ))
- ((# Lnzathash_v ^= Lnzathash_v >> 6 ))
+ ((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 ))
+ ((# Lbafh_v ^= Lbafh_v >> 6 ))
done
(( u )) || set -U
}
-function Lnzaathash_end {
- ((# Lnzathash_v *= 1025 ))
- ((# Lnzathash_v ^= Lnzathash_v >> 6 ))
- ((# Lnzathash_v += Lnzathash_v << 3 ))
- ((# Lnzathash_v = (Lnzathash_v ^
- (Lnzathash_v >> 11)) * 32769 ))
- print ${Lnzathash_v#16#}
-}
-function Lnzaathash {
- Lnzathash_v=0
- Lnzathash_add "$@"
- Lnzaathash_end
-}
-function Lnzathash {
- Lnzathash_v=0
- Lnzathash_add "$@"
- Lnzathash_end
-}
-function Lnzathash_end {
- if (( Lnzathash_v )); then
- Lnzaathash_end
- else
- Lnzathash_v=1
- print ${Lnzathash_v#16#}
- fi
+function Lbafh_finish {
+ local -Ui t
+
+ ((# t = (((Lbafh_v >> 7) & 0x01010101) * 0x1B) ^ \
+ ((Lbafh_v << 1) & 0xFEFEFEFE) ))
+ ((# Lbafh_v = t ^ (t >>> 8) ^ (Lbafh_v >>> 8) ^ \
+ (Lbafh_v >>> 16) ^ (Lbafh_v >>> 24) ))
+ :
}
# strip comments (and leading/trailing whitespace if IFS is set) from
-/* $OpenBSD: edit.c,v 1.38 2013/06/03 15:41:59 tedu Exp $ */
+/* $OpenBSD: edit.c,v 1.39 2013/12/17 16:37:05 deraadt Exp $ */
/* $OpenBSD: edit.h,v 1.9 2011/05/30 17:14:35 martynas Exp $ */
-/* $OpenBSD: emacs.c,v 1.44 2011/09/05 04:50:33 marco Exp $ */
-/* $OpenBSD: vi.c,v 1.26 2009/06/29 22:50:19 martynas Exp $ */
+/* $OpenBSD: emacs.c,v 1.48 2013/12/17 16:37:05 deraadt Exp $ */
+/* $OpenBSD: vi.c,v 1.28 2013/12/18 16:45:46 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#ifndef MKSH_NO_CMDLINE_EDITING
-__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.270 2013/08/14 20:26:17 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.275 2014/01/05 21:57:24 tg Exp $");
/*
* in later versions we might use libtermcap for this, but since external
static void x_free_words(int, char **);
static int x_escape(const char *, size_t, int (*)(const char *, size_t));
static int x_emacs(char *);
-static void x_init_prompt(void);
+static void x_init_prompt(bool);
#if !MKSH_S_NOVI
static int x_vi(char *);
#endif
if (x_cols != xx_cols && editmode == 1) {
/* redraw line in Emacs mode */
xx_cols = x_cols;
+ x_init_prompt(false);
x_e_rebuildline(MKSH_CLRTOEOL_STRING);
}
}
static size_t x_bword(void);
static size_t x_fword(bool);
static void x_goto(char *);
-static char *x_bs0(char *, char *);
+static char *x_bs0(char *, char *) MKSH_A_PURE;
static void x_bs3(char **);
static int x_size_str(char *);
static int x_size2(char *, char **);
static void x_zots(char *);
-static void x_zotc2(int);
static void x_zotc3(char **);
static void x_load_hist(char **);
static int x_search(char *, int, int);
#endif
static char *x_lastcp(void);
static void do_complete(int, Comp_type);
-static size_t x_nb2nc(size_t);
+static size_t x_nb2nc(size_t) MKSH_A_PURE;
static int unget_char = -1;
}
static void
-x_init_prompt(void)
+x_init_prompt(bool doprint)
{
- prompt_trunc = pprompt(prompt, 0);
+ prompt_trunc = pprompt(prompt, doprint ? 0 : -1);
pwidth = prompt_trunc % x_cols;
prompt_trunc -= pwidth;
if ((mksh_uari_t)pwidth > ((mksh_uari_t)x_cols - 3 - MIN_EDIT_SPACE)) {
/* force newline after prompt */
prompt_trunc = -1;
pwidth = 0;
- x_e_putc2('\n');
+ if (doprint)
+ x_e_putc2('\n');
}
}
x_histp = histptr + 1;
x_last_command = XFUNC_error;
- x_init_prompt();
+ x_init_prompt(true);
x_displen = (xx_cols = x_cols) - 2 - (x_col = pwidth);
x_adj_done = 0;
x_adj_ok = true;
static int
x_size2(char *cp, char **dcp)
{
- int c = *(unsigned char *)cp;
+ uint8_t c = *(unsigned char *)cp;
if (UTFMODE && (c > 0x7F))
return (utf_widthadj(cp, (const char **)dcp));
if (c == '\t')
/* Kludge, tabs are always four spaces. */
return (4);
- if (c < ' ' || c == 0x7f)
+ if (ISCTRL(c) && /* but not C1 */ c < 0x80)
/* control unsigned char */
return (2);
return (1);
}
static void
-x_zotc2(int c)
-{
- if (c == '\t') {
- /* Kludge, tabs are always four spaces. */
- x_e_puts(" ");
- } else if (c < ' ' || c == 0x7f) {
- x_e_putc2('^');
- x_e_putc2(UNCTRL(c));
- } else
- x_e_putc2(c);
-}
-
-static void
x_zotc3(char **cp)
{
unsigned char c = **(unsigned char **)cp;
/* Kludge, tabs are always four spaces. */
x_e_puts(" ");
(*cp)++;
- } else if (c < ' ' || c == 0x7f) {
+ } else if (ISCTRL(c) && /* but not C1 */ c < 0x80) {
x_e_putc2('^');
x_e_putc2(UNCTRL(c));
(*cp)++;
static int
x_end_of_text(int c MKSH_A_UNUSED)
{
- x_zotc2(edchars.eof);
+ char tmp = edchars.eof;
+ char *cp = &tmp;
+
+ x_zotc3(&cp);
x_putc('\r');
x_putc('\n');
x_flush();
/* XXX -- should handle \^ escape? */
if (*cp == '^') {
cp++;
+ /*XXX or ^^ escape? this is ugly. */
if (*cp >= '?')
/* includes '?'; ASCII */
*op++ = CTRL(*cp);
{
char *p = *buf;
- if (c < ' ' || c == 0x7f) {
+ if (ISCTRL(c)) {
*p++ = '^';
*p++ = UNCTRL(c);
} else
#if !MKSH_S_NOVI
/* +++ vi editing mode +++ */
-#define Ctrl(c) (c&0x1f)
-
struct edstate {
char *cbuf;
ssize_t winleft;
static void restore_cbuf(void);
static int putbuf(const char *, ssize_t, bool);
static void del_range(int, int);
-static int findch(int, int, bool, bool);
+static int findch(int, int, bool, bool) MKSH_A_PURE;
static int forwword(int);
static int backword(int);
static int endword(int);
static void refresh(int);
static int outofwin(void);
static void rewindow(void);
-static int newcol(int, int);
+static int newcol(unsigned char, int);
static void display(char *, char *, int);
static void ed_mov_opt(int, char *);
static int expand_word(int);
static int complete_word(int, int);
static int print_expansions(struct edstate *, int);
-#define char_len(c) ((c) < ' ' || (c) == 0x7F ? 2 : 1)
+#define char_len(c) ((ISCTRL((unsigned char)c) && \
+ /* but not C1 */ (unsigned char)c < 0x80) ? 2 : 1)
static void x_vi_zotc(int);
static void vi_error(void);
static void vi_macro_reset(void);
es = &ebuf;
undo = &undobuf;
- x_init_prompt();
+ x_init_prompt(true);
x_col = pwidth;
if (wbuf_len != x_cols - 3 && ((wbuf_len = x_cols - 3))) {
x_flush();
while (/* CONSTCOND */ 1) {
if (macro.p) {
- c = *macro.p++;
+ c = (unsigned char)*macro.p++;
/* end of current macro? */
if (!c) {
/* more macros left to finish? */
case VNORMAL:
if (insert != 0) {
- if (ch == Ctrl('v')) {
+ if (ch == CTRL('v')) {
state = VLIT;
ch = '^';
}
break;
case VXCH:
- if (ch == Ctrl('['))
+ if (ch == CTRL('['))
state = VNORMAL;
else {
curcmd[cmdlen++] = ch;
break;
case VSEARCH:
- if (ch == '\r' || ch == '\n' /*|| ch == Ctrl('[')*/ ) {
+ if (ch == '\r' || ch == '\n' /*|| ch == CTRL('[')*/ ) {
restore_cbuf();
/* Repeat last search? */
if (srchlen == 0) {
memcpy(srchpat, locpat, srchlen + 1);
}
state = VCMD;
- } else if (ch == edchars.erase || ch == Ctrl('h')) {
+ } else if (ch == edchars.erase || ch == CTRL('h')) {
if (srchlen != 0) {
srchlen--;
- es->linelen -= char_len((unsigned char)locpat[srchlen]);
+ es->linelen -= char_len(locpat[srchlen]);
es->cursor = es->linelen;
refresh(0);
return (0);
refresh(0);
return (0);
} else if (ch == edchars.werase) {
- int i, n = srchlen;
+ unsigned int i, n;
struct edstate new_es, *save_es;
- new_es.cursor = n;
+ new_es.cursor = srchlen;
new_es.cbuf = locpat;
save_es = es;
n = backword(1);
es = save_es;
- for (i = srchlen; --i >= n; )
- es->linelen -= char_len((unsigned char)locpat[i]);
- srchlen = n;
+ i = (unsigned)srchlen;
+ while (--i >= n)
+ es->linelen -= char_len(locpat[i]);
+ srchlen = (int)n;
es->cursor = es->linelen;
refresh(0);
return (0);
vi_error();
else {
locpat[srchlen++] = ch;
- if (ch < ' ' || ch == 0x7f) {
+ if (ISCTRL(ch) && /* but not C1 */ ch < 0x80) {
if ((size_t)es->linelen + 2 >
(size_t)es->cbufsize)
vi_error();
es->cbuf[es->linelen++] = '^';
- es->cbuf[es->linelen++] = ch ^ '@';
+ es->cbuf[es->linelen++] = UNCTRL(ch);
} else {
if (es->linelen >= es->cbufsize)
vi_error();
return (VXCH);
else if (ch == '.')
return (VREDO);
- else if (ch == Ctrl('v'))
+ else if (ch == CTRL('v'))
return (VVERSION);
else if (is_cmd(ch))
return (VCMD);
{
int tcursor;
- if (ch == edchars.erase || ch == Ctrl('h')) {
+ if (ch == edchars.erase || ch == CTRL('h')) {
if (insert == REPLACE) {
if (es->cursor == undo->cursor) {
vi_error();
* buffer (if user inserts & deletes char, ibuf gets trashed and
* we don't want to use it)
*/
- if (first_insert && ch != Ctrl('['))
+ if (first_insert && ch != CTRL('['))
saved_inslen = 0;
switch (ch) {
case '\0':
case '\n':
return (1);
- case Ctrl('['):
+ case CTRL('['):
expanded = NONE;
if (first_insert) {
first_insert = false;
return (redo_insert(lastac - 1));
/* { Begin nonstandard vi commands */
- case Ctrl('x'):
+ case CTRL('x'):
expand_word(0);
break;
- case Ctrl('f'):
+ case CTRL('f'):
complete_word(0, 0);
break;
- case Ctrl('e'):
+ case CTRL('e'):
print_expansions(es, 0);
break;
- case Ctrl('i'):
+ case CTRL('i'):
if (Flag(FVITABCOMPLETE)) {
complete_word(0, 0);
break;
}
switch (*cmd) {
- case Ctrl('l'):
- case Ctrl('r'):
+ case CTRL('l'):
+ case CTRL('r'):
redraw_line(true);
break;
case 'j':
case '+':
- case Ctrl('n'):
+ case CTRL('n'):
if (grabhist(modified, hnum + argcnt) < 0)
return (-1);
else {
case 'k':
case '-':
- case Ctrl('p'):
+ case CTRL('p'):
if (grabhist(modified, hnum - argcnt) < 0)
return (-1);
else {
/* AT&T ksh */
case '=':
/* Nonstandard vi/ksh */
- case Ctrl('e'):
+ case CTRL('e'):
print_expansions(es, 1);
break;
/* Nonstandard vi/ksh */
- case Ctrl('i'):
+ case CTRL('i'):
if (!Flag(FVITABCOMPLETE))
return (-1);
complete_word(1, argcnt);
break;
/* some annoying AT&T kshs */
- case Ctrl('['):
+ case CTRL('['):
if (!Flag(FVIESCCOMPLETE))
return (-1);
/* AT&T ksh */
case '\\':
/* Nonstandard vi/ksh */
- case Ctrl('f'):
+ case CTRL('f'):
complete_word(1, argcnt);
break;
/* AT&T ksh */
case '*':
/* Nonstandard vi/ksh */
- case Ctrl('x'):
+ case CTRL('x'):
expand_word(1);
break;
break;
case 'h':
- case Ctrl('h'):
+ case CTRL('h'):
if (!sub && es->cursor == 0)
return (-1);
ncursor = es->cursor - argcnt;
{
char *hptr;
int hist;
- int anchored;
+ bool anchored;
if ((start == 0 && fwd == 0) || (start >= hlast - 1 && fwd == 1))
return (-1);
start++;
else
start--;
- anchored = *pat == '^' ? (++pat, 1) : 0;
+ anchored = *pat == '^' ? (++pat, true) : false;
if ((hist = findhist(start, fwd, pat, anchored)) < 0) {
/* (start != 0 && fwd && match(holdbufp, pat) >= 0) */
if (start != 0 && fwd && strcmp(holdbufp, pat) >= 0) {
}
static int
-newcol(int ch, int col)
+newcol(unsigned char ch, int col)
{
if (ch == '\t')
return ((col | 7) + 1);
*twb1++ = ' ';
} while (++col < winwidth && (col & 7) != 0);
else if (col < winwidth) {
- if (ch < ' ' || ch == 0x7f) {
+ if (ISCTRL(ch) && /* but not C1 */ ch < 0x80) {
*twb1++ = '^';
if (++col < winwidth) {
- *twb1++ = ch ^ '@';
+ *twb1++ = UNCTRL(ch);
col++;
}
} else {
static void
x_vi_zotc(int c)
{
- if (c < ' ' || c == 0x7f) {
+ if (ISCTRL(c)) {
x_putc('^');
- c ^= '@';
+ c = UNCTRL(c);
}
x_putc(c);
}
-/* $OpenBSD: eval.c,v 1.39 2013/07/01 17:25:27 jca Exp $ */
+/* $OpenBSD: eval.c,v 1.40 2013/09/14 20:09:30 millert Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.142 2013/07/24 18:03:57 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.150 2014/06/09 11:16:07 tg Exp $");
/*
* string expansion
static char *homedir(char *);
#endif
static void alt_expand(XPtrV *, char *, char *, char *, int);
-static int utflen(const char *);
+static int utflen(const char *) MKSH_A_PURE;
static void utfincptr(const char *, mksh_ari_t *);
/* UTFMODE functions */
}
continue;
case EXPRSUB:
- word = IFS_WORD;
tilde_ok = 0;
if (f & DONTRUNCOMMAND) {
+ word = IFS_WORD;
*dp++ = '$'; *dp++ = '('; *dp++ = '(';
while (*sp != '\0') {
Xcheck(ds, dp);
v_evaluate(&v, substitute(sp, 0),
KSH_UNWIND_ERROR, true);
sp = strnul(sp) + 1;
- cp = str_val(&v);
- while (*cp) {
- Xcheck(ds, dp);
- *dp++ = *cp++;
- }
+ x.str = str_val(&v);
+ type = XSUB;
+ if (f & DOBLANK)
+ doblank++;
}
continue;
case OSUBST: {
if (stype)
sp += slen;
switch (stype & 0x17F) {
- case 0x100 | '#': {
- char *beg, *end;
- mksh_ari_t seed;
- register uint32_t h;
-
- beg = wdcopy(sp, ATEMP);
- end = beg + (wdscan(sp, CSUBST) - sp);
- end[-2] = EOS;
- end = wdstrip(beg, 0);
- afree(beg, ATEMP);
- evaluate(substitute(end, 0),
- &seed, KSH_UNWIND_ERROR, true);
- /* hash with seed, for now */
- h = seed;
- NZATUpdateString(h,
- str_val(st->var));
- NZAATFinish(h);
+ case 0x100 | '#':
x.str = shf_smprintf("%08X",
- (unsigned int)h);
+ (unsigned int)hash(str_val(st->var)));
break;
- }
case 0x100 | 'Q': {
struct shf shf;
*dp = '\0';
quote = st->quotep;
f = st->f;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank--;
switch (st->stype & 0x17F) {
case '#':
*/
x.str = trimsub(str_val(st->var),
dp, st->stype);
- if (x.str[0] != '\0' || st->quotep)
+ if (x.str[0] != '\0') {
+ word = IFS_WS;
type = XSUB;
- else
- type = XNULLSUB;
- if (f&DOBLANK)
+ } else
+ type = quote ? XSUB : XNULLSUB;
+ if (f & DOBLANK)
doblank++;
st = st->prev;
continue;
dp, len), KSH_UNWIND_ERROR);
x.str = str_val(st->var);
type = XSUB;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank++;
st = st->prev;
continue;
case 0x100 | 'Q':
dp = Xrestpos(ds, dp, st->base);
type = XSUB;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank++;
st = st->prev;
continue;
* other stuff inside the quotes).
*/
type = XBASE;
- if (f&DOBLANK) {
+ if (f & DOBLANK) {
doblank--;
/*
- * not really correct: x=; "$x$@" should
- * generate a null argument and
- * set A; "${@:+}" shouldn't.
+ * XXX not really correct:
+ * x=; "$x$@"
+ * should generate a null argument and
+ * set A; "${@:+}"
+ * shouldn't.
*/
if (dp == Xstring(ds, dp))
word = IFS_WS;
case XSUBMID:
if ((c = *x.str++) == 0) {
type = XBASE;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank--;
continue;
}
word = IFS_WORD;
if ((x.str = *x.u.strv++) == NULL) {
type = XBASE;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank--;
continue;
}
if (x.split)
subst_exstat = waitlast();
type = XBASE;
- if (f&DOBLANK)
+ if (f & DOBLANK)
doblank--;
continue;
}
if (*sp == '!' && sp[1]) {
++sp;
xp->var = global(sp);
- if (vstrchr(sp, '[')) {
- if (xp->var->flag & ISSET)
- xp->str = shf_smprintf("%lu",
- arrayindex(xp->var));
- else
- xp->str = null;
- } else if (xp->var->flag & ISSET)
- xp->str = xp->var->name;
+ if (vstrchr(sp, '['))
+ xp->str = shf_smprintf("%s[%lu]",
+ xp->var->name,
+ arrayindex(xp->var));
else
- /* ksh93 compat */
- xp->str = "0";
+ xp->str = xp->var->name;
} else {
xp->var = global(sp);
xp->str = str_val(xp->var);
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.125 2013/07/21 20:44:44 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.132 2014/06/24 18:38:31 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
if (vp_pipest->flag & INT_L) {
unset(vp_pipest, 1);
vp_pipest->flag = DEFINED | ISSET | INTEGER | RDONLY |
- ARRAY | INT_U;
+ ARRAY | INT_U | INT_L;
vp_pipest->val.i = rv;
}
/* go on, use the builtin */
break;
#endif
-#if !defined(MKSH_SMALL)
} else if (tp->val.f == c_trap) {
t->u.evalflags &= ~DOTCOMEXEC;
break;
-#endif
} else
break;
tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC));
}
-#if !defined(MKSH_SMALL)
if (t->u.evalflags & DOTCOMEXEC)
flags |= XEXEC;
-#endif
l_expand = e->loc;
if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN))))
type_flags = 0;
/* but assign in there as usual */
typeset(cp, type_flags, 0, 0, 0);
if (bourne_function_call && !(type_flags & EXPORT))
- typeset(cp, LOCAL|LOCAL_COPY|EXPORT, 0, 0, 0);
+ typeset(cp, LOCAL | LOCAL_COPY | EXPORT, 0, 0, 0);
}
if (Flag(FXTRACE)) {
/* set $_ to programme's full path */
/* setstr() can't fail here */
- setstr(typeset("_", LOCAL|EXPORT, 0, INTEGER, 0),
+ setstr(typeset("_", LOCAL | EXPORT, 0, INTEGER, 0),
tp->val.s, KSH_RETURN_ERROR);
if (flags&XEXEC) {
*tp->args-- = tp->str;
#ifndef MKSH_SMALL
- if ((fd = open(tp->str, O_RDONLY)) >= 0) {
+ if ((fd = open(tp->str, O_RDONLY | O_BINARY)) >= 0) {
/* read first MAXINTERP octets from file */
if (read(fd, buf, sizeof(buf)) <= 0)
/* read error -> no good */
fd = (char *)cp - buf; /* either 0 or (if BOM) 3 */
/* scan for newline (or CR) or NUL _before_ end of buffer */
- while ((char *)cp < (buf + sizeof(buf)))
+ while ((size_t)((char *)cp - buf) < sizeof(buf))
if (*cp == '\0' || *cp == '\n' || *cp == '\r') {
*cp = '\0';
break;
} else
++cp;
/* if the shebang line is longer than MAXINTERP, bail out */
- if ((char *)cp >= (buf + sizeof(buf)))
+ if ((size_t)((char *)cp - buf) >= sizeof(buf))
goto noshebang;
/* restore begin of shebang position (buf+0 or buf+3) */
*tp->args-- = (char *)cp;
}
noshebang:
+ if (buf[0] == 0x7F && buf[1] == 'E' && buf[2] == 'L' &&
+ buf[3] == 'F')
+ errorf("%s: not executable: %d-bit ELF file", tp->str,
+ 32 * ((uint8_t)buf[4]));
fd = buf[0] << 8 | buf[1];
if ((fd == /* OMAGIC */ 0407) ||
(fd == /* NMAGIC */ 0410) ||
(fd == /* ECOFF_I386 */ 0x4C01) ||
(fd == /* ECOFF_M68K */ 0x0150 || fd == 0x5001) ||
(fd == /* ECOFF_SH */ 0x0500 || fd == 0x0005) ||
- (fd == 0x7F45 && buf[2] == 'L' && buf[3] == 'F') ||
(fd == /* "MZ" */ 0x4D5A) ||
(fd == /* gzip */ 0x1F8B))
errorf("%s: not executable: magic %04X", tp->str, fd);
warningf(true, "%s: %s", cp, "restricted");
return (-1);
}
- u = open(cp, flags, 0666);
+ u = open(cp, flags | O_BINARY, 0666);
}
if (u < 0) {
/* herein() may already have printed message */
* so temp doesn't get removed too soon).
*/
h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
- if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY, 0)) < 0) {
+ if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY | O_BINARY, 0)) < 0) {
i = errno;
warningf(true, "can't %s temporary file %s: %s",
!shf ? "create" : "open", h->tffn, cstrerror(i));
dbteste_isa(Test_env *te, Test_meta meta)
{
Test_op ret = TO_NONOP;
- int uqword;
+ bool uqword;
const char *p;
if (!*te->pos.wp)
-/* $OpenBSD: expr.c,v 1.22 2013/03/28 08:39:28 nicm Exp $ */
+/* $OpenBSD: expr.c,v 1.23 2013/12/17 16:37:06 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.72 2013/07/21 18:38:56 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.76 2014/06/24 19:53:19 tg Exp $");
/* the order of these enums is constrained by the order of opinfo[] */
enum token {
return (rv);
}
-#ifndef MKSH_mirbsd_wcwidth
-/* From: X11/xc/programs/xterm/wcwidth.c,v 1.6 2013/05/31 23:27:09 tg Exp $ */
+/* From: X11/xc/programs/xterm/wcwidth.c,v 1.8 2014/06/24 19:53:53 tg Exp $ */
struct mb_ucsrange {
unsigned short beg;
};
static int mb_ucsbsearch(const struct mb_ucsrange arr[], size_t elems,
- unsigned int val);
+ unsigned int val) MKSH_A_PURE;
/*
- * Generated by MirOS: contrib/code/Snippets/eawparse,v 1.1 2013/05/31 23:27:16 tg Exp $
- * from Unicode 6.2.0
+ * Generated by MirOS: contrib/code/Snippets/eawparse,v 1.2 2013/11/30 13:45:17 tg Exp $
+ * from the Unicode Character Database, Version 7.0.0
*/
static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0x05C1, 0x05C2 },
{ 0x05C4, 0x05C5 },
{ 0x05C7, 0x05C7 },
- { 0x0600, 0x0604 },
+ { 0x0600, 0x0605 },
{ 0x0610, 0x061A },
+ { 0x061C, 0x061C },
{ 0x064B, 0x065F },
{ 0x0670, 0x0670 },
{ 0x06D6, 0x06DD },
{ 0x0825, 0x0827 },
{ 0x0829, 0x082D },
{ 0x0859, 0x085B },
- { 0x08E4, 0x08FE },
- { 0x0900, 0x0902 },
+ { 0x08E4, 0x0902 },
{ 0x093A, 0x093A },
{ 0x093C, 0x093C },
{ 0x0941, 0x0948 },
{ 0x0B82, 0x0B82 },
{ 0x0BC0, 0x0BC0 },
{ 0x0BCD, 0x0BCD },
+ { 0x0C00, 0x0C00 },
{ 0x0C3E, 0x0C40 },
{ 0x0C46, 0x0C48 },
{ 0x0C4A, 0x0C4D },
{ 0x0C55, 0x0C56 },
{ 0x0C62, 0x0C63 },
+ { 0x0C81, 0x0C81 },
{ 0x0CBC, 0x0CBC },
{ 0x0CBF, 0x0CBF },
{ 0x0CC6, 0x0CC6 },
{ 0x0CCC, 0x0CCD },
{ 0x0CE2, 0x0CE3 },
+ { 0x0D01, 0x0D01 },
{ 0x0D41, 0x0D44 },
{ 0x0D4D, 0x0D4D },
{ 0x0D62, 0x0D63 },
{ 0x17C6, 0x17C6 },
{ 0x17C9, 0x17D3 },
{ 0x17DD, 0x17DD },
- { 0x180B, 0x180D },
+ { 0x180B, 0x180E },
{ 0x18A9, 0x18A9 },
{ 0x1920, 0x1922 },
{ 0x1927, 0x1928 },
{ 0x1932, 0x1932 },
{ 0x1939, 0x193B },
{ 0x1A17, 0x1A18 },
+ { 0x1A1B, 0x1A1B },
{ 0x1A56, 0x1A56 },
{ 0x1A58, 0x1A5E },
{ 0x1A60, 0x1A60 },
{ 0x1A65, 0x1A6C },
{ 0x1A73, 0x1A7C },
{ 0x1A7F, 0x1A7F },
+ { 0x1AB0, 0x1ABE },
{ 0x1B00, 0x1B03 },
{ 0x1B34, 0x1B34 },
{ 0x1B36, 0x1B3A },
{ 0x1B80, 0x1B81 },
{ 0x1BA2, 0x1BA5 },
{ 0x1BA8, 0x1BA9 },
- { 0x1BAB, 0x1BAB },
+ { 0x1BAB, 0x1BAD },
{ 0x1BE6, 0x1BE6 },
{ 0x1BE8, 0x1BE9 },
{ 0x1BED, 0x1BED },
{ 0x1CE2, 0x1CE8 },
{ 0x1CED, 0x1CED },
{ 0x1CF4, 0x1CF4 },
- { 0x1DC0, 0x1DE6 },
+ { 0x1CF8, 0x1CF9 },
+ { 0x1DC0, 0x1DF5 },
{ 0x1DFC, 0x1DFF },
{ 0x200B, 0x200F },
{ 0x202A, 0x202E },
{ 0x2060, 0x2064 },
- { 0x206A, 0x206F },
+ { 0x2066, 0x206F },
{ 0x20D0, 0x20F0 },
{ 0x2CEF, 0x2CF1 },
{ 0x2D7F, 0x2D7F },
{ 0xA9B3, 0xA9B3 },
{ 0xA9B6, 0xA9B9 },
{ 0xA9BC, 0xA9BC },
+ { 0xA9E5, 0xA9E5 },
{ 0xAA29, 0xAA2E },
{ 0xAA31, 0xAA32 },
{ 0xAA35, 0xAA36 },
{ 0xAA43, 0xAA43 },
{ 0xAA4C, 0xAA4C },
+ { 0xAA7C, 0xAA7C },
{ 0xAAB0, 0xAAB0 },
{ 0xAAB2, 0xAAB4 },
{ 0xAAB7, 0xAAB8 },
{ 0xABED, 0xABED },
{ 0xFB1E, 0xFB1E },
{ 0xFE00, 0xFE0F },
- { 0xFE20, 0xFE26 },
+ { 0xFE20, 0xFE2D },
{ 0xFEFF, 0xFEFF },
{ 0xFFF9, 0xFFFB }
};
return (2);
return (1);
}
-#endif
-/* $OpenBSD: c_ksh.c,v 1.33 2009/02/07 14:03:24 kili Exp $ */
-/* $OpenBSD: c_sh.c,v 1.43 2013/04/19 17:39:45 deraadt Exp $ */
+/* $OpenBSD: c_ksh.c,v 1.34 2013/12/17 16:37:05 deraadt Exp $ */
+/* $OpenBSD: c_sh.c,v 1.44 2013/09/04 15:49:18 millert Exp $ */
/* $OpenBSD: c_test.c,v 1.18 2009/03/01 20:11:06 otto Exp $ */
-/* $OpenBSD: c_ulimit.c,v 1.17 2008/03/21 12:51:19 millert Exp $ */
+/* $OpenBSD: c_ulimit.c,v 1.19 2013/11/28 10:33:37 sobrado Exp $ */
/*-
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- * 2010, 2011, 2012, 2013
+ * 2010, 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#endif
#endif
-__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.244 2013/06/03 22:28:32 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.256 2014/06/09 13:25:52 tg Exp $");
#if HAVE_KILLPG
/*
#define c_ulimit c_true
#endif
+#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
+static int c_suspend(const char **);
+#endif
+
/* getn() that prints error */
static int
bi_getn(const char *as, int *ai)
{"*=return", c_exitreturn},
{Tsgset, c_set},
{"*=shift", c_shift},
+#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
+ {"suspend", c_suspend},
+#endif
{"test", c_test},
{"*=times", c_times},
{"*=trap", c_trap},
const char *opts;
const char *fieldstr = NULL, *basestr = NULL;
bool localv = false, func = false, pflag = false, istset = true;
+ enum namerefflag new_refflag = SRF_NOP;
switch (**wp) {
flag = LCASEV;
break;
case 'n':
- set_refflag = (builtin_opt.info & GI_PLUS) ?
+ new_refflag = (builtin_opt.info & GI_PLUS) ?
SRF_DISABLE : SRF_ENABLE;
break;
/* export, readonly: POSIX -p flag */
flag = EXPORT;
break;
case '?':
- errout:
- set_refflag = SRF_NOP;
return (1);
}
if (builtin_opt.info & GI_PLUS) {
}
if (fieldstr && !bi_getn(fieldstr, &field))
- goto errout;
+ return (1);
if (basestr && (!bi_getn(basestr, &base) || base < 1 || base > 36)) {
bi_errorf("%s: %s", "bad integer base", basestr);
- goto errout;
+ return (1);
}
if (!(builtin_opt.info & GI_MINUSMINUS) && wp[builtin_opt.optind] &&
}
if (func && (((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT)) ||
- set_refflag != SRF_NOP)) {
+ new_refflag != SRF_NOP)) {
bi_errorf("only -t, -u and -x options may be used with -f");
- goto errout;
+ return (1);
}
if (wp[builtin_opt.optind]) {
/*
* are also set in this command
*/
if ((fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL | LCASEV |
- INTEGER | INT_U | INT_L)) || set_refflag != SRF_NOP)
+ INTEGER | INT_U | INT_L)) || new_refflag != SRF_NOP)
fclr |= ~fset & (LJUST | RJUST | ZEROFIL | UCASEV_AL |
LCASEV | INTEGER | INT_U | INT_L);
}
+ if (new_refflag != SRF_NOP) {
+ fclr &= ~(ARRAY | ASSOC);
+ fset &= ~(ARRAY | ASSOC);
+ fclr |= EXPORT;
+ fset |= ASSOC;
+ if (new_refflag == SRF_DISABLE)
+ fclr |= ASSOC;
+ }
/* set variables and attributes */
if (wp[builtin_opt.optind] &&
}
} else if (!typeset(wp[i], fset, fclr, field, base)) {
bi_errorf("%s: %s", wp[i], "is not an identifier");
- goto errout;
+ return (1);
}
}
- set_refflag = SRF_NOP;
return (rv);
}
- set_refflag = SRF_NOP;
/* list variables and attributes */
/* no difference at this point.. */
for (; wp[i]; i++) {
if (!bi_getn(wp[i], &n))
return (1);
+#if (NSIG < 128)
if (n > 128 && n < 128 + NSIG)
n -= 128;
+#endif
if (n > 0 && n < NSIG)
shprintf("%s\n", sigtraps[n].name);
else
#define SOFT 0x1
#define HARD 0x2
-struct limits {
- const char *name;
- int resource; /* resource to get/set */
- unsigned int factor; /* multiply by to get rlim_{cur,max} values */
- char option;
-};
-
-static void print_ulimit(const struct limits *, int);
-static int set_ulimit(const struct limits *, const char *, int);
-
/* Magic to divine the 'm' and 'v' limits */
#ifdef RLIMIT_AS
#undef ULIMIT_M_IS_VMEM
#endif
+#if defined(ULIMIT_M_IS_RSS) && defined(ULIMIT_M_IS_VMEM)
+# error nonsensical m ulimit
+#endif
+
+#if defined(ULIMIT_V_IS_VMEM) && defined(ULIMIT_V_IS_AS)
+# error nonsensical v ulimit
+#endif
+
+#define RLIMITS_DEFNS
+#include "rlimits.gen"
+
+static void print_ulimit(const struct limits *, int);
+static int set_ulimit(const struct limits *, const char *, int);
+
+static const struct limits * const rlimits[] = {
+#define RLIMITS_ITEMS
+#include "rlimits.gen"
+};
+
+static const char rlimits_opts[] =
+#define RLIMITS_OPTCS
+#include "rlimits.gen"
+ ;
int
c_ulimit(const char **wp)
{
- static const struct limits limits[] = {
- /* do not use options -H, -S or -a or change the order */
-#ifdef RLIMIT_CPU
- { "time(cpu-seconds)", RLIMIT_CPU, 1, 't' },
-#endif
-#ifdef RLIMIT_FSIZE
- { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
-#endif
-#ifdef RLIMIT_CORE
- { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
-#endif
-#ifdef RLIMIT_DATA
- { "data(KiB)", RLIMIT_DATA, 1024, 'd' },
-#endif
-#ifdef RLIMIT_STACK
- { "stack(KiB)", RLIMIT_STACK, 1024, 's' },
-#endif
-#ifdef RLIMIT_MEMLOCK
- { "lockedmem(KiB)", RLIMIT_MEMLOCK, 1024, 'l' },
-#endif
-#ifdef RLIMIT_NOFILE
- { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
-#endif
-#ifdef RLIMIT_NPROC
- { "processes", RLIMIT_NPROC, 1, 'p' },
-#endif
-#ifdef RLIMIT_SWAP
- { "swap(KiB)", RLIMIT_SWAP, 1024, 'w' },
-#endif
-#ifdef RLIMIT_LOCKS
- { "flocks", RLIMIT_LOCKS, -1, 'L' },
-#endif
-#ifdef RLIMIT_TIME
- { "humantime(seconds)", RLIMIT_TIME, 1, 'T' },
-#endif
-#ifdef RLIMIT_NOVMON
- { "vnodemonitors", RLIMIT_NOVMON, 1, 'V' },
-#endif
-#ifdef RLIMIT_SIGPENDING
- { "sigpending", RLIMIT_SIGPENDING, 1, 'i' },
-#endif
-#ifdef RLIMIT_MSGQUEUE
- { "msgqueue(bytes)", RLIMIT_MSGQUEUE, 1, 'q' },
-#endif
-#ifdef RLIMIT_AIO_MEM
- { "AIOlockedmem(KiB)", RLIMIT_AIO_MEM, 1024, 'M' },
-#endif
-#ifdef RLIMIT_AIO_OPS
- { "AIOoperations", RLIMIT_AIO_OPS, 1, 'O' },
-#endif
-#ifdef RLIMIT_TCACHE
- { "cachedthreads", RLIMIT_TCACHE, 1, 'C' },
-#endif
-#ifdef RLIMIT_SBSIZE
- { "sockbufsiz(KiB)", RLIMIT_SBSIZE, 1024, 'B' },
-#endif
-#ifdef RLIMIT_PTHREAD
- { "threadsperprocess", RLIMIT_PTHREAD, 1, 'P' },
-#endif
-#ifdef RLIMIT_NICE
- { "maxnice", RLIMIT_NICE, 1, 'e' },
-#endif
-#ifdef RLIMIT_RTPRIO
- { "maxrtprio", RLIMIT_RTPRIO, 1, 'r' },
-#endif
-#if defined(ULIMIT_M_IS_RSS)
- { "resident-set(KiB)", RLIMIT_RSS, 1024, 'm' },
-#elif defined(ULIMIT_M_IS_VMEM)
- { "memory(KiB)", RLIMIT_VMEM, 1024, 'm' },
-#endif
-#if defined(ULIMIT_V_IS_VMEM)
- { "virtual-memory(KiB)", RLIMIT_VMEM, 1024, 'v' },
-#elif defined(ULIMIT_V_IS_AS)
- { "address-space(KiB)", RLIMIT_AS, 1024, 'v' },
-#endif
- { NULL, 0, 0, 0 }
- };
- static const char opts[] = "a"
-#ifdef RLIMIT_SBSIZE
- "B"
-#endif
-#ifdef RLIMIT_TCACHE
- "C"
-#endif
-#ifdef RLIMIT_CORE
- "c"
-#endif
-#ifdef RLIMIT_DATA
- "d"
-#endif
-#ifdef RLIMIT_NICE
- "e"
-#endif
-#ifdef RLIMIT_FSIZE
- "f"
-#endif
- "H"
-#ifdef RLIMIT_SIGPENDING
- "i"
-#endif
-#ifdef RLIMIT_LOCKS
- "L"
-#endif
-#ifdef RLIMIT_MEMLOCK
- "l"
-#endif
-#ifdef RLIMIT_AIO_MEM
- "M"
-#endif
-#if defined(ULIMIT_M_IS_RSS) || defined(ULIMIT_M_IS_VMEM)
- "m"
-#endif
-#ifdef RLIMIT_NOFILE
- "n"
-#endif
-#ifdef RLIMIT_AIO_OPS
- "O"
-#endif
-#ifdef RLIMIT_PTHREAD
- "P"
-#endif
-#ifdef RLIMIT_NPROC
- "p"
-#endif
-#ifdef RLIMIT_MSGQUEUE
- "q"
-#endif
-#ifdef RLIMIT_RTPRIO
- "r"
-#endif
- "S"
-#ifdef RLIMIT_STACK
- "s"
-#endif
-#ifdef RLIMIT_TIME
- "T"
-#endif
-#ifdef RLIMIT_CPU
- "t"
-#endif
-#ifdef RLIMIT_NOVMON
- "V"
-#endif
-#if defined(ULIMIT_V_IS_VMEM) || defined(ULIMIT_V_IS_AS)
- "v"
-#endif
-#ifdef RLIMIT_SWAP
- "w"
-#endif
- ;
+ size_t i = 0;
int how = SOFT | HARD, optc, what = 'f';
bool all = false;
- const struct limits *l;
- while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
+ while ((optc = ksh_getopt(wp, &builtin_opt, rlimits_opts)) != -1)
switch (optc) {
case 'H':
how = HARD;
all = true;
break;
case '?':
- bi_errorf("usage: ulimit [-%s] [value]", opts);
+ bi_errorf("usage: ulimit [-%s] [value]", rlimits_opts);
return (1);
default:
what = optc;
}
- for (l = limits; l->name && l->option != what; l++)
- ;
- if (!l->name) {
- internal_warningf("ulimit: %c", what);
- return (1);
+ while (i < NELEM(rlimits)) {
+ if (rlimits[i]->optchar == what)
+ goto found;
+ ++i;
}
-
+ internal_warningf("ulimit: %c", what);
+ return (1);
+ found:
if (wp[builtin_opt.optind]) {
if (all || wp[builtin_opt.optind + 1]) {
bi_errorf("too many arguments");
return (1);
}
- return (set_ulimit(l, wp[builtin_opt.optind], how));
+ return (set_ulimit(rlimits[i], wp[builtin_opt.optind], how));
}
if (!all)
- print_ulimit(l, how);
- else for (l = limits; l->name; l++) {
- shprintf("%-20s ", l->name);
- print_ulimit(l, how);
+ print_ulimit(rlimits[i], how);
+ else for (i = 0; i < NELEM(rlimits); ++i) {
+ shprintf("%-20s ", rlimits[i]->name);
+ print_ulimit(rlimits[i], how);
}
return (0);
}
}
if (getrlimit(l->resource, &limit) < 0) {
- /* some can't be read, e.g. Linux RLIMIT_LOCKS */
+#ifndef MKSH_SMALL
+ bi_errorf("limit %s could not be read, contact the mksh developers: %s",
+ l->name, cstrerror(errno));
+#endif
+ /* some can't be read */
limit.rlim_cur = RLIM_INFINITY;
limit.rlim_max = RLIM_INFINITY;
}
fn = *wp++;
if (fn[0] == '-' && fn[1] == '\0')
fd = STDIN_FILENO;
- else if ((fd = open(fn, O_RDONLY)) < 0) {
+ else if ((fd = open(fn, O_RDONLY | O_BINARY)) < 0) {
eno = errno;
bi_errorf("%s: %s", fn, cstrerror(eno));
rv = 1;
break;
while (n) {
w = write(STDOUT_FILENO, cp, n);
- eno = errno;
- /* give the user a chance to ^C out */
- intrcheck();
if (w == -1) {
- if (eno == EINTR)
+ if (errno == EINTR)
/* interrupted, try again */
continue;
/* an error occured during writing */
+ eno = errno;
bi_errorf("%s: %s", "<stdout>",
cstrerror(eno));
rv = 1;
return (rv);
}
#endif
+
+#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
+static int
+c_suspend(const char **wp)
+{
+ if (wp[1] != NULL) {
+ bi_errorf("too many arguments");
+ return (1);
+ }
+ if (Flag(FLOGIN)) {
+ /* Can't suspend an orphaned process group. */
+ if (getpgid(kshppid) == getpgid(0) ||
+ getsid(kshppid) != getsid(0)) {
+ bi_errorf("can't suspend a login shell");
+ return (1);
+ }
+ }
+ j_suspend();
+ return (0);
+}
+#endif
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012
+ * 2011, 2012, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include <sys/file.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.131 2012/12/28 02:28:35 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134 2014/06/09 13:25:53 tg Exp $");
Trap sigtraps[NSIG + 1];
static struct sigaction Sigact_ign;
hp = NULL;
}
} else {
- int anchored = *str == '?' ? (++str, 0) : 1;
+ bool anchored = *str == '?' ? (++str, false) : true;
/* the -1 is to avoid the current fc command */
if ((n = findhist(histptr - history - 1, 0, str, anchored)) < 0)
* direction.
*/
int
-findhist(int start, int fwd, const char *str, int anchored)
+findhist(int start, int fwd, const char *str, bool anchored)
{
char **hp;
int maxhist = histptr - history;
retry:
/* we have a file and are interactive */
- if ((fd = open(hname, O_RDWR | O_CREAT | O_APPEND, 0600)) < 0)
+ if ((fd = open(hname, O_RDWR | O_CREAT | O_APPEND | O_BINARY,
+ 0600)) < 0)
return;
histfd = savefd(fd);
/* create temporary file */
nhname = shf_smprintf("%s.%d", hname, (int)procpid);
if ((fd = open(nhname, O_RDWR | O_CREAT | O_TRUNC |
- O_EXCL, 0600)) < 0) {
+ O_EXCL | O_BINARY, 0600)) < 0) {
/* just don't truncate then, meh. */
goto hist_trunc_dont;
}
trap_exstat = -1;
/* Populate sigtraps based on sys_signame and sys_siglist. */
+ /*XXX this is idiotic, use a multi-key/value hashtable! */
for (i = 0; i <= NSIG; i++) {
sigtraps[i].signal = i;
if (i == ksh_SIGERR) {
-/* $OpenBSD: jobs.c,v 1.39 2009/12/13 04:36:48 deraadt Exp $ */
+/* $OpenBSD: jobs.c,v 1.40 2013/09/04 15:49:18 millert Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
- * 2012, 2013
+ * 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.100 2013/07/26 20:33:23 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.104 2014/06/10 22:17:09 tg Exp $");
#if HAVE_KILLPG
#define mksh_killpg killpg
}
}
+#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
+/* suspend the shell */
+void
+j_suspend(void)
+{
+ struct sigaction sa, osa;
+
+ /* Restore tty and pgrp. */
+ if (ttypgrp_ok) {
+ if (tty_hasstate)
+ mksh_tcset(tty_fd, &tty_state);
+ if (restore_ttypgrp >= 0) {
+ if (tcsetpgrp(tty_fd, restore_ttypgrp) < 0) {
+ warningf(false, "%s: %s %s: %s", "j_suspend",
+ "tcsetpgrp", "failed", cstrerror(errno));
+ } else if (setpgid(0, restore_ttypgrp) < 0) {
+ warningf(false, "%s: %s %s: %s", "j_suspend",
+ "setpgid", "failed", cstrerror(errno));
+ }
+ }
+ }
+
+ /* Suspend the shell. */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = SIG_DFL;
+ sigaction(SIGTSTP, &sa, &osa);
+ kill(0, SIGTSTP);
+
+ /* Back from suspend, reset signals, pgrp and tty. */
+ sigaction(SIGTSTP, &osa, NULL);
+ if (ttypgrp_ok) {
+ if (restore_ttypgrp >= 0) {
+ if (setpgid(0, kshpid) < 0) {
+ warningf(false, "%s: %s %s: %s", "j_suspend",
+ "setpgid", "failed", cstrerror(errno));
+ ttypgrp_ok = false;
+ } else if (tcsetpgrp(tty_fd, kshpid) < 0) {
+ warningf(false, "%s: %s %s: %s", "j_suspend",
+ "tcsetpgrp", "failed", cstrerror(errno));
+ ttypgrp_ok = false;
+ }
+ }
+ tty_init_state();
+ }
+}
+#endif
+
/* job cleanup before shell exit */
void
j_exit(void)
rv = vp->val.i;
p = p->next;
}
+ } else if (Flag(FPIPEFAIL) && (j->proc_list != NULL)) {
+ Proc *p = j->proc_list;
+ int i;
+
+ while (p != NULL) {
+ if ((i = proc_errorlevel(p)))
+ rv = i;
+ p = p->next;
+ }
}
if (!(flags & JW_ASYNCNOTIFY)
getrusage(RUSAGE_CHILDREN, &ru0);
do {
#ifndef MKSH_NOPROSPECTOFWORK
- pid = waitpid(-1, &status, (WNOHANG|WUNTRACED));
+ pid = waitpid(-1, &status, (WNOHANG |
+#ifdef WCONTINUED
+ WCONTINUED |
+#endif
+ WUNTRACED));
#else
pid = wait(&status);
#endif
if (WIFSTOPPED(status))
p->state = PSTOPPED;
else
+#ifdef WIFCONTINUED
+ if (WIFCONTINUED(status)) {
+ p->state = j->state = PRUNNING;
+ /* skip check_job(), no-op in this case */
+ continue;
+ } else
+#endif
#endif
if (WIFSIGNALED(status))
p->state = PSIGNALLED;
-/* $OpenBSD: lex.c,v 1.47 2013/03/03 19:11:34 guenther Exp $ */
+/* $OpenBSD: lex.c,v 1.49 2013/12/17 16:37:06 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.188 2013/08/10 13:44:31 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.193 2014/06/29 11:28:28 tg Exp $");
/*
* states while lexing word
state = statep->type; \
} while (/* CONSTCOND */ 0)
-#define PUSH_SRETRACE() do { \
+#define PUSH_SRETRACE(s) do { \
struct sretrace_info *ri; \
\
+ PUSH_STATE(s); \
statep->ls_start = Xsavepos(ws, wp); \
ri = alloc(sizeof(struct sretrace_info), ATEMP); \
Xinit(ri->xs, ri->xp, 64, ATEMP); \
dp = (void *)retrace_info; \
retrace_info = retrace_info->next; \
afree(dp, ATEMP); \
+ POP_STATE(); \
} while (/* CONSTCOND */ 0)
/**
c = getsc();
if (c == '(') /*)*/ {
*wp++ = EXPRSUB;
- PUSH_STATE(SASPAREN);
+ PUSH_SRETRACE(SASPAREN);
statep->nparen = 2;
- PUSH_SRETRACE();
*retrace_info->xp++ = '(';
} else {
ungetsc(c);
if (statep->nparen == 1) {
/* end of EXPRSUB */
POP_SRETRACE();
- POP_STATE();
if ((c2 = getsc()) == /*(*/ ')') {
cz = strlen(sp) - 2;
} else if (c2 == '"') {
/* FALLTHROUGH */
case '"':
- state = statep->type = SHEREDQUOTE;
- PUSH_SRETRACE();
+ PUSH_SRETRACE(SHEREDQUOTE);
break;
}
ungetsc(c2);
alarm(0);
}
cp = Xstring(s->xs, xp);
+ rndpush(cp);
s->start = s->str = cp;
strip_nuls(Xstring(s->xs, xp), Xlength(s->xs, xp));
/* Note: if input is all nulls, this is not eof */
int
pprompt(const char *cp, int ntruncate)
{
- int columns = 0, lines = 0;
- bool indelimit = false;
char delimiter = 0;
+ bool doprint = (ntruncate != -1);
+ bool indelimit = false;
+ int columns = 0, lines = 0;
/*
* Undocumented AT&T ksh feature:
else if (UTFMODE && ((unsigned char)*cp > 0x7F)) {
const char *cp2;
columns += utf_widthadj(cp, &cp2);
- if (indelimit ||
- (ntruncate < (x_cols * lines + columns)))
+ if (doprint && (indelimit ||
+ (ntruncate < (x_cols * lines + columns))))
shf_write(cp, cp2 - cp, shl_out);
cp = cp2 - /* loop increment */ 1;
continue;
} else
columns++;
- if ((*cp != delimiter) &&
+ if (doprint && (*cp != delimiter) &&
(indelimit || (ntruncate < (x_cols * lines + columns))))
shf_putc(*cp, shl_out);
}
- shf_flush(shl_out);
+ if (doprint)
+ shf_flush(shl_out);
return (x_cols * lines + columns);
}
-/* $OpenBSD: main.c,v 1.52 2013/06/15 17:25:19 millert Exp $ */
+/* $OpenBSD: main.c,v 1.54 2013/11/28 10:33:37 sobrado Exp $ */
/* $OpenBSD: tty.c,v 1.9 2006/03/14 22:08:01 deraadt Exp $ */
-/* $OpenBSD: io.c,v 1.22 2006/03/17 16:30:13 millert Exp $ */
+/* $OpenBSD: io.c,v 1.23 2013/12/17 16:37:06 deraadt Exp $ */
/* $OpenBSD: table.c,v 1.15 2012/02/19 07:52:30 otto Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include <locale.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/main.c,v 1.269 2013/07/25 18:07:46 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/main.c,v 1.280 2014/06/09 12:28:17 tg Exp $");
extern char **environ;
static uint8_t isuc(const char *);
static int main_init(int, const char *[], Source **, struct block **);
-uint32_t chvt_rndsetup(const void *, size_t);
void chvt_reinit(void);
static void reclaim(void);
static void remove_temps(struct temp *);
/* not in Android for political reasons */
/* not in ARGE mksh due to no job control */
"stop=kill -STOP",
- "suspend=kill -STOP $$",
#endif
"autoload=typeset -fu",
"functions=typeset -f",
return ((mksh_uari_t)h);
}
-uint32_t
-chvt_rndsetup(const void *bp, size_t sz)
-{
- register uint32_t h;
-
- NZATInit(h);
- /* variation through pid, ppid, and the works */
- NZATUpdateMem(h, &rndsetupstate, sizeof(rndsetupstate));
- /* some variation, some possibly entropy, depending on OE */
- NZATUpdateMem(h, bp, sz);
- NZAATFinish(h);
-
- return (h);
-}
-
void
chvt_reinit(void)
{
if (!*ccp)
ccp = empty_argv[0];
+ /*
+ * Turn on nohup by default. (AT&T ksh does not have a nohup
+ * option - it always sends the hup).
+ */
+ Flag(FNOHUP) = 1;
+
+ /*
+ * Turn on brace expansion by default. AT&T kshs that have
+ * alternation always have it on.
+ */
+ Flag(FBRACEEXPAND) = 1;
+
+ /*
+ * Turn on "set -x" inheritance by default.
+ */
+ Flag(FXTRACEREC) = 1;
+
/* define built-in commands and see if we were called as one */
ktinit(APERM, &builtins,
/* currently up to 51 builtins: 75% of 128 = 2^7 */
/* setstr can't fail here */
setstr(vp, def_path, KSH_RETURN_ERROR);
- /*
- * Turn on nohup by default for now - will change to off
- * by default once people are aware of its existence
- * (AT&T ksh does not have a nohup option - it always sends
- * the hup).
- */
- Flag(FNOHUP) = 1;
-
- /*
- * Turn on brace expansion by default. AT&T kshs that have
- * alternation always have it on.
- */
- Flag(FBRACEEXPAND) = 1;
-
- /*
- * Turn on "set -x" inheritance by default.
- */
- Flag(FXTRACEREC) = 1;
-
#ifndef MKSH_NO_CMDLINE_EDITING
/*
* Set edit mode to emacs by default, may be overridden
#endif
/* import environment */
- if (environ != NULL)
- for (wp = (const char **)environ; *wp != NULL; wp++)
+ if (environ != NULL) {
+ wp = (const char **)environ;
+ while (*wp != NULL) {
+ rndpush(*wp);
typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
+ ++wp;
+ }
+ }
/* for security */
typeset(initifs, 0, 0, 0, 0);
setint_n((vp_pipest = global("PIPESTATUS")), 0, 10);
/* Set this before parsing arguments */
- Flag(FPRIVILEGED) = kshuid != ksheuid || kshgid != kshegid;
+ Flag(FPRIVILEGED) = (kshuid != ksheuid || kshgid != kshegid) ? 2 : 0;
/* this to note if monitor is set on command line (see below) */
#ifndef MKSH_UNEMPLOYED
return (1);
}
-#if defined(DEBUG) && !defined(MKSH_LEGACY_MODE)
- /* test wraparound of arithmetic types */
- {
- volatile long xl;
- volatile unsigned long xul;
- volatile int xi;
- volatile unsigned int xui;
- volatile mksh_ari_t xa;
- volatile mksh_uari_t xua, xua2;
- volatile uint8_t xc;
-
- xa = 2147483647;
- xua = 2147483647;
- ++xa;
- ++xua;
- xua2 = xa;
- xl = xa;
- xul = xua;
- xa = 0;
- xua = 0;
- --xa;
- --xua;
- xi = xa;
- xui = xua;
- xa = -1;
- xua = xa;
- ++xa;
- ++xua;
- xc = 0;
- --xc;
- if ((xua2 != 2147483648UL) ||
- (xl != (-2147483647L-1)) || (xul != 2147483648UL) ||
- (xi != -1) || (xui != 4294967295U) ||
- (xa != 0) || (xua != 0) || (xc != 255))
- errorf("integer wraparound test failed");
- }
-#endif
-
/* process this later only, default to off (hysterical raisins) */
utf_flag = UTFMODE;
UTFMODE = 0;
s = pushs(SSTRINGCMDLINE, ATEMP);
if (!(s->start = s->str = argv[argi++]))
errorf("%s %s", "-c", "requires an argument");
-#if !defined(MKSH_SMALL)
while (*s->str) {
if (*s->str != ' ' && ctype(*s->str, C_QUOTE))
break;
if (!*s->str)
s->flags |= SF_MAYEXEC;
s->str = s->start;
-#endif
#ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
/* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */
if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--"))
#ifndef MKSH_ASSUME_UTF8
/* auto-detect from locale or environment */
utf_flag = 4;
-#elif MKSH_ASSUME_UTF8
+#else /* this may not be an #elif */
+#if MKSH_ASSUME_UTF8
utf_flag = 1;
#else
/* always disable UTF-8 (for interactive) */
utf_flag = 0;
#endif
+#endif
}
#ifndef MKSH_NO_CMDLINE_EDITING
x_init();
if (!current_wd[0] && Flag(FTALKING))
warningf(false, "can't determine current directory");
- if (Flag(FLOGIN)) {
+ if (Flag(FLOGIN))
include(MKSH_SYSTEM_PROFILE, 0, NULL, true);
- if (!Flag(FPRIVILEGED))
- include(substitute("$HOME/.profile", 0), 0,
- NULL, true);
- }
- if (Flag(FPRIVILEGED))
+ if (!Flag(FPRIVILEGED)) {
+ if (Flag(FLOGIN))
+ include(substitute("$HOME/.profile", 0), 0, NULL, true);
+ if (Flag(FTALKING)) {
+ cp = substitute(substitute("${ENV:-" MKSHRC_PATH "}",
+ 0), DOTILDE);
+ if (cp[0] != '\0')
+ include(cp, 0, NULL, true);
+ }
+ } else {
include(MKSH_SUID_PROFILE, 0, NULL, true);
- else if (Flag(FTALKING)) {
- char *env_file;
-
- /* include $ENV */
- env_file = substitute(substitute("${ENV:-" MKSHRC_PATH "}", 0),
- DOTILDE);
- if (*env_file != '\0')
- include(env_file, 0, NULL, true);
+ /* turn off -p if not set explicitly */
+ if (Flag(FPRIVILEGED) != 1)
+ change_flag(FPRIVILEGED, OF_INTERNAL, false);
}
if (restricted) {
unwind(LEXIT);
break;
}
- }
-#if !defined(MKSH_SMALL)
- else if ((s->flags & SF_MAYEXEC) && t->type == TCOM)
+ } else if ((s->flags & SF_MAYEXEC) && t->type == TCOM)
t->u.evalflags |= DOTCOMEXEC;
-#endif
if (!Flag(FNOEXEC) || (s->flags & SF_TTY))
exstat = execute(t, 0, NULL) & 0xFF;
} while (len < 5);
/* cyclically attempt to open a temporary file */
- while ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR, 0600)) < 0) {
+ while ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR | O_BINARY,
+ 0600)) < 0) {
if (errno != EEXIST)
goto maketemp_out;
/* count down from z to a then from 9 to 0 */
cb = *ocb;
if (forread) {
+ cb.c_iflag &= ~(ISTRIP);
cb.c_lflag &= ~(ICANON) | ECHO;
} else {
- cb.c_iflag &= ~(INLCR | ICRNL);
+ cb.c_iflag &= ~(INLCR | ICRNL | ISTRIP);
cb.c_lflag &= ~(ISIG | ICANON | ECHO);
}
#if defined(VLNEXT) && defined(_POSIX_VDISABLE)
--- /dev/null
+/*-
+ * Copyright © 2011, 2014
+ * Thorsten Glaser <tg@mirbsd.org>
+ *
+ * Provided that these terms and disclaimer and all copyright notices
+ * are retained or reproduced in an accompanying document, permission
+ * is granted to deal in this work without restriction, including un‐
+ * limited rights to use, publicly perform, distribute, sell, modify,
+ * merge, give away, or sublicence.
+ *
+ * This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
+ * the utmost extent permitted by applicable law, neither express nor
+ * implied; without malicious intent or gross negligence. In no event
+ * may a licensor, author or contributor be held liable for indirect,
+ * direct, other damage, loss, or other issues arising in any way out
+ * of dealing in the work, even if advised of the possibility of such
+ * damage or existence of a defect, except proven that it results out
+ * of said person’s immediate fault when using the work as intended.
+ *-
+ * This file provides BAFH (Better Avalanche for the Jenkins Hash) as
+ * inline macro bodies that operate on “register uint32_t” variables,
+ * with variants that use their local intermediate registers.
+ *
+ * Usage note for BAFH with entropy distribution: input up to 4 bytes
+ * is best combined into a 32-bit unsigned integer, which is then run
+ * through BAFHFinish_reg for mixing and then used as context instead
+ * of 0. Longer input should be handled the same: take the first four
+ * bytes as IV after mixing then add subsequent bytes the same way.
+ * This needs counting input bytes and is endian-dependent, thus not,
+ * for speed reasons, specified for the regular stable hash, but very
+ * much recommended if the actual output value may differ across runs
+ * (so is using a random value instead of 0 for the IV).
+ */
+
+#ifndef SYSKERN_MIRHASH_H
+#define SYSKERN_MIRHASH_H 1
+#define SYSKERN_MIRHASH_BAFH
+
+#include <sys/types.h>
+
+__RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.2 2014/06/29 11:48:05 tg Exp $");
+
+/*-
+ * BAFH itself is defined by the following primitives:
+ *
+ * • BAFHInit(ctx) initialises the hash context, which consists of a
+ * sole 32-bit unsigned integer (ideally in a register), to 0.
+ * It is possible to use any initial value out of [0; 2³²[ – which
+ * is, in fact, recommended if using BAFH for entropy distribution
+ * – but for a regular stable hash, the IV 0 is needed.
+ *
+ * • BAFHUpdateOctet(ctx,val) compresses the unsigned 8-bit quantity
+ * into the hash context. The algorithm used is Jenkins’ one-at-a-
+ * time, except that an additional constant 1 is added so that, if
+ * the context is (still) zero, adding a NUL byte is not ignored.
+ *
+ * • BAFHror(eax,cl) evaluates to the unsigned 32-bit integer “eax”,
+ * rotated right by “cl” ∈ [0;31]; no casting, be careful!
+ *
+ * • BAFHFinish(ctx) avalanches the context around so every sub-byte
+ * depends on all input octets; afterwards, the context variable’s
+ * value is the hash output. BAFH does not use any padding, nor is
+ * the input length added; this is due to the common use case (for
+ * quick entropy distribution and use with a hashtable).
+ * Warning: BAFHFinish uses the MixColumn algorithm of AES – which
+ * is reversible (to avoid introducing funnels and reducing entro‐
+ * py), so blinding may need to be employed for some uses, e.g. in
+ * mksh, after a fork.
+ *
+ * The BAFHUpdateOctet and BAFHFinish are available in two flavours:
+ * suffixed with _reg (assumes the context is in a register) or _mem
+ * (which doesn’t).
+ *
+ * The following high-level macros (with _reg and _mem variants) are
+ * available:
+ *
+ * • BAFHUpdateMem(ctx,buf,len) adds a memory block to a context.
+ * • BAFHUpdateStr(ctx,buf) is equivalent to using len=strlen(buf).
+ * • BAFHHostMem(ctx,buf,len) calculates the hash of the memory buf‐
+ * fer using the first 4 octets (mixed) for IV, as outlined above;
+ * the result is endian-dependent; “ctx” assumed to be a register.
+ * • BAFHHostStr(ctx,buf) does the same for C strings.
+ *
+ * All macros may use ctx multiple times in their expansion, but all
+ * other arguments are always evaluated at most once.
+ *
+ * To stay portable, never use the BAFHHost*() macros (these are for
+ * host-local entropy shuffling), and encode numbers using ULEB128.
+ */
+
+#define BAFHInit(h) do { \
+ (h) = 0; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHUpdateOctet_reg(h,b) do { \
+ (h) += (uint8_t)(b); \
+ ++(h); \
+ (h) += (h) << 10; \
+ (h) ^= (h) >> 6; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHUpdateOctet_mem(m,b) do { \
+ register uint32_t BAFH_h = (m); \
+ \
+ BAFHUpdateOctet_reg(BAFH_h, (b)); \
+ (m) = BAFH_h; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHror(eax,cl) (((eax) >> (cl)) | ((eax) << (32 - (cl))))
+
+#define BAFHFinish_reg(h) do { \
+ register uint32_t BAFHFinish_v; \
+ \
+ BAFHFinish_v = ((h) >> 7) & 0x01010101U; \
+ BAFHFinish_v += BAFHFinish_v << 1; \
+ BAFHFinish_v += BAFHFinish_v << 3; \
+ BAFHFinish_v ^= ((h) << 1) & 0xFEFEFEFEU; \
+ \
+ BAFHFinish_v ^= BAFHror(BAFHFinish_v, 8); \
+ BAFHFinish_v ^= ((h) = BAFHror((h), 8)); \
+ BAFHFinish_v ^= ((h) = BAFHror((h), 8)); \
+ (h) = BAFHror((h), 8) ^ BAFHFinish_v; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHFinish_mem(m) do { \
+ register uint32_t BAFHFinish_v, BAFH_h = (m); \
+ \
+ BAFHFinish_v = (BAFH_h >> 7) & 0x01010101U; \
+ BAFHFinish_v += BAFHFinish_v << 1; \
+ BAFHFinish_v += BAFHFinish_v << 3; \
+ BAFHFinish_v ^= (BAFH_h << 1) & 0xFEFEFEFEU; \
+ \
+ BAFHFinish_v ^= BAFHror(BAFHFinish_v, 8); \
+ BAFHFinish_v ^= (BAFH_h = BAFHror(BAFH_h, 8)); \
+ BAFHFinish_v ^= (BAFH_h = BAFHror(BAFH_h, 8)); \
+ (m) = BAFHror(BAFH_h, 8) ^ BAFHFinish_v; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHUpdateMem_reg(h,p,z) do { \
+ register const uint8_t *BAFHUpdate_p; \
+ register size_t BAFHUpdate_z = (z); \
+ \
+ BAFHUpdate_p = (const void *)(p); \
+ while (BAFHUpdate_z--) \
+ BAFHUpdateOctet_reg((h), *BAFHUpdate_p++); \
+} while (/* CONSTCOND */ 0)
+
+/* meh should have named them _r/m but that’s not valid C */
+#define BAFHUpdateMem_mem(m,p,z) do { \
+ register uint32_t BAFH_h = (m); \
+ \
+ BAFHUpdateMem_reg(BAFH_h, (p), (z)); \
+ (m) = BAFH_h; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHUpdateStr_reg(h,s) do { \
+ register const uint8_t *BAFHUpdate_s; \
+ register uint8_t BAFHUpdate_c; \
+ \
+ BAFHUpdate_s = (const void *)(s); \
+ while ((BAFHUpdate_c = *BAFHUpdate_s++) != 0) \
+ BAFHUpdateOctet_reg((h), BAFHUpdate_c); \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHUpdateStr_mem(m,s) do { \
+ register uint32_t BAFH_h = (m); \
+ \
+ BAFHUpdateStr_reg(BAFH_h, (s)); \
+ (m) = BAFH_h; \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHHostMem(h,p,z) do { \
+ register const uint8_t *BAFHUpdate_p; \
+ register size_t BAFHUpdate_z = (z); \
+ size_t BAFHHost_z; \
+ union { \
+ uint8_t as_u8[4]; \
+ uint32_t as_u32; \
+ } BAFHHost_v; \
+ \
+ BAFHUpdate_p = (const void *)(p); \
+ BAFHHost_v.as_u32 = 0; \
+ BAFHHost_z = BAFHUpdate_z < 4 ? BAFHUpdate_z : 4; \
+ memcpy(BAFHHost_v.as_u8, BAFHUpdate_p, BAFHHost_z); \
+ BAFHUpdate_p += BAFHHost_z; \
+ BAFHUpdate_z -= BAFHHost_z; \
+ (h) = BAFHHost_v.as_u32; \
+ BAFHFinish_reg(h); \
+ while (BAFHUpdate_z--) \
+ BAFHUpdateOctet_reg((h), *BAFHUpdate_p++); \
+ BAFHFinish_reg(h); \
+} while (/* CONSTCOND */ 0)
+
+#define BAFHHostStr(h,s) do { \
+ register const uint8_t *BAFHUpdate_s; \
+ register uint8_t BAFHUpdate_c; \
+ union { \
+ uint8_t as_u8[4]; \
+ uint32_t as_u32; \
+ } BAFHHost_v; \
+ \
+ BAFHUpdate_s = (const void *)(s); \
+ if ((BAFHHost_v.as_u8[0] = *BAFHUpdate_s) != 0) \
+ ++BAFHUpdate_s; \
+ if ((BAFHHost_v.as_u8[1] = *BAFHUpdate_s) != 0) \
+ ++BAFHUpdate_s; \
+ if ((BAFHHost_v.as_u8[2] = *BAFHUpdate_s) != 0) \
+ ++BAFHUpdate_s; \
+ if ((BAFHHost_v.as_u8[3] = *BAFHUpdate_s) != 0) \
+ ++BAFHUpdate_s; \
+ (h) = BAFHHost_v.as_u32; \
+ BAFHFinish_reg(h); \
+ while ((BAFHUpdate_c = *BAFHUpdate_s++) != 0) \
+ BAFHUpdateOctet_reg((h), BAFHUpdate_c); \
+ BAFHFinish_reg(h); \
+} while (/* CONSTCOND */ 0)
+
+#endif
-/* $OpenBSD: misc.c,v 1.37 2009/04/19 20:34:05 sthen Exp $ */
+/* $OpenBSD: misc.c,v 1.38 2013/11/28 10:33:37 sobrado Exp $ */
/* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include <grp.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.214 2013/08/11 14:57:09 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219 2014/01/05 21:57:27 tg Exp $");
#define KSH_CHVT_FLAG
#ifdef MKSH_SMALL
unsigned char chtypes[UCHAR_MAX + 1];
static const unsigned char *pat_scan(const unsigned char *,
- const unsigned char *, bool);
+ const unsigned char *, bool) MKSH_A_PURE;
static int do_gmatch(const unsigned char *, const unsigned char *,
- const unsigned char *, const unsigned char *);
-static const unsigned char *cclass(const unsigned char *, unsigned char);
+ const unsigned char *, const unsigned char *) MKSH_A_PURE;
+static const unsigned char *cclass(const unsigned char *, unsigned char)
+ MKSH_A_PURE;
#ifdef KSH_CHVT_CODE
static void chvt(const Getopt *);
#endif
#define SHFLAGS_DEFNS
-#include "sh_flags.h"
+#include "sh_flags.gen"
#define OFC(i) (options[i][-2])
#define OFF(i) (((const unsigned char *)options[i])[-1])
const char * const options[] = {
#define SHFLAGS_ITEMS
-#include "sh_flags.h"
+#include "sh_flags.gen"
};
/*
/*XXX this can probably be optimised */
kshegid = kshgid = getgid();
+ ksheuid = kshuid = getuid();
#if HAVE_SETRESUGID
DO_SETUID(setresgid, (kshegid, kshegid, kshegid));
#if HAVE_SETGROUPS
setgroups(1, &kshegid);
#endif
DO_SETUID(setresuid, (ksheuid, ksheuid, ksheuid));
-#else
+#else /* !HAVE_SETRESUGID */
/* seteuid, setegid, setgid don't EAGAIN on Linux */
- ksheuid = kshuid = getuid();
#ifndef MKSH__NO_SETEUGID
seteuid(ksheuid);
#endif
setegid(kshegid);
#endif
setgid(kshegid);
-#endif
+#endif /* !HAVE_SETRESUGID */
} else if ((f == FPOSIX || f == FSH) && newval) {
/* Turning on -o posix or -o sh? */
Flag(FBRACEEXPAND) = 0;
int what,
bool *setargsp)
{
- static char cmd_opts[NELEM(options) + 5]; /* o:T:\0 */
- static char set_opts[NELEM(options) + 6]; /* A:o;s\0 */
+ static const char cmd_opts[] =
+#define SHFLAGS_NOT_SET
+#define SHFLAGS_OPTCS
+#include "sh_flags.gen"
+#undef SHFLAGS_NOT_SET
+ ;
+ static const char set_opts[] =
+#define SHFLAGS_NOT_CMD
+#define SHFLAGS_OPTCS
+#include "sh_flags.gen"
+#undef SHFLAGS_NOT_CMD
+ ;
bool set;
- char *opts;
+ const char *opts;
const char *array = NULL;
Getopt go;
size_t i;
bool sortargs = false;
bool fcompatseen = false;
- /* First call? Build option strings... */
- if (cmd_opts[0] == '\0') {
- char ch, *p = cmd_opts, *q = set_opts;
-
- /* see cmd_opts[] declaration */
- *p++ = 'o';
- *p++ = ':';
-#ifdef KSH_CHVT_FLAG
- *p++ = 'T';
- *p++ = ':';
-#endif
- /* see set_opts[] declaration */
- *q++ = 'A';
- *q++ = ':';
- *q++ = 'o';
- *q++ = ';';
- *q++ = 's';
-
- for (i = 0; i < NELEM(options); i++) {
- if ((ch = OFC(i))) {
- if (OFF(i) & OF_CMDLINE)
- *p++ = ch;
- if (OFF(i) & OF_SET)
- *q++ = ch;
- }
- }
- *p = '\0';
- *q = '\0';
- }
-
if (what == OF_CMDLINE) {
const char *p = argv[0], *q;
/*
#ifdef KSH_CHVT_CODE
-extern uint32_t chvt_rndsetup(const void *, size_t);
extern void chvt_reinit(void);
static void
#endif
}
}
- if ((fd = open(dv, O_RDWR)) < 0) {
+ if ((fd = open(dv, O_RDWR | O_BINARY)) < 0) {
sleep(1);
- if ((fd = open(dv, O_RDWR)) < 0) {
+ if ((fd = open(dv, O_RDWR | O_BINARY)) < 0) {
errorf("%s: %s %s", "chvt", "can't open", dv);
}
}
-.\" $MirOS: src/bin/mksh/mksh.1,v 1.320 2013/08/10 14:11:39 tg Exp $
-.\" $OpenBSD: ksh.1,v 1.147 2013/06/13 19:43:09 millert Exp $
+.\" $MirOS: src/bin/mksh/mksh.1,v 1.336 2014/06/24 20:47:44 tg Exp $
+.\" $OpenBSD: ksh.1,v 1.152 2014/02/12 16:28:13 schwarze Exp $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-.\" 2010, 2011, 2012, 2013
+.\" 2010, 2011, 2012, 2013, 2014
.\" Thorsten Glaser <tg@mirbsd.org>
.\"
.\" Provided that these terms and disclaimer and all copyright notices
.\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always.
.\"
-.Dd $Mdocdate: August 10 2013 $
+.Dd $Mdocdate: June 24 2014 $
.\"
.\" Check which macro package we use, and do other -mdoc setup.
.\"
Privileged shell.
A shell is
.Dq privileged
-if this option is used
-or if the real user ID or group ID does not match the
+if the real user ID or group ID does not match the
effective user ID or group ID (see
.Xr getuid 2
and
its effective user ID (group ID) to its real user ID (group ID).
For further implications, see
.Sx Startup files .
+If the shell is privileged and this flag is not explicitly set, the
+.Dq privileged
+option is cleared automatically after processing the startup files.
.It Fl r
Restricted shell.
A shell is
substitution; if unset or empty, the user mkshrc profile is processed;
otherwise, if a file whose name is the substitution result exists,
it is processed; non-existence is silently ignored.
+A privileged shell then drops privileges if neither was the
+.Fl p
+option given on the command line nor set during execution of the startup files.
.Ss Command syntax
The shell begins parsing its input by removing any backslash-newline
combinations, then breaking it into
.Sq !=
and
.Sq =
-expressions are patterns (e.g. the comparison
+expressions are a subset of patterns (e.g. the comparison
.Ic \&[[ foobar = f*r ]]
succeeds).
This even works indirectly:
.Pp
Perhaps surprisingly, the first comparison succeeds,
whereas the second doesn't.
+This does not apply to all extglob metacharacters, currently.
.El
.El
.Ss Quoting
nohup=\*(aqnohup \*(aq
r=\*(aqfc \-e \-\*(aq
stop=\*(aqkill \-STOP\*(aq
-suspend=\*(aqkill \-STOP $$\*(aq
type=\*(aqwhence \-v\*(aq
.Ed
.Pp
must start with a space, opening parenthesis or digit to be recognised.
Cannot be applied to a vector.
.Pp
-.It Xo
-.Pf ${ Ar name
-.Pf @# Ns Oo Ar seed Oc Ns }
-.Xc
-The internal hash of the expansion of
-.Ar name ,
-with an optional (defaulting to zero)
-.Op Ar seed .
-At the moment, this is NZAAT (a 32-bit hash based on
-Bob Jenkins' one-at-a-time hash), but this is not set.
-This is the hash the shell uses internally for its associative arrays.
+.It Pf ${ Ns Ar name Ns @#}
+The hash (using the BAFH algorithm) of the expansion of
+.Ar name .
+This is also used internally for the shell's hashtables.
.Pp
.It Pf ${ Ns Ar name Ns @Q}
A quoted expression safe for re-entry, whose value is the value of the
in the prompt string:
.Bd -literal -offset indent
x=$(print \e\e001)
-PS1="$x$(print \e\er)$x$(tput smso)$x\e$PWD$x$(tput rmso)$x\*(Gt "
+PS1="$x$(print \e\er)$x$(tput so)$x\e$PWD$x$(tput se)$x\*(Gt "
.Ed
.Pp
Due to a strong suggestion from David G. Korn,
built-in command.
Prefixing numbers with a sole digit zero
.Pq Sq 0
-leads to the shell interpreting it as base-8 integer in
+leads to the shell interpreting it as base-8 (octal) integer in
.Ic posix
mode
.Em only ;
.Ic false , fc , fg , getopts ,
.Ic jobs , kill , let , mknod ,
.Ic print , pwd , read , realpath ,
-.Ic rename , sleep , test , true ,
-.Ic ulimit , umask , unalias , whence
+.Ic rename , sleep , suspend , test ,
+.Ic true , ulimit , umask , unalias ,
+.Ic whence
.Pp
Once the type of command has been determined, any command-line parameter
assignments are performed and exported for the duration of the command.
.Ar last
select commands from the history.
Commands can be selected by history number
+(negative numbers go backwards from the current, most recent, line)
or a string specifying the most recent command starting with that string.
The
.Fl l
is syntactic sugar for
.No let \&" Ns Ar expr Ns \&" .
.Pp
-.It let]
+.It Ic let]
Internally used alias for
.Ic let .
.Pp
.It Fl C \*(Ba Fl o Ic noclobber
Prevent \*(Gt redirection from overwriting existing files.
Instead, \*(Gt\*(Ba must be used to force an overwrite.
+Note that this is not safe to use for creation of temporary files or
+lockfiles due to a TOCTOU in a check allowing one to redirect output to
+.Pa /dev/null
+or other device files even in
+.Ic noclobber
+mode.
.It Fl e \*(Ba Fl o Ic errexit
Exit (after executing the
.Dv ERR
Enable
.Xr vi 1 Ns -like
command-line editing (interactive shells only).
+See
+.Sx Vi editing mode
+for documentation and limitations.
.It Fl o Ic vi\-esccomplete
In vi command-line editing, do command and file name completion when escape
(\*(ha[) is entered in command mode.
.Nm mksh ,
this is implemented as a shell alias instead of a builtin.
.Pp
+.It Ic suspend
+Stops the shell as if it had received the suspend character from
+the terminal.
+It is not possible to suspend a login shell unless the parent process
+is a member of the same terminal session but is a member of a different
+process group.
+As a general rule, if the shell was started by another shell or via
+.Xr su 1 ,
+it can be suspended.
+.Pp
.It Ic test Ar expression
.It Ic \&[ Ar expression Ic \&]
.Ic test
.Pp
.It Xo
.Ic ulimit
-.Op Fl aBCcdefHiLlMmnOPpqrSsTtVvw
+.Op Fl aBCcdefHilMmnOPpqrSsTtVvw
.Op Ar value
.Xc
Display or set process limits.
.It Fl i Ar n
Set the number of pending signals to
.Ar n .
-.It Fl L Ar n
-Control flocks; documentation is missing.
.It Fl l Ar n
Impose a limit of
.Ar n
.Ss Vi editing mode
.Em Note:
The vi command-line editing mode is orphaned, yet still functional.
+It is 8-bit clean but specifically does not support UTF-8 or MBCS.
.Pp
The vi command-line editor in
.Nm
.%A Stephen G. Kochan
.%A Patrick H. Wood
.%B "\\*(tNUNIX\\*(sP Shell Programming"
-.%V "Revised Edition"
-.%D 1990
-.%I "Hayden"
-.%P "xi\ +\ 490 pages"
-.%O "ISBN 978\-0\-672\-48448\-3 (0\-672\-48448\-X)"
+.%V "3rd Edition"
+.%D 2003
+.%I "Sams"
+.%P "xiii\ +\ 437 pages"
+.%O "ISBN 978\-0\-672\-32490\-1 (0\-672\-32490\-3)"
.Re
.Rs
.%A "IEEE Inc."
-.%B "\\*(tNIEEE\\*(sP Standard for Information Technology \*(en Portable Operating System Interface (POSIX)"
+.%T "\\*(tNIEEE\\*(sP Standard for Information Technology \*(en Portable Operating System Interface (POSIX)"
.%V "Part 2: Shell and Utilities"
.%D 1993
.%I "IEEE Press"
.%O "ISBN 978\-0\-201\-56324\-5 (0\-201\-56324\-X)"
.Re
.Sh AUTHORS
+.An -nosplit
.Nm "The MirBSD Korn Shell"
is developed by
.An Thorsten Glaser Aq tg@mirbsd.org
and currently maintained as part of The MirOS Project.
-This shell is based upon the Public Domain Korn SHell.
-The developer of mksh recognises the efforts of the pdksh authors,
-who had dedicated their work into Public Domain, our users, and
-all contributors, such as the Debian and OpenBSD projects.
-.\"
-.\" Charles Forsyth, author of the (Public Domain) Bourne Shell clone,
-.\" which mksh is derived from, agreed to the following:
-.\"
-.\" In countries where the Public Domain status of the work may not be
-.\" valid, its primary author hereby grants a copyright licence to the
-.\" general public to deal in the work without restriction and permis-
-.\" sion to sublicence derivates under the terms of any (OSI approved)
-.\" Open Source licence.
-.\"
+This shell is based on the public domain 7th edition Bourne shell clone by
+.An Charles Forsyth ,
+who kindly agreed to, in countries where the Public Domain status of the work
+may not be valid, grant a copyright licence to the general public to deal in
+the work without restriction and permission to sublicence derivates under the
+terms of any (OSI approved) Open Source licence,
+and parts of the BRL shell by
+.An Doug A. Gwyn ,
+.An Doug Kingston ,
+.An Ron Natalie ,
+.An Arnold Robbins ,
+.An Lou Salkind ,
+and others.
+The first release of
+.Nm pdksh
+was created by
+.An Eric Gisin ,
+and it was subsequently maintained by
+.An John R. MacMillan Aq Mt change!john@sq.sq.com ,
+.An Simon J. Gerraty Aq Mt sjg@zen.void.oz.au ,
+and
+.An Michael Rendell Aq Mt michael@cs.mun.ca .
+The effort of several projects, such as Debian and OpenBSD, and other
+contributors including our users, to improve the shell is appreciated.
See the documentation, CVS, and web site for details.
.Pp
The BSD daemon is Copyright \(co Marshall Kirk McKusick.
.Ed
.Pp
This document attempts to describe
-.Nm mksh\ R48
+.Nm mksh\ R50
and up,
compiled without any options impacting functionality, such as
.Dv MKSH_SMALL ,
--- /dev/null
+#ifndef RLIMITS_OPTCS
+#if defined(RLIMITS_DEFNS)
+__RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.1 2013/11/17 22:21:18 tg Exp $");
+struct limits {
+ /* limit resource */
+ int resource;
+ /* multiply by to get rlim_{cur,max} values */
+ unsigned int factor;
+ /* getopts char */
+ char optchar;
+ /* limit name */
+ char name[1];
+};
+#define FN(lname,lid,lfac,lopt) static const struct { int resource; unsigned int factor; char optchar; char name[sizeof(lname)]; } rlimits_ ## lid = { lid, lfac, lopt, lname };
+#elif defined(RLIMITS_ITEMS)
+#define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
+#endif
+#ifndef F0
+#define F0 FN
+#endif
+#ifdef RLIMIT_CPU
+FN("time(cpu-seconds)", RLIMIT_CPU, 1, 't')
+#endif
+#ifdef RLIMIT_FSIZE
+FN("file(blocks)", RLIMIT_FSIZE, 512, 'f')
+#endif
+#ifdef RLIMIT_CORE
+FN("coredump(blocks)", RLIMIT_CORE, 512, 'c')
+#endif
+#ifdef RLIMIT_DATA
+FN("data(KiB)", RLIMIT_DATA, 1024, 'd')
+#endif
+#ifdef RLIMIT_STACK
+FN("stack(KiB)", RLIMIT_STACK, 1024, 's')
+#endif
+#ifdef RLIMIT_MEMLOCK
+FN("lockedmem(KiB)", RLIMIT_MEMLOCK, 1024, 'l')
+#endif
+#ifdef RLIMIT_NOFILE
+FN("nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n')
+#endif
+#ifdef RLIMIT_NPROC
+FN("processes", RLIMIT_NPROC, 1, 'p')
+#endif
+#ifdef RLIMIT_SWAP
+FN("swap(KiB)", RLIMIT_SWAP, 1024, 'w')
+#endif
+#ifdef RLIMIT_TIME
+FN("humantime(seconds)", RLIMIT_TIME, 1, 'T')
+#endif
+#ifdef RLIMIT_NOVMON
+FN("vnodemonitors", RLIMIT_NOVMON, 1, 'V')
+#endif
+#ifdef RLIMIT_SIGPENDING
+FN("sigpending", RLIMIT_SIGPENDING, 1, 'i')
+#endif
+#ifdef RLIMIT_MSGQUEUE
+FN("msgqueue(bytes)", RLIMIT_MSGQUEUE, 1, 'q')
+#endif
+#ifdef RLIMIT_AIO_MEM
+FN("AIOlockedmem(KiB)", RLIMIT_AIO_MEM, 1024, 'M')
+#endif
+#ifdef RLIMIT_AIO_OPS
+FN("AIOoperations", RLIMIT_AIO_OPS, 1, 'O')
+#endif
+#ifdef RLIMIT_TCACHE
+FN("cachedthreads", RLIMIT_TCACHE, 1, 'C')
+#endif
+#ifdef RLIMIT_SBSIZE
+FN("sockbufsiz(KiB)", RLIMIT_SBSIZE, 1024, 'B')
+#endif
+#ifdef RLIMIT_PTHREAD
+FN("threadsperprocess", RLIMIT_PTHREAD, 1, 'P')
+#endif
+#ifdef RLIMIT_NICE
+FN("maxnice", RLIMIT_NICE, 1, 'e')
+#endif
+#ifdef RLIMIT_RTPRIO
+FN("maxrtprio", RLIMIT_RTPRIO, 1, 'r')
+#endif
+#ifdef ULIMIT_M_IS_RSS
+FN("resident-set(KiB)", RLIMIT_RSS, 1024, 'm')
+#endif
+#ifdef ULIMIT_M_IS_VMEM
+FN("memory(KiB)", RLIMIT_VMEM, 1024, 'm')
+#endif
+#ifdef ULIMIT_V_IS_VMEM
+FN("virtual-memory(KiB)", RLIMIT_VMEM, 1024, 'v')
+#endif
+#ifdef ULIMIT_V_IS_AS
+FN("address-space(KiB)", RLIMIT_AS, 1024, 'v')
+#endif
+#undef F0
+#undef FN
+#undef RLIMITS_DEFNS
+#undef RLIMITS_ITEMS
+#else
+"a"
+#ifdef RLIMIT_SBSIZE
+"B"
+#endif
+#ifdef RLIMIT_TCACHE
+"C"
+#endif
+#ifdef RLIMIT_CORE
+"c"
+#endif
+#ifdef RLIMIT_DATA
+"d"
+#endif
+#ifdef RLIMIT_NICE
+"e"
+#endif
+#ifdef RLIMIT_FSIZE
+"f"
+#endif
+"H"
+#ifdef RLIMIT_SIGPENDING
+"i"
+#endif
+#ifdef RLIMIT_MEMLOCK
+"l"
+#endif
+#ifdef RLIMIT_AIO_MEM
+"M"
+#endif
+#ifdef ULIMIT_M_IS_RSS
+"m"
+#endif
+#ifdef ULIMIT_M_IS_VMEM
+"m"
+#endif
+#ifdef RLIMIT_NOFILE
+"n"
+#endif
+#ifdef RLIMIT_AIO_OPS
+"O"
+#endif
+#ifdef RLIMIT_PTHREAD
+"P"
+#endif
+#ifdef RLIMIT_NPROC
+"p"
+#endif
+#ifdef RLIMIT_MSGQUEUE
+"q"
+#endif
+#ifdef RLIMIT_RTPRIO
+"r"
+#endif
+"S"
+#ifdef RLIMIT_STACK
+"s"
+#endif
+#ifdef RLIMIT_TIME
+"T"
+#endif
+#ifdef RLIMIT_CPU
+"t"
+#endif
+#ifdef RLIMIT_NOVMON
+"V"
+#endif
+#ifdef ULIMIT_V_IS_AS
+"v"
+#endif
+#ifdef ULIMIT_V_IS_VMEM
+"v"
+#endif
+#ifdef RLIMIT_SWAP
+"w"
+#endif
+#undef RLIMITS_OPTCS
+#endif
--- /dev/null
+@RLIMITS_DEFNS
+__RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.1 2013/11/17 22:21:18 tg Exp $");
+struct limits {
+ /* limit resource */
+ int resource;
+ /* multiply by to get rlim_{cur,max} values */
+ unsigned int factor;
+ /* getopts char */
+ char optchar;
+ /* limit name */
+ char name[1];
+};
+#define FN(lname,lid,lfac,lopt) static const struct { int resource; unsigned int factor; char optchar; char name[sizeof(lname)]; } rlimits_ ## lid = { lid, lfac, lopt, lname };
+@RLIMITS_ITEMS
+#define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
+@@
+
+/* generic options for the ulimit builtin */
+
+<a|
+<H|
+<S|
+
+/* do not use options -H, -S or -a or change the order */
+
+>t|RLIMIT_CPU
+FN("time(cpu-seconds)", RLIMIT_CPU, 1
+
+>f|RLIMIT_FSIZE
+FN("file(blocks)", RLIMIT_FSIZE, 512
+
+>c|RLIMIT_CORE
+FN("coredump(blocks)", RLIMIT_CORE, 512
+
+>d|RLIMIT_DATA
+FN("data(KiB)", RLIMIT_DATA, 1024
+
+>s|RLIMIT_STACK
+FN("stack(KiB)", RLIMIT_STACK, 1024
+
+>l|RLIMIT_MEMLOCK
+FN("lockedmem(KiB)", RLIMIT_MEMLOCK, 1024
+
+>n|RLIMIT_NOFILE
+FN("nofiles(descriptors)", RLIMIT_NOFILE, 1
+
+>p|RLIMIT_NPROC
+FN("processes", RLIMIT_NPROC, 1
+
+>w|RLIMIT_SWAP
+FN("swap(KiB)", RLIMIT_SWAP, 1024
+
+>T|RLIMIT_TIME
+FN("humantime(seconds)", RLIMIT_TIME, 1
+
+>V|RLIMIT_NOVMON
+FN("vnodemonitors", RLIMIT_NOVMON, 1
+
+>i|RLIMIT_SIGPENDING
+FN("sigpending", RLIMIT_SIGPENDING, 1
+
+>q|RLIMIT_MSGQUEUE
+FN("msgqueue(bytes)", RLIMIT_MSGQUEUE, 1
+
+>M|RLIMIT_AIO_MEM
+FN("AIOlockedmem(KiB)", RLIMIT_AIO_MEM, 1024
+
+>O|RLIMIT_AIO_OPS
+FN("AIOoperations", RLIMIT_AIO_OPS, 1
+
+>C|RLIMIT_TCACHE
+FN("cachedthreads", RLIMIT_TCACHE, 1
+
+>B|RLIMIT_SBSIZE
+FN("sockbufsiz(KiB)", RLIMIT_SBSIZE, 1024
+
+>P|RLIMIT_PTHREAD
+FN("threadsperprocess", RLIMIT_PTHREAD, 1
+
+>e|RLIMIT_NICE
+FN("maxnice", RLIMIT_NICE, 1
+
+>r|RLIMIT_RTPRIO
+FN("maxrtprio", RLIMIT_RTPRIO, 1
+
+>m|ULIMIT_M_IS_RSS
+FN("resident-set(KiB)", RLIMIT_RSS, 1024
+>m|ULIMIT_M_IS_VMEM
+FN("memory(KiB)", RLIMIT_VMEM, 1024
+
+>v|ULIMIT_V_IS_VMEM
+FN("virtual-memory(KiB)", RLIMIT_VMEM, 1024
+>v|ULIMIT_V_IS_AS
+FN("address-space(KiB)", RLIMIT_AS, 1024
+
+|RLIMITS_OPTCS
-/* $OpenBSD: sh.h,v 1.31 2012/09/10 01:25:30 tedu Exp $ */
+/* $OpenBSD: sh.h,v 1.33 2013/12/18 13:53:12 millert Exp $ */
/* $OpenBSD: shf.h,v 1.6 2005/12/11 18:53:51 deraadt Exp $ */
/* $OpenBSD: table.h,v 1.8 2012/02/19 07:52:30 otto Exp $ */
/* $OpenBSD: tree.h,v 1.10 2005/03/28 21:28:22 deraadt Exp $ */
/* $OpenBSD: expand.h,v 1.6 2005/03/30 17:16:37 deraadt Exp $ */
/* $OpenBSD: lex.h,v 1.13 2013/03/03 19:11:34 guenther Exp $ */
-/* $OpenBSD: proto.h,v 1.34 2012/06/27 07:17:19 otto Exp $ */
+/* $OpenBSD: proto.h,v 1.35 2013/09/04 15:49:19 millert Exp $ */
/* $OpenBSD: c_test.h,v 1.4 2004/12/20 11:34:26 otto Exp $ */
/* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */
/*-
* Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#undef __attribute__
#if HAVE_ATTRIBUTE_BOUNDED
-#define MKSH_A_BOUNDED(x,y,z) __attribute__((__bounded__ (x, y, z)))
+#define MKSH_A_BOUNDED(x,y,z) __attribute__((__bounded__(x, y, z)))
#else
#define MKSH_A_BOUNDED(x,y,z) /* nothing */
#endif
#if HAVE_ATTRIBUTE_FORMAT
-#define MKSH_A_FORMAT(x,y,z) __attribute__((__format__ (x, y, z)))
+#define MKSH_A_FORMAT(x,y,z) __attribute__((__format__(x, y, z)))
#else
#define MKSH_A_FORMAT(x,y,z) /* nothing */
#endif
#else
#define MKSH_A_NORETURN /* nothing */
#endif
+#if HAVE_ATTRIBUTE_PURE
+#define MKSH_A_PURE __attribute__((__pure__))
+#else
+#define MKSH_A_PURE /* nothing */
+#endif
#if HAVE_ATTRIBUTE_UNUSED
#define MKSH_A_UNUSED __attribute__((__unused__))
#else
#endif
#ifdef EXTERN
-__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.667 2013/08/14 20:26:19 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.691 2014/06/29 11:28:28 tg Exp $");
#endif
-#define MKSH_VERSION "R48 2013/08/14"
+#define MKSH_VERSION "R50 2014/06/29"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
#define ksh_isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
#define ksh_tolower(c) (((c) >= 'A') && ((c) <= 'Z') ? (c) - 'A' + 'a' : (c))
#define ksh_toupper(c) (((c) >= 'a') && ((c) <= 'z') ? (c) - 'a' + 'A' : (c))
-#define ksh_isdash(s) (((s) != NULL) && ((s)[0] == '-') && ((s)[1] == '\0'))
+#define ksh_isdash(s) (((s)[0] == '-') && ((s)[1] == '\0'))
#define ksh_isspace(c) ((((c) >= 0x09) && ((c) <= 0x0D)) || ((c) == 0x20))
#define ksh_min(x,y) ((x) < (y) ? (x) : (y))
#define ksh_max(x,y) ((x) > (y) ? (x) : (y))
#define NSIG (SIGMAX+1)
#elif defined(_SIGMAX)
#define NSIG (_SIGMAX+1)
+#else
+# error Please have your platform define NSIG.
+#define NSIG 64
+#endif
#endif
+
+/* get rid of this (and awk/printf(1) in Build.sh) later */
+#if (NSIG < 1)
+# error Your NSIG value is not positive.
+#unset NSIG
+#define NSIG 64
#endif
#endif
#endif
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
#ifdef MKSH__NO_SYMLINK
#undef S_ISLNK
#define S_ISLNK(m) (/* CONSTCOND */ 0)
#define mksh_tcset(fd,st) ioctl((fd), TCSETAW, (st))
#endif
-/* remove redundancies */
-
-#if defined(MirBSD) && (MirBSD >= 0x0AB3) && !defined(MKSH_OPTSTATIC)
-#define MKSH_mirbsd_wcwidth
-#define utf_wcwidth(i) wcwidth((__WCHAR_TYPE__)i)
-extern int wcwidth(__WCHAR_TYPE__);
+#ifndef ISTRIP
+#define ISTRIP 0
#endif
#define mkssert(e) do { } while (/* CONSTCOND */ 0)
#endif
-#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 481)
+#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 501)
#error Must run Build.sh to compile this.
extern void thiswillneverbedefinedIhope(void);
int
*/
enum sh_flag {
#define SHFLAGS_ENUMS
-#include "sh_flags.h"
+#include "sh_flags.gen"
FNFLAGS /* (place holder: how many flags are there) */
};
#define arrayindex(vp) ((unsigned long)((vp)->flag & AINDEX ? \
(vp)->ua.index : 0))
-EXTERN enum {
+enum namerefflag {
SRF_NOP,
SRF_ENABLE,
SRF_DISABLE
-} set_refflag E_INIT(SRF_NOP);
+};
/* command types */
#define CNONE 0 /* undefined */
#define DOTEMP BIT(8) /* dito: in word part of ${..[%#=?]..} */
#define DOVACHECK BIT(9) /* var assign check (for typeset, set, etc) */
#define DOMARKDIRS BIT(10) /* force markdirs behaviour */
-#if !defined(MKSH_SMALL)
#define DOTCOMEXEC BIT(11) /* not an eval flag, used by sh -c hack */
-#endif
-
-/*
- * The arguments of [[ .. ]] expressions are kept in t->args[] and flags
- * indicating how the arguments have been munged are kept in t->vars[].
- * The contents of t->vars[] are stuffed strings (so they can be treated
- * like all other t->vars[]) in which the second character is the one that
- * is examined. The DB_* defines are the values for these second characters.
- */
-#define DB_NORM 1 /* normal argument */
-#define DB_OR 2 /* || -> -o conversion */
-#define DB_AND 3 /* && -> -a conversion */
-#define DB_BE 4 /* an inserted -BE */
-#define DB_PAT 5 /* a pattern argument */
#define X_EXTRA 20 /* this many extra bytes in X string */
#define XcheckN(xs, xp, n) do { \
ssize_t more = ((xp) + (n)) - (xs).end; \
if (more > 0) \
- (xp) = Xcheck_grow(&(xs), (xp), more); \
+ (xp) = Xcheck_grow(&(xs), (xp), (size_t)more); \
} while (/* CONSTCOND */ 0)
/* check for overflow, expand string */
#define SF_ALIASEND BIT(2) /* faking space at end of alias */
#define SF_TTY BIT(3) /* type == SSTDIN & it is a tty */
#define SF_HASALIAS BIT(4) /* u.tblp valid (SALIAS, SEOF) */
-#if !defined(MKSH_SMALL)
#define SF_MAYEXEC BIT(5) /* special sh -c optimisation hack */
-#endif
typedef union {
int i;
#undef CTRL
#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
#define UNCTRL(x) ((x) ^ 0x40) /* ASCII */
+#define ISCTRL(x) (((signed char)((uint8_t)(x) + 1)) < 33)
#define IDENT 64
} while (/* CONSTCOND */ 0)
-/* NZAAT hash based on Bob Jenkins' one-at-a-time hash */
-
-/* From: src/kern/include/nzat.h,v 1.2 2011/07/18 00:35:40 tg Exp $ */
-
-#define NZATInit(h) do { \
- (h) = 0; \
-} while (/* CONSTCOND */ 0)
-
-#define NZATUpdateByte(h,b) do { \
- (h) += (uint8_t)(b); \
- ++(h); \
- (h) += (h) << 10; \
- (h) ^= (h) >> 6; \
-} while (/* CONSTCOND */ 0)
-
-#define NZATUpdateMem(h,p,z) do { \
- register const uint8_t *NZATUpdateMem_p; \
- register size_t NZATUpdateMem_z = (z); \
- \
- NZATUpdateMem_p = (const void *)(p); \
- while (NZATUpdateMem_z--) \
- NZATUpdateByte((h), *NZATUpdateMem_p++); \
-} while (/* CONSTCOND */ 0)
-
-#define NZATUpdateString(h,s) do { \
- register const char *NZATUpdateString_s; \
- register uint8_t NZATUpdateString_c; \
- \
- NZATUpdateString_s = (const void *)(s); \
- while ((NZATUpdateString_c = *NZATUpdateString_s++)) \
- NZATUpdateByte((h), NZATUpdateString_c); \
-} while (/* CONSTCOND */ 0)
-
-#define NZAATFinish(h) do { \
- (h) += (h) << 10; \
- (h) ^= (h) >> 6; \
- (h) += (h) << 3; \
- (h) ^= (h) >> 11; \
- (h) += (h) << 15; \
-} while (/* CONSTCOND */ 0)
-
-
/* lalloc.c */
void ainit(Area *);
void afreeall(Area *);
size_t utf_mbtowc(unsigned int *, const char *);
size_t utf_wctomb(char *, unsigned int);
int utf_widthadj(const char *, const char **);
-size_t utf_mbswidth(const char *);
-const char *utf_skipcols(const char *, int);
-size_t utf_ptradj(const char *);
-#ifndef MKSH_mirbsd_wcwidth
-int utf_wcwidth(unsigned int);
-#endif
+size_t utf_mbswidth(const char *) MKSH_A_PURE;
+const char *utf_skipcols(const char *, int) MKSH_A_PURE;
+size_t utf_ptradj(const char *) MKSH_A_PURE;
+int utf_wcwidth(unsigned int) MKSH_A_PURE;
int ksh_access(const char *, int);
struct tbl *tempvar(void);
/* funcs.c */
void sethistfile(const char *);
#endif
#if !defined(MKSH_NO_CMDLINE_EDITING) && !MKSH_S_NOVI
-char **histpos(void);
+char **histpos(void) MKSH_A_PURE;
int histnum(int);
#endif
-int findhist(int, int, const char *, int);
+int findhist(int, int, const char *, bool) MKSH_A_PURE;
char **hist_get_newest(bool);
void inittraps(void);
void alarm_init(void);
#ifndef MKSH_UNEMPLOYED
int j_resume(const char *, int);
#endif
+#if !defined(MKSH_UNEMPLOYED) && HAVE_GETSID
+void j_suspend(void);
+#endif
int j_jobs(const char *, int, int);
void j_notify(void);
pid_t j_async(void);
/* misc.c */
void setctypes(const char *, int);
void initctypes(void);
-size_t option(const char *);
+size_t option(const char *) MKSH_A_PURE;
char *getoptions(void);
void change_flag(enum sh_flag, int, bool);
void change_xtrace(unsigned char, bool);
int parse_args(const char **, int, bool *);
int getn(const char *, int *);
int gmatchx(const char *, const char *, bool);
-int has_globbing(const char *, const char *);
-int xstrcmp(const void *, const void *);
+int has_globbing(const char *, const char *) MKSH_A_PURE;
+int xstrcmp(const void *, const void *) MKSH_A_PURE;
void ksh_getopt_reset(Getopt *, int);
int ksh_getopt(const char **, Getopt *, const char *);
void print_value_quoted(struct shf *, const char *);
void setint_n(struct tbl *, mksh_ari_t, int);
struct tbl *typeset(const char *, uint32_t, uint32_t, int, int);
void unset(struct tbl *, int);
-const char *skip_varname(const char *, int);
-const char *skip_wdvarname(const char *, bool);
-int is_wdvarname(const char *, bool);
-int is_wdvarassign(const char *);
+const char *skip_varname(const char *, bool) MKSH_A_PURE;
+const char *skip_wdvarname(const char *, bool) MKSH_A_PURE;
+int is_wdvarname(const char *, bool) MKSH_A_PURE;
+int is_wdvarassign(const char *) MKSH_A_PURE;
struct tbl *arraysearch(struct tbl *, uint32_t);
char **makenv(void);
void change_winsz(void);
-size_t array_ref_len(const char *);
+size_t array_ref_len(const char *) MKSH_A_PURE;
char *arrayname(const char *);
mksh_uari_t set_array(const char *, bool, const char **);
-uint32_t hash(const void *);
+uint32_t hash(const void *) MKSH_A_PURE;
+uint32_t chvt_rndsetup(const void *, size_t) MKSH_A_PURE;
mksh_ari_t rndget(void);
void rndset(unsigned long);
+void rndpush(const void *);
enum Test_op {
/* non-operator */
extern const char * const dbtest_tokens[];
-Test_op test_isop(Test_meta, const char *);
+Test_op test_isop(Test_meta, const char *) MKSH_A_PURE;
int test_eval(Test_env *, Test_op, const char *, const char *, bool);
int test_parse(Test_env *);
+/* tty_fd is not opened O_BINARY, it's thus never read/written */
EXTERN int tty_fd E_INIT(-1); /* dup'd tty file descriptor */
EXTERN bool tty_devtty; /* true if tty_fd is from /dev/tty */
EXTERN mksh_ttyst tty_state; /* saved tty state */
--- /dev/null
+#ifndef SHFLAGS_OPTCS
+#if defined(SHFLAGS_DEFNS)
+__RCSID("$MirOS: src/bin/mksh/sh_flags.opt,v 1.2 2014/06/09 12:28:19 tg Exp $");
+#define FN(sname,cname,flags,ochar) static const struct { /* character flag (if any) */ char c; /* OF_* */ unsigned char optflags; /* long name of option */ char name[sizeof(sname)]; } shoptione_ ## cname = { ochar, flags, sname };
+#elif defined(SHFLAGS_ENUMS)
+#define FN(sname,cname,flags,ochar) cname,
+#define F0(sname,cname,flags,ochar) cname = 0,
+#elif defined(SHFLAGS_ITEMS)
+#define FN(sname,cname,flags,ochar) ((const char *)(&shoptione_ ## cname)) + 2,
+#endif
+#ifndef F0
+#define F0 FN
+#endif
+F0("allexport", FEXPORT, OF_ANY, 'a')
+#if HAVE_NICE
+FN("bgnice", FBGNICE, OF_ANY, 0)
+#endif
+FN("braceexpand", FBRACEEXPAND, OF_ANY, 0)
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("emacs", FEMACS, OF_ANY, 0)
+#endif
+FN("errexit", FERREXIT, OF_ANY, 'e')
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("gmacs", FGMACS, OF_ANY, 0)
+#endif
+FN("ignoreeof", FIGNOREEOF, OF_ANY, 0)
+FN("inherit-xtrace", FXTRACEREC, OF_ANY, 0)
+#ifndef SHFLAGS_NOT_CMD
+FN("interactive", FTALKING, OF_CMDLINE, 'i')
+#endif
+FN("keyword", FKEYWORD, OF_ANY, 'k')
+#ifndef SHFLAGS_NOT_CMD
+FN("login", FLOGIN, OF_CMDLINE, 'l')
+#endif
+FN("markdirs", FMARKDIRS, OF_ANY, 'X')
+#ifndef MKSH_UNEMPLOYED
+FN("monitor", FMONITOR, OF_ANY, 'm')
+#endif
+FN("noclobber", FNOCLOBBER, OF_ANY, 'C')
+FN("noexec", FNOEXEC, OF_ANY, 'n')
+FN("noglob", FNOGLOB, OF_ANY, 'f')
+FN("nohup", FNOHUP, OF_ANY, 0)
+FN("nolog", FNOLOG, OF_ANY, 0)
+#ifndef MKSH_UNEMPLOYED
+FN("notify", FNOTIFY, OF_ANY, 'b')
+#endif
+FN("nounset", FNOUNSET, OF_ANY, 'u')
+FN("physical", FPHYSICAL, OF_ANY, 0)
+FN("pipefail", FPIPEFAIL, OF_ANY, 0)
+FN("posix", FPOSIX, OF_ANY, 0)
+FN("privileged", FPRIVILEGED, OF_ANY, 'p')
+#ifndef SHFLAGS_NOT_CMD
+FN("restricted", FRESTRICTED, OF_CMDLINE, 'r')
+#endif
+FN("sh", FSH, OF_ANY, 0)
+#ifndef SHFLAGS_NOT_CMD
+FN("stdin", FSTDIN, OF_CMDLINE, 's')
+#endif
+FN("trackall", FTRACKALL, OF_ANY, 'h')
+FN("utf8-mode", FUNICODE, OF_ANY, 'U')
+FN("verbose", FVERBOSE, OF_ANY, 'v')
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi", FVI, OF_ANY, 0)
+#endif
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi-esccomplete", FVIESCCOMPLETE, OF_ANY, 0)
+#endif
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi-tabcomplete", FVITABCOMPLETE, OF_ANY, 0)
+#endif
+#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("viraw", FVIRAW, OF_ANY, 0)
+#endif
+FN("xtrace", FXTRACE, OF_ANY, 'x')
+#ifndef SHFLAGS_NOT_CMD
+FN("", FCOMMAND, OF_CMDLINE, 'c')
+#endif
+FN("", FAS_BUILTIN, OF_INTERNAL, 0)
+FN("", FTALKING_I, OF_INTERNAL, 0)
+#undef F0
+#undef FN
+#undef SHFLAGS_DEFNS
+#undef SHFLAGS_ENUMS
+#undef SHFLAGS_ITEMS
+#else
+#ifndef SHFLAGS_NOT_SET
+"A:"
+#endif
+"a"
+#ifndef MKSH_UNEMPLOYED
+"b"
+#endif
+"C"
+#ifndef SHFLAGS_NOT_CMD
+"c"
+#endif
+"e"
+"f"
+"h"
+#ifndef SHFLAGS_NOT_CMD
+"i"
+#endif
+"k"
+#ifndef SHFLAGS_NOT_CMD
+"l"
+#endif
+#ifndef MKSH_UNEMPLOYED
+"m"
+#endif
+"n"
+#ifndef SHFLAGS_NOT_CMD
+"o:"
+#endif
+#ifndef SHFLAGS_NOT_SET
+"o;"
+#endif
+"p"
+#ifndef SHFLAGS_NOT_CMD
+"r"
+#endif
+#ifndef SHFLAGS_NOT_CMD
+"s"
+#endif
+#ifndef SHFLAGS_NOT_SET
+"s"
+#endif
+#ifndef SHFLAGS_NOT_CMD
+"T:"
+#endif
+"U"
+"u"
+"v"
+"X"
+"x"
+#undef SHFLAGS_OPTCS
+#endif
+++ /dev/null
-#if defined(SHFLAGS_DEFNS)
-__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.16 2013/08/11 14:57:11 tg Exp $");
-#define FN(sname,cname,ochar,flags) \
- static const struct { \
- /* character flag (if any) */ \
- char c; \
- /* OF_* */ \
- unsigned char optflags; \
- /* long name of option */ \
- char name[sizeof(sname)]; \
- } shoptione_ ## cname = { \
- ochar, flags, sname \
- };
-#elif defined(SHFLAGS_ENUMS)
-#define FN(sname,cname,ochar,flags) cname,
-#define F0(sname,cname,ochar,flags) cname = 0,
-#elif defined(SHFLAGS_ITEMS)
-#define FN(sname,cname,ochar,flags) \
- ((const char *)(&shoptione_ ## cname)) + 2,
-#endif
-
-#ifndef F0
-#define F0 FN
-#endif
-
-/*
- * special cases (see parse_args()): -A, -o, -s
- *
- * options are sorted by their longnames
- */
-
-/* -a all new parameters are created with the export attribute */
-F0("allexport", FEXPORT, 'a', OF_ANY)
-
-#if HAVE_NICE
-/* ./. bgnice */
-FN("bgnice", FBGNICE, 0, OF_ANY)
-#endif
-
-/* ./. enable {} globbing (non-standard) */
-FN("braceexpand", FBRACEEXPAND, 0, OF_ANY)
-
-#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
-/* ./. Emacs command line editing mode */
-FN("emacs", FEMACS, 0, OF_ANY)
-#endif
-
-/* -e quit on error */
-FN("errexit", FERREXIT, 'e', OF_ANY)
-
-#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
-/* ./. Emacs command line editing mode, gmacs variant */
-FN("gmacs", FGMACS, 0, OF_ANY)
-#endif
-
-/* ./. reading EOF does not exit */
-FN("ignoreeof", FIGNOREEOF, 0, OF_ANY)
-
-/* ./. inherit -x flag */
-FN("inherit-xtrace", FXTRACEREC, 0, OF_ANY)
-
-/* -i interactive shell */
-FN("interactive", FTALKING, 'i', OF_CMDLINE)
-
-/* -k name=value are recognised anywhere */
-FN("keyword", FKEYWORD, 'k', OF_ANY)
-
-/* -l login shell */
-FN("login", FLOGIN, 'l', OF_CMDLINE)
-
-/* -X mark dirs with / in file name completion */
-FN("markdirs", FMARKDIRS, 'X', OF_ANY)
-
-#ifndef MKSH_UNEMPLOYED
-/* -m job control monitoring */
-FN("monitor", FMONITOR, 'm', OF_ANY)
-#endif
-
-/* -C don't overwrite existing files */
-FN("noclobber", FNOCLOBBER, 'C', OF_ANY)
-
-/* -n don't execute any commands */
-FN("noexec", FNOEXEC, 'n', OF_ANY)
-
-/* -f don't do file globbing */
-FN("noglob", FNOGLOB, 'f', OF_ANY)
-
-/* ./. don't kill running jobs when login shell exits */
-FN("nohup", FNOHUP, 0, OF_ANY)
-
-/* ./. don't save functions in history (no effect) */
-FN("nolog", FNOLOG, 0, OF_ANY)
-
-#ifndef MKSH_UNEMPLOYED
-/* -b asynchronous job completion notification */
-FN("notify", FNOTIFY, 'b', OF_ANY)
-#endif
-
-/* -u using an unset variable is an error */
-FN("nounset", FNOUNSET, 'u', OF_ANY)
-
-/* ./. don't do logical cds/pwds (non-standard) */
-FN("physical", FPHYSICAL, 0, OF_ANY)
-
-/* ./. errorlevel of a pipeline is the rightmost nonzero value */
-FN("pipefail", FPIPEFAIL, 0, OF_ANY)
-
-/* ./. adhere more closely to POSIX even when undesirable */
-FN("posix", FPOSIX, 0, OF_ANY)
-
-/* -p use suid_profile; privileged shell */
-FN("privileged", FPRIVILEGED, 'p', OF_ANY)
-
-/* -r restricted shell */
-FN("restricted", FRESTRICTED, 'r', OF_CMDLINE)
-
-/* ./. kludge mode for better compat with traditional sh (OS-specific) */
-FN("sh", FSH, 0, OF_ANY)
-
-/* -s (invocation) parse stdin (pseudo non-standard) */
-FN("stdin", FSTDIN, 's', OF_CMDLINE)
-
-/* -h create tracked aliases for all commands */
-FN("trackall", FTRACKALL, 'h', OF_ANY)
-
-/* -U enable UTF-8 processing (non-standard) */
-FN("utf8-mode", FUNICODE, 'U', OF_ANY)
-
-/* -v echo input */
-FN("verbose", FVERBOSE, 'v', OF_ANY)
-
-#if !defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
-/* ./. Vi command line editing mode */
-FN("vi", FVI, 0, OF_ANY)
-
-/* ./. enable ESC as file name completion character (non-standard) */
-FN("vi-esccomplete", FVIESCCOMPLETE, 0, OF_ANY)
-
-/* ./. enable Tab as file name completion character (non-standard) */
-FN("vi-tabcomplete", FVITABCOMPLETE, 0, OF_ANY)
-
-/* ./. always read in raw mode (no effect) */
-FN("viraw", FVIRAW, 0, OF_ANY)
-#endif
-
-/* -x execution trace (display commands as they are run) */
-FN("xtrace", FXTRACE, 'x', OF_ANY)
-
-/* -c (invocation) execute specified command */
-FN("", FCOMMAND, 'c', OF_CMDLINE)
-
-/*
- * anonymous flags: used internally by shell only (not visible to user)
- */
-
-/* ./. direct builtin call (divined from argv[0] multi-call binary) */
-FN("", FAS_BUILTIN, 0, OF_INTERNAL)
-
-/* ./. (internal) initial shell was interactive */
-FN("", FTALKING_I, 0, OF_INTERNAL)
-
-#undef FN
-#undef F0
-#undef SHFLAGS_DEFNS
-#undef SHFLAGS_ENUMS
-#undef SHFLAGS_ITEMS
--- /dev/null
+@SHFLAGS_DEFNS
+__RCSID("$MirOS: src/bin/mksh/sh_flags.opt,v 1.2 2014/06/09 12:28:19 tg Exp $");
+#define FN(sname,cname,flags,ochar) static const struct { /* character flag (if any) */ char c; /* OF_* */ unsigned char optflags; /* long name of option */ char name[sizeof(sname)]; } shoptione_ ## cname = { ochar, flags, sname };
+@SHFLAGS_ENUMS
+#define FN(sname,cname,flags,ochar) cname,
+#define F0(sname,cname,flags,ochar) cname = 0,
+@SHFLAGS_ITEMS
+#define FN(sname,cname,flags,ochar) ((const char *)(&shoptione_ ## cname)) + 2,
+@@
+
+/* special cases */
+
+<o:|!SHFLAGS_NOT_CMD
+<T:|!SHFLAGS_NOT_CMD
+<A:|!SHFLAGS_NOT_SET
+<o;|!SHFLAGS_NOT_SET
+<s|!SHFLAGS_NOT_SET
+
+/*
+ * options are sorted by their longnames
+ */
+
+/* -a all new parameters are created with the export attribute */
+>a|
+F0("allexport", FEXPORT, OF_ANY
+
+/* ./. bgnice */
+>| HAVE_NICE
+FN("bgnice", FBGNICE, OF_ANY
+
+/* ./. enable {} globbing (non-standard) */
+>|
+FN("braceexpand", FBRACEEXPAND, OF_ANY
+
+/* ./. Emacs command line editing mode */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("emacs", FEMACS, OF_ANY
+
+/* -e quit on error */
+>e|
+FN("errexit", FERREXIT, OF_ANY
+
+/* ./. Emacs command line editing mode, gmacs variant */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("gmacs", FGMACS, OF_ANY
+
+/* ./. reading EOF does not exit */
+>|
+FN("ignoreeof", FIGNOREEOF, OF_ANY
+
+/* ./. inherit -x flag */
+>|
+FN("inherit-xtrace", FXTRACEREC, OF_ANY
+
+/* -i interactive shell */
+>i|!SHFLAGS_NOT_CMD
+FN("interactive", FTALKING, OF_CMDLINE
+
+/* -k name=value are recognised anywhere */
+>k|
+FN("keyword", FKEYWORD, OF_ANY
+
+/* -l login shell */
+>l|!SHFLAGS_NOT_CMD
+FN("login", FLOGIN, OF_CMDLINE
+
+/* -X mark dirs with / in file name completion */
+>X|
+FN("markdirs", FMARKDIRS, OF_ANY
+
+/* -m job control monitoring */
+>m|!MKSH_UNEMPLOYED
+FN("monitor", FMONITOR, OF_ANY
+
+/* -C don't overwrite existing files */
+>C|
+FN("noclobber", FNOCLOBBER, OF_ANY
+
+/* -n don't execute any commands */
+>n|
+FN("noexec", FNOEXEC, OF_ANY
+
+/* -f don't do file globbing */
+>f|
+FN("noglob", FNOGLOB, OF_ANY
+
+/* ./. don't kill running jobs when login shell exits */
+>|
+FN("nohup", FNOHUP, OF_ANY
+
+/* ./. don't save functions in history (no effect) */
+>|
+FN("nolog", FNOLOG, OF_ANY
+
+/* -b asynchronous job completion notification */
+>b|!MKSH_UNEMPLOYED
+FN("notify", FNOTIFY, OF_ANY
+
+/* -u using an unset variable is an error */
+>u|
+FN("nounset", FNOUNSET, OF_ANY
+
+/* ./. don't do logical cds/pwds (non-standard) */
+>|
+FN("physical", FPHYSICAL, OF_ANY
+
+/* ./. errorlevel of a pipeline is the rightmost nonzero value */
+>|
+FN("pipefail", FPIPEFAIL, OF_ANY
+
+/* ./. adhere more closely to POSIX even when undesirable */
+>|
+FN("posix", FPOSIX, OF_ANY
+
+/* -p privileged shell (suid) */
+>p|
+FN("privileged", FPRIVILEGED, OF_ANY
+
+/* -r restricted shell */
+>r|!SHFLAGS_NOT_CMD
+FN("restricted", FRESTRICTED, OF_CMDLINE
+
+/* ./. kludge mode for better compat with traditional sh (OS-specific) */
+>|
+FN("sh", FSH, OF_ANY
+
+/* -s (invocation) parse stdin (pseudo non-standard) */
+>s|!SHFLAGS_NOT_CMD
+FN("stdin", FSTDIN, OF_CMDLINE
+
+/* -h create tracked aliases for all commands */
+>h|
+FN("trackall", FTRACKALL, OF_ANY
+
+/* -U enable UTF-8 processing (non-standard) */
+>U|
+FN("utf8-mode", FUNICODE, OF_ANY
+
+/* -v echo input */
+>v|
+FN("verbose", FVERBOSE, OF_ANY
+
+/* ./. Vi command line editing mode */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi", FVI, OF_ANY
+
+/* ./. enable ESC as file name completion character (non-standard) */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi-esccomplete", FVIESCCOMPLETE, OF_ANY
+
+/* ./. enable Tab as file name completion character (non-standard) */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("vi-tabcomplete", FVITABCOMPLETE, OF_ANY
+
+/* ./. always read in raw mode (no effect) */
+>|!defined(MKSH_NO_CMDLINE_EDITING) || defined(MKSH_LEGACY_MODE)
+FN("viraw", FVIRAW, OF_ANY
+
+/* -x execution trace (display commands as they are run) */
+>x|
+FN("xtrace", FXTRACE, OF_ANY
+
+/* -c (invocation) execute specified command */
+>c|!SHFLAGS_NOT_CMD
+FN("", FCOMMAND, OF_CMDLINE
+
+/*
+ * anonymous flags: used internally by shell only (not visible to user
+ */
+
+/* ./. direct builtin call (divined from argv[0] multi-call binary) */
+>|
+FN("", FAS_BUILTIN, OF_INTERNAL
+
+/* ./. (internal) initial shell was interactive */
+>|
+FN("", FTALKING_I, OF_INTERNAL
+
+|SHFLAGS_OPTCS
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.61 2013/07/21 18:36:03 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.62 2013/10/09 11:59:30 tg Exp $");
/* flags to shf_emptybuf() */
#define EB_READSW 0x01 /* about to switch to reading */
shf->flags = SHF_ALLOCS;
/* Rest filled in by reopen. */
- fd = open(name, oflags, mode);
+ fd = open(name, oflags | O_BINARY, mode);
if (fd < 0) {
eno = errno;
afree(shf, shf->areap);
--- /dev/null
+ { "ABRT", 6 },
+ { "FPE", 8 },
+ { "ILL", 4 },
+ { "INT", 2 },
+ { "SEGV", 11 },
+ { "TERM", 15 },
+ { "ALRM", 14 },
+ { "BUS", 7 },
+ { "CHLD", 17 },
+ { "CONT", 18 },
+ { "HUP", 1 },
+ { "KILL", 9 },
+ { "PIPE", 13 },
+ { "QUIT", 3 },
+ { "STOP", 19 },
+ { "TSTP", 20 },
+ { "TTIN", 21 },
+ { "TTOU", 22 },
+ { "USR1", 10 },
+ { "USR2", 12 },
+ { "POLL", 29 },
+ { "PROF", 27 },
+ { "SYS", 31 },
+ { "TRAP", 5 },
+ { "URG", 23 },
+ { "VTALRM", 26 },
+ { "XCPU", 24 },
+ { "XFSZ", 25 },
+ { "WINCH", 28 },
+ { "PWR", 30 },
+ { "STKFLT", 16 },
/*-
- * Copyright (c) 2006, 2008, 2009
+ * Copyright (c) 2006, 2008, 2009, 2013
* Thorsten Glaser <tg@mirbsd.org>
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/strlcpy.c,v 1.7 2009/06/10 18:12:50 tg Rel $");
+__RCSID("$MirOS: src/bin/mksh/strlcpy.c,v 1.8 2013/11/05 22:10:15 tg Exp $");
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
+#undef strlcpy
size_t
strlcpy(char *dst, const char *src, size_t siz)
{
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.92 2013/06/03 22:28:17 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.94 2014/01/05 21:57:29 tg Exp $");
struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */
static void nesting_push(struct nesting_state *, int);
static void nesting_pop(struct nesting_state *);
static int assign_command(const char *);
-static int inalias(struct source *);
+static int inalias(struct source *) MKSH_A_PURE;
static Test_op dbtestp_isa(Test_env *, Test_meta);
static const char *dbtestp_getopnd(Test_env *, Test_op, bool);
static int dbtestp_eval(Test_env *, Test_op, const char *,
dbtestp_isa(Test_env *te, Test_meta meta)
{
int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN));
- int uqword;
+ bool uqword;
char *save = NULL;
Test_op ret = TO_NONOP;
#include "sh.h"
-__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.71 2013/07/26 20:33:24 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.72 2013/09/24 20:19:45 tg Exp $");
#define INDENT 8
if (--sz == 0 || (c = (unsigned char)(*cp++)) == 0)
/* NUL or not enough free space */
goto vist_out;
- if ((c & 0x60) == 0 || (c & 0x7F) == 0x7F) {
+ if (ISCTRL(c & 0x7F)) {
/* C0 or C1 control character or DEL */
if (--sz == 0)
/* not enough free space for two chars */
goto vist_out;
*dst++ = (c & 0x80) ? '$' : '^';
- c = (c & 0x7F) ^ 0x40;
+ c = UNCTRL(c & 0x7F);
} else if (UTFMODE && c > 0x7F) {
/* better not try to display broken multibyte chars */
+ /* also go easy on the Unicode: no U+FFFD here */
c = '?';
}
*dst++ = c;
void
dumpchar(struct shf *shf, int c)
{
- if (((c & 0x60) == 0) || ((c & 0x7F) == 0x7F)) {
+ if (ISCTRL(c & 0x7F)) {
/* C0 or C1 control character or DEL */
shf_putc((c & 0x80) ? '$' : '^', shf);
- c = (c & 0x7F) ^ 0x40;
+ c = UNCTRL(c & 0x7F);
}
shf_putc(c, shf);
}
-/* $OpenBSD: var.c,v 1.35 2013/04/05 01:31:30 tedu Exp $ */
+/* $OpenBSD: var.c,v 1.38 2013/12/20 17:53:09 zhuk Exp $ */
/*-
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- * 2011, 2012, 2013
+ * 2011, 2012, 2013, 2014
* Thorsten Glaser <tg@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
*/
#include "sh.h"
+#include "mirhash.h"
#if defined(__OpenBSD__)
#include <sys/sysctl.h>
#endif
-__RCSID("$MirOS: src/bin/mksh/var.c,v 1.173 2013/05/31 22:47:14 tg Exp $");
+__RCSID("$MirOS: src/bin/mksh/var.c,v 1.180 2014/06/26 20:36:02 tg Exp $");
/*-
* Variables
*/
static struct table specials;
-static uint32_t lcg_state = 5381;
+static uint32_t lcg_state = 5381, qh_state = 4711;
+/* may only be set by typeset() just before call to array_index_calc() */
+static enum namerefflag innermost_refflag = SRF_NOP;
static char *formatstr(struct tbl *, const char *);
static void exportprep(struct tbl *, const char *);
/*
* Used to calculate an array index for global()/local(). Sets *arrayp
* to true if this is an array, sets *valp to the array index, returns
- * the basename of the array.
+ * the basename of the array. May only be called from global()/local()
+ * and must be their first callee.
*/
static const char *
array_index_calc(const char *n, bool *arrayp, uint32_t *valp)
*arrayp = false;
redo_from_ref:
p = skip_varname(n, false);
- if (set_refflag == SRF_NOP && (p != n) && ksh_isalphx(n[0])) {
+ if (innermost_refflag == SRF_NOP && (p != n) && ksh_isalphx(n[0])) {
struct tbl *vp;
char *vn;
/* check if this is a reference */
varsearch(e->loc, &vp, vn, hash(vn));
afree(vn, ATEMP);
- if (vp && (vp->flag & (DEFINED|ASSOC|ARRAY)) ==
- (DEFINED|ASSOC)) {
+ if (vp && (vp->flag & (DEFINED | ASSOC | ARRAY)) ==
+ (DEFINED | ASSOC)) {
char *cp;
/* gotcha! */
goto redo_from_ref;
}
}
+ innermost_refflag = SRF_NOP;
if (p != n && *p == '[' && (len = array_ref_len(p))) {
char *sub, *tmp;
bool array;
uint32_t h, val;
- /* Check to see if this is an array */
+ /*
+ * check to see if this is an array;
+ * dereference namerefs; must come first
+ */
n = array_index_calc(n, &array, &val);
h = hash(n);
- c = n[0];
+ c = (unsigned char)n[0];
if (!ksh_isalphx(c)) {
if (array)
errorf("bad substitution");
vp->areap = ATEMP;
*vp->name = c;
if (ksh_isdigit(c)) {
- for (c = 0; ksh_isdigit(*n); n++)
- c = c*10 + *n-'0';
- if (c <= l->argc)
+ if (getn(n, &c) && (c <= l->argc))
/* setstr can't fail here */
setstr(vp, l->argv[c], KSH_RETURN_ERROR);
vp->flag |= RDONLY;
bool array;
uint32_t h, val;
- /* check to see if this is an array */
+ /*
+ * check to see if this is an array;
+ * dereference namerefs; must come first
+ */
n = array_index_calc(n, &array, &val);
mkssert(n != NULL);
h = hash(n);
base = 8;
have_base = true;
}
- while ((c = *s++)) {
+ while ((c = (unsigned char)*s++)) {
if (c == '-') {
neg = true;
continue;
const char *val;
size_t len;
bool vappend = false;
+ enum namerefflag new_refflag = SRF_NOP;
+
+ if ((set & (ARRAY | ASSOC)) == ASSOC) {
+ new_refflag = SRF_ENABLE;
+ set &= ~(ARRAY | ASSOC);
+ }
+ if ((clr & (ARRAY | ASSOC)) == ASSOC) {
+ new_refflag = SRF_DISABLE;
+ clr &= ~(ARRAY | ASSOC);
+ }
/* check for valid variable name, search for value */
val = skip_varname(var, false);
return (NULL);
}
if (*val == '[') {
- if (set_refflag != SRF_NOP)
+ if (new_refflag != SRF_NOP)
errorf("%s: %s", var,
"reference variable can't be an array");
len = array_ref_len(val);
tvar[len - 3] = '\0';
}
- if (set_refflag == SRF_ENABLE) {
- const char *qval;
+ if (new_refflag == SRF_ENABLE) {
+ const char *qval, *ccp;
/* bail out on 'nameref foo+=bar' */
if (vappend)
- errorfz();
+ errorf("appending not allowed for nameref");
/* find value if variable already exists */
if ((qval = val) == NULL) {
varsearch(e->loc, &vp, tvar, hash(tvar));
if (vp != NULL)
qval = str_val(vp);
}
+ /* check target value for being a valid variable name */
+ ccp = skip_varname(qval, false);
+ if (ccp == qval)
+ errorf("%s: %s", var, "empty nameref target");
+ len = (*ccp == '[') ? array_ref_len(ccp) : 0;
+ if (ccp[len]) {
+ /*
+ * works for cases "no array", "valid array with
+ * junk after it" and "invalid array"; in the
+ * latter case, len is also 0 and points to '['
+ */
+ errorf("%s: %s", qval,
+ "nameref target not a valid parameter name");
+ }
/* prevent nameref loops */
while (qval) {
if (!strcmp(qval, tvar))
"expression recurses on parameter");
varsearch(e->loc, &vp, qval, hash(qval));
qval = NULL;
- if (vp && ((vp->flag & (ARRAY|ASSOC)) == ASSOC))
+ if (vp && ((vp->flag & (ARRAY | ASSOC)) == ASSOC))
qval = str_val(vp);
}
}
strcmp(tvar, "ENV") == 0 || strcmp(tvar, "SHELL") == 0))
errorf("%s: %s", tvar, "restricted");
- vp = (set&LOCAL) ? local(tvar, tobool(set & LOCAL_COPY)) :
+ innermost_refflag = new_refflag;
+ vp = (set & LOCAL) ? local(tvar, tobool(set & LOCAL_COPY)) :
global(tvar);
- if (set_refflag == SRF_DISABLE && (vp->flag & (ARRAY|ASSOC)) == ASSOC)
+ if (new_refflag == SRF_DISABLE && (vp->flag & (ARRAY|ASSOC)) == ASSOC)
vp->flag &= ~ASSOC;
- else if (set_refflag == SRF_ENABLE) {
+ else if (new_refflag == SRF_ENABLE) {
if (vp->flag & ARRAY) {
struct tbl *a, *tmp;
set &= ~(LOCAL|LOCAL_COPY);
- vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp;
+ vpbase = (vp->flag & ARRAY) ? global(arrayname(tvar)) : vp;
/*
* only allow export flag to be set; AT&T ksh allows any
* attribute to be changed which means it can be truncated or
* modified (-L/-R/-Z/-i)
*/
- if ((vpbase->flag&RDONLY) &&
+ if ((vpbase->flag & RDONLY) &&
(val || clr || (set & ~EXPORT)))
/* XXX check calls - is error here ok by POSIX? */
errorfx(2, "read-only: %s", tvar);
* the terminating NUL if whole string is legal).
*/
const char *
-skip_varname(const char *s, int aok)
+skip_varname(const char *s, bool aok)
{
size_t alen;
struct tbl *prev, *curr, *news;
size_t len;
- vp->flag = (vp->flag | (ARRAY|DEFINED)) & ~ASSOC;
+ vp->flag = (vp->flag | (ARRAY | DEFINED)) & ~ASSOC;
/* the table entry is always [0] */
if (val == 0)
return (vp);
* Return the length of an array reference (eg, [1+2]) - cp is assumed
* to point to the open bracket. Returns 0 if there is no matching
* closing bracket.
+ *
+ * XXX this should parse the actual arithmetic syntax
*/
size_t
array_ref_len(const char *cp)
afree(cp, ATEMP);
}
while ((ccp = vals[i])) {
+#if 0 /* temporarily taken out due to regression */
if (*ccp == '[') {
int level = 0;
} else
ccp = vals[i];
}
+#endif
vq = arraysearch(vp, j);
/* would be nice to deal with errors here... (see above) */
void
change_winsz(void)
{
+ struct timeval tv;
+
+ mksh_TIME(tv);
+ BAFHUpdateMem_mem(qh_state, &tv, sizeof(tv));
+
#ifdef TIOCGWINSZ
/* check if window size has changed */
if (tty_init_fd() < 2) {
{
register uint32_t h;
- NZATInit(h);
- NZATUpdateString(h, s);
- NZAATFinish(h);
+ BAFHInit(h);
+ BAFHUpdateStr_reg(h, s);
+ BAFHFinish_reg(h);
+ return (h);
+}
+
+uint32_t
+chvt_rndsetup(const void *bp, size_t sz)
+{
+ register uint32_t h;
+
+ /* use LCG as seed but try to get them to deviate immediately */
+ h = lcg_state;
+ (void)rndget();
+ BAFHFinish_reg(h);
+ /* variation through pid, ppid, and the works */
+ BAFHUpdateMem_reg(h, &rndsetupstate, sizeof(rndsetupstate));
+ /* some variation, some possibly entropy, depending on OE */
+ BAFHUpdateMem_reg(h, bp, sz);
+ /* mix them all up */
+ BAFHFinish_reg(h);
+
return (h);
}
rndset(unsigned long v)
{
register uint32_t h;
+#if defined(arc4random_pushb_fast) || defined(MKSH_A4PB)
+ register uint32_t t;
+#endif
+ struct {
+ struct timeval tv;
+ void *sp;
+ uint32_t qh;
+ pid_t pp;
+ short r;
+ } z;
+
+#ifdef DEBUG
+ /* clear the allocated space, for valgrind */
+ memset(&z, 0, sizeof(z));
+#endif
- NZATInit(h);
- NZATUpdateMem(h, &lcg_state, sizeof(lcg_state));
- NZATUpdateMem(h, &v, sizeof(v));
+ h = lcg_state;
+ BAFHFinish_reg(h);
+ BAFHUpdateMem_reg(h, &v, sizeof(v));
+
+ mksh_TIME(z.tv);
+ z.sp = &lcg_state;
+ z.pp = procpid;
+ z.r = (short)rndget();
#if defined(arc4random_pushb_fast) || defined(MKSH_A4PB)
+ t = qh_state;
+ BAFHFinish_reg(t);
+ z.qh = (t & 0xFFFF8000) | rndget();
+ lcg_state = (t << 15) | rndget();
/*
* either we have very chap entropy get and push available,
* with malloc() pulling in this code already anyway, or the
* user requested us to use the old functions
*/
- lcg_state = h;
- NZAATFinish(lcg_state);
+ t = h;
+ BAFHUpdateMem_reg(t, &lcg_state, sizeof(lcg_state));
+ BAFHFinish_reg(t);
+ lcg_state = t;
#if defined(arc4random_pushb_fast)
arc4random_pushb_fast(&lcg_state, sizeof(lcg_state));
lcg_state = arc4random();
#else
lcg_state = arc4random_pushb(&lcg_state, sizeof(lcg_state));
#endif
- NZATUpdateMem(h, &lcg_state, sizeof(lcg_state));
+ BAFHUpdateMem_reg(h, &lcg_state, sizeof(lcg_state));
+#else
+ z.qh = qh_state;
#endif
- NZAATFinish(h);
+ BAFHUpdateMem_reg(h, &z, sizeof(z));
+ BAFHFinish_reg(h);
lcg_state = h;
}
+
+void
+rndpush(const void *s)
+{
+ register uint32_t h = qh_state;
+
+ BAFHUpdateStr_reg(h, s);
+ BAFHUpdateOctet_reg(h, 0);
+ qh_state = h;
+}