update to a prerelease for Debian checks
mirabilos authored 3 years ago
mirabilos committed 3 years ago
0 | 0 | #!/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 $' | |
2 | 2 | #- |
3 | 3 | # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
4 | 4 | # 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, |
720 | 720 | add_cppflags -DMKSH_NO_SIGSETJMP |
721 | 721 | add_cppflags -DMKSH_TYPEDEF_SIG_ATOMIC_T=int |
722 | 722 | ;; |
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 | ;; | |
723 | 730 | AIX) |
724 | 731 | add_cppflags -D_ALL_SOURCE |
725 | 732 | : "${HAVE_SETLOCALE_CTYPE=0}" |
861 | 868 | ;; |
862 | 869 | Minix3) |
863 | 870 | add_cppflags -DMKSH_UNEMPLOYED |
864 | add_cppflags -DMKSH_NO_LIMITS | |
865 | 871 | add_cppflags -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2 -D_MINIX |
866 | 872 | 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 | |
868 | 874 | ;; |
869 | 875 | MirBSD) |
870 | 876 | ;; |
897 | 903 | Ninix3) |
898 | 904 | # similar to Minix3 |
899 | 905 | add_cppflags -DMKSH_UNEMPLOYED |
900 | add_cppflags -DMKSH_NO_LIMITS | |
906 | : "${MKSH_UNLIMITED=1}" #XXX recheck ulimit | |
901 | 907 | # but no idea what else could be needed |
902 | 908 | oswarn="; it has unknown issues" |
903 | 909 | ;; |
910 | 916 | HAVE_ISOFF_MKSH_ASSUME_UTF8=1 |
911 | 917 | HAVE_TERMIOS_H=0 |
912 | 918 | HAVE_MKNOD=0 # setmode() incompatible |
913 | oswarn="; it is being ported" | |
914 | 919 | check_categories="$check_categories nosymlink" |
915 | 920 | : "${CC=gcc}" |
916 | 921 | : "${SIZE=: size}" |
917 | 922 | SRCS="$SRCS os2.c" |
918 | 923 | add_cppflags -DMKSH_UNEMPLOYED |
919 | 924 | add_cppflags -DMKSH_NOPROSPECTOFWORK |
920 | add_cppflags -DMKSH_NO_LIMITS | |
921 | 925 | add_cppflags -DMKSH_DOSPATH |
926 | : "${MKSH_UNLIMITED=1}" | |
922 | 927 | if test $textmode = 0; then |
923 | 928 | x='dis' |
924 | 929 | y='standard OS/2 tools' |
1362 | 1367 | etd=" on $et" |
1363 | 1368 | case $et in |
1364 | 1369 | klibc) |
1365 | add_cppflags -DMKSH_NO_LIMITS | |
1370 | : "${MKSH_UNLIMITED=1}" | |
1366 | 1371 | ;; |
1367 | 1372 | unknown) |
1368 | 1373 | # nothing special detected, don’t worry |
1897 | 1902 | int main(int ac, char *av[]) { return ((u_int8_t)(size_t)av[ac]); } |
1898 | 1903 | EOF |
1899 | 1904 | |
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 | ||
1917 | 1905 | # only testn: added later below |
1918 | 1906 | ac_testn sig_t <<-'EOF' |
1919 | 1907 | #include <sys/types.h> |
2064 | 2052 | lks.l_type = F_WRLCK | F_UNLCK; |
2065 | 2053 | return (fcntl(0, F_SETLKW, &lks)); |
2066 | 2054 | } |
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)); } | |
2067 | 2084 | EOF |
2068 | 2085 | |
2069 | 2086 | ac_test getrusage <<-'EOF' |
2456 | 2473 | $e done. |
2457 | 2474 | fi |
2458 | 2475 | |
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 | ||
2459 | 2488 | addsrcs '!' HAVE_STRLCPY strlcpy.c |
2460 | 2489 | addsrcs USE_PRINTF_BUILTIN printf.c |
2461 | test 1 = "$USE_PRINTF_BUILTIN" && add_cppflags -DMKSH_PRINTF_BUILTIN | |
2490 | addsrcs '!' MKSH_UNLIMITED ulimit.c | |
2491 | ||
2462 | 2492 | test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose" |
2463 | add_cppflags -DMKSH_BUILD_R=592 | |
2493 | add_cppflags -DMKSH_BUILD_R=593 | |
2464 | 2494 | |
2465 | 2495 | $e $bi$me: Finished configuration testing, now producing output.$ao |
2466 | 2496 | |
2543 | 2573 | args[\${#args[*]}]=\$TMPDIR |
2544 | 2574 | fi |
2545 | 2575 | 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/^./& /' | |
2547 | 2577 | print "This shell is actually:\\n\\t\$KSH_VERSION" |
2548 | 2578 | print 'test.sh built for mksh $dstversion' |
2549 | 2579 | cstr='\$os = defined \$^O ? \$^O : "unknown";' |
2603 | 2633 | op=`echo x"$file" | sed 's/^x\(.*\)\.c$/\1./'` |
2604 | 2634 | test -f $file || file=$srcdir/$file |
2605 | 2635 | files="$files$sp$file" |
2606 | sp=' ' | |
2607 | 2636 | echo "$CC $CFLAGS $CPPFLAGS $emitbc $file || exit 1" >>Rebuild.sh |
2608 | 2637 | if test $cm = dragonegg; then |
2609 | 2638 | echo "mv ${op}s ${op}ll" >>Rebuild.sh |
2612 | 2641 | else |
2613 | 2642 | objs="$objs$sp${op}o" |
2614 | 2643 | fi |
2644 | sp=' ' | |
2615 | 2645 | done |
2616 | 2646 | case $cm in |
2617 | 2647 | dragonegg|llvm) |
2627 | 2657 | echo "$CC $CFLAGS $LDFLAGS -o \$tcfn $lobjs $LIBS $ccpr" >>Rebuild.sh |
2628 | 2658 | echo "test -f \$tcfn || exit 1; $SIZE \$tcfn" >>Rebuild.sh |
2629 | 2659 | 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' | |
2631 | 2661 | test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc" |
2632 | 2662 | gens= genq= |
2633 | 2663 | for file in $optfiles; do |
2733 | 2763 | fi |
2734 | 2764 | $e |
2735 | 2765 | $e Installing the manual: |
2736 | if test -e FAQ.htm; then | |
2766 | if test -f FAQ.htm; then | |
2737 | 2767 | $e "# $i -c -o root -g bin -m 444 FAQ.htm /usr/share/doc/mksh/" |
2738 | 2768 | fi |
2739 | 2769 | if test -f mksh.cat1; then |
2740 | if test -e FAQ.htm; then | |
2770 | if test -f FAQ.htm; then | |
2741 | 2771 | $e plus either |
2742 | 2772 | fi |
2743 | 2773 | $e "# $i -c -o root -g bin -m 444 lksh.cat1" \ |
2750 | 2780 | $e |
2751 | 2781 | $e Run the regression test suite: ./test.sh |
2752 | 2782 | $e Please also read the sample file dot.mkshrc and the fine manual. |
2753 | test -e FAQ.htm || \ | |
2783 | test -f FAQ.htm || \ | |
2754 | 2784 | $e Run FAQ2HTML.sh and place FAQ.htm into a suitable location as well. |
2755 | 2785 | exit 0 |
2756 | 2786 | |
2774 | 2804 | TARGET_OSREV [QNX] default: $(uname -r) |
2775 | 2805 | |
2776 | 2806 | ==== feature selectors ==== |
2807 | MKSH_UNLIMITED 1 to omit ulimit builtin completely | |
2777 | 2808 | USE_PRINTF_BUILTIN 1 to include (unsupported) printf(1) as builtin |
2778 | 2809 | ===== general format ===== |
2779 | 2810 | HAVE_STRLEN ac_test |
2781 | 2812 | HAVE_CAN_FSTACKPROTECTORALL ac_flags |
2782 | 2813 | |
2783 | 2814 | ==== cpp definitions ==== |
2784 | DEBUG dont use in production, wants gcc, implies: | |
2815 | DEBUG don’t use in production, wants gcc, implies: | |
2785 | 2816 | DEBUG_LEAKS enable freeing resources before exiting |
2786 | 2817 | KSH_VERSIONNAME_VENDOR_EXT when patching; space+plus+word (e.g. " +SuSE") |
2787 | 2818 | MKSHRC_PATH "~/.mkshrc" (do not change) |
2803 | 2834 | MKSH_NOPWNAM skip PAM calls, for -static on glibc or Solaris |
2804 | 2835 | MKSH_NO_CMDLINE_EDITING disable command line editing code entirely |
2805 | 2836 | MKSH_NO_DEPRECATED_WARNING omit warning when deprecated stuff is run |
2806 | MKSH_NO_LIMITS omit ulimit code | |
2807 | 2837 | MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available |
2808 | 2838 | MKSH_NO_SIGSUSPEND use sigprocmask+pause instead of sigsuspend |
2809 | 2839 | 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 $' | |
2 | 2 | #- |
3 | 3 | # Copyright © 2020 |
4 | 4 | # mirabilos <m@mirbsd.org> |
36 | 36 | src_id=$(sed $p -n '/^RCSID: /s///p' "$srcdir"/mksh.faq) |
37 | 37 | # sanity check |
38 | 38 | case $src_id in |
39 | (*"$nl"*) | |
39 | *"$nl"*) | |
40 | 40 | echo >&2 "E: more than one RCSID in mksh.faq?" |
41 | 41 | exit 1 ;; |
42 | 42 | 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 $ | |
1 | 1 | # $OpenBSD: th,v 1.1 2013/12/02 20:39:44 millert Exp $ |
2 | 2 | #- |
3 | 3 | # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, |
54 | 54 | # default is no arguments. |
55 | 55 | # script m Value is written to a file which |
56 | 56 | # is passed as an argument to the program |
57 | # (after the arguments arguments) | |
57 | # (after the arguments from arguments) | |
58 | 58 | # stdin m Value is written to a file which is |
59 | 59 | # used as standard-input for the program; |
60 | 60 | # default is to use /dev/null. |
194 | 194 | the path (kludge option) |
195 | 195 | -p p Use p as the program to test |
196 | 196 | -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). | |
198 | 198 | -T dir Use dir instead of /tmp to hold temporary files |
199 | 199 | -t t Use t as default time limit for tests (default is unlimited) |
200 | 200 | -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 $ | |
1 | 1 | # -*- mode: sh -*- |
2 | 2 | #- |
3 | 3 | # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
30 | 30 | # (2013/12/02 20:39:44) http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date |
31 | 31 | |
32 | 32 | expected-stdout: |
33 | KSH R59 2020/05/16 | |
33 | KSH R59 2020/10/31 | |
34 | 34 | description: |
35 | 35 | Check base version of full shell |
36 | 36 | stdin: |
6108 | 6108 | --- |
6109 | 6109 | name: regression-28 |
6110 | 6110 | description: |
6111 | variable assignements not detected well | |
6111 | variable assignments not detected well | |
6112 | 6112 | stdin: |
6113 | 6113 | a.x=1 echo hi |
6114 | 6114 | expected-exit: e != 0 |
6183 | 6183 | --- |
6184 | 6184 | name: regression-35 |
6185 | 6185 | 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 | |
6187 | 6187 | the function is parsed (before it is executed) |
6188 | 6188 | stdin: |
6189 | 6189 | f1() { |
7456 | 7456 | name: xxx-param-subst-qmark-1 |
7457 | 7457 | description: |
7458 | 7458 | 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. | |
7460 | 7460 | ksh88/93, Solaris /bin/sh and /usr/xpg4/bin/sh all print the error. |
7461 | 7461 | stdin: |
7462 | 7462 | unset foo |
8852 | 8852 | XXX if the OS can already execute them, we lose |
8853 | 8853 | note: cygwin execve(2) doesn't return to us with ENOEXEC, we lose |
8854 | 8854 | 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 | |
8855 | 8856 | XXX fails when LD_PRELOAD is set with -e and Perl chokes it (ASan) |
8856 | 8857 | 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 | |
8858 | 8859 | env-setup: !FOO=BAR! |
8859 | 8860 | stdin: |
8860 | 8861 | print '#!'"$__progname"'\nprint "1 a=$ENV{FOO}";' >t1 |
11495 | 11496 | description: |
11496 | 11497 | Verify that file descriptors > 2 are private for Korn shells |
11497 | 11498 | 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 | |
11500 | 11499 | stdin: |
11501 | 11500 | cat >cld <<-EOF |
11502 | 11501 | #!$__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 \$!"; | |
11505 | 11504 | EOF |
11506 | 11505 | chmod +x cld |
11507 | 11506 | exec 9>&1 |
11514 | 11513 | description: |
11515 | 11514 | Verify that file descriptors > 2 are not private for POSIX shells |
11516 | 11515 | See Debian Bug #154540, Closes: #499139 |
11517 | XXX fails on some old Perl installations | |
11518 | need-pass: no | |
11519 | 11516 | stdin: |
11520 | 11517 | cat >cld <<-EOF |
11521 | 11518 | #!$__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 \$!"; | |
11524 | 11521 | EOF |
11525 | 11522 | chmod +x cld |
11526 | 11523 | test -n "$POSH_VERSION" || set -o posix |
12085 | 12082 | EOFN |
12086 | 12083 | )|tr u x); } |
12087 | 12084 | function reread_IOWRITE_IOCLOB_IOHERE_noIOSKIP { |
12088 | x=$( ( \cat >|bar <<"EOFN" | |
12085 | x=$( ( \cat >|bar <<"EOFN" ) | \tr u x | |
12089 | 12086 | foo |
12090 | 12087 | EOFN |
12091 | ) | \tr u x ) | |
12088 | ) | |
12092 | 12089 | } |
12093 | 12090 | inline_IOWRITE_noIOCLOB_IOHERE_IOSKIP() { |
12094 | 12091 | cat 1>bar <<-EOFI |
12118 | 12115 | EOFI |
12119 | 12116 | )|tr u x); } |
12120 | 12117 | function reread_IOWRITE_noIOCLOB_IOHERE_IOSKIP { |
12121 | x=$( ( \cat >bar <<-EOFI | |
12118 | x=$( ( \cat >bar <<-EOFI ) | \tr u x | |
12122 | 12119 | foo |
12123 | 12120 | EOFI |
12124 | ) | \tr u x ) | |
12121 | ) | |
12125 | 12122 | } |
12126 | 12123 | inline_IORDWR_IODUP() { |
12127 | 12124 | sh 1<>/dev/console 0<&1 2>&1 |
13646 | 13643 | words, and command -p[vV] should find aliases, reserved words, and |
13647 | 13644 | builtins over external commands. |
13648 | 13645 | stdin: |
13646 | # extra checks prep | |
13647 | mkdir mrr | |
13648 | :>mrr/miau | |
13649 | chmod +x mrr/miau | |
13650 | # priorities | |
13649 | 13651 | PATH=/bin:/usr/bin |
13650 | 13652 | alias foo="bar baz" |
13651 | 13653 | alias '[ab]=:' |
13659 | 13661 | # extra checks |
13660 | 13662 | alias '[ab]' |
13661 | 13663 | 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 | } | |
13662 | 13672 | expected-stdout: |
13663 | 13673 | if |
13664 | 13674 | if |
13686 | 13696 | '[ab]' is an alias for : |
13687 | 13697 | '[ab]'=: |
13688 | 13698 | : |
13699 | ok | |
13689 | 13700 | --- |
13690 | 13701 | name: whence-preserve-tradition |
13691 | 13702 | description: |
28 | 28 | |
29 | 29 | #ifndef MKSH_NO_CMDLINE_EDITING |
30 | 30 | |
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 $"); | |
32 | 32 | |
33 | 33 | /* |
34 | 34 | * in later versions we might use libtermcap for this, but since external |
39 | 39 | #ifndef MKSH_CLS_STRING |
40 | 40 | #define MKSH_CLS_STRING KSH_ESC_STRING "[;H" KSH_ESC_STRING "[J" |
41 | 41 | #endif |
42 | ||
43 | static const char ctrl_x_e[] = "fc -e \"${VISUAL:-${EDITOR:-vi}}\" --"; | |
42 | 44 | |
43 | 45 | /* tty driver characters we are interested in */ |
44 | 46 | #define EDCHAR_DISABLED 0xFFFFU |
152 | 154 | char c; |
153 | 155 | ssize_t n; |
154 | 156 | |
155 | while ((n = blocking_read(STDIN_FILENO, &c, 1)) < 0 && errno == EINTR) | |
157 | while ((n = blocking_read(0, &c, 1)) < 0 && errno == EINTR) | |
156 | 158 | if (trap) { |
157 | 159 | x_mode(false); |
158 | 160 | runtraps(0); |
969 | 971 | static int wbuf_len; /* length of window buffers (x_cols - 3) */ |
970 | 972 | static int win; /* window buffer in use */ |
971 | 973 | static char morec; /* more character at right of window */ |
972 | static int lastref; /* argument to last refresh() */ | |
973 | 974 | static int holdlen; /* length of holdbuf */ |
974 | 975 | #endif |
975 | 976 | static int pwidth; /* width of prompt */ |
988 | 989 | static void x_zotc3(char **); |
989 | 990 | static void x_vi_zotc(int); |
990 | 991 | static void x_load_hist(char **); |
991 | static int x_search(char *, int, int); | |
992 | static int x_search(const char *, int, int); | |
992 | 993 | #ifndef MKSH_SMALL |
993 | 994 | static int x_search_dir(int); |
994 | 995 | #endif |
995 | static int x_match(char *, char *); | |
996 | static int x_match(const char *, const char *); | |
996 | 997 | static void x_redraw(int); |
997 | 998 | static void x_push(size_t); |
998 | 999 | static void x_bind_showone(int, int); |
1945 | 1946 | offset = x_match(xbuf, pat); |
1946 | 1947 | if (offset >= 0) { |
1947 | 1948 | x_goto(xbuf + offset + (p - pat) - |
1948 | (*pat == '^')); | |
1949 | (*pat == '^' ? 1 : 0)); | |
1949 | 1950 | continue; |
1950 | 1951 | } |
1951 | 1952 | } |
1967 | 1968 | |
1968 | 1969 | /* search backward from current line */ |
1969 | 1970 | static int |
1970 | x_search(char *pat, int sameline, int offset) | |
1971 | x_search(const char *pat, int sameline, int offset) | |
1971 | 1972 | { |
1972 | 1973 | char **hp; |
1973 | 1974 | int i; |
1974 | ||
1975 | size_t patlen = strlen(pat); | |
1976 | ||
1977 | if (*pat == '^') | |
1978 | --patlen; | |
1975 | 1979 | for (hp = x_histp - (sameline ? 0 : 1); hp >= history; --hp) { |
1976 | 1980 | i = x_match(*hp, pat); |
1977 | 1981 | if (i >= 0) { |
1978 | 1982 | if (offset < 0) |
1979 | 1983 | x_e_putc2('\n'); |
1980 | 1984 | x_load_hist(hp); |
1981 | x_goto(xbuf + i + strlen(pat) - (*pat == '^')); | |
1985 | x_goto(xbuf + i + patlen); | |
1982 | 1986 | return (i); |
1983 | 1987 | } |
1984 | 1988 | } |
2023 | 2027 | |
2024 | 2028 | /* return position of first match of pattern in string, else -1 */ |
2025 | 2029 | static int |
2026 | x_match(char *str, char *pat) | |
2030 | x_match(const char *str, const char *pat) | |
2027 | 2031 | { |
2028 | 2032 | if (*pat == '^') { |
2029 | 2033 | return ((strncmp(str, pat + 1, strlen(pat + 1)) == 0) ? 0 : -1); |
3124 | 3128 | x_edit_line(int c MKSH_A_UNUSED) |
3125 | 3129 | { |
3126 | 3130 | if (x_arg_defaulted) { |
3127 | if (xep == xbuf) { | |
3128 | x_e_putc2(KSH_BEL); | |
3129 | return (KSTD); | |
3130 | } | |
3131 | 3131 | if (modified) { |
3132 | 3132 | *xep = '\0'; |
3133 | 3133 | histsave(&source->line, xbuf, HIST_STORE, true); |
3136 | 3136 | x_arg = source->line - (histptr - x_histp); |
3137 | 3137 | } |
3138 | 3138 | 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); | |
3141 | 3140 | else |
3142 | strlcpy(xbuf, "fc -e ${VISUAL:-${EDITOR:-vi}} --", xend - xbuf); | |
3141 | strlcpy(xbuf, ctrl_x_e, xend - xbuf); | |
3143 | 3142 | xep = strnul(xbuf); |
3144 | 3143 | return (x_newline('\n')); |
3145 | 3144 | } |
3432 | 3431 | static int Backword(int); |
3433 | 3432 | static int Endword(int); |
3434 | 3433 | static int grabhist(int, int); |
3435 | static int grabsearch(int, int, int, const char *); | |
3434 | static int grabsearch(const char *, int, int, bool); | |
3436 | 3435 | static void redraw_line(bool); |
3437 | static void refresh(int); | |
3436 | static void refresh(bool); | |
3438 | 3437 | static int outofwin(void); |
3439 | 3438 | static void rewindow(void); |
3440 | 3439 | static int newcol(unsigned char, int); |
3441 | static void display(char *, char *, int); | |
3440 | static void display(char *, char *, bool); | |
3442 | 3441 | static void ed_mov_opt(int, char *); |
3443 | 3442 | static int expand_word(int); |
3444 | 3443 | static int complete_word(int, int); |
3609 | 3608 | winwidth = x_cols - pwidth - 3; |
3610 | 3609 | win = 0; |
3611 | 3610 | morec = ' '; |
3612 | lastref = 1; | |
3613 | 3611 | holdlen = 0; |
3614 | 3612 | |
3615 | 3613 | editmode = 2; |
3711 | 3709 | case 0: |
3712 | 3710 | if (state == VLIT) { |
3713 | 3711 | vs->cursor--; |
3714 | refresh(0); | |
3712 | refresh(false); | |
3715 | 3713 | } else |
3716 | 3714 | refresh(insert != 0); |
3717 | 3715 | break; |
3737 | 3735 | if (putbuf(ord(ch) == ORD('/') ? |
3738 | 3736 | "/" : "?", 1, false) != 0) |
3739 | 3737 | return (-1); |
3740 | refresh(0); | |
3738 | refresh(false); | |
3741 | 3739 | } |
3742 | 3740 | if (state == VVERSION) { |
3743 | 3741 | save_cbuf(); |
3745 | 3743 | vs->linelen = 0; |
3746 | 3744 | putbuf(KSH_VERSION, |
3747 | 3745 | strlen(KSH_VERSION), false); |
3748 | refresh(0); | |
3746 | refresh(false); | |
3749 | 3747 | } |
3750 | 3748 | } |
3751 | 3749 | } |
3757 | 3755 | vi_error(); |
3758 | 3756 | } else |
3759 | 3757 | vs->cbuf[vs->cursor++] = ch; |
3760 | refresh(1); | |
3758 | refresh(true); | |
3761 | 3759 | state = VNORMAL; |
3762 | 3760 | break; |
3763 | 3761 | |
3764 | 3762 | case VVERSION: |
3765 | 3763 | restore_cbuf(); |
3766 | 3764 | state = VNORMAL; |
3767 | refresh(0); | |
3765 | refresh(false); | |
3768 | 3766 | break; |
3769 | 3767 | |
3770 | 3768 | case VARG1: |
3828 | 3826 | if (!srchpat[0]) { |
3829 | 3827 | vi_error(); |
3830 | 3828 | state = VNORMAL; |
3831 | refresh(0); | |
3829 | refresh(false); | |
3832 | 3830 | return (0); |
3833 | 3831 | } |
3834 | 3832 | } else { |
3841 | 3839 | srchlen--; |
3842 | 3840 | vs->linelen -= char_len(locpat[srchlen]); |
3843 | 3841 | vs->cursor = vs->linelen; |
3844 | refresh(0); | |
3842 | refresh(false); | |
3845 | 3843 | return (0); |
3846 | 3844 | } |
3847 | 3845 | restore_cbuf(); |
3848 | 3846 | state = VNORMAL; |
3849 | refresh(0); | |
3847 | refresh(false); | |
3850 | 3848 | } else if (isched(ch, edchars.kill)) { |
3851 | 3849 | srchlen = 0; |
3852 | 3850 | vs->linelen = 1; |
3853 | 3851 | vs->cursor = 1; |
3854 | refresh(0); | |
3852 | refresh(false); | |
3855 | 3853 | return (0); |
3856 | 3854 | } else if (isched(ch, edchars.werase)) { |
3857 | 3855 | unsigned int i, n; |
3870 | 3868 | vs->linelen -= char_len(locpat[i]); |
3871 | 3869 | srchlen = (int)n; |
3872 | 3870 | vs->cursor = vs->linelen; |
3873 | refresh(0); | |
3871 | refresh(false); | |
3874 | 3872 | return (0); |
3875 | 3873 | } else { |
3876 | 3874 | if (srchlen == SRCHLEN - 1) |
3889 | 3887 | vs->cbuf[vs->linelen++] = ch; |
3890 | 3888 | } |
3891 | 3889 | vs->cursor = vs->linelen; |
3892 | refresh(0); | |
3890 | refresh(false); | |
3893 | 3891 | } |
3894 | 3892 | return (0); |
3895 | 3893 | } |
3930 | 3928 | switch (vi_cmd(argc1, curcmd)) { |
3931 | 3929 | case -1: |
3932 | 3930 | vi_error(); |
3933 | refresh(0); | |
3931 | refresh(false); | |
3934 | 3932 | break; |
3935 | 3933 | case 0: |
3936 | 3934 | if (insert != 0) |
3938 | 3936 | refresh(insert != 0); |
3939 | 3937 | break; |
3940 | 3938 | case 1: |
3941 | refresh(0); | |
3939 | refresh(false); | |
3942 | 3940 | return (1); |
3943 | 3941 | case 2: |
3944 | 3942 | /* back from a 'v' command - don't redraw the screen */ |
3953 | 3951 | switch (vi_cmd(lastac, lastcmd)) { |
3954 | 3952 | case -1: |
3955 | 3953 | vi_error(); |
3956 | refresh(0); | |
3954 | refresh(false); | |
3957 | 3955 | break; |
3958 | 3956 | case 0: |
3959 | 3957 | if (insert != 0) { |
3966 | 3964 | vi_error(); |
3967 | 3965 | } |
3968 | 3966 | } |
3969 | refresh(0); | |
3967 | refresh(false); | |
3970 | 3968 | break; |
3971 | 3969 | case 1: |
3972 | refresh(0); | |
3970 | refresh(false); | |
3973 | 3971 | return (1); |
3974 | 3972 | case 2: |
3975 | 3973 | /* back from a 'v' command - can't happen */ |
4134 | 4132 | vi_cmd(int argcnt, const char *cmd) |
4135 | 4133 | { |
4136 | 4134 | int ncursor; |
4137 | int cur, c1, c2, c3 = 0; | |
4135 | int cur, c1, c2; | |
4138 | 4136 | int any; |
4137 | bool b; | |
4139 | 4138 | struct edstate *t; |
4140 | 4139 | |
4141 | 4140 | if (argcnt == 0 && !is_zerocount(*cmd)) |
4406 | 4405 | |
4407 | 4406 | case ORD('v'): |
4408 | 4407 | if (!argcnt) { |
4409 | if (vs->linelen == 0) | |
4410 | return (-1); | |
4411 | 4408 | if (modified) { |
4412 | 4409 | vs->cbuf[vs->linelen] = '\0'; |
4413 | 4410 | histsave(&source->line, vs->cbuf, |
4418 | 4415 | } |
4419 | 4416 | if (argcnt) |
4420 | 4417 | shf_snprintf(vs->cbuf, vs->cbufsize, Tf_sd, |
4421 | "fc -e ${VISUAL:-${EDITOR:-vi}} --", | |
4422 | argcnt); | |
4418 | ctrl_x_e, argcnt); | |
4423 | 4419 | else |
4424 | strlcpy(vs->cbuf, | |
4425 | "fc -e ${VISUAL:-${EDITOR:-vi}} --", | |
4426 | vs->cbufsize); | |
4420 | strlcpy(vs->cbuf, ctrl_x_e, vs->cbufsize); | |
4427 | 4421 | vs->linelen = strlen(vs->cbuf); |
4428 | 4422 | return (2); |
4429 | 4423 | |
4473 | 4467 | |
4474 | 4468 | /* FALLTHROUGH */ |
4475 | 4469 | case ORD('/'): |
4476 | c3 = 1; | |
4470 | c1 = 1; | |
4477 | 4471 | srchlen = 0; |
4478 | 4472 | lastsearch = *cmd; |
4479 | /* FALLTHROUGH */ | |
4473 | if (0) | |
4474 | /* FALLTHROUGH */ | |
4480 | 4475 | case ORD('n'): |
4481 | 4476 | case ORD('N'): |
4477 | c1 = 0; | |
4482 | 4478 | if (lastsearch == ORD(' ')) |
4483 | 4479 | return (-1); |
4484 | if (lastsearch == ORD('?')) | |
4485 | c1 = 1; | |
4486 | else | |
4487 | c1 = 0; | |
4480 | b = (lastsearch == ORD('?')); | |
4488 | 4481 | 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) { | |
4493 | 4485 | restore_cbuf(); |
4494 | refresh(0); | |
4486 | refresh(false); | |
4495 | 4487 | } |
4496 | 4488 | return (-1); |
4497 | 4489 | } else { |
5116 | 5108 | } |
5117 | 5109 | |
5118 | 5110 | static int |
5119 | grabsearch(int save, int start, int fwd, const char *pat) | |
5111 | grabsearch(const char *pat, int save, int start, bool fwd) | |
5120 | 5112 | { |
5121 | 5113 | char *hptr; |
5122 | 5114 | int hist; |
5123 | 5115 | bool anchored; |
5124 | 5116 | |
5125 | if ((start == 0 && fwd == 0) || (start >= hlast - 1 && fwd == 1)) | |
5117 | if ((start == 0 && !fwd) || (start >= hlast - 1 && fwd)) | |
5126 | 5118 | return (-1); |
5127 | 5119 | if (fwd) |
5128 | 5120 | start++; |
5129 | 5121 | else |
5130 | 5122 | start--; |
5131 | 5123 | anchored = *pat == '^' ? (++pat, true) : false; |
5132 | if ((hist = findhist(start, fwd, pat, anchored)) < 0) { | |
5124 | if ((hist = findhist(start, pat, fwd, anchored)) < 0) { | |
5133 | 5125 | /* (start != 0 && fwd && match(holdbufp, pat) >= 0) */ |
5134 | 5126 | if (start != 0 && fwd && strcmp(holdbufp, pat) >= 0) { |
5135 | 5127 | restore_cbuf(); |
5162 | 5154 | } |
5163 | 5155 | |
5164 | 5156 | static void |
5165 | refresh(int leftside) | |
5166 | { | |
5167 | if (leftside < 0) | |
5168 | leftside = lastref; | |
5169 | else | |
5170 | lastref = leftside; | |
5157 | refresh(bool leftside) | |
5158 | { | |
5171 | 5159 | if (outofwin()) |
5172 | 5160 | rewindow(); |
5173 | 5161 | display(wbuf[1 - win], wbuf[win], leftside); |
5223 | 5211 | } |
5224 | 5212 | |
5225 | 5213 | static void |
5226 | display(char *wb1, char *wb2, int leftside) | |
5214 | display(char *wb1, char *wb2, bool leftside) | |
5227 | 5215 | { |
5228 | 5216 | unsigned char ch; |
5229 | 5217 | char *twb1, *twb2, mc; |
5378 | 5366 | hnum = hlast; |
5379 | 5367 | insert = INSERT; |
5380 | 5368 | lastac = 0; |
5381 | refresh(0); | |
5369 | refresh(false); | |
5382 | 5370 | return (rval); |
5383 | 5371 | } |
5384 | 5372 | |
5493 | 5481 | insert = INSERT; |
5494 | 5482 | /* prevent this from being redone... */ |
5495 | 5483 | lastac = 0; |
5496 | refresh(0); | |
5484 | refresh(false); | |
5497 | 5485 | |
5498 | 5486 | return (rval); |
5499 | 5487 | } |
23 | 23 | |
24 | 24 | #include "sh.h" |
25 | 25 | |
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 $"); | |
27 | 27 | |
28 | 28 | #ifndef MKSH_DEFAULT_EXECSHELL |
29 | 29 | #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh" |
1212 | 1212 | } |
1213 | 1213 | |
1214 | 1214 | Search: |
1215 | if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) && | |
1215 | if ((!tp || (tp->type == CTALIAS && !(tp->flag & ISSET))) && | |
1216 | 1216 | (flags & FC_PATH)) { |
1217 | 1217 | if (!tp) { |
1218 | 1218 | if (insert && !(flags & FC_DEFPATH)) { |
1350 | 1350 | XcheckN(xs, xp, p - sp); |
1351 | 1351 | memcpy(xp, sp, p - sp); |
1352 | 1352 | xp += p - sp; |
1353 | #ifdef __OS2__ | |
1354 | if (xp > Xstring(xs, xp) && mksh_cdirsep(xp[-1])) | |
1353 | if (mksh_cdirsep(xp[-1])) | |
1355 | 1354 | xp--; |
1356 | #endif | |
1357 | 1355 | *xp++ = '/'; |
1358 | 1356 | } |
1359 | 1357 | sp = p; |
22 | 22 | |
23 | 23 | #include "sh.h" |
24 | 24 | |
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 $"); | |
26 | 26 | |
27 | 27 | #define EXPRTOK_DEFNS |
28 | 28 | #include "exprtok.h" |
885 | 885 | unsigned int val) MKSH_A_PURE; |
886 | 886 | |
887 | 887 | /* |
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 $ | |
890 | 890 | */ |
891 | 891 | |
892 | 892 | /*- |
1135 | 1135 | { 0xABE5, 0xABE5 }, |
1136 | 1136 | { 0xABE8, 0xABE8 }, |
1137 | 1137 | { 0xABED, 0xABED }, |
1138 | { 0xD7B0, 0xD7FF }, | |
1138 | 1139 | { 0xFB1E, 0xFB1E }, |
1139 | 1140 | { 0xFE00, 0xFE0F }, |
1140 | 1141 | { 0xFE20, 0xFE2F }, |
0 | 0 | /* $OpenBSD: c_ksh.c,v 1.37 2015/09/10 22:48:58 nicm Exp $ */ |
1 | 1 | /* $OpenBSD: c_sh.c,v 1.46 2015/07/20 20:46:24 guenther Exp $ */ |
2 | 2 | /* $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 $ */ | |
4 | 3 | |
5 | 4 | /*- |
6 | 5 | * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, |
38 | 37 | #endif |
39 | 38 | #endif |
40 | 39 | |
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 $"); | |
42 | 41 | |
43 | 42 | #if HAVE_KILLPG |
44 | 43 | /* |
51 | 50 | #define mksh_kill kill |
52 | 51 | #endif |
53 | 52 | |
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 | |
60 | 54 | #define c_ulimit c_true |
61 | 55 | #endif |
62 | 56 | |
706 | 700 | "exported " : "", |
707 | 701 | Talias); |
708 | 702 | } |
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); | |
710 | 720 | } else { |
711 | 721 | if (vflag) |
712 | 722 | shprintf(Tnot_found_s, id); |
3212 | 3222 | bi_errorf(Tf_s, msg); |
3213 | 3223 | } |
3214 | 3224 | |
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 | ||
3423 | 3225 | int |
3424 | 3226 | c_rename(const char **wp) |
3425 | 3227 | { |
3476 | 3278 | int |
3477 | 3279 | c_cat(const char **wp) |
3478 | 3280 | { |
3479 | int fd = STDIN_FILENO, rv; | |
3281 | int fd = 0, rv; | |
3480 | 3282 | ssize_t n, w; |
3481 | 3283 | const char *fn = "<stdin>"; |
3482 | 3284 | char *buf, *cp; |
3509 | 3311 | if (*wp) { |
3510 | 3312 | fn = *wp++; |
3511 | 3313 | if (ksh_isdash(fn)) |
3512 | fd = STDIN_FILENO; | |
3314 | fd = 0; | |
3513 | 3315 | else if ((fd = binopen2(fn, O_RDONLY)) < 0) { |
3514 | 3316 | bi_errorf(Tf_sD_s, fn, cstrerror(errno)); |
3515 | 3317 | rv = 1; |
3528 | 3330 | opipe = block_pipe(); |
3529 | 3331 | continue; |
3530 | 3332 | } |
3531 | /* an error occured during reading */ | |
3333 | /* an error occurred during reading */ | |
3532 | 3334 | bi_errorf(Tf_sD_s, fn, cstrerror(errno)); |
3533 | 3335 | rv = 1; |
3534 | 3336 | break; |
3538 | 3340 | while (n) { |
3539 | 3341 | if (intrsig) |
3540 | 3342 | goto has_intrsig; |
3541 | if ((w = write(STDOUT_FILENO, cp, n)) != -1) { | |
3343 | if ((w = write(1, cp, n)) != -1) { | |
3542 | 3344 | n -= w; |
3543 | 3345 | cp += w; |
3544 | 3346 | continue; |
3557 | 3359 | /* fake receiving signal */ |
3558 | 3360 | rv = ksh_sigmask(SIGPIPE); |
3559 | 3361 | } else { |
3560 | /* an error occured during writing */ | |
3362 | /* an error occurred during writing */ | |
3561 | 3363 | bi_errorf(Tf_sD_s, "<stdout>", |
3562 | 3364 | cstrerror(errno)); |
3563 | 3365 | rv = 1; |
3564 | 3366 | } |
3565 | if (fd != STDIN_FILENO) | |
3367 | if (fd != 0) | |
3566 | 3368 | close(fd); |
3567 | 3369 | goto out; |
3568 | 3370 | } |
3569 | 3371 | } |
3570 | if (fd != STDIN_FILENO) | |
3372 | if (fd != 0) | |
3571 | 3373 | close(fd); |
3572 | 3374 | } while (*wp); |
3573 | 3375 |
26 | 26 | #include <sys/file.h> |
27 | 27 | #endif |
28 | 28 | |
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 $"); | |
30 | 30 | |
31 | 31 | Trap sigtraps[ksh_NSIG + 1]; |
32 | 32 | static struct sigaction Sigact_ign; |
414 | 414 | bool anchored = *str == '?' ? (++str, false) : true; |
415 | 415 | |
416 | 416 | /* 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) | |
418 | 419 | bi_errorf(Tf_sD_s, str, Tnot_in_history); |
419 | 420 | else |
420 | 421 | hp = &history[n]; |
478 | 479 | * direction. |
479 | 480 | */ |
480 | 481 | int |
481 | findhist(int start, int fwd, const char *str, bool anchored) | |
482 | findhist(int start, const char *str, bool fwd, bool anchored) | |
482 | 483 | { |
483 | 484 | char **hp; |
484 | 485 | 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 $ | |
1 | 1 | .\"- |
2 | 2 | .\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016, 2017, 2018 |
3 | 3 | .\" mirabilos <m@mirbsd.org> |
24 | 24 | .\" thus use - for hyphens and \- for minus signs and option dashes |
25 | 25 | .\" * ~ is size-reduced and placed atop in groff, so use \*(TI |
26 | 26 | .\" * ^ 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 | |
28 | 29 | .\" * <>| are problematic, so redefine and use \*(Lt\*(Gt\*(Ba |
29 | 30 | .\" Also make sure to use \& *before* a punctuation char that is to not |
30 | 31 | .\" be interpreted as punctuation, and especially with two-letter words |
58 | 59 | . ds ha ^ |
59 | 60 | . ds en \(em |
60 | 61 | .\} |
62 | .ie n \{\ | |
63 | . ds EM \ \*(en\ \& | |
64 | .\} | |
65 | .el \{\ | |
66 | . ds EM \f(TR\^\(em\^\fP | |
67 | .\} | |
61 | 68 | .\" |
62 | 69 | .\" Implement .Dd with the Mdocdate RCS keyword |
63 | 70 | .\" |
73 | 80 | .\" with -mandoc, it might implement .Mx itself, but we want to |
74 | 81 | .\" use our own definition. And .Dd must come *first*, always. |
75 | 82 | .\" |
76 | .Dd $Mdocdate: December 25 2018 $ | |
83 | .Dd $Mdocdate: September 4 2020 $ | |
77 | 84 | .\" |
78 | 85 | .\" Check which macro package we use, and do other -mdoc setup. |
79 | 86 | .\" |
34 | 34 | #include <locale.h> |
35 | 35 | #endif |
36 | 36 | |
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 $"); | |
38 | 38 | |
39 | 39 | #ifndef MKSHRC_PATH |
40 | 40 | #define MKSHRC_PATH "~/.mkshrc" |
1196 | 1196 | |
1197 | 1197 | /* |
1198 | 1198 | * 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 | |
1200 | 1200 | * for setting up the tty process group. Return values: |
1201 | 1201 | * 0 = got controlling tty |
1202 | 1202 | * 1 = got terminal but no controlling tty |
1428 | 1428 | /* Avoid foo: foo[2]: ... */ |
1429 | 1429 | if (!fileline || !source || !source->file || |
1430 | 1430 | 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)); | |
1432 | 1433 | if (fileline && source && source->file != NULL) { |
1433 | 1434 | shf_fprintf(shl_out, "%s[%lu]: ", source->file, |
1434 | 1435 | (unsigned long)(source->errline ? |
32 | 32 | #include <grp.h> |
33 | 33 | #endif |
34 | 34 | |
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 $"); | |
36 | 36 | |
37 | 37 | #define KSH_CHVT_FLAG |
38 | 38 | #ifdef MKSH_SMALL |
1327 | 1327 | if (go->flags & GF_ERROR) |
1328 | 1328 | bi_errorfz(); |
1329 | 1329 | } |
1330 | return ('?'); | |
1330 | return (ORD('?')); | |
1331 | 1331 | } |
1332 | 1332 | /** |
1333 | 1333 | * : means argument must be present, may be part of option argument |
1346 | 1346 | if (optionsp[0] == ':') { |
1347 | 1347 | go->buf[0] = c; |
1348 | 1348 | go->optarg = go->buf; |
1349 | return (':'); | |
1349 | return (ORD(':')); | |
1350 | 1350 | } |
1351 | 1351 | warningf(true, Tf_optfoo, |
1352 | 1352 | (go->flags & GF_NONAME) ? "" : argv[0], |
1354 | 1354 | c, Treq_arg); |
1355 | 1355 | if (go->flags & GF_ERROR) |
1356 | 1356 | bi_errorfz(); |
1357 | return ('?'); | |
1357 | return (ORD('?')); | |
1358 | 1358 | } |
1359 | 1359 | go->p = 0; |
1360 | 1360 | } else if (*o == ',') { |
1382 | 1382 | go->optarg = NULL; |
1383 | 1383 | } |
1384 | 1384 | } |
1385 | return (c); | |
1385 | return (ord(c)); | |
1386 | 1386 | } |
1387 | 1387 | |
1388 | 1388 | /* |
1926 | 1926 | * - if file starts with '/', append file to result & set cdpathp to NULL |
1927 | 1927 | * - if file starts with ./ or ../ append cwd and file to result |
1928 | 1928 | * 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 | |
1930 | 1930 | * then cwd is appended to result. |
1931 | 1931 | * - the first element of cdpathp is appended to result |
1932 | 1932 | * - file is appended to result |
1982 | 1982 | XcheckN(*xsp, xp, len); |
1983 | 1983 | memcpy(xp, cwd, len); |
1984 | 1984 | xp += len; |
1985 | if (!mksh_cdirsep(cwd[len - 1])) | |
1986 | Xput(*xsp, xp, '/'); | |
1985 | if (mksh_cdirsep(xp[-1])) | |
1986 | xp--; | |
1987 | *xp++ = '/'; | |
1987 | 1988 | } |
1988 | 1989 | *phys_pathp = Xlength(*xsp, xp); |
1989 | 1990 | if (use_cdpath && plen) { |
1990 | 1991 | XcheckN(*xsp, xp, plen); |
1991 | 1992 | memcpy(xp, plist, plen); |
1992 | 1993 | xp += plen; |
1993 | if (!mksh_cdirsep(plist[plen - 1])) | |
1994 | Xput(*xsp, xp, '/'); | |
1994 | if (mksh_cdirsep(xp[-1])) | |
1995 | xp--; | |
1996 | *xp++ = '/'; | |
1995 | 1997 | rval = 1; |
1996 | 1998 | } |
1997 | 1999 | } |
2055 | 2057 | case '\\': |
2056 | 2058 | #endif |
2057 | 2059 | /* 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])) { | |
2059 | 2061 | /* keep them, e.g. for UNC pathnames */ |
2062 | #ifdef MKSH_DOSPATH | |
2063 | *p++ = '/'; | |
2064 | #else | |
2060 | 2065 | ++p; |
2066 | #endif | |
2067 | } | |
2061 | 2068 | needslash = true; |
2062 | 2069 | break; |
2063 | 2070 | default: |
2188 | 2195 | oldpwd_s = global(TOLDPWD); |
2189 | 2196 | |
2190 | 2197 | if (!wp[0]) { |
2191 | /* No arguments - go home */ | |
2198 | /* no arguments; go home */ | |
2192 | 2199 | if ((dir = str_val(global("HOME"))) == null) { |
2193 | 2200 | bi_errorf("no home directory (HOME not set)"); |
2194 | 2201 | return (2); |
2195 | 2202 | } |
2196 | 2203 | } 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])) { | |
2202 | 2206 | dir = str_val(oldpwd_s); |
2203 | 2207 | if (dir == null) { |
2204 | 2208 | bi_errorf(Tno_OLDPWD); |
2205 | 2209 | return (2); |
2206 | 2210 | } |
2207 | 2211 | printpath = true; |
2212 | } else { | |
2213 | strdupx(allocd, wp[0], ATEMP); | |
2214 | dir = allocd; | |
2208 | 2215 | } |
2209 | 2216 | } else if (!wp[2]) { |
2210 | /* Two arguments - substitute arg1 in PWD for arg2 */ | |
2217 | /* two arguments; substitute arg1 in PWD for arg2 */ | |
2211 | 2218 | size_t ilen, olen, nlen, elen; |
2212 | 2219 | char *cp; |
2213 | 2220 | |
2216 | 2223 | return (2); |
2217 | 2224 | } |
2218 | 2225 | /* |
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. | |
2223 | 2229 | */ |
2224 | 2230 | if ((cp = strstr(current_wd, wp[0])) == NULL) { |
2225 | 2231 | 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 $ | |
1 | 1 | .\" $OpenBSD: ksh.1,v 1.160 2015/07/04 13:27:04 feinerer Exp $ |
2 | 2 | .\"- |
3 | 3 | .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, |
83 | 83 | .\" with -mandoc, it might implement .Mx itself, but we want to |
84 | 84 | .\" use our own definition. And .Dd must come *first*, always. |
85 | 85 | .\" |
86 | .Dd $Mdocdate: May 16 2020 $ | |
86 | .Dd $Mdocdate: October 1 2020 $ | |
87 | 87 | .\" |
88 | 88 | .\" Check which macro package we use, and do other -mdoc setup. |
89 | 89 | .\" |
1413 | 1413 | where |
1414 | 1414 | .Ar name |
1415 | 1415 | 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 | |
1417 | 1417 | .Ar expr |
1418 | 1418 | in the latter form mentioned above, expand the element with the key |
1419 | 1419 | .Dq 0 . |
5332 | 5332 | Impose a size limit of |
5333 | 5333 | .Ar n |
5334 | 5334 | blocks on the size of core dumps. |
5335 | Silently ignored if the system does not support this limit. | |
5335 | 5336 | .It Fl d Ar n |
5336 | 5337 | Limit the size of the data area to |
5337 | 5338 | .Ar n |
5338 | 5339 | kibibytes. |
5340 | .br | |
5341 | On some systems, read-only maximum | |
5342 | .Xr brk 2 | |
5343 | size minus | |
5344 | .Li etext . | |
5339 | 5345 | .It Fl e Ar n |
5340 | 5346 | Set the maximum niceness to |
5341 | 5347 | .Ar n . |
5368 | 5374 | Impose a limit of |
5369 | 5375 | .Ar n |
5370 | 5376 | file descriptors that can be open at once. |
5377 | On some systems attempts to set are silently ignored. | |
5371 | 5378 | .It Fl O Ar n |
5372 | 5379 | Set the number of AIO operations to |
5373 | 5380 | .Ar n . |
6063 | 6070 | .Op Ar n |
6064 | 6071 | .No \*(haXe |
6065 | 6072 | .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 | |
6067 | 6077 | .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. | |
6071 | 6085 | .It end\-of\-history: \*(ha[\*(Gt |
6072 | 6086 | Moves to the end of the history. |
6073 | 6087 | .It end\-of\-line: \*(haE, ANSI-End, PC-End |
6425 | 6439 | .It Xo |
6426 | 6440 | .Oo Ar n Oc Ns v |
6427 | 6441 | .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 | |
6429 | 6446 | .Ar n |
6430 | using the | |
6431 | .Xr vi 1 | |
6432 | editor; if | |
6447 | (if | |
6433 | 6448 | .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. | |
6437 | 6454 | .It * and \*(haX |
6438 | 6455 | Command or file name expansion is applied to the current big-word (with an |
6439 | 6456 | appended |
7071 | 7088 | .Xr memmove 3 . |
7072 | 7089 | .Pp |
7073 | 7090 | This document attempts to describe |
7074 | .Nm mksh\ R59b | |
7091 | .Nm mksh\ R59c | |
7075 | 7092 | and up, |
7076 | 7093 | .\" with vendor patches from insert-your-name-here, |
7077 | 7094 | 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 $ | |
1 | 1 | ToC: spelling |
2 | 2 | Title: How do you spell <tt>mksh</tt>? How do you pronounce it? |
3 | 3 | |
206 | 206 | ToC: oldbsd |
207 | 207 | Title: Why do other BSDs and QNX still use pdksh instead of mksh? |
208 | 208 | |
209 | <p>Some systems are resistent to change, mostly due to bikeshedding | |
209 | <p>Some systems are resistant to change, mostly due to bikeshedding | |
210 | 210 | (some people would, for example, rather see all shells banned to |
211 | 211 | ports/pkgsrc®) and hysterial raisins (historical reasons ☻). Most |
212 | 212 | BSDs have mksh packages available, and it works on all of them and |
295 | 295 | pdksh derivative); <tt>$SH_VERSION</tt> (“PD KSH” as sh), <tt>$YASH_VERSION</tt> |
296 | 296 | (yash), <tt>$ZSH_VERSION</tt> (or if <tt>$VERSION</tt> begins with “zsh”); a <a |
297 | 297 | 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> | |
298 | 321 | ---- |
299 | 322 | ToC: ctrl-l-cls |
300 | 323 | Title: ^L (Ctrl-L) does not clear the screen |
437 | 460 | <tt>[[ foo =~ (foo|bar).*baz ]]</tt><br /> |
438 | 461 | … becomes…<br /> |
439 | 462 | <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> | |
440 | 472 | ---- |
441 | 473 | ToC: extensions-to-avoid |
442 | 474 | Title: Are there any extensions to avoid? |
0 | 0 | /*- |
1 | 1 | * Copyright (c) 2015, 2017, 2020 |
2 | 2 | * KO Myung-Hun <komh@chollian.net> |
3 | * Copyright (c) 2017 | |
3 | * Copyright (c) 2017, 2020 | |
4 | 4 | * mirabilos <m@mirbsd.org> |
5 | 5 | * |
6 | 6 | * Provided that these terms and disclaimer and all copyright notices |
31 | 31 | #include <unistd.h> |
32 | 32 | #include <process.h> |
33 | 33 | |
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 *); | |
39 | 51 | static void response(int *, const char ***); |
40 | 52 | static char *make_response_file(char * const *); |
41 | 53 | static void add_temp(const char *); |
222 | 234 | } |
223 | 235 | |
224 | 236 | /* 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; | |
229 | 241 | |
230 | 242 | while (--p > name && *p == '.') |
231 | 243 | /* nothing */; |
232 | 244 | |
233 | 245 | if (*p != '.' && *p != '/' && *p != '\\' && *p != ':') |
234 | 246 | 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 | } | |
241 | 248 | |
242 | 249 | /* alias of stat() */ |
243 | 250 | extern int _std_stat(const char *, struct stat *); |
246 | 253 | int |
247 | 254 | stat(const char *name, struct stat *buffer) |
248 | 255 | { |
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)); | |
250 | 262 | } |
251 | 263 | |
252 | 264 | /* alias of access() */ |
256 | 268 | int |
257 | 269 | access(const char *name, int mode) |
258 | 270 | { |
271 | size_t namelen = strlen(name) + 1; | |
272 | char nodots[namelen]; | |
273 | ||
259 | 274 | /* |
260 | 275 | * On OS/2 kLIBC, X_OK is set only for executable files. |
261 | 276 | * This prevents scripts from being executed. |
263 | 278 | if (mode & X_OK) |
264 | 279 | mode = (mode & ~X_OK) | R_OK; |
265 | 280 | |
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)); | |
267 | 284 | } |
268 | 285 | |
269 | 286 | #define MAX_X_SUFFIX_LEN 4 |
273 | 290 | |
274 | 291 | /* call fn() by appending executable extensions */ |
275 | 292 | 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) | |
277 | 294 | { |
278 | 295 | char *x_name; |
279 | 296 | const char **x_suffix; |
287 | 304 | strlcpy(x_name, name, x_namelen); |
288 | 305 | strlcat(x_name, *x_suffix, x_namelen); |
289 | 306 | |
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); | |
291 | 309 | } |
292 | 310 | |
293 | 311 | afree(x_name, ATEMP); |
299 | 317 | int |
300 | 318 | access_ex(int (*fn)(const char *, int), const char *name, int mode) |
301 | 319 | { |
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)); | |
304 | 326 | } |
305 | 327 | |
306 | 328 | /* stat()/lstat() version */ |
308 | 330 | stat_ex(int (*fn)(const char *, struct stat *), |
309 | 331 | const char *name, struct stat *buffer) |
310 | 332 | { |
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)); | |
312 | 339 | } |
313 | 340 | |
314 | 341 | static int |
315 | test_exec_exist(const char *name, char *real_name) | |
342 | test_exec_exist(const char *name, void *arg) | |
316 | 343 | { |
317 | 344 | struct stat sb; |
345 | char *real_name; | |
318 | 346 | |
319 | 347 | if (stat(name, &sb) < 0 || !S_ISREG(sb.st_mode)) |
320 | 348 | return (-1); |
321 | 349 | |
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; | |
325 | 353 | return (0); |
326 | 354 | } |
327 | 355 | |
328 | 356 | const char * |
329 | 357 | real_exec_name(const char *name) |
330 | 358 | { |
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); | |
339 | 366 | } |
340 | 367 | |
341 | 368 | /* make a response file to pass a very long command line */ |
0 | 0 | /*- |
1 | * Copyright (c) 2013, 2015 | |
1 | * Copyright (c) 2013, 2015, 2019 | |
2 | 2 | * mirabilos <m@mirbsd.org> |
3 | 3 | * |
4 | 4 | * Provided that these terms and disclaimer and all copyright notices |
15 | 15 | * of dealing in the work, even if advised of the possibility of such |
16 | 16 | * damage or existence of a defect, except proven that it results out |
17 | 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! | |
18 | 20 | */ |
19 | 21 | |
20 | 22 | @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 $"); | |
22 | 24 | @RLIMITS_ITEMS |
23 | 25 | #define FN(lname,lid,lfac,lopt) (const struct limits *)(&rlimits_ ## lid), |
24 | 26 | @@ |
77 | 77 | #if HAVE_PATHS_H |
78 | 78 | #include <paths.h> |
79 | 79 | #endif |
80 | #ifndef MKSH_NOPWNAM | |
80 | 81 | #include <pwd.h> |
82 | #endif | |
81 | 83 | #include <setjmp.h> |
82 | 84 | #include <signal.h> |
83 | 85 | #include <stdarg.h> |
190 | 192 | #endif |
191 | 193 | |
192 | 194 | #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" | |
196 | 198 | |
197 | 199 | /* arithmetic types: C implementation */ |
198 | 200 | #if !HAVE_CAN_INTTYPES |
245 | 247 | #endif |
246 | 248 | |
247 | 249 | /* other standard types */ |
248 | ||
249 | #if !HAVE_RLIM_T | |
250 | typedef unsigned long rlim_t; | |
251 | #endif | |
252 | 250 | |
253 | 251 | #if !HAVE_SIG_T |
254 | 252 | #undef sig_t |
667 | 665 | #endif |
668 | 666 | #endif |
669 | 667 | |
670 | #if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 592) | |
668 | #if (!defined(MKSH_BUILDMAKEFILE4BSD) && !defined(MKSH_BUILDSH)) || (MKSH_BUILD_R != 593) | |
671 | 669 | #error Must run Build.sh to compile this. |
672 | 670 | extern void thiswillneverbedefinedIhope(void); |
673 | 671 | int |
2521 | 2519 | char **histpos(void) MKSH_A_PURE; |
2522 | 2520 | int histnum(int); |
2523 | 2521 | #endif |
2524 | int findhist(int, int, const char *, bool) MKSH_A_PURE; | |
2522 | int findhist(int, const char *, bool, bool) MKSH_A_PURE; | |
2525 | 2523 | char **hist_get_newest(bool); |
2526 | 2524 | void inittraps(void); |
2527 | 2525 | void alarm_init(void); |
26 | 26 | |
27 | 27 | #include "sh.h" |
28 | 28 | |
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 $"); | |
30 | 30 | |
31 | 31 | /* flags to shf_emptybuf() */ |
32 | 32 | #define EB_READSW 0x01 /* about to switch to reading */ |
665 | 665 | if (nbytes < 0) |
666 | 666 | internal_errorf(Tf_szs, Tshf_write, nbytes, Tbytes); |
667 | 667 | |
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 */ | |
669 | 669 | if ((ncopy = shf->wnleft) && |
670 | 670 | (shf->wp != shf->buf || nbytes < shf->wnleft)) { |
671 | 671 | if (ncopy > nbytes) |
781 | 781 | #define FL_ZERO 0x040 /* '0' seen */ |
782 | 782 | #define FL_DOT 0x080 /* '.' seen */ |
783 | 783 | #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] */ | |
785 | 785 | #define FL_SIZET 0x400 /* 'z' seen */ |
786 | 786 | #define FM_SIZES 0x430 /* h/l/z mask */ |
787 | 787 |
23 | 23 | |
24 | 24 | #include "sh.h" |
25 | 25 | |
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 $"); | |
27 | 27 | |
28 | 28 | struct nesting_state { |
29 | 29 | int start_token; /* token than began nesting (eg, FOR) */ |
267 | 267 | { |
268 | 268 | struct op *t; |
269 | 269 | int c, iopn = 0, syniocf, lno; |
270 | struct ioword *iop, **iops; | |
270 | struct ioword *iop; | |
271 | 271 | XPtrV args, vars; |
272 | 272 | struct nesting_state old_nesting; |
273 | 273 | 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 | ||
277 | 276 | XPinit(args, 16); |
278 | 277 | XPinit(vars, 16); |
279 | 278 | |
281 | 280 | switch (c = token(cf|KEYWORD|sALIAS|CMDASN)) { |
282 | 281 | default: |
283 | 282 | REJECT; |
284 | afree(iops, ATEMP); | |
285 | 283 | XPfree(args); |
286 | 284 | XPfree(vars); |
287 | 285 | /* empty line */ |
509 | 507 | } |
510 | 508 | |
511 | 509 | if (iopn == 0) { |
512 | afree(iops, ATEMP); | |
513 | 510 | t->ioact = NULL; |
514 | 511 | } else { |
515 | 512 | 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 *)); | |
518 | 515 | } |
519 | 516 | |
520 | 517 | if (t->type == TCOM || t->type == TDBRACKET) { |
22 | 22 | |
23 | 23 | #include "sh.h" |
24 | 24 | |
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 $"); | |
26 | 26 | |
27 | 27 | #define INDENT 8 |
28 | 28 | |
35 | 35 | |
36 | 36 | /* "foo& ; bar" and "foo |& ; bar" are invalid */ |
37 | 37 | 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) | |
38 | 51 | |
39 | 52 | static const char Telif_pT[] = "elif %T"; |
40 | 53 | |
81 | 94 | w = (const char **)t->vars; |
82 | 95 | while (*w) |
83 | 96 | fptreef(shf, indent, Tf_S_, *w++); |
84 | } else | |
97 | } | |
98 | #ifndef MKSH_SMALL | |
99 | else | |
85 | 100 | shf_puts("#no-vars# ", shf); |
101 | #endif | |
86 | 102 | if (t->args) { |
87 | 103 | w = t->args; |
88 | 104 | if (*w && **w == CHAR) { |
96 | 112 | } |
97 | 113 | while (*w) |
98 | 114 | fptreef(shf, indent, Tf_S_, *w++); |
99 | } else | |
115 | } | |
116 | #ifndef MKSH_SMALL | |
117 | else | |
100 | 118 | shf_puts("#no-args# ", shf); |
119 | #endif | |
101 | 120 | break; |
102 | 121 | case TEXEC: |
103 | 122 | t = t->left; |
220 | 239 | prevent_semicolon = false; |
221 | 240 | break; |
222 | 241 | } |
223 | if ((ioact = t->ioact) != NULL) { | |
224 | bool need_nl = false; | |
225 | ||
242 | if ((ioact = t->ioact) != NULL) | |
226 | 243 | while (*ioact != NULL) |
227 | 244 | 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 | } | |
253 | 245 | } |
254 | 246 | |
255 | 247 | static void |
271 | 263 | shf_putc('<', shf); |
272 | 264 | break; |
273 | 265 | case IOHERE: |
266 | if (flag & IOHERESTR) { | |
267 | shf_puts("<<<", shf); | |
268 | goto ioheredelim; | |
269 | } | |
274 | 270 | shf_puts("<<", shf); |
275 | 271 | if (flag & IOSKIP) |
276 | 272 | 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); | |
279 | 289 | break; |
280 | 290 | case IOCAT: |
281 | 291 | shf_puts(">>", shf); |
292 | 302 | shf_puts(flag & IORDUP ? "<&" : ">&", shf); |
293 | 303 | break; |
294 | 304 | } |
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) { | |
300 | 307 | if (flag & IONAMEXP) |
301 | 308 | print_value_quoted(shf, iop->ioname); |
302 | 309 | else |
341 | 348 | c = ord(*wp++); |
342 | 349 | if (opmode & WDS_TPUTS) |
343 | 350 | 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; | |
351 | 351 | default: |
352 | 352 | if (quotelevel == 0) |
353 | 353 | /* FALLTHROUGH */ |
465 | 465 | vfptreef(struct shf *shf, int indent, const char *fmt, va_list va) |
466 | 466 | { |
467 | 467 | int c; |
468 | ||
469 | if (!ptree_nest++) | |
470 | ptree_hashere = false; | |
468 | 471 | |
469 | 472 | while ((c = ord(*fmt++))) { |
470 | 473 | if (c == '%') { |
503 | 506 | shf_putc(';', shf); |
504 | 507 | shf_putc(' ', shf); |
505 | 508 | } else { |
506 | int i; | |
507 | ||
509 | int i = indent; | |
510 | ||
511 | ptree_outhere(shf); | |
508 | 512 | shf_putc('\n', shf); |
509 | i = indent; | |
510 | 513 | while (i >= 8) { |
511 | 514 | shf_putc('\t', shf); |
512 | 515 | i -= 8; |
529 | 532 | dont_trash_prevent_semicolon: |
530 | 533 | ; |
531 | 534 | } |
535 | ||
536 | if (!--ptree_nest) | |
537 | ptree_outhere(shf); | |
532 | 538 | } |
533 | 539 | |
534 | 540 | /* |
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 |
28 | 28 | #include <sys/sysctl.h> |
29 | 29 | #endif |
30 | 30 | |
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 $"); | |
32 | 32 | |
33 | 33 | /*- |
34 | 34 | * Variables |
1899 | 1899 | break; |
1900 | 1900 | } |
1901 | 1901 | |
1902 | /* see comment below regarding possible opions */ | |
1902 | /* see comment below regarding possible options */ | |
1903 | 1903 | opts = istset ? "L#R#UZ#afgi#lnprtux" : "p"; |
1904 | 1904 | |
1905 | 1905 | builtin_opt.flags |= GF_PLUSOPT; |