Upgrade mksh to mksh-R59c

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

View file

@ -38,6 +38,7 @@ cc_defaults {
"src/shf.c",
"src/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\"",

View file

@ -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

View file

@ -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
}
}

View file

@ -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, dont worry
@ -1898,23 +1903,6 @@ ac_test can_ucbint8 '!' can_int8type 1 "for UCB 8-bit integer type" <<-'EOF'
int main(int ac, char *av[]) { return ((u_int8_t)(size_t)av[ac]); }
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 dont 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)

View file

@ -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

View file

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.pl,v 1.50 2019/08/01 20:05:55 tg Exp $
# $MirOS: src/bin/mksh/check.pl,v 1.51 2020/06/22 17:10:59 tg Exp $
# $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $
#-
# 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

View file

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.845 2020/05/16 22:19:15 tg Exp $
# $MirOS: src/bin/mksh/check.t,v 1.853 2020/10/31 03:53:03 tg Exp $
# -*- mode: sh -*-
#-
# 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:

View file

@ -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);
}

View file

@ -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;

View file

@ -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 },

View file

@ -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 = "<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);

View file

@ -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;

View file

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/lksh.1,v 1.25 2018/12/25 19:38:08 tg Exp $
.\" $MirOS: src/bin/mksh/lksh.1,v 1.26 2020/09/04 22:37:01 tg Exp $
.\"-
.\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016, 2017, 2018
.\" 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.
.\"

View file

@ -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 ?

View file

@ -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);

View file

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.491 2020/05/16 22:12:36 tg Exp $
.\" $MirOS: src/bin/mksh/mksh.1,v 1.494 2020/10/01 22:39:57 tg Exp $
.\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $
.\"-
.\" 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

View file

@ -1,4 +1,4 @@
RCSID: $MirOS: src/bin/mksh/mksh.faq,v 1.7 2020/04/25 12:09:55 tg Exp $
RCSID: $MirOS: src/bin/mksh/mksh.faq,v 1.10 2020/10/01 22:59:12 tg Exp $
ToC: spelling
Title: How do you spell <tt>mksh</tt>? How do you pronounce it?
@ -207,7 +207,7 @@ Title: Why doesnt this use a Makefile to build?
ToC: oldbsd
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, mkshs input line editing uses a “windowed one-line”
concept: the line the cursor is on is a “window” into the whole input,
horizontally scrolled. Some other shells (that are much larger and have
more dependencies on external tooling) use a “multi-line” editing mode,
and users occasionally wish for this. It is on the long-term TODO, but
(due to the aforementioned implications) this is not trivial.</p>
<p>One way to achieve multi-line editing is to <em>dis</em>able input
line editing: <tt>set +o emacs +o vi</tt><br />This will, however, lose
you all editing features: tab completion, cursor keys, history, etc.</p>
<p>Another way, if you dont need it all the time, is to use a function
that spawns your editor on the input line: press <tt>^Xe</tt> in the
default emacs mode or <tt>Esc + v</tt> in vi mode. Once you exit the
editor, whatever was written there is run; this includes the original
command line if you quit without saving, so request the editor to exit
nōn-zero (e.g. using jupps “abendjoe” command) to prevent execution.
This is <em>really</em> useful to write ad-hōc scripts as well.</p>
----
ToC: ctrl-l-cls
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?

View file

@ -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 */

View file

@ -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

View file

@ -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),
@@

View file

@ -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);

View file

@ -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 */

View file

