Upgrade mksh to mksh-R59c

Test: TreeHugger
Change-Id: I6d4f4497e54fd97672ee0d634b322277326a9748
This commit is contained in:
Sadaf Ebrahimi 2023-03-31 18:17:33 +00:00
parent e249d87246
commit b02792c9ac
28 changed files with 934 additions and 528 deletions

View file

@ -38,6 +38,7 @@ cc_defaults {
"src/shf.c", "src/shf.c",
"src/syn.c", "src/syn.c",
"src/tree.c", "src/tree.c",
"src/ulimit.c",
"src/var.c", "src/var.c",
], ],
@ -125,7 +126,7 @@ cc_defaults {
"-DHAVE_SYS_ERRLIST_DECL=0", "-DHAVE_SYS_ERRLIST_DECL=0",
"-DHAVE_SYS_SIGLIST_DECL=1", "-DHAVE_SYS_SIGLIST_DECL=1",
"-DHAVE_PERSISTENT_HISTORY=0", "-DHAVE_PERSISTENT_HISTORY=0",
"-DMKSH_BUILD_R=592", "-DMKSH_BUILD_R=593",
// Additional flags // Additional flags
"-DMKSH_DEFAULT_PROFILEDIR=\"/system/etc\"", "-DMKSH_DEFAULT_PROFILEDIR=\"/system/etc\"",

View file

@ -1,8 +1,7 @@
Only in src: FAQ.htm diff -u mksh-R59c/mksh/funcs.c src/funcs.c
diff -u mksh-R59b/funcs.c src/funcs.c --- mksh-R59c/mksh/funcs.c 2020-08-27 19:53:11.000000000 +0000
--- mksh-R59b/funcs.c 2020-05-16 15:38:48.000000000 -0700 +++ src/funcs.c 2023-03-31 18:02:12.376044783 +0000
+++ src/funcs.c 2020-05-20 17:14:19.588510856 -0700 @@ -98,7 +98,9 @@
@@ -104,7 +104,9 @@
{Tsgbreak, c_brkcont}, {Tsgbreak, c_brkcont},
{T__builtin, c_builtin}, {T__builtin, c_builtin},
{Tbuiltin, c_builtin}, {Tbuiltin, c_builtin},
@ -12,7 +11,7 @@ diff -u mksh-R59b/funcs.c src/funcs.c
{Tcd, c_cd}, {Tcd, c_cd},
/* dash compatibility hack */ /* dash compatibility hack */
{"chdir", c_cd}, {"chdir", c_cd},
@@ -125,7 +127,9 @@ @@ -119,7 +121,9 @@
{"pwd", c_pwd}, {"pwd", c_pwd},
{Tread, c_read}, {Tread, c_read},
{Tdsgreadonly, c_typeset}, {Tdsgreadonly, c_typeset},
@ -22,7 +21,7 @@ diff -u mksh-R59b/funcs.c src/funcs.c
{"~rename", c_rename}, {"~rename", c_rename},
{"*=return", c_exitreturn}, {"*=return", c_exitreturn},
{Tsghset, c_set}, {Tsghset, c_set},
@@ -159,8 +163,10 @@ @@ -153,8 +157,10 @@
{"~printf", c_printf}, {"~printf", c_printf},
#endif #endif
#if HAVE_SELECT #if HAVE_SELECT
@ -33,25 +32,22 @@ diff -u mksh-R59b/funcs.c src/funcs.c
#ifdef __MirBSD__ #ifdef __MirBSD__
/* alias to "true" for historical reasons */ /* alias to "true" for historical reasons */
{"domainname", c_true}, {"domainname", c_true},
diff -u mksh-R59b/main.c src/main.c diff -u mksh-R59c/mksh/main.c src/main.c
--- mksh-R59b/main.c 2020-05-16 15:51:51.000000000 -0700 --- mksh-R59c/mksh/main.c 2020-10-01 20:29:21.000000000 +0000
+++ src/main.c 2020-05-20 17:14:19.588510856 -0700 +++ src/main.c 2023-03-31 18:09:32.827660886 +0000
@@ -414,6 +414,12 @@ @@ -413,6 +413,12 @@
/* import environment */ /* import environment */
init_environ(); init_environ();
+
+ /* override default PATH regardless of environment */ + /* override default PATH regardless of environment */
+#ifdef MKSH_DEFPATH_OVERRIDE +#ifdef MKSH_DEFPATH_OVERRIDE
+ vp = global(TPATH); + vp = global(TPATH);
+ setstr(vp, MKSH_DEFPATH_OVERRIDE, KSH_RETURN_ERROR); + setstr(vp, MKSH_DEFPATH_OVERRIDE, KSH_RETURN_ERROR);
+#endif +#endif
+
/* for security */ /* for security */
typeset(TinitIFS, 0, 0, 0, 0); typeset(TinitIFS, 0, 0, 0, 0);
Only in src/: rlimits.gen
Only in src: main.c.orig Only in src/: sh_flags.gen
Only in src: Rebuild.sh Only in src/: ulimits.gen
Only in src: rlimits.gen
Only in src: sh_flags.gen
Only in src: signames.inc
Only in src: test.sh

View file

@ -1,3 +1,18 @@
name: "mksh"
third_party { third_party {
url {
type: HOMEPAGE
value: "http://www.mirbsd.org/mksh"
}
url {
type: ARCHIVE
value: "http://www.mirbsd.org/MirOS/dist/mir/mksh/mksh-R59c.tgz"
}
version: "mksh-R59c"
license_type: NOTICE license_type: NOTICE
last_upgrade_date {
year: 2023
month: 3
day: 31
}
} }

View file

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.756 2020/05/16 22:53:03 tg Exp $' srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.763 2020/09/04 21:01:37 tg Exp $'
#- #-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, # 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
@ -721,6 +721,13 @@ case $TARGET_OS in
add_cppflags -DMKSH_NO_SIGSETJMP add_cppflags -DMKSH_NO_SIGSETJMP
add_cppflags -DMKSH_TYPEDEF_SIG_ATOMIC_T=int add_cppflags -DMKSH_TYPEDEF_SIG_ATOMIC_T=int
;; ;;
A/UX)
add_cppflags -D_POSIX_SOURCE
: "${CC=gcc}"
: "${LIBS=-lposix}"
# GCC defines AUX but cc nothing
add_cppflags -D__A_UX__
;;
AIX) AIX)
add_cppflags -D_ALL_SOURCE add_cppflags -D_ALL_SOURCE
: "${HAVE_SETLOCALE_CTYPE=0}" : "${HAVE_SETLOCALE_CTYPE=0}"
@ -862,10 +869,9 @@ Minix-vmd)
;; ;;
Minix3) Minix3)
add_cppflags -DMKSH_UNEMPLOYED add_cppflags -DMKSH_UNEMPLOYED
add_cppflags -DMKSH_NO_LIMITS
add_cppflags -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2 -D_MINIX add_cppflags -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2 -D_MINIX
oldish_ed=no-stderr-ed # /usr/bin/ed(!) is broken oldish_ed=no-stderr-ed # /usr/bin/ed(!) is broken
: "${HAVE_SETLOCALE_CTYPE=0}" : "${HAVE_SETLOCALE_CTYPE=0}${MKSH_UNLIMITED=1}" #XXX recheck ulimit
;; ;;
MirBSD) MirBSD)
;; ;;
@ -898,7 +904,7 @@ NEXTSTEP)
Ninix3) Ninix3)
# similar to Minix3 # similar to Minix3
add_cppflags -DMKSH_UNEMPLOYED add_cppflags -DMKSH_UNEMPLOYED
add_cppflags -DMKSH_NO_LIMITS : "${MKSH_UNLIMITED=1}" #XXX recheck ulimit
# but no idea what else could be needed # but no idea what else could be needed
oswarn="; it has unknown issues" oswarn="; it has unknown issues"
;; ;;
@ -911,15 +917,14 @@ OS/2)
HAVE_ISOFF_MKSH_ASSUME_UTF8=1 HAVE_ISOFF_MKSH_ASSUME_UTF8=1
HAVE_TERMIOS_H=0 HAVE_TERMIOS_H=0
HAVE_MKNOD=0 # setmode() incompatible HAVE_MKNOD=0 # setmode() incompatible
oswarn="; it is being ported"
check_categories="$check_categories nosymlink" check_categories="$check_categories nosymlink"
: "${CC=gcc}" : "${CC=gcc}"
: "${SIZE=: size}" : "${SIZE=: size}"
SRCS="$SRCS os2.c" SRCS="$SRCS os2.c"
add_cppflags -DMKSH_UNEMPLOYED add_cppflags -DMKSH_UNEMPLOYED
add_cppflags -DMKSH_NOPROSPECTOFWORK add_cppflags -DMKSH_NOPROSPECTOFWORK
add_cppflags -DMKSH_NO_LIMITS
add_cppflags -DMKSH_DOSPATH add_cppflags -DMKSH_DOSPATH
: "${MKSH_UNLIMITED=1}"
if test $textmode = 0; then if test $textmode = 0; then
x='dis' x='dis'
y='standard OS/2 tools' y='standard OS/2 tools'
@ -1363,7 +1368,7 @@ esac
etd=" on $et" etd=" on $et"
case $et in case $et in
klibc) klibc)
add_cppflags -DMKSH_NO_LIMITS : "${MKSH_UNLIMITED=1}"
;; ;;
unknown) unknown)
# nothing special detected, dont worry # nothing special detected, dont worry
@ -1898,23 +1903,6 @@ ac_test can_ucbint8 '!' can_int8type 1 "for UCB 8-bit integer type" <<-'EOF'
int main(int ac, char *av[]) { return ((u_int8_t)(size_t)av[ac]); } int main(int ac, char *av[]) { return ((u_int8_t)(size_t)av[ac]); }
EOF EOF
ac_test rlim_t <<-'EOF'
#include <sys/types.h>
#if HAVE_BOTH_TIME_H
#include <sys/time.h>
#include <time.h>
#elif HAVE_SYS_TIME_H
#include <sys/time.h>
#elif HAVE_TIME_H
#include <time.h>
#endif
#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <unistd.h>
int main(void) { return (((int)(rlim_t)0) + isatty(0)); }
EOF
# only testn: added later below # only testn: added later below
ac_testn sig_t <<-'EOF' ac_testn sig_t <<-'EOF'
#include <sys/types.h> #include <sys/types.h>
@ -2067,6 +2055,35 @@ ac_test lock_fcntl '!' flock 1 'whether we can lock files with fcntl' <<-'EOF'
} }
EOF EOF
ac_test rlimit '' 'getrlimit and setrlimit' <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
int main(void) {
struct rlimit l;
if (getrlimit(0, &l)) return 1;
l.rlim_max = l.rlim_cur;
l.rlim_cur = RLIM_INFINITY;
return (setrlimit(0, &l));
}
EOF
ac_test rlim_t rlimit 0 <<-'EOF'
#include <sys/types.h>
#if HAVE_BOTH_TIME_H
#include <sys/time.h>
#include <time.h>
#elif HAVE_SYS_TIME_H
#include <sys/time.h>
#elif HAVE_TIME_H
#include <time.h>
#endif
#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <unistd.h>
int main(void) { return (((int)(rlim_t)0) + isatty(0)); }
EOF
ac_test getrusage <<-'EOF' ac_test getrusage <<-'EOF'
#define MKSH_INCLUDES_ONLY #define MKSH_INCLUDES_ONLY
#include "sh.h" #include "sh.h"
@ -2457,11 +2474,24 @@ mksh_cfg= cfg_NSIG
$e done. $e done.
fi fi
if test 1 = "$MKSH_UNLIMITED"; then
add_cppflags -DMKSH_UNLIMITED
else
MKSH_UNLIMITED=0
fi
if test 1 = "$USE_PRINTF_BUILTIN"; then
add_cppflags -DMKSH_PRINTF_BUILTIN
else
USE_PRINTF_BUILTIN=0
fi
addsrcs '!' HAVE_STRLCPY strlcpy.c addsrcs '!' HAVE_STRLCPY strlcpy.c
addsrcs USE_PRINTF_BUILTIN printf.c addsrcs USE_PRINTF_BUILTIN printf.c
test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN addsrcs '!' MKSH_UNLIMITED ulimit.c
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose" test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
add_cppflags -DMKSH_BUILD_R=592 add_cppflags -DMKSH_BUILD_R=593
$e $bi$me: Finished configuration testing, now producing output.$ao $e $bi$me: Finished configuration testing, now producing output.$ao
@ -2544,7 +2574,7 @@ cat >test.sh <<-EOF
args[\${#args[*]}]=\$TMPDIR args[\${#args[*]}]=\$TMPDIR
fi fi
print Testing mksh for conformance: print Testing mksh for conformance:
grep -F -e Mir''OS: -e MIRBSD "\$sflag" grep -F -e 'KSH R' -e Mir''OS: "\$sflag" | sed '/KSH/s/^./& /'
print "This shell is actually:\\n\\t\$KSH_VERSION" print "This shell is actually:\\n\\t\$KSH_VERSION"
print 'test.sh built for mksh $dstversion' print 'test.sh built for mksh $dstversion'
cstr='\$os = defined \$^O ? \$^O : "unknown";' cstr='\$os = defined \$^O ? \$^O : "unknown";'
@ -2604,7 +2634,6 @@ for file in $SRCS; do
op=`echo x"$file" | sed 's/^x\(.*\)\.c$/\1./'` op=`echo x"$file" | sed 's/^x\(.*\)\.c$/\1./'`
test -f $file || file=$srcdir/$file test -f $file || file=$srcdir/$file
files="$files$sp$file" files="$files$sp$file"
sp=' '
echo "$CC $CFLAGS $CPPFLAGS $emitbc $file || exit 1" >>Rebuild.sh echo "$CC $CFLAGS $CPPFLAGS $emitbc $file || exit 1" >>Rebuild.sh
if test $cm = dragonegg; then if test $cm = dragonegg; then
echo "mv ${op}s ${op}ll" >>Rebuild.sh echo "mv ${op}s ${op}ll" >>Rebuild.sh
@ -2613,6 +2642,7 @@ for file in $SRCS; do
else else
objs="$objs$sp${op}o" objs="$objs$sp${op}o"
fi fi
sp=' '
done done
case $cm in case $cm in
dragonegg|llvm) dragonegg|llvm)
@ -2628,7 +2658,7 @@ echo tcfn=$mkshexe >>Rebuild.sh
echo "$CC $CFLAGS $LDFLAGS -o \$tcfn $lobjs $LIBS $ccpr" >>Rebuild.sh echo "$CC $CFLAGS $LDFLAGS -o \$tcfn $lobjs $LIBS $ccpr" >>Rebuild.sh
echo "test -f \$tcfn || exit 1; $SIZE \$tcfn" >>Rebuild.sh echo "test -f \$tcfn || exit 1; $SIZE \$tcfn" >>Rebuild.sh
if test $cm = makefile; then if test $cm = makefile; then
extras='emacsfn.h exprtok.h rlimits.opt sh.h sh_flags.opt var_spec.h' extras='emacsfn.h exprtok.h rlimits.opt sh.h sh_flags.opt ulimits.opt var_spec.h'
test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc" test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc"
gens= genq= gens= genq=
for file in $optfiles; do for file in $optfiles; do
@ -2734,11 +2764,11 @@ if test $legacy = 0; then
fi fi
$e $e
$e Installing the manual: $e Installing the manual:
if test -e FAQ.htm; then if test -f FAQ.htm; then
$e "# $i -c -o root -g bin -m 444 FAQ.htm /usr/share/doc/mksh/" $e "# $i -c -o root -g bin -m 444 FAQ.htm /usr/share/doc/mksh/"
fi fi
if test -f mksh.cat1; then if test -f mksh.cat1; then
if test -e FAQ.htm; then if test -f FAQ.htm; then
$e plus either $e plus either
fi fi
$e "# $i -c -o root -g bin -m 444 lksh.cat1" \ $e "# $i -c -o root -g bin -m 444 lksh.cat1" \
@ -2751,7 +2781,7 @@ $e "# $i -c -o root -g bin -m 444 lksh.1 mksh.1 /usr/share/man/man1/"
$e $e
$e Run the regression test suite: ./test.sh $e Run the regression test suite: ./test.sh
$e Please also read the sample file dot.mkshrc and the fine manual. $e Please also read the sample file dot.mkshrc and the fine manual.
test -e FAQ.htm || \ test -f FAQ.htm || \
$e Run FAQ2HTML.sh and place FAQ.htm into a suitable location as well. $e Run FAQ2HTML.sh and place FAQ.htm into a suitable location as well.
exit 0 exit 0
@ -2775,6 +2805,7 @@ TARGET_OS default: $(uname -s || uname)
TARGET_OSREV [QNX] default: $(uname -r) TARGET_OSREV [QNX] default: $(uname -r)
==== feature selectors ==== ==== feature selectors ====
MKSH_UNLIMITED 1 to omit ulimit builtin completely
USE_PRINTF_BUILTIN 1 to include (unsupported) printf(1) as builtin USE_PRINTF_BUILTIN 1 to include (unsupported) printf(1) as builtin
===== general format ===== ===== general format =====
HAVE_STRLEN ac_test HAVE_STRLEN ac_test
@ -2782,7 +2813,7 @@ HAVE_STRING_H ac_header
HAVE_CAN_FSTACKPROTECTORALL ac_flags HAVE_CAN_FSTACKPROTECTORALL ac_flags
==== cpp definitions ==== ==== cpp definitions ====
DEBUG dont use in production, wants gcc, implies: DEBUG dont use in production, wants gcc, implies:
DEBUG_LEAKS enable freeing resources before exiting DEBUG_LEAKS enable freeing resources before exiting
KSH_VERSIONNAME_VENDOR_EXT when patching; space+plus+word (e.g. " +SuSE") KSH_VERSIONNAME_VENDOR_EXT when patching; space+plus+word (e.g. " +SuSE")
MKSHRC_PATH "~/.mkshrc" (do not change) MKSHRC_PATH "~/.mkshrc" (do not change)
@ -2804,7 +2835,6 @@ MKSH_NOPROSPECTOFWORK disable jobs, co-processes, etc. (do not use)
MKSH_NOPWNAM skip PAM calls, for -static on glibc or Solaris MKSH_NOPWNAM skip PAM calls, for -static on glibc or Solaris
MKSH_NO_CMDLINE_EDITING disable command line editing code entirely MKSH_NO_CMDLINE_EDITING disable command line editing code entirely
MKSH_NO_DEPRECATED_WARNING omit warning when deprecated stuff is run MKSH_NO_DEPRECATED_WARNING omit warning when deprecated stuff is run
MKSH_NO_LIMITS omit ulimit code
MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available
MKSH_NO_SIGSUSPEND use sigprocmask+pause instead of sigsuspend MKSH_NO_SIGSUSPEND use sigprocmask+pause instead of sigsuspend
MKSH_SMALL omit some code, optimise hard for size (slower) MKSH_SMALL omit some code, optimise hard for size (slower)

