Codebase list mksh / d2dbc83
update to a prerelease for Debian checks mirabilos authored 3 years ago mirabilos committed 3 years ago
23 changed file(s) with 844 addition(s) and 514 deletion(s). Raw diff Collapse all Expand all
00 #!/bin/sh
1 srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.756 2020/05/16 22:53:03 tg Exp $'
1 srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.763 2020/09/04 21:01:37 tg Exp $'
22 #-
33 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
44 # 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
720720 add_cppflags -DMKSH_NO_SIGSETJMP
721721 add_cppflags -DMKSH_TYPEDEF_SIG_ATOMIC_T=int
722722 ;;
723 A/UX)
724 add_cppflags -D_POSIX_SOURCE
725 : "${CC=gcc}"
726 : "${LIBS=-lposix}"
727 # GCC defines AUX but cc nothing
728 add_cppflags -D__A_UX__
729 ;;
723730 AIX)
724731 add_cppflags -D_ALL_SOURCE
725732 : "${HAVE_SETLOCALE_CTYPE=0}"
861868 ;;
862869 Minix3)
863870 add_cppflags -DMKSH_UNEMPLOYED
864 add_cppflags -DMKSH_NO_LIMITS
865871 add_cppflags -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2 -D_MINIX
866872 oldish_ed=no-stderr-ed # /usr/bin/ed(!) is broken
867 : "${HAVE_SETLOCALE_CTYPE=0}"
873 : "${HAVE_SETLOCALE_CTYPE=0}${MKSH_UNLIMITED=1}" #XXX recheck ulimit
868874 ;;
869875 MirBSD)
870876 ;;
897903 Ninix3)
898904 # similar to Minix3
899905 add_cppflags -DMKSH_UNEMPLOYED
900 add_cppflags -DMKSH_NO_LIMITS
906 : "${MKSH_UNLIMITED=1}" #XXX recheck ulimit
901907 # but no idea what else could be needed
902908 oswarn="; it has unknown issues"
903909 ;;
910916 HAVE_ISOFF_MKSH_ASSUME_UTF8=1
911917 HAVE_TERMIOS_H=0
912918 HAVE_MKNOD=0 # setmode() incompatible
913 oswarn="; it is being ported"
914919 check_categories="$check_categories nosymlink"
915920 : "${CC=gcc}"
916921 : "${SIZE=: size}"
917922 SRCS="$SRCS os2.c"
918923 add_cppflags -DMKSH_UNEMPLOYED
919924 add_cppflags -DMKSH_NOPROSPECTOFWORK
920 add_cppflags -DMKSH_NO_LIMITS
921925 add_cppflags -DMKSH_DOSPATH
926 : "${MKSH_UNLIMITED=1}"
922927 if test $textmode = 0; then
923928 x='dis'
924929 y='standard OS/2 tools'
13621367 etd=" on $et"
13631368 case $et in
13641369 klibc)
1365 add_cppflags -DMKSH_NO_LIMITS
1370 : "${MKSH_UNLIMITED=1}"
13661371 ;;
13671372 unknown)
13681373 # nothing special detected, don’t worry
18971902 int main(int ac, char *av[]) { return ((u_int8_t)(size_t)av[ac]); }
18981903 EOF
18991904
1900 ac_test rlim_t <<-'EOF'
1901 #include <sys/types.h>
1902 #if HAVE_BOTH_TIME_H
1903 #include <sys/time.h>
1904 #include <time.h>
1905 #elif HAVE_SYS_TIME_H
1906 #include <sys/time.h>
1907 #elif HAVE_TIME_H
1908 #include <time.h>
1909 #endif
1910 #if HAVE_SYS_RESOURCE_H
1911 #include <sys/resource.h>
1912 #endif
1913 #include <unistd.h>
1914 int main(void) { return (((int)(rlim_t)0) + isatty(0)); }
1915 EOF
1916
19171905 # only testn: added later below
19181906 ac_testn sig_t <<-'EOF'
19191907 #include <sys/types.h>
20642052 lks.l_type = F_WRLCK | F_UNLCK;
20652053 return (fcntl(0, F_SETLKW, &lks));
20662054 }
2055 EOF
2056
2057 ac_test rlimit '' 'getrlimit and setrlimit' <<-'EOF'
2058 #define MKSH_INCLUDES_ONLY
2059 #include "sh.h"
2060 int main(void) {
2061 struct rlimit l;
2062 if (getrlimit(0, &l)) return 1;
2063 l.rlim_max = l.rlim_cur;
2064 l.rlim_cur = RLIM_INFINITY;
2065 return (setrlimit(0, &l));
2066 }
2067 EOF
2068
2069 ac_test rlim_t rlimit 0 <<-'EOF'
2070 #include <sys/types.h>
2071 #if HAVE_BOTH_TIME_H
2072 #include <sys/time.h>
2073 #include <time.h>
2074 #elif HAVE_SYS_TIME_H
2075 #include <sys/time.h>
2076 #elif HAVE_TIME_H
2077 #include <time.h>
2078 #endif
2079 #if HAVE_SYS_RESOURCE_H
2080 #include <sys/resource.h>
2081 #endif
2082 #include <unistd.h>
2083 int main(void) { return (((int)(rlim_t)0) + isatty(0)); }
20672084 EOF
20682085
20692086 ac_test getrusage <<-'EOF'
24562473 $e done.
24572474 fi
24582475
2476 if test 1 = "$MKSH_UNLIMITED"; then
2477 add_cppflags -DMKSH_UNLIMITED
2478 else
2479 MKSH_UNLIMITED=0
2480 fi
2481
2482 if test 1 = "$USE_PRINTF_BUILTIN"; then
2483 add_cppflags -DMKSH_PRINTF_BUILTIN
2484 else
2485 USE_PRINTF_BUILTIN=0
2486 fi
2487
24592488 addsrcs '!' HAVE_STRLCPY strlcpy.c
24602489 addsrcs USE_PRINTF_BUILTIN printf.c
2461 test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN
2490 addsrcs '!' MKSH_UNLIMITED ulimit.c
2491
24622492 test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
2463 add_cppflags -DMKSH_BUILD_R=592
2493 add_cppflags -DMKSH_BUILD_R=593
24642494
24652495 $e $bi$me: Finished configuration testing, now producing output.$ao
24662496
25432573 args[\${#args[*]}]=\$TMPDIR
25442574 fi
25452575 print Testing mksh for conformance:
2546 grep -F -e Mir''OS: -e MIRBSD "\$sflag"
2576 grep -F -e 'KSH R' -e Mir''OS: "\$sflag" | sed '/KSH/s/^./& /'
25472577 print "This shell is actually:\\n\\t\$KSH_VERSION"
25482578 print 'test.sh built for mksh $dstversion'
25492579 cstr='\$os = defined \$^O ? \$^O : "unknown";'
26032633 op=`echo x"$file" | sed 's/^x\(.*\)\.c$/\1./'`
26042634 test -f $file || file=$srcdir/$file
26052635 files="$files$sp$file"
2606 sp=' '
26072636 echo "$CC $CFLAGS $CPPFLAGS $emitbc $file || exit 1" >>Rebuild.sh
26082637 if test $cm = dragonegg; then
26092638 echo "mv ${op}s ${op}ll" >>Rebuild.sh
26122641 else
26132642 objs="$objs$sp${op}o"
26142643 fi
2644 sp=' '
26152645 done
26162646 case $cm in
26172647 dragonegg|llvm)
26272657 echo "$CC $CFLAGS $LDFLAGS -o \$tcfn $lobjs $LIBS $ccpr" >>Rebuild.sh
26282658 echo "test -f \$tcfn || exit 1; $SIZE \$tcfn" >>Rebuild.sh
26292659 if test $cm = makefile; then
2630 extras='emacsfn.h exprtok.h rlimits.opt sh.h sh_flags.opt var_spec.h'
2660 extras='emacsfn.h exprtok.h rlimits.opt sh.h sh_flags.opt ulimits.opt var_spec.h'
26312661 test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc"
26322662 gens= genq=
26332663 for file in $optfiles; do
27332763 fi
27342764 $e
27352765 $e Installing the manual:
2736 if test -e FAQ.htm; then
2766 if test -f FAQ.htm; then
27372767 $e "# $i -c -o root -g bin -m 444 FAQ.htm /usr/share/doc/mksh/"
27382768 fi
27392769 if test -f mksh.cat1; then
2740 if test -e FAQ.htm; then
2770 if test -f FAQ.htm; then
27412771 $e plus either
27422772 fi
27432773 $e "# $i -c -o root -g bin -m 444 lksh.cat1" \
27502780 $e
27512781 $e Run the regression test suite: ./test.sh
27522782 $e Please also read the sample file dot.mkshrc and the fine manual.
2753 test -e FAQ.htm || \
2783 test -f FAQ.htm || \
27542784 $e Run FAQ2HTML.sh and place FAQ.htm into a suitable location as well.
27552785 exit 0
27562786
27742804 TARGET_OSREV [QNX] default: $(uname -r)
27752805
27762806 ==== feature selectors ====
2807 MKSH_UNLIMITED 1 to omit ulimit builtin completely
27772808 USE_PRINTF_BUILTIN 1 to include (unsupported) printf(1) as builtin
27782809 ===== general format =====
27792810 HAVE_STRLEN ac_test
27812812 HAVE_CAN_FSTACKPROTECTORALL ac_flags
27822813
27832814 ==== cpp definitions ====
2784 DEBUG dont use in production, wants gcc, implies:
2815 DEBUG don’t use in production, wants gcc, implies:
27852816 DEBUG_LEAKS enable freeing resources before exiting
27862817 KSH_VERSIONNAME_VENDOR_EXT when patching; space+plus+word (e.g. " +SuSE")
27872818 MKSHRC_PATH "~/.mkshrc" (do not change)
28032834 MKSH_NOPWNAM skip PAM calls, for -static on glibc or Solaris
28042835 MKSH_NO_CMDLINE_EDITING disable command line editing code entirely
28052836 MKSH_NO_DEPRECATED_WARNING omit warning when deprecated stuff is run
2806 MKSH_NO_LIMITS omit ulimit code
28072837 MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available
28082838 MKSH_NO_SIGSUSPEND use sigprocmask+pause instead of sigsuspend
28092839 MKSH_SMALL omit some code, optimise hard for size (slower)
0 #!/bin/mksh
1 rcsid='$MirOS: src/bin/mksh/FAQ2HTML.sh,v 1.1 2020/02/03 22:23:33 tg Exp $'
0 #!/bin/sh
1 rcsid='$MirOS: src/bin/mksh/FAQ2HTML.sh,v 1.2 2020/10/31 04:17:36 tg Exp $'
22 #-
33 # Copyright © 2020
44 # mirabilos <m@mirbsd.org>
3636 src_id=$(sed $p -n '/^RCSID: /s///p' "$srcdir"/mksh.faq)
3737 # sanity check
3838 case $src_id in
39 (*"$nl"*)
39 *"$nl"*)
4040 echo >&2 "E: more than one RCSID in mksh.faq?"
4141 exit 1 ;;
4242 esac
0 # $MirOS: src/bin/mksh/check.pl,v 1.50 2019/08/01 20:05:55 tg Exp $
0 # $MirOS: src/bin/mksh/check.pl,v 1.51 2020/06/22 17:10:59 tg Exp $
11 # $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $
22 #-
33 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
5454 # default is no arguments.
5555 # script m Value is written to a file which
5656 # is passed as an argument to the program
57 # (after the arguments arguments)
57 # (after the arguments from arguments)
5858 # stdin m Value is written to a file which is
5959 # used as standard-input for the program;
6060 # default is to use /dev/null.
194194 the path (kludge option)
195195 -p p Use p as the program to test
196196 -s s Read tests from file s; if s is a directory, it is recursively
197 scaned for test files (which end in .t).
197 scanned for test files (which end in .t).
198198 -T dir Use dir instead of /tmp to hold temporary files
199199 -t t Use t as default time limit for tests (default is unlimited)
200200 -U lcl Use lcl as UTF-8 locale (e.g. C.UTF-8) instead of the default
0 # $MirOS: src/bin/mksh/check.t,v 1.845 2020/05/16 22:19:15 tg Exp $
0 # $MirOS: src/bin/mksh/check.t,v 1.853 2020/10/31 03:53:03 tg Exp $
11 # -*- mode: sh -*-
22 #-
33 # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3030 # (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
3131
3232 expected-stdout:
33 KSH R59 2020/05/16
33 KSH R59 2020/10/31
3434 description:
3535 Check base version of full shell
3636 stdin:
61086108 ---
61096109 name: regression-28
61106110 description:
6111 variable assignements not detected well
6111 variable assignments not detected well
61126112 stdin:
61136113 a.x=1 echo hi
61146114 expected-exit: e != 0
61836183 ---
61846184 name: regression-35
61856185 description:
6186 Tempory files used for here-docs in functions get trashed after
6186 Temporay files used for here-docs in functions get trashed after
61876187 the function is parsed (before it is executed)
61886188 stdin:
61896189 f1() {
74567456 name: xxx-param-subst-qmark-1
74577457 description:
74587458 Check suppresion of error message with null string. According to
7459 POSIX, it shouldn't print the error as 'word' isn't ommitted.
7459 POSIX, it shouldn't print the error as 'word' isn't omitted.
74607460 ksh88/93, Solaris /bin/sh and /usr/xpg4/bin/sh all print the error.
74617461 stdin:
74627462 unset foo
88528852 XXX if the OS can already execute them, we lose
88538853 note: cygwin execve(2) doesn't return to us with ENOEXEC, we lose
88548854 note: Ultrix perl5 t4 returns 65280 (exit-code 255) and no text
8855 note: A/UX perl5 returns 6400 (exit-code 25), passes #1-3
88558856 XXX fails when LD_PRELOAD is set with -e and Perl chokes it (ASan)
88568857 need-pass: no
8857 category: !os:cygwin,!os:midipix,!os:msys,!os:ultrix,!os:uwin-nt,!smksh
8858 category: !os:aux,!os:cygwin,!os:midipix,!os:msys,!os:ultrix,!os:uwin-nt,!smksh
88588859 env-setup: !FOO=BAR!
88598860 stdin:
88608861 print '#!'"$__progname"'\nprint "1 a=$ENV{FOO}";' >t1
1149511496 description:
1149611497 Verify that file descriptors > 2 are private for Korn shells
1149711498 AT&T ksh93 does this still, which means we must keep it as well
11498 XXX fails on some old Perl installations
11499 need-pass: no
1150011499 stdin:
1150111500 cat >cld <<-EOF
1150211501 #!$__perlname
11503 open(my \$fh, ">&", 9) or die "E: open \$!";
11504 syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!";
11502 open(FH, ">&9") or die "E: open \$!";
11503 syswrite(FH, "Fowl\\n", 5) or die "E: write \$!";
1150511504 EOF
1150611505 chmod +x cld
1150711506 exec 9>&1
1151411513 description:
1151511514 Verify that file descriptors > 2 are not private for POSIX shells
1151611515 See Debian Bug #154540, Closes: #499139
11517 XXX fails on some old Perl installations
11518 need-pass: no
1151911516 stdin:
1152011517 cat >cld <<-EOF
1152111518 #!$__perlname
11522 open(my \$fh, ">&", 9) or die "E: open \$!";
11523 syswrite(\$fh, "Fowl\\n", 5) or die "E: write \$!";
11519 open(FH, ">&9") or die "E: open \$!";
11520 syswrite(FH, "Fowl\\n", 5) or die "E: write \$!";
1152411521 EOF
1152511522 chmod +x cld
1152611523 test -n "$POSH_VERSION" || set -o posix
1208512082 EOFN
1208612083 )|tr u x); }
1208712084 function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP {
12088 x=$( ( \cat >|bar <<"EOFN"
12085 x=$( ( \cat >|bar <<"EOFN" ) | \tr u x
1208912086 foo
1209012087 EOFN
12091 ) | \tr u x )
12088 )
1209212089 }
1209312090 inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() {
1209412091 cat 1>bar <<-EOFI
1211812115 EOFI
1211912116 )|tr u x); }
1212012117 function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP {
12121 x=$( ( \cat >bar <<-EOFI
12118 x=$( ( \cat >bar <<-EOFI ) | \tr u x
1212212119 foo
1212312120 EOFI
12124 ) | \tr u x )
12121 )
1212512122 }
1212612123 inline_IORDWR_IODUP() {
1212712124 sh 1<>/dev/console 0<&1 2>&1
1364613643 words, and command -p[vV] should find aliases, reserved words, and
1364713644 builtins over external commands.
1364813645 stdin:
13646 # extra checks prep
13647 mkdir mrr
13648 :>mrr/miau
13649 chmod +x mrr/miau
13650 # priorities
1364913651 PATH=/bin:/usr/bin
1365013652 alias foo="bar baz"
1365113653 alias '[ab]=:'
1365913661 # extra checks
1366013662 alias '[ab]'
1366113663 whence '[ab]'
13664 PATH=mrr
13665 case $(command -v miau) {
13666 (mrr/miau) echo fail ;;
13667 (!(/*|[A-Z]:/*)) echo fail2 ;;
13668 ($PWD/mrr/miau) echo ok ;;
13669 (/*|[A-Z]:/*) echo pwd bad? ;;
13670 (*) echo not reached ;;
13671 }
1366213672 expected-stdout:
1366313673 if
1366413674 if
1368613696 '[ab]' is an alias for :
1368713697 '[ab]'=:
1368813698 :
13699 ok
1368913700 ---
1369013701 name: whence-preserve-tradition
1369113702 description:
2828
2929 #ifndef MKSH_NO_CMDLINE_EDITING
3030
31 __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.351 2020/04/15 20:16:19 tg Exp $");
31 __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.356 2020/10/01 22:39:56 tg Exp $");
3232
3333 /*
3434 * in later versions we might use libtermcap for this, but since external
3939 #ifndef MKSH_CLS_STRING
4040 #define MKSH_CLS_STRING KSH_ESC_STRING "[;H" KSH_ESC_STRING "[J"
4141 #endif
42
43 static const char ctrl_x_e[] = "fc -e \"${VISUAL:-${EDITOR:-vi}}\" --";
4244
4345 /* tty driver characters we are interested in */
4446 #define EDCHAR_DISABLED 0xFFFFU
152154 char c;
153155 ssize_t n;
154156
155 while ((n = blocking_read(STDIN_FILENO, &c, 1)) < 0 && errno == EINTR)
157 while ((n = blocking_read(0, &c, 1)) < 0 && errno == EINTR)
156158 if (trap) {
157159 x_mode(false);
158160 runtraps(0);
969971 static int wbuf_len; /* length of window buffers (x_cols - 3) */
970972 static int win; /* window buffer in use */
971973 static char morec; /* more character at right of window */
972 static int lastref; /* argument to last refresh() */
973974 static int holdlen; /* length of holdbuf */
974975 #endif
975976 static int pwidth; /* width of prompt */
988989 static void x_zotc3(char **);
989990 static void x_vi_zotc(int);
990991 static void x_load_hist(char **);
991 static int x_search(char *, int, int);
992 static int x_search(const char *, int, int);
992993 #ifndef MKSH_SMALL
993994 static int x_search_dir(int);
994995 #endif
995 static int x_match(char *, char *);
996 static int x_match(const char *, const char *);
996997 static void x_redraw(int);
997998 static void x_push(size_t);
998999 static void x_bind_showone(int, int);
19451946 offset = x_match(xbuf, pat);
19461947 if (offset >= 0) {
19471948 x_goto(xbuf + offset + (p - pat) -
1948 (*pat == '^'));
1949 (*pat == '^' ? 1 : 0));
19491950 continue;
19501951 }
19511952 }
19671968
19681969 /* search backward from current line */
19691970 static int
1970 x_search(char *pat, int sameline, int offset)
1971 x_search(const char *pat, int sameline, int offset)
19711972 {
19721973 char **hp;
19731974 int i;
1974
1975 size_t patlen = strlen(pat);
1976
1977 if (*pat == '^')
1978 --patlen;
19751979 for (hp = x_histp - (sameline ? 0 : 1); hp >= history; --hp) {
19761980 i = x_match(*hp, pat);
19771981 if (i >= 0) {
19781982 if (offset < 0)
19791983 x_e_putc2('\n');
19801984 x_load_hist(hp);
1981 x_goto(xbuf + i + strlen(pat) - (*pat == '^'));
1985 x_goto(xbuf + i + patlen);
19821986 return (i);
19831987 }
19841988 }
20232027
20242028 /* return position of first match of pattern in string, else -1 */
20252029 static int
2026 x_match(char *str, char *pat)
2030 x_match(const char *str, const char *pat)
20272031 {
20282032 if (*pat == '^') {
20292033 return ((strncmp(str, pat + 1, strlen(pat + 1)) == 0) ? 0 : -1);
31243128 x_edit_line(int c MKSH_A_UNUSED)
31253129 {
31263130 if (x_arg_defaulted) {
3127 if (xep == xbuf) {
3128 x_e_putc2(KSH_BEL);
3129 return (KSTD);
3130 }
31313131 if (modified) {
31323132 *xep = '\0';
31333133 histsave(&source->line, xbuf, HIST_STORE, true);
31363136 x_arg = source->line - (histptr - x_histp);
31373137 }
31383138 if (x_arg)
3139 shf_snprintf(xbuf, xend - xbuf, Tf_sd,
3140 "fc -e ${VISUAL:-${EDITOR:-vi}} --", x_arg);
3139 shf_snprintf(xbuf, xend - xbuf, Tf_sd, ctrl_x_e, x_arg);
31413140 else
3142 strlcpy(xbuf, "fc -e ${VISUAL:-${EDITOR:-vi}} --", xend - xbuf);
3141 strlcpy(xbuf, ctrl_x_e, xend - xbuf);
31433142 xep = strnul(xbuf);
31443143 return (x_newline('\n'));
31453144 }
34323431 static int Backword(int);
34333432 static int Endword(int);
34343433 static int grabhist(int, int);
3435 static int grabsearch(int, int, int, const char *);
3434 static int grabsearch(const char *, int, int, bool);
34363435 static void redraw_line(bool);
3437 static void refresh(int);
3436 static void refresh(bool);
34383437 static int outofwin(void);
34393438 static void rewindow(void);
34403439 static int newcol(unsigned char, int);
3441 static void display(char *, char *, int);
3440 static void display(char *, char *, bool);
34423441 static void ed_mov_opt(int, char *);
34433442 static int expand_word(int);
34443443 static int complete_word(int, int);
36093608 winwidth = x_cols - pwidth - 3;
36103609 win = 0;
36113610 morec = ' ';
3612 lastref = 1;
36133611 holdlen = 0;
36143612
36153613 editmode = 2;
37113709 case 0:
37123710 if (state == VLIT) {
37133711 vs->cursor--;
3714 refresh(0);
3712 refresh(false);
37153713 } else
37163714 refresh(insert != 0);
37173715 break;
37373735 if (putbuf(ord(ch) == ORD('/') ?
37383736 "/" : "?", 1, false) != 0)
37393737 return (-1);
3740 refresh(0);
3738 refresh(false);
37413739 }
37423740 if (state == VVERSION) {
37433741 save_cbuf();
37453743 vs->linelen = 0;
37463744 putbuf(KSH_VERSION,
37473745 strlen(KSH_VERSION), false);
3748 refresh(0);
3746 refresh(false);
37493747 }
37503748 }
37513749 }
37573755 vi_error();
37583756 } else
37593757 vs->cbuf[vs->cursor++] = ch;
3760 refresh(1);
3758 refresh(true);
37613759 state = VNORMAL;
37623760 break;
37633761
37643762 case VVERSION:
37653763 restore_cbuf();
37663764 state = VNORMAL;
3767 refresh(0);
3765 refresh(false);
37683766 break;
37693767
37703768 case VARG1:
38283826 if (!srchpat[0]) {
38293827 vi_error();
38303828 state = VNORMAL;
3831 refresh(0);
3829 refresh(false);
38323830 return (0);
38333831 }
38343832 } else {
38413839 srchlen--;
38423840 vs->linelen -= char_len(locpat[srchlen]);
38433841 vs->cursor = vs->linelen;
3844 refresh(0);
3842 refresh(false);
38453843 return (0);
38463844 }
38473845 restore_cbuf();
38483846 state = VNORMAL;
3849 refresh(0);
3847 refresh(false);
38503848 } else if (isched(ch, edchars.kill)) {
38513849 srchlen = 0;
38523850 vs->linelen = 1;
38533851 vs->cursor = 1;
3854 refresh(0);
3852 refresh(false);
38553853 return (0);
38563854 } else if (isched(ch, edchars.werase)) {
38573855 unsigned int i, n;
38703868 vs->linelen -= char_len(locpat[i]);
38713869 srchlen = (int)n;
38723870 vs->cursor = vs->linelen;
3873 refresh(0);
3871 refresh(false);
38743872 return (0);
38753873 } else {
38763874 if (srchlen == SRCHLEN - 1)
38893887 vs->cbuf[vs->linelen++] = ch;
38903888 }
38913889 vs->cursor = vs->linelen;
3892 refresh(0);
3890 refresh(false);
38933891 }
38943892 return (0);
38953893 }
39303928 switch (vi_cmd(argc1, curcmd)) {
39313929 case -1:
39323930 vi_error();
3933 refresh(0);
3931 refresh(false);
39343932 break;
39353933 case 0:
39363934 if (insert != 0)
39383936 refresh(insert != 0);
39393937 break;
39403938 case 1:
3941 refresh(0);
3939 refresh(false);
39423940 return (1);
39433941 case 2:
39443942 /* back from a 'v' command - don't redraw the screen */
39533951 switch (vi_cmd(lastac, lastcmd)) {
39543952 case -1:
39553953 vi_error();
3956 refresh(0);
3954 refresh(false);
39573955 break;
39583956 case 0:
39593957 if (insert != 0) {
39663964 vi_error();
39673965 }
39683966 }
3969 refresh(0);
3967 refresh(false);
39703968 break;
39713969 case 1:
3972 refresh(0);
3970 refresh(false);
39733971 return (1);
39743972 case 2:
39753973 /* back from a 'v' command - can't happen */
41344132 vi_cmd(int argcnt, const char *cmd)
41354133 {
41364134 int ncursor;
4137 int cur, c1, c2, c3 = 0;
4135 int cur, c1, c2;
41384136 int any;
4137 bool b;
41394138 struct edstate *t;
41404139
41414140 if (argcnt == 0 && !is_zerocount(*cmd))
44064405
44074406 case ORD('v'):
44084407 if (!argcnt) {
4409 if (vs->linelen == 0)
4410 return (-1);
44114408 if (modified) {
44124409 vs->cbuf[vs->linelen] = '\0';
44134410 histsave(&source->line, vs->cbuf,
44184415 }
44194416 if (argcnt)
44204417 shf_snprintf(vs->cbuf, vs->cbufsize, Tf_sd,
4421 "fc -e ${VISUAL:-${EDITOR:-vi}} --",
4422 argcnt);
4418 ctrl_x_e, argcnt);
44234419 else
4424 strlcpy(vs->cbuf,
4425 "fc -e ${VISUAL:-${EDITOR:-vi}} --",
4426 vs->cbufsize);
4420 strlcpy(vs->cbuf, ctrl_x_e, vs->cbufsize);
44274421 vs->linelen = strlen(vs->cbuf);
44284422 return (2);
44294423
44734467
44744468 /* FALLTHROUGH */
44754469 case ORD('/'):
4476 c3 = 1;
4470 c1 = 1;
44774471 srchlen = 0;
44784472 lastsearch = *cmd;
4479 /* FALLTHROUGH */
4473 if (0)
4474 /* FALLTHROUGH */
44804475 case ORD('n'):
44814476 case ORD('N'):
4477 c1 = 0;
44824478 if (lastsearch == ORD(' '))
44834479 return (-1);
4484 if (lastsearch == ORD('?'))
4485 c1 = 1;
4486 else
4487 c1 = 0;
4480 b = (lastsearch == ORD('?'));
44884481 if (*cmd == 'N')
4489 c1 = !c1;
4490 if ((c2 = grabsearch(modified, hnum,
4491 c1, srchpat)) < 0) {
4492 if (c3) {
4482 b = !b;
4483 if ((c2 = grabsearch(srchpat, modified, hnum, b)) < 0) {
4484 if (c1) {
44934485 restore_cbuf();
4494 refresh(0);
4486 refresh(false);
44954487 }
44964488 return (-1);
44974489 } else {
51165108 }
51175109
51185110 static int
5119 grabsearch(int save, int start, int fwd, const char *pat)
5111 grabsearch(const char *pat, int save, int start, bool fwd)
51205112 {
51215113 char *hptr;
51225114 int hist;
51235115 bool anchored;
51245116
5125 if ((start == 0 && fwd == 0) || (start >= hlast - 1 && fwd == 1))
5117 if ((start == 0 && !fwd) || (start >= hlast - 1 && fwd))
51265118 return (-1);
51275119 if (fwd)
51285120 start++;
51295121 else
51305122 start--;
51315123 anchored = *pat == '^' ? (++pat, true) : false;
5132 if ((hist = findhist(start, fwd, pat, anchored)) < 0) {
5124 if ((hist = findhist(start, pat, fwd, anchored)) < 0) {
51335125 /* (start != 0 && fwd && match(holdbufp, pat) >= 0) */
51345126 if (start != 0 && fwd && strcmp(holdbufp, pat) >= 0) {
51355127 restore_cbuf();
51625154 }
51635155
51645156 static void
5165 refresh(int leftside)
5166 {
5167 if (leftside < 0)
5168 leftside = lastref;
5169 else
5170 lastref = leftside;
5157 refresh(bool leftside)
5158 {
51715159 if (outofwin())
51725160 rewindow();
51735161 display(wbuf[1 - win], wbuf[win], leftside);
52235211 }
52245212
52255213 static void
5226 display(char *wb1, char *wb2, int leftside)
5214 display(char *wb1, char *wb2, bool leftside)
52275215 {
52285216 unsigned char ch;
52295217 char *twb1, *twb2, mc;
53785366 hnum = hlast;
53795367 insert = INSERT;
53805368 lastac = 0;
5381 refresh(0);
5369 refresh(false);
53825370 return (rval);
53835371 }
53845372
54935481 insert = INSERT;
54945482 /* prevent this from being redone... */
54955483 lastac = 0;
5496 refresh(0);
5484 refresh(false);
54975485
54985486 return (rval);
54995487 }
2323
2424 #include "sh.h"
2525
26 __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.223 2020/04/07 23:14:41 tg Exp $");
26 __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.224 2020/08/27 19:52:43 tg Exp $");
2727
2828 #ifndef MKSH_DEFAULT_EXECSHELL
2929 #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
12121212 }
12131213
12141214 Search:
1215 if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) &&
1215 if ((!tp || (tp->type == CTALIAS && !(tp->flag & ISSET))) &&
12161216 (flags & FC_PATH)) {
12171217 if (!tp) {
12181218 if (insert && !(flags & FC_DEFPATH)) {
13501350 XcheckN(xs, xp, p - sp);
13511351 memcpy(xp, sp, p - sp);
13521352 xp += p - sp;
1353 #ifdef __OS2__
1354 if (xp > Xstring(xs, xp) && mksh_cdirsep(xp[-1]))
1353 if (mksh_cdirsep(xp[-1]))
13551354 xp--;
1356 #endif
13571355 *xp++ = '/';
13581356 }
13591357 sp = p;
2222
2323 #include "sh.h"
2424
25 __RCSID("$MirOS: src/bin/mksh/expr.c,v 1.107 2020/03/27 02:49:40 tg Exp $");
25 __RCSID("$MirOS: src/bin/mksh/expr.c,v 1.108 2020/06/20 02:27:50 tg Exp $");
2626
2727 #define EXPRTOK_DEFNS
2828 #include "exprtok.h"
885885 unsigned int val) MKSH_A_PURE;
886886
887887 /*
888 * Generated from the UCD 13.0.0 by
889 * MirOS: contrib/code/Snippets/eawparse,v 1.14 2020/03/27 01:33:21 tg Exp $
888 * Generated from the UCD 13.0.0 - see /usr/share/doc/legal/LICENCE-BSD - by
889 * MirOS: contrib/code/Snippets/eawparse,v 1.15 2020/06/15 20:31:13 tg Exp $
890890 */
891891
892892 /*-
11351135 { 0xABE5, 0xABE5 },
11361136 { 0xABE8, 0xABE8 },
11371137 { 0xABED, 0xABED },
1138 { 0xD7B0, 0xD7FF },
11381139 { 0xFB1E, 0xFB1E },
11391140 { 0xFE00, 0xFE0F },
11401141 { 0xFE20, 0xFE2F },
00 /* $OpenBSD: c_ksh.c,v 1.37 2015/09/10 22:48:58 nicm Exp $ */
11 /* $OpenBSD: c_sh.c,v 1.46 2015/07/20 20:46:24 guenther Exp $ */
22 /* $OpenBSD: c_test.c,v 1.18 2009/03/01 20:11:06 otto Exp $ */
3 /* $OpenBSD: c_ulimit.c,v 1.19 2013/11/28 10:33:37 sobrado Exp $ */
43
54 /*-
65 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3837 #endif
3938 #endif
4039
41 __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.373 2020/05/16 22:38:21 tg Exp $");
40 __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.379 2020/08/27 19:52:44 tg Exp $");
4241
4342 #if HAVE_KILLPG
4443 /*
5150 #define mksh_kill kill
5251 #endif
5352
54 /* XXX conditions correct? */
55 #if !defined(RLIM_INFINITY) && !defined(MKSH_NO_LIMITS)
56 #define MKSH_NO_LIMITS 1
57 #endif
58
59 #ifdef MKSH_NO_LIMITS
53 #ifdef MKSH_UNLIMITED
6054 #define c_ulimit c_true
6155 #endif
6256
706700 "exported " : "",
707701 Talias);
708702 }
709 shf_puts(tp->val.s, shl_stdout);
703 if (!mksh_abspath(tp->val.s)) {
704 const char *xcwd = current_wd[0] ?
705 current_wd : ".";
706 size_t xlen = strlen(xcwd);
707 size_t clen = strlen(tp->val.s) + 1;
708 char *xp = alloc(xlen + 1 + clen, ATEMP);
709
710 memcpy(xp, xcwd, xlen);
711 if (mksh_cdirsep(xp[xlen - 1]))
712 --xlen;
713 xp[xlen++] = '/';
714 memcpy(xp + xlen, tp->val.s, clen);
715 simplify_path(xp);
716 shf_puts(xp, shl_stdout);
717 afree(xp, ATEMP);
718 } else
719 shf_puts(tp->val.s, shl_stdout);
710720 } else {
711721 if (vflag)
712722 shprintf(Tnot_found_s, id);
32123222 bi_errorf(Tf_s, msg);
32133223 }
32143224
3215 #ifndef MKSH_NO_LIMITS
3216 #define SOFT 0x1
3217 #define HARD 0x2
3218
3219 /* Magic to divine the 'm' and 'v' limits */
3220
3221 #ifdef RLIMIT_AS
3222 #if !defined(RLIMIT_VMEM) || (RLIMIT_VMEM == RLIMIT_AS) || \
3223 !defined(RLIMIT_RSS) || (RLIMIT_VMEM == RLIMIT_RSS)
3224 #define ULIMIT_V_IS_AS
3225 #elif defined(RLIMIT_VMEM)
3226 #if !defined(RLIMIT_RSS) || (RLIMIT_RSS == RLIMIT_AS)
3227 #define ULIMIT_V_IS_AS
3228 #else
3229 #define ULIMIT_V_IS_VMEM
3230 #endif
3231 #endif
3232 #endif
3233
3234 #ifdef RLIMIT_RSS
3235 #ifdef ULIMIT_V_IS_VMEM
3236 #define ULIMIT_M_IS_RSS
3237 #elif defined(RLIMIT_VMEM) && (RLIMIT_VMEM == RLIMIT_RSS)
3238 #define ULIMIT_M_IS_VMEM
3239 #else
3240 #define ULIMIT_M_IS_RSS
3241 #endif
3242 #if defined(ULIMIT_M_IS_RSS) && defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)
3243 #undef ULIMIT_M_IS_RSS
3244 #endif
3245 #endif
3246
3247 #if !defined(RLIMIT_AS) && !defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_VMEM)
3248 #define ULIMIT_V_IS_VMEM
3249 #endif
3250
3251 #if !defined(ULIMIT_V_IS_VMEM) && defined(RLIMIT_VMEM) && \
3252 (!defined(RLIMIT_RSS) || (defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)))
3253 #define ULIMIT_M_IS_VMEM
3254 #endif
3255
3256 #if defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_AS) && \
3257 (RLIMIT_VMEM == RLIMIT_AS)
3258 #undef ULIMIT_M_IS_VMEM
3259 #endif
3260
3261 #if defined(ULIMIT_M_IS_RSS) && defined(ULIMIT_M_IS_VMEM)
3262 # error nonsensical m ulimit
3263 #endif
3264
3265 #if defined(ULIMIT_V_IS_VMEM) && defined(ULIMIT_V_IS_AS)
3266 # error nonsensical v ulimit
3267 #endif
3268
3269 struct limits {
3270 /* limit resource */
3271 int resource;
3272 /* multiply by to get rlim_{cur,max} values */
3273 unsigned int factor;
3274 /* getopts char */
3275 char optchar;
3276 /* limit name */
3277 char name[1];
3278 };
3279
3280 #define RLIMITS_DEFNS
3281 #define FN(lname,lid,lfac,lopt) \
3282 static const struct { \
3283 int resource; \
3284 unsigned int factor; \
3285 char optchar; \
3286 char name[sizeof(lname)]; \
3287 } rlimits_ ## lid = { \
3288 lid, lfac, lopt, lname \
3289 };
3290 #include "rlimits.gen"
3291
3292 static void print_ulimit(const struct limits *, int);
3293 static int set_ulimit(const struct limits *, const char *, int);
3294
3295 static const struct limits * const rlimits[] = {
3296 #define RLIMITS_ITEMS
3297 #include "rlimits.gen"
3298 };
3299
3300 static const char rlimits_opts[] =
3301 #define RLIMITS_OPTCS
3302 #include "rlimits.gen"
3303 ;
3304
3305 int
3306 c_ulimit(const char **wp)
3307 {
3308 size_t i = 0;
3309 int how = SOFT | HARD, optc, what = 'f';
3310 bool all = false;
3311
3312 while ((optc = ksh_getopt(wp, &builtin_opt, rlimits_opts)) != -1)
3313 switch (optc) {
3314 case 'H':
3315 how = HARD;
3316 break;
3317 case 'S':
3318 how = SOFT;
3319 break;
3320 case 'a':
3321 all = true;
3322 break;
3323 case '?':
3324 bi_errorf("usage: ulimit [-%s] [value]", rlimits_opts);
3325 return (1);
3326 default:
3327 what = optc;
3328 }
3329
3330 while (i < NELEM(rlimits)) {
3331 if (rlimits[i]->optchar == what)
3332 goto found;
3333 ++i;
3334 }
3335 internal_warningf("ulimit: %c", what);
3336 return (1);
3337 found:
3338 if (wp[builtin_opt.optind]) {
3339 if (all || wp[builtin_opt.optind + 1]) {
3340 bi_errorf(Ttoo_many_args);
3341 return (1);
3342 }
3343 return (set_ulimit(rlimits[i], wp[builtin_opt.optind], how));
3344 }
3345 if (!all)
3346 print_ulimit(rlimits[i], how);
3347 else for (i = 0; i < NELEM(rlimits); ++i) {
3348 shprintf("-%c: %-20s ", rlimits[i]->optchar, rlimits[i]->name);
3349 print_ulimit(rlimits[i], how);
3350 }
3351 return (0);
3352 }
3353
3354 static int
3355 set_ulimit(const struct limits *l, const char *v, int how)
3356 {
3357 rlim_t val = (rlim_t)0;
3358 struct rlimit limit;
3359
3360 if (strcmp(v, "unlimited") == 0)
3361 val = (rlim_t)RLIM_INFINITY;
3362 else {
3363 mksh_uari_t rval;
3364
3365 if (!evaluate(v, (mksh_ari_t *)&rval, KSH_RETURN_ERROR, false))
3366 return (1);
3367 /*
3368 * Avoid problems caused by typos that evaluate misses due
3369 * to evaluating unset parameters to 0...
3370 * If this causes problems, will have to add parameter to
3371 * evaluate() to control if unset params are 0 or an error.
3372 */
3373 if (!rval && !ctype(v[0], C_DIGIT)) {
3374 bi_errorf("invalid %s limit: %s", l->name, v);
3375 return (1);
3376 }
3377 val = (rlim_t)((rlim_t)rval * l->factor);
3378 }
3379
3380 if (getrlimit(l->resource, &limit) < 0) {
3381 #ifndef MKSH_SMALL
3382 bi_errorf("limit %s could not be read, contact the mksh developers: %s",
3383 l->name, cstrerror(errno));
3384 #endif
3385 /* some can't be read */
3386 limit.rlim_cur = RLIM_INFINITY;
3387 limit.rlim_max = RLIM_INFINITY;
3388 }
3389 if (how & SOFT)
3390 limit.rlim_cur = val;
3391 if (how & HARD)
3392 limit.rlim_max = val;
3393 if (!setrlimit(l->resource, &limit))
3394 return (0);
3395 if (errno == EPERM)
3396 bi_errorf("%s exceeds allowable %s limit", v, l->name);
3397 else
3398 bi_errorf("bad %s limit: %s", l->name, cstrerror(errno));
3399 return (1);
3400 }
3401
3402 static void
3403 print_ulimit(const struct limits *l, int how)
3404 {
3405 rlim_t val = (rlim_t)0;
3406 struct rlimit limit;
3407
3408 if (getrlimit(l->resource, &limit)) {
3409 shf_puts("unknown\n", shl_stdout);
3410 return;
3411 }
3412 if (how & SOFT)
3413 val = limit.rlim_cur;
3414 else if (how & HARD)
3415 val = limit.rlim_max;
3416 if (val == (rlim_t)RLIM_INFINITY)
3417 shf_puts("unlimited\n", shl_stdout);
3418 else
3419 shprintf("%lu\n", (unsigned long)(val / l->factor));
3420 }
3421 #endif
3422
34233225 int
34243226 c_rename(const char **wp)
34253227 {
34763278 int
34773279 c_cat(const char **wp)
34783280 {
3479 int fd = STDIN_FILENO, rv;
3281 int fd = 0, rv;
34803282 ssize_t n, w;
34813283 const char *fn = "<stdin>";
34823284 char *buf, *cp;
35093311 if (*wp) {
35103312 fn = *wp++;
35113313 if (ksh_isdash(fn))
3512 fd = STDIN_FILENO;
3314 fd = 0;
35133315 else if ((fd = binopen2(fn, O_RDONLY)) < 0) {
35143316 bi_errorf(Tf_sD_s, fn, cstrerror(errno));
35153317 rv = 1;
35283330 opipe = block_pipe();
35293331 continue;
35303332 }
3531 /* an error occured during reading */
3333 /* an error occurred during reading */
35323334 bi_errorf(Tf_sD_s, fn, cstrerror(errno));
35333335 rv = 1;
35343336 break;
35383340 while (n) {
35393341 if (intrsig)
35403342 goto has_intrsig;
3541 if ((w = write(STDOUT_FILENO, cp, n)) != -1) {
3343 if ((w = write(1, cp, n)) != -1) {
35423344 n -= w;
35433345 cp += w;
35443346 continue;
35573359 /* fake receiving signal */
35583360 rv = ksh_sigmask(SIGPIPE);
35593361 } else {
3560 /* an error occured during writing */
3362 /* an error occurred during writing */
35613363 bi_errorf(Tf_sD_s, "<stdout>",
35623364 cstrerror(errno));
35633365 rv = 1;
35643366 }
3565 if (fd != STDIN_FILENO)
3367 if (fd != 0)
35663368 close(fd);
35673369 goto out;
35683370 }
35693371 }
3570 if (fd != STDIN_FILENO)
3372 if (fd != 0)
35713373 close(fd);
35723374 } while (*wp);
35733375
2626 #include <sys/file.h>
2727 #endif
2828
29 __RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.169 2019/09/16 21:10:33 tg Exp $");
29 __RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.170 2020/10/01 22:53:20 tg Exp $");
3030
3131 Trap sigtraps[ksh_NSIG + 1];
3232 static struct sigaction Sigact_ign;
414414 bool anchored = *str == '?' ? (++str, false) : true;
415415
416416 /* the -1 is to avoid the current fc command */
417 if ((n = findhist(histptr - history - 1, 0, str, anchored)) < 0)
417 if ((n = findhist(histptr - history - 1, str, false,
418 anchored)) < 0)
418419 bi_errorf(Tf_sD_s, str, Tnot_in_history);
419420 else
420421 hp = &history[n];
478479 * direction.
479480 */
480481 int
481 findhist(int start, int fwd, const char *str, bool anchored)
482 findhist(int start, const char *str, bool fwd, bool anchored)
482483 {
483484 char **hp;
484485 int maxhist = histptr - history;
0 .\" $MirOS: src/bin/mksh/lksh.1,v 1.25 2018/12/25 19:38:08 tg Exp $
0 .\" $MirOS: src/bin/mksh/lksh.1,v 1.26 2020/09/04 22:37:01 tg Exp $
11 .\"-
22 .\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016, 2017, 2018
33 .\" mirabilos <m@mirbsd.org>
2424 .\" thus use - for hyphens and \- for minus signs and option dashes
2525 .\" * ~ is size-reduced and placed atop in groff, so use \*(TI
2626 .\" * ^ is size-reduced and placed atop in groff, so use \*(ha
27 .\" * \(en does not work in nroff, so use \*(en
27 .\" * \(en does not work in nroff, so use \*(en for a solo en dash
28 .\" * and \*(EM for a correctly spaced em dash
2829 .\" * <>| are problematic, so redefine and use \*(Lt\*(Gt\*(Ba
2930 .\" Also make sure to use \& *before* a punctuation char that is to not
3031 .\" be interpreted as punctuation, and especially with two-letter words
5859 . ds ha ^
5960 . ds en \(em
6061 .\}
62 .ie n \{\
63 . ds EM \ \*(en\ \&
64 .\}
65 .el \{\
66 . ds EM \f(TR\^\(em\^\fP
67 .\}
6168 .\"
6269 .\" Implement .Dd with the Mdocdate RCS keyword
6370 .\"
7380 .\" with -mandoc, it might implement .Mx itself, but we want to
7481 .\" use our own definition. And .Dd must come *first*, always.
7582 .\"
76 .Dd $Mdocdate: December 25 2018 $
83 .Dd $Mdocdate: September 4 2020 $
7784 .\"
7885 .\" Check which macro package we use, and do other -mdoc setup.
7986 .\"
3434 #include <locale.h>
3535 #endif
3636
37 __RCSID("$MirOS: src/bin/mksh/main.c,v 1.372 2020/05/16 22:51:24 tg Exp $");
37 __RCSID("$MirOS: src/bin/mksh/main.c,v 1.374 2020/10/01 20:28:54 tg Exp $");
3838
3939 #ifndef MKSHRC_PATH
4040 #define MKSHRC_PATH "~/.mkshrc"
11961196
11971197 /*
11981198 * Initialise tty_fd. Used for tracking the size of the terminal,
1199 * saving/resetting tty modes upon forground job completion, and
1199 * saving/resetting tty modes upon foreground job completion, and
12001200 * for setting up the tty process group. Return values:
12011201 * 0 = got controlling tty
12021202 * 1 = got terminal but no controlling tty
14281428 /* Avoid foo: foo[2]: ... */
14291429 if (!fileline || !source || !source->file ||
14301430 strcmp(source->file, kshname) != 0)
1431 shf_fprintf(shl_out, Tf_sD_, kshname + (*kshname == '-'));
1431 shf_fprintf(shl_out, Tf_sD_, kshname +
1432 (*kshname == '-' ? 1 : 0));
14321433 if (fileline && source && source->file != NULL) {
14331434 shf_fprintf(shl_out, "%s[%lu]: ", source->file,
14341435 (unsigned long)(source->errline ?
3232 #include <grp.h>
3333 #endif
3434
35 __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.299 2020/05/16 22:19:58 tg Exp $");
35 __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.302 2020/08/27 19:52:45 tg Exp $");
3636
3737 #define KSH_CHVT_FLAG
3838 #ifdef MKSH_SMALL
13271327 if (go->flags & GF_ERROR)
13281328 bi_errorfz();
13291329 }
1330 return ('?');
1330 return (ORD('?'));
13311331 }
13321332 /**
13331333 * : means argument must be present, may be part of option argument
13461346 if (optionsp[0] == ':') {
13471347 go->buf[0] = c;
13481348 go->optarg = go->buf;
1349 return (':');
1349 return (ORD(':'));
13501350 }
13511351 warningf(true, Tf_optfoo,
13521352 (go->flags & GF_NONAME) ? "" : argv[0],
13541354 c, Treq_arg);
13551355 if (go->flags & GF_ERROR)
13561356 bi_errorfz();
1357 return ('?');
1357 return (ORD('?'));
13581358 }
13591359 go->p = 0;
13601360 } else if (*o == ',') {
13821382 go->optarg = NULL;
13831383 }
13841384 }
1385 return (c);
1385 return (ord(c));
13861386 }
13871387
13881388 /*
19261926 * - if file starts with '/', append file to result & set cdpathp to NULL
19271927 * - if file starts with ./ or ../ append cwd and file to result
19281928 * and set cdpathp to NULL
1929 * - if the first element of cdpathp doesnt start with a '/' xx or '.' xx
1929 * - if the first element of cdpathp doesn't start with a '/' xx or '.' xx
19301930 * then cwd is appended to result.
19311931 * - the first element of cdpathp is appended to result
19321932 * - file is appended to result
19821982 XcheckN(*xsp, xp, len);
19831983 memcpy(xp, cwd, len);
19841984 xp += len;
1985 if (!mksh_cdirsep(cwd[len - 1]))
1986 Xput(*xsp, xp, '/');
1985 if (mksh_cdirsep(xp[-1]))
1986 xp--;
1987 *xp++ = '/';
19871988 }
19881989 *phys_pathp = Xlength(*xsp, xp);
19891990 if (use_cdpath && plen) {
19901991 XcheckN(*xsp, xp, plen);
19911992 memcpy(xp, plist, plen);
19921993 xp += plen;
1993 if (!mksh_cdirsep(plist[plen - 1]))
1994 Xput(*xsp, xp, '/');
1994 if (mksh_cdirsep(xp[-1]))
1995 xp--;
1996 *xp++ = '/';
19951997 rval = 1;
19961998 }
19971999 }
20552057 case '\\':
20562058 #endif
20572059 /* exactly two leading slashes? (SUSv4 3.266) */
2058 if (p[1] == p[0] && !mksh_cdirsep(p[2]))
2060 if (p[1] == p[0] && !mksh_cdirsep(p[2])) {
20592061 /* keep them, e.g. for UNC pathnames */
2062 #ifdef MKSH_DOSPATH
2063 *p++ = '/';
2064 #else
20602065 ++p;
2066 #endif
2067 }
20612068 needslash = true;
20622069 break;
20632070 default:
21882195 oldpwd_s = global(TOLDPWD);
21892196
21902197 if (!wp[0]) {
2191 /* No arguments - go home */
2198 /* no arguments; go home */
21922199 if ((dir = str_val(global("HOME"))) == null) {
21932200 bi_errorf("no home directory (HOME not set)");
21942201 return (2);
21952202 }
21962203 } else if (!wp[1]) {
2197 /* One argument: - or dir */
2198 strdupx(allocd, wp[0], ATEMP);
2199 if (ksh_isdash((dir = allocd))) {
2200 afree(allocd, ATEMP);
2201 allocd = NULL;
2204 /* one argument: - or dir */
2205 if (ksh_isdash(wp[0])) {
22022206 dir = str_val(oldpwd_s);
22032207 if (dir == null) {
22042208 bi_errorf(Tno_OLDPWD);
22052209 return (2);
22062210 }
22072211 printpath = true;
2212 } else {
2213 strdupx(allocd, wp[0], ATEMP);
2214 dir = allocd;
22082215 }
22092216 } else if (!wp[2]) {
2210 /* Two arguments - substitute arg1 in PWD for arg2 */
2217 /* two arguments; substitute arg1 in PWD for arg2 */
22112218 size_t ilen, olen, nlen, elen;
22122219 char *cp;
22132220
22162223 return (2);
22172224 }
22182225 /*
2219 * substitute arg1 for arg2 in current path.
2220 * if the first substitution fails because the cd fails
2221 * we could try to find another substitution. For now
2222 * we don't
2226 * Substitute arg1 for arg2 in current path. If the first
2227 * substitution fails because the cd fails we could try to
2228 * find another substitution. For now, we don't.
22232229 */
22242230 if ((cp = strstr(current_wd, wp[0])) == NULL) {
22252231 bi_errorf(Tbadsubst);
0 .\" $MirOS: src/bin/mksh/mksh.1,v 1.491 2020/05/16 22:12:36 tg Exp $
0 .\" $MirOS: src/bin/mksh/mksh.1,v 1.494 2020/10/01 22:39:57 tg Exp $
11 .\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $
22 .\"-
33 .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
8383 .\" with -mandoc, it might implement .Mx itself, but we want to
8484 .\" use our own definition. And .Dd must come *first*, always.
8585 .\"
86 .Dd $Mdocdate: May 16 2020 $
86 .Dd $Mdocdate: October 1 2020 $
8787 .\"
8888 .\" Check which macro package we use, and do other -mdoc setup.
8989 .\"
14131413 where
14141414 .Ar name
14151415 is a parameter name.
1416 Substitutions of an an array in scalar context, i.e. without an
1416 Substitutions of an array in scalar context, i.e. without an
14171417 .Ar expr
14181418 in the latter form mentioned above, expand the element with the key
14191419 .Dq 0 .
53325332 Impose a size limit of
53335333 .Ar n
53345334 blocks on the size of core dumps.
5335 Silently ignored if the system does not support this limit.
53355336 .It Fl d Ar n
53365337 Limit the size of the data area to
53375338 .Ar n
53385339 kibibytes.
5340 .br
5341 On some systems, read-only maximum
5342 .Xr brk 2
5343 size minus
5344 .Li etext .
53395345 .It Fl e Ar n
53405346 Set the maximum niceness to
53415347 .Ar n .
53685374 Impose a limit of
53695375 .Ar n
53705376 file descriptors that can be open at once.
5377 On some systems attempts to set are silently ignored.
53715378 .It Fl O Ar n
53725379 Set the number of AIO operations to
53735380 .Ar n .
60636070 .Op Ar n
60646071 .No \*(haXe
60656072 .Xc
6066 Edit line
6073 Internally run the command
6074 .Ic fc \-e \&"${VISUAL:\-${EDITOR:\-vi}}" Fl \- Ar n
6075 .br
6076 on a temporary script file to interactively edit line
60676077 .Ar n
6068 or the current line, if not specified, interactively.
6069 The actual command executed is
6070 .Ic fc \-e ${VISUAL:\-${EDITOR:\-vi}} Ar n .
6078 (if
6079 .Ar n
6080 is not specified, the current line); then, unless the editor invoked
6081 exits nonzero but even if the script was not changed, execute the
6082 resulting script as if typed on the command line; both the edited
6083 .Pq resulting
6084 and original lines are added onto history.
60716085 .It end\-of\-history: \*(ha[\*(Gt
60726086 Moves to the end of the history.
60736087 .It end\-of\-line: \*(haE, ANSI-End, PC-End
64256439 .It Xo
64266440 .Oo Ar n Oc Ns v
64276441 .Xc
6428 Edit line
6442 Internally run the command
6443 .Ic fc \-e \&"${VISUAL:\-${EDITOR:\-vi}}" Fl \- Ar n
6444 .br
6445 on a temporary script file to interactively edit line
64296446 .Ar n
6430 using the
6431 .Xr vi 1
6432 editor; if
6447 (if
64336448 .Ar n
6434 is not specified, the current line is edited.
6435 The actual command executed is
6436 .Ic fc \-e ${VISUAL:\-${EDITOR:\-vi}} Ar n .
6449 is not specified, the current line); then, unless the editor invoked
6450 exits nonzero but even if the script was not changed, execute the
6451 resulting script as if typed on the command line; both the edited
6452 .Pq resulting
6453 and original lines are added onto history.
64376454 .It * and \*(haX
64386455 Command or file name expansion is applied to the current big-word (with an
64396456 appended
70717088 .Xr memmove 3 .
70727089 .Pp
70737090 This document attempts to describe
7074 .Nm mksh\ R59b
7091 .Nm mksh\ R59c
70757092 and up,
70767093 .\" with vendor patches from insert-your-name-here,
70777094 compiled without any options impacting functionality, such as
0 RCSID: $MirOS: src/bin/mksh/mksh.faq,v 1.7 2020/04/25 12:09:55 tg Exp $
0 RCSID: $MirOS: src/bin/mksh/mksh.faq,v 1.10 2020/10/01 22:59:12 tg Exp $
11 ToC: spelling
22 Title: How do you spell <tt>mksh</tt>? How do you pronounce it?
33
206206 ToC: oldbsd
207207 Title: Why do other BSDs and QNX still use pdksh instead of mksh?
208208
209 <p>Some systems are resistent to change, mostly due to bikeshedding
209 <p>Some systems are resistant to change, mostly due to bikeshedding
210210 (some people would, for example, rather see all shells banned to
211211 ports/pkgsrc®) and hysterial raisins (historical reasons ☻). Most
212212 BSDs have mksh packages available, and it works on all of them and
295295 pdksh derivative); <tt>$SH_VERSION</tt> (“PD KSH” as sh), <tt>$YASH_VERSION</tt>
296296 (yash), <tt>$ZSH_VERSION</tt> (or if <tt>$VERSION</tt> begins with “zsh”); a <a
297297 href="@@RELPATH@@ksh-chan.htm#which-shell">list of more approaches</a> exists.
298 ----
299 ToC: ctrl-x-e
300 Title: Multiline command editing
301
302 <p>mksh is very independent of the terminal and external libraries and
303 databases, such as termcap, and therefore is conservative in which ANSI
304 control codes are sent to the terminal.</p>
305 <p>For this reason, mksh’s input line editing uses a “windowed one-line”
306 concept: the line the cursor is on is a “window” into the whole input,
307 horizontally scrolled. Some other shells (that are much larger and have
308 more dependencies on external tooling) use a “multi-line” editing mode,
309 and users occasionally wish for this. It is on the long-term TODO, but
310 (due to the aforementioned implications) this is not trivial.</p>
311 <p>One way to achieve multi-line editing is to <em>dis</em>able input
312 line editing: <tt>set +o emacs +o vi</tt><br />This will, however, lose
313 you all editing features: tab completion, cursor keys, history, etc.</p>
314 <p>Another way, if you don’t need it all the time, is to use a function
315 that spawns your editor on the input line: press <tt>^Xe</tt> in the
316 default emacs mode or <tt>Esc + v</tt> in vi mode. Once you exit the
317 editor, whatever was written there is run; this includes the original
318 command line if you quit without saving, so request the editor to exit
319 nōn-zero (e.g. using jupp’s “abendjoe” command) to prevent execution.
320 This is <em>really</em> useful to write ad-hōc scripts as well.</p>
298321 ----
299322 ToC: ctrl-l-cls
300323 Title: ^L (Ctrl-L) does not clear the screen
437460 <tt>[[ foo =~ (foo|bar).*baz ]]</tt><br />
438461 … becomes…<br />
439462 <tt>[[ foo = *@(foo|bar)*baz* ]]</tt></p>
463 ----
464 ToC: trim-vector
465 Title: ${@?}: bad substitution
466
467 <p>In mksh, you cannot assign to or trim a vector (yet). For most
468 cases it is possible to write the affected code in a way avoiding
469 this extension; for example, trimming <tt>${@#foo}</tt> could be
470 applied to <tt>$1</tt> only and <tt>${@?}</tt> can be replaced
471 with a test whether <tt>$# -eq 0</tt>.</p>
440472 ----
441473 ToC: extensions-to-avoid
442474 Title: Are there any extensions to avoid?
+62
-35
os2.c less more
00 /*-
11 * Copyright (c) 2015, 2017, 2020
22 * KO Myung-Hun <komh@chollian.net>
3 * Copyright (c) 2017
3 * Copyright (c) 2017, 2020
44 * mirabilos <m@mirbsd.org>
55 *
66 * Provided that these terms and disclaimer and all copyright notices
3131 #include <unistd.h>
3232 #include <process.h>
3333
34 __RCSID("$MirOS: src/bin/mksh/os2.c,v 1.10 2020/04/07 11:13:45 tg Exp $");
35
36 static char *remove_trailing_dots(char *);
37 static int access_stat_ex(int (*)(), const char *, void *);
38 static int test_exec_exist(const char *, char *);
34 __RCSID("$MirOS: src/bin/mksh/os2.c,v 1.11 2020/10/01 21:13:45 tg Exp $");
35
36 struct a_s_arg {
37 union {
38 int (*i)(const char *, int);
39 int (*p)(const char *, void *);
40 } fn;
41 union {
42 int i;
43 void *p;
44 } arg;
45 bool isint;
46 };
47
48 static void remove_trailing_dots(char *, size_t);
49 static int access_stat_ex(const char *, struct a_s_arg *);
50 static int test_exec_exist(const char *, void *);
3951 static void response(int *, const char ***);
4052 static char *make_response_file(char * const *);
4153 static void add_temp(const char *);
222234 }
223235
224236 /* remove trailing dots */
225 static char *
226 remove_trailing_dots(char *name)
227 {
228 char *p = strnul(name);
237 static void
238 remove_trailing_dots(char *name, size_t namelen)
239 {
240 char *p = name + namelen;
229241
230242 while (--p > name && *p == '.')
231243 /* nothing */;
232244
233245 if (*p != '.' && *p != '/' && *p != '\\' && *p != ':')
234246 p[1] = '\0';
235
236 return (name);
237 }
238
239 #define REMOVE_TRAILING_DOTS(name) \
240 remove_trailing_dots(memcpy(alloca(strlen(name) + 1), name, strlen(name) + 1))
247 }
241248
242249 /* alias of stat() */
243250 extern int _std_stat(const char *, struct stat *);
246253 int
247254 stat(const char *name, struct stat *buffer)
248255 {
249 return (_std_stat(REMOVE_TRAILING_DOTS(name), buffer));
256 size_t namelen = strlen(name) + 1;
257 char nodots[namelen];
258
259 memcpy(nodots, name, namelen);
260 remove_trailing_dots(nodots, namelen);
261 return (_std_stat(nodots, buffer));
250262 }
251263
252264 /* alias of access() */
256268 int
257269 access(const char *name, int mode)
258270 {
271 size_t namelen = strlen(name) + 1;
272 char nodots[namelen];
273
259274 /*
260275 * On OS/2 kLIBC, X_OK is set only for executable files.
261276 * This prevents scripts from being executed.
263278 if (mode & X_OK)
264279 mode = (mode & ~X_OK) | R_OK;
265280
266 return (_std_access(REMOVE_TRAILING_DOTS(name), mode));
281 memcpy(nodots, name, namelen);
282 remove_trailing_dots(nodots, namelen);
283 return (_std_access(nodots, mode));
267284 }
268285
269286 #define MAX_X_SUFFIX_LEN 4
273290
274291 /* call fn() by appending executable extensions */
275292 static int
276 access_stat_ex(int (*fn)(), const char *name, void *arg)
293 access_stat_ex(const char *name, struct a_s_arg *action)
277294 {
278295 char *x_name;
279296 const char **x_suffix;
287304 strlcpy(x_name, name, x_namelen);
288305 strlcat(x_name, *x_suffix, x_namelen);
289306
290 rc = fn(x_name, arg);
307 rc = action->isint ? action->fn.i(x_name, action->arg.i) :
308 action->fn.p(x_name, action->arg.p);
291309 }
292310
293311 afree(x_name, ATEMP);
299317 int
300318 access_ex(int (*fn)(const char *, int), const char *name, int mode)
301319 {
302 /*XXX this smells fishy --mirabilos */
303 return (access_stat_ex(fn, name, (void *)mode));
320 struct a_s_arg arg;
321
322 arg.fn.i = fn;
323 arg.arg.i = mode;
324 arg.isint = true;
325 return (access_stat_ex(name, &arg));
304326 }
305327
306328 /* stat()/lstat() version */
308330 stat_ex(int (*fn)(const char *, struct stat *),
309331 const char *name, struct stat *buffer)
310332 {
311 return (access_stat_ex(fn, name, buffer));
333 struct a_s_arg arg;
334
335 arg.fn.p = fn;
336 arg.arg.p = buffer;
337 arg.isint = false;
338 return (access_stat_ex(name, &arg));
312339 }
313340
314341 static int
315 test_exec_exist(const char *name, char *real_name)
342 test_exec_exist(const char *name, void *arg)
316343 {
317344 struct stat sb;
345 char *real_name;
318346
319347 if (stat(name, &sb) < 0 || !S_ISREG(sb.st_mode))
320348 return (-1);
321349
322 /* safe due to calculations in real_exec_name() */
323 memcpy(real_name, name, strlen(name) + 1);
324
350 /*XXX memory leak */
351 strdupx(real_name, name, ATEMP);
352 *((char **)arg) = real_name;
325353 return (0);
326354 }
327355
328356 const char *
329357 real_exec_name(const char *name)
330358 {
331 char x_name[strlen(name) + MAX_X_SUFFIX_LEN + 1];
332 const char *real_name = name;
333
334 if (access_stat_ex(test_exec_exist, real_name, x_name) != -1)
335 /*XXX memory leak */
336 strdupx(real_name, x_name, ATEMP);
337
338 return (real_name);
359 struct a_s_arg arg;
360 char *real_name;
361
362 arg.fn.p = &test_exec_exist;
363 arg.arg.p = (void *)(&real_name);
364 arg.isint = false;
365 return (access_stat_ex(name, &arg) ? name : real_name);
339366 }
340367
341368 /* make a response file to pass a very long command line */
00 /*-
1 * Copyright (c) 2013, 2015
1 * Copyright (c) 2013, 2015, 2019
22 * mirabilos <m@mirbsd.org>
33 *
44 * Provided that these terms and disclaimer and all copyright notices
1515 * of dealing in the work, even if advised of the possibility of such
1616 * damage or existence of a defect, except proven that it results out
1717 * of said person's immediate fault when using the work as intended.
18 *-
19 * Keep {r,u}limits.opt in sync with each other!
1820 */
1921
2022 @RLIMITS_DEFNS
21 __RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.4 2019/04/24 20:56:31 tg Exp $");
23 __RCSID("$MirOS: src/bin/mksh/rlimits.opt,v 1.5 2020/07/24 20:11:18 tg Exp $");
2224 @RLIMITS_ITEMS
2325 #define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid),
2426 @@
7777 #if HAVE_PATHS_H
7878 #include <paths.h>
7979 #endif
80 #ifndef MKSH_NOPWNAM
8081 #include <pwd.h>
82 #endif
8183 #include <setjmp.h>
8284 #include <signal.h>
8385 #include <stdarg.h>
190192 #endif
191193
192194 #ifdef EXTERN
193 __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.898 2020/05/16 22:38:23 tg Exp $");
194 #endif
195 #define MKSH_VERSION "R59 2020/05/16"
195 __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.904 2020/10/31 03:53:06 tg Exp $");
196 #endif
197 #define MKSH_VERSION "R59 2020/10/31"
196198
197199 /* arithmetic types: C implementation */
198200 #if !HAVE_CAN_INTTYPES
245247 #endif
246248
247249 /* other standard types */
248
249 #if !HAVE_RLIM_T
250 typedef unsigned long rlim_t;
251 #endif
252250
253251 #if !HAVE_SIG_T
254252 #undef sig_t
667665 #endif
668666 #endif
669667
670 #if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 592)
668 #if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 593)
671669 #error Must run Build.sh to compile this.
672670 extern void thiswillneverbedefinedIhope(void);
673671 int
25212519 char **histpos(void) MKSH_A_PURE;
25222520 int histnum(int);
25232521 #endif
2524 int findhist(int, int, const char *, bool) MKSH_A_PURE;
2522 int findhist(int, const char *, bool, bool) MKSH_A_PURE;
25252523 char **hist_get_newest(bool);
25262524 void inittraps(void);
25272525 void alarm_init(void);
2626
2727 #include "sh.h"
2828
29 __RCSID("$MirOS: src/bin/mksh/shf.c,v 1.101 2019/12/11 17:56:58 tg Exp $");
29 __RCSID("$MirOS: src/bin/mksh/shf.c,v 1.102 2020/06/22 17:11:03 tg Exp $");
3030
3131 /* flags to shf_emptybuf() */
3232 #define EB_READSW 0x01 /* about to switch to reading */
665665 if (nbytes < 0)
666666 internal_errorf(Tf_szs, Tshf_write, nbytes, Tbytes);
667667
668 /* Don't buffer if buffer is empty and we're writting a large amount. */
668 /* don't buffer if buffer is empty and we're writing a large amount */
669669 if ((ncopy = shf->wnleft) &&
670670 (shf->wp != shf->buf || nbytes < shf->wnleft)) {
671671 if (ncopy > nbytes)
781781 #define FL_ZERO 0x040 /* '0' seen */
782782 #define FL_DOT 0x080 /* '.' seen */
783783 #define FL_UPPER 0x100 /* format character was uppercase */
784 #define FL_NUMBER 0x200 /* a number was formated %[douxefg] */
784 #define FL_NUMBER 0x200 /* a number was formatted %[douxefg] */
785785 #define FL_SIZET 0x400 /* 'z' seen */
786786 #define FM_SIZES 0x430 /* h/l/z mask */
787787
2323
2424 #include "sh.h"
2525
26 __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.128 2020/03/31 00:30:05 tg Exp $");
26 __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.129 2020/10/31 01:21:58 tg Exp $");
2727
2828 struct nesting_state {
2929 int start_token; /* token than began nesting (eg, FOR) */
267267 {
268268 struct op *t;
269269 int c, iopn = 0, syniocf, lno;
270 struct ioword *iop, **iops;
270 struct ioword *iop;
271271 XPtrV args, vars;
272272 struct nesting_state old_nesting;
273273 bool check_decl_utility;
274
275 /* NUFILE is small enough to leave this addition unchecked */
276 iops = alloc2((NUFILE + 1), sizeof(struct ioword *), ATEMP);
274 static struct ioword *iops[NUFILE + 1];
275
277276 XPinit(args, 16);
278277 XPinit(vars, 16);
279278
281280 switch (c = token(cf|KEYWORD|sALIAS|CMDASN)) {
282281 default:
283282 REJECT;
284 afree(iops, ATEMP);
285283 XPfree(args);
286284 XPfree(vars);
287285 /* empty line */
509507 }
510508
511509 if (iopn == 0) {
512 afree(iops, ATEMP);
513510 t->ioact = NULL;
514511 } else {
515512 iops[iopn++] = NULL;
516 iops = aresize2(iops, iopn, sizeof(struct ioword *), ATEMP);
517 t->ioact = iops;
513 t->ioact = alloc2(iopn, sizeof(struct ioword *), ATEMP);
514 memcpy(t->ioact, iops, iopn * sizeof(struct ioword *));
518515 }
519516
520517 if (t->type == TCOM || t->type == TDBRACKET) {
2222
2323 #include "sh.h"
2424
25 __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.97 2018/10/20 18:46:00 tg Exp $");
25 __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.100 2020/10/31 04:28:54 tg Exp $");
2626
2727 #define INDENT 8
2828
3535
3636 /* "foo& ; bar" and "foo |& ; bar" are invalid */
3737 static bool prevent_semicolon;
38
39 /* here document diversion */
40 static unsigned short ptree_nest;
41 static bool ptree_hashere;
42 static struct shf ptree_heredoc;
43 #define ptree_outhere(shf) do { \
44 if (ptree_hashere) { \
45 shf_puts(shf_sclose(&ptree_heredoc), (shf)); \
46 shf_putc('\n', (shf)); \
47 ptree_hashere = false; \
48 /*prevent_semicolon = true;*/ \
49 } \
50 } while (/* CONSTCOND */ 0)
3851
3952 static const char Telif_pT[] = "elif %T";
4053
8194 w = (const char **)t->vars;
8295 while (*w)
8396 fptreef(shf, indent, Tf_S_, *w++);
84 } else
97 }
98 #ifndef MKSH_SMALL
99 else
85100 shf_puts("#no-vars# ", shf);
101 #endif
86102 if (t->args) {
87103 w = t->args;
88104 if (*w && **w == CHAR) {
96112 }
97113 while (*w)
98114 fptreef(shf, indent, Tf_S_, *w++);
99 } else
115 }
116 #ifndef MKSH_SMALL
117 else
100118 shf_puts("#no-args# ", shf);
119 #endif
101120 break;
102121 case TEXEC:
103122 t = t->left;
220239 prevent_semicolon = false;
221240 break;
222241 }
223 if ((ioact = t->ioact) != NULL) {
224 bool need_nl = false;
225
242 if ((ioact = t->ioact) != NULL)
226243 while (*ioact != NULL)
227244 pioact(shf, *ioact++);
228 /* Print here documents after everything else... */
229 ioact = t->ioact;
230 while (*ioact != NULL) {
231 struct ioword *iop = *ioact++;
232
233 /* heredoc is NULL when tracing (set -x) */
234 if ((iop->ioflag & (IOTYPE | IOHERESTR)) == IOHERE &&
235 iop->heredoc) {
236 shf_putc('\n', shf);
237 shf_puts(iop->heredoc, shf);
238 fptreef(shf, indent, Tf_s,
239 evalstr(iop->delim, 0));
240 need_nl = true;
241 }
242 }
243 /*
244 * Last delimiter must be followed by a newline (this
245 * often leads to an extra blank line, but it's not
246 * worth worrying about)
247 */
248 if (need_nl) {
249 shf_putc('\n', shf);
250 prevent_semicolon = true;
251 }
252 }
253245 }
254246
255247 static void
271263 shf_putc('<', shf);
272264 break;
273265 case IOHERE:
266 if (flag & IOHERESTR) {
267 shf_puts("<<<", shf);
268 goto ioheredelim;
269 }
274270 shf_puts("<<", shf);
275271 if (flag & IOSKIP)
276272 shf_putc('-', shf);
277 else if (flag & IOHERESTR)
278 shf_putc('<', shf);
273 if (iop->heredoc /* nil when tracing */) {
274 /* here document diversion */
275 if (!ptree_hashere) {
276 shf_sopen(NULL, 0, SHF_WR | SHF_DYNAMIC,
277 &ptree_heredoc);
278 ptree_hashere = true;
279 }
280 shf_putc('\n', &ptree_heredoc);
281 shf_puts(iop->heredoc, &ptree_heredoc);
282 /* iop->delim is set before iop->heredoc */
283 shf_puts(evalstr(iop->delim, 0), &ptree_heredoc);
284 }
285 ioheredelim:
286 /* delim is NULL during syntax error printing */
287 if (iop->delim && !(iop->ioflag & IONDELIM))
288 wdvarput(shf, iop->delim, 0, WDS_TPUTS);
279289 break;
280290 case IOCAT:
281291 shf_puts(">>", shf);
292302 shf_puts(flag & IORDUP ? "<&" : ">&", shf);
293303 break;
294304 }
295 /* name/delim are NULL when printing syntax errors */
296 if (type == IOHERE) {
297 if (iop->delim && !(iop->ioflag & IONDELIM))
298 wdvarput(shf, iop->delim, 0, WDS_TPUTS);
299 } else if (iop->ioname) {
305 /* name is NULL for IOHERE or when printing syntax errors */
306 if (iop->ioname) {
300307 if (flag & IONAMEXP)
301308 print_value_quoted(shf, iop->ioname);
302309 else
341348 c = ord(*wp++);
342349 if (opmode & WDS_TPUTS)
343350 switch (c) {
344 case ORD('\n'):
345 if (quotelevel == 0) {
346 c = ORD('\'');
347 shf_putc(c, shf);
348 shf_putc(ORD('\n'), shf);
349 }
350 break;
351351 default:
352352 if (quotelevel == 0)
353353 /* FALLTHROUGH */
465465 vfptreef(struct shf *shf, int indent, const char *fmt, va_list va)
466466 {
467467 int c;
468
469 if (!ptree_nest++)
470 ptree_hashere = false;
468471
469472 while ((c = ord(*fmt++))) {
470473 if (c == '%') {
503506 shf_putc(';', shf);
504507 shf_putc(' ', shf);
505508 } else {
506 int i;
507
509 int i = indent;
510
511 ptree_outhere(shf);
508512 shf_putc('\n', shf);
509 i = indent;
510513 while (i >= 8) {
511514 shf_putc('\t', shf);
512515 i -= 8;
529532 dont_trash_prevent_semicolon:
530533 ;
531534 }
535
536 if (!--ptree_nest)
537 ptree_outhere(shf);
532538 }
533539
534540 /*
0 /* $OpenBSD: c_ulimit.c,v 1.19 2013/11/28 10:33:37 sobrado Exp $ */
1
2 /*-
3 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
4 * 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
5 * 2019, 2020
6 * mirabilos <m@mirbsd.org>
7 *
8 * Provided that these terms and disclaimer and all copyright notices
9 * are retained or reproduced in an accompanying document, permission
10 * is granted to deal in this work without restriction, including un-
11 * limited rights to use, publicly perform, distribute, sell, modify,
12 * merge, give away, or sublicence.
13 *
14 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
15 * the utmost extent permitted by applicable law, neither express nor
16 * implied; without malicious intent or gross negligence. In no event
17 * may a licensor, author or contributor be held liable for indirect,
18 * direct, other damage, loss, or other issues arising in any way out
19 * of dealing in the work, even if advised of the possibility of such
20 * damage or existence of a defect, except proven that it results out
21 * of said person's immediate fault when using the work as intended.
22 */
23
24 #include "sh.h"
25
26 __RCSID("$MirOS: src/bin/mksh/ulimit.c,v 1.3 2020/07/24 21:08:26 tg Exp $");
27
28 #define SOFT 0x1
29 #define HARD 0x2
30
31 #if HAVE_RLIMIT
32
33 #if !HAVE_RLIM_T
34 typedef unsigned long rlim_t;
35 #endif
36
37 /* Magic to divine the 'm' and 'v' limits */
38
39 #ifdef RLIMIT_AS
40 #if !defined(RLIMIT_VMEM) || (RLIMIT_VMEM == RLIMIT_AS) || \
41 !defined(RLIMIT_RSS) || (RLIMIT_VMEM == RLIMIT_RSS)
42 #define ULIMIT_V_IS_AS
43 #elif defined(RLIMIT_VMEM)
44 #if !defined(RLIMIT_RSS) || (RLIMIT_RSS == RLIMIT_AS)
45 #define ULIMIT_V_IS_AS
46 #else
47 #define ULIMIT_V_IS_VMEM
48 #endif
49 #endif
50 #endif
51
52 #ifdef RLIMIT_RSS
53 #ifdef ULIMIT_V_IS_VMEM
54 #define ULIMIT_M_IS_RSS
55 #elif defined(RLIMIT_VMEM) && (RLIMIT_VMEM == RLIMIT_RSS)
56 #define ULIMIT_M_IS_VMEM
57 #else
58 #define ULIMIT_M_IS_RSS
59 #endif
60 #if defined(ULIMIT_M_IS_RSS) && defined(RLIMIT_AS) && \
61 !defined(__APPLE__) && (RLIMIT_RSS == RLIMIT_AS)
62 /* On Mac OSX keep -m as -v alias for pkgsrc and other software expecting it */
63 #undef ULIMIT_M_IS_RSS
64 #endif
65 #endif
66
67 #if !defined(RLIMIT_AS) && !defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_VMEM)
68 #define ULIMIT_V_IS_VMEM
69 #endif
70
71 #if !defined(ULIMIT_V_IS_VMEM) && defined(RLIMIT_VMEM) && \
72 (!defined(RLIMIT_RSS) || (defined(RLIMIT_AS) && (RLIMIT_RSS == RLIMIT_AS)))
73 #define ULIMIT_M_IS_VMEM
74 #endif
75
76 #if defined(ULIMIT_M_IS_VMEM) && defined(RLIMIT_AS) && \
77 (RLIMIT_VMEM == RLIMIT_AS)
78 #undef ULIMIT_M_IS_VMEM
79 #endif
80
81 #if defined(ULIMIT_M_IS_RSS) && defined(ULIMIT_M_IS_VMEM)
82 # error nonsensical m ulimit
83 #endif
84
85 #if defined(ULIMIT_V_IS_VMEM) && defined(ULIMIT_V_IS_AS)
86 # error nonsensical v ulimit
87 #endif
88
89 #define LIMITS_GEN "rlimits.gen"
90
91 #else /* !HAVE_RLIMIT */
92
93 #undef RLIMIT_CORE /* just in case */
94
95 #if defined(UL_GETFSIZE)
96 #define KSH_UL_GFIL UL_GETFSIZE
97 #elif defined(UL_GFILLIM)
98 #define KSH_UL_GFIL UL_GFILLIM
99 #elif defined(__A_UX__) || defined(KSH_ULIMIT2_TEST)
100 #define KSH_UL_GFIL 1
101 #endif
102
103 #if defined(UL_SETFSIZE)
104 #define KSH_UL_SFIL UL_SETFSIZE
105 #elif defined(UL_SFILLIM)
106 #define KSH_UL_SFIL UL_SFILLIM
107 #elif defined(__A_UX__) || defined(KSH_ULIMIT2_TEST)
108 #define KSH_UL_SFIL 2
109 #endif
110
111 #if defined(KSH_UL_SFIL)
112 #define KSH_UL_WFIL true
113 #else
114 #define KSH_UL_WFIL false
115 #define KSH_UL_SFIL 0
116 #endif
117
118 #if defined(UL_GETMAXBRK)
119 #define KSH_UL_GBRK UL_GETMAXBRK
120 #elif defined(UL_GMEMLIM)
121 #define KSH_UL_GBRK UL_GMEMLIM
122 #elif defined(__A_UX__) || defined(KSH_ULIMIT2_TEST)
123 #define KSH_UL_GBRK 3
124 #endif
125
126 #if defined(UL_GDESLIM)
127 #define KSH_UL_GDES UL_GDESLIM
128 #elif defined(__GLIBC__) || defined(KSH_ULIMIT2_TEST)
129 #define KSH_UL_GDES 4
130 #endif
131
132 extern char etext;
133 extern long ulimit(int, long);
134
135 #define LIMITS_GEN "ulimits.gen"
136
137 #endif /* !HAVE_RLIMIT */
138
139 struct limits {
140 /* limit resource / read command */
141 int resource;
142 #if HAVE_RLIMIT
143 /* multiply by to get rlim_{cur,max} values */
144 unsigned int factor;
145 #else
146 /* write command */
147 int wesource;
148 /* writable? */
149 bool writable;
150 #endif
151 /* getopts char */
152 char optchar;
153 /* limit name */
154 char name[1];
155 };
156
157 #define RLIMITS_DEFNS
158 #if HAVE_RLIMIT
159 #define FN(lname,lid,lfac,lopt) \
160 static const struct { \
161 int resource; \
162 unsigned int factor; \
163 char optchar; \
164 char name[sizeof(lname)]; \
165 } rlimits_ ## lid = { \
166 lid, lfac, lopt, lname \
167 };
168 #else
169 #define FN(lname,lg,ls,lw,lopt) \
170 static const struct { \
171 int rcmd; \
172 int wcmd; \
173 bool writable; \
174 char optchar; \
175 char name[sizeof(lname)]; \
176 } rlimits_ ## lg = { \
177 lg, ls, lw, lopt, lname \
178 };
179 #endif
180 #include LIMITS_GEN
181
182 static void print_ulimit(const struct limits *, int);
183 static int set_ulimit(const struct limits *, const char *, int);
184
185 static const struct limits * const rlimits[] = {
186 #define RLIMITS_ITEMS
187 #include LIMITS_GEN
188 };
189
190 static const char rlimits_opts[] =
191 #define RLIMITS_OPTCS
192 #include LIMITS_GEN
193 #ifndef RLIMIT_CORE
194 "c"
195 #endif
196 ;
197
198 int
199 c_ulimit(const char **wp)
200 {
201 size_t i = 0;
202 int how = SOFT | HARD, optc;
203 char what = 'f';
204 bool all = false;
205
206 while ((optc = ksh_getopt(wp, &builtin_opt, rlimits_opts)) != -1)
207 switch (optc) {
208 case ORD('H'):
209 how = HARD;
210 break;
211 case ORD('S'):
212 how = SOFT;
213 break;
214 case ORD('a'):
215 all = true;
216 break;
217 case ORD('?'):
218 bi_errorf("usage: ulimit [-%s] [value]", rlimits_opts);
219 return (1);
220 default:
221 what = optc;
222 }
223
224 while (i < NELEM(rlimits)) {
225 if (rlimits[i]->optchar == what)
226 goto found;
227 ++i;
228 }
229 #ifndef RLIMIT_CORE
230 if (what == ORD('c'))
231 /* silently accept */
232 return 0;
233 #endif
234 internal_warningf("ulimit: %c", what);
235 return (1);
236 found:
237 if (wp[builtin_opt.optind]) {
238 if (all || wp[builtin_opt.optind + 1]) {
239 bi_errorf(Ttoo_many_args);
240 return (1);
241 }
242 return (set_ulimit(rlimits[i], wp[builtin_opt.optind], how));
243 }
244 if (!all)
245 print_ulimit(rlimits[i], how);
246 else for (i = 0; i < NELEM(rlimits); ++i) {
247 shprintf("-%c: %-20s ", rlimits[i]->optchar, rlimits[i]->name);
248 print_ulimit(rlimits[i], how);
249 }
250 return (0);
251 }
252
253 #if HAVE_RLIMIT
254 #define RL_T rlim_t
255 #define RL_U (rlim_t)RLIM_INFINITY
256 #else
257 #define RL_T long
258 #define RL_U LONG_MAX
259 #endif
260
261 static int
262 set_ulimit(const struct limits *l, const char *v, int how MKSH_A_UNUSED)
263 {
264 RL_T val = (RL_T)0;
265 #if HAVE_RLIMIT
266 struct rlimit limit;
267 #endif
268
269 if (strcmp(v, "unlimited") == 0)
270 val = RL_U;
271 else {
272 mksh_uari_t rval;
273
274 if (!evaluate(v, (mksh_ari_t *)&rval, KSH_RETURN_ERROR, false))
275 return (1);
276 /*
277 * Avoid problems caused by typos that evaluate misses due
278 * to evaluating unset parameters to 0...
279 * If this causes problems, will have to add parameter to
280 * evaluate() to control if unset params are 0 or an error.
281 */
282 if (!rval && !ctype(v[0], C_DIGIT)) {
283 bi_errorf("invalid %s limit: %s", l->name, v);
284 return (1);
285 }
286 #if HAVE_RLIMIT
287 val = (rlim_t)((rlim_t)rval * l->factor);
288 #else
289 val = (RL_T)rval;
290 #endif
291 }
292
293 #if HAVE_RLIMIT
294 if (getrlimit(l->resource, &limit) < 0) {
295 #ifndef MKSH_SMALL
296 bi_errorf("limit %s could not be read, contact the mksh developers: %s",
297 l->name, cstrerror(errno));
298 #endif
299 /* some can't be read */
300 limit.rlim_cur = RLIM_INFINITY;
301 limit.rlim_max = RLIM_INFINITY;
302 }
303 if (how & SOFT)
304 limit.rlim_cur = val;
305 if (how & HARD)
306 limit.rlim_max = val;
307 if (!setrlimit(l->resource, &limit))
308 return (0);
309 #else
310 if (l->writable == false) {
311 /* check.t:ulimit-2 fails if we return 1 and/or do:
312 bi_errorf(Tf_ro, l->name);
313 */
314 return (0);
315 }
316 if (ulimit(l->wesource, val) != -1L)
317 return (0);
318 #endif
319 if (errno == EPERM)
320 bi_errorf("%s exceeds allowable %s limit", v, l->name);
321 else
322 bi_errorf("bad %s limit: %s", l->name, cstrerror(errno));
323 return (1);
324 }
325
326 static void
327 print_ulimit(const struct limits *l, int how MKSH_A_UNUSED)
328 {
329 RL_T val = (RL_T)0;
330 #if HAVE_RLIMIT
331 struct rlimit limit;
332
333 if (getrlimit(l->resource, &limit))
334 #else
335 if ((val = ulimit(l->resource, 0)) < 0)
336 #endif
337 {
338 shf_puts("unknown\n", shl_stdout);
339 return;
340 }
341 #if HAVE_RLIMIT
342 if (how & SOFT)
343 val = limit.rlim_cur;
344 else if (how & HARD)
345 val = limit.rlim_max;
346 #endif
347 if (val == RL_U)
348 shf_puts("unlimited\n", shl_stdout);
349 else {
350 #if HAVE_RLIMIT
351 val /= l->factor;
352 #elif defined(KSH_UL_GBRK)
353 if (l->resource == KSH_UL_GBRK)
354 val = (RL_T)(((size_t)val - (size_t)&etext) /
355 (size_t)1024);
356 #endif
357 shprintf("%lu\n", (unsigned long)val);
358 }
359 }
0 /*-
1 * Copyright (c) 2013, 2015, 2020
2 * mirabilos <m@mirbsd.org>
3 *
4 * Provided that these terms and disclaimer and all copyright notices
5 * are retained or reproduced in an accompanying document, permission
6 * is granted to deal in this work without restriction, including un-
7 * limited rights to use, publicly perform, distribute, sell, modify,
8 * merge, give away, or sublicence.
9 *
10 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
11 * the utmost extent permitted by applicable law, neither express nor
12 * implied; without malicious intent or gross negligence. In no event
13 * may a licensor, author or contributor be held liable for indirect,
14 * direct, other damage, loss, or other issues arising in any way out
15 * of dealing in the work, even if advised of the possibility of such
16 * damage or existence of a defect, except proven that it results out
17 * of said person's immediate fault when using the work as intended.
18 *-
19 * Keep {r,u}limits.opt in sync with each other!
20 */
21
22 @RLIMITS_DEFNS
23 __RCSID("$MirOS: src/bin/mksh/ulimits.opt,v 1.2 2020/07/24 20:50:11 tg Exp $");
24 @RLIMITS_ITEMS
25 #define FN(lname,lg,ls,lw,lopt) (const struct limits *)(&rlimits_ ## lg),
26 @@
27
28 /* generic options for the ulimit builtin */
29
30 <a|
31 <H|
32 <S|
33
34 /* do not use options -H, -S or -a or change the order */
35
36 >f|KSH_UL_GFIL
37 FN("file(blocks)", KSH_UL_GFIL, KSH_UL_SFIL, KSH_UL_WFIL
38
39 >d|KSH_UL_GBRK
40 FN("data(KiB)", KSH_UL_GBRK, 0, false
41
42 >n|KSH_UL_GDES
43 FN("nofiles(descriptors)", KSH_UL_GDES, 0, false
44
45 |RLIMITS_OPTCS
2828 #include <sys/sysctl.h>
2929 #endif
3030
31 __RCSID("$MirOS: src/bin/mksh/var.c,v 1.236 2020/04/13 16:29:34 tg Exp $");
31 __RCSID("$MirOS: src/bin/mksh/var.c,v 1.237 2020/06/22 17:11:03 tg Exp $");
3232
3333 /*-
3434 * Variables
18991899 break;
19001900 }
19011901
1902 /* see comment below regarding possible opions */
1902 /* see comment below regarding possible options */
19031903 opts = istset ? "L#R#UZ#afgi#lnprtux" : "p";
19041904
19051905 builtin_opt.flags |= GF_PLUSOPT;