@ -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) {

View file

@ -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
View file

@ -0,0 +1,360 @@
/* $OpenBSD: c_ulimit.c,v 1.19 2013/11/28 10:33:37 sobrado Exp $ */
/*-
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
* 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
* 2019, 2020
* mirabilos <m@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
* are retained or reproduced in an accompanying document, permission
* is granted to deal in this work without restriction, including un-
* limited rights to use, publicly perform, distribute, sell, modify,
* merge, give away, or sublicence.
*
* This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
* the utmost extent permitted by applicable law, neither express nor
* implied; without malicious intent or gross negligence. In no event
* may a licensor, author or contributor be held liable for indirect,
* direct, other damage, loss, or other issues arising in any way out
* of dealing in the work, even if advised of the possibility of such
* damage or existence of a defect, except proven that it results out
* of said person's immediate fault when using the work as intended.
*/
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/ulimit.c,v 1.3 2020/07/24 21:08:26 tg Exp $");
#define SOFT 0x1
#define HARD 0x2
#if HAVE_RLIMIT
#if !HAVE_RLIM_T
typedef unsigned long rlim_t;
#endif
/* Magic to divine the 'm' and 'v' limits */
#ifdef RLIMIT_AS
#if !defined(RLIMIT_VMEM) || (RLIMIT_VMEM == RLIMIT_AS) || \
!defined(RLIMIT_RSS) || (RLIMIT_VMEM == RLIMIT_RSS)
#define ULIMIT_V_IS_AS
#elif defined(RLIMIT_VMEM)
#if !defined(RLIMIT_RSS) || (RLIMIT_RSS == RLIMIT_AS)
#define ULIMIT_V_IS_AS
#else
#define ULIMIT_V_IS_VMEM
#endif
#endif
#endif
#ifdef RLIMIT_RSS
#ifdef ULIMIT_V_IS_VMEM
#define ULIMIT_M_IS_RSS
#elif defined(RLIMIT_VMEM) && (RLIMIT_VMEM == RLIMIT_RSS)
#define ULIMIT_M_IS_VMEM
#else
#define ULIMIT_M_IS_RSS
#endif
#if defined(ULIMIT_M_IS_RSS) && defined(RLIMIT_AS) && \
!defined(__APPLE__) && (RLIMIT_RSS == RLIMIT_AS)
/* On Mac OSX keep -m as -v alias for pkgsrc and other software expecting it */
#undef ULIMIT_M_IS_RSS
#endif
#endif
#if !defined(RLIMIT_AS) && !defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_VMEM)
#define ULIMIT_V_IS_VMEM
#endif
#if !defined(ULIMIT_V_IS_VMEM) && defined(RLIMIT_VMEM) && \
(!defined(RLIMIT_RSS) || (defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)))
#define ULIMIT_M_IS_VMEM
#endif
#if defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_AS) && \
(RLIMIT_VMEM == RLIMIT_AS)
#undef ULIMIT_M_IS_VMEM
#endif
#if defined(ULIMIT_M_IS_RSS) && defined(ULIMIT_M_IS_VMEM)
# error nonsensical m ulimit
#endif
#if defined(ULIMIT_V_IS_VMEM) && defined(ULIMIT_V_IS_AS)
# error nonsensical v ulimit
#endif
#define LIMITS_GEN "rlimits.gen"
#else /* !HAVE_RLIMIT */
#undef RLIMIT_CORE /* just in case */
#if defined(UL_GETFSIZE)
#define KSH_UL_GFIL UL_GETFSIZE
#elif defined(UL_GFILLIM)
#define KSH_UL_GFIL UL_GFILLIM
#elif defined(__A_UX__) || defined(KSH_ULIMIT2_TEST)
#define KSH_UL_GFIL 1
#endif
#if defined(UL_SETFSIZE)
#define KSH_UL_SFIL UL_SETFSIZE
#elif defined(UL_SFILLIM)
#define KSH_UL_SFIL UL_SFILLIM
#elif defined(__A_UX__) || defined(KSH_ULIMIT2_TEST)
#define KSH_UL_SFIL 2
#endif
#if defined(KSH_UL_SFIL)
#define KSH_UL_WFIL true
#else
#define KSH_UL_WFIL false
#define KSH_UL_SFIL 0
#endif
#if defined(UL_GETMAXBRK)
#define KSH_UL_GBRK UL_GETMAXBRK
#elif defined(UL_GMEMLIM)
#define KSH_UL_GBRK UL_GMEMLIM
#elif defined(__A_UX__) || defined(KSH_ULIMIT2_TEST)
#define KSH_UL_GBRK 3
#endif
#if defined(UL_GDESLIM)
#define KSH_UL_GDES UL_GDESLIM
#elif defined(__GLIBC__) || defined(KSH_ULIMIT2_TEST)
#define KSH_UL_GDES 4
#endif
extern char etext;
extern long ulimit(int, long);
#define LIMITS_GEN "ulimits.gen"
#endif /* !HAVE_RLIMIT */
struct limits {
/* limit resource / read command */
int resource;
#if HAVE_RLIMIT
/* multiply by to get rlim_{cur,max} values */
unsigned int factor;
#else
/* write command */
int wesource;
/* writable? */
bool writable;
#endif
/* getopts char */
char optchar;
/* limit name */
char name[1];
};
#define RLIMITS_DEFNS
#if HAVE_RLIMIT
#define FN(lname,lid,lfac,lopt) \
static const struct { \
int resource; \
unsigned int factor; \
char optchar; \
char name[sizeof(lname)]; \
} rlimits_ ## lid = { \
lid, lfac, lopt, lname \
};
#else
#define FN(lname,lg,ls,lw,lopt) \
static const struct { \
int rcmd; \
int wcmd; \
bool writable; \
char optchar; \
char name[sizeof(lname)]; \
} rlimits_ ## lg = { \
lg, ls, lw, lopt, lname \
};
#endif
#include LIMITS_GEN
static void print_ulimit(const struct limits *, int);
static int set_ulimit(const struct limits *, const char *, int);
static const struct limits * const rlimits[] = {
#define RLIMITS_ITEMS
#include LIMITS_GEN
};
static const char rlimits_opts[] =
#define RLIMITS_OPTCS
#include LIMITS_GEN
#ifndef RLIMIT_CORE
"c"
#endif
;
int
c_ulimit(const char **wp)
{
size_t i = 0;
int how = SOFT | HARD, optc;
char what = 'f';
bool all = false;
while ((optc = ksh_getopt(wp, &builtin_opt, rlimits_opts)) != -1)
switch (optc) {
case ORD('H'):
how = HARD;
break;
case ORD('S'):
how = SOFT;
break;
case ORD('a'):
all = true;
break;
case ORD('?'):
bi_errorf("usage: ulimit [-%s] [value]", rlimits_opts);
return (1);
default:
what = optc;
}
while (i < NELEM(rlimits)) {
if (rlimits[i]->optchar == what)
goto found;
++i;
}
#ifndef RLIMIT_CORE
if (what == ORD('c'))
/* silently accept */
return 0;
#endif
internal_warningf("ulimit: %c", what);
return (1);
found:
if (wp[builtin_opt.optind]) {
if (all || wp[builtin_opt.optind + 1]) {
bi_errorf(Ttoo_many_args);
return (1);
}
return (set_ulimit(rlimits[i], wp[builtin_opt.optind], how));
}
if (!all)
print_ulimit(rlimits[i], how);
else for (i = 0; i < NELEM(rlimits); ++i) {
shprintf("-%c: %-20s ", rlimits[i]->optchar, rlimits[i]->name);
print_ulimit(rlimits[i], how);
}
return (0);
}
#if HAVE_RLIMIT
#define RL_T rlim_t
#define RL_U (rlim_t)RLIM_INFINITY
#else
#define RL_T long
#define RL_U LONG_MAX
#endif
static int
set_ulimit(const struct limits *l, const char *v, int how MKSH_A_UNUSED)
{
RL_T val = (RL_T)0;
#if HAVE_RLIMIT
struct rlimit limit;
#endif
if (strcmp(v, "unlimited") == 0)
val = RL_U;
else {
mksh_uari_t rval;
if (!evaluate(v, (mksh_ari_t *)&rval, KSH_RETURN_ERROR, false))
return (1);
/*
* Avoid problems caused by typos that evaluate misses due
* to evaluating unset parameters to 0...
* If this causes problems, will have to add parameter to
* evaluate() to control if unset params are 0 or an error.
*/
if (!rval && !ctype(v[0], C_DIGIT)) {
bi_errorf("invalid %s limit: %s", l->name, v);
return (1);
}
#if HAVE_RLIMIT
val = (rlim_t)((rlim_t)rval * l->factor);
#else
val = (RL_T)rval;
#endif
}
#if HAVE_RLIMIT
if (getrlimit(l->resource, &limit) < 0) {
#ifndef MKSH_SMALL
bi_errorf("limit %s could not be read, contact the mksh developers: %s",
l->name, cstrerror(errno));
#endif
/* some can't be read */
limit.rlim_cur = RLIM_INFINITY;
limit.rlim_max = RLIM_INFINITY;
}
if (how & SOFT)
limit.rlim_cur = val;
if (how & HARD)
limit.rlim_max = val;
if (!setrlimit(l->resource, &limit))
return (0);
#else
if (l->writable == false) {
/* check.t:ulimit-2 fails if we return 1 and/or do:
bi_errorf(Tf_ro, l->name);
*/
return (0);
}
if (ulimit(l->wesource, val) != -1L)
return (0);
#endif
if (errno == EPERM)
bi_errorf("%s exceeds allowable %s limit", v, l->name);
else
bi_errorf("bad %s limit: %s", l->name, cstrerror(errno));
return (1);
}
static void
print_ulimit(const struct limits *l, int how MKSH_A_UNUSED)
{
RL_T val = (RL_T)0;
#if HAVE_RLIMIT
struct rlimit limit;
if (getrlimit(l->resource, &limit))
#else
if ((val = ulimit(l->resource, 0)) < 0)
#endif
{
shf_puts("unknown\n", shl_stdout);
return;
}
#if HAVE_RLIMIT
if (how & SOFT)
val = limit.rlim_cur;
else if (how & HARD)
val = limit.rlim_max;
#endif
if (val == RL_U)
shf_puts("unlimited\n", shl_stdout);
else {
#if HAVE_RLIMIT
val /= l->factor;
#elif defined(KSH_UL_GBRK)
if (l->resource == KSH_UL_GBRK)
val = (RL_T)(((size_t)val - (size_t)&etext) /
(size_t)1024);
#endif
shprintf("%lu\n", (unsigned long)val);
}
}