View file

@ -1,5 +1,5 @@
#!/bin/mksh #!/bin/sh
rcsid='$MirOS: src/bin/mksh/FAQ2HTML.sh,v 1.1 2020/02/03 22:23:33 tg Exp $' rcsid='$MirOS: src/bin/mksh/FAQ2HTML.sh,v 1.2 2020/10/31 04:17:36 tg Exp $'
#- #-
# Copyright © 2020 # Copyright © 2020
# mirabilos <m@mirbsd.org> # mirabilos <m@mirbsd.org>
@ -37,7 +37,7 @@ fi
src_id=$(sed $p -n '/^RCSID: /s///p' "$srcdir"/mksh.faq) src_id=$(sed $p -n '/^RCSID: /s///p' "$srcdir"/mksh.faq)
# sanity check # sanity check
case $src_id in case $src_id in
(*"$nl"*) *"$nl"*)
echo >&2 "E: more than one RCSID in mksh.faq?" echo >&2 "E: more than one RCSID in mksh.faq?"
exit 1 ;; exit 1 ;;
esac esac

View file

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.pl,v 1.50 2019/08/01 20:05:55 tg Exp $ # $MirOS: src/bin/mksh/check.pl,v 1.51 2020/06/22 17:10:59 tg Exp $
# $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $ # $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $
#- #-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
@ -55,7 +55,7 @@
# default is no arguments. # default is no arguments.
# script m Value is written to a file which # script m Value is written to a file which
# is passed as an argument to the program # is passed as an argument to the program
# (after the arguments arguments) # (after the arguments from arguments)
# stdin m Value is written to a file which is # stdin m Value is written to a file which is
# used as standard-input for the program; # used as standard-input for the program;
# default is to use /dev/null. # default is to use /dev/null.
@ -195,7 +195,7 @@ Usage: $prog [-Pv] [-C cat] [-e e=v] [-p prog] [-s fn] [-T dir] \
the path (kludge option) the path (kludge option)
-p p Use p as the program to test -p p Use p as the program to test
-s s Read tests from file s; if s is a directory, it is recursively -s s Read tests from file s; if s is a directory, it is recursively
scaned for test files (which end in .t). scanned for test files (which end in .t).
-T dir Use dir instead of /tmp to hold temporary files -T dir Use dir instead of /tmp to hold temporary files
-t t Use t as default time limit for tests (default is unlimited) -t t Use t as default time limit for tests (default is unlimited)
-U lcl Use lcl as UTF-8 locale (e.g. C.UTF-8) instead of the default -U lcl Use lcl as UTF-8 locale (e.g. C.UTF-8) instead of the default

