From b02792c9ac5b8ff483bec88fdb16c886edf576f7 Mon Sep 17 00:00:00 2001
From: Sadaf Ebrahimi
Date: Fri, 31 Mar 2023 18:17:33 +0000
Subject: [PATCH] Upgrade mksh to mksh-R59c
Test: TreeHugger
Change-Id: I6d4f4497e54fd97672ee0d634b322277326a9748
---
Android.bp | 3 +-
Android.patch.txt | 36 +++--
METADATA | 15 ++
src/Build.sh | 98 ++++++++-----
src/FAQ2HTML.sh | 6 +-
src/check.pl | 6 +-
src/check.t | 47 +++---
src/edit.c | 122 ++++++++--------
src/exec.c | 8 +-
src/expr.c | 7 +-
src/funcs.c | 250 ++++----------------------------
src/histrap.c | 7 +-
src/lksh.1 | 13 +-
src/main.c | 7 +-
src/misc.c | 50 ++++---
src/mksh.1 | 47 ++++--
src/mksh.faq | 36 ++++-
src/os2.c | 89 ++++++++----
src/rlimits.gen | 6 +-
src/rlimits.opt | 6 +-
src/sh.h | 14 +-
src/shf.c | 6 +-
src/syn.c | 13 +-
src/tree.c | 100 +++++++------
src/ulimit.c | 360 ++++++++++++++++++++++++++++++++++++++++++++++
src/ulimits.gen | 60 ++++++++
src/ulimits.opt | 46 ++++++
src/var.c | 4 +-
28 files changed, 934 insertions(+), 528 deletions(-)
create mode 100644 src/ulimit.c
create mode 100644 src/ulimits.gen
create mode 100644 src/ulimits.opt
diff --git a/Android.bp b/Android.bp
index dcb534e..a300947 100644
--- a/Android.bp
+++ b/Android.bp
@@ -38,6 +38,7 @@ cc_defaults {
"src/shf.c",
"src/syn.c",
"src/tree.c",
+ "src/ulimit.c",
"src/var.c",
],
@@ -125,7 +126,7 @@ cc_defaults {
"-DHAVE_SYS_ERRLIST_DECL=0",
"-DHAVE_SYS_SIGLIST_DECL=1",
"-DHAVE_PERSISTENT_HISTORY=0",
- "-DMKSH_BUILD_R=592",
+ "-DMKSH_BUILD_R=593",
// Additional flags
"-DMKSH_DEFAULT_PROFILEDIR=\"/system/etc\"",
diff --git a/Android.patch.txt b/Android.patch.txt
index eefcd5c..72a9db5 100644
--- a/Android.patch.txt
+++ b/Android.patch.txt
@@ -1,8 +1,7 @@
-Only in src: FAQ.htm
-diff -u mksh-R59b/funcs.c src/funcs.c
---- mksh-R59b/funcs.c 2020-05-16 15:38:48.000000000 -0700
-+++ src/funcs.c 2020-05-20 17:14:19.588510856 -0700
-@@ -104,7 +104,9 @@
+diff -u mksh-R59c/mksh/funcs.c src/funcs.c
+--- mksh-R59c/mksh/funcs.c 2020-08-27 19:53:11.000000000 +0000
++++ src/funcs.c 2023-03-31 18:02:12.376044783 +0000
+@@ -98,7 +98,9 @@
{Tsgbreak, c_brkcont},
{T__builtin, c_builtin},
{Tbuiltin, c_builtin},
@@ -12,7 +11,7 @@ diff -u mksh-R59b/funcs.c src/funcs.c
{Tcd, c_cd},
/* dash compatibility hack */
{"chdir", c_cd},
-@@ -125,7 +127,9 @@
+@@ -119,7 +121,9 @@
{"pwd", c_pwd},
{Tread, c_read},
{Tdsgreadonly, c_typeset},
@@ -22,7 +21,7 @@ diff -u mksh-R59b/funcs.c src/funcs.c
{"~rename", c_rename},
{"*=return", c_exitreturn},
{Tsghset, c_set},
-@@ -159,8 +163,10 @@
+@@ -153,8 +157,10 @@
{"~printf", c_printf},
#endif
#if HAVE_SELECT
@@ -33,25 +32,22 @@ diff -u mksh-R59b/funcs.c src/funcs.c
#ifdef __MirBSD__
/* alias to "true" for historical reasons */
{"domainname", c_true},
-diff -u mksh-R59b/main.c src/main.c
---- mksh-R59b/main.c 2020-05-16 15:51:51.000000000 -0700
-+++ src/main.c 2020-05-20 17:14:19.588510856 -0700
-@@ -414,6 +414,12 @@
+diff -u mksh-R59c/mksh/main.c src/main.c
+--- mksh-R59c/mksh/main.c 2020-10-01 20:29:21.000000000 +0000
++++ src/main.c 2023-03-31 18:09:32.827660886 +0000
+@@ -413,6 +413,12 @@
+
/* import environment */
init_environ();
-
++
+ /* override default PATH regardless of environment */
+#ifdef MKSH_DEFPATH_OVERRIDE
+ vp = global(TPATH);
+ setstr(vp, MKSH_DEFPATH_OVERRIDE, KSH_RETURN_ERROR);
+#endif
-+
+
/* for security */
typeset(TinitIFS, 0, 0, 0, 0);
-
-Only in src: main.c.orig
-Only in src: Rebuild.sh
-Only in src: rlimits.gen
-Only in src: sh_flags.gen
-Only in src: signames.inc
-Only in src: test.sh
+Only in src/: rlimits.gen
+Only in src/: sh_flags.gen
+Only in src/: ulimits.gen
diff --git a/METADATA b/METADATA
index d97975c..c6745e1 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,18 @@
+name: "mksh"
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
+ last_upgrade_date {
+ year: 2023
+ month: 3
+ day: 31
+ }
}
diff --git a/src/Build.sh b/src/Build.sh
index 1d30045..597d8ca 100644
--- a/src/Build.sh
+++ b/src/Build.sh
@@ -1,5 +1,5 @@
#!/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,
# 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
@@ -721,6 +721,13 @@ case $TARGET_OS in
add_cppflags -DMKSH_NO_SIGSETJMP
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)
add_cppflags -D_ALL_SOURCE
: "${HAVE_SETLOCALE_CTYPE=0}"
@@ -862,10 +869,9 @@ Minix-vmd)
;;
Minix3)
add_cppflags -DMKSH_UNEMPLOYED
- add_cppflags -DMKSH_NO_LIMITS
add_cppflags -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2 -D_MINIX
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)
;;
@@ -898,7 +904,7 @@ NEXTSTEP)
Ninix3)
# similar to Minix3
add_cppflags -DMKSH_UNEMPLOYED
- add_cppflags -DMKSH_NO_LIMITS
+ : "${MKSH_UNLIMITED=1}" #XXX recheck ulimit
# but no idea what else could be needed
oswarn="; it has unknown issues"
;;
@@ -911,15 +917,14 @@ OS/2)
HAVE_ISOFF_MKSH_ASSUME_UTF8=1
HAVE_TERMIOS_H=0
HAVE_MKNOD=0 # setmode() incompatible
- oswarn="; it is being ported"
check_categories="$check_categories nosymlink"
: "${CC=gcc}"
: "${SIZE=: size}"
SRCS="$SRCS os2.c"
add_cppflags -DMKSH_UNEMPLOYED
add_cppflags -DMKSH_NOPROSPECTOFWORK
- add_cppflags -DMKSH_NO_LIMITS
add_cppflags -DMKSH_DOSPATH
+ : "${MKSH_UNLIMITED=1}"
if test $textmode = 0; then
x='dis'
y='standard OS/2 tools'
@@ -1363,7 +1368,7 @@ esac
etd=" on $et"
case $et in
klibc)
- add_cppflags -DMKSH_NO_LIMITS
+ : "${MKSH_UNLIMITED=1}"
;;
unknown)
# nothing special detected, don’t 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]); }
EOF
-ac_test rlim_t <<-'EOF'
- #include
- #if HAVE_BOTH_TIME_H
- #include
- #include
- #elif HAVE_SYS_TIME_H
- #include
- #elif HAVE_TIME_H
- #include
- #endif
- #if HAVE_SYS_RESOURCE_H
- #include
- #endif
- #include
- int main(void) { return (((int)(rlim_t)0) + isatty(0)); }
-EOF
-
# only testn: added later below
ac_testn sig_t <<-'EOF'
#include
@@ -2067,6 +2055,35 @@ ac_test lock_fcntl '!' flock 1 'whether we can lock files with fcntl' <<-'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
+ #if HAVE_BOTH_TIME_H
+ #include
+ #include
+ #elif HAVE_SYS_TIME_H
+ #include
+ #elif HAVE_TIME_H
+ #include
+ #endif
+ #if HAVE_SYS_RESOURCE_H
+ #include
+ #endif
+ #include
+ int main(void) { return (((int)(rlim_t)0) + isatty(0)); }
+EOF
+
ac_test getrusage <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
@@ -2457,11 +2474,24 @@ mksh_cfg= cfg_NSIG
$e done.
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 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"
-add_cppflags -DMKSH_BUILD_R=592
+add_cppflags -DMKSH_BUILD_R=593
$e $bi$me: Finished configuration testing, now producing output.$ao
@@ -2544,7 +2574,7 @@ cat >test.sh <<-EOF
args[\${#args[*]}]=\$TMPDIR
fi
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 'test.sh built for mksh $dstversion'
cstr='\$os = defined \$^O ? \$^O : "unknown";'
@@ -2604,7 +2634,6 @@ for file in $SRCS; do
op=`echo x"$file" | sed 's/^x\(.*\)\.c$/\1./'`
test -f $file || file=$srcdir/$file
files="$files$sp$file"
- sp=' '
echo "$CC $CFLAGS $CPPFLAGS $emitbc $file || exit 1" >>Rebuild.sh
if test $cm = dragonegg; then
echo "mv ${op}s ${op}ll" >>Rebuild.sh
@@ -2613,6 +2642,7 @@ for file in $SRCS; do
else
objs="$objs$sp${op}o"
fi
+ sp=' '
done
case $cm in
dragonegg|llvm)
@@ -2628,7 +2658,7 @@ echo tcfn=$mkshexe >>Rebuild.sh
echo "$CC $CFLAGS $LDFLAGS -o \$tcfn $lobjs $LIBS $ccpr" >>Rebuild.sh
echo "test -f \$tcfn || exit 1; $SIZE \$tcfn" >>Rebuild.sh
if test $cm = makefile; then
- extras='emacsfn.h 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"
gens= genq=
for file in $optfiles; do
@@ -2734,11 +2764,11 @@ if test $legacy = 0; then
fi
$e
$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/"
fi
if test -f mksh.cat1; then
- if test -e FAQ.htm; then
+ if test -f FAQ.htm; then
$e plus either
fi
$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 Run the regression test suite: ./test.sh
$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.
exit 0
@@ -2775,6 +2805,7 @@ TARGET_OS default: $(uname -s || uname)
TARGET_OSREV [QNX] default: $(uname -r)
==== feature selectors ====
+MKSH_UNLIMITED 1 to omit ulimit builtin completely
USE_PRINTF_BUILTIN 1 to include (unsupported) printf(1) as builtin
===== general format =====
HAVE_STRLEN ac_test
@@ -2782,7 +2813,7 @@ HAVE_STRING_H ac_header
HAVE_CAN_FSTACKPROTECTORALL ac_flags
==== cpp definitions ====
-DEBUG dont use in production, wants gcc, implies:
+DEBUG don’t use in production, wants gcc, implies:
DEBUG_LEAKS enable freeing resources before exiting
KSH_VERSIONNAME_VENDOR_EXT when patching; space+plus+word (e.g. " +SuSE")
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_NO_CMDLINE_EDITING disable command line editing code entirely
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_SIGSUSPEND use sigprocmask+pause instead of sigsuspend
MKSH_SMALL omit some code, optimise hard for size (slower)
diff --git a/src/FAQ2HTML.sh b/src/FAQ2HTML.sh
index 180ed98..ecff077 100644
--- a/src/FAQ2HTML.sh
+++ b/src/FAQ2HTML.sh
@@ -1,5 +1,5 @@
-#!/bin/mksh
-rcsid='$MirOS: src/bin/mksh/FAQ2HTML.sh,v 1.1 2020/02/03 22:23:33 tg Exp $'
+#!/bin/sh
+rcsid='$MirOS: src/bin/mksh/FAQ2HTML.sh,v 1.2 2020/10/31 04:17:36 tg Exp $'
#-
# Copyright © 2020
# mirabilos
@@ -37,7 +37,7 @@ fi
src_id=$(sed $p -n '/^RCSID: /s///p' "$srcdir"/mksh.faq)
# sanity check
case $src_id in
-(*"$nl"*)
+*"$nl"*)
echo >&2 "E: more than one RCSID in mksh.faq?"
exit 1 ;;
esac
diff --git a/src/check.pl b/src/check.pl
index c08e287..8e3efe9 100644
--- a/src/check.pl
+++ b/src/check.pl
@@ -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 $
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
@@ -55,7 +55,7 @@
# default is no arguments.
# script m Value is written to a file which
# 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
# used as standard-input for the program;
# 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)
-p p Use p as the program to test
-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 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
diff --git a/src/check.t b/src/check.t
index 8818822..311f5c1 100644
--- a/src/check.t
+++ b/src/check.t
@@ -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 -*-
#-
# 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
expected-stdout:
- KSH R59 2020/05/16
+ KSH R59 2020/10/31
description:
Check base version of full shell
stdin:
@@ -6109,7 +6109,7 @@ expected-stderr-pattern: /does\/not\/exist/
---
name: regression-28
description:
- variable assignements not detected well
+ variable assignments not detected well
stdin:
a.x=1 echo hi
expected-exit: e != 0
@@ -6184,7 +6184,7 @@ expected-stdout:
---
name: regression-35
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)
stdin:
f1() {
@@ -7457,7 +7457,7 @@ expected-stdout:
name: xxx-param-subst-qmark-1
description:
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.
stdin:
unset foo
@@ -8853,9 +8853,10 @@ description:
XXX if the OS can already execute them, we lose
note: cygwin execve(2) doesn't return to us with ENOEXEC, we lose
note: Ultrix perl5 t4 returns 65280 (exit-code 255) and no text
+ 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)
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!
stdin:
print '#!'"$__progname"'\nprint "1 a=$ENV{FOO}";' >t1
@@ -11489,13 +11490,11 @@ name: fd-cloexec-1
description:
Verify that file descriptors > 2 are private for Korn shells
AT&T ksh93 does this still, which means we must keep it as well
- XXX fails on some old Perl installations
-need-pass: no
stdin:
cat >cld <<-EOF
#!$__perlname
- open(my \$fh, ">&", 9) or die "E: open \$!";
- syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!";
+ open(FH, ">&9") or die "E: open \$!";
+ syswrite(FH, "Fowl\\n", 5) or die "E: write \$!";
EOF
chmod +x cld
exec 9>&1
@@ -11508,13 +11507,11 @@ name: fd-cloexec-2
description:
Verify that file descriptors > 2 are not private for POSIX shells
See Debian Bug #154540, Closes: #499139
- XXX fails on some old Perl installations
-need-pass: no
stdin:
cat >cld <<-EOF
#!$__perlname
- open(my \$fh, ">&", 9) or die "E: open \$!";
- syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!";
+ open(FH, ">&9") or die "E: open \$!";
+ syswrite(FH, "Fowl\\n", 5) or die "E: write \$!";
EOF
chmod +x cld
test -n "$POSH_VERSION" || set -o posix
@@ -12079,10 +12076,10 @@ expected-stdout:
EOFN
)|tr u x); }
function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP {
- x=$( ( \cat >|bar <<"EOFN"
+ x=$( ( \cat >|bar <<"EOFN" ) | \tr u x
foo
EOFN
- ) | \tr u x )
+ )
}
inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() {
cat 1>bar <<-EOFI
@@ -12112,10 +12109,10 @@ expected-stdout:
EOFI
)|tr u x); }
function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP {
- x=$( ( \cat >bar <<-EOFI
+ x=$( ( \cat >bar <<-EOFI ) | \tr u x
foo
EOFI
- ) | \tr u x )
+ )
}
inline_IORDWR_IODUP() {
sh 1<>/dev/console 0<&1 2>&1
@@ -13640,6 +13637,11 @@ description:
words, and command -p[vV] should find aliases, reserved words, and
builtins over external commands.
stdin:
+ # extra checks prep
+ mkdir mrr
+ :>mrr/miau
+ chmod +x mrr/miau
+ # priorities
PATH=/bin:/usr/bin
alias foo="bar baz"
alias '[ab]=:'
@@ -13653,6 +13655,14 @@ stdin:
# extra checks
alias '[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:
if
if
@@ -13680,6 +13690,7 @@ expected-stdout:
'[ab]' is an alias for :
'[ab]'=:
:
+ ok
---
name: whence-preserve-tradition
description:
diff --git a/src/edit.c b/src/edit.c
index 8c1c2c8..a98f5dd 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -29,7 +29,7 @@
#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
@@ -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"
#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 */
#define EDCHAR_DISABLED 0xFFFFU
#define EDCHAR_INITIAL 0xFFFEU
@@ -153,7 +157,7 @@ x_getc(void)
char c;
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) {
x_mode(false);
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 win; /* window buffer in use */
static char morec; /* more character at right of window */
-static int lastref; /* argument to last refresh() */
static int holdlen; /* length of holdbuf */
#endif
static int pwidth; /* width of prompt */
@@ -989,11 +992,11 @@ static void x_zots(char *);
static void x_zotc3(char **);
static void x_vi_zotc(int);
static void x_load_hist(char **);
-static int x_search(char *, int, int);
+static int x_search(const char *, int, int);
#ifndef MKSH_SMALL
static int x_search_dir(int);
#endif
-static int x_match(char *, char *);
+static int x_match(const char *, const char *);
static void x_redraw(int);
static void x_push(size_t);
static void x_bind_showone(int, int);
@@ -1946,7 +1949,7 @@ x_search_hist(int c)
offset = x_match(xbuf, pat);
if (offset >= 0) {
x_goto(xbuf + offset + (p - pat) -
- (*pat == '^'));
+ (*pat == '^' ? 1 : 0));
continue;
}
}
@@ -1968,18 +1971,21 @@ x_search_hist(int c)
/* search backward from current line */
static int
-x_search(char *pat, int sameline, int offset)
+x_search(const char *pat, int sameline, int offset)
{
char **hp;
int i;
+ size_t patlen = strlen(pat);
+ if (*pat == '^')
+ --patlen;
for (hp = x_histp - (sameline ? 0 : 1); hp >= history; --hp) {
i = x_match(*hp, pat);
if (i >= 0) {
if (offset < 0)
x_e_putc2('\n');
x_load_hist(hp);
- x_goto(xbuf + i + strlen(pat) - (*pat == '^'));
+ x_goto(xbuf + i + patlen);
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 */
static int
-x_match(char *str, char *pat)
+x_match(const char *str, const char *pat)
{
if (*pat == '^') {
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)
{
if (x_arg_defaulted) {
- if (xep == xbuf) {
- x_e_putc2(KSH_BEL);
- return (KSTD);
- }
if (modified) {
*xep = '\0';
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);
}
if (x_arg)
- shf_snprintf(xbuf, xend - xbuf, Tf_sd,
- "fc -e ${VISUAL:-${EDITOR:-vi}} --", x_arg);
+ shf_snprintf(xbuf, xend - xbuf, Tf_sd, ctrl_x_e, x_arg);
else
- strlcpy(xbuf, "fc -e ${VISUAL:-${EDITOR:-vi}} --", xend - xbuf);
+ strlcpy(xbuf, ctrl_x_e, xend - xbuf);
xep = strnul(xbuf);
return (x_newline('\n'));
}
@@ -3433,13 +3434,13 @@ static int Forwword(int);
static int Backword(int);
static int Endword(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 refresh(int);
+static void refresh(bool);
static int outofwin(void);
static void rewindow(void);
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 int expand_word(int);
static int complete_word(int, int);
@@ -3610,7 +3611,6 @@ x_vi(char *buf)
winwidth = x_cols - pwidth - 3;
win = 0;
morec = ' ';
- lastref = 1;
holdlen = 0;
editmode = 2;
@@ -3712,7 +3712,7 @@ vi_hook(int ch)
case 0:
if (state == VLIT) {
vs->cursor--;
- refresh(0);
+ refresh(false);
} else
refresh(insert != 0);
break;
@@ -3738,7 +3738,7 @@ vi_hook(int ch)
if (putbuf(ord(ch) == ORD('/') ?
"/" : "?", 1, false) != 0)
return (-1);
- refresh(0);
+ refresh(false);
}
if (state == VVERSION) {
save_cbuf();
@@ -3746,7 +3746,7 @@ vi_hook(int ch)
vs->linelen = 0;
putbuf(KSH_VERSION,
strlen(KSH_VERSION), false);
- refresh(0);
+ refresh(false);
}
}
}
@@ -3758,14 +3758,14 @@ vi_hook(int ch)
vi_error();
} else
vs->cbuf[vs->cursor++] = ch;
- refresh(1);
+ refresh(true);
state = VNORMAL;
break;
case VVERSION:
restore_cbuf();
state = VNORMAL;
- refresh(0);
+ refresh(false);
break;
case VARG1:
@@ -3829,7 +3829,7 @@ vi_hook(int ch)
if (!srchpat[0]) {
vi_error();
state = VNORMAL;
- refresh(0);
+ refresh(false);
return (0);
}
} else {
@@ -3842,17 +3842,17 @@ vi_hook(int ch)
srchlen--;
vs->linelen -= char_len(locpat[srchlen]);
vs->cursor = vs->linelen;
- refresh(0);
+ refresh(false);
return (0);
}
restore_cbuf();
state = VNORMAL;
- refresh(0);
+ refresh(false);
} else if (isched(ch, edchars.kill)) {
srchlen = 0;
vs->linelen = 1;
vs->cursor = 1;
- refresh(0);
+ refresh(false);
return (0);
} else if (isched(ch, edchars.werase)) {
unsigned int i, n;
@@ -3871,7 +3871,7 @@ vi_hook(int ch)
vs->linelen -= char_len(locpat[i]);
srchlen = (int)n;
vs->cursor = vs->linelen;
- refresh(0);
+ refresh(false);
return (0);
} else {
if (srchlen == SRCHLEN - 1)
@@ -3890,7 +3890,7 @@ vi_hook(int ch)
vs->cbuf[vs->linelen++] = ch;
}
vs->cursor = vs->linelen;
- refresh(0);
+ refresh(false);
}
return (0);
}
@@ -3931,7 +3931,7 @@ vi_hook(int ch)
switch (vi_cmd(argc1, curcmd)) {
case -1:
vi_error();
- refresh(0);
+ refresh(false);
break;
case 0:
if (insert != 0)
@@ -3939,7 +3939,7 @@ vi_hook(int ch)
refresh(insert != 0);
break;
case 1:
- refresh(0);
+ refresh(false);
return (1);
case 2:
/* back from a 'v' command - don't redraw the screen */
@@ -3954,7 +3954,7 @@ vi_hook(int ch)
switch (vi_cmd(lastac, lastcmd)) {
case -1:
vi_error();
- refresh(0);
+ refresh(false);
break;
case 0:
if (insert != 0) {
@@ -3967,10 +3967,10 @@ vi_hook(int ch)
vi_error();
}
}
- refresh(0);
+ refresh(false);
break;
case 1:
- refresh(0);
+ refresh(false);
return (1);
case 2:
/* back from a 'v' command - can't happen */
@@ -4135,8 +4135,9 @@ static int
vi_cmd(int argcnt, const char *cmd)
{
int ncursor;
- int cur, c1, c2, c3 = 0;
+ int cur, c1, c2;
int any;
+ bool b;
struct edstate *t;
if (argcnt == 0 && !is_zerocount(*cmd))
@@ -4407,8 +4408,6 @@ vi_cmd(int argcnt, const char *cmd)
case ORD('v'):
if (!argcnt) {
- if (vs->linelen == 0)
- return (-1);
if (modified) {
vs->cbuf[vs->linelen] = '\0';
histsave(&source->line, vs->cbuf,
@@ -4419,12 +4418,9 @@ vi_cmd(int argcnt, const char *cmd)
}
if (argcnt)
shf_snprintf(vs->cbuf, vs->cbufsize, Tf_sd,
- "fc -e ${VISUAL:-${EDITOR:-vi}} --",
- argcnt);
+ ctrl_x_e, argcnt);
else
- strlcpy(vs->cbuf,
- "fc -e ${VISUAL:-${EDITOR:-vi}} --",
- vs->cbufsize);
+ strlcpy(vs->cbuf, ctrl_x_e, vs->cbufsize);
vs->linelen = strlen(vs->cbuf);
return (2);
@@ -4474,25 +4470,23 @@ vi_cmd(int argcnt, const char *cmd)
/* FALLTHROUGH */
case ORD('/'):
- c3 = 1;
+ c1 = 1;
srchlen = 0;
lastsearch = *cmd;
- /* FALLTHROUGH */
+ if (0)
+ /* FALLTHROUGH */
case ORD('n'):
case ORD('N'):
+ c1 = 0;
if (lastsearch == ORD(' '))
return (-1);
- if (lastsearch == ORD('?'))
- c1 = 1;
- else
- c1 = 0;
+ b = (lastsearch == ORD('?'));
if (*cmd == 'N')
- c1 = !c1;
- if ((c2 = grabsearch(modified, hnum,
- c1, srchpat)) < 0) {
- if (c3) {
+ b = !b;
+ if ((c2 = grabsearch(srchpat, modified, hnum, b)) < 0) {
+ if (c1) {
restore_cbuf();
- refresh(0);
+ refresh(false);
}
return (-1);
} else {
@@ -5117,20 +5111,20 @@ grabhist(int save, int n)
}
static int
-grabsearch(int save, int start, int fwd, const char *pat)
+grabsearch(const char *pat, int save, int start, bool fwd)
{
char *hptr;
int hist;
bool anchored;
- if ((start == 0 && fwd == 0) || (start >= hlast - 1 && fwd == 1))
+ if ((start == 0 && !fwd) || (start >= hlast - 1 && fwd))
return (-1);
if (fwd)
start++;
else
start--;
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) */
if (start != 0 && fwd && strcmp(holdbufp, pat) >= 0) {
restore_cbuf();
@@ -5163,12 +5157,8 @@ redraw_line(bool newl)
}
static void
-refresh(int leftside)
+refresh(bool leftside)
{
- if (leftside < 0)
- leftside = lastref;
- else
- lastref = leftside;
if (outofwin())
rewindow();
display(wbuf[1 - win], wbuf[win], leftside);
@@ -5224,7 +5214,7 @@ newcol(unsigned char ch, int col)
}
static void
-display(char *wb1, char *wb2, int leftside)
+display(char *wb1, char *wb2, bool leftside)
{
unsigned char ch;
char *twb1, *twb2, mc;
@@ -5379,7 +5369,7 @@ expand_word(int cmd)
hnum = hlast;
insert = INSERT;
lastac = 0;
- refresh(0);
+ refresh(false);
return (rval);
}
@@ -5494,7 +5484,7 @@ complete_word(int cmd, int count)
insert = INSERT;
/* prevent this from being redone... */
lastac = 0;
- refresh(0);
+ refresh(false);
return (rval);
}
diff --git a/src/exec.c b/src/exec.c
index 9d1b69b..447d441 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -24,7 +24,7 @@
#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
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
@@ -1213,7 +1213,7 @@ findcom(const char *name, int flags)
}
Search:
- if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) &&
+ if ((!tp || (tp->type == CTALIAS && !(tp->flag & ISSET))) &&
(flags & FC_PATH)) {
if (!tp) {
if (insert && !(flags & FC_DEFPATH)) {
@@ -1351,10 +1351,8 @@ search_path(const char *name, const char *lpath,
XcheckN(xs, xp, p - sp);
memcpy(xp, sp, p - sp);
xp += p - sp;
-#ifdef __OS2__
- if (xp > Xstring(xs, xp) && mksh_cdirsep(xp[-1]))
+ if (mksh_cdirsep(xp[-1]))
xp--;
-#endif
*xp++ = '/';
}
sp = p;
diff --git a/src/expr.c b/src/expr.c
index 6764279..cb389c1 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -23,7 +23,7 @@
#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
#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;
/*
- * Generated from the UCD 13.0.0 by
- * MirOS: contrib/code/Snippets/eawparse,v 1.14 2020/03/27 01:33:21 tg Exp $
+ * Generated from the UCD 13.0.0 - see /usr/share/doc/legal/LICENCE-BSD - by
+ * 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 },
{ 0xABE8, 0xABE8 },
{ 0xABED, 0xABED },
+ { 0xD7B0, 0xD7FF },
{ 0xFB1E, 0xFB1E },
{ 0xFE00, 0xFE0F },
{ 0xFE20, 0xFE2F },
diff --git a/src/funcs.c b/src/funcs.c
index d3427d0..ff6506d 100644
--- a/src/funcs.c
+++ b/src/funcs.c
@@ -1,7 +1,6 @@
/* $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_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,
@@ -39,7 +38,7 @@
#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
/*
@@ -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
#endif
-/* XXX conditions correct? */
-#if !defined(RLIM_INFINITY) && !defined(MKSH_NO_LIMITS)
-#define MKSH_NO_LIMITS 1
-#endif
-
-#ifdef MKSH_NO_LIMITS
+#ifdef MKSH_UNLIMITED
#define c_ulimit c_true
#endif
@@ -713,7 +707,23 @@ do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
"exported " : "",
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 {
if (vflag)
shprintf(Tnot_found_s, id);
@@ -3219,214 +3229,6 @@ ptest_error(Test_env *te, int ofs, const char *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
c_rename(const char **wp)
{
@@ -3483,7 +3285,7 @@ c_realpath(const char **wp)
int
c_cat(const char **wp)
{
- int fd = STDIN_FILENO, rv;
+ int fd = 0, rv;
ssize_t n, w;
const char *fn = "";
char *buf, *cp;
@@ -3516,7 +3318,7 @@ c_cat(const char **wp)
if (*wp) {
fn = *wp++;
if (ksh_isdash(fn))
- fd = STDIN_FILENO;
+ fd = 0;
else if ((fd = binopen2(fn, O_RDONLY)) < 0) {
bi_errorf(Tf_sD_s, fn, cstrerror(errno));
rv = 1;
@@ -3535,7 +3337,7 @@ c_cat(const char **wp)
opipe = block_pipe();
continue;
}
- /* an error occured during reading */
+ /* an error occurred during reading */
bi_errorf(Tf_sD_s, fn, cstrerror(errno));
rv = 1;
break;
@@ -3545,7 +3347,7 @@ c_cat(const char **wp)
while (n) {
if (intrsig)
goto has_intrsig;
- if ((w = write(STDOUT_FILENO, cp, n)) != -1) {
+ if ((w = write(1, cp, n)) != -1) {
n -= w;
cp += w;
continue;
@@ -3564,17 +3366,17 @@ c_cat(const char **wp)
/* fake receiving signal */
rv = ksh_sigmask(SIGPIPE);
} else {
- /* an error occured during writing */
+ /* an error occurred during writing */
bi_errorf(Tf_sD_s, "",
cstrerror(errno));
rv = 1;
}
- if (fd != STDIN_FILENO)
+ if (fd != 0)
close(fd);
goto out;
}
}
- if (fd != STDIN_FILENO)
+ if (fd != 0)
close(fd);
} while (*wp);
diff --git a/src/histrap.c b/src/histrap.c
index 84211c6..7f46201 100644
--- a/src/histrap.c
+++ b/src/histrap.c
@@ -27,7 +27,7 @@
#include
#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];
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;
/* 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);
else
hp = &history[n];
@@ -479,7 +480,7 @@ histnum(int n)
* direction.
*/
int
-findhist(int start, int fwd, const char *str, bool anchored)
+findhist(int start, const char *str, bool fwd, bool anchored)
{
char **hp;
int maxhist = histptr - history;
diff --git a/src/lksh.1 b/src/lksh.1
index 0d6b226..7965156 100644
--- a/src/lksh.1
+++ b/src/lksh.1
@@ -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
.\" mirabilos
@@ -25,7 +25,8 @@
.\" 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 \*(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
.\" Also make sure to use \& *before* a punctuation char that is to not
.\" be interpreted as punctuation, and especially with two-letter words
@@ -59,6 +60,12 @@
. ds ha ^
. ds en \(em
.\}
+.ie n \{\
+. ds EM \ \*(en\ \&
+.\}
+.el \{\
+. ds EM \f(TR\^\(em\^\fP
+.\}
.\"
.\" Implement .Dd with the Mdocdate RCS keyword
.\"
@@ -74,7 +81,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to
.\" 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.
.\"
diff --git a/src/main.c b/src/main.c
index 1328045..e17ac75 100644
--- a/src/main.c
+++ b/src/main.c
@@ -35,7 +35,7 @@
#include
#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
#define MKSHRC_PATH "~/.mkshrc"
@@ -1203,7 +1203,7 @@ remove_temps(struct temp *tp)
/*
* 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:
* 0 = got controlling tty
* 1 = got terminal but no controlling tty
@@ -1435,7 +1435,8 @@ error_prefix(bool fileline)
/* Avoid foo: foo[2]: ... */
if (!fileline || !source || !source->file ||
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) {
shf_fprintf(shl_out, "%s[%lu]: ", source->file,
(unsigned long)(source->errline ?
diff --git a/src/misc.c b/src/misc.c
index b19a253..f9f0201 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -33,7 +33,7 @@
#include
#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
#ifdef MKSH_SMALL
@@ -1328,7 +1328,7 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
if (go->flags & GF_ERROR)
bi_errorfz();
}
- return ('?');
+ return (ORD('?'));
}
/**
* : 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] == ':') {
go->buf[0] = c;
go->optarg = go->buf;
- return (':');
+ return (ORD(':'));
}
warningf(true, Tf_optfoo,
(go->flags & GF_NONAME) ? "" : argv[0],
@@ -1355,7 +1355,7 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
c, Treq_arg);
if (go->flags & GF_ERROR)
bi_errorfz();
- return ('?');
+ return (ORD('?'));
}
go->p = 0;
} else if (*o == ',') {
@@ -1383,7 +1383,7 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
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 ./ or ../ append cwd and file to result
* 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.
* - the first element of cdpathp 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);
memcpy(xp, cwd, len);
xp += len;
- if (!mksh_cdirsep(cwd[len - 1]))
- Xput(*xsp, xp, '/');
+ if (mksh_cdirsep(xp[-1]))
+ xp--;
+ *xp++ = '/';
}
*phys_pathp = Xlength(*xsp, xp);
if (use_cdpath && plen) {
XcheckN(*xsp, xp, plen);
memcpy(xp, plist, plen);
xp += plen;
- if (!mksh_cdirsep(plist[plen - 1]))
- Xput(*xsp, xp, '/');
+ if (mksh_cdirsep(xp[-1]))
+ xp--;
+ *xp++ = '/';
rval = 1;
}
}
@@ -2056,9 +2058,14 @@ simplify_path(char *p)
case '\\':
#endif
/* 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 */
+#ifdef MKSH_DOSPATH
+ *p++ = '/';
+#else
++p;
+#endif
+ }
needslash = true;
break;
default:
@@ -2189,26 +2196,26 @@ c_cd(const char **wp)
oldpwd_s = global(TOLDPWD);
if (!wp[0]) {
- /* No arguments - go home */
+ /* no arguments; go home */
if ((dir = str_val(global("HOME"))) == null) {
bi_errorf("no home directory (HOME not set)");
return (2);
}
} else if (!wp[1]) {
- /* One argument: - or dir */
- strdupx(allocd, wp[0], ATEMP);
- if (ksh_isdash((dir = allocd))) {
- afree(allocd, ATEMP);
- allocd = NULL;
+ /* one argument: - or dir */
+ if (ksh_isdash(wp[0])) {
dir = str_val(oldpwd_s);
if (dir == null) {
bi_errorf(Tno_OLDPWD);
return (2);
}
printpath = true;
+ } else {
+ strdupx(allocd, wp[0], ATEMP);
+ dir = allocd;
}
} 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;
char *cp;
@@ -2217,10 +2224,9 @@ c_cd(const char **wp)
return (2);
}
/*
- * substitute arg1 for arg2 in current path.
- * if the first substitution fails because the cd fails
- * we could try to find another substitution. For now
- * we don't
+ * Substitute arg1 for arg2 in current path. If the first
+ * substitution fails because the cd fails we could try to
+ * find another substitution. For now, we don't.
*/
if ((cp = strstr(current_wd, wp[0])) == NULL) {
bi_errorf(Tbadsubst);
diff --git a/src/mksh.1 b/src/mksh.1
index 1f1a121..6cfb70c 100644
--- a/src/mksh.1
+++ b/src/mksh.1
@@ -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 $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
@@ -84,7 +84,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always.
.\"
-.Dd $Mdocdate: May 16 2020 $
+.Dd $Mdocdate: October 1 2020 $
.\"
.\" Check which macro package we use, and do other -mdoc setup.
.\"
@@ -1414,7 +1414,7 @@ or
where
.Ar 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
in the latter form mentioned above, expand the element with the key
.Dq 0 .
@@ -5333,10 +5333,16 @@ Set the number of cached threads to
Impose a size limit of
.Ar n
blocks on the size of core dumps.
+Silently ignored if the system does not support this limit.
.It Fl d Ar n
Limit the size of the data area to
.Ar n
kibibytes.
+.br
+On some systems, read-only maximum
+.Xr brk 2
+size minus
+.Li etext .
.It Fl e Ar n
Set the maximum niceness to
.Ar n .
@@ -5369,6 +5375,7 @@ kibibytes on the amount of physical memory used.
Impose a limit of
.Ar n
file descriptors that can be open at once.
+On some systems attempts to set are silently ignored.
.It Fl O Ar n
Set the number of AIO operations to
.Ar n .
@@ -6064,11 +6071,18 @@ words.
.Op Ar n
.No \*(haXe
.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
-or the current line, if not specified, interactively.
-The actual command executed is
-.Ic fc \-e ${VISUAL:\-${EDITOR:\-vi}} Ar n .
+(if
+.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
Moves to the end of the history.
.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
.Oo Ar n Oc Ns v
.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
-using the
-.Xr vi 1
-editor; if
+(if
.Ar n
-is not specified, the current line is edited.
-The actual command executed is
-.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 * and \*(haX
Command or file name expansion is applied to the current big-word (with an
appended
@@ -7072,7 +7089,7 @@ for the in-memory portion of the history is slow, should use
.Xr memmove 3 .
.Pp
This document attempts to describe
-.Nm mksh\ R59b
+.Nm mksh\ R59c
and up,
.\" with vendor patches from insert-your-name-here,
compiled without any options impacting functionality, such as
diff --git a/src/mksh.faq b/src/mksh.faq
index 83e0191..6634d60 100644
--- a/src/mksh.faq
+++ b/src/mksh.faq
@@ -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
Title: How do you spell mksh? How do you pronounce it?
@@ -207,7 +207,7 @@ Title: Why doesn’t this use a Makefile to build?
ToC: oldbsd
Title: Why do other BSDs and QNX still use pdksh instead of mksh?
-Some systems are resistent to change, mostly due to bikeshedding
+
Some systems are resistant to change, mostly due to bikeshedding
(some people would, for example, rather see all shells banned to
ports/pkgsrc®) and hysterial raisins (historical reasons ☻). Most
BSDs have mksh packages available, and it works on all of them and
@@ -297,6 +297,29 @@ pdksh derivative); $SH_VERSION (“PD KSH” as sh), $YASH_VERSION<
(yash), $ZSH_VERSION (or if $VERSION begins with “zsh”); a list of more approaches exists.
----
+ToC: ctrl-x-e
+Title: Multiline command editing
+
+
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.
+For this reason, mksh’s 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.
+One way to achieve multi-line editing is to disable input
+ line editing: set +o emacs +o vi
This will, however, lose
+ you all editing features: tab completion, cursor keys, history, etc.
+Another way, if you don’t need it all the time, is to use a function
+ that spawns your editor on the input line: press ^Xe in the
+ default emacs mode or Esc + v 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 jupp’s “abendjoe” command) to prevent execution.
+ This is really useful to write ad-hōc scripts as well.
+----
ToC: ctrl-l-cls
Title: ^L (Ctrl-L) does not clear the screen
@@ -439,6 +462,15 @@ Title: I get an error in this regex comparison
… becomes…
[[ foo = *@(foo|bar)*baz* ]]
----
+ToC: trim-vector
+Title: ${@?}: bad substitution
+
+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 ${@#foo} could be
+ applied to $1 only and ${@?} can be replaced
+ with a test whether $# -eq 0.
+----
ToC: extensions-to-avoid
Title: Are there any extensions to avoid?
diff --git a/src/os2.c b/src/os2.c
index 8a80782..ed31eff 100644
--- a/src/os2.c
+++ b/src/os2.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2015, 2017, 2020
* KO Myung-Hun
- * Copyright (c) 2017
+ * Copyright (c) 2017, 2020
* mirabilos
*
* Provided that these terms and disclaimer and all copyright notices
@@ -32,11 +32,23 @@
#include
#include
-__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 *);
-static int access_stat_ex(int (*)(), const char *, void *);
-static int test_exec_exist(const char *, char *);
+struct a_s_arg {
+ union {
+ 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 char *make_response_file(char * const *);
static void add_temp(const char *);
@@ -223,23 +235,18 @@ setextlibpath(const char *name, const char *val)
}
/* remove trailing dots */
-static char *
-remove_trailing_dots(char *name)
+static void
+remove_trailing_dots(char *name, size_t namelen)
{
- char *p = strnul(name);
+ char *p = name + namelen;
while (--p > name && *p == '.')
/* nothing */;
if (*p != '.' && *p != '/' && *p != '\\' && *p != ':')
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() */
extern int _std_stat(const char *, struct stat *);
@@ -247,7 +254,12 @@ extern int _std_stat(const char *, struct stat *);
int
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() */
@@ -257,6 +269,9 @@ extern int _std_access(const char *, int);
int
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.
* This prevents scripts from being executed.
@@ -264,7 +279,9 @@ access(const char *name, int mode)
if (mode & X_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
@@ -274,7 +291,7 @@ static const char *x_suffix_list[] =
/* call fn() by appending executable extensions */
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;
const char **x_suffix;
@@ -288,7 +305,8 @@ access_stat_ex(int (*fn)(), const char *name, void *arg)
strlcpy(x_name, name, 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);
@@ -300,8 +318,12 @@ access_stat_ex(int (*fn)(), const char *name, void *arg)
int
access_ex(int (*fn)(const char *, int), const char *name, int mode)
{
- /*XXX this smells fishy --mirabilos */
- return (access_stat_ex(fn, name, (void *)mode));
+ struct a_s_arg arg;
+
+ arg.fn.i = fn;
+ arg.arg.i = mode;
+ arg.isint = true;
+ return (access_stat_ex(name, &arg));
}
/* stat()/lstat() version */
@@ -309,34 +331,39 @@ int
stat_ex(int (*fn)(const char *, struct stat *),
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
-test_exec_exist(const char *name, char *real_name)
+test_exec_exist(const char *name, void *arg)
{
struct stat sb;
+ char *real_name;
if (stat(name, &sb) < 0 || !S_ISREG(sb.st_mode))
return (-1);
- /* safe due to calculations in real_exec_name() */
- memcpy(real_name, name, strlen(name) + 1);
-
+ /*XXX memory leak */
+ strdupx(real_name, name, ATEMP);
+ *((char **)arg) = real_name;
return (0);
}
const char *
real_exec_name(const char *name)
{
- char x_name[strlen(name) + MAX_X_SUFFIX_LEN + 1];
- const char *real_name = name;
+ struct a_s_arg arg;
+ char *real_name;
- if (access_stat_ex(test_exec_exist, real_name, x_name) != -1)
- /*XXX memory leak */
- strdupx(real_name, x_name, ATEMP);
-
- return (real_name);
+ arg.fn.p = &test_exec_exist;
+ arg.arg.p = (void *)(&real_name);
+ arg.isint = false;
+ return (access_stat_ex(name, &arg) ? name : real_name);
}
/* make a response file to pass a very long command line */
diff --git a/src/rlimits.gen b/src/rlimits.gen
index 5ccd007..cf684b4 100644
--- a/src/rlimits.gen
+++ b/src/rlimits.gen
@@ -1,6 +1,6 @@
/* +++ GENERATED FILE +++ DO NOT EDIT +++ */
/*-
- * Copyright (c) 2013, 2015
+ * Copyright (c) 2013, 2015, 2019
* mirabilos
*
* 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
* 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/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)
#define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
#endif
diff --git a/src/rlimits.opt b/src/rlimits.opt
index db2a531..b806b40 100644
--- a/src/rlimits.opt
+++ b/src/rlimits.opt
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013, 2015
+ * Copyright (c) 2013, 2015, 2019
* mirabilos
*
* 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
* 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/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
#define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
@@
diff --git a/src/sh.h b/src/sh.h
index 8394c89..575f9bf 100644
--- a/src/sh.h
+++ b/src/sh.h
@@ -78,7 +78,9 @@
#if HAVE_PATHS_H
#include
#endif
+#ifndef MKSH_NOPWNAM
#include
+#endif
#include
#include
#include
@@ -191,9 +193,9 @@
#endif
#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
-#define MKSH_VERSION "R59 2020/05/16"
+#define MKSH_VERSION "R59 2020/10/31"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
@@ -247,10 +249,6 @@ typedef u_int8_t uint8_t;
/* other standard types */
-#if !HAVE_RLIM_T
-typedef unsigned long rlim_t;
-#endif
-
#if !HAVE_SIG_T
#undef sig_t
typedef void (*sig_t)(int);
@@ -668,7 +666,7 @@ char *ucstrstr(char *, const char *);
#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.
extern void thiswillneverbedefinedIhope(void);
int
@@ -2522,7 +2520,7 @@ void sethistfile(const char *);
char **histpos(void) MKSH_A_PURE;
int histnum(int);
#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);
void inittraps(void);
void alarm_init(void);
diff --git a/src/shf.c b/src/shf.c
index 8e95fc6..ec7fc1f 100644
--- a/src/shf.c
+++ b/src/shf.c
@@ -27,7 +27,7 @@
#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() */
#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)
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) &&
(shf->wp != shf->buf || nbytes < shf->wnleft)) {
if (ncopy > nbytes)
@@ -782,7 +782,7 @@ shf_smprintf(const char *fmt, ...)
#define FL_ZERO 0x040 /* '0' seen */
#define FL_DOT 0x080 /* '.' seen */
#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 FM_SIZES 0x430 /* h/l/z mask */
diff --git a/src/syn.c b/src/syn.c
index 3387cf5..bcb5a5a 100644
--- a/src/syn.c
+++ b/src/syn.c
@@ -24,7 +24,7 @@
#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 {
int start_token; /* token than began nesting (eg, FOR) */
@@ -268,13 +268,12 @@ get_command(int cf, int sALIAS)
{
struct op *t;
int c, iopn = 0, syniocf, lno;
- struct ioword *iop, **iops;
+ struct ioword *iop;
XPtrV args, vars;
struct nesting_state old_nesting;
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(vars, 16);
@@ -282,7 +281,6 @@ get_command(int cf, int sALIAS)
switch (c = token(cf|KEYWORD|sALIAS|CMDASN)) {
default:
REJECT;
- afree(iops, ATEMP);
XPfree(args);
XPfree(vars);
/* empty line */
@@ -510,12 +508,11 @@ get_command(int cf, int sALIAS)
}
if (iopn == 0) {
- afree(iops, ATEMP);
t->ioact = NULL;
} else {
iops[iopn++] = NULL;
- iops = aresize2(iops, iopn, sizeof(struct ioword *), ATEMP);
- t->ioact = iops;
+ t->ioact = alloc2(iopn, sizeof(struct ioword *), ATEMP);
+ memcpy(t->ioact, iops, iopn * sizeof(struct ioword *));
}
if (t->type == TCOM || t->type == TDBRACKET) {
diff --git a/src/tree.c b/src/tree.c
index 335e3fb..85fa0d6 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -23,7 +23,7 @@
#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
@@ -37,6 +37,19 @@ static void iofree(struct ioword **, Area *);
/* "foo& ; bar" and "foo |& ; bar" are invalid */
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";
/*
@@ -82,8 +95,11 @@ ptree(struct op *t, int indent, struct shf *shf)
w = (const char **)t->vars;
while (*w)
fptreef(shf, indent, Tf_S_, *w++);
- } else
+ }
+#ifndef MKSH_SMALL
+ else
shf_puts("#no-vars# ", shf);
+#endif
if (t->args) {
w = t->args;
if (*w && **w == CHAR) {
@@ -97,8 +113,11 @@ ptree(struct op *t, int indent, struct shf *shf)
}
while (*w)
fptreef(shf, indent, Tf_S_, *w++);
- } else
+ }
+#ifndef MKSH_SMALL
+ else
shf_puts("#no-args# ", shf);
+#endif
break;
case TEXEC:
t = t->left;
@@ -221,36 +240,9 @@ ptree(struct op *t, int indent, struct shf *shf)
prevent_semicolon = false;
break;
}
- if ((ioact = t->ioact) != NULL) {
- bool need_nl = false;
-
+ if ((ioact = t->ioact) != NULL)
while (*ioact != NULL)
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
@@ -272,11 +264,29 @@ pioact(struct shf *shf, struct ioword *iop)
shf_putc('<', shf);
break;
case IOHERE:
+ if (flag & IOHERESTR) {
+ shf_puts("<<<", shf);
+ goto ioheredelim;
+ }
shf_puts("<<", shf);
if (flag & IOSKIP)
shf_putc('-', shf);
- else if (flag & IOHERESTR)
- shf_putc('<', shf);
+ if (iop->heredoc /* nil when tracing */) {
+ /* 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;
case IOCAT:
shf_puts(">>", shf);
@@ -293,11 +303,8 @@ pioact(struct shf *shf, struct ioword *iop)
shf_puts(flag & IORDUP ? "<&" : ">&", shf);
break;
}
- /* name/delim are NULL when printing syntax errors */
- if (type == IOHERE) {
- if (iop->delim && !(iop->ioflag & IONDELIM))
- wdvarput(shf, iop->delim, 0, WDS_TPUTS);
- } else if (iop->ioname) {
+ /* name is NULL for IOHERE or when printing syntax errors */
+ if (iop->ioname) {
if (flag & IONAMEXP)
print_value_quoted(shf, iop->ioname);
else
@@ -342,13 +349,6 @@ wdvarput(struct shf *shf, const char *wp, int quotelevel, int opmode)
c = ord(*wp++);
if (opmode & WDS_TPUTS)
switch (c) {
- case ORD('\n'):
- if (quotelevel == 0) {
- c = ORD('\'');
- shf_putc(c, shf);
- shf_putc(ORD('\n'), shf);
- }
- break;
default:
if (quotelevel == 0)
/* FALLTHROUGH */
@@ -467,6 +467,9 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
{
int c;
+ if (!ptree_nest++)
+ ptree_hashere = false;
+
while ((c = ord(*fmt++))) {
if (c == '%') {
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);
} else {
- int i;
+ int i = indent;
+ ptree_outhere(shf);
shf_putc('\n', shf);
- i = indent;
while (i >= 8) {
shf_putc('\t', shf);
i -= 8;
@@ -530,6 +533,9 @@ vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
dont_trash_prevent_semicolon:
;
}
+
+ if (!--ptree_nest)
+ ptree_outhere(shf);
}
/*
diff --git a/src/ulimit.c b/src/ulimit.c
new file mode 100644
index 0000000..5bdfdd1
--- /dev/null
+++ b/src/ulimit.c
@@ -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
+ *
+ * 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);
+ }
+}
diff --git a/src/ulimits.gen b/src/ulimits.gen
new file mode 100644
index 0000000..374df60
--- /dev/null
+++ b/src/ulimits.gen
@@ -0,0 +1,60 @@
+/* +++ GENERATED FILE +++ DO NOT EDIT +++ */
+/*-
+ * Copyright (c) 2013, 2015, 2020
+ * mirabilos
+ *
+ * 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
diff --git a/src/ulimits.opt b/src/ulimits.opt
new file mode 100644
index 0000000..aad64be
--- /dev/null
+++ b/src/ulimits.opt
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2013, 2015, 2020
+ * mirabilos
+ *
+ * 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 */
+
+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
diff --git a/src/var.c b/src/var.c
index ade60c5..e3c92eb 100644
--- a/src/var.c
+++ b/src/var.c
@@ -29,7 +29,7 @@
#include
#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
@@ -1900,7 +1900,7 @@ c_typeset(const char **wp)
break;
}
- /* see comment below regarding possible opions */
+ /* see comment below regarding possible options */
opts = istset ? "L#R#UZ#afgi#lnprtux" : "p";
builtin_opt.flags |= GF_PLUSOPT;