60
src/ulimits.gen Normal file
View file

@ -0,0 +1,60 @@
/* +++ GENERATED FILE +++ DO NOT EDIT +++ */
/*-
* Copyright (c) 2013, 2015, 2020
* mirabilos <m@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
* are retained or reproduced in an accompanying document, permission
* is granted to deal in this work without restriction, including un-
* limited rights to use, publicly perform, distribute, sell, modify,
* merge, give away, or sublicence.
*
* This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
* the utmost extent permitted by applicable law, neither express nor
* implied; without malicious intent or gross negligence. In no event
* may a licensor, author or contributor be held liable for indirect,
* direct, other damage, loss, or other issues arising in any way out
* of dealing in the work, even if advised of the possibility of such
* damage or existence of a defect, except proven that it results out
* of said person's immediate fault when using the work as intended.
*-
* Keep {r,u}limits.opt in sync with each other!
*/
#ifndef RLIMITS_OPTCS
#if defined(RLIMITS_DEFNS)
__RCSID("$MirOS: src/bin/mksh/ulimits.opt,v 1.2 2020/07/24 20:50:11 tg Exp $");
#elif defined(RLIMITS_ITEMS)
#define FN(lname,lg,ls,lw,lopt) (const struct limits *)(&rlimits_ ## lg),
#endif
#ifndef F0
#define F0 FN
#endif
#ifdef KSH_UL_GFIL
FN("file(blocks)", KSH_UL_GFIL, KSH_UL_SFIL, KSH_UL_WFIL, 'f')
#endif
#ifdef KSH_UL_GBRK
FN("data(KiB)", KSH_UL_GBRK, 0, false, 'd')
#endif
#ifdef KSH_UL_GDES
FN("nofiles(descriptors)", KSH_UL_GDES, 0, false, 'n')
#endif
#undef F0
#undef FN
#undef RLIMITS_DEFNS
#undef RLIMITS_ITEMS
#else
"a"
#ifdef KSH_UL_GBRK
"d"
#endif
#ifdef KSH_UL_GFIL
"f"
#endif
"H"
#ifdef KSH_UL_GDES
"n"
#endif
"S"
#undef RLIMITS_OPTCS
#endif