View file

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.845 2020/05/16 22:19:15 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.853 2020/10/31 03:53:03 tg Exp $
# -*- mode: sh -*- # -*- mode: sh -*-
#- #-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -31,7 +31,7 @@
# (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date # (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout: expected-stdout:
KSH R59 2020/05/16 KSH R59 2020/10/31
description: description:
Check base version of full shell Check base version of full shell
stdin: stdin:
@ -6109,7 +6109,7 @@ expected-stderr-pattern: /does\/not\/exist/
--- ---
name: regression-28 name: regression-28
description: description:
variable assignements not detected well variable assignments not detected well
stdin: stdin:
a.x=1 echo hi a.x=1 echo hi
expected-exit: e != 0 expected-exit: e != 0
@ -6184,7 +6184,7 @@ expected-stdout:
--- ---
name: regression-35 name: regression-35
description: description:
Tempory files used for here-docs in functions get trashed after Temporay files used for here-docs in functions get trashed after
the function is parsed (before it is executed) the function is parsed (before it is executed)
stdin: stdin:
f1() { f1() {
@ -7457,7 +7457,7 @@ expected-stdout:
name: xxx-param-subst-qmark-1 name: xxx-param-subst-qmark-1
description: description:
Check suppresion of error message with null string. According to Check suppresion of error message with null string. According to
POSIX, it shouldn't print the error as 'word' isn't ommitted. POSIX, it shouldn't print the error as 'word' isn't omitted.
ksh88/93, Solaris /bin/sh and /usr/xpg4/bin/sh all print the error. ksh88/93, Solaris /bin/sh and /usr/xpg4/bin/sh all print the error.
stdin: stdin:
unset foo unset foo
@ -8853,9 +8853,10 @@ description:
XXX if the OS can already execute them, we lose XXX if the OS can already execute them, we lose
note: cygwin execve(2) doesn't return to us with ENOEXEC, we lose note: cygwin execve(2) doesn't return to us with ENOEXEC, we lose
note: Ultrix perl5 t4 returns 65280 (exit-code 255) and no text note: Ultrix perl5 t4 returns 65280 (exit-code 255) and no text
note: A/UX perl5 returns 6400 (exit-code 25), passes #1-3
XXX fails when LD_PRELOAD is set with -e and Perl chokes it (ASan) XXX fails when LD_PRELOAD is set with -e and Perl chokes it (ASan)
need-pass: no need-pass: no
category: !os:cygwin,!os:midipix,!os:msys,!os:ultrix,!os:uwin-nt,!smksh category: !os:aux,!os:cygwin,!os:midipix,!os:msys,!os:ultrix,!os:uwin-nt,!smksh
env-setup: !FOO=BAR! env-setup: !FOO=BAR!
stdin: stdin:
print '#!'"$__progname"'\nprint "1 a=$ENV{FOO}";' >t1 print '#!'"$__progname"'\nprint "1 a=$ENV{FOO}";' >t1
@ -11489,13 +11490,11 @@ name: fd-cloexec-1
description: description:
Verify that file descriptors > 2 are private for Korn shells Verify that file descriptors > 2 are private for Korn shells
AT&T ksh93 does this still, which means we must keep it as well AT&T ksh93 does this still, which means we must keep it as well
XXX fails on some old Perl installations
need-pass: no
stdin: stdin:
cat >cld <<-EOF cat >cld <<-EOF
#!$__perlname #!$__perlname
open(my \$fh, ">&", 9) or die "E: open \$!"; open(FH, ">&9") or die "E: open \$!";
syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!"; syswrite(FH, "Fowl\\n", 5) or die "E: write \$!";
EOF EOF
chmod +x cld chmod +x cld
exec 9>&1 exec 9>&1
@ -11508,13 +11507,11 @@ name: fd-cloexec-2
description: description:
Verify that file descriptors > 2 are not private for POSIX shells Verify that file descriptors > 2 are not private for POSIX shells
See Debian Bug #154540, Closes: #499139 See Debian Bug #154540, Closes: #499139
XXX fails on some old Perl installations
need-pass: no
stdin: stdin:
cat >cld <<-EOF cat >cld <<-EOF
#!$__perlname #!$__perlname
open(my \$fh, ">&", 9) or die "E: open \$!"; open(FH, ">&9") or die "E: open \$!";
syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!"; syswrite(FH, "Fowl\\n", 5) or die "E: write \$!";
EOF EOF
chmod +x cld chmod +x cld
test -n "$POSH_VERSION" || set -o posix test -n "$POSH_VERSION" || set -o posix
@ -12079,10 +12076,10 @@ expected-stdout:
EOFN EOFN
)|tr u x); } )|tr u x); }
function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP { function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP {
x=$( ( \cat >|bar <<"EOFN" x=$( ( \cat >|bar <<"EOFN" ) | \tr u x
foo foo
EOFN EOFN
) | \tr u x ) )
} }
inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() { inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() {
cat 1>bar <<-EOFI cat 1>bar <<-EOFI
@ -12112,10 +12109,10 @@ expected-stdout:
EOFI EOFI
)|tr u x); } )|tr u x); }
function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP { function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP {
x=$( ( \cat >bar <<-EOFI x=$( ( \cat >bar <<-EOFI ) | \tr u x
foo foo
EOFI EOFI
) | \tr u x ) )
} }
inline_IORDWR_IODUP() { inline_IORDWR_IODUP() {
sh 1<>/dev/console 0<&1 2>&1 sh 1<>/dev/console 0<&1 2>&1
@ -13640,6 +13637,11 @@ description:
words, and command -p[vV] should find aliases, reserved words, and words, and command -p[vV] should find aliases, reserved words, and
builtins over external commands. builtins over external commands.
stdin: stdin:
# extra checks prep
mkdir mrr
:>mrr/miau
chmod +x mrr/miau
# priorities
PATH=/bin:/usr/bin PATH=/bin:/usr/bin
alias foo="bar baz" alias foo="bar baz"
alias '[ab]=:' alias '[ab]=:'
@ -13653,6 +13655,14 @@ stdin:
# extra checks # extra checks
alias '[ab]' alias '[ab]'
whence '[ab]' whence '[ab]'
PATH=mrr
case $(command -v miau) {
(mrr/miau) echo fail ;;
(!(/*|[A-Z]:/*)) echo fail2 ;;
($PWD/mrr/miau) echo ok ;;
(/*|[A-Z]:/*) echo pwd bad? ;;
(*) echo not reached ;;
}
expected-stdout: expected-stdout:
if if
if if
@ -13680,6 +13690,7 @@ expected-stdout:
'[ab]' is an alias for : '[ab]' is an alias for :
'[ab]'=: '[ab]'=:
: :
ok
--- ---
name: whence-preserve-tradition name: whence-preserve-tradition
description: description:

View file

@ -29,7 +29,7 @@
#ifndef MKSH_NO_CMDLINE_EDITING #ifndef MKSH_NO_CMDLINE_EDITING
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.351 2020/04/15 20:16:19 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.357 2020/10/31 05:02:17 tg Exp $");
/* /*
* in later versions we might use libtermcap for this, but since external * in later versions we might use libtermcap for this, but since external
@ -41,6 +41,10 @@ __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.351 2020/04/15 20:16:19 tg Exp $");
#define MKSH_CLS_STRING KSH_ESC_STRING "[;H" KSH_ESC_STRING "[J" #define MKSH_CLS_STRING KSH_ESC_STRING "[;H" KSH_ESC_STRING "[J"
#endif #endif
#if !defined(MKSH_SMALL) || !MKSH_S_NOVI
static const char ctrl_x_e[] = "fc -e \"${VISUAL:-${EDITOR:-vi}}\" --";
#endif
/* tty driver characters we are interested in */ /* tty driver characters we are interested in */
#define EDCHAR_DISABLED 0xFFFFU #define EDCHAR_DISABLED 0xFFFFU
#define EDCHAR_INITIAL 0xFFFEU #define EDCHAR_INITIAL 0xFFFEU
@ -153,7 +157,7 @@ x_getc(void)
char c; char c;
ssize_t n; ssize_t n;
while ((n = blocking_read(STDIN_FILENO, &c, 1)) < 0 && errno == EINTR) while ((n = blocking_read(0, &c, 1)) < 0 && errno == EINTR)
if (trap) { if (trap) {
x_mode(false); x_mode(false);
runtraps(0); runtraps(0);
@ -970,7 +974,6 @@ static char *wbuf[2]; /* window buffers */
static int wbuf_len; /* length of window buffers (x_cols - 3) */ static int wbuf_len; /* length of window buffers (x_cols - 3) */
static int win; /* window buffer in use */ static int win; /* window buffer in use */
static char morec; /* more character at right of window */ static char morec; /* more character at right of window */
static int lastref; /* argument to last refresh() */
static int holdlen; /* length of holdbuf */ static int holdlen; /* length of holdbuf */
#endif #endif
static int pwidth; /* width of prompt */ static int pwidth; /* width of prompt */
@ -989,11 +992,11 @@ static void x_zots(char *);
static void x_zotc3(char **); static void x_zotc3(char **);
static void x_vi_zotc(int); static void x_vi_zotc(int);
static void x_load_hist(char **); static void x_load_hist(char **);
static int x_search(char *, int, int); static int x_search(const char *, int, int);
#ifndef MKSH_SMALL #ifndef MKSH_SMALL
static int x_search_dir(int); static int x_search_dir(int);
#endif #endif
static int x_match(char *, char *); static int x_match(const char *, const char *);
static void x_redraw(int); static void x_redraw(int);
static void x_push(size_t); static void x_push(size_t);
static void x_bind_showone(int, int); static void x_bind_showone(int, int);
@ -1946,7 +1949,7 @@ x_search_hist(int c)
offset = x_match(xbuf, pat); offset = x_match(xbuf, pat);
if (offset >= 0) { if (offset >= 0) {
x_goto(xbuf + offset + (p - pat) - x_goto(xbuf + offset + (p - pat) -
(*pat == '^')); (*pat == '^' ? 1 : 0));
continue; continue;
} }
} }
@ -1968,18 +1971,21 @@ x_search_hist(int c)
/* search backward from current line */ /* search backward from current line */
static int static int
x_search(char *pat, int sameline, int offset) x_search(const char *pat, int sameline, int offset)
{ {
char **hp; char **hp;
int i; int i;
size_t patlen = strlen(pat);
if (*pat == '^')
--patlen;
for (hp = x_histp - (sameline ? 0 : 1); hp >= history; --hp) { for (hp = x_histp - (sameline ? 0 : 1); hp >= history; --hp) {
i = x_match(*hp, pat); i = x_match(*hp, pat);
if (i >= 0) { if (i >= 0) {
if (offset < 0) if (offset < 0)
x_e_putc2('\n'); x_e_putc2('\n');
x_load_hist(hp); x_load_hist(hp);
x_goto(xbuf + i + strlen(pat) - (*pat == '^')); x_goto(xbuf + i + patlen);
return (i); return (i);
} }
} }
@ -2024,7 +2030,7 @@ x_search_dir(int search_dir /* should've been bool */)
/* return position of first match of pattern in string, else -1 */ /* return position of first match of pattern in string, else -1 */
static int static int
x_match(char *str, char *pat) x_match(const char *str, const char *pat)
{ {
if (*pat == '^') { if (*pat == '^') {
return ((strncmp(str, pat + 1, strlen(pat + 1)) == 0) ? 0 : -1); return ((strncmp(str, pat + 1, strlen(pat + 1)) == 0) ? 0 : -1);
@ -3125,10 +3131,6 @@ static int
x_edit_line(int c MKSH_A_UNUSED) x_edit_line(int c MKSH_A_UNUSED)
{ {
if (x_arg_defaulted) { if (x_arg_defaulted) {
if (xep == xbuf) {
x_e_putc2(KSH_BEL);
return (KSTD);
}
if (modified) { if (modified) {
*xep = '\0'; *xep = '\0';
histsave(&source->line, xbuf, HIST_STORE, true); histsave(&source->line, xbuf, HIST_STORE, true);
@ -3137,10 +3139,9 @@ x_edit_line(int c MKSH_A_UNUSED)
x_arg = source->line - (histptr - x_histp); x_arg = source->line - (histptr - x_histp);
} }
if (x_arg) if (x_arg)
shf_snprintf(xbuf, xend - xbuf, Tf_sd, shf_snprintf(xbuf, xend - xbuf, Tf_sd, ctrl_x_e, x_arg);
"fc -e ${VISUAL:-${EDITOR:-vi}} --", x_arg);
else else
strlcpy(xbuf, "fc -e ${VISUAL:-${EDITOR:-vi}} --", xend - xbuf); strlcpy(xbuf, ctrl_x_e, xend - xbuf);
xep = strnul(xbuf); xep = strnul(xbuf);
return (x_newline('\n')); return (x_newline('\n'));
} }
@ -3433,13 +3434,13 @@ static int Forwword(int);
static int Backword(int); static int Backword(int);
static int Endword(int); static int Endword(int);
static int grabhist(int, int); static int grabhist(int, int);
static int grabsearch(int, int, int, const char *); static int grabsearch(const char *, int, int, bool);
static void redraw_line(bool); static void redraw_line(bool);
static void refresh(int); static void refresh(bool);
static int outofwin(void); static int outofwin(void);
static void rewindow(void); static void rewindow(void);
static int newcol(unsigned char, int); static int newcol(unsigned char, int);
static void display(char *, char *, int); static void display(char *, char *, bool);
static void ed_mov_opt(int, char *); static void ed_mov_opt(int, char *);
static int expand_word(int); static int expand_word(int);
static int complete_word(int, int); static int complete_word(int, int);
@ -3610,7 +3611,6 @@ x_vi(char *buf)
winwidth = x_cols - pwidth - 3; winwidth = x_cols - pwidth - 3;
win = 0; win = 0;
morec = ' '; morec = ' ';
lastref = 1;
holdlen = 0; holdlen = 0;
editmode = 2; editmode = 2;
@ -3712,7 +3712,7 @@ vi_hook(int ch)
case 0: case 0:
if (state == VLIT) { if (state == VLIT) {
vs->cursor--; vs->cursor--;
refresh(0); refresh(false);
} else } else
refresh(insert != 0); refresh(insert != 0);
break; break;
@ -3738,7 +3738,7 @@ vi_hook(int ch)
if (putbuf(ord(ch) == ORD('/') ? if (putbuf(ord(ch) == ORD('/') ?
"/" : "?", 1, false) != 0) "/" : "?", 1, false) != 0)
return (-1); return (-1);
refresh(0); refresh(false);
} }
if (state == VVERSION) { if (state == VVERSION) {
save_cbuf(); save_cbuf();
@ -3746,7 +3746,7 @@ vi_hook(int ch)
vs->linelen = 0; vs->linelen = 0;
putbuf(KSH_VERSION, putbuf(KSH_VERSION,
strlen(KSH_VERSION), false); strlen(KSH_VERSION), false);
refresh(0); refresh(false);
} }
} }
} }
@ -3758,14 +3758,14 @@ vi_hook(int ch)
vi_error(); vi_error();
} else } else
vs->cbuf[vs->cursor++] = ch; vs->cbuf[vs->cursor++] = ch;
refresh(1); refresh(true);
state = VNORMAL; state = VNORMAL;
break; break;
case VVERSION: case VVERSION:
restore_cbuf(); restore_cbuf();
state = VNORMAL; state = VNORMAL;
refresh(0); refresh(false);
break; break;
case VARG1: case VARG1:
@ -3829,7 +3829,7 @@ vi_hook(int ch)
if (!srchpat[0]) { if (!srchpat[0]) {
vi_error(); vi_error();
state = VNORMAL; state = VNORMAL;
refresh(0); refresh(false);
return (0); return (0);
} }
} else { } else {
@ -3842,17 +3842,17 @@ vi_hook(int ch)
srchlen--; srchlen--;
vs->linelen -= char_len(locpat[srchlen]); vs->linelen -= char_len(locpat[srchlen]);
vs->cursor = vs->linelen; vs->cursor = vs->linelen;
refresh(0); refresh(false);
return (0); return (0);
} }
restore_cbuf(); restore_cbuf();
state = VNORMAL; state = VNORMAL;
refresh(0); refresh(false);
} else if (isched(ch, edchars.kill)) { } else if (isched(ch, edchars.kill)) {
srchlen = 0; srchlen = 0;
vs->linelen = 1; vs->linelen = 1;
vs->cursor = 1; vs->cursor = 1;
refresh(0); refresh(false);
return (0); return (0);
} else if (isched(ch, edchars.werase)) { } else if (isched(ch, edchars.werase)) {
unsigned int i, n; unsigned int i, n;
@ -3871,7 +3871,7 @@ vi_hook(int ch)
vs->linelen -= char_len(locpat[i]); vs->linelen -= char_len(locpat[i]);
srchlen = (int)n; srchlen = (int)n;
vs->cursor = vs->linelen; vs->cursor = vs->linelen;
refresh(0); refresh(false);
return (0); return (0);
} else { } else {
if (srchlen == SRCHLEN - 1) if (srchlen == SRCHLEN - 1)
@ -3890,7 +3890,7 @@ vi_hook(int ch)
vs->cbuf[vs->linelen++] = ch; vs->cbuf[vs->linelen++] = ch;
} }
vs->cursor = vs->linelen; vs->cursor = vs->linelen;
refresh(0); refresh(false);
} }
return (0); return (0);
} }
@ -3931,7 +3931,7 @@ vi_hook(int ch)
switch (vi_cmd(argc1, curcmd)) { switch (vi_cmd(argc1, curcmd)) {
case -1: case -1:
vi_error(); vi_error();
refresh(0); refresh(false);
break; break;
case 0: case 0:
if (insert != 0) if (insert != 0)
@ -3939,7 +3939,7 @@ vi_hook(int ch)
refresh(insert != 0); refresh(insert != 0);
break; break;
case 1: case 1:
refresh(0); refresh(false);
return (1); return (1);
case 2: case 2:
/* back from a 'v' command - don't redraw the screen */ /* back from a 'v' command - don't redraw the screen */
@ -3954,7 +3954,7 @@ vi_hook(int ch)
switch (vi_cmd(lastac, lastcmd)) { switch (vi_cmd(lastac, lastcmd)) {
case -1: case -1:
vi_error(); vi_error();
refresh(0); refresh(false);
break; break;
case 0: case 0:
if (insert != 0) { if (insert != 0) {
@ -3967,10 +3967,10 @@ vi_hook(int ch)
vi_error(); vi_error();
} }
} }
refresh(0); refresh(false);
break; break;
case 1: case 1:
refresh(0); refresh(false);
return (1); return (1);
case 2: case 2:
/* back from a 'v' command - can't happen */ /* back from a 'v' command - can't happen */
@ -4135,8 +4135,9 @@ static int
vi_cmd(int argcnt, const char *cmd) vi_cmd(int argcnt, const char *cmd)
{ {
int ncursor; int ncursor;
int cur, c1, c2, c3 = 0; int cur, c1, c2;
int any; int any;
bool b;
struct edstate *t; struct edstate *t;
if (argcnt == 0 && !is_zerocount(*cmd)) if (argcnt == 0 && !is_zerocount(*cmd))
@ -4407,8 +4408,6 @@ vi_cmd(int argcnt, const char *cmd)
case ORD('v'): case ORD('v'):
if (!argcnt) { if (!argcnt) {
if (vs->linelen == 0)
return (-1);
if (modified) { if (modified) {
vs->cbuf[vs->linelen] = '\0'; vs->cbuf[vs->linelen] = '\0';
histsave(&source->line, vs->cbuf, histsave(&source->line, vs->cbuf,
@ -4419,12 +4418,9 @@ vi_cmd(int argcnt, const char *cmd)
} }
if (argcnt) if (argcnt)
shf_snprintf(vs->cbuf, vs->cbufsize, Tf_sd, shf_snprintf(vs->cbuf, vs->cbufsize, Tf_sd,
"fc -e ${VISUAL:-${EDITOR:-vi}} --", ctrl_x_e, argcnt);
argcnt);
else else
strlcpy(vs->cbuf, strlcpy(vs->cbuf, ctrl_x_e, vs->cbufsize);
"fc -e ${VISUAL:-${EDITOR:-vi}} --",
vs->cbufsize);
vs->linelen = strlen(vs->cbuf); vs->linelen = strlen(vs->cbuf);
return (2); return (2);
@ -4474,25 +4470,23 @@ vi_cmd(int argcnt, const char *cmd)
/* FALLTHROUGH */ /* FALLTHROUGH */
case ORD('/'): case ORD('/'):
c3 = 1; c1 = 1;
srchlen = 0; srchlen = 0;
lastsearch = *cmd; lastsearch = *cmd;
/* FALLTHROUGH */ if (0)
/* FALLTHROUGH */
case ORD('n'): case ORD('n'):
case ORD('N'): case ORD('N'):
c1 = 0;
if (lastsearch == ORD(' ')) if (lastsearch == ORD(' '))
return (-1); return (-1);
if (lastsearch == ORD('?')) b = (lastsearch == ORD('?'));
c1 = 1;
else
c1 = 0;
if (*cmd == 'N') if (*cmd == 'N')
c1 = !c1; b = !b;
if ((c2 = grabsearch(modified, hnum, if ((c2 = grabsearch(srchpat, modified, hnum, b)) < 0) {
c1, srchpat)) < 0) { if (c1) {
if (c3) {
restore_cbuf(); restore_cbuf();
refresh(0); refresh(false);
} }
return (-1); return (-1);
} else { } else {
@ -5117,20 +5111,20 @@ grabhist(int save, int n)
} }
static int static int
grabsearch(int save, int start, int fwd, const char *pat) grabsearch(const char *pat, int save, int start, bool fwd)
{ {
char *hptr; char *hptr;
int hist; int hist;
bool anchored; bool anchored;
if ((start == 0 && fwd == 0) || (start >= hlast - 1 && fwd == 1)) if ((start == 0 && !fwd) || (start >= hlast - 1 && fwd))
return (-1); return (-1);
if (fwd) if (fwd)
start++; start++;
else else
start--; start--;
anchored = *pat == '^' ? (++pat, true) : false; anchored = *pat == '^' ? (++pat, true) : false;
if ((hist = findhist(start, fwd, pat, anchored)) < 0) { if ((hist = findhist(start, pat, fwd, anchored)) < 0) {
/* (start != 0 && fwd && match(holdbufp, pat) >= 0) */ /* (start != 0 && fwd && match(holdbufp, pat) >= 0) */
if (start != 0 && fwd && strcmp(holdbufp, pat) >= 0) { if (start != 0 && fwd && strcmp(holdbufp, pat) >= 0) {
restore_cbuf(); restore_cbuf();
@ -5163,12 +5157,8 @@ redraw_line(bool newl)
} }
static void static void
refresh(int leftside) refresh(bool leftside)
{ {
if (leftside < 0)
leftside = lastref;
else
lastref = leftside;
if (outofwin()) if (outofwin())
rewindow(); rewindow();
display(wbuf[1 - win], wbuf[win], leftside); display(wbuf[1 - win], wbuf[win], leftside);
@ -5224,7 +5214,7 @@ newcol(unsigned char ch, int col)
} }
static void static void
display(char *wb1, char *wb2, int leftside) display(char *wb1, char *wb2, bool leftside)
{ {
unsigned char ch; unsigned char ch;
char *twb1, *twb2, mc; char *twb1, *twb2, mc;
@ -5379,7 +5369,7 @@ expand_word(int cmd)
hnum = hlast; hnum = hlast;
insert = INSERT; insert = INSERT;
lastac = 0; lastac = 0;
refresh(0); refresh(false);
return (rval); return (rval);
} }
@ -5494,7 +5484,7 @@ complete_word(int cmd, int count)
insert = INSERT; insert = INSERT;
/* prevent this from being redone... */ /* prevent this from being redone... */
lastac = 0; lastac = 0;
refresh(0); refresh(false);
return (rval); return (rval);
} }

View file

@ -24,7 +24,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.223 2020/04/07 23:14:41 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.224 2020/08/27 19:52:43 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL #ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh" #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
@ -1213,7 +1213,7 @@ findcom(const char *name, int flags)
} }
Search: Search:
if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) && if ((!tp || (tp->type == CTALIAS && !(tp->flag & ISSET))) &&
(flags & FC_PATH)) { (flags & FC_PATH)) {
if (!tp) { if (!tp) {
if (insert && !(flags & FC_DEFPATH)) { if (insert && !(flags & FC_DEFPATH)) {
@ -1351,10 +1351,8 @@ search_path(const char *name, const char *lpath,
XcheckN(xs, xp, p - sp); XcheckN(xs, xp, p - sp);
memcpy(xp, sp, p - sp); memcpy(xp, sp, p - sp);
xp += p - sp; xp += p - sp;
#ifdef __OS2__ if (mksh_cdirsep(xp[-1]))
if (xp > Xstring(xs, xp) && mksh_cdirsep(xp[-1]))
xp--; xp--;
#endif
*xp++ = '/'; *xp++ = '/';
} }
sp = p; sp = p;

View file

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.107 2020/03/27 02:49:40 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/expr.c,v 1.108 2020/06/20 02:27:50 tg Exp $");
#define EXPRTOK_DEFNS #define EXPRTOK_DEFNS
#include "exprtok.h" #include "exprtok.h"
@ -886,8 +886,8 @@ static int mb_ucsbsearch(const struct mb_ucsrange arr[], size_t elems,
unsigned int val) MKSH_A_PURE; unsigned int val) MKSH_A_PURE;
/* /*
* Generated from the UCD 13.0.0 by * Generated from the UCD 13.0.0 - see /usr/share/doc/legal/LICENCE-BSD - by
* MirOS: contrib/code/Snippets/eawparse,v 1.14 2020/03/27 01:33:21 tg Exp $ * MirOS: contrib/code/Snippets/eawparse,v 1.15 2020/06/15 20:31:13 tg Exp $
*/ */
/*- /*-
@ -1136,6 +1136,7 @@ static const struct mb_ucsrange mb_ucs_combining[] = {
{ 0xABE5, 0xABE5 }, { 0xABE5, 0xABE5 },
{ 0xABE8, 0xABE8 }, { 0xABE8, 0xABE8 },
{ 0xABED, 0xABED }, { 0xABED, 0xABED },
{ 0xD7B0, 0xD7FF },
{ 0xFB1E, 0xFB1E }, { 0xFB1E, 0xFB1E },
{ 0xFE00, 0xFE0F }, { 0xFE00, 0xFE0F },
{ 0xFE20, 0xFE2F }, { 0xFE20, 0xFE2F },

View file

@ -1,7 +1,6 @@
/* $OpenBSD: c_ksh.c,v 1.37 2015/09/10 22:48:58 nicm Exp $ */ /* $OpenBSD: c_ksh.c,v 1.37 2015/09/10 22:48:58 nicm Exp $ */
/* $OpenBSD: c_sh.c,v 1.46 2015/07/20 20:46:24 guenther Exp $ */ /* $OpenBSD: c_sh.c,v 1.46 2015/07/20 20:46:24 guenther Exp $ */
/* $OpenBSD: c_test.c,v 1.18 2009/03/01 20:11:06 otto Exp $ */ /* $OpenBSD: c_test.c,v 1.18 2009/03/01 20:11:06 otto Exp $ */
/* $OpenBSD: c_ulimit.c,v 1.19 2013/11/28 10:33:37 sobrado Exp $ */
/*- /*-
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
@ -39,7 +38,7 @@
#endif #endif
#endif #endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.373 2020/05/16 22:38:21 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.379 2020/08/27 19:52:44 tg Exp $");
#if HAVE_KILLPG #if HAVE_KILLPG
/* /*
@ -52,12 +51,7 @@ __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.373 2020/05/16 22:38:21 tg Exp $");
#define mksh_kill kill #define mksh_kill kill
#endif #endif
/* XXX conditions correct? */ #ifdef MKSH_UNLIMITED
#if !defined(RLIM_INFINITY) && !defined(MKSH_NO_LIMITS)
#define MKSH_NO_LIMITS 1
#endif
#ifdef MKSH_NO_LIMITS
#define c_ulimit c_true #define c_ulimit c_true
#endif #endif
@ -713,7 +707,23 @@ do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
"exported " : "", "exported " : "",
Talias); Talias);
} }
shf_puts(tp->val.s, shl_stdout); if (!mksh_abspath(tp->val.s)) {
const char *xcwd = current_wd[0] ?
current_wd : ".";
size_t xlen = strlen(xcwd);
size_t clen = strlen(tp->val.s) + 1;
char *xp = alloc(xlen + 1 + clen, ATEMP);
memcpy(xp, xcwd, xlen);
if (mksh_cdirsep(xp[xlen - 1]))
--xlen;
xp[xlen++] = '/';
memcpy(xp + xlen, tp->val.s, clen);
simplify_path(xp);
shf_puts(xp, shl_stdout);
afree(xp, ATEMP);
} else
shf_puts(tp->val.s, shl_stdout);
} else { } else {
if (vflag) if (vflag)
shprintf(Tnot_found_s, id); shprintf(Tnot_found_s, id);
@ -3219,214 +3229,6 @@ ptest_error(Test_env *te, int ofs, const char *msg)
bi_errorf(Tf_s, msg); bi_errorf(Tf_s, msg);
} }
#ifndef MKSH_NO_LIMITS
#define SOFT 0x1
#define HARD 0x2
/* Magic to divine the 'm' and 'v' limits */
#ifdef RLIMIT_AS
#if !defined(RLIMIT_VMEM) || (RLIMIT_VMEM == RLIMIT_AS) || \
!defined(RLIMIT_RSS) || (RLIMIT_VMEM == RLIMIT_RSS)
#define ULIMIT_V_IS_AS
#elif defined(RLIMIT_VMEM)
#if !defined(RLIMIT_RSS) || (RLIMIT_RSS == RLIMIT_AS)
#define ULIMIT_V_IS_AS
#else
#define ULIMIT_V_IS_VMEM
#endif
#endif
#endif
#ifdef RLIMIT_RSS
#ifdef ULIMIT_V_IS_VMEM
#define ULIMIT_M_IS_RSS
#elif defined(RLIMIT_VMEM) && (RLIMIT_VMEM == RLIMIT_RSS)
#define ULIMIT_M_IS_VMEM
#else
#define ULIMIT_M_IS_RSS
#endif
#if defined(ULIMIT_M_IS_RSS) && defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)
#undef ULIMIT_M_IS_RSS
#endif
#endif
#if !defined(RLIMIT_AS) && !defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_VMEM)
#define ULIMIT_V_IS_VMEM
#endif
#if !defined(ULIMIT_V_IS_VMEM) && defined(RLIMIT_VMEM) && \
(!defined(RLIMIT_RSS) || (defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)))
#define ULIMIT_M_IS_VMEM
#endif
#if defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_AS) && \
(RLIMIT_VMEM == 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
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 RLIMITS_DEFNS
#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 \
};
#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)
{
size_t i = 0;
int how = SOFT | HARD, optc, what = 'f';
bool all = false;
while ((optc = ksh_getopt(wp, &builtin_opt, rlimits_opts)) != -1)
switch (optc) {
case 'H':
how = HARD;
break;
case 'S':
how = SOFT;
break;
case 'a':
all = true;
break;
case '?':
bi_errorf("usage: ulimit [-%s] [value]", rlimits_opts);
return (1);
default:
what = optc;
}
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(Ttoo_many_args);
return (1);
}
return (set_ulimit(rlimits[i], wp[builtin_opt.optind], how));
}
if (!all)
print_ulimit(rlimits[i], how);
else for (i = 0; i < NELEM(rlimits); ++i) {
shprintf("-%c: %-20s ", rlimits[i]->optchar, rlimits[i]->name);
print_ulimit(rlimits[i], how);
}
return (0);
}
static int
set_ulimit(const struct limits *l, const char *v, int how)
{
rlim_t val = (rlim_t)0;
struct rlimit limit;
if (strcmp(v, "unlimited") == 0)
val = (rlim_t)RLIM_INFINITY;
else {
mksh_uari_t rval;
if (!evaluate(v, (mksh_ari_t *)&rval, KSH_RETURN_ERROR, false))
return (1);
/*
* Avoid problems caused by typos that evaluate misses due
* to evaluating unset parameters to 0...
* If this causes problems, will have to add parameter to
* evaluate() to control if unset params are 0 or an error.
*/
if (!rval && !ctype(v[0], C_DIGIT)) {
bi_errorf("invalid %s limit: %s", l->name, v);
return (1);
}
val = (rlim_t)((rlim_t)rval * l->factor);
}
if (getrlimit(l->resource, &limit) < 0) {
#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;
}
if (how & SOFT)
limit.rlim_cur = val;
if (how & HARD)
limit.rlim_max = val;
if (!setrlimit(l->resource, &limit))
return (0);
if (errno == EPERM)
bi_errorf("%s exceeds allowable %s limit", v, l->name);
else
bi_errorf("bad %s limit: %s", l->name, cstrerror(errno));
return (1);
}
static void
print_ulimit(const struct limits *l, int how)
{
rlim_t val = (rlim_t)0;
struct rlimit limit;
if (getrlimit(l->resource, &limit)) {
shf_puts("unknown\n", shl_stdout);
return;
}
if (how & SOFT)
val = limit.rlim_cur;
else if (how & HARD)
val = limit.rlim_max;
if (val == (rlim_t)RLIM_INFINITY)
shf_puts("unlimited\n", shl_stdout);
else
shprintf("%lu\n", (unsigned long)(val / l->factor));
}
#endif
int int
c_rename(const char **wp) c_rename(const char **wp)
{ {
@ -3483,7 +3285,7 @@ c_realpath(const char **wp)
int int
c_cat(const char **wp) c_cat(const char **wp)
{ {
int fd = STDIN_FILENO, rv; int fd = 0, rv;
ssize_t n, w; ssize_t n, w;
const char *fn = "<stdin>"; const char *fn = "<stdin>";
char *buf, *cp; char *buf, *cp;
@ -3516,7 +3318,7 @@ c_cat(const char **wp)
if (*wp) { if (*wp) {
fn = *wp++; fn = *wp++;
if (ksh_isdash(fn)) if (ksh_isdash(fn))
fd = STDIN_FILENO; fd = 0;
else if ((fd = binopen2(fn, O_RDONLY)) < 0) { else if ((fd = binopen2(fn, O_RDONLY)) < 0) {
bi_errorf(Tf_sD_s, fn, cstrerror(errno)); bi_errorf(Tf_sD_s, fn, cstrerror(errno));
rv = 1; rv = 1;
@ -3535,7 +3337,7 @@ c_cat(const char **wp)
opipe = block_pipe(); opipe = block_pipe();
continue; continue;
} }
/* an error occured during reading */ /* an error occurred during reading */
bi_errorf(Tf_sD_s, fn, cstrerror(errno)); bi_errorf(Tf_sD_s, fn, cstrerror(errno));
rv = 1; rv = 1;
break; break;
@ -3545,7 +3347,7 @@ c_cat(const char **wp)
while (n) { while (n) {
if (intrsig) if (intrsig)
goto has_intrsig; goto has_intrsig;
if ((w = write(STDOUT_FILENO, cp, n)) != -1) { if ((w = write(1, cp, n)) != -1) {
n -= w; n -= w;
cp += w; cp += w;
continue; continue;
@ -3564,17 +3366,17 @@ c_cat(const char **wp)
/* fake receiving signal */ /* fake receiving signal */
rv = ksh_sigmask(SIGPIPE); rv = ksh_sigmask(SIGPIPE);
} else { } else {
/* an error occured during writing */ /* an error occurred during writing */
bi_errorf(Tf_sD_s, "<stdout>", bi_errorf(Tf_sD_s, "<stdout>",
cstrerror(errno)); cstrerror(errno));
rv = 1; rv = 1;
} }
if (fd != STDIN_FILENO) if (fd != 0)
close(fd); close(fd);
goto out; goto out;
} }
} }
if (fd != STDIN_FILENO) if (fd != 0)
close(fd); close(fd);
} while (*wp); } while (*wp);

View file

@ -27,7 +27,7 @@
#include <sys/file.h> #include <sys/file.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.169 2019/09/16 21:10:33 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.170 2020/10/01 22:53:20 tg Exp $");
Trap sigtraps[ksh_NSIG + 1]; Trap sigtraps[ksh_NSIG + 1];
static struct sigaction Sigact_ign; static struct sigaction Sigact_ign;
@ -415,7 +415,8 @@ hist_get(const char *str, bool approx, bool allow_cur)
bool anchored = *str == '?' ? (++str, false) : true; bool anchored = *str == '?' ? (++str, false) : true;
/* the -1 is to avoid the current fc command */ /* the -1 is to avoid the current fc command */
if ((n = findhist(histptr - history - 1, 0, str, anchored)) < 0) if ((n = findhist(histptr - history - 1, str, false,
anchored)) < 0)
bi_errorf(Tf_sD_s, str, Tnot_in_history); bi_errorf(Tf_sD_s, str, Tnot_in_history);
else else
hp = &history[n]; hp = &history[n];
@ -479,7 +480,7 @@ histnum(int n)
* direction. * direction.
*/ */
int int
findhist(int start, int fwd, const char *str, bool anchored) findhist(int start, const char *str, bool fwd, bool anchored)
{ {
char **hp; char **hp;
int maxhist = histptr - history; int maxhist = histptr - history;

View file

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/lksh.1,v 1.25 2018/12/25 19:38:08 tg Exp $ .\" $MirOS: src/bin/mksh/lksh.1,v 1.26 2020/09/04 22:37:01 tg Exp $
.\"- .\"-
.\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016, 2017, 2018 .\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016, 2017, 2018
.\" mirabilos <m@mirbsd.org> .\" mirabilos <m@mirbsd.org>
@ -25,7 +25,8 @@
.\" thus use - for hyphens and \- for minus signs and option dashes .\" thus use - for hyphens and \- for minus signs and option dashes
.\" * ~ is size-reduced and placed atop in groff, so use \*(TI .\" * ~ is size-reduced and placed atop in groff, so use \*(TI
.\" * ^ is size-reduced and placed atop in groff, so use \*(ha .\" * ^ is size-reduced and placed atop in groff, so use \*(ha
.\" * \(en does not work in nroff, so use \*(en .\" * \(en does not work in nroff, so use \*(en for a solo en dash
.\" * and \*(EM for a correctly spaced em dash
.\" * <>| are problematic, so redefine and use \*(Lt\*(Gt\*(Ba .\" * <>| are problematic, so redefine and use \*(Lt\*(Gt\*(Ba
.\" Also make sure to use \& *before* a punctuation char that is to not .\" Also make sure to use \& *before* a punctuation char that is to not
.\" be interpreted as punctuation, and especially with two-letter words .\" be interpreted as punctuation, and especially with two-letter words
@ -59,6 +60,12 @@
. ds ha ^ . ds ha ^
. ds en \(em . ds en \(em
.\} .\}
.ie n \{\
. ds EM \ \*(en\ \&
.\}
.el \{\
. ds EM \f(TR\^\(em\^\fP
.\}
.\" .\"
.\" Implement .Dd with the Mdocdate RCS keyword .\" Implement .Dd with the Mdocdate RCS keyword
.\" .\"
@ -74,7 +81,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to .\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always. .\" use our own definition. And .Dd must come *first*, always.
.\" .\"
.Dd $Mdocdate: December 25 2018 $ .Dd $Mdocdate: September 4 2020 $
.\" .\"
.\" Check which macro package we use, and do other -mdoc setup. .\" Check which macro package we use, and do other -mdoc setup.
.\" .\"

View file

@ -35,7 +35,7 @@
#include <locale.h> #include <locale.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.372 2020/05/16 22:51:24 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/main.c,v 1.374 2020/10/01 20:28:54 tg Exp $");
#ifndef MKSHRC_PATH #ifndef MKSHRC_PATH
#define MKSHRC_PATH "~/.mkshrc" #define MKSHRC_PATH "~/.mkshrc"
@ -1203,7 +1203,7 @@ remove_temps(struct temp *tp)
/* /*
* Initialise tty_fd. Used for tracking the size of the terminal, * Initialise tty_fd. Used for tracking the size of the terminal,
* saving/resetting tty modes upon forground job completion, and * saving/resetting tty modes upon foreground job completion, and
* for setting up the tty process group. Return values: * for setting up the tty process group. Return values:
* 0 = got controlling tty * 0 = got controlling tty
* 1 = got terminal but no controlling tty * 1 = got terminal but no controlling tty
@ -1435,7 +1435,8 @@ error_prefix(bool fileline)
/* Avoid foo: foo[2]: ... */ /* Avoid foo: foo[2]: ... */
if (!fileline || !source || !source->file || if (!fileline || !source || !source->file ||
strcmp(source->file, kshname) != 0) strcmp(source->file, kshname) != 0)
shf_fprintf(shl_out, Tf_sD_, kshname + (*kshname == '-')); shf_fprintf(shl_out, Tf_sD_, kshname +
(*kshname == '-' ? 1 : 0));
if (fileline && source && source->file != NULL) { if (fileline && source && source->file != NULL) {
shf_fprintf(shl_out, "%s[%lu]: ", source->file, shf_fprintf(shl_out, "%s[%lu]: ", source->file,
(unsigned long)(source->errline ? (unsigned long)(source->errline ?

View file

@ -33,7 +33,7 @@
#include <grp.h> #include <grp.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.299 2020/05/16 22:19:58 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.302 2020/08/27 19:52:45 tg Exp $");
#define KSH_CHVT_FLAG #define KSH_CHVT_FLAG
#ifdef MKSH_SMALL #ifdef MKSH_SMALL
@ -1328,7 +1328,7 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
if (go->flags & GF_ERROR) if (go->flags & GF_ERROR)
bi_errorfz(); bi_errorfz();
} }
return ('?'); return (ORD('?'));
} }
/** /**
* : means argument must be present, may be part of option argument * : means argument must be present, may be part of option argument
@ -1347,7 +1347,7 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
if (optionsp[0] == ':') { if (optionsp[0] == ':') {
go->buf[0] = c; go->buf[0] = c;
go->optarg = go->buf; go->optarg = go->buf;
return (':'); return (ORD(':'));
} }
warningf(true, Tf_optfoo, warningf(true, Tf_optfoo,
(go->flags & GF_NONAME) ? "" : argv[0], (go->flags & GF_NONAME) ? "" : argv[0],
@ -1355,7 +1355,7 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
c, Treq_arg); c, Treq_arg);
if (go->flags & GF_ERROR) if (go->flags & GF_ERROR)
bi_errorfz(); bi_errorfz();
return ('?'); return (ORD('?'));
} }
go->p = 0; go->p = 0;
} else if (*o == ',') { } else if (*o == ',') {
@ -1383,7 +1383,7 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
go->optarg = NULL; go->optarg = NULL;
} }
} }
return (c); return (ord(c));
} }
/* /*
@ -1927,7 +1927,7 @@ do_realpath(const char *upath)
* - if file starts with '/', append file to result & set cdpathp to NULL * - if file starts with '/', append file to result & set cdpathp to NULL
* - if file starts with ./ or ../ append cwd and file to result * - if file starts with ./ or ../ append cwd and file to result
* and set cdpathp to NULL * and set cdpathp to NULL
* - if the first element of cdpathp doesnt start with a '/' xx or '.' xx * - if the first element of cdpathp doesn't start with a '/' xx or '.' xx
* then cwd is appended to result. * then cwd is appended to result.
* - the first element of cdpathp is appended to result * - the first element of cdpathp is appended to result
* - file is appended to result * - file is appended to result
@ -1983,16 +1983,18 @@ make_path(const char *cwd, const char *file,
XcheckN(*xsp, xp, len); XcheckN(*xsp, xp, len);
memcpy(xp, cwd, len); memcpy(xp, cwd, len);
xp += len; xp += len;
if (!mksh_cdirsep(cwd[len - 1])) if (mksh_cdirsep(xp[-1]))
Xput(*xsp, xp, '/'); xp--;
*xp++ = '/';
} }
*phys_pathp = Xlength(*xsp, xp); *phys_pathp = Xlength(*xsp, xp);
if (use_cdpath && plen) { if (use_cdpath && plen) {
XcheckN(*xsp, xp, plen); XcheckN(*xsp, xp, plen);
memcpy(xp, plist, plen); memcpy(xp, plist, plen);
xp += plen; xp += plen;
if (!mksh_cdirsep(plist[plen - 1])) if (mksh_cdirsep(xp[-1]))
Xput(*xsp, xp, '/'); xp--;
*xp++ = '/';
rval = 1; rval = 1;
} }
} }
@ -2056,9 +2058,14 @@ simplify_path(char *p)
case '\\': case '\\':
#endif #endif
/* exactly two leading slashes? (SUSv4 3.266) */ /* exactly two leading slashes? (SUSv4 3.266) */
if (p[1] == p[0] && !mksh_cdirsep(p[2])) if (p[1] == p[0] && !mksh_cdirsep(p[2])) {
/* keep them, e.g. for UNC pathnames */ /* keep them, e.g. for UNC pathnames */
#ifdef MKSH_DOSPATH
*p++ = '/';
#else
++p; ++p;
#endif
}
needslash = true; needslash = true;
break; break;
default: default:
@ -2189,26 +2196,26 @@ c_cd(const char **wp)
oldpwd_s = global(TOLDPWD); oldpwd_s = global(TOLDPWD);
if (!wp[0]) { if (!wp[0]) {
/* No arguments - go home */ /* no arguments; go home */
if ((dir = str_val(global("HOME"))) == null) { if ((dir = str_val(global("HOME"))) == null) {
bi_errorf("no home directory (HOME not set)"); bi_errorf("no home directory (HOME not set)");
return (2); return (2);
} }
} else if (!wp[1]) { } else if (!wp[1]) {
/* One argument: - or dir */ /* one argument: - or dir */
strdupx(allocd, wp[0], ATEMP); if (ksh_isdash(wp[0])) {
if (ksh_isdash((dir = allocd))) {
afree(allocd, ATEMP);
allocd = NULL;
dir = str_val(oldpwd_s); dir = str_val(oldpwd_s);
if (dir == null) { if (dir == null) {
bi_errorf(Tno_OLDPWD); bi_errorf(Tno_OLDPWD);
return (2); return (2);
} }
printpath = true; printpath = true;
} else {
strdupx(allocd, wp[0], ATEMP);
dir = allocd;
} }
} else if (!wp[2]) { } else if (!wp[2]) {
/* Two arguments - substitute arg1 in PWD for arg2 */ /* two arguments; substitute arg1 in PWD for arg2 */
size_t ilen, olen, nlen, elen; size_t ilen, olen, nlen, elen;
char *cp; char *cp;
@ -2217,10 +2224,9 @@ c_cd(const char **wp)
return (2); return (2);
} }
/* /*
* substitute arg1 for arg2 in current path. * Substitute arg1 for arg2 in current path. If the first
* if the first substitution fails because the cd fails * substitution fails because the cd fails we could try to
* we could try to find another substitution. For now * find another substitution. For now, we don't.
* we don't
*/ */
if ((cp = strstr(current_wd, wp[0])) == NULL) { if ((cp = strstr(current_wd, wp[0])) == NULL) {
bi_errorf(Tbadsubst); bi_errorf(Tbadsubst);

View file

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.491 2020/05/16 22:12:36 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.494 2020/10/01 22:39:57 tg Exp $
.\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $ .\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $
.\"- .\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
@ -84,7 +84,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to .\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always. .\" use our own definition. And .Dd must come *first*, always.
.\" .\"
.Dd $Mdocdate: May 16 2020 $ .Dd $Mdocdate: October 1 2020 $
.\" .\"
.\" Check which macro package we use, and do other -mdoc setup. .\" Check which macro package we use, and do other -mdoc setup.
.\" .\"
@ -1414,7 +1414,7 @@ or
where where
.Ar name .Ar name
is a parameter name. is a parameter name.
Substitutions of an an array in scalar context, i.e. without an Substitutions of an array in scalar context, i.e. without an
.Ar expr .Ar expr
in the latter form mentioned above, expand the element with the key in the latter form mentioned above, expand the element with the key
.Dq 0 . .Dq 0 .
@ -5333,10 +5333,16 @@ Set the number of cached threads to
Impose a size limit of Impose a size limit of
.Ar n .Ar n
blocks on the size of core dumps. blocks on the size of core dumps.
Silently ignored if the system does not support this limit.
.It Fl d Ar n .It Fl d Ar n
Limit the size of the data area to Limit the size of the data area to
.Ar n .Ar n
kibibytes. kibibytes.
.br
On some systems, read-only maximum
.Xr brk 2
size minus
.Li etext .
.It Fl e Ar n .It Fl e Ar n
Set the maximum niceness to Set the maximum niceness to
.Ar n . .Ar n .
@ -5369,6 +5375,7 @@ kibibytes on the amount of physical memory used.
Impose a limit of Impose a limit of
.Ar n .Ar n
file descriptors that can be open at once. file descriptors that can be open at once.
On some systems attempts to set are silently ignored.
.It Fl O Ar n .It Fl O Ar n
Set the number of AIO operations to Set the number of AIO operations to
.Ar n . .Ar n .
@ -6064,11 +6071,18 @@ words.
.Op Ar n .Op Ar n
.No \*(haXe .No \*(haXe
.Xc .Xc
Edit line Internally run the command
.Ic fc \-e \&"${VISUAL:\-${EDITOR:\-vi}}" Fl \- Ar n
.br
on a temporary script file to interactively edit line
.Ar n .Ar n
or the current line, if not specified, interactively. (if
The actual command executed is .Ar n
.Ic fc \-e ${VISUAL:\-${EDITOR:\-vi}} Ar n . is not specified, the current line); then, unless the editor invoked
exits nonzero but even if the script was not changed, execute the
resulting script as if typed on the command line; both the edited
.Pq resulting
and original lines are added onto history.
.It end\-of\-history: \*(ha[\*(Gt .It end\-of\-history: \*(ha[\*(Gt
Moves to the end of the history. Moves to the end of the history.
.It end\-of\-line: \*(haE, ANSI-End, PC-End .It end\-of\-line: \*(haE, ANSI-End, PC-End
@ -6426,15 +6440,18 @@ is not specified, it goes to the most recent remembered line.
.It Xo .It Xo
.Oo Ar n Oc Ns v .Oo Ar n Oc Ns v
.Xc .Xc
Edit line Internally run the command
.Ic fc \-e \&"${VISUAL:\-${EDITOR:\-vi}}" Fl \- Ar n
.br
on a temporary script file to interactively edit line
.Ar n .Ar n
using the (if
.Xr vi 1
editor; if
.Ar n .Ar n
is not specified, the current line is edited. is not specified, the current line); then, unless the editor invoked
The actual command executed is exits nonzero but even if the script was not changed, execute the
.Ic fc \-e ${VISUAL:\-${EDITOR:\-vi}} Ar n . resulting script as if typed on the command line; both the edited
.Pq resulting
and original lines are added onto history.
.It * and \*(haX .It * and \*(haX
Command or file name expansion is applied to the current big-word (with an Command or file name expansion is applied to the current big-word (with an
appended appended
@ -7072,7 +7089,7 @@ for the in-memory portion of the history is slow, should use
.Xr memmove 3 . .Xr memmove 3 .
.Pp .Pp
This document attempts to describe This document attempts to describe
.Nm mksh\ R59b .Nm mksh\ R59c
and up, and up,
.\" with vendor patches from insert-your-name-here, .\" with vendor patches from insert-your-name-here,
compiled without any options impacting functionality, such as compiled without any options impacting functionality, such as

View file

@ -1,4 +1,4 @@
RCSID: $MirOS: src/bin/mksh/mksh.faq,v 1.7 2020/04/25 12:09:55 tg Exp $ RCSID: $MirOS: src/bin/mksh/mksh.faq,v 1.10 2020/10/01 22:59:12 tg Exp $
ToC: spelling ToC: spelling
Title: How do you spell <tt>mksh</tt>? How do you pronounce it? Title: How do you spell <tt>mksh</tt>? How do you pronounce it?
@ -207,7 +207,7 @@ Title: Why doesnt this use a Makefile to build?
ToC: oldbsd ToC: oldbsd
Title: Why do other BSDs and QNX still use pdksh instead of mksh? Title: Why do other BSDs and QNX still use pdksh instead of mksh?
<p>Some systems are resistent to change, mostly due to bikeshedding <p>Some systems are resistant to change, mostly due to bikeshedding
(some people would, for example, rather see all shells banned to (some people would, for example, rather see all shells banned to
ports/pkgsrc®) and hysterial raisins (historical reasons ☻). Most ports/pkgsrc®) and hysterial raisins (historical reasons ☻). Most
BSDs have mksh packages available, and it works on all of them and BSDs have mksh packages available, and it works on all of them and
@ -297,6 +297,29 @@ pdksh derivative); <tt>$SH_VERSION</tt> (“PD KSH” as sh), <tt>$YASH_VERSION<
(yash), <tt>$ZSH_VERSION</tt> (or if <tt>$VERSION</tt> begins with “zsh”); a <a (yash), <tt>$ZSH_VERSION</tt> (or if <tt>$VERSION</tt> begins with “zsh”); a <a
href="@@RELPATH@@ksh-chan.htm#which-shell">list of more approaches</a> exists. href="@@RELPATH@@ksh-chan.htm#which-shell">list of more approaches</a> exists.
---- ----
ToC: ctrl-x-e
Title: Multiline command editing
<p>mksh is very independent of the terminal and external libraries and
databases, such as termcap, and therefore is conservative in which ANSI
control codes are sent to the terminal.</p>
<p>For this reason, mkshs input line editing uses a “windowed one-line”
concept: the line the cursor is on is a “window” into the whole input,
horizontally scrolled. Some other shells (that are much larger and have
more dependencies on external tooling) use a “multi-line” editing mode,
and users occasionally wish for this. It is on the long-term TODO, but
(due to the aforementioned implications) this is not trivial.</p>
<p>One way to achieve multi-line editing is to <em>dis</em>able input
line editing: <tt>set +o emacs +o vi</tt><br />This will, however, lose
you all editing features: tab completion, cursor keys, history, etc.</p>
<p>Another way, if you dont need it all the time, is to use a function
that spawns your editor on the input line: press <tt>^Xe</tt> in the
default emacs mode or <tt>Esc + v</tt> in vi mode. Once you exit the
editor, whatever was written there is run; this includes the original
command line if you quit without saving, so request the editor to exit
nōn-zero (e.g. using jupps “abendjoe” command) to prevent execution.
This is <em>really</em> useful to write ad-hōc scripts as well.</p>
----
ToC: ctrl-l-cls ToC: ctrl-l-cls
Title: ^L (Ctrl-L) does not clear the screen Title: ^L (Ctrl-L) does not clear the screen
@ -439,6 +462,15 @@ Title: I get an error in this regex comparison
 becomes…<br />  becomes…<br />
<tt>[[ foo = *@(foo|bar)*baz* ]]</tt></p> <tt>[[ foo = *@(foo|bar)*baz* ]]</tt></p>
---- ----
ToC: trim-vector
Title: ${@?}: bad substitution
<p>In mksh, you cannot assign to or trim a vector (yet). For most
cases it is possible to write the affected code in a way avoiding
this extension; for example, trimming <tt>${@#foo}</tt> could be
applied to <tt>$1</tt> only and <tt>${@?}</tt> can be replaced
with a test whether <tt>$# -eq 0</tt>.</p>
----
ToC: extensions-to-avoid ToC: extensions-to-avoid
Title: Are there any extensions to avoid? Title: Are there any extensions to avoid?

View file

@ -1,7 +1,7 @@
/*- /*-
* Copyright (c) 2015, 2017, 2020 * Copyright (c) 2015, 2017, 2020
* KO Myung-Hun <komh@chollian.net> * KO Myung-Hun <komh@chollian.net>
* Copyright (c) 2017 * Copyright (c) 2017, 2020
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -32,11 +32,23 @@
#include <unistd.h> #include <unistd.h>
#include <process.h> #include <process.h>
__RCSID("$MirOS: src/bin/mksh/os2.c,v 1.10 2020/04/07 11:13:45 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/os2.c,v 1.11 2020/10/01 21:13:45 tg Exp $");
static char *remove_trailing_dots(char *); struct a_s_arg {
static int access_stat_ex(int (*)(), const char *, void *); union {
static int test_exec_exist(const char *, char *); int (*i)(const char *, int);
int (*p)(const char *, void *);
} fn;
union {
int i;
void *p;
} arg;
bool isint;
};
static void remove_trailing_dots(char *, size_t);
static int access_stat_ex(const char *, struct a_s_arg *);
static int test_exec_exist(const char *, void *);
static void response(int *, const char ***); static void response(int *, const char ***);
static char *make_response_file(char * const *); static char *make_response_file(char * const *);
static void add_temp(const char *); static void add_temp(const char *);
@ -223,23 +235,18 @@ setextlibpath(const char *name, const char *val)
} }
/* remove trailing dots */ /* remove trailing dots */
static char * static void
remove_trailing_dots(char *name) remove_trailing_dots(char *name, size_t namelen)
{ {
char *p = strnul(name); char *p = name + namelen;
while (--p > name && *p == '.') while (--p > name && *p == '.')
/* nothing */; /* nothing */;
if (*p != '.' && *p != '/' && *p != '\\' && *p != ':') if (*p != '.' && *p != '/' && *p != '\\' && *p != ':')
p[1] = '\0'; p[1] = '\0';
return (name);
} }
#define REMOVE_TRAILING_DOTS(name) \
remove_trailing_dots(memcpy(alloca(strlen(name) + 1), name, strlen(name) + 1))
/* alias of stat() */ /* alias of stat() */
extern int _std_stat(const char *, struct stat *); extern int _std_stat(const char *, struct stat *);
@ -247,7 +254,12 @@ extern int _std_stat(const char *, struct stat *);
int int
stat(const char *name, struct stat *buffer) stat(const char *name, struct stat *buffer)
{ {
return (_std_stat(REMOVE_TRAILING_DOTS(name), buffer)); size_t namelen = strlen(name) + 1;
char nodots[namelen];
memcpy(nodots, name, namelen);
remove_trailing_dots(nodots, namelen);
return (_std_stat(nodots, buffer));
} }
/* alias of access() */ /* alias of access() */
@ -257,6 +269,9 @@ extern int _std_access(const char *, int);
int int
access(const char *name, int mode) access(const char *name, int mode)
{ {
size_t namelen = strlen(name) + 1;
char nodots[namelen];
/* /*
* On OS/2 kLIBC, X_OK is set only for executable files. * On OS/2 kLIBC, X_OK is set only for executable files.
* This prevents scripts from being executed. * This prevents scripts from being executed.
@ -264,7 +279,9 @@ access(const char *name, int mode)
if (mode & X_OK) if (mode & X_OK)
mode = (mode & ~X_OK) | R_OK; mode = (mode & ~X_OK) | R_OK;
return (_std_access(REMOVE_TRAILING_DOTS(name), mode)); memcpy(nodots, name, namelen);
remove_trailing_dots(nodots, namelen);
return (_std_access(nodots, mode));
} }
#define MAX_X_SUFFIX_LEN 4 #define MAX_X_SUFFIX_LEN 4
@ -274,7 +291,7 @@ static const char *x_suffix_list[] =
/* call fn() by appending executable extensions */ /* call fn() by appending executable extensions */
static int static int
access_stat_ex(int (*fn)(), const char *name, void *arg) access_stat_ex(const char *name, struct a_s_arg *action)
{ {
char *x_name; char *x_name;
const char **x_suffix; const char **x_suffix;
@ -288,7 +305,8 @@ access_stat_ex(int (*fn)(), const char *name, void *arg)
strlcpy(x_name, name, x_namelen); strlcpy(x_name, name, x_namelen);
strlcat(x_name, *x_suffix, x_namelen); strlcat(x_name, *x_suffix, x_namelen);
rc = fn(x_name, arg); rc = action->isint ? action->fn.i(x_name, action->arg.i) :
action->fn.p(x_name, action->arg.p);
} }
afree(x_name, ATEMP); afree(x_name, ATEMP);
@ -300,8 +318,12 @@ access_stat_ex(int (*fn)(), const char *name, void *arg)
int int
access_ex(int (*fn)(const char *, int), const char *name, int mode) access_ex(int (*fn)(const char *, int), const char *name, int mode)
{ {
/*XXX this smells fishy --mirabilos */ struct a_s_arg arg;
return (access_stat_ex(fn, name, (void *)mode));
arg.fn.i = fn;
arg.arg.i = mode;
arg.isint = true;
return (access_stat_ex(name, &arg));
} }
/* stat()/lstat() version */ /* stat()/lstat() version */
@ -309,34 +331,39 @@ int
stat_ex(int (*fn)(const char *, struct stat *), stat_ex(int (*fn)(const char *, struct stat *),
const char *name, struct stat *buffer) const char *name, struct stat *buffer)
{ {
return (access_stat_ex(fn, name, buffer)); struct a_s_arg arg;
arg.fn.p = fn;
arg.arg.p = buffer;
arg.isint = false;
return (access_stat_ex(name, &arg));
} }
static int static int
test_exec_exist(const char *name, char *real_name) test_exec_exist(const char *name, void *arg)
{ {
struct stat sb; struct stat sb;
char *real_name;
if (stat(name, &sb) < 0 || !S_ISREG(sb.st_mode)) if (stat(name, &sb) < 0 || !S_ISREG(sb.st_mode))
return (-1); return (-1);
/* safe due to calculations in real_exec_name() */ /*XXX memory leak */
memcpy(real_name, name, strlen(name) + 1); strdupx(real_name, name, ATEMP);
*((char **)arg) = real_name;
return (0); return (0);
} }
const char * const char *
real_exec_name(const char *name) real_exec_name(const char *name)
{ {
char x_name[strlen(name) + MAX_X_SUFFIX_LEN + 1]; struct a_s_arg arg;
const char *real_name = name; char *real_name;
if (access_stat_ex(test_exec_exist, real_name, x_name) != -1) arg.fn.p = &test_exec_exist;
/*XXX memory leak */ arg.arg.p = (void *)(&real_name);
strdupx(real_name, x_name, ATEMP); arg.isint = false;
return (access_stat_ex(name, &arg) ? name : real_name);
return (real_name);
} }
/* make a response file to pass a very long command line */ /* make a response file to pass a very long command line */

View file

@ -1,6 +1,6 @@
/* +++ GENERATED FILE +++ DO NOT EDIT +++ */ /* +++ GENERATED FILE +++ DO NOT EDIT +++ */
/*- /*-
* Copyright (c) 2013, 2015 * Copyright (c) 2013, 2015, 2019
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -17,11 +17,13 @@
* of dealing in the work, even if advised of the possibility of such * 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 * damage or existence of a defect, except proven that it results out
* of said person's immediate fault when using the work as intended. * of said person's immediate fault when using the work as intended.
*-
* Keep {r,u}limits.opt in sync with each other!
*/ */
#ifndef RLIMITS_OPTCS #ifndef RLIMITS_OPTCS
#if defined(RLIMITS_DEFNS) #if defined(RLIMITS_DEFNS)
__RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.4 2019/04/24 20:56:31 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.5 2020/07/24 20:11:18 tg Exp $");
#elif defined(RLIMITS_ITEMS) #elif defined(RLIMITS_ITEMS)
#define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid), #define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
#endif #endif

View file

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2013, 2015 * Copyright (c) 2013, 2015, 2019
* mirabilos <m@mirbsd.org> * mirabilos <m@mirbsd.org>
* *
* Provided that these terms and disclaimer and all copyright notices * Provided that these terms and disclaimer and all copyright notices
@ -16,10 +16,12 @@
* of dealing in the work, even if advised of the possibility of such * 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 * damage or existence of a defect, except proven that it results out
* of said person's immediate fault when using the work as intended. * of said person's immediate fault when using the work as intended.
*-
* Keep {r,u}limits.opt in sync with each other!
*/ */
@RLIMITS_DEFNS @RLIMITS_DEFNS
__RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.4 2019/04/24 20:56:31 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.5 2020/07/24 20:11:18 tg Exp $");
@RLIMITS_ITEMS @RLIMITS_ITEMS
#define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid), #define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
@@ @@

View file

@ -78,7 +78,9 @@
#if HAVE_PATHS_H #if HAVE_PATHS_H
#include <paths.h> #include <paths.h>
#endif #endif
#ifndef MKSH_NOPWNAM
#include <pwd.h> #include <pwd.h>
#endif
#include <setjmp.h> #include <setjmp.h>
#include <signal.h> #include <signal.h>
#include <stdarg.h> #include <stdarg.h>
@ -191,9 +193,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.898 2020/05/16 22:38:23 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.904 2020/10/31 03:53:06 tg Exp $");
#endif #endif
#define MKSH_VERSION "R59 2020/05/16" #define MKSH_VERSION "R59 2020/10/31"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES
@ -247,10 +249,6 @@ typedef u_int8_t uint8_t;
/* other standard types */ /* other standard types */
#if !HAVE_RLIM_T
typedef unsigned long rlim_t;
#endif
#if !HAVE_SIG_T #if !HAVE_SIG_T
#undef sig_t #undef sig_t
typedef void (*sig_t)(int); typedef void (*sig_t)(int);
@ -668,7 +666,7 @@ char *ucstrstr(char *, const char *);
#endif #endif
#endif #endif
#if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 592) #if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 593)
#error Must run Build.sh to compile this. #error Must run Build.sh to compile this.
extern void thiswillneverbedefinedIhope(void); extern void thiswillneverbedefinedIhope(void);
int int
@ -2522,7 +2520,7 @@ void sethistfile(const char *);
char **histpos(void) MKSH_A_PURE; char **histpos(void) MKSH_A_PURE;
int histnum(int); int histnum(int);
#endif #endif
int findhist(int, int, const char *, bool) MKSH_A_PURE; int findhist(int, const char *, bool, bool) MKSH_A_PURE;
char **hist_get_newest(bool); char **hist_get_newest(bool);
void inittraps(void); void inittraps(void);
void alarm_init(void); void alarm_init(void);

View file

@ -27,7 +27,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.101 2019/12/11 17:56:58 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/shf.c,v 1.102 2020/06/22 17:11:03 tg Exp $");
/* flags to shf_emptybuf() */ /* flags to shf_emptybuf() */
#define EB_READSW 0x01 /* about to switch to reading */ #define EB_READSW 0x01 /* about to switch to reading */
@ -666,7 +666,7 @@ shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
if (nbytes < 0) if (nbytes < 0)
internal_errorf(Tf_szs, Tshf_write, nbytes, Tbytes); internal_errorf(Tf_szs, Tshf_write, nbytes, Tbytes);
/* Don't buffer if buffer is empty and we're writting a large amount. */ /* don't buffer if buffer is empty and we're writing a large amount */
if ((ncopy = shf->wnleft) && if ((ncopy = shf->wnleft) &&
(shf->wp != shf->buf || nbytes < shf->wnleft)) { (shf->wp != shf->buf || nbytes < shf->wnleft)) {
if (ncopy > nbytes) if (ncopy > nbytes)
@ -782,7 +782,7 @@ shf_smprintf(const char *fmt, ...)
#define FL_ZERO 0x040 /* '0' seen */ #define FL_ZERO 0x040 /* '0' seen */
#define FL_DOT 0x080 /* '.' seen */ #define FL_DOT 0x080 /* '.' seen */
#define FL_UPPER 0x100 /* format character was uppercase */ #define FL_UPPER 0x100 /* format character was uppercase */
#define FL_NUMBER 0x200 /* a number was formated %[douxefg] */ #define FL_NUMBER 0x200 /* a number was formatted %[douxefg] */
#define FL_SIZET 0x400 /* 'z' seen */ #define FL_SIZET 0x400 /* 'z' seen */
#define FM_SIZES 0x430 /* h/l/z mask */ #define FM_SIZES 0x430 /* h/l/z mask */

View file

@ -24,7 +24,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.128 2020/03/31 00:30:05 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.129 2020/10/31 01:21:58 tg Exp $");
struct nesting_state { struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */ int start_token; /* token than began nesting (eg, FOR) */
@ -268,13 +268,12 @@ get_command(int cf, int sALIAS)
{ {
struct op *t; struct op *t;
int c, iopn = 0, syniocf, lno; int c, iopn = 0, syniocf, lno;
struct ioword *iop, **iops; struct ioword *iop;
XPtrV args, vars; XPtrV args, vars;
struct nesting_state old_nesting; struct nesting_state old_nesting;
bool check_decl_utility; bool check_decl_utility;
static struct ioword *iops[NUFILE + 1];
/* NUFILE is small enough to leave this addition unchecked */
iops = alloc2((NUFILE + 1), sizeof(struct ioword *), ATEMP);
XPinit(args, 16); XPinit(args, 16);
XPinit(vars, 16); XPinit(vars, 16);
@ -282,7 +281,6 @@ get_command(int cf, int sALIAS)
switch (c = token(cf|KEYWORD|sALIAS|CMDASN)) { switch (c = token(cf|KEYWORD|sALIAS|CMDASN)) {
default: default:
REJECT; REJECT;
afree(iops, ATEMP);
XPfree(args); XPfree(args);
XPfree(vars); XPfree(vars);
/* empty line */ /* empty line */
@ -510,12 +508,11 @@ get_command(int cf, int sALIAS)
} }
if (iopn == 0) { if (iopn == 0) {
afree(iops, ATEMP);
t->ioact = NULL; t->ioact = NULL;
} else { } else {
iops[iopn++] = NULL; iops[iopn++] = NULL;
iops = aresize2(iops, iopn, sizeof(struct ioword *), ATEMP); t->ioact = alloc2(iopn, sizeof(struct ioword *), ATEMP);
t->ioact = iops; memcpy(t->ioact, iops, iopn * sizeof(struct ioword *));
} }
if (t->type == TCOM || t->type == TDBRACKET) { if (t->type == TCOM || t->type == TDBRACKET) {

View file

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.97 2018/10/20 18:46:00 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.100 2020/10/31 04:28:54 tg Exp $");
#define INDENT 8 #define INDENT 8
@ -37,6 +37,19 @@ static void iofree(struct ioword **, Area *);
/* "foo& ; bar" and "foo |& ; bar" are invalid */ /* "foo& ; bar" and "foo |& ; bar" are invalid */
static bool prevent_semicolon; static bool prevent_semicolon;
/* here document diversion */
static unsigned short ptree_nest;
static bool ptree_hashere;
static struct shf ptree_heredoc;
#define ptree_outhere(shf) do { \
if (ptree_hashere) { \
shf_puts(shf_sclose(&ptree_heredoc), (shf)); \
shf_putc('\n', (shf)); \
ptree_hashere = false; \
/*prevent_semicolon = true;*/ \
} \
} while (/* CONSTCOND */ 0)
static const char Telif_pT[] = "elif %T"; static const char Telif_pT[] = "elif %T";
/* /*
@ -82,8 +95,11 @@ ptree(struct op *t, int indent, struct shf *shf)
w = (const char **)t->vars; w = (const char **)t->vars;
while (*w) while (*w)
fptreef(shf, indent, Tf_S_, *w++); fptreef(shf, indent, Tf_S_, *w++);
} else }
#ifndef MKSH_SMALL
else
shf_puts("#no-vars# ", shf); shf_puts("#no-vars# ", shf);
#endif
if (t->args) { if (t->args) {
w = t->args; w = t->args;
if (*w && **w == CHAR) { if (*w && **w == CHAR) {
@ -97,8 +113,11 @@ ptree(struct op *t, int indent, struct shf *shf)
} }
while (*w) while (*w)
fptreef(shf, indent, Tf_S_, *w++); fptreef(shf, indent, Tf_S_, *w++);
} else }
#ifndef MKSH_SMALL
else
shf_puts("#no-args# ", shf); shf_puts("#no-args# ", shf);
#endif
break; break;
case TEXEC: case TEXEC:
t = t->left; t = t->left;
@ -221,36 +240,9 @@ ptree(struct op *t, int indent, struct shf *shf)
prevent_semicolon = false; prevent_semicolon = false;
break; break;
} }
if ((ioact = t->ioact) != NULL) { if ((ioact = t->ioact) != NULL)
bool need_nl = false;
while (*ioact != NULL) while (*ioact != NULL)
pioact(shf, *ioact++); pioact(shf, *ioact++);
/* Print here documents after everything else... */
ioact = t->ioact;
while (*ioact != NULL) {
struct ioword *iop = *ioact++;
/* heredoc is NULL when tracing (set -x) */
if ((iop->ioflag & (IOTYPE | IOHERESTR)) == IOHERE &&
iop->heredoc) {
shf_putc('\n', shf);
shf_puts(iop->heredoc, shf);
fptreef(shf, indent, Tf_s,
evalstr(iop->delim, 0));
need_nl = true;
}
}
/*
* Last delimiter must be followed by a newline (this
* often leads to an extra blank line, but it's not
* worth worrying about)
*/
if (need_nl) {
shf_putc('\n', shf);
prevent_semicolon = true;
}
}
} }
static void static void
@ -272,11 +264,29 @@ pioact(struct shf *shf, struct ioword *iop)
shf_putc('<', shf); shf_putc('<', shf);
break; break;
case IOHERE: case IOHERE:
if (flag & IOHERESTR) {
shf_puts("<<<", shf);
goto ioheredelim;
}
shf_puts("<<", shf); shf_puts("<<", shf);
if (flag & IOSKIP) if (flag & IOSKIP)
shf_putc('-', shf); shf_putc('-', shf);
else if (flag & IOHERESTR) if (iop->heredoc /* nil when tracing */) {
shf_putc('<', shf); /* here document diversion */
if (!ptree_hashere) {
shf_sopen(NULL, 0, SHF_WR | SHF_DYNAMIC,
&ptree_heredoc);
ptree_hashere = true;
}
shf_putc('\n', &ptree_heredoc);
shf_puts(iop->heredoc, &ptree_heredoc);
/* iop->delim is set before iop->heredoc */
shf_puts(evalstr(iop->delim, 0), &ptree_heredoc);
}
ioheredelim:
/* delim is NULL during syntax error printing */
if (iop->delim && !(iop->ioflag & IONDELIM))
wdvarput(shf, iop->delim, 0, WDS_TPUTS);
break; break;
case IOCAT: case IOCAT:
shf_puts(">>", shf); shf_puts(">>", shf);
@ -293,11 +303,8 @@ pioact(struct shf *shf, struct ioword *iop)
shf_puts(flag & IORDUP ? "<&" : ">&", shf); shf_puts(flag & IORDUP ? "<&" : ">&", shf);
break; break;
} }
/* name/delim are NULL when printing syntax errors */ /* name is NULL for IOHERE or when printing syntax errors */
if (type == IOHERE) { if (iop->ioname) {
if (iop->delim && !(iop->ioflag & IONDELIM))
wdvarput(shf, iop->delim, 0, WDS_TPUTS);
} else if (iop->ioname) {
if (flag & IONAMEXP) if (flag & IONAMEXP)
print_value_quoted(shf, iop->ioname); print_value_quoted(shf, iop->ioname);
else else
@ -342,13 +349,6 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
c = ord(*wp++); c = ord(*wp++);
if (opmode & WDS_TPUTS) if (opmode & WDS_TPUTS)
switch (c) { switch (c) {
case ORD('\n'):
if (quotelevel == 0) {
c = ORD('\'');
shf_putc(c, shf);
shf_putc(ORD('\n'), shf);
}
break;
default: default:
if (quotelevel == 0) if (quotelevel == 0)
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -467,6 +467,9 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
{ {
int c; int c;
if (!ptree_nest++)
ptree_hashere = false;
while ((c = ord(*fmt++))) { while ((c = ord(*fmt++))) {
if (c == '%') { if (c == '%') {
switch ((c = ord(*fmt++))) { switch ((c = ord(*fmt++))) {
@ -504,10 +507,10 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
shf_putc(';', shf); shf_putc(';', shf);
shf_putc(' ', shf); shf_putc(' ', shf);
} else { } else {
int i; int i = indent;
ptree_outhere(shf);
shf_putc('\n', shf); shf_putc('\n', shf);
i = indent;
while (i >= 8) { while (i >= 8) {
shf_putc('\t', shf); shf_putc('\t', shf);
i -= 8; i -= 8;
@ -530,6 +533,9 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
dont_trash_prevent_semicolon: dont_trash_prevent_semicolon:
; ;
} }
if (!--ptree_nest)
ptree_outhere(shf);
} }
/* /*

360
src/ulimit.c Normal file
View file

@ -0,0 +1,360 @@
/* $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, 2014, 2015, 2016, 2017,
* 2019, 2020
* mirabilos <m@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.
*/
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/ulimit.c,v 1.3 2020/07/24 21:08:26 tg Exp $");
#define SOFT 0x1
#define HARD 0x2
#if HAVE_RLIMIT
#if !HAVE_RLIM_T
typedef unsigned long rlim_t;
#endif
/* Magic to divine the 'm' and 'v' limits */
#ifdef RLIMIT_AS
#if !defined(RLIMIT_VMEM) || (RLIMIT_VMEM == RLIMIT_AS) || \
!defined(RLIMIT_RSS) || (RLIMIT_VMEM == RLIMIT_RSS)
#define ULIMIT_V_IS_AS
#elif defined(RLIMIT_VMEM)
#if !defined(RLIMIT_RSS) || (RLIMIT_RSS == RLIMIT_AS)
#define ULIMIT_V_IS_AS
#else
#define ULIMIT_V_IS_VMEM
#endif
#endif
#endif
#ifdef RLIMIT_RSS
#ifdef ULIMIT_V_IS_VMEM
#define ULIMIT_M_IS_RSS
#elif defined(RLIMIT_VMEM) && (RLIMIT_VMEM == RLIMIT_RSS)
#define ULIMIT_M_IS_VMEM
#else
#define ULIMIT_M_IS_RSS
#endif
#if defined(ULIMIT_M_IS_RSS) && defined(RLIMIT_AS) && \
!defined(__APPLE__) && (RLIMIT_RSS == RLIMIT_AS)
/* On Mac OSX keep -m as -v alias for pkgsrc and other software expecting it */
#undef ULIMIT_M_IS_RSS
#endif
#endif
#if !defined(RLIMIT_AS) && !defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_VMEM)
#define ULIMIT_V_IS_VMEM
#endif
#if !defined(ULIMIT_V_IS_VMEM) && defined(RLIMIT_VMEM) && \
(!defined(RLIMIT_RSS) || (defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)))
#define ULIMIT_M_IS_VMEM
#endif
#if defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_AS) && \
(RLIMIT_VMEM == 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 LIMITS_GEN "rlimits.gen"
#else /* !HAVE_RLIMIT */
#undef RLIMIT_CORE /* just in case */
#if defined(UL_GETFSIZE)
#define KSH_UL_GFIL UL_GETFSIZE
#elif defined(UL_GFILLIM)
#define KSH_UL_GFIL UL_GFILLIM
#elif defined(__A_UX__) || defined(KSH_ULIMIT2_TEST)
#define KSH_UL_GFIL 1
#endif
#if defined(UL_SETFSIZE)
#define KSH_UL_SFIL UL_SETFSIZE
#elif defined(UL_SFILLIM)
#define KSH_UL_SFIL UL_SFILLIM
#elif defined(__A_UX__) || defined(KSH_ULIMIT2_TEST)
#define KSH_UL_SFIL 2
#endif
#if defined(KSH_UL_SFIL)
#define KSH_UL_WFIL true
#else
#define KSH_UL_WFIL false
#define KSH_UL_SFIL 0
#endif
#if defined(UL_GETMAXBRK)
#define KSH_UL_GBRK UL_GETMAXBRK
#elif defined(UL_GMEMLIM)
#define KSH_UL_GBRK UL_GMEMLIM
#elif defined(__A_UX__) || defined(KSH_ULIMIT2_TEST)
#define KSH_UL_GBRK 3
#endif
#if defined(UL_GDESLIM)
#define KSH_UL_GDES UL_GDESLIM
#elif defined(__GLIBC__) || defined(KSH_ULIMIT2_TEST)
#define KSH_UL_GDES 4
#endif
extern char etext;
extern long ulimit(int, long);
#define LIMITS_GEN "ulimits.gen"
#endif /* !HAVE_RLIMIT */
struct limits {
/* limit resource / read command */
int resource;
#if HAVE_RLIMIT
/* multiply by to get rlim_{cur,max} values */
unsigned int factor;
#else
/* write command */
int wesource;
/* writable? */
bool writable;
#endif
/* getopts char */
char optchar;
/* limit name */
char name[1];
};
#define RLIMITS_DEFNS
#if HAVE_RLIMIT
#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 \
};
#else
#define FN(lname,lg,ls,lw,lopt) \
static const struct { \
int rcmd; \
int wcmd; \
bool writable; \
char optchar; \
char name[sizeof(lname)]; \
} rlimits_ ## lg = { \
lg, ls, lw, lopt, lname \
};
#endif
#include LIMITS_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 LIMITS_GEN
};
static const char rlimits_opts[] =
#define RLIMITS_OPTCS
#include LIMITS_GEN
#ifndef RLIMIT_CORE
"c"
#endif
;
int
c_ulimit(const char **wp)
{
size_t i = 0;
int how = SOFT | HARD, optc;
char what = 'f';
bool all = false;
while ((optc = ksh_getopt(wp, &builtin_opt, rlimits_opts)) != -1)
switch (optc) {
case ORD('H'):
how = HARD;
break;
case ORD('S'):
how = SOFT;
break;
case ORD('a'):
all = true;
break;
case ORD('?'):
bi_errorf("usage: ulimit [-%s] [value]", rlimits_opts);
return (1);
default:
what = optc;
}
while (i < NELEM(rlimits)) {
if (rlimits[i]->optchar == what)
goto found;
++i;
}
#ifndef RLIMIT_CORE
if (what == ORD('c'))
/* silently accept */
return 0;
#endif
internal_warningf("ulimit: %c", what);
return (1);
found:
if (wp[builtin_opt.optind]) {
if (all || wp[builtin_opt.optind + 1]) {
bi_errorf(Ttoo_many_args);
return (1);
}
return (set_ulimit(rlimits[i], wp[builtin_opt.optind], how));
}
if (!all)
print_ulimit(rlimits[i], how);
else for (i = 0; i < NELEM(rlimits); ++i) {
shprintf("-%c: %-20s ", rlimits[i]->optchar, rlimits[i]->name);
print_ulimit(rlimits[i], how);
}
return (0);
}
#if HAVE_RLIMIT
#define RL_T rlim_t
#define RL_U (rlim_t)RLIM_INFINITY
#else
#define RL_T long
#define RL_U LONG_MAX
#endif
static int
set_ulimit(const struct limits *l, const char *v, int how MKSH_A_UNUSED)
{
RL_T val = (RL_T)0;
#if HAVE_RLIMIT
struct rlimit limit;
#endif
if (strcmp(v, "unlimited") == 0)
val = RL_U;
else {
mksh_uari_t rval;
if (!evaluate(v, (mksh_ari_t *)&rval, KSH_RETURN_ERROR, false))
return (1);
/*
* Avoid problems caused by typos that evaluate misses due
* to evaluating unset parameters to 0...
* If this causes problems, will have to add parameter to
* evaluate() to control if unset params are 0 or an error.
*/
if (!rval && !ctype(v[0], C_DIGIT)) {
bi_errorf("invalid %s limit: %s", l->name, v);
return (1);
}
#if HAVE_RLIMIT
val = (rlim_t)((rlim_t)rval * l->factor);
#else
val = (RL_T)rval;
#endif
}
#if HAVE_RLIMIT
if (getrlimit(l->resource, &limit) < 0) {
#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;
}
if (how & SOFT)
limit.rlim_cur = val;
if (how & HARD)
limit.rlim_max = val;
if (!setrlimit(l->resource, &limit))
return (0);
#else
if (l->writable == false) {
/* check.t:ulimit-2 fails if we return 1 and/or do:
bi_errorf(Tf_ro, l->name);
*/
return (0);
}
if (ulimit(l->wesource, val) != -1L)
return (0);
#endif
if (errno == EPERM)
bi_errorf("%s exceeds allowable %s limit", v, l->name);
else
bi_errorf("bad %s limit: %s", l->name, cstrerror(errno));
return (1);
}
static void
print_ulimit(const struct limits *l, int how MKSH_A_UNUSED)
{
RL_T val = (RL_T)0;
#if HAVE_RLIMIT
struct rlimit limit;
if (getrlimit(l->resource, &limit))
#else
if ((val = ulimit(l->resource, 0)) < 0)
#endif
{
shf_puts("unknown\n", shl_stdout);
return;
}
#if HAVE_RLIMIT
if (how & SOFT)
val = limit.rlim_cur;
else if (how & HARD)
val = limit.rlim_max;
#endif
if (val == RL_U)
shf_puts("unlimited\n", shl_stdout);
else {
#if HAVE_RLIMIT
val /= l->factor;
#elif defined(KSH_UL_GBRK)
if (l->resource == KSH_UL_GBRK)
val = (RL_T)(((size_t)val - (size_t)&etext) /
(size_t)1024);
#endif
shprintf("%lu\n", (unsigned long)val);
}
}

60
src/ulimits.gen Normal file
View file

@ -0,0 +1,60 @@
/* +++ GENERATED FILE +++ DO NOT EDIT +++ */
/*-
* Copyright (c) 2013, 2015, 2020
* mirabilos <m@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.
*-
* Keep {r,u}limits.opt in sync with each other!
*/
#ifndef RLIMITS_OPTCS
#if defined(RLIMITS_DEFNS)
__RCSID("$MirOS: src/bin/mksh/ulimits.opt,v 1.2 2020/07/24 20:50:11 tg Exp $");
#elif defined(RLIMITS_ITEMS)
#define FN(lname,lg,ls,lw,lopt) (const struct limits *)(&rlimits_ ## lg),
#endif
#ifndef F0
#define F0 FN
#endif
#ifdef KSH_UL_GFIL
FN("file(blocks)", KSH_UL_GFIL, KSH_UL_SFIL, KSH_UL_WFIL, 'f')
#endif
#ifdef KSH_UL_GBRK
FN("data(KiB)", KSH_UL_GBRK, 0, false, 'd')
#endif
#ifdef KSH_UL_GDES
FN("nofiles(descriptors)", KSH_UL_GDES, 0, false, 'n')
#endif
#undef F0
#undef FN
#undef RLIMITS_DEFNS
#undef RLIMITS_ITEMS
#else
"a"
#ifdef KSH_UL_GBRK
"d"
#endif
#ifdef KSH_UL_GFIL
"f"
#endif
"H"
#ifdef KSH_UL_GDES
"n"
#endif
"S"
#undef RLIMITS_OPTCS
#endif

46
src/ulimits.opt Normal file
View file

@ -0,0 +1,46 @@
/*-
* Copyright (c) 2013, 2015, 2020
* mirabilos <m@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.
*-
* Keep {r,u}limits.opt in sync with each other!
*/
@RLIMITS_DEFNS
__RCSID("$MirOS: src/bin/mksh/ulimits.opt,v 1.2 2020/07/24 20:50:11 tg Exp $");
@RLIMITS_ITEMS
#define FN(lname,lg,ls,lw,lopt) (const struct limits *)(&rlimits_ ## lg),
@@
/* generic options for the ulimit builtin */
<a|
<H|
<S|
/* do not use options -H, -S or -a or change the order */
>f|KSH_UL_GFIL
FN("file(blocks)", KSH_UL_GFIL, KSH_UL_SFIL, KSH_UL_WFIL
>d|KSH_UL_GBRK
FN("data(KiB)", KSH_UL_GBRK, 0, false
>n|KSH_UL_GDES
FN("nofiles(descriptors)", KSH_UL_GDES, 0, false
|RLIMITS_OPTCS

View file

@ -29,7 +29,7 @@
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.236 2020/04/13 16:29:34 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/var.c,v 1.237 2020/06/22 17:11:03 tg Exp $");
/*- /*-
* Variables * Variables
@ -1900,7 +1900,7 @@ c_typeset(const char **wp)
break; break;
} }
/* see comment below regarding possible opions */ /* see comment below regarding possible options */
opts = istset ? "L#R#UZ#afgi#lnprtux" : "p"; opts = istset ? "L#R#UZ#afgi#lnprtux" : "p";
builtin_opt.flags |= GF_PLUSOPT; builtin_opt.flags |= GF_PLUSOPT;