Upgrade mksh to mksh-R59c
Test: TreeHugger Change-Id: I6d4f4497e54fd97672ee0d634b322277326a9748
This commit is contained in:
parent
e249d87246
commit
b02792c9ac
28 changed files with 934 additions and 528 deletions
|
@ -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\"",
|
||||
|
|
|
@ -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
|
||||
|
|
17
METADATA
17
METADATA
|
@ -1,3 +1,18 @@
|
|||
name: "mksh"
|
||||
third_party {
|
||||
license_type: NOTICE
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
98
src/Build.sh
98
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 <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
|
||||
ac_testn sig_t <<-'EOF'
|
||||
#include <sys/types.h>
|
||||
|
@ -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 <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'
|
||||
#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)
|
||||
|
|
|
@ -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 <m@mirbsd.org>
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
47
src/check.t
47
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:
|
||||
|
|
120
src/edit.c
120
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;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
@ -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;
|
||||
|
|
|
@ -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 },
|
||||
|
|
248
src/funcs.c
248
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,6 +707,22 @@ do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
|
|||
"exported " : "",
|
||||
Talias);
|
||||
}
|
||||
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)
|
||||
|
@ -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 = "<stdin>";
|
||||
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, "<stdout>",
|
||||
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);
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <sys/file.h>
|
||||
#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;
|
||||
|
|
13
src/lksh.1
13
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 <m@mirbsd.org>
|
||||
|
@ -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.
|
||||
.\"
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <locale.h>
|
||||
#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 ?
|
||||
|
|
50
src/misc.c
50
src/misc.c
|
@ -33,7 +33,7 @@
|
|||
#include <grp.h>
|
||||
#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);
|
||||
|
|
47
src/mksh.1
47
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
|
||||
|
|
36
src/mksh.faq
36
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 <tt>mksh</tt>? 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?
|
||||
|
||||
<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
|
||||
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); <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
|
||||
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, 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.</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 don’t 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 jupp’s “abendjoe” command) to prevent execution.
|
||||
This is <em>really</em> useful to write ad-hōc scripts as well.</p>
|
||||
----
|
||||
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…<br />
|
||||
<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
|
||||
Title: Are there any extensions to avoid?
|
||||
|
||||
|
|
89
src/os2.c
89
src/os2.c
|
@ -1,7 +1,7 @@
|
|||
/*-
|
||||
* Copyright (c) 2015, 2017, 2020
|
||||
* KO Myung-Hun <komh@chollian.net>
|
||||
* Copyright (c) 2017
|
||||
* Copyright (c) 2017, 2020
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* Provided that these terms and disclaimer and all copyright notices
|
||||
|
@ -32,11 +32,23 @@
|
|||
#include <unistd.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 *);
|
||||
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 */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* +++ GENERATED FILE +++ DO NOT EDIT +++ */
|
||||
/*-
|
||||
* Copyright (c) 2013, 2015
|
||||
* Copyright (c) 2013, 2015, 2019
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*-
|
||||
* Copyright (c) 2013, 2015
|
||||
* Copyright (c) 2013, 2015, 2019
|
||||
* mirabilos <m@mirbsd.org>
|
||||
*
|
||||
* 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),
|
||||
@@
|
||||
|
|
14
src/sh.h
14
src/sh.h
|
@ -78,7 +78,9 @@
|
|||
#if HAVE_PATHS_H
|
||||
#include <paths.h>
|
||||
#endif
|
||||
#ifndef MKSH_NOPWNAM
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
13
src/syn.c
13
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) {
|
||||
|
|
100
src/tree.c
100
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
360
src/ulimit.c
Normal file
360
src/ulimit.c
Normal 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
60
src/ulimits.gen
Normal 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
46
src/ulimits.opt
Normal 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
|
|
@ -29,7 +29,7 @@
|
|||
#include <sys/sysctl.h>
|
||||
#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;
|
||||
|
|
Loading…
Reference in a new issue