46
src/ulimits.opt Normal file
View file

@ -0,0 +1,46 @@
/*-
* Copyright (c) 2013, 2015, 2020
* mirabilos <m@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
* are retained or reproduced in an accompanying document, permission
* is granted to deal in this work without restriction, including un-
* limited rights to use, publicly perform, distribute, sell, modify,
* merge, give away, or sublicence.
*
* This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
* the utmost extent permitted by applicable law, neither express nor
* implied; without malicious intent or gross negligence. In no event
* may a licensor, author or contributor be held liable for indirect,
* direct, other damage, loss, or other issues arising in any way out
* of dealing in the work, even if advised of the possibility of such
* damage or existence of a defect, except proven that it results out
* of said person's immediate fault when using the work as intended.
*-
* Keep {r,u}limits.opt in sync with each other!
*/
@RLIMITS_DEFNS
__RCSID("$MirOS: src/bin/mksh/ulimits.opt,v 1.2 2020/07/24 20:50:11 tg Exp $");
@RLIMITS_ITEMS
#define FN(lname,lg,ls,lw,lopt) (const struct limits *)(&rlimits_ ## lg),
@@
/* generic options for the ulimit builtin */
<a|
<H|
<S|
/* do not use options -H, -S or -a or change the order */
>f|KSH_UL_GFIL
FN("file(blocks)", KSH_UL_GFIL, KSH_UL_SFIL, KSH_UL_WFIL
>d|KSH_UL_GBRK
FN("data(KiB)", KSH_UL_GBRK, 0, false
>n|KSH_UL_GDES
FN("nofiles(descriptors)", KSH_UL_GDES, 0, false
|RLIMITS_OPTCS

View file

@ -29,7 +29,7 @@
#include <sys/sysctl.h>
#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;