Codebase list mksh / a781241
Merge branch 'origtgz', update printf.c, sync mirabilos authored 2 years ago mirabilos committed 2 years ago
29 changed file(s) with 3072 addition(s) and 1969 deletion(s). Raw diff Collapse all Expand all
+133
-117
Build.sh less more
00 #!/bin/sh
1 srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.810 2021/10/11 22:23:01 tg Exp $'
1 srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.821 2022/01/28 14:26:27 tg Exp $'
2 set +evx
23 #-
34 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
45 # 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
5 # 2020, 2021
6 # 2020, 2021, 2022
67 # mirabilos <m@mirbsd.org>
78 #
89 # Provided that these terms and disclaimer and all copyright notices
245246 CPPFLAGS <$CPPFLAGS>
246247 LDFLAGS <$LDFLAGS>
247248 LIBS <$LIBS>
249 LDSTATIC <$LDSTATIC>
248250 TARGET_OS <$TARGET_OS> TARGET_OSREV <$TARGET_OSREV>
249251
250252 EOF
384386 fi
385387 vscan=
386388 if test $phase = u; then
387 test $ct = gcc && vscan='unrecogni[sz]ed'
388 test $ct = hpcc && vscan='unsupported'
389 test $ct = pcc && vscan='unsupported'
390 test $ct = sunpro && vscan='-e ignored -e turned.off'
389 case $ct in
390 gcc*) vscan='unrecogni[sz]ed' ;;
391 hpcc) vscan='unsupported' ;;
392 pcc) vscan='unsupported' ;;
393 sunpro) vscan='-e ignored -e turned.off' ;;
394 esac
391395 fi
392396 test_n "$vscan" && grep $vscan vv.out >/dev/null 2>&1 && fv=$fr
393397 return 0
827831 ;;
828832 AIX)
829833 add_cppflags -D_ALL_SOURCE
830 : "${HAVE_SETLOCALE_CTYPE=0}"
831834 ;;
832835 BeOS)
833836 : "${CC=gcc}"
864867 : "${HAVE_SETRESUGID=0}"
865868 ;;
866869 BSD/OS)
867 : "${HAVE_SETLOCALE_CTYPE=0}"
870 : "${HAVE_POSIX_UTF8_LOCALE=0}"
868871 ;;
869872 Coherent)
870873 oswarn="; it has major issues"
875878 cpp_define MKSH_DISABLE_TTY_WARNING 1
876879 ;;
877880 CYGWIN*)
878 : "${HAVE_SETLOCALE_CTYPE=0}"
881 : "${HAVE_POSIX_UTF8_LOCALE=0}"
879882 ;;
880883 Darwin)
881884 add_cppflags -D_DARWIN_C_SOURCE
887890 FreeMiNT)
888891 oswarn="; it has minor issues"
889892 add_cppflags -D_GNU_SOURCE
890 : "${HAVE_SETLOCALE_CTYPE=0}"
893 : "${HAVE_POSIX_UTF8_LOCALE=0}"
891894 ;;
892895 GNU)
893896 case $CC in
909912 cpp_define MKSH_ASSUME_UTF8 1
910913 HAVE_ISSET_MKSH_ASSUME_UTF8=1
911914 HAVE_ISOFF_MKSH_ASSUME_UTF8=0
912 : "${HAVE_SETLOCALE_CTYPE=0}"
913915 ;;
914916 Harvey)
915917 add_cppflags -D_POSIX_SOURCE
920922 cpp_define MKSH_ASSUME_UTF8 1
921923 HAVE_ISSET_MKSH_ASSUME_UTF8=1
922924 HAVE_ISOFF_MKSH_ASSUME_UTF8=0
923 : "${HAVE_SETLOCALE_CTYPE=0}"
925 : "${HAVE_POSIX_UTF8_LOCALE=0}"
924926 cpp_define MKSH__NO_SYMLINK 1
925927 check_categories="$check_categories nosymlink"
926928 cpp_define MKSH_NO_CMDLINE_EDITING 1
943945 ccpl='-Y '
944946 add_cppflags -D_ALL_SOURCE
945947 : "${LIBS=-lcrypt}"
946 : "${HAVE_SETLOCALE_CTYPE=0}"
948 : "${HAVE_POSIX_UTF8_LOCALE=0}"
947949 ;;
948950 IRIX*)
949 : "${HAVE_SETLOCALE_CTYPE=0}"
950951 ;;
951952 Jehanne)
952953 cpp_define MKSH_ASSUME_UTF8 1
953954 HAVE_ISSET_MKSH_ASSUME_UTF8=1
954955 HAVE_ISOFF_MKSH_ASSUME_UTF8=0
955 : "${HAVE_SETLOCALE_CTYPE=0}"
956 : "${HAVE_POSIX_UTF8_LOCALE=0}"
956957 cpp_define MKSH__NO_SYMLINK 1
957958 check_categories="$check_categories nosymlink"
958959 cpp_define MKSH_NO_CMDLINE_EDITING 1
987988 : "${HAVE_SETRESUGID=0}"
988989 cpp_define MKSH_UNEMPLOYED 1
989990 oldish_ed=no-stderr-ed # no /bin/ed, maybe see below
990 : "${HAVE_SETLOCALE_CTYPE=0}"
991 : "${HAVE_POSIX_UTF8_LOCALE=0}"
991992 ;;
992993 Minix3)
993994 add_cppflags -D_POSIX_SOURCE -D_POSIX_1_SOURCE=2 -D_MINIX
994995 cpp_define MKSH_UNEMPLOYED 1
995996 oldish_ed=no-stderr-ed # /usr/bin/ed(!) is broken
996 : "${HAVE_SETLOCALE_CTYPE=0}${MKSH_UNLIMITED=1}" #XXX recheck ulimit
997 : "${HAVE_POSIX_UTF8_LOCALE=0}"
998 : "${MKSH_UNLIMITED=1}" #XXX recheck ulimit
997999 ;;
9981000 Minoca)
9991001 : "${CC=gcc}"
10071009 HAVE_ISSET_MKSH_ASSUME_UTF8=1
10081010 HAVE_ISOFF_MKSH_ASSUME_UTF8=1
10091011 # almost same as CYGWIN* (from RT|Chatzilla)
1010 : "${HAVE_SETLOCALE_CTYPE=0}"
1012 : "${HAVE_POSIX_UTF8_LOCALE=0}"
10111013 # broken on this OE (from ir0nh34d)
10121014 : "${HAVE_STDINT_H=0}"
10131015 ;;
10311033 Ninix3)
10321034 # similar to Minix3
10331035 cpp_define MKSH_UNEMPLOYED 1
1034 : "${MKSH_UNLIMITED=1}" #XXX recheck ulimit
1036 : "${MKSH_UNLIMITED=1}" #XXX recheck ulimit
10351037 # but no idea what else could be needed
10361038 oswarn="; it has unknown issues"
10371039 ;;
10381040 OpenBSD)
1039 : "${HAVE_SETLOCALE_CTYPE=0}"
10401041 ;;
10411042 OS/2)
10421043 cpp_define MKSH_ASSUME_UTF8 0
10431044 HAVE_ISSET_MKSH_ASSUME_UTF8=1
10441045 HAVE_ISOFF_MKSH_ASSUME_UTF8=1
1045 : "${HAVE_SETLOCALE_CTYPE=0}"
1046 : "${HAVE_POSIX_UTF8_LOCALE=0}"
1047 # cf. https://github.com/komh/pdksh-os2/commit/590f2b19b0ff92a9a373295bce914654f9f5bf22
10461048 HAVE_TERMIOS_H=0
10471049 HAVE_MKNOD=0 # setmode() incompatible
10481050 check_categories="$check_categories nosymlink"
10791081 cpp_define MKSH_ASSUME_UTF8 0
10801082 HAVE_ISSET_MKSH_ASSUME_UTF8=1
10811083 HAVE_ISOFF_MKSH_ASSUME_UTF8=1
1082 : "${HAVE_SETLOCALE_CTYPE=0}"
1084 : "${HAVE_POSIX_UTF8_LOCALE=0}"
10831085 : "${CC=xlc}"
10841086 : "${SIZE=: size}"
10851087 cpp_define MKSH_FOR_Z_OS 1
10861088 add_cppflags -D_ALL_SOURCE
1089 $ebcdic || add_cppflags -D_ENHANCED_ASCII_EXT=0xFFFFFFFF
10871090 oswarn='; EBCDIC support is incomplete'
10881091 ;;
10891092 OSF1)
10921095 add_cppflags -D_POSIX_C_SOURCE=200112L
10931096 add_cppflags -D_XOPEN_SOURCE=600
10941097 add_cppflags -D_XOPEN_SOURCE_EXTENDED
1095 : "${HAVE_SETLOCALE_CTYPE=0}"
1098 : "${HAVE_POSIX_UTF8_LOCALE=0}"
10961099 ;;
10971100 Plan9)
10981101 add_cppflags -D_POSIX_SOURCE
11021105 cpp_define MKSH_ASSUME_UTF8 1
11031106 HAVE_ISSET_MKSH_ASSUME_UTF8=1
11041107 HAVE_ISOFF_MKSH_ASSUME_UTF8=0
1105 : "${HAVE_SETLOCALE_CTYPE=0}"
1108 : "${HAVE_POSIX_UTF8_LOCALE=0}"
11061109 cpp_define MKSH__NO_SYMLINK 1
11071110 check_categories="$check_categories nosymlink"
11081111 cpp_define MKSH_NO_CMDLINE_EDITING 1
11161119 PW32*)
11171120 HAVE_SIG_T=0 # incompatible
11181121 oswarn=' and will currently not work'
1119 : "${HAVE_SETLOCALE_CTYPE=0}"
1122 : "${HAVE_POSIX_UTF8_LOCALE=0}"
11201123 ;;
11211124 QNX)
11221125 add_cppflags -D__NO_EXT_QNX
11261129 oldish_ed=no-stderr-ed # oldish /bin/ed is broken
11271130 ;;
11281131 esac
1129 : "${HAVE_SETLOCALE_CTYPE=0}"
1132 : "${HAVE_POSIX_UTF8_LOCALE=0}"
11301133 ;;
11311134 scosysv)
11321135 cmplrflgs=-DMKSH_MAYBE_QUICK_C
11351138 cpp_define MKSH_BROKEN_OFFSETOF 1
11361139 cpp_define MKSH_TYPEDEF_SSIZE_T int
11371140 cpp_define MKSH_UNEMPLOYED 1
1138 : "${HAVE_SETLOCALE_CTYPE=0}${HAVE_TERMIOS_H=0}"
1141 : "${HAVE_POSIX_UTF8_LOCALE=0}${HAVE_TERMIOS_H=0}"
11391142 ;;
11401143 SCO_SV)
11411144 case $TARGET_OSREV in
11541157 : "${HAVE_SYS_SIGLIST=0}${HAVE__SYS_SIGLIST=0}"
11551158 ;;
11561159 SerenityOS)
1157 oswarn="; it has major issues"
1158 cpp_define MKSH_NO_SIGSUSPEND 1
1159 cpp_define MKSH_POLL_FOR_PAUSE 1
1160 oswarn="; it has issues"
11601161 : "${MKSH_UNLIMITED=1}${HAVE_GETRUSAGE=0}"
11611162 cpp_define MKSH_UNEMPLOYED 1
11621163 cpp_define MKSH_DISABLE_TTY_WARNING 1
1163 cpp_define MKSH_NO_SIGSETJMP 1
1164 cpp_define _setjmp setjmp
1165 cpp_define _longjmp longjmp
1166 cpp_define MKSH_USABLE_SIGNALFUNC signal
11671164 ;;
11681165 skyos)
11691166 oswarn="; it has minor issues"
11801177 ULTRIX)
11811178 : "${CC=cc -YPOSIX}"
11821179 cpp_define MKSH_TYPEDEF_SSIZE_T int
1183 : "${HAVE_SETLOCALE_CTYPE=0}"
1180 : "${HAVE_POSIX_UTF8_LOCALE=0}"
11841181 ;;
11851182 UnixWare|UNIX_SV)
11861183 # SCO UnixWare
11921189 tsts=" 3<>/dev/tty"
11931190 oswarn="; it will compile, but the target"
11941191 oswarn="$oswarn${nl}platform itself is very flakey/unreliable"
1195 : "${HAVE_SETLOCALE_CTYPE=0}"
1192 : "${HAVE_POSIX_UTF8_LOCALE=0}"
11961193 ;;
11971194 XENIX)
11981195 # mostly when crosscompiling from scosysv
12121209 cpp_define MKSH_NOPROSPECTOFWORK 1
12131210 cpp_define MKSH__NO_SYMLINK 1
12141211 check_categories="$check_categories nosymlink"
1215 : "${HAVE_SETLOCALE_CTYPE=0}"
1212 : "${HAVE_POSIX_UTF8_LOCALE=0}"
12161213 # these are broken
12171214 HAVE_TERMIOS_H=0
12181215 ;;
13391336 ct="clang"
13401337 #elif defined(__NWCC__)
13411338 ct="nwcc"
1339 #elif defined(__GNUC__) && (__GNUC__ < 2)
1340 ct="gcc1"
13421341 #elif defined(__GNUC__)
13431342 ct="gcc"
13441343 #elif defined(_COMPILER_VERSION)
13651364 const char *
13661365 #if defined(__KLIBC__) && !defined(__OS2__)
13671366 et="klibc"
1367 #elif defined(__dietlibc__)
1368 et="dietlibc"
13681369 #else
13691370 et="unknown"
13701371 #endif
14231424 echo >&2 " of this platform. Continue at your own risk,"
14241425 echo >&2 " please report success/failure to the developers."
14251426 ;;
1427 gcc1)
1428 vv '|' "$CC $CFLAGS $Cg $CPPFLAGS $LDFLAGS $NOWARN -v conftest.c $LIBS"
1429 vv '|' 'eval echo "\`$CC $CFLAGS $Cg $CPPFLAGS $LDFLAGS $NOWARN $LIBS -dumpmachine\`" \
1430 "gcc\`$CC $CFLAGS $Cg $CPPFLAGS $LDFLAGS $NOWARN $LIBS -dumpversion\`"'
1431 : "${HAVE_ATTRIBUTE_EXTENSION=0}" # false positive
1432 ;;
14261433 gcc)
14271434 test_z "$Cg" || Cg='-g3 -fno-builtin'
14281435 vv '|' "$CC $CFLAGS $Cg $CPPFLAGS $LDFLAGS $NOWARN -v conftest.c $LIBS"
14601467 own risk, please report success/failure to the developers.'
14611468 ;;
14621469 mipspro)
1470 test_z "$Cg" || Cg='-g3'
14631471 vv '|' "$CC $CFLAGS $Cg $CPPFLAGS $LDFLAGS $NOWARN $LIBS -version"
1472 : "${HAVE_STDINT_H=0}" # broken unless building with __c99
1473 : "${HAVE_ATTRIBUTE_EXTENSION=0}" # skip checking as we know it absent
14641474 ;;
14651475 msc)
14661476 ccpr= # errorlevels are not reliable
15171527 tendra)
15181528 vv '|' "$CC $CFLAGS $Cg $CPPFLAGS $LDFLAGS $NOWARN $LIBS -V 2>&1 | \
15191529 grep -i -e version -e release"
1530 : "${HAVE_ATTRIBUTE_EXTENSION=0}" # false positive
15201531 ;;
15211532 ucode)
15221533 vv '|' "$CC $CFLAGS $Cg $CPPFLAGS $LDFLAGS $NOWARN $LIBS -V"
15561567 ;;
15571568 esac
15581569 etd=" on $et"
1570 # still imake style but… can’t be helped
15591571 case $et in
1572 dietlibc)
1573 # live, BSD, live❣
1574 add_cppflags -D_BSD_SOURCE
1575 # broken
1576 HAVE_POSIX_UTF8_LOCALE=0
1577 ;;
15601578 klibc)
15611579 cpp_define MKSH_NO_SIGSETJMP 1
15621580 cpp_define _setjmp setjmp
17491767 dmc)
17501768 ac_flags 1 decl "${ccpc}-r" 'for strict prototype checks'
17511769 ac_flags 1 schk "${ccpc}-s" 'for stack overflow checking'
1770 ;;
1771 gcc1)
1772 # The following tests run with -Werror (gcc only) if possible
1773 NOWARN=$DOWARN; phase=u
1774 ac_flags 1 wnodeprecateddecls -Wno-deprecated-declarations
1775 # we do not even use CFrustFrust in MirBSD so don’t code in it…
1776 ac_flags 1 no_eh_frame -fno-asynchronous-unwind-tables
1777 ac_flags 1 fnostrictaliasing -fno-strict-aliasing
1778 ac_flags 1 data_abi_align -malign-data=abi
1779 i=1
17521780 ;;
17531781 gcc)
17541782 ac_flags 1 fnolto -fno-lto 'whether we can explicitly disable buggy GCC LTO' -fno-lto
18221850 ;;
18231851 mipspro)
18241852 ac_flags 1 fullwarn -fullwarn 'for remark output support'
1853 # unreachable-from-prevline loop, unused variable, enum vs int @exec.c
1854 # unused parameter, conversion pointer/same-sized integer
1855 ac_flags 1 diagsupp '-diag_suppress 1127,1174,1185,3201,3970' 'to quieten MIPSpro down'
18251856 ;;
18261857 msc)
18271858 ac_flags 1 strpool "${ccpc}/GF" 'if string pooling can be enabled'
19021933 # Compiler: check for stuff that only generates warnings
19031934 #
19041935 ac_test attribute_bounded attribute_extension 0 'for __attribute__((__bounded__))' <<-'EOF'
1905 #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1906 extern int thiswillneverbedefinedIhope(void);
1907 /* force a failure: TenDRA and gcc 1.42 have false positive here */
1908 int main(void) { return (thiswillneverbedefinedIhope()); }
1909 #else
19101936 #include <string.h>
19111937 #undef __attribute__
19121938 int xcopy(const void *, void *, size_t)
19201946 */
19211947 memmove(d, s, n); return ((int)n);
19221948 }
1923 #endif
19241949 EOF
19251950 ac_test attribute_format attribute_extension 0 'for __attribute__((__format__))' <<-'EOF'
1926 #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1927 extern int thiswillneverbedefinedIhope(void);
1928 /* force a failure: TenDRA and gcc 1.42 have false positive here */
1929 int main(void) { return (thiswillneverbedefinedIhope()); }
1930 #else
19311951 #define fprintf printfoo
19321952 #include <stdio.h>
19331953 #undef __attribute__
19351955 extern int fprintf(FILE *, const char *format, ...)
19361956 __attribute__((__format__(__printf__, 2, 3)));
19371957 int main(int ac, char *av[]) { return (fprintf(stderr, "%s%d", *av, ac)); }
1938 #endif
19391958 EOF
19401959 ac_test attribute_noreturn attribute_extension 0 'for __attribute__((__noreturn__))' <<-'EOF'
1941 #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1942 extern int thiswillneverbedefinedIhope(void);
1943 /* force a failure: TenDRA and gcc 1.42 have false positive here */
1944 int main(void) { return (thiswillneverbedefinedIhope()); }
1945 #else
19461960 #include <stdlib.h>
19471961 #undef __attribute__
19481962 void fnord(void) __attribute__((__noreturn__));
19491963 int main(void) { fnord(); }
19501964 void fnord(void) { exit(0); }
1951 #endif
19521965 EOF
19531966 ac_test attribute_pure attribute_extension 0 'for __attribute__((__pure__))' <<-'EOF'
1954 #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1955 extern int thiswillneverbedefinedIhope(void);
1956 /* force a failure: TenDRA and gcc 1.42 have false positive here */
1957 int main(void) { return (thiswillneverbedefinedIhope()); }
1958 #else
19591967 #include <unistd.h>
19601968 #undef __attribute__
19611969 int foo(const char *) __attribute__((__pure__));
19621970 int main(int ac, char *av[]) { return (foo(av[ac - 1]) + isatty(0)); }
19631971 int foo(const char *s) { return ((int)s[0]); }
1964 #endif
19651972 EOF
19661973 ac_test attribute_unused attribute_extension 0 'for __attribute__((__unused__))' <<-'EOF'
1967 #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1968 extern int thiswillneverbedefinedIhope(void);
1969 /* force a failure: TenDRA and gcc 1.42 have false positive here */
1970 int main(void) { return (thiswillneverbedefinedIhope()); }
1971 #else
19721974 #include <unistd.h>
19731975 #undef __attribute__
19741976 int main(int ac __attribute__((__unused__)), char *av[]
19751977 __attribute__((__unused__))) { return (isatty(0)); }
1976 #endif
19771978 EOF
19781979 ac_test attribute_used attribute_extension 0 'for __attribute__((__used__))' <<-'EOF'
1979 #if defined(__TenDRA__) || (defined(__GNUC__) && (__GNUC__ < 2))
1980 extern int thiswillneverbedefinedIhope(void);
1981 /* force a failure: TenDRA and gcc 1.42 have false positive here */
1982 int main(void) { return (thiswillneverbedefinedIhope()); }
1983 #else
19841980 #include <unistd.h>
19851981 #undef __attribute__
19861982 static const char fnord[] __attribute__((__used__)) = "42";
19871983 int main(void) { return (isatty(0)); }
1988 #endif
19891984 EOF
19901985
19911986 # End of tests run with -Werror
20112006 "if mksh will be built without job signals" && \
20122007 check_categories="$check_categories arge nojsig"
20132008 ac_ifcpp 'ifdef MKSH_ASSUME_UTF8' isset_MKSH_ASSUME_UTF8 '' \
2014 'if the default UTF-8 mode is specified' && : "${HAVE_SETLOCALE_CTYPE=0}"
2009 'if the default UTF-8 mode is specified' && : "${HAVE_POSIX_UTF8_LOCALE=0}"
20152010 ac_ifcpp 'if !MKSH_ASSUME_UTF8' isoff_MKSH_ASSUME_UTF8 \
20162011 isset_MKSH_ASSUME_UTF8 0 \
20172012 'if the default UTF-8 mode is disabled' && \
20732068 #
20742069 echo '#include <sys/types.h>
20752070 #include <unistd.h>
2076 /* check that off_t can represent 2^63-1 correctly, thx FSF */
2077 #define LARGE_OFF_T ((((off_t)1 << 31) << 31) - 1 + (((off_t)1 << 31) << 31))
2078 int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 &&
2079 LARGE_OFF_T % 2147483647 == 1) ? 1 : -1];
2080 int main(void) { return (isatty(0)); }' >lft.c
2071 struct ctassert_offt {
2072 off_t min63bits:63;
2073 };
2074 int main(void) { return ((int)sizeof(struct ctassert_offt)); }' >lft.c
20812075 ac_testn can_lfs '' "for large file support" <lft.c
20822076 save_CPPFLAGS=$CPPFLAGS
20832077 add_cppflags -D_FILE_OFFSET_BITS=64
20962090 #
20972091 ac_test can_inttypes '!' stdint_h 1 "for standard 32-bit integer types" <<-'EOF'
20982092 #include <sys/types.h>
2093 #include <limits.h>
20992094 #include <stddef.h>
2100 int main(int ac, char *av[]) { return ((uint32_t)(size_t)*av + (int32_t)ac); }
2101 EOF
2102 ac_test can_ucbints '!' can_inttypes 1 "for UCB 32-bit integer types" <<-'EOF'
2103 #include <sys/types.h>
2104 #include <stddef.h>
2105 int main(int ac, char *av[]) { return ((u_int32_t)(size_t)*av + (int32_t)ac); }
2095 int main(int ac, char *av[]) {
2096 return ((int)((uint32_t)(size_t)*av +
2097 ((int32_t)ac - INT32_MAX)));
2098 }
21062099 EOF
21072100
21082101 # only testn: added later below
21932186 #
21942187 # Environment: errors and signals
21952188 #
2196 test x"NetBSD" = x"$TARGET_OS" && $e Ignore the compatibility warning.
2197
2198 ac_testn sys_errlist '' "the sys_errlist[] array and sys_nerr" <<-'EOF'
2189
2190 HAVE_SOME_ERRLIST=0
2191
2192 ac_test strerrordesc_np '!' some_errlist 0 "GNU strerrordesc_np()" <<-'EOF'
2193 extern const char *strerrordesc_np(int);
2194 int main(int ac, char *av[]) { return (*strerrordesc_np(*av[ac])); }
2195 EOF
2196 test 1 = "$HAVE_STRERRORDESC_NP" && HAVE_SOME_ERRLIST=1
2197
2198 ac_testn sys_errlist '!' some_errlist 0 "the sys_errlist[] array and sys_nerr" <<-'EOF'
21992199 extern const int sys_nerr;
22002200 extern const char * const sys_errlist[];
22012201 extern int isatty(int);
22022202 int main(void) { return (*sys_errlist[sys_nerr - 1] + isatty(0)); }
22032203 EOF
2204 ac_testn _sys_errlist '!' sys_errlist 0 "the _sys_errlist[] array and _sys_nerr" <<-'EOF'
2204 test 1 = "$HAVE_SYS_ERRLIST" && HAVE_SOME_ERRLIST=1
2205
2206 ac_testn _sys_errlist '!' some_errlist 0 "the _sys_errlist[] array and _sys_nerr" <<-'EOF'
22052207 extern const int _sys_nerr;
22062208 extern const char * const _sys_errlist[];
22072209 extern int isatty(int);
22112213 cpp_define sys_nerr _sys_nerr
22122214 cpp_define sys_errlist _sys_errlist
22132215 HAVE_SYS_ERRLIST=1
2214 fi
2216 HAVE_SOME_ERRLIST=1
2217 fi
2218
22152219 ac_cppflags SYS_ERRLIST
22162220
22172221 for what in name list; do
22182222 uwhat=`upper $what`
2219 ac_testn sys_sig$what '' "the sys_sig$what[] array" <<-EOF
2223 eval HAVE_SOME_SIG$uwhat=0
2224
2225 case $what in name) x=sigabbrev_np ;; list) x=sigdescr_np ;; esac
2226 ac_test $x '!' some_sig$what 0 "GNU $x()" <<-EOF
2227 extern const char *$x(int);
2228 int main(int ac, char *av[]) { return (*$x(*av[ac])); }
2229 EOF
2230 test x"1" = x"$fv" && eval HAVE_SOME_SIG$uwhat=1
2231
2232 ac_testn sys_sig$what '!' some_sig$what 0 "the sys_sig$what[] array" <<-EOF
22202233 extern const char * const sys_sig$what[];
22212234 extern int isatty(int);
22222235 int main(void) { return (sys_sig$what[0][0] + isatty(0)); }
22232236 EOF
2224 ac_testn _sys_sig$what '!' sys_sig$what 0 "the _sys_sig$what[] array" <<-EOF
2237 test x"1" = x"$fv" && eval HAVE_SOME_SIG$uwhat=1
2238
2239 ac_testn _sys_sig$what '!' some_sig$what 0 "the _sys_sig$what[] array" <<-EOF
22252240 extern const char * const _sys_sig$what[];
22262241 extern int isatty(int);
22272242 int main(void) { return (_sys_sig$what[0][0] + isatty(0)); }
22282243 EOF
2229 eval uwhat_v=\$HAVE__SYS_SIG$uwhat
2230 if test 1 = "$uwhat_v"; then
2244 if test x"1" = x"$fv"; then
22312245 cpp_define sys_sig$what _sys_sig$what
22322246 eval HAVE_SYS_SIG$uwhat=1
2247 eval HAVE_SOME_SIG$uwhat=1
22332248 fi
22342249 ac_cppflags SYS_SIG$uwhat
22352250 done
23802395 int main(int ac, char *av[]) { return (ac + revoke(av[0])); }
23812396 EOF
23822397
2383 ac_test setlocale_ctype '' 'setlocale(LC_CTYPE, "")' <<-'EOF'
2398 ac_test posix_utf8_locale '' 'for setlocale(LC_CTYPE, "") and nl_langinfo(CODESET)' <<-'EOF'
23842399 #include <locale.h>
2385 #include <stddef.h>
2386 int main(void) { return ((int)(size_t)(void *)setlocale(LC_CTYPE, "")); }
2387 EOF
2388
2389 ac_test langinfo_codeset setlocale_ctype 0 'nl_langinfo(CODESET)' <<-'EOF'
23902400 #include <langinfo.h>
2391 #include <stddef.h>
2392 int main(void) { return ((int)(size_t)(void *)nl_langinfo(CODESET)); }
2401 int main(void) { return (!setlocale(LC_CTYPE, "") || !nl_langinfo(CODESET)); }
2402 EOF
2403
2404 $ebcdic && ac_test setlocale_lcall <<-'EOF'
2405 #include <locale.h>
2406 int main(void) { return (!setlocale(LC_ALL, "")); }
23932407 EOF
23942408
23952409 ac_test select <<-'EOF'
24892503 fi
24902504 fi
24912505
2492 ac_test strerror '!' sys_errlist 0 <<-'EOF'
2506 ac_test strerror '!' some_errlist 0 <<-'EOF'
24932507 extern char *strerror(int);
24942508 int main(int ac, char *av[]) { return (*strerror(*av[ac])); }
24952509 EOF
24962510
2497 ac_test strsignal '!' sys_siglist 0 <<-'EOF'
2511 ac_test strsignal '!' some_siglist 0 <<-'EOF'
24982512 #include <string.h>
24992513 #include <signal.h>
25002514 int main(void) { return (strsignal(1)[0]); }
25842598 #ifndef CHAR_BIT
25852599 #define CHAR_BIT 0
25862600 #endif
2587 struct ctasserts {
2588 #define cta(name,assertion) char name[(assertion) ? 1 : -1]
2589 cta(char_is_8_bits, (CHAR_BIT) == 8);
2590 cta(long_is_32_bits, sizeof(long) == 4);
2601 mbiCTAS(conftest) {
2602 mbiCTA(char_is_8_bits, (CHAR_BIT) == 8);
2603 mbiCTA(long_is_4_chars, sizeof(long) == 4);
2604 mbiCTA(ulong_is_32_bits, mbiTYPE_UBITS(unsigned long) == 32U);
2605 mbiCTA(slong_is_31_bits, mbiMASK_BITS(LONG_MAX) == 31U);
25912606 };
2592 int main(void) { return (sizeof(struct ctasserts)); }
2607 int main(void) { return (sizeof(struct ctassert_conftest)); }
25932608 EOF
25942609
25952610 ac_test long_64bit '!' long_32bit 0 'whether long is 64 bit wide' <<-'EOF'
25982613 #ifndef CHAR_BIT
25992614 #define CHAR_BIT 0
26002615 #endif
2601 struct ctasserts {
2602 #define cta(name,assertion) char name[(assertion) ? 1 : -1]
2603 cta(char_is_8_bits, (CHAR_BIT) == 8);
2604 cta(long_is_64_bits, sizeof(long) == 8);
2616 mbiCTAS(conftest) {
2617 mbiCTA(char_is_8_bits, (CHAR_BIT) == 8);
2618 mbiCTA(long_is_8_chars, sizeof(long) == 8);
2619 mbiCTA(ulong_is_64_bits, mbiTYPE_UBITS(unsigned long) == 64U);
2620 mbiCTA(slong_is_63_bits, mbiMASK_BITS(LONG_MAX) == 63U);
26052621 };
2606 int main(void) { return (sizeof(struct ctasserts)); }
2622 int main(void) { return (sizeof(struct ctassert_conftest)); }
26072623 EOF
26082624
26092625 case $HAVE_LONG_32BIT$HAVE_LONG_64BIT in
26162632 #
26172633 # Compiler: Praeprocessor (only if needed)
26182634 #
2619 test 0 = $HAVE_SYS_SIGNAME && if ac_testinit cpp_dd '' \
2635 test 0 = $HAVE_SOME_SIGNAME && if ac_testinit cpp_dd '' \
26202636 'checking if the C Preprocessor supports -dD'; then
26212637 echo '#define foo bar' >conftest.c
26222638 vv ']' "$CPP $CFLAGS $Cg $CPPFLAGS $NOWARN -dD conftest.c >x"
26372653 check_categories="$check_categories $oldish_ed"
26382654 rmf x vv.out
26392655
2640 if test 0 = $HAVE_SYS_SIGNAME; then
2656 if test 0 = $HAVE_SOME_SIGNAME; then
26412657 if test 1 = $HAVE_CPP_DD; then
26422658 $e Generating list of signal names...
26432659 else
29082924 echo "test -f \$tcfn || exit 1; $SIZE \$tcfn" >>Rebuild.sh
29092925 if test $cm = makefile; then
29102926 extras='emacsfn.h exprtok.h rlimits.opt sh.h sh_flags.opt ulimits.opt var_spec.h'
2911 test 0 = $HAVE_SYS_SIGNAME && extras="$extras signames.inc"
2927 test 0 = $HAVE_SOME_SIGNAME && extras="$extras signames.inc"
29122928 gens= genq=
29132929 for file in $optfiles; do
29142930 genf=`basename "$file" | sed 's/.opt$/.gen/'`
0 # $MirOS: src/bin/mksh/check.t,v 1.883 2021/10/10 21:33:50 tg Exp $
0 # $MirOS: src/bin/mksh/check.t,v 1.892 2022/01/28 10:28:14 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 2021/10/15
33 KSH R59 2022/01/27
3434 description:
3535 Check base version of full shell
3636 stdin:
440440 expected-stderr:
441441 1
442442 ---
443 name: arith-divnull
444 description:
445 Check what happens if dividing by 0
446 stdin:
447 echo 1 $((0 ? 2/0 : 666)) .
448 echo 2 $?
449 echo 3 $((1 ? 2/0 : 666)) .
450 echo 4 $?
451 expected-stdout:
452 1 666 .
453 2 0
454 expected-exit: e != 0
455 expected-stderr-pattern:
456 /^[^\n]*: zero divisor$/
457 ---
443458 name: arith-lazy-1
444459 description:
445460 Check that only one side of ternary operator is evaluated
611626 name: arith-div-intmin-by-minusone
612627 description:
613628 Check division overflow wraps around silently
614 category: int:32
629 category: shell:legacy-no
615630 stdin:
616631 echo signed:$((-2147483648 / -1))r$((-2147483648 % -1)).
617632 echo unsigned:$((# -2147483648 / -1))r$((# -2147483648 % -1)).
618633 expected-stdout:
619634 signed:-2147483648r0.
620635 unsigned:0r2147483648.
621 ---
622 name: arith-div-intmin-by-minusone-64
623 description:
624 Check division overflow wraps around silently
625 category: int:64
626 stdin:
627 echo signed:$((-9223372036854775808 / -1))r$((-9223372036854775808 % -1)).
628 echo unsigned:$((# -9223372036854775808 / -1))r$((# -9223372036854775808 % -1)).
629 expected-stdout:
630 signed:-9223372036854775808r0.
631 unsigned:0r9223372036854775808.
632636 ---
633637 name: arith-assop-assoc-1
634638 description:
14921496 XXX=_
14931497 PS1=X
14941498 false && echo hmmm
1495 need-ctty: yes
14961499 arguments: !-i!
14971500 stdin:
14981501 echo hi${XXX}there
14991502 expected-stdout:
15001503 hi_there
1501 expected-stderr: !
1502 XX
1504 expected-stderr-pattern:
1505 /^(?:W: [^\n]*(?:find tty fd|have full job control)[^\n]*\n)*XX$/
15031506 ---
15041507 name: expand-ugly
15051508 description:
50815084 Syntax errors in expressions and effects on bases
50825085 (interactive so errors don't cause exits)
50835086 (ksh88 fails this test - shell exits, even with -i)
5084 need-ctty: yes
50855087 arguments: !-i!
50865088 stdin:
50875089 PS1= # minimise prompt hassles
50925094 typeset -i2 a=2+
50935095 echo $a
50945096 expected-stderr-pattern:
5095 /^([#\$] )?.*:.*2+.*\n.*:.*2+.*\n$/
5097 /^(?:W: [^\n]*(?:find tty fd|have full job control)[^\n]*\n)*([#\$] )?.*:.*2\+.*\n.*:.*2\+.*\n$/
50965098 expected-stdout:
50975099 4#22
50985100 4#22
55985600 echo =1
55995601 trap "echo trap 2 executed" UNKNOWNSIGNAL EXIT 999999 FNORD
56005602 echo = $?
5601 ) 2>&1 | sed "s^${__progname%.exe}\.*e*x*e*: <stdin>\[[0-9]*]PROG"
5602 expected-stdout:
5603 PROG: trap: bad signal 'UNKNOWNSIGNAL'
5603 ) 2>&1 | sed \
5604 -e "s^${__progname%.exe}\.*e*x*e*: <stdin>\[[0-9]*]PROG" \
5605 -e "s^[EW]: ${__progname%.exe}\.*e*x*e*: <stdin>\[[0-9]*]PROG" \
5606 -e "s/bad signal '\\(.*\\)'\$/bad signal: \\1/"
5607 expected-stdout:
5608 PROG: trap: bad signal: UNKNOWNSIGNAL
56045609 foo
56055610 =1
5606 PROG: trap: bad signal 'UNKNOWNSIGNAL'
5607 PROG: trap: bad signal '999999'
5608 PROG: trap: bad signal 'FNORD'
5611 PROG: trap: bad signal: UNKNOWNSIGNAL
5612 PROG: trap: bad signal: 999999
5613 PROG: trap: bad signal: FNORD
56095614 = 1
56105615 trap 2 executed
56115616 ---
63396344 ---
63406345 name: regression-42
63416346 description:
6342 Can't use command line assignments to assign readonly parameters.
6347 Can't use command line assignments to assign read-only parameters.
63436348 stdin:
63446349 print '#!'"$__progname"'\nunset RANDOM\nexport | while IFS= read -r' \
63456350 'RANDOM; do eval '\''print -r -- "$RANDOM=$'\''"$RANDOM"'\'\"\'\; \
69766981 echo 1 $(( a ^<= 1 )) , $(( b ^<= 1 )) .
69776982 echo 2 $(( a ^>= 2 )) , $(( b ^>= 2 )) .
69786983 echo 3 $(( 5 ^< 1 )) .
6979 echo 4 $(( 5 ^> 1 )) .
6984 echo 4 $(( 5 ^> 1 )) , $((# 5 ^> 1 )) .
69806985 expected-stdout:
69816986 1 10 , 11 .
69826987 2 -2147483646 , -1073741822 .
69836988 3 10 .
6984 4 -2147483646 .
6989 4 -2147483646 , 2147483650 .
69856990 ---
69866991 name: export-1
69876992 description:
75437548 description:
75447549 Check special names are output correctly
75457550 stdin:
7551 prgsub() {
7552 sed \
7553 -e "s^${__progname%.exe}\.*e*x*e*: PROG: " \
7554 -e "s^[EW]: ${__progname%.exe}\.*e*x*e*: PROG: " \
7555 -e 's/^qmark_foo: /E: &/' \
7556 -e "s/^/$1: /g"
7557 }
75467558 doit() {
75477559 "$__progname" -c "$@" >o1 2>o2
75487560 rv=$?
75497561 echo RETVAL: $rv
7550 sed -e "s^${__progname%.exe}\.*e*x*e*: PROG: " -e 's/^/STDOUT: /g' <o1
7551 sed -e "s^${__progname%.exe}\.*e*x*e*: PROG: " -e 's/^/STDERR: /g' <o2
7562 prgsub STDOUT <o1
7563 prgsub STDERR <o2
75527564 }
75537565 doit 'echo ${1x}'
75547566 doit 'echo "${1x}"'
75557567 doit 'echo ${1?}'
75567568 doit 'echo ${19?}'
75577569 doit 'echo ${!:?}'
7558 doit -u 'echo ${*:?}' foo ""
7570 doit -u 'echo ${*:?}' qmark_foo ""
75597571 expected-stdout:
75607572 RETVAL: 1
75617573 STDERR: PROG: ${1x}: bad substitution
75687580 RETVAL: 1
75697581 STDERR: PROG: !: parameter null or not set
75707582 RETVAL: 1
7571 STDERR: foo: ${*:?}: bad substitution
7583 STDERR: E: qmark_foo: ${*:?}: bad substitution
75727584 ---
75737585 name: xxx-param-_-1
75747586 # fails due to weirdness of execv stuff
80568068 Check that ERR and EXIT traps are run just like GNU bash does.
80578069 ksh93 runs ERtrap after “parameter null or not set” (which mksh
80588070 used to do) but (bug) continues “and out”, exit 0, in +e eval-undef.
8059 file-setup: file 644 "x"
8071 file-setup: file 644 "xe"
80608072 v=; unset v
80618073 trap 'echo EXtrap' EXIT
80628074 trap 'echo ERtrap' ERR
80978109 ) 2>&1 | sed \
80988110 -e 's/parameter not set/parameter null or not set/' \
80998111 -e 's/[[]6]//' -e 's/: eval: line 1//' -e 's/: line 6//' \
8112 -e 's/^x[etfu]: /E: &/' \
81008113 -e "s^${__progname%.exe}\.*e*x*e*: <stdin>\[[0-9]*]PROG"
81018114 }
81028115 xe=-e
81038116 echo : $xe
8104 runtest x $xe true
8117 runtest xe $xe true
81058118 echo = eval-true $(<rc) .
8106 runtest x $xe false
8119 runtest xe $xe false
81078120 echo = eval-false $(<rc) .
8108 runtest x $xe '${v?}'
8121 runtest xe $xe '${v?}'
81098122 echo = eval-undef $(<rc) .
81108123 runtest xt $xe
81118124 echo = noeval-true $(<rc) .
81158128 echo = noeval-undef $(<rc) .
81168129 xe=+e
81178130 echo : $xe
8118 runtest x $xe true
8131 runtest xe $xe true
81198132 echo = eval-true $(<rc) .
8120 runtest x $xe false
8133 runtest xe $xe false
81218134 echo = eval-false $(<rc) .
8122 runtest x $xe '${v?}'
8135 runtest xe $xe '${v?}'
81238136 echo = eval-undef $(<rc) .
81248137 runtest xt $xe
81258138 echo = noeval-true $(<rc) .
81388151 EXtrap
81398152 = eval-false 1 .
81408153 and run ${v?}
8141 x: v: parameter null or not set
8154 E: xe: v: parameter null or not set
81428155 EXtrap
81438156 = eval-undef 1 .
81448157 and run true
81508163 EXtrap
81518164 = noeval-false 1 .
81528165 and run ${v?}
8153 xu: v: parameter null or not set
8166 E: xu: v: parameter null or not set
81548167 EXtrap
81558168 = noeval-undef 1 .
81568169 : +e
81658178 EXtrap
81668179 = eval-false 0 .
81678180 and run ${v?}
8168 x: v: parameter null or not set
8181 E: xe: v: parameter null or not set
81698182 EXtrap
81708183 = eval-undef 1 .
81718184 and run true
81788191 EXtrap
81798192 = noeval-false 0 .
81808193 and run ${v?}
8181 xu: v: parameter null or not set
8194 E: xu: v: parameter null or not set
81828195 EXtrap
81838196 = noeval-undef 1 .
81848197 ---
90569069 name: utf8opt-2
90579070 description:
90589071 Check that the utf8-mode flag is set at interactive startup.
9059 If your OS is old, try passing HAVE_SETLOCALE_CTYPE=0 to Build.sh
9072 If your OS is old and fails this, contact the mksh developer.
90609073 need-pass: no
90619074 category: !noutf8
90629075 need-ctty: yes
1005610069 unset baz
1005710070 print ${foo@#} ${bar@#} ${baz@#} .
1005810071 expected-stdout:
10059 9B15FBFB CFBDD32B 00000000 .
10072 D2F7C7B5 FE93FA63 03010102 .
1006010073 ---
1006110074 name: varexpand-special-hash-ebcdic
1006210075 description:
1006810081 unset baz
1006910082 print ${foo@#} ${bar@#} ${baz@#} .
1007010083 expected-stdout:
10071 016AE33D 9769C4AF 00000000 .
10084 7819D62A E1FC0712 00000000 .
1007210085 ---
1007310086 name: varexpand-special-quote
1007410087 description:
1137611389 expected-stdout:
1137711390 ===
1137811391 mir
11379 expected-stderr-pattern: /.*: can't (create|overwrite) .*/
11392 expected-stderr-pattern: /.*: foo: (create: |cannot overwrite existing file).*/
1138011393 ---
1138111394 name: bashiop-3b
1138211395 description:
1311513128 echo =14
1311613129 (mypid=$$; try mypid)
1311713130 echo =15
13118 ) 2>&1 | sed -e 's/^[A-Za-z]://' -e 's/^[^]]*]//' -e 's/^[^:]*: *//'
13131 ) 2>&1 | sed \
13132 -e "s^${__progname%.exe}\.*e*x*e*: <stdin>\[[0-9]*]PROGl" \
13133 -e "s^[EW]: ${__progname%.exe}\.*e*x*e*: <stdin>\[[0-9]*]PROGl" \
13134 -e "s^${__progname%.exe}\.*e*x*e*: PROGn: " \
13135 -e "s^[EW]: ${__progname%.exe}\.*e*x*e*: PROGn: "
1311913136 exit ${PIPESTATUS[0]}
1312013137 expected-stdout:
1312113138 y
1312213139 =1
13123 y: parameter not set
13140 PROGl: y: parameter not set
1312413141 =2
1312513142 x=nz
1312613143 =3
13127 y: parameter not set
13144 PROGn: y: parameter not set
1312813145 =4
1312913146 0=nz
1313013147 =5
13131 2: parameter not set
13148 PROGn: 2: parameter not set
1313213149 =6
13133 1: parameter not set
13150 PROGl: 1: parameter not set
1313413151 =7
1313513152 at=
1313613153 =8
1313813155 =9
1313913156 0
1314013157 =10
13141 !: parameter not set
13158 PROGl: !: parameter not set
1314213159 =11
1314313160 ush
1314413161 =12
1405214069 [[ -o utf8-mode ]]; local u=$?
1405314070 set +U
1405414071 local c s="$*" t=
14055 [[ -n $s ]] || { s=$(cat;print x); s=${s%x}; }
14072 [[ -n $s ]] || { s=$(cat;print .); s=${s%.}; }
1405614073 local -i i=0 n=${#s} p=0 v x
1405714074 local -i16 o
1405814075
00 mksh (59c-15) unstable; urgency=medium
11
22 * Require usable libklibc-dev (cf. #1004465)
3
4 -- Thorsten Glaser <tg@mirbsd.de> Fri, 28 Jan 2022 05:17:28 +0100
3 * Update to CVS HEAD:
4 - [tg, Redfoxmoon] Fixes for the MIPSpro compiler
5 - [tg] Clean up the pre-initio() codepaths
6 - [tg] Advance less-UB-y arithmetics project: shf_vfprintf et al.
7 - [tg] Overhaul error reporting functions avoiding some name doubling
8 - [tg] Fix if FCEDIT when TMPDIR contains whitespace
9 - [tg] Tighten locale and charset checks
10 - [tg] Handle gracefully users doing integer EPOCHREALTIME=
11 - [tg] Fix newer GCC warning on compile-time asserts
12 - [tg] Support GNU strerrordesc_np(3) replacement for _sys_errlist[]
13 - [tg] Better configure-time detection (TenDRA, dietlibc, …)
14 - [tg] Fix possible setsid(2) failure in chvt code by always forking,
15 with waiting if !, and communicate child process errors back
16 - [tg] Change some more numbers to unsigned, signed is evil in C
17 - [tg] Improve flags documentation, also fixes Debian #999706
18 - [tg] Clear nonblocking flag on entry for FIFOs as well, as POSIX says
19 - [komh, tg] Fix termio chvt flushing and link to Ilya Zakharevich’s
20 docs why no shell can use termios(4) on OS/2
21 - [tg] Introduce k32 type and arithmetics, used in hash, indicēs, …
22 - [tg] Add explicit masking for 8-bit to KBY and KBI macros
23 - [tg] Change remaining users off stdint.h types, except old arith
24 - [tg, bwh] Limit object size to the smaller of (size_t)PTRDIFF_MAX and
25 SIZE_MAX, so byte representation pointer offsets cannot cause UB
26 - [tg] PRNG improvements: track traps and history input
27 - [tg] Limit variable name length to INT_MAX-X_EXTRA to guarantee export
28 - [tg] Update portability glue for manpage
29 - [tg] Document local array howto and behaviour in the FAQ
30 - [tg] Fix missing backslash in posix-mode FAQ locale example code
31 - [tg] Change short hash from BAFH0-1 to BAFH1-0 (faster at no loss)
32 - [tg] Improve UB-safe type property detection and arithmetics; switch
33 more parts of lksh to UB-y (POSIXly “correct” though…) arithmetics
34 - [tg] Support GNU sigdescr_np(3) replacement for _sys_siglist[] and
35 sigabbrev_np(3) for _sys_signame[] (avoid glibc regression)
36 - [RT] Port to SerenityOS
37 * debian/printf.c: Update from MirBSD CVS to support new warning framework
38 * Sync debian/copyright accordingly
39
40 -- Thorsten Glaser <tg@mirbsd.de> Sun, 30 Jan 2022 18:02:53 +0100
541
642 mksh (59c-14) unstable; urgency=low
743
2424 The MirBSD Korn Shell (mksh) is
2525 Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2626 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
27 2020, 2021
27 2020, 2021, 2022
2828 mirabilos <m@mirbsd.org>
2929 Copyright (c) 2015, 2017, 2020
3030 KO Myung-Hun <komh@chollian.net>
7676
7777
7878 printf.c is
79 Copyright (c) 2005, 2009, 2010, 2011, 2012, 2020, 2021
80 mirabilos <m@mirbsd.org>
7981 Copyright (c) 1989
8082 The Regents of the University of California.
8183 All rights reserved.
11
22 /*-
33 * Copyright (c) 1989 The Regents of the University of California.
4 * Copyright (c) 2005, 2009, 2010, 2011, 2012, 2020, 2021
5 * mirabilos <m@mirbsd.org>
46 * All rights reserved.
57 *
68 * Redistribution and use in source and binary forms, with or without
4648 #define vstrchr strchr
4749 #endif
4850
49 __RCSID("$MirOS: src/usr.bin/printf/printf.c,v 1.21 2020/01/22 01:57:44 tg Exp $");
51 __RCSID("$MirOS: src/usr.bin/printf/printf.c,v 1.24 2021/11/21 03:47:51 tg Exp $");
5052
5153 static int print_escape_str(const char *);
5254 static int print_escape(const char *);
7375 static void s_prt(int);
7476
7577 static const char *s_ptr;
76
77 #define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
78 #endif
79
78 #else
8079 #define isodigit(c) ((c) >= '0' && (c) <= '7')
8180 #define octtobin(c) ((c) - '0')
8281 #define hextobin(c) ((c) >= 'A' && (c) <= 'F' ? c - 'A' + 10 : (c) >= 'a' && (c) <= 'f' ? c - 'a' + 10 : c - '0')
82 #endif
8383
8484 #define PF(f, func) do { \
8585 if (fieldwidth) \
9797 #define vstrchr strchr
9898 #endif
9999
100 #ifndef cstrerror
101 #define cstrerror(e) ((const char *)strerror(e))
102 #endif
103
104100 #ifdef MKSH_PRINTF_BUILTIN
105101 #define ufprintf shf_fprintf
106102 #define uprintf shprintf
107 #define uputc(c) shf_putchar((c), shl_stdout)
103 #define uputc(c) shf_putc((c), shl_stdout)
108104 #define ustderr shl_out
109 #define uwarnx warningf
110 #define UWARNX false,
105 #define uwarn1 kwarnf
106 #define UWARN1 (KWF_WARNING | KWF_PREFIX | KWF_FILELINE | \
107 KWF_BUILTIN | KWF_ONEMSG),
108 #define uwarnx kwarnf0
109 #define UWARNX (KWF_WARNING | KWF_PREFIX | KWF_FILELINE | \
110 KWF_BUILTIN | KWF_NOERRNO),
111111
112112 int
113113 c_printf(const char **wp)
139139 #define uprintf printf
140140 #define uputc putchar
141141 #define ustderr stderr
142 #define uwarn1 warn
143 #define UWARN1 "%s",
142144 #define uwarnx warnx
143145 #define UWARNX /* nothing */
144146
422424 value <<= 4;
423425 value += hextobin(*str);
424426 }
425 if (value > UCHAR_MAX) {
427 if ((unsigned int)value > (unsigned int)UCHAR_MAX) {
426428 uwarnx(UWARNX "escape sequence out of range for character");
427429 rval = 1;
428430 }
608610 uwarnx(UWARNX "%s: not completely converted", s);
609611 rval = 1;
610612 } else if (errno == ERANGE) {
611 uwarnx(UWARNX "%s: %s", s, cstrerror(ERANGE));
613 uwarn1(UWARN1 s);
612614 rval = 1;
613615 }
614616 }
636638 static void
637639 s_prt(int c)
638640 {
639 char ts[4];
640
641 if ((unsigned int)c < 0x100) {
642 ts[0] = c;
643 c = 1;
644 } else
641 if ((unsigned int)c < 0x100)
642 shf_putc((char)c, shl_stdout);
643 else {
644 char ts[5];
645
645646 c = (int)utf_wctomb(ts, c - 0x100);
646
647 shf_write(ts, c, shl_stdout);
648 }
649 #endif
647 shf_write(ts, c, shl_stdout);
648 }
649 }
650 #endif
00 # $Id$
1 # $MirOS: src/bin/mksh/dot.mkshrc,v 1.136 2021/01/24 20:38:30 tg Exp $
1 # $MirOS: src/bin/mksh/dot.mkshrc,v 1.139 2022/01/26 13:02:35 tg Exp $
22 #-
33 # Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010,
44 # 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
5 # 2020, 2021
5 # 2020, 2021, 2022
66 # mirabilos <m@mirbsd.org>
77 #
88 # Provided that these terms and disclaimer and all copyright notices
4848 \cat "$@" | "$fn"
4949 fi
5050 }
51 function _dot_mkshrc_cat_for_readN {
52 \\builtin typeset fn=$1
51 function _dot_mkshrc_cat_for_readNa {
52 \\builtin typeset fn=$1 s
5353 \\builtin shift
5454
5555 if (( $# )); then
56 \\builtin print -nr -- "$*" | "$fn"
56 \\builtin read -raN-1 s <<<"$*" || \\builtin return $?
57 \\builtin unset s[${#s[*]}-1]
5758 elif [[ -t 0 ]]; then
58 \cat | "$fn"
59 s=$(\cat || \builtin exit $?; \\builtin print .) || \
60 \\builtin return $?
61 \\builtin read -raN-1 s <<<"$s" || \\builtin return $?
62 \\builtin unset s[${#s[*]}-1]
63 \\builtin unset s[${#s[*]}-1]
5964 else
60 "$fn"
61 fi
65 \\builtin read -raN-1 s || \\builtin return $?
66 fi
67 "$fn"
6268 }
6369
6470 # pager (not control character safe)
376382 if (( $# )); then
377383 s="$*"
378384 elif [[ -t 0 ]]; then
379 s=$(\cat || \\builtin exit $?; \\builtin print x) || \
385 s=$(\cat || \\builtin exit $?; \\builtin print .) || \
380386 \\builtin return $?
381 s=${s%x}
387 s=${s%.}
382388 else
383389 \\builtin read -rN-1 s || \\builtin return $?
384390 fi
413419 \\builtin print -n -- "$t"
414420 }
415421 function Lb64encode {
416 \_dot_mkshrc_cat_for_readN _dot_mkshrc_b64encode "$@"
422 \\builtin set +U
423 \_dot_mkshrc_cat_for_readNa _dot_mkshrc_b64encode "$@"
417424 }
418425 function _dot_mkshrc_b64encode {
419 \\builtin set +Ue
420 \\builtin typeset c s t table
426 \\builtin set +e
427 \\builtin typeset c t table
421428 \\builtin set -A table -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
422429 a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
423 \\builtin read -raN-1 s || \\builtin return $?
424430 \\builtin typeset -i i=0 n=${#s[*]} v
425431
426432 while (( i < n )); do
444450 \:
445451 }
446452
447 # Better Avalanche for the Jenkins Hash
453 # Better Avalanche for the Jenkins Hash, IV=1 INC=0
448454 \\builtin typeset -Z11 -Uui16 Lbafh_v
449455 function Lbafh_init {
450 Lbafh_v=0
456 Lbafh_v=1
451457 }
452458 function Lbafh_add {
453 \_dot_mkshrc_cat_for_readN _dot_mkshrc_bafh_add "$@"
459 \\builtin set +U
460 \_dot_mkshrc_cat_for_readNa _dot_mkshrc_bafh_add "$@"
454461 }
455462 function _dot_mkshrc_bafh_add {
456 \\builtin set +Ue
457 \\builtin typeset s
458 \\builtin read -raN-1 s || \\builtin return $?
463 \\builtin set +e
459464 \\builtin typeset -i i=0 n=${#s[*]}
460465
461466 while (( i < n )); do
462 ((# Lbafh_v = (Lbafh_v + s[i++] + 1) * 1025 ))
467 ((# Lbafh_v = (Lbafh_v + s[i++]) * 1025 ))
463468 ((# Lbafh_v ^= Lbafh_v >> 6 ))
464469 done
465470 \:
55 /*-
66 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
77 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
8 * 2019, 2020, 2021
8 * 2019, 2020, 2021, 2022
99 * mirabilos <m@mirbsd.org>
1010 *
1111 * Provided that these terms and disclaimer and all copyright notices
2828
2929 #ifndef MKSH_NO_CMDLINE_EDITING
3030
31 __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.392 2021/10/16 01:28:05 tg Exp $");
31 __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.397 2022/01/06 22:34:53 tg Exp $");
3232
3333 /*
3434 * in later versions we might use libtermcap for this, but since external
418418 source = s;
419419 if (yylex(ONEWORD | LQCHAR) != LWORD) {
420420 source = sold;
421 internal_warningf(Tfg_badsubst);
421 kwarnf(KWF_INTERNAL | KWF_WARNING | KWF_ONEMSG | KWF_NOERRNO,
422 Tfg_badsubst);
422423 nwords = 0;
423424 goto out;
424425 }
10581059
10591060 static int x_ins(const void *);
10601061 static void x_delete(size_t, bool);
1061 static void x_bword(uint32_t, bool);
1062 static void x_fword(uint32_t, bool);
1062 static void x_bword(kui, bool);
1063 static void x_fword(kui, bool);
10631064 static void x_goto(char *);
10641065 static void x_bs3(char **);
10651066 static void x_uescs(char *);
10781079 static void x_e_putb(int);
10791080 static void x_e_puts(const char *);
10801081 #ifndef MKSH_SMALL
1081 static int x_fold_case(int, uint32_t);
1082 static int x_fold_case(int, kui);
10821083 #endif
10831084 static char *x_lastcp(void);
10841085 static void x_lastpos(void);
16641665 #endif
16651666
16661667 static void
1667 x_bword(uint32_t separator, bool erase)
1668 x_bword(kui separator, bool erase)
16681669 {
16691670 size_t nb = 0;
16701671 char *cp = xcp;
16891690 }
16901691
16911692 static void
1692 x_fword(uint32_t separator, bool erase)
1693 x_fword(kui separator, bool erase)
16931694 {
16941695 char *cp = xcp;
16951696
23672368 if ((x_last_command != XFUNC_yank && x_last_command != XFUNC_meta_yank) ||
23682369 killstack[killtp] == 0) {
23692370 killtp = killsp;
2370 x_e_puts("\nyank something first");
2371 x_e_puts(Tyankfirst);
23712372 x_redraw('\n');
23722373 return (KSTD);
23732374 }
26342635 x_bind(const char *s SMALLP(bool macro))
26352636 {
26362637 register kui t;
2637 struct x_bind_getc state = { s, 0 };
2638 struct x_bind_getc state;
26382639 kui c, key, prefix;
26392640 #ifndef MKSH_SMALL
26402641 bool hastilde = false;
26412642 char *ms = NULL;
26422643 #endif
26432644
2645 state.cp = s;
2646 state.next = 0;
26442647 prefix = 0;
26452648 c = x_bind_getc(&state);
26462649 if (!c || c == ORD('=')) {
33683371 * None
33693372 */
33703373 static int
3371 x_fold_case(int c, uint32_t separator)
3374 x_fold_case(int c, kui separator)
33723375 {
33733376 char *cp = xcp;
33743377
40734076 case 0:
40744077 if (insert != 0) {
40754078 if (lastcmd[0] == 's' ||
4076 ksh_eq(lastcmd[0], 'C', 'c')) {
4079 isCh(lastcmd[0], 'C', 'c')) {
40774080 if (redo_insert(1) != 0)
40784081 vi_error();
40794082 } else {
42024205 lastcmd[0] = 'a';
42034206 lastac = 1;
42044207 }
4205 if (lastcmd[0] == 's' || ksh_eq(lastcmd[0], 'C', 'c'))
4208 if (lastcmd[0] == 's' || isCh(lastcmd[0], 'C', 'c'))
42064209 return (redo_insert(0));
42074210 else
42084211 return (redo_insert(lastac - 1));
43624365 else {
43634366 if ((ncursor = domove(argcnt, &cmd[1], 1)) < 0)
43644367 return (-1);
4365 if (*cmd == 'c' && ksh_eq(cmd[1], 'W', 'w') &&
4368 if (*cmd == 'c' && isCh(cmd[1], 'W', 'w') &&
43664369 !ctype(vs->cbuf[vs->cursor], C_SPACE)) {
43674370 do {
43684371 --ncursor;
47934796 case ORD(';'):
47944797 if (fsavecmd == ORD(' '))
47954798 return (-1);
4796 i = ksh_eq(fsavecmd, 'F', 'f');
4799 i = isCh(fsavecmd, 'F', 'f');
47974800 t = rtt2asc(fsavecmd) > rtt2asc('a');
47984801 if (*cmd == ',')
47994802 t = !t;
52085211 }
52095212 (void)histnum(n);
52105213 if ((hptr = *histpos()) == NULL) {
5211 internal_warningf("grabhist: bad history array");
5214 kwarnf(KWF_INTERNAL | KWF_WARNING | KWF_ONEMSG | KWF_NOERRNO,
5215 "grabhist: bad history array");
52125216 return (-1);
52135217 }
52145218 if (save)
2323
2424 #include "sh.h"
2525
26 __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.243 2021/10/10 21:36:52 tg Exp $");
26 __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.247 2021/11/21 04:15:00 tg Exp $");
2727
2828 /*
2929 * string expansion
131131 s->start = s->str = cp;
132132 source = s;
133133 if (yylex(ONEWORD) != LWORD)
134 internal_errorf(Tbadsubst);
134 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_ONEMSG | KWF_NOERRNO,
135 Tbadsubst);
135136 source = sold;
136137 afree(s, ATEMP);
137138 return (evalstr(yylval.cp, f));
254255 char *cp;
255256
256257 if (ccp == NULL)
257 internal_errorf("expand(NULL)");
258 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_ONEMSG | KWF_NOERRNO,
259 "expand(NULL)");
258260 /* for alias, readonly, set, typeset commands */
259261 if ((f & DOVACHECK) && is_wdvarassign(ccp)) {
260262 f &= ~(DOVACHECK | DOBLANK | DOGLOB | DOTILDE);
405407 *end = EOS;
406408 str = snptreef(NULL, 64, Tf_S, beg);
407409 afree(beg, ATEMP);
408 errorf(Tf_sD_s, str, Tbadsubst);
410 kerrf(KWF_ERR(1) | KWF_PREFIX |
411 KWF_FILELINE | KWF_TWOMSG |
412 KWF_NOERRNO, str, Tbadsubst);
409413 }
410414 if (f & DOBLANK)
411415 doblank++;
704708 break;
705709 case ORD('?'):
706710 if (*sp == CSUBST)
707 errorf("%s: parameter null or not set",
708 st->var->name);
711 kerrf(KWF_ERR(1) | KWF_PREFIX |
712 KWF_FILELINE | KWF_TWOMSG |
713 KWF_NOERRNO, st->var->name,
714 "parameter null or not set");
709715 f &= ~DOBLANK;
710716 f |= DOTEMP;
711717 /* FALLTHROUGH */
786792 * in AT&T ksh.
787793 */
788794 /*
789 * XXX POSIX says readonly is only
795 * XXX POSIX says read-only is only
790796 * fatal for special builtins (setstr
791 * does readonly check).
797 * does read-only check).
792798 */
793799 len = strlen(dp) + 1;
794800 setstr(st->var,
804810 case ORD('?'):
805811 dp = Xrestpos(ds, dp, st->base);
806812
807 errorf(Tf_sD_s, st->var->name,
813 kerrf(KWF_ERR(1) | KWF_PREFIX |
814 KWF_FILELINE | KWF_TWOMSG |
815 KWF_NOERRNO, st->var->name,
808816 debunk(dp, dp, strlen(dp) + 1));
809817 break;
810818 case ORD('#') | STYPE_AT:
13191327 }
13201328 xp->var = global(sp);
13211329 /* use saved p from above */
1322 xp->str = p ? shf_smprintf("%s[%lu]", xp->var->name,
1330 xp->str = p ? shf_smprintf(Tf_sSQlu, xp->var->name,
13231331 arrayindex(xp->var)) : xp->var->name;
13241332 break;
13251333 #ifdef DEBUG
13261334 default:
1327 internal_errorf("stype mismatch");
1335 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_ONEMSG | KWF_NOERRNO,
1336 "stype mismatch");
13281337 /* NOTREACHED */
13291338 #endif
13301339 case ORD('%'):
13701379 }
13711380 /* ${%var} also here */
13721381 if (Flag(FNOUNSET) && sc == 0 && !zero_ok)
1373 errorf(Tf_parm, sp);
1382 kerrf(KWF_ERR(1) | KWF_PREFIX |
1383 KWF_FILELINE | KWF_TWOMSG |
1384 KWF_NOERRNO, sp, Tf_parm);
13741385 xp->str = shf_smprintf(Tf_d, sc);
13751386 break;
13761387 }
15131524 state = XBASE;
15141525 if (Flag(FNOUNSET) && xp->str == null && !zero_ok &&
15151526 (ctype(c, C_SUB2) || (state != XBASE && c != ORD('+'))))
1516 errorf(Tf_parm, sp);
1527 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG |
1528 KWF_NOERRNO, sp, Tf_parm);
15171529 *stypep = stype;
15181530 *slenp = slen;
15191531 return (state);
15671579 shf = shf_open(name = evalstr(io->ioname, DOTILDE),
15681580 O_RDONLY, 0, SHF_MAPHI | SHF_CLEXEC);
15691581 if (shf == NULL)
1570 warningf(!Flag(FTALKING), Tf_sD_sD_s,
1571 name, Tcant_filesub, cstrerror(errno));
1582 kwarnf(KWF_PREFIX | (Flag(FTALKING) ?
1583 KWF_FILELINE : 0) | KWF_TWOMSG,
1584 name, Tcant_filesub);
15721585 break;
15731586 case IOHERE:
15741587 if (!herein(io, &name)) {
15831596 shf = NULL;
15841597 break;
15851598 default:
1586 errorf(Tf_sD_s, T_funny_command,
1599 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
1600 KWF_TWOMSG | KWF_NOERRNO, T_funny_command,
15871601 snptreef(NULL, 32, Tft_R, io));
15881602 }
15891603 } else if (fn == FUNSUB) {
15951609 * with an shf open for reading (buffered) but yet unused
15961610 */
15971611 maketemp(ATEMP, TT_FUNSUB, &tf);
1598 if (!tf->shf) {
1599 errorf(Tf_temp,
1600 Tcreate, tf->tffn, cstrerror(errno));
1601 }
1612 if (!tf->shf)
1613 kerrf0(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE,
1614 Tf_temp, Tcreate, tf->tffn);
16021615 /* extract shf from temporary file, unlink and free it */
16031616 shf = tf->shf;
16041617 unlink(tf->tffn);
17571770 char *xp = *xpp;
17581771 char *se;
17591772 char odirsep;
1773 DIR *dirp;
1774 size_t prefix_len;
17601775
17611776 /* This to allow long expansions to be interrupted */
17621777 intrcheck();
18151830 Xcheck(*xs, xp);
18161831 *xp++ = *sp++;
18171832 }
1833 *xp = '\0';
18181834 np = mksh_sdirsep(sp);
18191835 if (np != NULL) {
18201836 se = np;
18391855 xp = strnul(xp);
18401856 *xpp = xp;
18411857 globit(xs, xpp, np, wp, check);
1842 } else {
1843 DIR *dirp;
1858 } else if ((dirp = opendir((prefix_len = Xlength(*xs, xp)) ?
1859 Xstring(*xs, xp) : Tdot))) {
18441860 struct dirent *d;
1845 char *name;
1846 size_t len, prefix_len;
1847
1848 /* xp = *xpp; copy_non_glob() may have re-alloc'd xs */
1849 *xp = '\0';
1850 prefix_len = Xlength(*xs, xp);
1851 dirp = opendir(prefix_len ? Xstring(*xs, xp) : Tdot);
1852 if (dirp == NULL)
1853 goto Nodir;
1861
18541862 while ((d = readdir(dirp)) != NULL) {
1855 name = d->d_name;
1856 if (name[0] == '.' &&
1857 (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
1863 size_t len;
1864
1865 if (isch(d->d_name[0], '.') && (!d->d_name[1] ||
1866 (isch(d->d_name[1], '.') && !d->d_name[2])))
18581867 /* always ignore . and .. */
18591868 continue;
1860 if ((*name == '.' && *sp != '.') ||
1861 !gmatchx(name, sp, true))
1869 if ((isch(d->d_name[0], '.') && !isch(*sp, '.')) ||
1870 !gmatchx(d->d_name, sp, true))
18621871 continue;
18631872
18641873 len = strlen(d->d_name) + 1;
18651874 XcheckN(*xs, xp, len);
1866 memcpy(xp, name, len);
1875 memcpy(xp, d->d_name, len);
18671876 *xpp = xp + len - 1;
18681877 globit(xs, xpp, np, wp, (check & GF_MARKDIR) |
18691878 GF_GLOBBED | (np ? GF_EXCHECK : GF_NONE));
18701879 xp = Xstring(*xs, xp) + prefix_len;
18711880 }
18721881 closedir(dirp);
1873 Nodir:
1874 ;
18751882 }
18761883
18771884 if (np != NULL)
22 /*-
33 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
44 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
5 * 2019, 2020, 2021
5 * 2019, 2020, 2021, 2022
66 * mirabilos <m@mirbsd.org>
77 *
88 * Provided that these terms and disclaimer and all copyright notices
2323
2424 #include "sh.h"
2525
26 __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.234 2021/10/10 21:35:04 tg Exp $");
26 __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.237 2022/01/06 22:34:55 tg Exp $");
2727
2828 #ifndef MKSH_DEFAULT_EXECSHELL
2929 #define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
150150 */
151151 if (tp && tp->type == CSHELL &&
152152 (tp->flag & SPEC_BI))
153 errorfz();
153 kerrf(KWF_ERR(1) | KWF_PREFIX |
154 KWF_FILELINE | KWF_ONEMSG |
155 KWF_NOERRNO, "redirection failure");
154156 /* Deal with FERREXIT, quitenv(), etc. */
155157 goto Break;
156158 }
225227 #endif
226228 /* Already have a (live) co-process? */
227229 if (coproc.job && coproc.write >= 0)
228 errorf("coprocess already exists");
230 kerrf(KWF_ERR(1) | KWF_PREFIX |
231 KWF_FILELINE | KWF_ONEMSG |
232 KWF_NOERRNO, "coprocess already exists");
229233
230234 /* Can we re-use the existing co-process pipe? */
231235 coproc_cleanup(true);
434438 for (iowp = t->left->ioact; *iowp != NULL; iowp++)
435439 if (((*iowp)->ioflag & IODUPSELF) &&
436440 fcntl((*iowp)->unit, F_SETFD, 0) == -1)
437 internal_warningf(Tcloexec_failed,
438 "clear", (*iowp)->unit,
439 cstrerror(errno));
441 kwarnf0(KWF_INTERNAL | KWF_WARNING,
442 Tcloexec_failed, "clear",
443 (*iowp)->unit);
440444 /* try to execute */
441445 {
442446 union mksh_ccphack cargs;
448452 if (rv == ENOEXEC)
449453 scriptexec(t, (const char **)up);
450454 else
451 errorfx(126, Tf_sD_s, t->str, cstrerror(rv));
455 kerrf(KWF_VERRNO | KWF_ERR(126) | KWF_PREFIX |
456 KWF_FILELINE | KWF_ONEMSG, rv, t->str);
452457 }
453458 Break:
454459 exstat = rv & 0xFF;
534539 break;
535540 }
536541 if ((tp = findcom(cp, FC_BI)) == NULL)
537 errorf(Tf_sD_sD_s, Tbuiltin, cp, Tnot_found);
542 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
543 KWF_THREEMSG | KWF_NOERRNO, Tbuiltin, cp,
544 Tnot_found);
538545 if (tp->type == CSHELL && (tp->flag & LOW_BI))
539546 break;
540547 continue;
578585 fcflags = FC_BI | FC_PATH;
579586 if (saw_p) {
580587 if (Flag(FRESTRICTED)) {
581 warningf(true, Tf_sD_s,
588 kwarnf(KWF_PREFIX | KWF_FILELINE |
589 KWF_TWOMSG | KWF_NOERRNO,
582590 "command -p", "restricted");
583591 rv = 1;
584592 goto Leave;
675683 goto Leave;
676684 } else if (!tp) {
677685 if (Flag(FRESTRICTED) && mksh_vdirsep(cp)) {
678 warningf(true, Tf_sD_s, cp, "restricted");
686 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG |
687 KWF_NOERRNO, cp, "restricted");
679688 rv = 1;
680689 goto Leave;
681690 }
694703
695704 /* function call */
696705 case CFUNC: {
697 volatile uint32_t old_inuse;
706 volatile kui old_inuse;
698707 const char * volatile old_kshname;
699708 volatile kby old_flags[FNFLAGS];
700709
704713 if (!tp->u.fpath) {
705714 fpath_error:
706715 rv = (tp->u2.errnov == ENOENT) ? 127 : 126;
707 warningf(true,
708 "%s: can't find function definition file: %s",
709 cp, cstrerror(tp->u2.errnov));
716 kwarnf(KWF_VERRNO | KWF_PREFIX | KWF_FILELINE |
717 KWF_TWOMSG, tp->u2.errnov, cp,
718 "can't find function definition file");
710719 break;
711720 }
712721 errno = 0;
725734 cp = tp->u.fpath;
726735 goto fpath_error;
727736 }
728 warningf(true, Tf_sD_s_s, cp,
737 kwarnf0(KWF_PREFIX | KWF_FILELINE | KWF_NOERRNO,
738 Tf_sD_s_s, cp,
729739 "function not defined by", tp->u.fpath);
730740 rv = 127;
731741 break;
816826 /* NOTREACHED */
817827 default:
818828 quitenv(NULL);
819 internal_errorf(Tunexpected_type, Tunwind, Tfunction, i);
829 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
830 Tunexpected_type, Tunwind, Tfunction, i);
820831 }
821832 break;
822833 }
828839 if (!(tp->flag&ISSET)) {
829840 if (tp->u2.errnov == ENOENT) {
830841 rv = 127;
831 warningf(true, Tf_sD_s_s, cp,
832 "inaccessible or", Tnot_found);
842 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG |
843 KWF_NOERRNO, cp, Tinacc_not_found);
833844 } else {
834845 rv = 126;
835 warningf(true, Tf_sD_sD_s, cp, "can't execute",
836 cstrerror(tp->u2.errnov));
846 kwarnf(KWF_VERRNO | KWF_PREFIX | KWF_FILELINE |
847 KWF_TWOMSG, tp->u2.errnov, cp,
848 "can't execute");
837849 }
838850 break;
839851 }
969981 #ifndef MKSH_EBCDIC
970982 m = buf[0] << 8 | buf[1];
971983 if (m == 0x7F45 && buf[2] == 'L' && buf[3] == 'F')
972 errorf("%s: not executable: %d-bit ELF file", tp->str,
973 32 * buf[4]);
984 kerrf0(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
985 KWF_NOERRNO, "%s: not executable: %d-bit ELF file",
986 tp->str, 32 * buf[4]);
974987 if ((m == /* OMAGIC */ 0407) ||
975988 (m == /* NMAGIC */ 0410) ||
976989 (m == /* ZMAGIC */ 0413) ||
9871000 (m == /* UTF-8 BOM */ 0xEFBB && buf[2] == 0xBF) ||
9881001 (m == /* UCS-4, may also be general binary */ 0x0000) ||
9891002 (m == /* UCS-2LE */ 0xFFFE) || (m == /* UCS-2BE */ 0xFEFF))
990 errorf("%s: not executable: magic %04X", tp->str, m);
1003 kerrf0(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
1004 KWF_NOERRNO, "%s: not executable: magic %04X",
1005 tp->str, m);
9911006 #endif
9921007 #ifdef __OS2__
9931008 cp = _getext(tp->str);
10131028 execve(args.rw[0], args.rw, cap.rw);
10141029
10151030 /* report both the program that was run and the bogus interpreter */
1016 errorf(Tf_sD_sD_s, tp->str, sh, cstrerror(errno));
1031 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG, tp->str, sh);
10171032 }
10181033
10191034 /* actual 'builtin' built-in utility call is handled in comexec() */
10341049 * is created if none is found.
10351050 */
10361051 struct tbl *
1037 findfunc(const char *name, uint32_t h, bool create)
1052 findfunc(const char *name, k32 h, bool create)
10381053 {
10391054 struct block *l;
10401055 struct tbl *tp = NULL;
10611076 int
10621077 define(const char *name, struct op *t)
10631078 {
1064 uint32_t nhash;
1079 k32 nhash;
10651080 struct tbl *tp;
10661081 bool was_set = false;
10671082
11111126 builtin(const char *name, int (*func) (const char **))
11121127 {
11131128 struct tbl *tp;
1114 uint32_t flag = DEFINED;
1129 kui flag = DEFINED;
11151130
11161131 /* see if any flags should be set for this builtin */
11171132 flags_loop:
11691184 findcom(const char *name, int flags)
11701185 {
11711186 static struct tbl temp;
1172 uint32_t h = hash(name);
1187 k32 h = hash(name);
11731188 struct tbl *tp = NULL, *tbi;
11741189 /* insert if not found */
11751190 unsigned char insert = Flag(FTRACKALL);
13841399 int rv;
13851400
13861401 if (!tp)
1387 internal_errorf(Tf_sD_s, where, wp[0]);
1402 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_TWOMSG | KWF_NOERRNO,
1403 where, wp[0]);
13881404 builtin_argv0 = wp[0];
13891405 builtin_spec = tobool(!resetspec && (tp->flag & SPEC_BI));
13901406 shf_reopen(1, SHF_WR, shl_stdout);
14871503 &emsg)) < 0) {
14881504 char *sp;
14891505
1490 warningf(true, Tf_sD_s,
1491 (sp = snptreef(NULL, 32, Tft_R, &iotmp)), emsg);
1506 sp = snptreef(NULL, 32, Tft_R, &iotmp);
1507 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG |
1508 KWF_NOERRNO, sp, emsg);
14921509 afree(sp, ATEMP);
14931510 return (-1);
14941511 }
15031520
15041521 if (do_open) {
15051522 if (Flag(FRESTRICTED) && (flags & O_CREAT)) {
1506 warningf(true, Tf_sD_s, cp, "restricted");
1523 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG |
1524 KWF_NOERRNO, cp, "restricted");
15071525 return (-1);
15081526 }
15091527 u = binopen3(cp, flags, 0666);
15201538 if (u < 0) {
15211539 /* herein() may already have printed message */
15221540 if (u == -1) {
1523 u = errno;
1524 warningf(true, Tf_cant_ss_s,
1541 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG, cp,
1542 (iotype == IOREAD || iotype == IOHERE) ? Topen :
15251543 #if 0
15261544 /* can't happen */
15271545 iotype == IODUP ? "dup" :
15281546 #endif
1529 (iotype == IOREAD || iotype == IOHERE) ?
1530 Topen : Tcreate, cp, cstrerror(u));
1547 Tcreate);
15311548 }
15321549 return (-1);
15331550 }
15501567 char *sp;
15511568
15521569 eno = errno;
1553 warningf(true, Tf_s_sD_s, Tredirection_dup,
1554 (sp = snptreef(NULL, 32, Tft_R, &iotmp)),
1555 cstrerror(eno));
1570 sp = snptreef(NULL, 32, Tft_s_R, Tredirection_dup,
1571 &iotmp);
1572 kwarnf(KWF_VERRNO | KWF_PREFIX | KWF_FILELINE |
1573 KWF_ONEMSG, eno, sp);
15561574 afree(sp, ATEMP);
15571575 if (iotype != IODUP)
15581576 close(u);
16061624 s->start = s->str = ccp;
16071625 source = s;
16081626 if (yylex(sub) != LWORD)
1609 internal_errorf("herein: yylex");
1627 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_ONEMSG | KWF_NOERRNO,
1628 "herein: yylex");
16101629 source = osource;
16111630 ccp = evalstr(yylval.cp, DOSCALAR | DOHEREDOC);
16121631 }
16411660 */
16421661 h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
16431662 if (!(shf = h->shf) || (fd = binopen3(h->tffn, O_RDONLY, 0)) < 0) {
1644 i = errno;
1645 warningf(true, Tf_temp,
1646 !shf ? Tcreate : Topen, h->tffn, cstrerror(i));
1663 kwarnf0(KWF_PREFIX | KWF_FILELINE, Tf_temp,
1664 !shf ? Tcreate : Topen, h->tffn);
16471665 if (shf)
16481666 shf_close(shf);
16491667 /* special to iosetup(): don't print error */
16591677 if (shf_close(shf) == -1) {
16601678 i = errno;
16611679 close(fd);
1662 warningf(true, Tf_temp,
1663 Twrite, h->tffn, cstrerror(i));
1680 kwarnf1(KWF_VERRNO | KWF_PREFIX | KWF_FILELINE, i,
1681 Tf_temp, Twrite, h->tffn);
16641682 /* special to iosetup(): don't print error */
16651683 return (-2);
16661684 }
18681886 dbteste_error(Test_env *te, int offset, const char *msg)
18691887 {
18701888 te->flags |= TEF_ERROR;
1871 internal_warningf("dbteste_error: %s (offset %d)", msg, offset);
1872 }
1889 kwarnf0(KWF_INTERNAL | KWF_WARNING | KWF_NOERRNO,
1890 "dbteste_error: %s (offset %d)", msg, offset);
1891 }
+89
-120
expr.c less more
22 /*-
33 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
44 * 2011, 2012, 2013, 2014, 2016, 2017, 2018, 2019,
5 * 2021
5 * 2021, 2022
66 * mirabilos <m@mirbsd.org>
77 *
88 * Provided that these terms and disclaimer and all copyright notices
2323
2424 #include "sh.h"
2525
26 __RCSID("$MirOS: src/bin/mksh/expr.c,v 1.114 2021/10/10 20:41:16 tg Exp $");
26 __RCSID("$MirOS: src/bin/mksh/expr.c,v 1.119 2022/01/28 07:01:12 tg Exp $");
2727
2828 #define EXPRTOK_DEFNS
2929 #include "exprtok.h"
141141 if (i == LAEXPR) {
142142 if (error_ok == KSH_RETURN_ERROR)
143143 return (0);
144 errorfz();
144 /* error already printed */
145 /* (cf. syn.c for why) */
146 exstat = 1;
147 shl_stdout_ok = false;
148 i = LERROR;
145149 }
146150 unwind(i);
147151 /* NOTREACHED */
162166 if (vp->flag & INTEGER)
163167 setint_v(vp, v, es->arith);
164168 else
165 /* can fail if readonly */
169 /* can fail if read-only */
166170 setstr(vp, str_val(v), error_ok);
167171
168172 quitenv(NULL);
197201 default:
198202 s = opname[(int)es->tok];
199203 }
200 warningf(true, Tf_sD_s_qs, es->expression,
201 Tunexpected, s);
204 kwarnf0(KWF_PREFIX | KWF_FILELINE | KWF_NOERRNO, Tf_sD_s_qs,
205 es->expression, Tunexpected, s);
202206 break;
203207
204208 case ET_BADLIT:
205 warningf(true, Tf_sD_s_qs, es->expression,
206 Tbadnum, str);
209 if (!strcmp(es->expression, str))
210 kwarnf0(KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG,
211 es->expression, Tbadnum);
212 else
213 kwarnf0(KWF_PREFIX | KWF_FILELINE, Tf_sD_s_qs,
214 es->expression, Tbadnum, str);
207215 break;
208216
209217 case ET_RECURSIVE:
210 warningf(true, Tf_sD_s_qs, es->expression,
211 "expression recurses on parameter", str);
218 kwarnf0(KWF_PREFIX | KWF_FILELINE | KWF_NOERRNO, Tf_sD_s_qs,
219 es->expression, "expression recurses on parameter", str);
212220 break;
213221
214222 case ET_LVALUE:
215 warningf(true, Tf_sD_s_s,
223 kwarnf0(KWF_PREFIX | KWF_FILELINE | KWF_NOERRNO, Tf_sD_s_s,
216224 es->expression, str, "requires lvalue");
217225 break;
218226
219227 case ET_RDONLY:
220 warningf(true, Tf_sD_s_s,
228 kwarnf0(KWF_PREFIX | KWF_FILELINE | KWF_NOERRNO, Tf_sD_s_s,
221229 es->expression, str, "applied to read-only variable");
222230 break;
223231
224232 default: /* keep gcc happy */
225233 case ET_STR:
226 warningf(true, Tf_sD_s, es->expression, str);
234 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG | KWF_NOERRNO,
235 es->expression, str);
227236 break;
228237 }
229238 unwind(LAEXPR);
262271 {
263272 struct tbl *vl, *vr = NULL, *vasn;
264273 enum token op;
265 mksh_uari_t res = 0, t1, t2, t3;
274 mksh_uari_t res = 0;
266275
267276 if (prec == P_PRIMARY) {
268277 switch ((int)(op = es->tok)) {
365374 } else if (op != O_LAND && op != O_LOR)
366375 vr = intvar(es, evalexpr(es, prec - 1));
367376
368 /* common ops setup */
377 /* op calculation */
378 #define cmpop(op) (es->natural ? \
379 (mksh_uari_t)(vl->val.u op vr->val.u) : \
380 (mksh_uari_t)(vl->val.i op vr->val.i) \
381 )
382 #ifndef MKSH_LEGACY_MODE
383 #define ariop(op) (vl->val.u op vr->val.u)
384 #else
385 #define ariop(op) cmpop(op)
386 #endif
369387 switch ((int)op) {
388 case O_PLUS:
389 case O_PLUSASN:
390 res = ariop(+);
391 break;
392 case O_MINUS:
393 case O_MINUSASN:
394 res = ariop(-);
395 break;
396 case O_TIMES:
397 case O_TIMESASN:
398 res = ariop(*);
399 break;
370400 case O_DIV:
371401 case O_DIVASN:
372402 case O_MOD:
373403 case O_MODASN:
374 if (vr->val.u == 0) {
404 if (vr->val.i == 0) {
375405 if (!es->noassign)
376406 evalerr(es, ET_STR, "zero divisor");
377 vr->val.u = 1;
378 }
379 /* calculate the absolute values */
380 t1 = vl->val.i < 0 ? -vl->val.u : vl->val.u;
381 t2 = vr->val.i < 0 ? -vr->val.u : vr->val.u;
382 break;
383 #ifndef MKSH_LEGACY_MODE
384 case O_LSHIFT:
385 case O_LSHIFTASN:
386 case O_RSHIFT:
387 case O_RSHIFTASN:
388 case O_ROL:
389 case O_ROLASN:
390 case O_ROR:
391 case O_RORASN:
392 t1 = vl->val.u;
393 t2 = vr->val.u & 31;
394 if (!t2) {
395 res = t1;
396 goto rotate_by_zero;
397 }
398 break;
399 #endif
400 case O_LAND:
401 case O_LOR:
402 t1 = vl->val.u;
403 t2 = 0; /* gcc */
404 break;
405 default:
406 t1 = vl->val.u;
407 t2 = vr->val.u;
408 break;
409 }
410
411 #define cmpop(op) (es->natural ? \
412 (mksh_uari_t)(vl->val.u op vr->val.u) : \
413 (mksh_uari_t)(vl->val.i op vr->val.i) \
414 )
415
416 /* op calculation */
417 switch ((int)op) {
418 case O_TIMES:
419 case O_TIMESASN:
420 res = t1 * t2;
421 break;
422 case O_MOD:
423 case O_MODASN:
424 if (es->natural) {
425 res = vl->val.u % vr->val.u;
407 res = vl->val.u; /* dummy value, could be 1 */
426408 break;
427409 }
428 goto signed_division;
429 case O_DIV:
430 case O_DIVASN:
431 if (es->natural) {
432 res = vl->val.u / vr->val.u;
433 break;
434 }
435 signed_division:
436 /*
437 * a / b = abs(a) / abs(b) * sgn((u)a^(u)b)
438 */
439 t3 = t1 / t2;
440410 #ifndef MKSH_LEGACY_MODE
441 res = ((vl->val.u ^ vr->val.u) & 0x80000000) ? -t3 : t3;
442 #else
443 res = ((t1 == vl->val.u ? 0 : 1) ^
444 (t2 == vr->val.u ? 0 : 1)) ? -t3 : t3;
411 if (!es->natural) {
412 mksh_uari_t u1, u2;
413
414 mbiVASdivrem(mksh_uari_t, mksh_ari_t,
415 u1, u2, vl->val.i, vr->val.i);
416 if (op == O_DIV || op == O_DIVASN)
417 res = u1;
418 else
419 res = u2;
420 } else
445421 #endif
446 if (op == O_MOD || op == O_MODASN) {
447 /*
448 * primitive modulo, to get the sign of
449 * the result correct:
450 * (a % b) = a - ((a / b) * b)
451 * the subtraction and multiplication
452 * are, amazingly enough, sign ignorant
453 */
454 res = vl->val.u - (res * vr->val.u);
455 }
456 break;
457 case O_PLUS:
458 case O_PLUSASN:
459 res = t1 + t2;
460 break;
461 case O_MINUS:
462 case O_MINUSASN:
463 res = t1 - t2;
422 if (op == O_DIV || op == O_DIVASN)
423 res = ariop(/);
424 else
425 res = ariop(%);
464426 break;
465427 #ifndef MKSH_LEGACY_MODE
466428 case O_ROL:
467429 case O_ROLASN:
468 res = (t1 << t2) | (t1 >> (32 - t2));
430 mbiVAUrol(mksh_uari_t, res, vl->val.u, vr->val.u);
469431 break;
470432 case O_ROR:
471433 case O_RORASN:
472 res = (t1 >> t2) | (t1 << (32 - t2));
473 rotate_by_zero:
434 mbiVAUror(mksh_uari_t, res, vl->val.u, vr->val.u);
474435 break;
475436 #endif
476437 case O_LSHIFT:
477438 case O_LSHIFTASN:
478 res = t1 << t2;
439 #ifndef MKSH_LEGACY_MODE
440 mbiVAUshl(mksh_uari_t, res, vl->val.u, vr->val.u);
441 #else
442 res = ariop(<<);
443 #endif
479444 break;
480445 case O_RSHIFT:
481446 case O_RSHIFTASN:
482 res = es->natural || vl->val.i >= 0 ?
483 t1 >> t2 :
484 ~(~t1 >> t2);
447 #ifndef MKSH_LEGACY_MODE
448 mbiVAUshr(mksh_uari_t, res,
449 !es->natural && vl->val.i < 0,
450 vl->val.u, vr->val.u);
451 #else
452 res = ariop(>>);
453 #endif
485454 break;
486455 case O_LT:
487456 res = cmpop(<);
496465 res = cmpop(>=);
497466 break;
498467 case O_EQ:
499 res = t1 == t2;
468 res = ariop(==);
500469 break;
501470 case O_NE:
502 res = t1 != t2;
471 res = ariop(!=);
503472 break;
504473 case O_BAND:
505474 case O_BANDASN:
506 res = t1 & t2;
475 res = ariop(&);
507476 break;
508477 case O_BXOR:
509478 case O_BXORASN:
510 res = t1 ^ t2;
479 res = ariop(^);
511480 break;
512481 case O_BOR:
513482 case O_BORASN:
514 res = t1 | t2;
483 res = ariop(|);
515484 break;
516485 case O_LAND:
517 if (!t1)
486 if (!vl->val.u)
518487 es->noassign++;
519488 exprtoken(es);
520489 vr = intvar(es, evalexpr(es, prec - 1));
521 res = t1 && vr->val.u;
522 if (!t1)
490 res = vl->val.u && vr->val.u;
491 if (!vl->val.u)
523492 es->noassign--;
524493 break;
525494 case O_LOR:
526 if (t1)
495 if (vl->val.u)
527496 es->noassign++;
528497 exprtoken(es);
529498 vr = intvar(es, evalexpr(es, prec - 1));
530 res = t1 || vr->val.u;
531 if (t1)
499 res = vl->val.u || vr->val.u;
500 if (vl->val.u)
532501 es->noassign--;
533502 break;
534503 case O_ASN:
535504 case O_COMMA:
536 res = t2;
505 res = vr->val.u;
537506 break;
538507 }
539
540508 #undef cmpop
541509
542510 if (IS_ASSIGNOP(op)) {
669637 struct tbl *vp;
670638 size_t vsize;
671639
672 vsize = strlen(vname) + 1;
640 /* vname is either "" or vtemp->name which maxes at 12 */
641 vsize = strlen(vname) + 1U;
673642 vp = alloc(offsetof(struct tbl, name[0]) + vsize, ATEMP);
674643 memcpy(vp->name, vname, vsize);
675644 vp->flag = ISSET|INTEGER;
44 /*-
55 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
66 * 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
7 * 2019, 2020, 2021
7 * 2019, 2020, 2021, 2022
88 * mirabilos <m@mirbsd.org>
99 *
1010 * Provided that these terms and disclaimer and all copyright notices
3434 #endif
3535 #endif
3636
37 __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.393 2021/10/10 20:30:33 tg Exp $");
37 __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.401 2022/01/28 10:28:17 tg Exp $");
3838
3939 #if HAVE_KILLPG
4040 /*
163163 const struct t_op u_ops[] = {
164164 /* 0*/ {"-a", TO_FILAXST },
165165 {"-b", TO_FILBDEV },
166 {"-c", TO_FILCDEV },
166 /* 2*/ {"-c", TO_FILCDEV },
167167 {"-d", TO_FILID },
168168 {"-e", TO_FILEXST },
169169 {"-f", TO_FILREG },
176176 /*12*/ {"-n", TO_STNZE },
177177 {"-O", TO_FILUID },
178178 /*14*/ {"-o", TO_OPTION },
179 {"-p", TO_FILFIFO },
179 /*15*/ {"-p", TO_FILFIFO },
180180 /*16*/ {"-r", TO_FILRD },
181181 {"-S", TO_FILSOCK },
182182 {"-s", TO_FILGZ },
188188 {"-z", TO_STZER },
189189 {"", TO_NONOP }
190190 };
191 cta(u_ops_size, NELEM(u_ops) == 26);
191 mbiCTAS(funcs_c) {
192 mbiCTA(u_ops_size, NELEM(u_ops) == 26);
193 };
192194 const struct t_op b_ops[] = {
193195 {"=", TO_STEQL },
194196 {"==", TO_STEQL },
385387 break;
386388 case 'p':
387389 if ((po.fd = coproc_getfd(W_OK, &emsg)) < 0) {
388 bi_errorf(Tf_coproc, emsg);
390 bi_errorf("%s: %s", Tdp, emsg);
389391 return (1);
390392 }
391393 break;
618620 static int
619621 do_whence(const char **wp, int fcflags, bool vflag, bool iscommand)
620622 {
621 uint32_t h;
623 k32 h;
622624 int rv = 0;
623625 struct tbl *tp;
624626 const char *id;
670672 break;
671673 case CEXEC:
672674 case CTALIAS:
675 if (vflag)
676 shf_puts(id, shl_stdout);
673677 if (tp->flag & ISSET) {
674678 if (vflag) {
675 shprintf("%s is ", id);
679 shf_puts(" is ", shl_stdout);
676680 if (tp->type == CTALIAS)
677681 shprintf("a tracked %s%s for ",
678682 (tp->flag & EXPORT) ?
681685 }
682686 if (!mksh_abspath(tp->val.s)) {
683687 const char *xcwd = current_wd[0] ?
684 current_wd : ".";
688 current_wd : Tdot;
685689 size_t xlen = strlen(xcwd);
686690 size_t clen = strlen(tp->val.s) + 1;
687691 char *xp = alloc(xlen + 1 + clen, ATEMP);
698702 shf_puts(tp->val.s, shl_stdout);
699703 } else {
700704 if (vflag)
701 shprintf(Tnot_found_s, id);
705 shf_puts(Tsp_not_found, shl_stdout);
702706 rv = 1;
703707 }
704708 break;
757761 struct table *t = &aliases;
758762 int rv = 0, prefix = 0;
759763 bool rflag = false, tflag, Uflag = false, pflag = false, chkalias;
760 uint32_t xflag = 0;
764 kui xflag = 0;
761765 int optc;
762766
763767 builtin_opt.flags |= GF_PLUSOPT;
844848 const char *alias = *wp, *val, *newval;
845849 char *xalias = NULL;
846850 struct tbl *ap;
847 uint32_t h;
851 k32 h;
848852
849853 if ((val = cstrchr(alias, '='))) {
850854 strndupx(xalias, alias, val++ - alias, ATEMP);
10651069 int i, n, rv, sig;
10661070
10671071 /* assume old style options if -digits or -UPPERCASE */
1068 if ((p = wp[1]) && *p == '-' && ctype(p[1], C_DIGIT | C_UPPER)) {
1069 if (!(t = gettrap(p + 1, false, false))) {
1070 bi_errorf(Tbad_sig_s, p + 1);
1072 if ((p = wp[1]) && isch(*p, '-') && ctype(p[1], C_DIGIT | C_UPPER)) {
1073 ++p;
1074 if (!(t = gettrap(p, false, false))) {
1075 kwarnf(KWF_BIERR | KWF_TWOMSG | KWF_NOERRNO,
1076 Tbad_sig, p);
10711077 return (1);
10721078 }
10731079 i = (wp[2] && strcmp(wp[2], "--") == 0) ? 3 : 2;
10821088 case 's':
10831089 if (!(t = gettrap(builtin_opt.optarg,
10841090 true, false))) {
1085 bi_errorf(Tbad_sig_s,
1091 kwarnf(KWF_BIERR | KWF_TWOMSG |
1092 KWF_NOERRNO, Tbad_sig,
10861093 builtin_opt.optarg);
10871094 return (1);
10881095 }
10981105 " { job | pid | pgrp } ...\n"
10991106 "\tkill -l [exit_status ...]\n", shl_out);
11001107 #endif
1101 bi_errorfz();
1108 bi_unwind(1);
11021109 return (1);
11031110 }
11041111
12161223 }
12171224
12181225 if (e->loc->next == NULL) {
1219 internal_warningf(Tf_sD_s, Tgetopts, Tno_args);
1226 kwarnf(KWF_INTERNAL | KWF_WARNING | KWF_TWOMSG | KWF_NOERRNO,
1227 Tgetopts, Tno_args);
12201228 return (1);
12211229 }
12221230 /* Which arguments are we parsing... */
13401348 n = 1;
13411349 else if (!evaluate(arg, &val, KSH_RETURN_ERROR, false)) {
13421350 /* error already printed */
1343 bi_errorfz();
1351 bi_unwind(1);
13441352 return (1);
13451353 } else if (!(n = val)) {
13461354 /* nothing to do */
15731581 bool rawmode = false, expanding = false;
15741582 bool lastparmmode = false, lastparmused = false;
15751583 enum { LINES, BYTES, UPTO, READALL } readmode = LINES;
1576 char delim = '\n';
1584 kby delim = ORD('\n');
15771585 size_t bytesleft = 128, bytesread;
15781586 struct tbl *vp /* FU gcc */ = NULL, *vq = NULL;
15791587 char *cp, *allocd = NULL, *xp;
15841592 bool restore_tios = false;
15851593 /* to catch read -aN2 foo[i] */
15861594 bool subarray = false;
1595 k32 idx = 0;
15871596 #if HAVE_SELECT
15881597 bool hastimeout = false;
15891598 struct timeval tv, tvlim;
15971606 #endif
15981607
15991608 while ((c = ksh_getopt(wp, &builtin_opt, c_read_opts)) != -1)
1600 switch (c) {
1601 case 'a':
1609 switch (ord(c)) {
1610 case ORD('a'):
16021611 aschars = true;
16031612 /* FALLTHROUGH */
1604 case 'A':
1613 case ORD('A'):
16051614 intoarray = true;
16061615 break;
1607 case 'd':
1608 delim = builtin_opt.optarg[0];
1616 case ORD('d'):
1617 delim = ord(builtin_opt.optarg[0]);
16091618 break;
1610 case 'N':
1611 case 'n':
1612 readmode = c == 'N' ? BYTES : UPTO;
1619 case ORD('N'):
1620 readmode = BYTES;
1621 if (0)
1622 /* FALLTHROUGH */
1623 case ORD('n'):
1624 readmode = UPTO;
16131625 if (!bi_getn(builtin_opt.optarg, &c))
16141626 return (2);
16151627 if (c == -1) {
16201632 break;
16211633 case 'p':
16221634 if ((fd = coproc_getfd(R_OK, &ccp)) < 0) {
1623 bi_errorf(Tf_coproc, ccp);
1635 bi_errorf("%s: %s", Tdp, ccp);
16241636 return (2);
16251637 }
16261638 break;
16441656 if (!builtin_opt.optarg[0])
16451657 fd = 0;
16461658 else if ((fd = check_fd(builtin_opt.optarg, R_OK, &ccp)) < 0) {
1647 bi_errorf(Tf_sD_sD_s, Tdu, builtin_opt.optarg, ccp);
1659 kwarnf(KWF_ERR(2) | KWF_PREFIX | KWF_FILELINE |
1660 KWF_BUILTIN | KWF_BIUNWIND | KWF_THREEMSG,
1661 Tdu, builtin_opt.optarg, ccp);
16481662 return (2);
16491663 }
16501664 break;
17901804 }
17911805 if (expanding) {
17921806 expanding = false;
1793 if (c == delim) {
1807 if (ord(c) == ord(delim)) {
17941808 if (Flag(FTALKING_I) && isatty(fd)) {
17951809 /*
17961810 * set prompt in case this is
18041818 /* and the delimiter */
18051819 break;
18061820 }
1807 } else if (c == delim) {
1821 } else if (ord(c) == ord(delim)) {
18081822 goto c_read_readdone;
1809 } else if (!rawmode && c == '\\') {
1823 } else if (!rawmode && ord(c) == ORD('\\')) {
18101824 expanding = true;
18111825 }
18121826 Xcheck(xs, xp);
18441858 subarray = last_lookup_was_array;
18451859 if (vp->flag & RDONLY) {
18461860 c_read_splitro:
1847 bi_errorf(Tf_ro, *wp);
1861 kwarnf(KWF_BIERR | KWF_TWOMSG | KWF_NOERRNO,
1862 Tread_only, *wp);
18481863 c_read_spliterr:
18491864 rv = 2;
18501865 afree(cp, ATEMP);
18511866 goto c_read_out;
18521867 }
18531868 /* counter for array index */
1854 c = subarray ? arrayindex(vp) : 0;
1869 if (subarray)
1870 idx = arrayindex(vp);
18551871 /* exporting an array is currently pointless */
18561872 unset(vp, subarray ? 0 : 1);
18571873 }
19671983 goto c_read_spliterr;
19681984 }
19691985 vq = vp;
1970 if (c)
1986 if (idx)
19711987 /* [0] doesn't */
19721988 vq->flag |= AINDEX;
1973 } else
1974 vq = arraysearch(vp, c++);
1989 } else {
1990 vq = arraysearch(vp, idx);
1991 idx = K32(idx + 1);
1992 }
19751993 } else {
19761994 vq = global(*wp);
19771995 /* must be checked before exporting */
20962114 i = 0;
20972115 while (*wp)
20982116 if (!(p = gettrap(*wp++, true, true))) {
2099 warningf(true, Tbad_sig_ss, builtin_argv0, wp[-1]);
2117 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_BUILTIN |
2118 KWF_TWOMSG | KWF_NOERRNO, Tbad_sig, wp[-1]);
21002119 i = 1;
21012120 } else
21022121 settrap(p, s);
21842203 * scripts, but don't generate an error (ie, keep going).
21852204 */
21862205 if ((unsigned int)n == quit) {
2187 warningf(true, Tf_cant_s, wp[0], wp[0]);
2206 kwarnf0(KWF_PREFIX | KWF_FILELINE | KWF_NOERRNO,
2207 Tf_cant_s, wp[0], wp[0]);
21882208 return (0);
21892209 }
21902210 /*
21942214 */
21952215 if (last_ep)
21962216 last_ep->flags &= ~EF_BRKCONT_PASS;
2197 warningf(true, "%s: can only %s %u level(s)",
2217 kwarnf0(KWF_PREFIX | KWF_FILELINE | KWF_NOERRNO,
2218 "%s: can only %s %u level(s)",
21982219 wp[0], wp[0], (unsigned int)n - quit);
21992220 }
22002221
22742295 unset_var = true;
22752296 break;
22762297 case '?':
2277 /*XXX not reached due to GF_ERROR */
2298 /*XXX not reached due to GF_ERROR in spec_bi */
22782299 return (2);
22792300 }
22802301 wp += builtin_opt.optind;
22992320 afree(cp, ATEMP);
23002321
23012322 if ((vp->flag&RDONLY)) {
2302 warningf(true, Tf_ro, vp->name);
2323 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG |
2324 KWF_NOERRNO, Tread_only, vp->name);
23032325 rv = 1;
23042326 } else
23052327 unset(vp, optc);
23602382 mksh_TIME(tv0);
23612383 if (ksh_getrusage(RUSAGE_SELF, &ru0) ||
23622384 ksh_getrusage(RUSAGE_CHILDREN, &cru0)) {
2363 warningf(true, "time: getrusage: %s", cstrerror(errno));
2385 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_ONEMSG,
2386 Ttime_getrusage);
23642387 return (125);
23652388 }
23662389 if (t->left) {
23802403 mksh_TIME(tv1);
23812404 if (ksh_getrusage(RUSAGE_SELF, &ru1) ||
23822405 ksh_getrusage(RUSAGE_CHILDREN, &cru1)) {
2383 warningf(true, "time: getrusage: %s", cstrerror(errno));
2406 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_ONEMSG,
2407 Ttime_getrusage);
23842408 return (rv);
23852409 }
23862410 } else
24402464 t->str[0] |= TF_POSIX;
24412465 break;
24422466 case '?':
2443 errorf(Tf_optfoo, Ttime, Tcolsp,
2444 opt.optarg[0], Tunknown_option);
2467 ksh_getopt_opterr(opt.optarg[0], Ttime,
2468 Tunknown_option);
2469 unwind(LERROR);
24452470 case ':':
2446 errorf(Tf_optfoo, Ttime, Tcolsp,
2447 opt.optarg[0], Treq_arg);
2471 ksh_getopt_opterr(opt.optarg[0], Ttime,
2472 Treq_arg);
2473 unwind(LERROR);
24482474 }
24492475 /* Copy command words down over options. */
24502476 if (opt.optind != 0) {
24792505 close((int)sfd);
24802506 if (i > 2 && !(e->savedfd[i] & FDICLMASK) &&
24812507 fcntl(i, F_SETFD, FD_CLOEXEC) == -1)
2482 internal_warningf(Tcloexec_failed, "set", i,
2483 cstrerror(errno));
2508 kwarnf0(KWF_INTERNAL | KWF_WARNING,
2509 Tcloexec_failed, "set", i);
24842510 }
24852511 } else {
24862512 /* … but not for POSIX or legacy/kludge sh */
25452571
25462572 majnum = strtoul(argv[2], &c, 0);
25472573 if ((c == argv[2]) || (*c != '\0')) {
2548 bi_errorf(Tf_nonnum, "device", "major", argv[2]);
2574 bi_errorf("%s: %s: %s", "major", "non-numeric", argv[2]);
25492575 goto c_mknod_err;
25502576 }
25512577 minnum = strtoul(argv[3], &c, 0);
25522578 if ((c == argv[3]) || (*c != '\0')) {
2553 bi_errorf(Tf_nonnum, "device", "minor", argv[3]);
2579 bi_errorf("%s: %s: %s", "minor", "non-numeric", argv[3]);
25542580 goto c_mknod_err;
25552581 }
25562582 dv = makedev(majnum, minnum);
25572583 if ((unsigned long)(major(dv)) != majnum) {
2558 bi_errorf(Tf_toolarge, "device", "major", majnum);
2584 bi_errorf(Tf_toolarge, "major", majnum);
25592585 goto c_mknod_err;
25602586 }
25612587 if ((unsigned long)(minor(dv)) != minnum) {
2562 bi_errorf(Tf_toolarge, "device", "minor", minnum);
2588 bi_errorf(Tf_toolarge, "minor", minnum);
25632589 goto c_mknod_err;
25642590 }
25652591 if (mknod(argv[0], mode, dv))
33 /*-
44 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
55 * 2011, 2012, 2014, 2015, 2016, 2017, 2018, 2019,
6 * 2021
6 * 2021, 2022
77 * mirabilos <m@mirbsd.org>
88 *
99 * Provided that these terms and disclaimer and all copyright notices
2323 */
2424
2525 #include "sh.h"
26 #include "mirhash.h"
2627 #if HAVE_SYS_FILE_H
2728 #include <sys/file.h>
2829 #endif
2930
30 __RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.176 2021/10/10 20:41:16 tg Exp $");
31 __RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.185 2022/01/28 03:54:35 tg Exp $");
3132
3233 Trap sigtraps[ksh_NSIG + 1];
3334
108109 size_t len = strlen(p);
109110
110111 /* almost certainly not overflowing */
111 editor = alloc(len + 4, ATEMP);
112 editor = alloc(len + 6U, ATEMP);
112113 memcpy(editor, p, len);
113 memcpy(editor + len, Tspdollaru, 4);
114 memcpy(editor + len, Tspdollaru, 6U);
114115 }
115116 break;
116117
293294
294295 tf = maketemp(ATEMP, TT_HIST_EDIT, &e->temps);
295296 if (!(shf = tf->shf)) {
296 bi_errorf(Tf_temp, Tcreate, tf->tffn, cstrerror(errno));
297 kwarnf0(KWF_BIERR, Tf_temp, Tcreate, tf->tffn);
297298 return (1);
298299 }
299300 for (hp = rflag ? hlast : hfirst;
300301 hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1)
301302 shf_fprintf(shf, Tf_sN, *hp);
302303 if (shf_close(shf) == -1) {
303 bi_errorf(Tf_temp, Twrite, tf->tffn, cstrerror(errno));
304 kwarnf0(KWF_BIERR, Tf_temp, Twrite, tf->tffn);
304305 return (1);
305306 }
306307
317318 ssize_t n;
318319
319320 if (!(shf = shf_open(tf->tffn, O_RDONLY, 0, 0))) {
320 bi_errorf(Tf_temp, Topen, tf->tffn, cstrerror(errno));
321 kwarnf0(KWF_BIERR, Tf_temp, Topen, tf->tffn);
321322 return (1);
322323 }
323324
324325 if (stat(tf->tffn, &statb) < 0)
325326 n = 128;
326327 else if ((off_t)statb.st_size > MKSH_MAXHISTFSIZE) {
327 bi_errorf(Tf_toolarge, Thistory,
328 Tfile, (unsigned long)statb.st_size);
328 bi_errorf(Tf_toolarge, Tfile,
329 (unsigned long)statb.st_size);
329330 goto errout;
330331 } else
331332 n = (size_t)statb.st_size + 1;
336337 XcheckN(xs, xp, Xlength(xs, xp));
337338 }
338339 if (n < 0) {
339 bi_errorf(Tf_temp, Tread, tf->tffn,
340 cstrerror(shf_errno(shf)));
340 kwarnf1(KWF_VERRNO | KWF_BIERR, shf_errno(shf),
341 Tf_temp, Tread, tf->tffn);
341342 errout:
342343 shf_close(shf);
343344 return (1);
870871 goto retry;
871872 }
872873 if (hs != hist_init_retry)
873 bi_errorf(Tf_cant_ss_s,
874 bi_errorf("can't %s %s: %s",
874875 "unlink HISTFILE", hname, cstrerror(errno));
875876 histfsize = 0;
876877 return;
10361037
10371038 /* +++ signals +++ */
10381039
1039 #if !HAVE_SYS_SIGNAME
1040 #if !HAVE_SIGABBREV_NP && !HAVE_SYS_SIGNAME
10401041 static const struct mksh_sigpair {
10411042 const char * const name;
10421043 int nr;
10461047 };
10471048 #endif
10481049
1049 #if HAVE_SYS_SIGLIST
1050 #if !HAVE_SYS_SIGLIST_DECL
1051 extern const char * const sys_siglist[];
1052 #endif
1053 #endif
1054
10551050 void
10561051 inittraps(void)
10571052 {
10581053 int i;
10591054 const char *cs;
1060 #if !HAVE_SYS_SIGNAME
1055 #if !HAVE_SIGABBREV_NP && !HAVE_SYS_SIGNAME
10611056 const struct mksh_sigpair *pair;
10621057 #endif
10631058
10661061 /* populate sigtraps based on sys_signame and sys_siglist */
10671062 for (i = 1; i < ksh_NSIG; i++) {
10681063 sigtraps[i].signal = i;
1069 #if HAVE_SYS_SIGNAME
1064 #if HAVE_SIGABBREV_NP
1065 cs = sigabbrev_np(i);
1066 #elif HAVE_SYS_SIGNAME
10701067 cs = sys_signame[i];
10711068 #else
10721069 pair = mksh_sigpairs;
10811078 char *s;
10821079
10831080 /* this is not optimal, what about SIGSIG1? */
1084 if (ksh_eq(cs[0], 'S', 's') &&
1085 ksh_eq(cs[1], 'I', 'i') &&
1086 ksh_eq(cs[2], 'G', 'g') &&
1081 if (isCh(cs[0], 'S', 's') &&
1082 isCh(cs[1], 'I', 'i') &&
1083 isCh(cs[2], 'G', 'g') &&
10871084 cs[3] != '\0') {
10881085 /* skip leading "SIG" */
10891086 cs += 3;
10961093 if (!strcmp(sigtraps[i].name, "EXIT") ||
10971094 !strcmp(sigtraps[i].name, "ERR")) {
10981095 #ifndef MKSH_SMALL
1099 internal_warningf(Tinvname, sigtraps[i].name,
1100 "signal");
1096 kwarnf0(KWF_INTERNAL | KWF_WARNING | KWF_NOERRNO,
1097 Tinvname, sigtraps[i].name, "signal");
11011098 #endif
11021099 sigtraps[i].name = null;
11031100 }
11041101 }
11051102 if (sigtraps[i].name == null)
11061103 sigtraps[i].name = shf_smprintf(Tf_d, i);
1107 #if HAVE_SYS_SIGLIST
1108 sigtraps[i].mess = sys_siglist[i];
1109 #elif HAVE_STRSIGNAL
1110 sigtraps[i].mess = strsignal(i);
1111 #else
1112 sigtraps[i].mess = NULL;
1113 #endif
1114 if ((sigtraps[i].mess == NULL) ||
1115 (sigtraps[i].mess[0] == '\0'))
1104 sigtraps[i].mess = ksh_sigmess(i);
1105 if (ksh_sigmessf(sigtraps[i].mess))
11161106 sigtraps[i].mess = shf_smprintf(Tf_sd,
11171107 "Signal", i);
11181108 }
11801170 /* do a lookup by name then */
11811171
11821172 /* this breaks SIGSIG1, but we do that above anyway */
1183 if (ksh_eq(cs[0], 'S', 's') &&
1184 ksh_eq(cs[1], 'I', 'i') &&
1185 ksh_eq(cs[2], 'G', 'g') &&
1173 if (isCh(cs[0], 'S', 's') &&
1174 isCh(cs[1], 'I', 'i') &&
1175 isCh(cs[2], 'G', 'g') &&
11861176 cs[3] != '\0') {
11871177 /* skip leading "SIG" */
11881178 cs += 3;
12191209 return (p);
12201210 }
12211211
1212 static k32
1213 traphash(int signo, int extra)
1214 {
1215 register k32 h;
1216 static volatile k32 state;
1217 k32 o;
1218 struct {
1219 struct timeval tv;
1220 void *sp;
1221 int i;
1222 int j;
1223 } z;
1224
1225 memset(&z, 0, sizeof(z));
1226 mksh_TIME(z.tv);
1227 z.sp = &z;
1228 z.i = signo;
1229 z.j = extra;
1230
1231 o = h = state;
1232 BAFHUpdateMem(h, &z, sizeof(z));
1233 while (state != o) {
1234 o = state;
1235 BAFHUpdateMem(h, &o, sizeof(o));
1236 }
1237 state = h;
1238 return (h);
1239 }
1240
12221241 /*
12231242 * trap signal handler
12241243 */
12251244 void
12261245 trapsig(int i)
12271246 {
1228 Trap *p = &sigtraps[i];
1229 int eno = errno;
1230
1247 Trap *p;
1248 int eno;
1249
1250 eno = errno;
1251 traphash(i, eno);
1252 p = &sigtraps[i];
12311253 trap = p->set = 1;
12321254 if (p->flags & TF_DFL_INTR)
12331255 intrsig = 1;
13001322 {
13011323 Trap *p = sigtraps;
13021324 int i = ksh_NSIG + 1;
1325 k32 h;
1326
1327 h = traphash(-666, (int)ksh_tmout_state);
1328 rndpush(&h, sizeof(h));
13031329
13041330 if (ksh_tmout_state == TMOUT_LEAVING) {
13051331 ksh_tmout_state = TMOUT_EXECUTING;
1306 warningf(false, "timed out waiting for input");
1332 kwarnf(KWF_PREFIX | KWF_ONEMSG | KWF_NOERRNO,
1333 "timed out waiting for input");
13071334 unwind(LEXIT);
13081335 } else
13091336 /*
15471574 {
15481575 /* XXX debugging */
15491576 if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL)))
1550 internal_errorf("setexecsig: unset signal %d(%s)",
1551 p->signal, p->name);
1577 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
1578 "setexecsig: unset signal %d(%s)", p->signal, p->name);
15521579
15531580 /* restore original value for exec'd kids */
15541581 p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL);
2525 #include <poll.h>
2626 #endif
2727
28 __RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.145 2021/10/10 20:41:17 tg Exp $");
28 __RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.151 2022/01/28 10:28:18 tg Exp $");
2929
3030 #if HAVE_KILLPG
3131 #define mksh_killpg killpg
261261 mksh_tcset(tty_fd, &tty_state);
262262 if (restore_ttypgrp >= 0) {
263263 if (tcsetpgrp(tty_fd, restore_ttypgrp) < 0) {
264 warningf(false, Tf_ssfaileds,
265 Tj_suspend, "tcsetpgrp", cstrerror(errno));
264 kwarnf0(KWF_PREFIX, Tf_ssfailed,
265 Tj_suspend, "tcsetpgrp");
266266 } else if (setpgid(0, restore_ttypgrp) < 0) {
267 warningf(false, Tf_ssfaileds,
268 Tj_suspend, "setpgid", cstrerror(errno));
267 kwarnf0(KWF_PREFIX, Tf_ssfailed,
268 Tj_suspend, "setpgid");
269269 }
270270 }
271271 }
279279 if (ttypgrp_ok) {
280280 if (restore_ttypgrp >= 0) {
281281 if (setpgid(0, kshpid) < 0) {
282 warningf(false, Tf_ssfaileds,
283 Tj_suspend, "setpgid", cstrerror(errno));
282 kwarnf0(KWF_PREFIX, Tf_ssfailed,
283 Tj_suspend, "setpgid");
284284 ttypgrp_ok = false;
285285 } else if (tcsetpgrp(tty_fd, kshpid) < 0) {
286 warningf(false, Tf_ssfaileds,
287 Tj_suspend, "tcsetpgrp", cstrerror(errno));
286 kwarnf0(KWF_PREFIX, Tf_ssfailed,
287 Tj_suspend, "tcsetpgrp");
288288 ttypgrp_ok = false;
289289 }
290290 }
369369 pid_t ttypgrp;
370370
371371 if ((ttypgrp = tcgetpgrp(tty_fd)) < 0) {
372 warningf(false, Tf_ssfaileds,
373 "j_init", "tcgetpgrp",
374 cstrerror(errno));
372 kwarnf0(KWF_PREFIX, Tf_ssfailed,
373 "j_init", "tcgetpgrp");
375374 ttypgrp_ok = false;
376375 break;
377376 }
385384 SS_RESTORE_DFL|SS_FORCE);
386385 if (ttypgrp_ok && kshpgrp != kshpid) {
387386 if (setpgid(0, kshpid) < 0) {
388 warningf(false, Tf_ssfaileds,
389 "j_init", "setpgid", cstrerror(errno));
387 kwarnf0(KWF_PREFIX, Tf_ssfailed,
388 "j_init", "setpgid");
390389 ttypgrp_ok = false;
391390 } else {
392391 if (tcsetpgrp(tty_fd, kshpid) < 0) {
393 warningf(false, Tf_ssfaileds,
394 "j_init", "tcsetpgrp",
395 cstrerror(errno));
392 kwarnf0(KWF_PREFIX, Tf_ssfailed,
393 "j_init", "tcsetpgrp");
396394 ttypgrp_ok = false;
397395 } else
398396 restore_ttypgrp = kshpgrp;
401399 }
402400 #ifndef MKSH_DISABLE_TTY_WARNING
403401 if (use_tty && !ttypgrp_ok)
404 warningf(false, Tf_sD_s, "warning",
402 kwarnf(KWF_PREFIX | KWF_ONEMSG | KWF_NOERRNO,
405403 "won't have full job control");
406404 #endif
407405 } else {
435433 errno = 0;
436434 /* this is gonna annoy users; complain to your distro, people! */
437435 if (nice(ness) == -1 && (eno = errno) != 0)
438 warningf(false, Tf_sD_s, "bgnice", cstrerror(eno));
436 kwarnf(KWF_VERRNO | KWF_PREFIX | KWF_ONEMSG, eno, "bgnice");
439437 #else
440438 (void)nice(ness);
441439 #endif
453451 static Proc *last_proc;
454452
455453 int rv = 0, forksleep, jwflags = JW_NONE;
454 int eno = /* stupid GCC */ 0;
456455 #ifndef MKSH_NOPROSPECTOFWORK
457456 sigset_t omask;
458457 #endif
487486 if (flags & XPIPEI) {
488487 /* continuing with a pipe */
489488 if (!last_job)
490 internal_errorf("exchild: XPIPEI and no last_job - pid %d",
491 (int)procpid);
489 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
490 "exchild: XPIPEI and no last_job - pid %ld",
491 (long)procpid);
492492 j = last_job;
493493 if (last_proc)
494494 last_proc->next = p;
519519
520520 /* create child process */
521521 forksleep = 1;
522 while ((cldpid = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
522 while ((cldpid = fork()) < 0 && (eno = errno) == EAGAIN &&
523 forksleep < 32) {
523524 if (intrsig)
524525 /* allow user to ^C out... */
525526 break;
535536 #ifndef MKSH_NOPROSPECTOFWORK
536537 sigprocmask(SIG_SETMASK, &omask, NULL);
537538 #endif
538 errorf("can't fork - try again");
539 kerrf(KWF_VERRNO | KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
540 KWF_ONEMSG, eno, "can't fork - try again");
539541 }
540542 p->pid = cldpid ? cldpid : (procpid = getpid());
541543
620622 #ifndef MKSH_SMALL
621623 if (t->type == TPIPE)
622624 unwind(LLEAVE);
623 internal_warningf("%s: execute() returned", "exchild");
625 kwarnf(KWF_INTERNAL | KWF_WARNING | KWF_TWOMSG,
626 "exchild", "execute() returned");
624627 fptreef(shl_out, 8, "%s: tried to execute {\n\t%T\n}\n",
625628 "exchild", t);
626629 shf_flush(shl_out);
697700 j = last_job;
698701 if (!j || !(j->flags & JF_STARTED)) {
699702 if (!j)
700 warningf(true, Tf_sD_s, "waitlast", "no last job");
703 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG |
704 KWF_NOERRNO, "waitlast", "no last job");
701705 else
702 internal_warningf(Tf_sD_s, "waitlast", Tnot_started);
706 kwarnf(KWF_INTERNAL | KWF_WARNING | KWF_TWOMSG | KWF_NOERRNO,
707 "waitlast", Tnot_started);
703708 #ifndef MKSH_NOPROSPECTOFWORK
704709 sigprocmask(SIG_SETMASK, &omask, NULL);
705710 #endif
883888 if (j->flags & JF_SAVEDTTY)
884889 mksh_tcset(tty_fd, &tty_state);
885890 sigprocmask(SIG_SETMASK, &omask, NULL);
886 bi_errorf(Tf_ldfailed,
887 "fg: 1st", "tcsetpgrp", tty_fd,
891 kwarnf1(KWF_VERRNO | KWF_BIERR, rv,
892 Tf_ldfailed, Tfirst, tty_fd,
888893 (long)((j->flags & JF_SAVEDTTYPGRP) ?
889 j->saved_ttypgrp : j->pgrp),
890 cstrerror(rv));
894 j->saved_ttypgrp : j->pgrp));
891895 return (1);
892896 }
893897 }
905909 if (ttypgrp_ok && (j->flags & JF_SAVEDTTY))
906910 mksh_tcset(tty_fd, &tty_state);
907911 if (ttypgrp_ok && tcsetpgrp(tty_fd, kshpgrp) < 0)
908 warningf(true, Tf_ldfailed,
909 "fg: 2nd", "tcsetpgrp", tty_fd,
910 (long)kshpgrp, cstrerror(errno));
912 kwarnf0(KWF_PREFIX | KWF_FILELINE,
913 Tf_ldfailed, "second", tty_fd,
914 (long)kshpgrp);
911915 }
912916 sigprocmask(SIG_SETMASK, &omask, NULL);
913917 bi_errorf(Tf_s_sD_s, "can't continue job",
10781082 if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE)
10791083 remove_job(async_job, "async");
10801084 if (!(j->flags & JF_STARTED)) {
1081 internal_warningf(Tf_sD_s, "j_async", Tjob_not_started);
1085 kwarnf(KWF_INTERNAL | KWF_WARNING | KWF_TWOMSG | KWF_NOERRNO,
1086 "j_async", Tjob_not_started);
10821087 return;
10831088 }
10841089 async_job = j;
10921097 if (!oldest) {
10931098 /* XXX debugging */
10941099 if (!(async_job->flags & JF_ZOMBIE) || nzombie != 1) {
1095 internal_warningf("%s: bad nzombie (%d)",
1096 "j_async", nzombie);
1100 kwarnf0(KWF_INTERNAL | KWF_WARNING | KWF_NOERRNO,
1101 "%s: bad nzombie (%d)", "j_async", nzombie);
10971102 nzombie = 0;
10981103 }
10991104 break;
12061211 (j->saved_ttypgrp = tcgetpgrp(tty_fd)) >= 0)
12071212 j->flags |= JF_SAVEDTTYPGRP;
12081213 if (tcsetpgrp(tty_fd, kshpgrp) < 0)
1209 warningf(true, Tf_ldfailed,
1210 "j_waitj:", "tcsetpgrp", tty_fd,
1211 (long)kshpgrp, cstrerror(errno));
1214 kwarnf0(KWF_PREFIX | KWF_FILELINE,
1215 Tf_ldfailed, "wait", tty_fd,
1216 (long)kshpgrp);
12121217 if (j->state == PSTOPPED) {
12131218 j->flags |= JF_SAVEDTTY;
12141219 mksh_tcget(tty_fd, &j->ttystat);
12721277 if (!(p = j->proc_list)) {
12731278 ; /* nothing */
12741279 } else if (flags & JW_PIPEST) {
1275 uint32_t num = 0;
1280 k32 num = 0;
12761281 struct tbl *vp;
12771282 kby *vt;
12781283
12901295 vp->u.array = (void *)vt;
12911296 vp = (void *)vt;
12921297 vp->areap = vp_pipest->areap;
1293 vp->ua.index = ++num;
1298 vp->ua.index = num = K32(num + 1);
12941299 vp->flag = DEFINED | ISSET | INTEGER | RDONLY |
12951300 ARRAY | INT_U | AINDEX;
12961301 got_array:
13631368 #endif
13641369
13651370 if (ksh_getrusage(RUSAGE_CHILDREN, &ru0))
1366 warningf(true, "getrusage1: %s", cstrerror(errno));
1371 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_ONEMSG, Tgetrusage);
13671372 do {
13681373 #ifndef MKSH_NOPROSPECTOFWORK
13691374 pid = waitpid(-1, &status, (WNOHANG |
13831388 goto j_sigchld_out;
13841389
13851390 if (ksh_getrusage(RUSAGE_CHILDREN, &ru1))
1386 warningf(true, "getrusage2: %s", cstrerror(errno));
1391 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_ONEMSG,
1392 Tgetrusage);
13871393
13881394 /* find job and process structures for this pid */
13891395 for (j = job_list; j != NULL; j = j->next)
13931399 found:
13941400 if (j == NULL) {
13951401 /* Can occur if process has kids, then execs shell
1396 warningf(true, "bad process waited for (pid = %d)",
1397 pid);
1402 kwarnf0(KWF_PREFIX | KWF_FILELINE | KWF_NOERRNO,
1403 "bad process waited for (pid = %d)", pid);
13981404 */
13991405 ru0 = ru1;
14001406 continue;
14551461
14561462 /* XXX debugging (nasty - interrupt routine using shl_out) */
14571463 if (!(j->flags & JF_STARTED)) {
1458 internal_warningf("check_job: job started (flags 0x%X)",
1464 kwarnf0(KWF_INTERNAL | KWF_WARNING | KWF_NOERRNO,
1465 "check_job: job started (flags 0x%X)",
14591466 (unsigned int)j->flags);
14601467 return;
14611468 }
16061613 msg = "Done";
16071614 else {
16081615 shf_snprintf(msgbuf, sizeof(msgbuf),
1609 "Done (%d)", status);
1616 TDone, status);
16101617 msg = msgbuf;
16111618 }
16121619 break;
18621869 curr = *prev;
18631870 }
18641871 if (curr != j) {
1865 internal_warningf("remove_job: job %s (%s)", Tnot_found, where);
1872 kwarnf0(KWF_INTERNAL | KWF_WARNING | KWF_NOERRNO,
1873 "remove_job: job %s (%s)", Tnot_found, where);
18661874 return;
18671875 }
18681876 *prev = curr->next;
19511959 break;
19521960 case 1:
19531961 #ifndef MKSH_DISABLE_TTY_WARNING
1954 warningf(false, "can't find controlling tty: %s",
1955 cstrerror(errno));
1962 kwarnf(KWF_PREFIX | KWF_ONEMSG, "can't find controlling tty");
19561963 #endif
19571964 break;
19581965 case 2:
19591966 #ifndef MKSH_DISABLE_TTY_WARNING
1960 warningf(false, "can't find tty fd: %s",
1961 cstrerror(errno));
1967 kwarnf(KWF_PREFIX | KWF_ONEMSG, "can't find tty fd");
19621968 #endif
19631969 break;
19641970 case 3:
1965 warningf(false, Tf_ssfaileds, "j_ttyinit",
1966 "dup of tty fd", cstrerror(errno));
1971 kwarnf0(KWF_PREFIX, Tf_ssfailed,
1972 "j_ttyinit", "dup of tty fd");
19671973 break;
19681974 case 4:
1969 warningf(false, Tf_sD_sD_s, "j_ttyinit",
1970 "can't set close-on-exec flag", cstrerror(errno));
1975 kwarnf(KWF_PREFIX | KWF_TWOMSG, "j_ttyinit",
1976 "can't set close-on-exec flag");
19711977 break;
19721978 }
19731979 }
00 /*-
1 * Copyright (c) 2009, 2010, 2011, 2013, 2014, 2016
1 * Copyright (c) 2009, 2010, 2011, 2013, 2014, 2016, 2021
22 * mirabilos <m@mirbsd.org>
33 *
44 * Provided that these terms and disclaimer and all copyright notices
2222 #include <err.h>
2323 #endif
2424
25 __RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.28 2021/10/10 20:41:17 tg Exp $");
25 __RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.31 2021/11/13 21:22:36 tg Exp $");
2626
2727 /* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */
2828 #if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0)
5454 {
5555 struct lalloc_item *lp, *lold = ptr;
5656
57 size = (size + 4095) & ~(size_t)4095;
57 size = (size + 4095U) & (size_t)~(size_t)4095;
5858
5959 if (lold && lold->len >= size)
6060 return (ptr);
7979 }
8080 #endif
8181
82 /* pre-initio() */
8283 void
8384 ainit(Area *ap)
8485 {
116117 fail:
117118 #endif
118119 #ifdef DEBUG
119 internal_warningf("rogue pointer %zX in ap %zX",
120 kwarnf0(KWF_INTERNAL | KWF_WARNING | KWF_NOERRNO,
121 "rogue pointer %zX in ap %zX",
120122 (size_t)ptr, (size_t)ap);
121123 /* try to get a coredump */
122124 abort();
123125 #else
124 internal_errorf("rogue pointer %zX", (size_t)ptr);
126 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
127 "rogue pointer %zX", (size_t)ptr);
125128 #endif
126129 }
127130 return (ap);
128131 }
129132
133 /* pre-initio() */
130134 void *
131135 aresize2(void *ptr, size_t fac1, size_t fac2, Area *ap)
132136 {
133137 if (notoktomul(fac1, fac2))
134 internal_errorf(Tintovfl, fac1, '*', fac2);
138 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
139 Tintovfl, fac1, '*', fac2);
135140 return (aresize(ptr, fac1 * fac2, ap));
136141 }
137142
143 /* pre-initio() ptr=NULL */
138144 void *
139145 aresize(void *ptr, size_t numb, Area *ap)
140146 {
148154 pp->next = lp->next;
149155 }
150156
151 if (notoktoadd(numb, sizeof(ALLOC_ITEM)) ||
152 (lp = remalloc(lp, numb + sizeof(ALLOC_ITEM))) == NULL
157 if (notoktoadd(numb, sizeof(ALLOC_ITEM))) {
158 errno = E2BIG;
159 alloc_fail:
160 if (!initio_done) {
161 SHIKATANAI write(2, SC("mksh: out of memory early\n"));
162 exit(255);
163 }
164 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF),
165 "can't allocate %zu data bytes", numb);
166 }
167 if ((lp = remalloc(lp, numb + sizeof(ALLOC_ITEM))) == NULL)
168 goto alloc_fail;
153169 #ifndef MKSH_SMALL
154 || ALLOC_ISUNALIGNED(lp)
155 #endif
156 )
157 internal_errorf(Toomem, numb);
170 if (ALLOC_ISUNALIGNED(lp)) {
171 #ifdef EPROTO
172 errno = EPROTO;
173 #endif
174 goto alloc_fail;
175 }
176 #endif
177
158178 /* area pointer and items share struct lalloc_common */
159179 /*XXX C99 §6.5(6) and footnote 72 may dislike this? */
160180 lp->next = ap->next;
22 /*-
33 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
44 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
5 * 2021
5 * 2021, 2022
66 * mirabilos <m@mirbsd.org>
77 *
88 * Provided that these terms and disclaimer and all copyright notices
2323
2424 #include "sh.h"
2525
26 __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.261 2021/10/10 21:36:53 tg Exp $");
26 __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.263 2022/01/06 22:34:58 tg Exp $");
2727
2828 /*
2929 * states while lexing word
10411041
10421042 if (*ident != '\0' && (cf & (KEYWORD | ALIAS))) {
10431043 struct tbl *p;
1044 uint32_t h = hash(ident);
1044 k32 h = hash(ident);
10451045
10461046 if ((cf & KEYWORD) && (p = ktsearch(&keywords, ident, h)) &&
10471047 (!(cf & ESACONLY) || p->val.i == ESAC ||
10981098 } else if (*ident == '\0') {
10991099 /* retain typeset et al. even when quoted */
11001100 struct tbl *tt = get_builtin((dp = wdstrip(yylval.cp, 0)));
1101 uint32_t flag = tt ? tt->flag : 0;
1101 kui flag = tt ? tt->flag : 0U;
11021102
11031103 if (flag & (DECL_UTIL | DECL_FWDR))
11041104 strlcpy(ident, dp, sizeof(ident));
12071207
12081208 if (!(iop->ioflag & IOEVAL))
12091209 ignore_backslash_newline--;
1210 }
1211
1212 void
1213 yyerror(const char *fmt, ...)
1214 {
1215 va_list va;
1216
1217 /* pop aliases and re-reads */
1218 while (source->type == SALIAS || source->type == SREREAD)
1219 source = source->next;
1220 /* zap pending input */
1221 source->str = null;
1222
1223 error_prefix(true);
1224 va_start(va, fmt);
1225 shf_vfprintf(shl_out, fmt, va);
1226 shf_putc('\n', shl_out);
1227 va_end(va);
1228 errorfz();
12291210 }
12301211
12311212 /*
14291410 alarm(0);
14301411 }
14311412 cp = Xstring(s->xs, xp);
1432 rndpush(cp);
14331413 s->start = s->str = cp;
14341414 strip_nuls(Xstring(s->xs, xp), Xlength(s->xs, xp));
14351415 /* Note: if input is all nulls, this is not eof */
0 .\" $MirOS: src/bin/mksh/lksh.1,v 1.28 2021/06/15 13:20:05 tg Exp $
0 .\" $MirOS: src/bin/mksh/lksh.1,v 1.30 2022/01/28 10:28:19 tg Exp $
11 .\"-
2 .\" Copyright (c) 2008, 2009, 2010, 2012, 2013, 2015, 2016, 2017, 2018
2 .\" Copyright © 2008, 2009, 2010, 2012, 2013, 2015, 2016, 2017,
3 .\" 2018
34 .\" mirabilos <m@mirbsd.org>
45 .\"
56 .\" Provided that these terms and disclaimer and all copyright notices
6061 . ds en \(em
6162 .\}
6263 .ie n \{\
63 . ds EM \ \*(en\ \&
64 . ds EM \ \(em\ \&
6465 .\}
6566 .el \{\
6667 . ds EM \f(TR\^\(em\^\fP
8081 .\" with -mandoc, it might implement .Mx itself, but we want to
8182 .\" use our own definition. And .Dd must come *first*, always.
8283 .\"
83 .Dd $Mdocdate: June 15 2021 $
84 .Dd $Mdocdate: January 28 2022 $
8485 .\"
8586 .\" Check which macro package we use, and do other -mdoc setup.
8687 .\"
+220
-334
main.c less more
55 /*-
66 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
77 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
8 * 2019, 2020, 2021
8 * 2019, 2020, 2021, 2022
99 * mirabilos <m@mirbsd.org>
1010 *
1111 * Provided that these terms and disclaimer and all copyright notices
2727 #define EXTERN
2828 #include "sh.h"
2929
30 #if HAVE_LANGINFO_CODESET
30 #if HAVE_POSIX_UTF8_LOCALE
31 #include <locale.h>
3132 #include <langinfo.h>
3233 #endif
33 #if HAVE_SETLOCALE_CTYPE
34 #include <locale.h>
35 #endif
36
37 __RCSID("$MirOS: src/bin/mksh/main.c,v 1.398 2021/10/12 23:18:13 tg Exp $");
34
35 __RCSID("$MirOS: src/bin/mksh/main.c,v 1.411 2022/01/27 13:45:05 tg Exp $");
36 __IDSTRING(mbsdint_h_rcsid, SYSKERN_MBSDINT_H);
37 __IDSTRING(sh_h_rcsid, MKSH_SH_H_ID);
3838
3939 #ifndef MKSHRC_PATH
4040 #define MKSHRC_PATH "~/.mkshrc"
4444 #define MKSH_DEFAULT_TMPDIR MKSH_UNIXROOT "/tmp"
4545 #endif
4646
47 #if !HAVE_SETLOCALE_CTYPE
47 #if !HAVE_POSIX_UTF8_LOCALE
4848 /* this is the “implementation-defined default locale” */
4949 #ifdef MKSH_DEFAULT_UTFLOC
5050 #define MKSH_DEFAULT_LOCALE "UTF-8"
5353 #endif
5454 #endif
5555
56 static kby isuc(const char *);
5756 static int main_init(int, const char *[], Source **, struct block **);
5857 void chvt_reinit(void);
5958 static void reclaim(void);
103102
104103 extern const char Tpipest[];
105104
106 static bool initio_done;
107
108105 /* top-level parsing and execution environment */
109106 static struct env env;
110107 struct env *e = &env;
111108
112 /* compile-time assertions */
113
114 /* this one should be defined by the standard */
115 cta(char_is_1_char, (sizeof(char) == 1) && (sizeof(signed char) == 1) &&
116 (sizeof(unsigned char) == 1));
117 cta(char_is_8_bits, ((CHAR_BIT) == 8) && ((int)(unsigned char)0xFF == 0xFF) &&
118 ((int)(unsigned char)0x100 == 0) && ((int)(unsigned char)(int)-1 == 0xFF));
109 /* many compile-time assertions */
110 mbiCTAS(main_c) {
111
112 /* require char to be 8 bit long */
113 mbiCTA(char_8bit, (CHAR_BIT) == 8 &&
114 (((unsigned int)(unsigned char)255U) == 255U) &&
115 (((unsigned int)(unsigned char)256U) == 0U) &&
116 mbiTYPE_UBITS(unsigned char) == 8U &&
117 mbiMASK_BITS(SCHAR_MAX) == 7U);
118
119 /* POSIX guarantees a 32-bit int */
120 mbiCTA(int_32bit, mbiTYPE_UBITS(unsigned int) >= 32U &&
121 mbiMASK_BITS(INT_MAX) >= 31U);
122 /* which implies unsigned long has at least 32 bit width, too */
123
119124 /* the next assertion is probably not really needed */
120 cta(short_is_2_char, sizeof(short) == 2);
121 cta(short_size_no_matter_of_signedness, sizeof(short) == sizeof(unsigned short));
125 mbiCTA(short_is_2_char, sizeof(short) == 2);
122126 /* the next assertion is probably not really needed */
123 cta(int_is_4_char, sizeof(int) == 4);
124 cta(int_size_no_matter_of_signedness, sizeof(int) == sizeof(unsigned int));
125
126 cta(long_ge_int, sizeof(long) >= sizeof(int));
127 cta(long_size_no_matter_of_signedness, sizeof(long) == sizeof(unsigned long));
127 mbiCTA(int_is_4_char, sizeof(int) == 4);
128128
129129 #ifndef MKSH_LEGACY_MODE
130 mbiCTA(basic_int32_ari,
131 mbiTYPE_UMAX(mksh_uari_t) == (UINT32_MAX) &&
132 sizeof(mksh_ari_t) <= (279 / CHAR_BIT) &&
133 sizeof(mksh_uari_t) <= (279 / CHAR_BIT) &&
134 mbiMASK_CHK(INT32_MAX) && mbiMASK_CHK(UINT32_MAX) &&
135 /* require two’s complement */
136 ((INT32_MIN) == -(INT32_MAX)-1));
130137 /* the next assertion is probably not really needed */
131 cta(ari_is_4_char, sizeof(mksh_ari_t) == 4);
138 mbiCTA(ari_is_4_char, sizeof(mksh_ari_t) == 4);
132139 /* but this is */
133 cta(ari_has_31_bit, 0 < (mksh_ari_t)(((((mksh_ari_t)1 << 15) << 15) - 1) * 2 + 1));
140 mbiCTA(ari_has_31_bit, mbiMASK_BITS(INT32_MAX) == 31);
134141 /* the next assertion is probably not really needed */
135 cta(uari_is_4_char, sizeof(mksh_uari_t) == 4);
136 /* but the next three are; we REQUIRE unsigned integer wraparound */
137 cta(uari_has_31_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 2 + 1));
138 cta(uari_has_32_bit, 0 < (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3));
139 cta(uari_wrap_32_bit,
140 (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 3) >
141 (mksh_uari_t)(((((mksh_uari_t)1 << 15) << 15) - 1) * 4 + 4));
142 mbiCTA(uari_is_4_char, sizeof(mksh_uari_t) == 4);
143 mbiCTA(uari_is_32_bit, mbiTYPE_UBITS(mksh_uari_t) == 32);
144 #else
145 mbiCTA(long_complement, (LONG_MIN) == -(LONG_MAX)-1);
142146 #endif
143147 /* these are always required */
144 cta(ari_is_signed, (mksh_ari_t)-1 < (mksh_ari_t)0);
145 cta(uari_is_unsigned, (mksh_uari_t)-1 > (mksh_uari_t)0);
148 mbiCTA(ari_is_signed, !mbiTYPE_ISU(mksh_ari_t));
149 mbiCTA(uari_is_unsigned, mbiTYPE_ISU(mksh_uari_t));
146150 /* we require these to have the precisely same size and assume 2s complement */
147 cta(ari_size_no_matter_of_signedness, sizeof(mksh_ari_t) == sizeof(mksh_uari_t));
148
149 cta(sizet_size_no_matter_of_signedness, sizeof(ssize_t) == sizeof(size_t));
150 cta(sizet_voidptr_same_size, sizeof(size_t) == sizeof(void *));
151 cta(sizet_funcptr_same_size, sizeof(size_t) == sizeof(void (*)(void)));
151 mbiCTA(ari_size_no_matter_of_signedness,
152 sizeof(mksh_ari_t) == sizeof(mksh_uari_t));
153
152154 /* our formatting routines assume this */
153 cta(ptr_fits_in_long, sizeof(size_t) <= sizeof(long));
154 cta(ari_fits_in_long, sizeof(mksh_ari_t) <= sizeof(long));
155 mbiCTA(ptr_fits_in_long, sizeof(size_t) <= sizeof(long));
156 mbiCTA(ari_fits_in_long, sizeof(mksh_ari_t) <= sizeof(long));
157
158 };
159 /* end of compile-time asserts */
155160
156161 static mksh_uari_t
157162 rndsetup(void)
158163 {
159 register uint32_t h;
164 register k32 h;
160165 struct {
161166 ALLOC_ITEM alloc_INT;
162 void *dataptr, *stkptr, *mallocptr;
167 void *bssptr, *dataptr, *stkptr, *mallocptr;
163168 #if defined(__GLIBC__) && (__GLIBC__ >= 2)
164169 sigjmp_buf jbuf;
165170 #endif
173178 /* undo what alloc() did to the malloc result address */
174179 bufptr = (void *)(cp - sizeof(ALLOC_ITEM));
175180 /* PIE or something similar provides us with deltas here */
176 bufptr->dataptr = &rndsetupstate;
181 bufptr->bssptr = &rndsetupstate;
182 bufptr->dataptr = &e;
177183 /* ASLR in at least Windows, Linux, some BSDs */
178184 bufptr->stkptr = &bufptr;
179185 /* randomised malloc in BSD (and possibly others) */
182188 /* glibc pointer guard */
183189 sigsetjmp(bufptr->jbuf, 1);
184190 #endif
185 /* introduce variation (and yes, second arg MBZ for portability) */
191 /* introduce variation (cannot use gettimeofday *tzp portably) */
186192 mksh_TIME(bufptr->tv);
187193
188194 #ifdef MKSH_ALLOC_CATCH_UNDERRUNS
194200 return ((mksh_uari_t)h);
195201 }
196202
203 /* pre-initio() */
197204 void
198205 chvt_reinit(void)
199206 {
207214 Tmksh, NULL
208215 };
209216
217 #ifndef MKSH_EARLY_LOCALE_TRACKING
210218 static kby
211219 isuc(const char *cx) {
212 char *cp, *x;
213 kby rv = 0;
220 const char *cp;
214221
215222 if (!cx || !*cx)
216223 return (0);
217224
218 /* uppercase a string duplicate */
219 strdupx(x, cx, ATEMP);
220 cp = x;
221 while ((*cp = ksh_toupper(*cp)))
225 if ((cp = cstrchr(cx, '.')))
222226 ++cp;
223
224 /* check for UTF-8 */
225 if (vstrstr(x, "UTF-8") || vstrstr(x, "UTF8"))
226 rv = 1;
227
228 /* free copy and out */
229 afree(x, ATEMP);
227 else
228 cp = cx;
229 if (!isCh(cp[0], 'U', 'u') ||
230 !isCh(cp[1], 'T', 't') ||
231 !isCh(cp[2], 'F', 'f'))
232 return (0);
233 cp += isch(cp[3], '-') ? 4 : 3;
234 return (isch(*cp, '8') && (isch(cp[1], '@') || !cp[1]));
235 }
236 #endif
237
238 kby
239 kshname_islogin(const char **kshbasenamep)
240 {
241 const char *cp;
242 size_t o;
243 kby rv;
244
245 /* determine the basename (without '-' or path) of the executable */
246 cp = kshname;
247 o = 0;
248 while ((rv = cp[o++])) {
249 if (mksh_cdirsep(rv)) {
250 cp += o;
251 o = 0;
252 }
253 }
254 rv = isch(*cp, '-') || isch(*kshname, '-');
255 if (isch(*cp, '-'))
256 ++cp;
257 if (!*cp)
258 cp = empty_argv[0];
259 *kshbasenamep = cp;
230260 return (rv);
231261 }
232262
263 /* pre-initio() */
233264 static int
234265 main_init(int argc, const char *argv[], Source **sp, struct block **lp)
235266 {
236 int argi, i;
267 int argi = 0, i;
237268 Source *s = NULL;
238269 struct block *l;
239270 unsigned char restricted_shell = 0, errexit, utf_flag;
271302 /* initialise permanent Area */
272303 ainit(&aperm);
273304 /* max. name length: -2147483648 = 11 (+ NUL) */
274 vtemp = alloc(offsetof(struct tbl, name[0]) + 12, APERM);
305 vtemp = alloc(offsetof(struct tbl, name[0]) + 12U, APERM);
275306
276307 /* set up base environment */
277308 env.type = E_NONE;
279310 /* set up global l->vars and l->funs */
280311 newblock();
281312
282 /* Do this first so output routines (eg, errorf, shellf) can work */
313 /* Do this first so output routines (eg. kwarnf, shellf) can work */
283314 initio();
284315
285 /* determine the basename (without '-' or path) of the executable */
286 ccp = kshname;
287 goto begin_parsing_kshname;
288 while ((i = ccp[argi++])) {
289 if (mksh_cdirsep(i)) {
290 ccp += argi;
291 begin_parsing_kshname:
292 argi = 0;
293 }
294 }
295 Flag(FLOGIN) = (ord(*ccp) == ORD('-')) || (ord(*kshname) == ORD('-'));
296 if (ord(*ccp) == ORD('-'))
297 ++ccp;
298 if (!*ccp)
299 ccp = empty_argv[0];
316 /* check kshname: leading dash, determine basename */
317 Flag(FLOGIN) = kshname_islogin(&ccp);
300318
301319 /*
302320 * Turn on nohup by default. (AT&T ksh does not have a nohup
337355 if (argi < 0)
338356 return (1);
339357 /* called as rsh, rmksh, -rsh, RKSH.EXE, etc.? */
340 if (ksh_eq(*ccp, 'R', 'r')) {
358 if (isCh(*ccp, 'R', 'r')) {
341359 ++ccp;
342360 ++restricted_shell;
343361 }
344362 #if defined(MKSH_BINSHPOSIX) || defined(MKSH_BINSHREDUCED)
345363 /* are we called as -rsh or /bin/sh or SH.EXE or so? */
346 if (ksh_eq(ccp[0], 'S', 's') &&
347 ksh_eq(ccp[1], 'H', 'h')) {
364 if (isCh(ccp[0], 'S', 's') &&
365 isCh(ccp[1], 'H', 'h')) {
348366 /* either also turns off braceexpand */
349367 #ifdef MKSH_BINSHPOSIX
350368 /* enable better POSIX conformance */
417435 * by the environment or the user. Also, we want tab completion
418436 * on in vi by default.
419437 */
420 change_flag(FEMACS, OF_SPECIAL, true);
438 change_flag(FEMACS, OF_INTERNAL, true);
421439 #if !MKSH_S_NOVI
422440 Flag(FVITABCOMPLETE) = 1;
423441 #endif
511529 } else if (Flag(FCOMMAND)) {
512530 s = pushs(SSTRINGCMDLINE, ATEMP);
513531 if (!(s->start = s->str = argv[argi++]))
514 errorf(Tf_optdcs, 'c', Treq_arg);
532 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
533 KWF_TWOMSG | KWF_NOERRNO, Tdc, Treq_arg);
515534 while (*s->str) {
516535 if (ctype(*s->str, C_QUOTE))
517536 break;
548567 SHF_MAPHI | SHF_CLEXEC);
549568 if (s->u.shf == NULL) {
550569 shl_stdout_ok = false;
551 warningf(true, Tf_sD_s, s->file, cstrerror(errno));
570 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_ONEMSG, s->file);
552571 /* mandated by SUSv4 */
553572 exstat = 127;
554573 unwind(LERROR);
571590
572591 /* this bizarreness is mandated by POSIX */
573592 if (Flag(FTALKING) && fstat(0, &s_stdin) >= 0 &&
574 S_ISCHR(s_stdin.st_mode))
593 (S_ISCHR(s_stdin.st_mode) || S_ISFIFO(s_stdin.st_mode)))
575594 reset_nonblock(0);
576595
577596 /* initialise job control */
634653 /* auto-detect from locale or environment */
635654 case 4:
636655 #ifndef MKSH_EARLY_LOCALE_TRACKING
637 #if HAVE_SETLOCALE_CTYPE
656 #if HAVE_POSIX_UTF8_LOCALE
638657 ccp = setlocale(LC_CTYPE, "");
639 #if HAVE_LANGINFO_CODESET
640658 if (!isuc(ccp))
641659 ccp = nl_langinfo(CODESET);
642 #endif
643660 if (!isuc(ccp))
644661 ccp = null;
645662 #endif
704721 * user will know why things broke.
705722 */
706723 if (!current_wd[0] && Flag(FTALKING))
707 warningf(false, "can't determine current directory");
724 kwarnf(KWF_PREFIX | KWF_ONEMSG | KWF_NOERRNO,
725 "can't determine current directory");
708726
709727 if (Flag(FLOGIN))
710728 include(MKSH_SYSTEM_PROFILE, 0, NULL, true);
824842 unwind(i);
825843 /* NOTREACHED */
826844 default:
827 internal_errorf(Tunexpected_type, Tunwind, Tsource, i);
845 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
846 Tunexpected_type, Tunwind, Tsource, i);
828847 /* NOTREACHED */
829848 }
830849 }
891910 unwind(i);
892911 /* NOTREACHED */
893912 }
894 internal_errorf(Tf_cant_s, Tshell,
895 i == LBREAK ? Tbreak : Tcontinue);
913 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
914 Tf_cant_s, Tshell, i == LBREAK ? Tbreak : Tcontinue);
896915 /* NOTREACHED */
897916 case LINTR:
898917 /* we get here if SIGINT not caught or ignored */
936955 default:
937956 source = old_source;
938957 quitenv(NULL);
939 internal_errorf(Tunexpected_type, Tunwind, Tshell, i);
958 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
959 Tunexpected_type, Tunwind, Tshell, i);
940960 /* NOTREACHED */
941961 }
942962 while (/* CONSTCOND */ 1) {
12501270 goto got_fd;
12511271 }
12521272 #endif
1253 if ((fd = open(T_devtty, O_RDWR, 0)) >= 0) {
1273 if ((fd = open("/dev/tty", O_RDWR, 0)) >= 0) {
12541274 do_close = true;
12551275 goto got_fd;
12561276 }
12921312 return (rv);
12931313 }
12941314
1295 /* A shell error occurred (eg, syntax error, etc.) */
1296
1297 #define VWARNINGF_ERRORPREFIX 1
1298 #define VWARNINGF_FILELINE 2
1299 #define VWARNINGF_BUILTIN 4
1300 #define VWARNINGF_INTERNAL 8
1301
1302 static void vwarningf(unsigned int, const char *, va_list)
1303 MKSH_A_FORMAT(__printf__, 2, 0);
1304
1305 static void
1306 vwarningf(unsigned int flags, const char *fmt, va_list ap)
1307 {
1308 if (fmt) {
1309 if (flags & VWARNINGF_INTERNAL)
1310 shf_fprintf(shl_out, Tf_sD_, "internal error");
1311 if (flags & VWARNINGF_ERRORPREFIX)
1312 error_prefix(tobool(flags & VWARNINGF_FILELINE));
1313 if ((flags & VWARNINGF_BUILTIN) &&
1314 /* not set when main() calls parse_args() */
1315 builtin_argv0 && builtin_argv0 != kshname)
1316 shf_fprintf(shl_out, Tf_sD_, builtin_argv0);
1317 shf_vfprintf(shl_out, fmt, ap);
1318 shf_putc('\n', shl_out);
1319 }
1320 shf_flush(shl_out);
1321 }
1322
1323 void
1324 errorfx(int rc, const char *fmt, ...)
1325 {
1326 va_list va;
1327
1328 exstat = rc;
1329
1330 /* debugging: note that stdout not valid */
1331 shl_stdout_ok = false;
1332
1333 va_start(va, fmt);
1334 vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE, fmt, va);
1335 va_end(va);
1336 unwind(LERROR);
1337 }
1338
1339 void
1340 errorf(const char *fmt, ...)
1341 {
1342 va_list va;
1343
1344 exstat = 1;
1345
1346 /* debugging: note that stdout not valid */
1347 shl_stdout_ok = false;
1348
1349 va_start(va, fmt);
1350 vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE, fmt, va);
1351 va_end(va);
1352 unwind(LERROR);
1353 }
1354
1355 /* like errorf(), but no unwind is done */
1356 void
1357 warningf(bool fileline, const char *fmt, ...)
1358 {
1359 va_list va;
1360
1361 va_start(va, fmt);
1362 vwarningf(VWARNINGF_ERRORPREFIX | (fileline ? VWARNINGF_FILELINE : 0),
1363 fmt, va);
1364 va_end(va);
1365 }
1366
1367 /*
1368 * Used by built-in utilities to prefix shell and utility name to message
1369 * (also unwinds environments for special builtins).
1370 */
1371 void
1372 bi_errorf(const char *fmt, ...)
1373 {
1374 va_list va;
1375
1376 /* debugging: note that stdout not valid */
1377 shl_stdout_ok = false;
1378
1379 exstat = 1;
1380
1381 va_start(va, fmt);
1382 vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE |
1383 VWARNINGF_BUILTIN, fmt, va);
1384 va_end(va);
1385
1386 /* POSIX special builtins cause non-interactive shells to exit */
1387 if (builtin_spec) {
1388 builtin_argv0 = NULL;
1389 /* may not want to use LERROR here */
1390 unwind(LERROR);
1391 }
1392 }
1393
1394 /*
1395 * Used by functions called by builtins and not:
1396 * identical to errorfx if first argument is nil,
1397 * like bi_errorf storing the errorlevel into it otherwise
1398 */
1399 void
1400 maybe_errorf(int *ep, int rc, const char *fmt, ...)
1401 {
1402 va_list va;
1403
1404 /* debugging: note that stdout not valid */
1405 shl_stdout_ok = false;
1406
1407 exstat = rc;
1408
1409 va_start(va, fmt);
1410 vwarningf(VWARNINGF_ERRORPREFIX | VWARNINGF_FILELINE |
1411 (ep ? VWARNINGF_BUILTIN : 0), fmt, va);
1412 va_end(va);
1413
1414 if (!ep)
1415 goto and_out;
1416 *ep = rc;
1417
1418 /* POSIX special builtins cause non-interactive shells to exit */
1419 if (builtin_spec) {
1420 builtin_argv0 = NULL;
1421 /* may not want to use LERROR here */
1422 and_out:
1423 unwind(LERROR);
1424 }
1425 }
1426
1427 /* Called when something that shouldn't happen does */
1428 void
1429 internal_errorf(const char *fmt, ...)
1430 {
1431 va_list va;
1432
1433 exstat = 0xFF;
1434 if (trap_exstat != -1)
1435 trap_exstat = exstat;
1436
1437 va_start(va, fmt);
1438 vwarningf(VWARNINGF_INTERNAL, fmt, va);
1439 va_end(va);
1440 unwind(LERROR);
1441 }
1442
1443 void
1444 internal_warningf(const char *fmt, ...)
1445 {
1446 va_list va;
1447
1448 va_start(va, fmt);
1449 vwarningf(VWARNINGF_INTERNAL, fmt, va);
1450 va_end(va);
1451 }
1452
1453 /* used by error reporting functions to print "ksh: .kshrc[25]: " */
1454 void
1455 error_prefix(bool fileline)
1456 {
1457 /* Avoid foo: foo[2]: ... */
1458 if (!fileline || !source || !source->file ||
1459 strcmp(source->file, kshname) != 0)
1460 shf_fprintf(shl_out, Tf_sD_, kshname +
1461 (*kshname == '-' ? 1 : 0));
1462 if (fileline && source && source->file != NULL) {
1463 shf_fprintf(shl_out, "%s[%lu]: ", source->file,
1464 (unsigned long)(source->errline ?
1465 source->errline : source->line));
1466 source->errline = 0;
1467 }
1468 }
1469
14701315 /* printf to shl_out (stderr) with flush */
14711316 void
14721317 shellf(const char *fmt, ...)
14731318 {
14741319 va_list va;
14751320
1476 if (!initio_done)
1477 /* shl_out may not be set up yet... */
1478 return;
14791321 va_start(va, fmt);
14801322 shf_vfprintf(shl_out, fmt, va);
14811323 va_end(va);
14891331 va_list va;
14901332
14911333 if (!shl_stdout_ok)
1492 internal_errorf("shl_stdout not valid");
1334 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_ONEMSG | KWF_NOERRNO,
1335 "shl_stdout not valid");
14931336 va_start(va, fmt);
14941337 shf_vfprintf(shl_stdout, fmt, va);
14951338 va_end(va);
15131356 #endif
15141357 struct shf shf_iob[NSHF_IOB];
15151358
1359 /* pre-initio() */
15161360 void
15171361 initio(void)
15181362 {
15241368 shf_fdopen(1, SHF_WR, shl_stdout);
15251369 shf_fdopen(2, SHF_WR, shl_out);
15261370 shf_fdopen(2, SHF_WR, shl_xtrace);
1371 initio_done = true;
15271372 #ifdef DF
15281373 if ((lfp = getenv("SDMKSH_PATH")) == NULL) {
15291374 if ((lfp = getenv("HOME")) == NULL || !mksh_abspath(lfp))
1530 errorf("can't get home directory");
1375 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_ONEMSG |
1376 KWF_NOERRNO, "can't get home directory");
15311377 strpathx(lfp, lfp, "mksh-dbg.txt", 1);
15321378 }
15331379
15341380 if ((shl_dbg_fd = open(lfp, O_WRONLY | O_APPEND | O_CREAT, 0600)) < 0)
1535 errorf("can't open debug output file %s", lfp);
1381 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_TWOMSG,
1382 lfp, "can't open debug output file");
15361383 if (shl_dbg_fd < FDBASE) {
15371384 int nfd;
15381385
1539 nfd = fcntl(shl_dbg_fd, F_DUPFD, FDBASE);
1386 if ((nfd = fcntl(shl_dbg_fd, F_DUPFD, FDBASE)) == -1)
1387 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_ONEMSG,
1388 "can't dup debug output file");
15401389 close(shl_dbg_fd);
1541 if ((shl_dbg_fd = nfd) == -1)
1542 errorf("can't dup debug output file");
1390 shl_dbg_fd = nfd;
15431391 }
15441392 fcntl(shl_dbg_fd, F_SETFD, FD_CLOEXEC);
15451393 shf_fdopen(shl_dbg_fd, SHF_WR, shl_dbg);
15461394 DF("=== open ===");
1547 #endif
1548 initio_done = true;
1395 initio_done = 2;
1396 #endif
15491397 }
15501398
15511399 /* A dup2() with error checking */
15551403 int rv;
15561404
15571405 if (((rv = dup2(ofd, nfd)) < 0) && !errok && (errno != EBADF))
1558 errorf(Ttoo_many_files, ofd, nfd, cstrerror(errno));
1406 kerrf0(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE,
1407 Ttoo_many_files, ofd, nfd);
15591408
15601409 #ifdef __ultrix
15611410 /*XXX imake style */
15801429 (errno == EBADF || errno == EPERM))
15811430 return (-1);
15821431 if (nfd < FDBASE || nfd > (int)(kui)FDMAXNUM)
1583 errorf(Ttoo_many_files, fd, nfd, cstrerror(errno));
1432 kerrf0(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE,
1433 Ttoo_many_files, fd, nfd);
15841434 if (fcntl(nfd, F_SETFD, FD_CLOEXEC) == -1)
1585 internal_warningf(Tcloexec_failed, "set", nfd,
1586 cstrerror(errno));
1435 kwarnf0(KWF_INTERNAL | KWF_WARNING, Tcloexec_failed,
1436 "set", nfd);
15871437 return (nfd);
15881438 }
15891439
16081458 int lpv[2];
16091459
16101460 if (pipe(lpv) < 0)
1611 errorf("can't create pipe - try again");
1461 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE | KWF_ONEMSG,
1462 "pipe");
16121463 pv[0] = savefd(lpv[0]);
16131464 if (pv[0] != lpv[0])
16141465 close(lpv[0]);
16451496 illegal_fd_name:
16461497 if (emsgp)
16471498 *emsgp = "illegal file descriptor name";
1499 errno = EINVAL;
16481500 return (-1);
16491501 }
16501502
16661518 *emsgp = (fl == O_WRONLY) ?
16671519 "fd not open for reading" :
16681520 "fd not open for writing";
1521 #ifdef ENXIO
1522 errno = ENXIO;
1523 #else
1524 errno = EBADF;
1525 #endif
16691526 return (-1);
16701527 }
16711528 return (fd);
17301587 return (fd);
17311588 if (emsgp)
17321589 *emsgp = "no coprocess";
1590 errno = EBADF;
17331591 return (-1);
17341592 }
17351593
17701628 dir = tmpdir ? tmpdir : MKSH_DEFAULT_TMPDIR;
17711629 /* add "/shXXXXXX.tmp" plus NUL */
17721630 len = strlen(dir);
1773 checkoktoadd(len, offsetof(struct temp, tffn[0]) + 14);
1774 tp = alloc(offsetof(struct temp, tffn[0]) + 14 + len, ap);
1775
1631 checkoktoadd(len, offsetof(struct temp, tffn[0]) + 14U);
1632 cp = alloc(offsetof(struct temp, tffn[0]) + 14U + len, ap);
1633
1634 tp = (void *)cp;
17761635 tp->shf = NULL;
17771636 tp->pid = procpid;
17781637 tp->type = type;
17791638
1780 if (stat(dir, &sb) || !S_ISDIR(sb.st_mode)) {
1781 tp->tffn[0] = '\0';
1782 goto maketemp_out;
1783 }
1784
1785 cp = (void *)tp;
17861639 cp += offsetof(struct temp, tffn[0]);
17871640 memcpy(cp, dir, len);
17881641 cp += len;
17891642 memstr(cp, "/shXXXXXX.tmp");
1643
1644 if (stat(dir, &sb) || !S_ISDIR(sb.st_mode))
1645 goto maketemp_out;
1646
17901647 /* point to the first of six Xes */
17911648 cp += 3;
17921649
18361693 static void tgrow(struct table *);
18371694 static int tnamecmp(const void *, const void *);
18381695
1696 /* pre-initio() tp->tbls=NULL tp->tshift=INIT_TBLSHIFT-1 */
18391697 static void
18401698 tgrow(struct table *tp)
18411699 {
18441702 struct tbl **ntblp, **otblp = tp->tbls;
18451703
18461704 if (tp->tshift > 29)
1847 internal_errorf("hash table size limit reached");
1705 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_ONEMSG | KWF_NOERRNO,
1706 "hash table size limit reached");
18481707
18491708 /* calculate old size, new shift and new size */
18501709 osize = (size_t)1 << (tp->tshift++);
18861745 afree(otblp, tp->areap);
18871746 }
18881747
1748 /* pre-initio() initshift=0 */
18891749 void
18901750 ktinit(Area *ap, struct table *tp, kby initshift)
18911751 {
18981758
18991759 /* table, name (key) to search for, hash(name), rv pointer to tbl ptr */
19001760 struct tbl *
1901 ktscan(struct table *tp, const char *name, uint32_t h, struct tbl ***ppp)
1761 ktscan(struct table *tp, const char *name, k32 h, struct tbl ***ppp)
19021762 {
19031763 size_t j, perturb, mask;
19041764 struct tbl **pp, *p;
19231783
19241784 /* table, name (key) to enter, hash(n) */
19251785 struct tbl *
1926 ktenter(struct table *tp, const char *n, uint32_t h)
1786 ktenter(struct table *tp, const char *n, k32 h)
19271787 {
19281788 struct tbl **pp, *p;
19291789 size_t len;
19401800
19411801 /* create new tbl entry */
19421802 len = strlen(n);
1943 checkoktoadd(len, offsetof(struct tbl, name[0]) + 1);
1803 checkoktoadd(len, offsetof(struct tbl, name[0]) + 1U);
19441804 p = alloc(offsetof(struct tbl, name[0]) + ++len, tp->areap);
19451805 p->flag = 0;
19461806 p->type = 0;
20751935 }
20761936
20771937 #ifdef MKSH_ENVDIR
2078 #if HAVE_SETLOCALE_CTYPE
1938 #if HAVE_POSIX_UTF8_LOCALE
20791939 # error MKSH_ENVDIR has not been adapted to work with POSIX locale!
20801940 #else
20811941 static void
20891949 struct dirent *dent;
20901950
20911951 if ((dirp = opendir(MKSH_ENVDIR)) == NULL) {
2092 warningf(false, "cannot read environment from %s: %s",
2093 MKSH_ENVDIR, cstrerror(errno));
1952 kwarnf(KWF_PREFIX | KWF_TWOMSG, MKSH_ENVDIR,
1953 "can't read environment");
20941954 return;
20951955 }
20961956 XinitN(xs, 256, ATEMP);
21001960 if (skip_varname(dent->d_name, true)[0] == '\0') {
21011961 strpathx(xp, MKSH_ENVDIR, dent->d_name, 1);
21021962 if (!(shf = shf_open(xp, O_RDONLY, 0, 0))) {
2103 warningf(false,
2104 "cannot read environment %s from %s: %s",
2105 dent->d_name, MKSH_ENVDIR,
2106 cstrerror(errno));
1963 kwarnf(KWF_PREFIX | KWF_THREEMSG, MKSH_ENVDIR,
1964 dent->d_name, "can't read environment");
21071965 goto read_envfile;
21081966 }
21091967 afree(xp, ATEMP);
21191977 XcheckN(xs, xp, 128);
21201978 }
21211979 if (n < 0) {
2122 warningf(false,
2123 "cannot read environment %s from %s: %s",
2124 dent->d_name, MKSH_ENVDIR,
2125 cstrerror(shf_errno(shf)));
1980 kwarnf(KWF_VERRNO | KWF_PREFIX | KWF_THREEMSG,
1981 shf_errno(shf), MKSH_ENVDIR,
1982 dent->d_name, "can't read environment");
21261983 } else {
21271984 *xp = '\0';
1985 rndpush(Xstring(xs, xp), Xlength(xs, xp));
21281986 xp = Xstring(xs, xp);
2129 rndpush(xp);
21301987 typeset(xp, IMPORT | EXPORT, 0, 0, 0);
21311988 }
21321989 shf_close(shf);
21331990 }
21341991 goto read_envfile;
21351992 } else if (errno)
2136 warningf(false, "cannot read environment from %s: %s",
2137 MKSH_ENVDIR, cstrerror(errno));
1993 kwarnf(KWF_PREFIX | KWF_TWOMSG, MKSH_ENVDIR,
1994 "can't read environment");
21381995 closedir(dirp);
21391996 Xfree(xs, xp);
21401997 }
21522009
21532010 wp = (const char **)environ;
21542011 while (*wp != NULL) {
2155 rndpush(*wp);
2012 rndpush(*wp, strlen(*wp));
21562013 typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
21572014 #ifdef MKSH_EARLY_LOCALE_TRACKING
2158 if (ord((*wp)[0]) == ORD('L') && (
2159 (ord((*wp)[1]) == ORD('C') && ord((*wp)[2]) == ORD('_')) ||
2015 if (isch((*wp)[0], 'L') && (
2016 (isch((*wp)[1], 'C') && isch((*wp)[2], '_')) ||
21602017 !strcmp(*wp, "LANG"))) {
21612018 const char **P;
21622019
21802037 recheck_ctype(void)
21812038 {
21822039 const char *ccp;
2183
2184 /*XXX OSX has LC_CTYPE=UTF-8 */
2040 #if !HAVE_POSIX_UTF8_LOCALE
2041 const char *cdp;
2042 #endif
2043
2044 /* determine active LC_CTYPE value */
21852045 ccp = str_val(global("LC_ALL"));
2186 if (ccp == null)
2046 if (!*ccp)
21872047 ccp = str_val(global("LC_CTYPE"));
2188 if (ccp == null)
2048 if (!*ccp)
21892049 ccp = str_val(global("LANG"));
2190 #if !HAVE_SETLOCALE_CTYPE
2191 /*XXX == null? this :- or - ? */
2192 if (ccp == null)
2050 #if !HAVE_POSIX_UTF8_LOCALE
2051 if (!*ccp)
21932052 ccp = MKSH_DEFAULT_LOCALE;
21942053 #endif
2195 /*XXX check either the parameters directly or setlocale, not both */
2196 UTFMODE = isuc(ccp);
2197 #if HAVE_SETLOCALE_CTYPE
2198 ccp = setlocale(LC_CTYPE, ccp);
2199 #if HAVE_LANGINFO_CODESET
2200 /*XXX setlocale without nl_langinfo(CODESET) makes no sense for us */
2201 if (!isuc(ccp))
2202 ccp = nl_langinfo(CODESET);
2203 #endif
2204 if (isuc(ccp))
2205 UTFMODE = 1;
2206 #endif
2054
2055 /* determine codeset used */
2056 #if HAVE_POSIX_UTF8_LOCALE
2057 errno = EINVAL;
2058 if (!setlocale(LC_CTYPE, ccp)) {
2059 kwarnf(KWF_PREFIX | KWF_FILELINE | KWF_ONEMSG, "setlocale");
2060 return;
2061 }
2062 ccp = nl_langinfo(CODESET);
2063 #else
2064 /* tacked on to a locale name or just a codeset? */
2065 if ((cdp = cstrchr(ccp, '.')))
2066 ccp = cdp + 1;
2067 #endif
2068
2069 /* see whether it’s UTF-8 */
2070 UTFMODE = 0;
2071 if (!isCh(ccp[0], 'U', 'u') ||
2072 !isCh(ccp[1], 'T', 't') ||
2073 !isCh(ccp[2], 'F', 'f'))
2074 return;
2075 ccp += isch(ccp[3], '-') ? 4 : 3;
2076 if (!isch(*ccp, '8'))
2077 return;
2078 ++ccp;
2079 /* verify nothing untoward trails the string */
2080 #if !HAVE_POSIX_UTF8_LOCALE
2081 if (cdp) {
2082 /* tacked onto a locale name */
2083 if (*ccp && !isch(*ccp, '@'))
2084 return;
2085 } else
2086 /* OSX has a "UTF-8" locale… */
2087 #endif
2088 /* just a codeset so require EOS */
2089 if (*ccp != '\0')
2090 return;
2091 /* positively identified as UTF-8 */
2092 UTFMODE = 1;
22072093 }
22082094 #endif
22092095
0 /*-
1 * MirBSD sanitisation attempt for C integer madness
2 *
3 * Published under Ⓕ CC0
4 */
5
6 #ifndef SYSKERN_MBSDINT_H
7 #define SYSKERN_MBSDINT_H "$MirOS: src/bin/mksh/mbsdint.h,v 1.2 2022/01/28 03:49:12 tg Exp $"
8
9 /* if you have <sys/types.h> and/or <stdint.h>, include them before this */
10
11 #if !defined(_KERNEL) && !defined(_STANDALONE)
12 #include <limits.h>
13 #include <stddef.h>
14 #else
15 #include <sys/cdefs.h>
16 #include <sys/limits.h>
17 #include <sys/stddef.h>
18 #endif
19
20 /* should be in <sys/cdefs.h> via <limits.h> */
21 #ifndef __predict_true
22 #if defined(__GNUC__) && (__GNUC__ >= 3) /* 2.96, but keep it simple here */
23 #define __predict_true(exp) __builtin_expect(!!(exp), 1)
24 #define __predict_false(exp) __builtin_expect(!!(exp), 0)
25 #else
26 #define __predict_true(exp) (!!(exp))
27 #define __predict_false(exp) (!!(exp))
28 #endif /* !GCC 3.x */
29 #endif /* ndef(__predict_true) */
30
31 #if !defined(SIZE_MAX) && defined(SIZE_T_MAX)
32 #define SIZE_MAX SIZE_T_MAX
33 #endif
34
35 /* compile-time assertions: mbiCTAS(srcf_c) { … }; */
36 #define mbiCTAS(name) struct ctassert_ ## name
37 #define mbiCTA(name,cond) char cta_ ## name [(cond) ? 1 : -1]
38 /* special CTAs */
39 #define mbiCTA_TYPE_NOTF(type) char ctati_ ## type [((type)0.5 == 0) ? 1 : -1]
40
41 /* largest integer */
42 #if defined(INTMAX_MIN)
43 #define mbiHUGE_S intmax_t
44 #define mbiHUGE_MIN INTMAX_MIN
45 #define mbiHUGE_MAX INTMAX_MAX
46 #define mbiHUGE_U uintmax_t
47 #define mbiHUGE_UMAX UINTMAX_MAX
48 #elif defined(LLONG_MIN)
49 #define mbiHUGE_S long long
50 #define mbiHUGE_MIN LLONG_MIN
51 #define mbiHUGE_MAX LLONG_MAX
52 #define mbiHUGE_U unsigned long long
53 #define mbiHUGE_UMAX ULLONG_MAX
54 #else
55 #define mbiHUGE_S long
56 #define mbiHUGE_MIN LONG_MIN
57 #define mbiHUGE_MAX LONG_MAX
58 #define mbiHUGE_U unsigned long
59 #define mbiHUGE_UMAX ULONG_MAX
60 #endif
61
62 /* kinds of types */
63 /* runtime only, but see mbiCTA_TYPE_NOTF */
64 #define mbiTYPE_ISF(type) ((double)0.5 == (double)(type)0.5)
65 /* compile-time and runtime */
66 #define mbiTYPE_ISU(type) ((type)-1 > 0)
67 /* limits of types */
68 #define mbiTYPE_UMAX(type) ((type)~(type)0)
69 #define mbiTYPE_UBITS(type) mbiMASK_BITS(mbiTYPE_UMAX(type))
70 /* calculation by Hallvard B Furuseth (from comp.lang.c), up to 2039 bits */
71 #define mbiMASK_BITS(maxv) ((unsigned int)((maxv) / ((maxv) % 255 + 1) / \
72 255 % 255 * 8 + 7 - 86 / ((maxv) % 255 + 12)))
73
74 /* ensure v is a positive (2ⁿ-1) number (n>0), up to 279 bits */
75 #define mbiMASK_CHK(v) ((v) > 0 ? mbi_maskchk31_1((v)) : 0)
76 #define mbi_maskchks(v,m,o,n) (v <= m ? o : ((v & m) == m) && n)
77 #define mbi_maskchk31s(v,n) mbi_maskchks(v, 0x7FFFFFFFUL, \
78 mbi_maskchk16(v), n)
79 #define mbi_maskchk31_1(v) mbi_maskchk31s(v, mbi_maskchk31_2(v >> 31))
80 #define mbi_maskchk31_2(v) mbi_maskchk31s(v, mbi_maskchk31_3(v >> 31))
81 #define mbi_maskchk31_3(v) mbi_maskchk31s(v, mbi_maskchk31_4(v >> 31))
82 #define mbi_maskchk31_4(v) mbi_maskchk31s(v, mbi_maskchk31_5(v >> 31))
83 #define mbi_maskchk31_5(v) mbi_maskchk31s(v, mbi_maskchk31_6(v >> 31))
84 #define mbi_maskchk31_6(v) mbi_maskchk31s(v, mbi_maskchk31_7(v >> 31))
85 #define mbi_maskchk31_7(v) mbi_maskchk31s(v, mbi_maskchk31_8(v >> 31))
86 #define mbi_maskchk31_8(v) mbi_maskchk31s(v, mbi_maskchk31_9(v >> 31))
87 #define mbi_maskchk31_9(v) (v <= 0x7FFFFFFFUL && mbi_maskchk16(v))
88 #define mbi_maskchk16(v) mbi_maskchks(v, 0xFFFFU, \
89 mbi_maskchk8(v), mbi_maskchk8(v >> 16))
90 #define mbi_maskchk8(v) mbi_maskchks(v, 0xFFU, \
91 mbi_maskchk4(v), mbi_maskchk4(v >> 8))
92 #define mbi_maskchk4(v) mbi_maskchks(v, 0xFU, \
93 mbi_maskchkF(v), mbi_maskchkF(v >> 4))
94 #define mbi_maskchkF(v) (v == 0xF || v == 7 || v == 3 || v == 1 || !v)
95
96 /* compile-time assertions for mbsdint.h */
97 mbiCTAS(mbsdint_h) {
98 /* compiler (in)sanity, from autoconf */
99 #define mbiCTf(x) 'x'
100 mbiCTA(xlc6, mbiCTf(a) == 'x');
101 #undef mbiCTf
102 mbiCTA(osf4, '\x00' == 0);
103 /* C types */
104 mbiCTA(basic_char,
105 sizeof(char) == 1 && (CHAR_BIT) >= 7 && (CHAR_BIT) < 2040 &&
106 mbiTYPE_UMAX(unsigned char) == (UCHAR_MAX) &&
107 sizeof(signed char) == 1 &&
108 sizeof(unsigned char) == 1 &&
109 mbiMASK_CHK(SCHAR_MAX) && mbiMASK_CHK(UCHAR_MAX) &&
110 ((SCHAR_MIN) == -(SCHAR_MAX) || (SCHAR_MIN) == -(SCHAR_MAX)-1) &&
111 mbiTYPE_UBITS(unsigned char) == (unsigned int)(CHAR_BIT));
112 mbiCTA(basic_short,
113 mbiTYPE_UMAX(unsigned short) == (USHRT_MAX) &&
114 sizeof(short) <= (279 / CHAR_BIT) &&
115 sizeof(unsigned short) <= (279 / CHAR_BIT) &&
116 mbiMASK_CHK(SHRT_MAX) && mbiMASK_CHK(USHRT_MAX) &&
117 ((SHRT_MIN) == -(SHRT_MAX) || (SHRT_MIN) == -(SHRT_MAX)-1) &&
118 sizeof(short) >= sizeof(signed char) &&
119 sizeof(unsigned short) >= sizeof(unsigned char) &&
120 sizeof(short) == sizeof(unsigned short));
121 mbiCTA(basic_int,
122 mbiTYPE_UMAX(unsigned int) == (UINT_MAX) &&
123 sizeof(int) <= (279 / CHAR_BIT) &&
124 sizeof(unsigned int) <= (279 / CHAR_BIT) &&
125 mbiMASK_CHK(INT_MAX) && mbiMASK_CHK(UINT_MAX) &&
126 ((INT_MIN) == -(INT_MAX) || (INT_MIN) == -(INT_MAX)-1) &&
127 sizeof(int) >= sizeof(short) &&
128 sizeof(unsigned int) >= sizeof(unsigned short) &&
129 sizeof(int) == sizeof(unsigned int));
130 mbiCTA(basic_long,
131 mbiTYPE_UMAX(unsigned long) == (ULONG_MAX) &&
132 sizeof(long) <= (279 / CHAR_BIT) &&
133 sizeof(unsigned long) <= (279 / CHAR_BIT) &&
134 mbiMASK_CHK(LONG_MAX) && mbiMASK_CHK(ULONG_MAX) &&
135 ((LONG_MIN) == -(LONG_MAX) || (LONG_MIN) == -(LONG_MAX)-1) &&
136 sizeof(long) >= sizeof(int) &&
137 sizeof(unsigned long) >= sizeof(unsigned int) &&
138 sizeof(long) == sizeof(unsigned long));
139 #ifdef LLONG_MIN
140 mbiCTA(basic_quad,
141 mbiTYPE_UMAX(unsigned long long) == (ULLONG_MAX) &&
142 sizeof(long long) <= (279 / CHAR_BIT) &&
143 sizeof(unsigned long long) <= (279 / CHAR_BIT) &&
144 mbiMASK_CHK(LLONG_MAX) && mbiMASK_CHK(ULLONG_MAX) &&
145 ((LLONG_MIN) == -(LLONG_MAX) || (LLONG_MIN) == -(LLONG_MAX)-1) &&
146 sizeof(long long) >= sizeof(long) &&
147 sizeof(unsigned long long) >= sizeof(unsigned long) &&
148 sizeof(long long) == sizeof(unsigned long long));
149 #endif
150 #ifdef INTMAX_MIN
151 mbiCTA(basic_imax,
152 mbiTYPE_UMAX(uintmax_t) == (UINTMAX_MAX) &&
153 sizeof(intmax_t) <= (279 / CHAR_BIT) &&
154 sizeof(uintmax_t) <= (279 / CHAR_BIT) &&
155 mbiMASK_CHK(INTMAX_MAX) && mbiMASK_CHK(UINTMAX_MAX) &&
156 ((INTMAX_MIN) == -(INTMAX_MAX) || (INTMAX_MIN) == -(INTMAX_MAX)-1) &&
157 #ifdef LLONG_MIN
158 sizeof(intmax_t) >= sizeof(long long) &&
159 sizeof(uintmax_t) >= sizeof(unsigned long long) &&
160 #else
161 sizeof(intmax_t) >= sizeof(long) &&
162 sizeof(uintmax_t) >= sizeof(unsigned long) &&
163 #endif
164 sizeof(intmax_t) == sizeof(uintmax_t));
165 #endif
166 /* size_t is C but ssize_t is POSIX */
167 mbiCTA_TYPE_NOTF(size_t);
168 mbiCTA(basic_sizet,
169 sizeof(size_t) >= sizeof(unsigned int) &&
170 sizeof(size_t) <= sizeof(mbiHUGE_U) &&
171 mbiTYPE_ISU(size_t) &&
172 #ifdef SIZE_MAX
173 mbiMASK_CHK(SIZE_MAX) &&
174 mbiMASK_BITS(SIZE_MAX) <= mbiTYPE_UBITS(size_t) &&
175 ((SIZE_MAX) == (mbiHUGE_U)(size_t)(SIZE_MAX)) &&
176 #endif
177 mbiTYPE_UBITS(size_t) <= mbiMASK_BITS(mbiHUGE_UMAX));
178 mbiCTA_TYPE_NOTF(ptrdiff_t);
179 mbiCTA(basic_ptrdifft,
180 sizeof(ptrdiff_t) >= sizeof(int) &&
181 sizeof(ptrdiff_t) <= sizeof(mbiHUGE_S) &&
182 !mbiTYPE_ISU(ptrdiff_t) &&
183 #ifdef PTRDIFF_MAX
184 mbiMASK_CHK(PTRDIFF_MAX) &&
185 ((PTRDIFF_MAX) == (mbiHUGE_S)(ptrdiff_t)(PTRDIFF_MAX)) &&
186 #endif
187 1);
188 /* UGH! off_t is POSIX, with no _MIN/_MAX constants… WTF‽ */
189 #ifdef SSIZE_MAX
190 mbiCTA_TYPE_NOTF(ssize_t);
191 mbiCTA(basic_ssizet,
192 sizeof(ssize_t) == sizeof(size_t) &&
193 !mbiTYPE_ISU(ssize_t) &&
194 mbiMASK_CHK(SSIZE_MAX) &&
195 ((SSIZE_MAX) == (mbiHUGE_S)(ssize_t)(SSIZE_MAX)) &&
196 #ifdef SIZE_MAX
197 mbiMASK_BITS(SSIZE_MAX) <= mbiMASK_BITS(SIZE_MAX) &&
198 #endif
199 mbiMASK_BITS(SSIZE_MAX) < mbiTYPE_UBITS(size_t));
200 #endif
201 /* C99 §6.2.6.2(1, 2, 6) permits M ≤ N, but M < N is normally desired */
202 /* here require signed/unsigned types to have same width (M=N-1) */
203 mbiCTA(vbits_char, mbiMASK_BITS(UCHAR_MAX) == mbiMASK_BITS(SCHAR_MAX) + 1U);
204 mbiCTA(vbits_short, mbiMASK_BITS(USHRT_MAX) == mbiMASK_BITS(SHRT_MAX) + 1U);
205 mbiCTA(vbits_int, mbiMASK_BITS(UINT_MAX) == mbiMASK_BITS(INT_MAX) + 1U);
206 mbiCTA(vbits_long, mbiMASK_BITS(ULONG_MAX) == mbiMASK_BITS(LONG_MAX) + 1U);
207 #ifdef LLONG_MIN
208 mbiCTA(vbits_quad, mbiMASK_BITS(ULLONG_MAX) == mbiMASK_BITS(LLONG_MAX) + 1U);
209 #endif
210 #ifdef INTMAX_MIN
211 mbiCTA(vbits_imax, mbiMASK_BITS(UINTMAX_MAX) == mbiMASK_BITS(INTMAX_MAX) + 1U);
212 #endif
213 /* require pointers and size_t to take up the same amount of space */
214 mbiCTA(sizet_voidptr, sizeof(size_t) == sizeof(void *));
215 mbiCTA(sizet_funcptr, sizeof(size_t) == sizeof(void (*)(void)));
216 #if 0 /* breaks on LLP64 (e.g. Windows/amd64) */
217 mbiCTA(sizet_inulong, sizeof(size_t) <= sizeof(long));
218 #endif
219 /* assume ptrdiff_t and (s)size_t will fit each other */
220 mbiCTA(sizet_ptrdiff, sizeof(size_t) == sizeof(ptrdiff_t));
221 };
222
223 /*
224 * calculations where the unsigned type is used as backing store,
225 * doing the two’s complement conversion manually (to avoid UB/IB);
226 * (M=N-1), see above, is required for these to work (symmetrically)
227 *
228 * ut = unsigned type (e.g. unsigned long); st = signed type (e.g. long)
229 * SM = signed max (e.g. LONG_MAX); v = value
230 * m = magnitude (≥ 0 value); vz = signbit (0:value; 1:-value)
231 * HM = half mask (e.g. (ut)0x7FFFUL); FM = full mask (e.g. (ut)0xFFFFUL)
232 */
233
234 /* 1. casting between unsigned(two’s complement) and signed(native) */
235 #define mbiA_U2S(ut,st,SM,v) (((v) > (ut)(SM)) ? \
236 (st)(-(st)(~(v)) - (st)1) : \
237 (st)(v))
238 #define mbiA_S2U(ut,st,v) (((v) < 0) ? \
239 (ut)(~(ut)(-((v) + (st)1))) : \
240 (ut)(v))
241
242 /* 2. converting between signed(native) and signbit(vz) plus magnitude */
243 #define mbiA_VZM2S(ut,st,vz,m) (((vz) && (m) > 0) ? \
244 (st)(-(st)((m) - (ut)1) - (st)1) : \
245 (st)(m))
246 #define mbiA_S2VZ(v) ((v) < 0)
247 #define mbiA_S2M(ut,st,v) (((v) < 0) ? \
248 (ut)((ut)(-((v) + (st)1)) + (ut)1) : \
249 (ut)(v))
250
251 /* 3. masking arithmetics in possibly-longer type */
252 #define mbiMA_U2S(ut,st,FM,HM,v) \
253 (((ut)((v) & FM) > HM) ? \
254 (st)(-(st)(~(v) & HM) - (st)1) : \
255 (st)((v) & HM))
256 #define mbiMA_S2U(ut,st,FM,v) ((ut)(mbiA_S2U(ut, st, v) & FM))
257 #define mbiMA_VZM2S(ut,st,FM,HM,vz,m) \
258 (((vz) && (ut)((m) & FM) > 0) ? \
259 (st)(-(st)(((m) - (ut)1) & HM) - (st)1) : \
260 (st)((m) & HM))
261 #define mbiMA_S2VZ(v) ((v) < 0)
262 #define mbiMA_S2M(ut,st,HM,v) (((v) < 0) ? \
263 (ut)((ut)((-((v) + (st)1)) & HM) + (ut)1) : \
264 (ut)((ut)(v) & HM))
265
266 /*
267 * UB-safe overflow/underflow-checking integer arithmetics
268 *
269 * Before using, #define mbiCfail to the action that should be
270 * taken on check (e.g. "goto fail" or "return (0)"); make sure
271 * to #undef mbiCfail before the end of the function body though!
272 *
273 * There is IB on some signed operations, but that is only either
274 * the result (which is checked) is implementation-defined, thus
275 * safe, or an implementation-defined signal is raised, which is
276 * the caller’s problem ☻
277 */
278
279 /* 1. for unsigned types checking afterwards is OK */
280 #define mbiCAUinc(vl) mbiCAUadd(vl, 1)
281 #define mbiCAUdec(vl) mbiCAUsub(vl, 1)
282 #define mbiCAUadd(vl,vr) do { \
283 (vl) += (vr); \
284 if (__predict_false((vl) < (vr))) \
285 mbiCfail; \
286 } while (/* CONSTCOND */ 0)
287 #define mbiCAUsub(vl,vr) do { \
288 if (__predict_false((vl) < (vr))) \
289 mbiCfail; \
290 (vl) -= (vr); \
291 } while (/* CONSTCOND */ 0)
292 #define mbiCAUmul(vl,vr) do { \
293 if (__predict_false((((vl) * (vr)) / (vr)) < (vl))) \
294 mbiCfail; \
295 (vl) *= (vr); \
296 } while (/* CONSTCOND */ 0)
297
298 /* 2. for signed types; lim is a prefix (e.g. SHRT) */
299 #define mbiCASinc(lim,vl) do { \
300 if (__predict_false((vl) == lim ## _MAX)) \
301 mbiCfail; \
302 ++(vl); \
303 } while (/* CONSTCOND */ 0)
304 #define mbiCASdec(lim,vl) do { \
305 if (__predict_false((vl) == lim ## _MIN)) \
306 mbiCfail; \
307 --(vl); \
308 } while (/* CONSTCOND */ 0)
309 #define mbiCASadd(lim,vl,vr) do { \
310 if (__predict_false((vl) > (lim ## _MAX - (vr)))) \
311 mbiCfail; \
312 (vl) += (vr); \
313 } while (/* CONSTCOND */ 0)
314 #define mbiCASsub(lim,vl,vr) do { \
315 if (__predict_false((vl) < (lim ## _MIN + (vr)))) \
316 mbiCfail; \
317 (vl) -= (vr); \
318 } while (/* CONSTCOND */ 0)
319 #define mbiCASmul(lim,vl,vr) do { \
320 if (__predict_false((lim ## _MAX / (vr)) < (vl) || \
321 (lim ## _MIN / (vr)) > (vl))) \
322 mbiCfail; \
323 (vl) *= (vr); \
324 } while (/* CONSTCOND */ 0)
325
326 /* 3. signed narrowing assign; this is IB */
327 #define mbiCASlet(dsttype,vl,srctype,vr) do { \
328 (vl) = (dsttype)(vr); \
329 if (__predict_false((srctype)(vl) != (vr))) \
330 mbiCfail; \
331 } while (/* CONSTCOND */ 0)
332
333 /*
334 * calculations on manual two’s complement
335 *
336 * addition, subtraction and multiplication, bitwise and boolean
337 * operations, as well as equality comparisons can be done on the
338 * unsigned value; other comparisons must be done on the signed
339 * value and the other operations follow
340 */
341
342 /* rotate and shift: pass *unsigned* values; shr shifts in vz bits */
343 #define mbiVAU_shift(ut,dst,vl,vr,rv) do { \
344 (dst) = (vr) & (mbiTYPE_UBITS(ut) - 1); \
345 (dst) = (dst) ? (rv) : (vl); \
346 } while (/* CONSTCOND */ 0)
347 #define mbiVAUrol(ut,dst,vl,vr) mbiVAU_shift(ut, dst, vl, vr, \
348 ((vl) << (dst)) | ((vl) >> (mbiTYPE_UBITS(ut) - (dst))))
349 #define mbiVAUror(ut,dst,vl,vr) mbiVAU_shift(ut, dst, vl, vr, \
350 ((vl) >> (dst)) | ((vl) << (mbiTYPE_UBITS(ut) - (dst))))
351 #define mbiVAUshl(ut,dst,vl,vr) mbiVAU_shift(ut, dst, vl, vr, \
352 (vl) << (dst))
353 #define mbiVAUshr(ut,dst,vz,vl,vr) mbiVAU_shift(ut, dst, vl, vr, \
354 (vz) ? (ut)~((ut)~(vl) >> (dst)) : (vl) >> (dst))
355 #define mbiM_do(dst,FM,act) do { act; (dst) &= FM; } while (/* CONSTCOND */ 0)
356 #define mbiMVAUrol(ut,FM,dst,vl,vr) mbiM_do(dst, FM, mbiVAUrol(ut,dst,vl,vr))
357 #define mbiMVAUror(ut,FM,dst,vl,vr) mbiM_do(dst, FM, mbiVAUror(ut,dst,vl,vr))
358 #define mbiMVAUshl(ut,FM,dst,vl,vr) mbiM_do(dst, FM, mbiVAUshl(ut,dst,vl,vr))
359 #define mbiMVAUshr(ut,FM,dst,vz,vl,vr) \
360 mbiM_do(dst, FM, mbiVAUshr(ut,dst,vz,vl,vr))
361
362 /* division and remainder; pass *signed* values and unsigned result vars */
363 #define mbiVASdivrem(ut,st,udiv,urem,vl,vr) do { \
364 (udiv) = mbiA_S2M(ut, st, (vl)) / mbiA_S2M(ut, st, (vr)); \
365 if (mbiA_S2VZ(vl) ^ mbiA_S2VZ(vr)) \
366 (udiv) = -(udiv); \
367 (urem) = mbiA_S2U(ut, st, (vl)) - \
368 ((udiv) * mbiA_S2U(ut, st, (vr))); \
369 } while (/* CONSTCOND */ 0)
370 #define mbiMVASdivrem(ut,st,FM,HM,udiv,urem,vl,vr) do { \
371 (udiv) = mbiMA_S2M(ut, st, HM, (vl)) / \
372 mbiMA_S2M(ut, st, HM, (vr)); \
373 if (mbiMA_S2VZ(vl) ^ mbiMA_S2VZ(vr)) \
374 (udiv) = -(udiv); \
375 (urem) = mbiA_S2U(ut, st, (vl)) - \
376 ((udiv) * mbiA_S2U(ut, st, (vr))); \
377 (udiv) &= FM; \
378 (urem) &= FM; \
379 } while (/* CONSTCOND */ 0)
380
381 #endif /* !SYSKERN_MBSDINT_H */
00 /*-
1 * Copyright © 2011, 2014, 2015, 2021
1 * Copyright © 2011, 2014, 2015, 2021, 2022
22 * mirabilos <m@mirbsd.org>
33 *
44 * Provided that these terms and disclaimer and all copyright notices
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.
1818 *-
19 * This file provides BAFH (Better Avalanche for the Jenkins Hash) as
20 * inline macro bodies that operate on “register uint32_t” variables,
21 * with variants that use their local intermediate registers.
22 *
23 * Usage note for BAFH with entropy distribution: input up to 4 bytes
24 * is best combined into a 32-bit unsigned integer, which is then run
25 * through BAFHFinish_reg for mixing and then used as context instead
26 * of 0. Longer input should be handled the same: take the first four
27 * bytes as IV after mixing then add subsequent bytes the same way.
28 * This needs counting input bytes and is endian-dependent, thus not,
29 * for speed reasons, specified for the regular stable hash, but very
30 * much recommended if the actual output value may differ across runs
31 * (so is using a random value instead of 0 for the IV).
19 * This file provides BAFH1-0 (Better Avalanche for the Jenkins Hash)
20 * as macro bodies operating on “register k32” variables (from sh.h).
3221 *-
3322 * Little quote gem:
3423 * We are looking into it. Changing the core
3726 * -- Rasmus Lerdorf
3827 */
3928
40 #ifndef SYSKERN_MIRHASH_H
41 #define SYSKERN_MIRHASH_H 1
42 #define SYSKERN_MIRHASH_BAFH
29 #ifndef MKSH_MIRHASH_H
30 #define MKSH_MIRHASH_H
4331
4432 #include <sys/types.h>
4533
46 __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.9 2021/07/31 19:56:33 tg Exp $");
34 __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.14 2022/01/27 14:15:41 tg Exp $");
4735
4836 /*-
49 * BAFH itself is defined by the following primitives:
37 * BAFH1-0 is defined by the following primitives:
5038 *
5139 * • BAFHInit(ctx) initialises the hash context, which consists of a
52 * sole 32-bit unsigned integer (ideally in a register), to 0.
53 * It is possible to use any initial value out of [0; 2³²[ – which
40 * sole 32-bit unsigned integer (ideally in a register), to 0^H1.
41 * It is possible to use any initial value out of [0; 2³²[ — which
5442 * is, in fact, recommended if using BAFH for entropy distribution
55 * – but for a regular stable hash, the IV 0 is needed.
43 * — but for a regular stable hash, the IV 0^H1 is needed.
5644 *
5745 * • BAFHUpdateOctet(ctx,val) compresses the unsigned 8-bit quantity
58 * into the hash context. The algorithm used is Jenkins’ one-at-a-
59 * time, except that an additional constant 1 is added so that, if
60 * the context is (still) zero, adding a NUL byte is not ignored.
46 * into the hash context using Jenkins’ one-at-a-time algorithm.
6147 *
6248 * • BAFHror(eax,cl) evaluates to the unsigned 32-bit integer “eax”,
6349 * rotated right by “cl” ∈ [1; 31] (no casting, be careful!) where
64 * “eax” must be uint32_t and “cl” an in-range integer.
50 * “eax” is K32()d and “cl” must be within range.
6551 *
6652 * • BAFHFinish(ctx) avalanches the context around so every sub-byte
6753 * depends on all input octets; afterwards, the context variable’s
6854 * value is the hash output. BAFH does not use any padding, nor is
6955 * the input length added; this is due to the common use case (for
7056 * quick entropy distribution and use with a hashtable).
71 * Warning: BAFHFinish uses the MixColumn algorithm of AES – which
57 * Warning: BAFHFinish uses the MixColumn algorithm of AES — which
7258 * is reversible (to avoid introducing funnels and reducing entro‐
7359 * py), so blinding may need to be employed for some uses, e.g. in
7460 * mksh, after a fork.
7561 *
76 * The BAFHUpdateOctet and BAFHFinish are available in two flavours:
77 * suffixed with _reg (assumes the context is in a register) or _mem
78 * (which doesn’t).
79 *
80 * The following high-level macros (with _reg and _mem variants) are
81 * available:
62 * The following high-level macros are available:
8263 *
8364 * • BAFHUpdateMem(ctx,buf,len) adds a memory block to a context.
8465 * • BAFHUpdateStr(ctx,buf) is equivalent to using len=strlen(buf).
8566 *
8667 * All macros may use ctx multiple times in their expansion, but all
8768 * other arguments are always evaluated at most once except BAFHror.
88 *
89 * To stay portable, encode numbers using ULEB128, or better and for
90 * sortability, VLQ (same unsigned but big endian), normal or Git’s.
9169 */
9270
9371 #define BAFHInit(h) do { \
94 (h) = 0; \
72 (h) = 1U; \
9573 } while (/* CONSTCOND */ 0)
9674
97 #define BAFHUpdateOctet_reg(h,b) do { \
98 (h) += (unsigned char)(b); \
99 ++(h); \
100 (h) += (h) << 10; \
101 (h) ^= (h) >> 6; \
75 #define BAFHUpdateOctet(h,b) do { \
76 (h) = K32(K32(h) + KBI(b)); \
77 (h) = K32((h) + K32((h) << 10)); \
78 (h) = K32((h) ^ K32((h) >> 6)); \
10279 } while (/* CONSTCOND */ 0)
10380
104 #define BAFHUpdateOctet_mem(m,b) do { \
105 register uint32_t BAFH_h = (m); \
81 #define BAFHror(eax,cl) K32(K32(K32(eax) >> (cl)) | K32(K32(eax) << (32 - (cl))))
82
83 #define BAFHFinish__impl(h,v,d) \
84 v = K32(K32(h) >> 7) & 0x01010101U; \
85 v = K32(v + K32(v << 1)); \
86 v = K32(v + K32(v << 3)); \
87 v = K32(v ^ (K32(K32(h) << 1) & 0xFEFEFEFEU)); \
10688 \
107 BAFHUpdateOctet_reg(BAFH_h, (b)); \
108 (m) = BAFH_h; \
89 v = K32(v ^ BAFHror(v, 8)); \
90 v = K32(v ^ (h = BAFHror(h, 8))); \
91 v = K32(v ^ (h = BAFHror(h, 8))); \
92 d = K32(v ^ BAFHror(h, 8));
93
94 #define BAFHFinish(h) do { \
95 register k32 BAFHFinish_v; \
96 \
97 BAFHFinish__impl((h), BAFHFinish_v, (h)) \
10998 } while (/* CONSTCOND */ 0)
11099
111 #define BAFHror(eax,cl) (((eax) >> (cl)) | ((eax) << (32 - (cl))))
112
113 #define BAFHFinish_reg(h) do { \
114 register uint32_t BAFHFinish_v; \
100 #define BAFHUpdateMem(h,p,z) do { \
101 register const unsigned char *BAFHUpdate_p; \
102 register const unsigned char *BAFHUpdate_d; \
115103 \
116 BAFHFinish_v = ((h) >> 7) & 0x01010101U; \
117 BAFHFinish_v += BAFHFinish_v << 1; \
118 BAFHFinish_v += BAFHFinish_v << 3; \
119 BAFHFinish_v ^= ((h) << 1) & 0xFEFEFEFEU; \
120 \
121 BAFHFinish_v ^= BAFHror(BAFHFinish_v, 8); \
122 BAFHFinish_v ^= ((h) = BAFHror((h), 8)); \
123 BAFHFinish_v ^= ((h) = BAFHror((h), 8)); \
124 (h) = BAFHror((h), 8) ^ BAFHFinish_v; \
104 BAFHUpdate_p = (const void *)(p); \
105 BAFHUpdate_d = BAFHUpdate_p + (z); \
106 while (BAFHUpdate_p < BAFHUpdate_d) \
107 BAFHUpdateOctet((h), *BAFHUpdate_p++); \
125108 } while (/* CONSTCOND */ 0)
126109
127 #define BAFHFinish_mem(m) do { \
128 register uint32_t BAFHFinish_v, BAFH_h = (m); \
129 \
130 BAFHFinish_v = (BAFH_h >> 7) & 0x01010101U; \
131 BAFHFinish_v += BAFHFinish_v << 1; \
132 BAFHFinish_v += BAFHFinish_v << 3; \
133 BAFHFinish_v ^= (BAFH_h << 1) & 0xFEFEFEFEU; \
134 \
135 BAFHFinish_v ^= BAFHror(BAFHFinish_v, 8); \
136 BAFHFinish_v ^= (BAFH_h = BAFHror(BAFH_h, 8)); \
137 BAFHFinish_v ^= (BAFH_h = BAFHror(BAFH_h, 8)); \
138 (m) = BAFHror(BAFH_h, 8) ^ BAFHFinish_v; \
139 } while (/* CONSTCOND */ 0)
140
141 #define BAFHUpdateMem_reg(h,p,z) do { \
142 register const unsigned char *BAFHUpdate_p; \
143 register size_t BAFHUpdate_z = (z); \
144 \
145 BAFHUpdate_p = (const void *)(p); \
146 while (BAFHUpdate_z--) \
147 BAFHUpdateOctet_reg((h), *BAFHUpdate_p++); \
148 } while (/* CONSTCOND */ 0)
149
150 /* meh should have named them _r/m but that’s not valid C */
151 #define BAFHUpdateMem_mem(m,p,z) do { \
152 register uint32_t BAFH_h = (m); \
153 \
154 BAFHUpdateMem_reg(BAFH_h, (p), (z)); \
155 (m) = BAFH_h; \
156 } while (/* CONSTCOND */ 0)
157
158 #define BAFHUpdateStr_reg(h,s) do { \
110 #define BAFHUpdateStr(h,s) do { \
159111 register const unsigned char *BAFHUpdate_s; \
160112 register unsigned char BAFHUpdate_c; \
161113 \
162114 BAFHUpdate_s = (const void *)(s); \
163115 while ((BAFHUpdate_c = *BAFHUpdate_s++) != 0) \
164 BAFHUpdateOctet_reg((h), BAFHUpdate_c); \
165 } while (/* CONSTCOND */ 0)
166
167 #define BAFHUpdateStr_mem(m,s) do { \
168 register uint32_t BAFH_h = (m); \
169 \
170 BAFHUpdateStr_reg(BAFH_h, (s)); \
171 (m) = BAFH_h; \
116 BAFHUpdateOctet((h), BAFHUpdate_c); \
172117 } while (/* CONSTCOND */ 0)
173118
174119 #endif
+236
-123
misc.c less more
33 /*-
44 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
55 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019,
6 * 2020, 2021
6 * 2020, 2021, 2022
77 * mirabilos <m@mirbsd.org>
88 * Copyright (c) 2015
99 * Daniel Richard G. <skunk@iSKUNK.ORG>
3232 #include <grp.h>
3333 #endif
3434
35 __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.330 2021/10/10 20:41:17 tg Exp $");
36
37 #define KSH_CHVT_FLAG
38 #ifdef MKSH_SMALL
39 #undef KSH_CHVT_FLAG
40 #endif
41 #ifdef TIOCSCTTY
42 #define KSH_CHVT_CODE
43 #define KSH_CHVT_FLAG
44 #endif
35 __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.341 2022/01/27 13:45:05 tg Exp $");
4536
4637 static const unsigned char *pat_scan(const unsigned char *,
4738 const unsigned char *, bool) MKSH_A_PURE;
5041 const unsigned char *) MKSH_A_PURE;
5142 static const unsigned char *gmatch_cclass(const unsigned char *, unsigned char)
5243 MKSH_A_PURE;
53 #ifdef KSH_CHVT_CODE
5444 static void chvt(const Getopt *);
55 #endif
5645 static unsigned int dollarqU(struct shf *, const unsigned char *);
5746 #ifndef MKSH_SMALL
5847 static void dollarq8(struct shf *, const unsigned char *);
6756 /* we don't need to check for other codes, EPERM won't happen */
6857 #define DO_SETUID(func,argvec) do { \
6958 if ((func argvec) && errno == EAGAIN) \
70 errorf("%s failed with EAGAIN, probably due to a" \
71 " too low process limit; aborting", #func); \
59 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE | \
60 KWF_TWOMSG, #func, "failed, probably due to a" \
61 " too low process limit; aborting"); \
7262 } while (/* CONSTCOND */ 0)
7363 #else
7464 #define DO_SETUID(func,argvec) func argvec
9080 }
9181
9282 #define SHFLAGS_DEFNS
93 #define FN(sname,cname,flags,ochar) \
94 static const struct { \
95 /* character flag (if any) */ \
96 char c; \
97 /* OF_* */ \
98 unsigned char optflags; \
99 /* long name of option */ \
100 char name[sizeof(sname)]; \
101 } shoptione_ ## cname = { \
102 ochar, flags, sname \
83 #define FN(sname,cname,flags,ochar) \
84 static const struct shoptionS_ ## cname { \
85 /* character flag (if any) */ \
86 char c; \
87 /* OF_* */ \
88 unsigned char optflags; \
89 /* long name of option */ \
90 char name[sizeof(sname)]; \
91 } shoptione_ ## cname = { \
92 ochar, flags, sname \
10393 };
10494 #include "sh_flags.gen"
95
96 mbiCTAS(sh_flags_gen) {
97 #define FN(sname,cname,flags,ochar) mbiCTA(cta_ ## cname, \
98 offsetof(struct shoptionS_ ## cname, optflags) == 1 && \
99 offsetof(struct shoptionS_ ## cname, name[0]) == 2);
100 #include "sh_flags.gen"
101 };
105102
106103 #define OFC(i) (options[i][-2])
107104 #define OFF(i) (((const unsigned char *)options[i])[-1])
242239
243240 /* change a Flag(*) value; takes care of special actions */
244241 void
245 change_flag(enum sh_flag f, int what, bool newset)
242 change_flag(enum sh_flag f,
243 /* OF_INTERNAL, OF_FIRSTTIME, OF_CMDLINE, or OF_SET */
244 unsigned int what,
245 bool newset)
246246 {
247247 unsigned char oldval = Flag(f);
248248 unsigned char newval = (newset ? 1 : 0);
312312
313313 if (f == FTALKING) {
314314 /* Changing interactive flag? */
315 if ((what == OF_CMDLINE || what == OF_SET) && procpid == kshpid)
315 if (what == OF_CMDLINE && procpid == kshpid)
316316 Flag(FTALKING_I) = newval;
317317 #ifndef MKSH_UNEMPLOYED
318318 } else if (f == FMONITOR) {
357357 if ((Flag(FXTRACE) = newval) == 2) {
358358 in_xtrace = true;
359359 Flag(FXTRACE) = 0;
360 shf_puts(substitute(str_val(global("PS4")), 0), shl_xtrace);
360 shf_putsv(substitute(str_val(global("PS4")), 0), shl_xtrace);
361361 Flag(FXTRACE) = 2;
362362 in_xtrace = false;
363363 }
370370 int
371371 parse_args(const char **argv,
372372 /* OF_FIRSTTIME, OF_CMDLINE, or OF_SET */
373 int what,
373 unsigned int what,
374374 bool *setargsp)
375375 {
376376 static const char cmd_opts[] =
386386 #undef SHFLAGS_NOT_CMD
387387 ;
388388 bool set;
389 const char *opts = what == OF_CMDLINE || what == OF_FIRSTTIME ?
390 cmd_opts : set_opts;
389 const char * const opts = what == OF_SET ? set_opts : cmd_opts;
391390 const char *array = NULL;
392391 Getopt go;
393392 size_t i;
414413 * lone -o: print options
415414 *
416415 * Note that on the command line, -o requires
417 * an option (ie, can't get here if what is
418 * OF_CMDLINE).
416 * an option (i.e. can't get here if what is
417 * not OF_SET).
419418 */
420419 #if !defined(MKSH_SMALL) || defined(DEBUG)
421420 if (!set && !baseline_flags[(int)FNFLAGS]) {
471470 }
472471 break;
473472
474 #ifdef KSH_CHVT_FLAG
475473 case 'T':
476474 if (what != OF_FIRSTTIME)
477475 break;
478 #ifndef KSH_CHVT_CODE
479 errorf("no TIOCSCTTY ioctl");
480 #else
481 change_flag(FTALKING, OF_CMDLINE, true);
482476 chvt(&go);
483477 break;
484 #endif
485 #endif
486478
487479 case '?':
488480 return (-1);
490482 default:
491483 if (what == OF_FIRSTTIME)
492484 break;
493 /* -s: sort positional params (AT&T ksh stupidity) */
494 if (what == OF_SET && optc == 's') {
485 /* -s: sort positional params (via AT&T ksh) */
486 if (what == OF_SET && isch(optc, 's')) {
495487 sortargs = true;
496488 break;
497489 }
502494 break;
503495 }
504496 if (i == NELEM(options))
505 internal_errorf("parse_args: '%c'", optc);
506 }
507 }
508 if (!(go.info & GI_MINUSMINUS) && argv[go.optind] &&
497 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
498 "parse_args: '%c'", optc);
499 }
500 }
501 /* lone ‘-’ (or ‘+’)? */
502 if (argv[go.optind] && argv[go.optind][1] == '\0' &&
509503 ctype(argv[go.optind][0], C_MINUS | C_PLUS) &&
510 argv[go.optind][1] == '\0') {
511 /* lone - clears -v and -x flags */
512 if (argv[go.optind][0] == '-') {
504 !(go.info & GI_MINUSMINUS)) {
505 /* POSIX: lone hyphen-minus sh first arg ignored */
506 if (what == OF_SET && isch(argv[go.optind][0], '-')) {
507 /* set; lone dash clears -v and -x flags (obsolete) */
513508 Flag(FVERBOSE) = 0;
514509 change_xtrace(0, false);
515510 }
516 /* set skips lone - or + option */
511 /* either way, skip it (POSIX only dash but… meh) */
517512 go.optind++;
518513 }
519514 if (setargsp)
548543 int
549544 getn(const char *s, int *ai)
550545 {
551 return (getpn(&s, ai) && !*s);
546 if (!getpn(&s, ai))
547 return (0);
548 if (!*s)
549 return (1);
550 errno = EINVAL;
551 return (0);
552552 }
553553
554554 /*
582582 }
583583
584584 while (ctype(c, C_DIGIT)) {
585 if (num > 214748364U)
585 if (num > 214748364U) {
586586 /* overflow on multiplication */
587587 state = 2;
588 errno = EOVERFLOW;
589 }
588590 if (state < 2) {
589591 state = 1;
590592 num = num * 10U + (unsigned int)ksh_numdig(c);
594596 }
595597 --s;
596598
597 if (num > (neg ? 2147483648U : 2147483647U))
599 if (num > (neg ? 2147483648U : 2147483647U)) {
598600 /* overflow for signed 32-bit int */
599601 state = 2;
602 errno = EOVERFLOW;
603 }
600604
601605 if (state)
602606 *sp = s;
607 else
608 errno = EINVAL;
603609 if (state != 1) {
604610 *ai = 0;
605611 return (0);
993999 /*XXX this is a prime example for bsearch or a const hashtable */
9941000 static const struct cclass {
9951001 const char *name;
996 uint32_t value;
1002 kui value;
9971003 } cclasses[] = {
9981004 /* POSIX */
9991005 { "alnum", C_ALNUM },
12861292 *
12871293 * Non-standard features:
12881294 * - ';' is like ':' in options, except the argument is optional
1289 * (if it isn't present, optarg is set to 0).
1295 * (if it isn't present, optarg is set to NULL).
12901296 * Used for 'set -o'.
12911297 * - ',' is like ':' in options, except the argument always immediately
12921298 * follows the option character (optarg is set to the null string if
13361342 go->buf[0] = c;
13371343 go->optarg = go->buf;
13381344 } else {
1339 warningf(true, Tf_optfoo,
1340 (go->flags & GF_NONAME) ? "" : argv[0],
1341 (go->flags & GF_NONAME) ? "" : Tcolsp,
1342 c, Tunknown_option);
1345 ksh_getopt_opterr(c,
1346 (go->flags & GF_NONAME) ? null : argv[0],
1347 Tunknown_option);
13431348 if (go->flags & GF_ERROR)
1344 bi_errorfz();
1349 bi_unwind(1);
13451350 }
13461351 return (ORD('?'));
13471352 }
13641369 go->optarg = go->buf;
13651370 return (ORD(':'));
13661371 }
1367 warningf(true, Tf_optfoo,
1368 (go->flags & GF_NONAME) ? "" : argv[0],
1369 (go->flags & GF_NONAME) ? "" : Tcolsp,
1370 c, Treq_arg);
1372 ksh_getopt_opterr(c,
1373 (go->flags & GF_NONAME) ? null : argv[0],
1374 Treq_arg);
13711375 if (go->flags & GF_ERROR)
1372 bi_errorfz();
1376 bi_unwind(1);
13731377 return (ORD('?'));
13741378 }
13751379 go->p = 0;
13991403 }
14001404 }
14011405 return (ord(c));
1406 }
1407
1408 void
1409 ksh_getopt_opterr(int ch, const char *name, const char *msg)
1410 {
1411 static char buf[3] = { '-', KSH_BEL, '\0' };
1412
1413 buf[1] = ch;
1414 if (name == null || name == kshname)
1415 kwarnf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
1416 KWF_TWOMSG | KWF_NOERRNO, buf, msg);
1417 else
1418 kwarnf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
1419 KWF_THREEMSG | KWF_NOERRNO, name, buf, msg);
14021420 }
14031421
14041422 /*
16821700
16831701 if (max_colz > 2147483646) {
16841702 #ifndef MKSH_SMALL
1685 internal_warningf("print_columns called with %s=%zu >= INT_MAX",
1703 kwarnf0(KWF_INTERNAL | KWF_WARNING | KWF_NOERRNO,
1704 "print_columns called with %s=%zu >= INT_MAX",
16861705 "max_col", max_colz);
16871706 #endif
16881707 return;
16911710
16921711 if (max_oct > 2147483646) {
16931712 #ifndef MKSH_SMALL
1694 internal_warningf("print_columns called with %s=%zu >= INT_MAX",
1713 kwarnf0(KWF_INTERNAL | KWF_WARNING | KWF_NOERRNO,
1714 "print_columns called with %s=%zu >= INT_MAX",
16951715 "max_oct", max_oct);
16961716 #endif
16971717 return;
17571777 {
17581778 char *cp, *dp, *ep;
17591779
1780 rndpush(buf, len);
17601781 if (!len || !(dp = memchr(buf, '\0', len)))
17611782 return;
17621783
19671988 if (pathcnd) {
19681989 #ifdef MKSH__NO_PATH_MAX
19691990 /* same as notoktoadd(pathlen, 1) but adapted */
1970 if ((uintmax_t)sb.st_size >= (uintmax_t)SIZE_MAX) {
1991 if ((uintmax_t)sb.st_size >= (uintmax_t)mksh_MAXSZ) {
19711992 errno = ENAMETOOLONG;
19721993 goto notfound;
19731994 }
1974 ldestlen = sb.st_size + 1; /* <= SIZE_MAX */
1995 ldestlen = sb.st_size + 1; /* <= mksh_MAXSZ */
19751996 #endif
19761997 /* ldestsz == pathlen + 1 */
19771998 ldest = aresize(ldest, ldestsz, ATEMP);
24662487 * setting in AT&T ksh)
24672488 */
24682489 if (current_wd[0])
2469 /* Ignore failure (happens if readonly or integer) */
2490 /* Ignore failure (happens if read-only or integer) */
24702491 setstr(oldpwd_s, current_wd, KSH_RETURN_ERROR);
24712492
24722493 if (!mksh_abspath(Xstring(xs, xp))) {
24852506 char *ptmp = pwd;
24862507
24872508 set_current_wd(ptmp);
2488 /* Ignore failure (happens if readonly or integer) */
2509 /* Ignore failure (happens if read-only or integer) */
24892510 setstr(pwd_s, ptmp, KSH_RETURN_ERROR);
24902511 } else {
24912512 set_current_wd(null);
25022523 return (rv);
25032524 }
25042525
2505 #ifdef KSH_CHVT_CODE
25062526 extern void chvt_reinit(void);
25072527
25082528 static void
25092529 chvt(const Getopt *go)
25102530 {
2531 char buf[99], ch;
25112532 const char *dv = go->optarg;
2512 char *cp = NULL;
2513 int fd;
2514
2515 switch (*dv) {
2516 case '-':
2533 int fd, pfd[2];
2534 pid_t cpid;
2535 bool isdaemon = false, dowait = false;
2536 #ifndef MKSH_DISABLE_REVOKE_WARNING
2537 int revwarn = 0;
2538 #if !HAVE_REVOKE
2539 #define ifrevwarn
2540 #else
2541 #define ifrevwarn if (revwarn)
2542 #endif
2543 #endif
2544
2545 switch (ord(*dv)) {
2546 case ORD('-'):
2547 isdaemon = true;
25172548 dv = "/dev/null";
25182549 break;
2519 case '!':
2550 case ORD('!'):
2551 dowait = true;
25202552 ++dv;
25212553 /* FALLTHROUGH */
25222554 default: {
25232555 struct stat sb;
25242556
25252557 if (stat(dv, &sb)) {
2526 cp = shf_smprintf("/dev/ttyC%s", dv);
2527 dv = cp;
2528 if (stat(dv, &sb)) {
2529 memmove(cp + 1, cp, /* /dev/tty */ 8);
2530 dv = cp + 1;
2531 if (stat(dv, &sb)) {
2532 errorf(Tchvt2,
2533 "can't find tty", go->optarg);
2558 int E = errno;
2559
2560 memcpy(buf, "/dev/ttyC", 9U);
2561 strlcpy(buf + 9U, dv, sizeof(buf) - 9U);
2562 if (stat(buf, &sb)) {
2563 strlcpy(buf + 8U, dv, sizeof(buf) - 8U);
2564 if (stat(buf, &sb))
2565 kerrf(KWF_VERRNO | KWF_ERR(1) |
2566 KWF_PREFIX | KWF_TWOMSG, E,
2567 "chvt", dv);
2568 }
2569 dv = buf;
2570 }
2571 if (!S_ISCHR(sb.st_mode))
2572 kerrf(KWF_VERRNO | KWF_ERR(1) | KWF_PREFIX |
2573 KWF_TWOMSG, (int)(ENOTTY), "chvt", dv);
2574 #ifndef MKSH_DISABLE_REVOKE_WARNING
2575 #if !HAVE_REVOKE
2576 #ifdef ENOSYS
2577 revwarn = ENOSYS;
2578 #else
2579 revwarn = EINVAL;
2580 #endif
2581 #else
2582 revwarn = revoke(dv) ? errno : 0;
2583 #endif
2584 ifrevwarn kwarnf(KWF_VERRNO | KWF_PREFIX | KWF_THREEMSG,
2585 revwarn, "chvt", dv,
2586 "can't revoke; new shell is potentially insecure");
2587 #endif
2588 }
2589 }
2590 if (pipe(pfd))
2591 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_TWOMSG, "chvt", "pipe");
2592 switch ((cpid = fork())) {
2593 case -1:
2594 close(pfd[0]);
2595 close(pfd[1]);
2596 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_TWOMSG, "chvt", "fork");
2597 case 0:
2598 close(pfd[0]);
2599 break;
2600 default:
2601 close(pfd[1]);
2602 if (read(pfd[0], &ch, 1) != 1 || !isch(ch, '.'))
2603 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_THREEMSG |
2604 KWF_NOERRNO, "chvt", dv,
2605 "child process initialisation failure");
2606 close(pfd[0]);
2607 if (dowait) {
2608 pid_t corpse;
2609 int status;
2610
2611 while (/* CONSTCOND */ 1) {
2612 #ifndef MKSH_NOPROSPECTOFWORK
2613 corpse = waitpid(cpid, &status, 0);
2614 #else
2615 corpse = wait(&status);
2616 #endif
2617 if (corpse == -1) {
2618 status = errno;
2619 if (status == ECHILD)
2620 break;
2621 if (status == EINTR)
2622 continue;
2623 kerrf(KWF_ERR(1) | KWF_PREFIX |
2624 KWF_TWOMSG, "chvt", "wait");
25342625 }
2535 }
2536 }
2537 if (!S_ISCHR(sb.st_mode))
2538 errorf(Tchvt2, "not a char device", dv);
2539 #ifndef MKSH_DISABLE_REVOKE_WARNING
2540 #if HAVE_REVOKE
2541 if (revoke(dv))
2542 #endif
2543 warningf(false, Tchvt2,
2544 "new shell is potentially insecure, can't revoke",
2545 dv);
2546 #endif
2547 }
2548 }
2626 #ifdef MKSH_NOPROSPECTOFWORK
2627 /* should not happen but… */
2628 if (corpse != cpid)
2629 continue;
2630 #endif
2631 if (WIFSIGNALED(status)) {
2632 status = WTERMSIG(status);
2633 dv = status > 0 && status < ksh_NSIG ?
2634 ksh_sigmess(status) : NULL;
2635 if (ksh_sigmessf(dv))
2636 dv = "Signalled";
2637 kwarnf(KWF_PREFIX | KWF_TWOMSG |
2638 KWF_NOERRNO, "chvt", dv);
2639 } else if (WIFEXITED(status)) {
2640 status = (WEXITSTATUS(status)) & 255;
2641 if (!status)
2642 break;
2643 kwarnf0(KWF_PREFIX | KWF_NOERRNO,
2644 TchvtDone, status);
2645 } else
2646 continue;
2647 }
2648 }
2649 exit(0);
2650 }
2651 if (setsid() == -1)
2652 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_TWOMSG, "chvt", "setsid");
25492653 if ((fd = binopen2(dv, O_RDWR)) < 0) {
25502654 sleep(1);
2551 if ((fd = binopen2(dv, O_RDWR)) < 0) {
2552 errorf(Tchvt2, Topen, dv);
2553 }
2554 }
2555 afree(cp, ATEMP);
2556 if (go->optarg[0] != '!') {
2557 switch (fork()) {
2558 case -1:
2559 errorf(Tchvt_failed, "fork");
2560 case 0:
2561 break;
2562 default:
2563 exit(0);
2564 }
2565 }
2566 if (setsid() == -1)
2567 errorf(Tchvt_failed, "setsid");
2568 if (go->optarg[0] != '-') {
2655 if ((fd = binopen2(dv, O_RDWR)) < 0)
2656 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_THREEMSG,
2657 "chvt", dv, Topen);
2658 }
2659 if (!isdaemon) {
2660 #ifdef TIOCSCTTY
25692661 if (ioctl(fd, TIOCSCTTY, NULL) == -1)
2570 errorf(Tchvt_failed, "TIOCSCTTY");
2662 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_TWOMSG,
2663 "chvt", "TIOCSCTTY");
2664 #endif
2665 #if HAVE_TERMIOS_H
25712666 if (tcflush(fd, TCIOFLUSH))
2572 errorf(Tchvt_failed, "TCIOFLUSH");
2667 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_TWOMSG,
2668 "chvt", "TCIOFLUSH");
2669 #else
2670 if (ioctl(fd, TCFLSH, 2) == -1)
2671 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_TWOMSG,
2672 "chvt", "TCFLSH");
2673 #endif
25732674 }
25742675 ksh_dup2(fd, 0, false);
25752676 ksh_dup2(fd, 1, false);
25762677 ksh_dup2(fd, 2, false);
2678 #ifndef MKSH_DISABLE_REVOKE_WARNING
2679 if (!isdaemon) {
2680 ifrevwarn kwarnf(KWF_VERRNO | KWF_PREFIX | KWF_THREEMSG,
2681 revwarn, "chvt", dv,
2682 "can't revoke; new shell is potentially insecure");
2683 }
2684 #endif
25772685 if (fd > 2)
25782686 close(fd);
25792687 rndset((unsigned long)chvt_rndsetup(go, sizeof(Getopt)));
25802688 chvt_reinit();
2581 }
2582 #endif
2689 /* signal parent the all OK */
2690 if (write(pfd[1], Tdot, 1) != 1)
2691 kwarnf(KWF_PREFIX | KWF_TWOMSG, "chvt", "write");
2692 close(pfd[1]);
2693 }
25832694
25842695 #if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
25852696 char *
26402751 errno = EINVAL;
26412752 #endif
26422753 if ((CLK_TCK = sysconf(_SC_CLK_TCK)) == -1L)
2643 internal_errorf("sysconf(_SC_CLK_TCK): %s", cstrerror(errno));
2754 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_ONEMSG,
2755 "sysconf(_SC_CLK_TCK)");
26442756 #endif
26452757 INVTCK(ru->ru_utime, u);
26462758 INVTCK(ru->ru_stime, s);
27812893
27822894 #ifdef DEBUG
27832895 #undef strchr
2896 /* pre-initio() */
27842897 char *
27852898 ucstrchr(char *s, int c)
27862899 {
+201
-148
mksh.1 less more
0 .\" $MirOS: src/bin/mksh/mksh.1,v 1.525+locale-tracking 2021/10/10 21:33:55 tg Exp $
0 .\" $MirOS: src/bin/mksh/mksh.1,v 1.532+locale-tracking 2022/01/28 10:28:19 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,
44 .\" 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
5 .\" 2018, 2019, 2020, 2021
5 .\" 2018, 2019, 2020, 2021, 2022
66 .\" mirabilos <m@mirbsd.org>
77 .\"
88 .\" Provided that these terms and disclaimer and all copyright notices
6363 . ds en \(em
6464 .\}
6565 .ie n \{\
66 . ds EM \ \*(en\ \&
66 . ds EM \ \(em\ \&
6767 .\}
6868 .el \{\
6969 . ds EM \f(TR\^\(em\^\fP
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: October 10 2021 $
86 .Dd $Mdocdate: January 28 2022 $
8787 .\"
8888 .\" Check which macro package we use, and do other -mdoc setup.
8989 .\"
197197 .Nd MirBSD Korn shell
198198 .Sh SYNOPSIS
199199 .Nm
200 .Bk -words
201200 .Op Fl +abCefhiklmnprUuvXx
202 .Oo
203 .Fl T Oo Ar \&! Oc Ns Ar tty
204 \*(Ba
205 .Ar \&\-
201 .Op Fl +o Ar option
202 .Oo Fl T Oo Ar !\&
203 .Oc Ns Ar tty Ns \*(Ba Ns Ar \-\&
206204 .Oc
205 .Op Ar file Op Ar arg1 ...
206 .Nm
207 .Op Fl +abCefhiklmnprUuvXx
207208 .Op Fl +o Ar option
208 .Oo
209 .Fl c Ar string \*(Ba
210 .Fl s \*(Ba
211 .Ar file
212 .Op Ar argument ...
209 .Oo Fl T Oo Ar !\&
210 .Oc Ns Ar tty Ns \*(Ba Ns Ar \-\&
213211 .Oc
214 .Ek
212 .Fl c
213 .Ar cmd
214 .Op Ar arg0 ...
215 .Nm
216 .Op Fl +abCefhiklmnprUuvXx
217 .Op Fl +o Ar option
218 .Oo Fl T Oo Ar !\&
219 .Oc Ns Ar tty Ns \*(Ba Ns Ar \-\&
220 .Oc
221 .Fl s
222 .Op Ar arg1 ...
215223 .Nm builtin-name
216224 .Op Ar argument ...
217225 .Sh DESCRIPTION
218226 .Nm
219227 is a command interpreter intended for both interactive and shell
220228 script use.
221 Its command language is a superset of the
229 Its command language is a superset of both
222230 .Xr sh C
231 and
232 .Tn POSIX
223233 shell language and largely compatible to the original Korn shell.
224234 At times, this manual page may give scripting advice; while it
225235 sometimes does take portable shell scripting or various standards
230240 Please refer to:
231241 .Pa http://www.mirbsd.org/mksh\-faq.htm#sowhatismksh
232242 .Ss Invocation
233 Most builtins can be called directly, for example if a link points from its
234 name to the shell; not all make sense, have been tested or work at all though.
243 Most builtins can be called directly, for example if a link or
244 .Xr symlink 7
245 points to
246 .Nm ,
247 or if
248 .Va argv[0]
249 is set correspondingly;
250 this does not make sense for, or works properly with, all built-in utilities though.
235251 .Pp
236252 The options are as follows:
237 .Bl -tag -width XcXstring
238 .It Fl c Ar string
253 .Bl -tag -width 2n
254 .It Fl c
239255 .Nm
240256 will execute the command(s) contained in
241 .Ar string .
257 .Ar cmd ,
258 setting
259 .Li $0
260 to
261 .Ar arg0
262 .Pq if present ,
263 .Li $1
264 to the next argument, etc.
265 If compiled with
266 .Dv \-DMKSH_MIDNIGHTBSD01ASH_COMPAT
267 and in
268 .Fl o Ic sh
269 mode, a
270 .Dq Li \-\-
271 argument directly following
272 .Ar cmd
273 is ignored for compatibility with the legacy
274 .Fx
275 .Nm sh ;
276 this is deprecated and may go away in the future.
242277 .It Fl i
243278 Interactive shell.
244279 A shell that reads commands from standard input is
269304 command below).
270305 .It Fl l
271306 Login shell.
272 If the name or basename the shell is called with (i.e. argv[0])
273 starts with
307 If the name the shell is called as
308 .Pq i.e.\& Va argv[0]
309 or its basename begins with a dash
310 .Pq hyphen-minus
274311 .Ql \-
275 or if this option is used,
276 the shell is assumed to be a login shell; see
312 or if this option is given,
313 the shell is a
314 .Dq login shell ;
315 see
277316 .Sx Startup files
278317 below.
279318 .It Fl p
280319 Privileged shell.
281320 A shell is
282321 .Dq privileged
283 if the real user ID or group ID does not match the
284 effective user ID or group ID (see
322 if the real user ID from
285323 .Xr getuid 2
286 and
287 .Xr getgid 2 ) .
324 or group ID from
325 .Xr getgid 2
326 does not match the effective user ID or group ID.
288327 Clearing the privileged option causes the shell to set
289 its effective user ID (group ID) to its initial real user ID (group ID).
328 its effective user ID and group ID to its initial real user ID
329 and group ID, respectively.
290330 For further implications, see
331 .Ic set Fl p
332 and
291333 .Sx Startup files .
292 If the shell is privileged and this flag is not explicitly set, the
334 If the shell is privileged and this flag is not set explicitly on invocation,
335 nor during processing the startup files, the
293336 .Dq privileged
294 option is cleared automatically after processing the startup files.
337 flag is cleared automatically afterwards.
295338 .It Fl r
296339 Restricted shell.
297340 A shell is
298341 .Dq restricted
299 if the basename the shell is called with, after
300 .Ql \-
301 processing, starts with
342 if the basename the shell is called with, after dash removal, begins with
302343 .Ql r
303344 or if this option is used.
304345 The following restrictions come into effect after the shell processes any
308349 .Pp
309350 .Bl -bullet -compact
310351 .It
311 Command names cannot be specified with pathnames, absolute or relative,
312 nor using the
352 Command names cannot be specified with pathnames, either absolute or relative;
353 the
313354 .Fl p
314 option of the
355 flag of the
315356 .Ic command
316 built-in utility; the
357 built-in utility is not usable.
358 The
317359 .Ev ENV ,
318360 .Ev PATH
319361 and
322364 .It
323365 The current location is fixed: the
324366 .Ic cd
325 command and its alias
326 .Ic chdir
327 is disabled.
367 builtin is disabled.
328368 .It
329 Redirections that create files can't be used (i.e.\&
369 Redirections that create files, i.e.\&
330370 .Dq Li \*(Gt ,
331371 .Dq Li \*(Gt\*(Ba ,
332 .Dq Li \*(Gt\*(Gt ,
333 .Dq Li \*(Lt\*(Gt ) ,
334 and the
372 .Dq Li \*(Gt\*(Gt
373 and
374 .Dq Li \*(Lt\*(Gt ,
375 cannot be used, and the
335376 .Ev HISTFILE
336377 parameter cannot be changed.
337378 .El
338379 .It Fl s
339 The shell reads commands from standard input; all non-option arguments
340 are positional parameters.
341 .It Fl T Ar name
380 .Nm
381 will read and execute commands from standard input; all non-option arguments
382 are assigned to the positional parameters.
383 .It Fl T Ar \-
384 Detach from the controlling terminal, return immediately
385 .Pq daemonise .
386 .It Xo
387 .Fl T Oo Ar !\& Oc Ns Ar name
388 .Xc
342389 Spawn
343390 .Nm
344391 on the
346393 device given.
347394 The paths
348395 .Ar name ,
349 .Pa /dev/ttyC Ns Ar name
350 and
351 .Pa /dev/tty Ns Ar name
396 .Li /dev/ttyC Ns Ar name
397 and
398 .Li /dev/tty Ns Ar name
352399 are attempted in order.
353 Unless
354 .Ar name
355 begins with an exclamation mark
356 .Pq Ql \&! ,
357 this is done in a subshell and returns immediately.
358400 If
359401 .Ar name
360 is a dash
361 .Pq Ql \&\- ,
362 detach from controlling terminal (daemonise) instead.
402 is prefixed with an exclamation mark
403 .Pq Ql \&! ,
404 wait for the spawned shell to return,
405 report its exit status or terminating signal visually.
406 Exit 0 if spawned.
363407 .El
364408 .Pp
365 In addition to the above, the options described in the
409 In addition to the above, the flags
410 .Op Fl +abCefhkmnUuvXx
411 and
412 .Op Fl +o Ar option ,
413 respectively for single-letter and long options,
414 as described for the
366415 .Ic set
367 built-in command can also be used on the command line:
368 both
369 .Op Fl +abCefhkmnuvXx
370 and
371 .Op Fl +o Ar option
372 can be used for single letter or long options, respectively.
416 built-in utility, can be used on the command line.
373417 .Pp
374418 If neither the
375419 .Fl c
376420 nor the
377421 .Fl s
378 option is specified, the first non-option argument specifies the name
379 of a file the shell reads commands from.
380 If there are no non-option
381 arguments, the shell reads commands from the standard input.
382 The name of the shell (i.e. the contents of $0)
383 is determined as follows: if the
384 .Fl c
385 option is used and there is a non-option argument, it is used as the name;
386 if commands are being read from a file, the file is used as the name;
387 otherwise, the name the shell was called with (i.e. argv[0]) is used.
388 .Pp
389 The exit status of the shell is 127 if the command file specified on the
390 command line could not be opened, or non-zero if a fatal syntax error
391 occurred during the execution of a script.
392 In the absence of fatal errors,
393 the exit status is that of the last command executed, or zero if no
394 command is executed.
422 options are specified,
423 .Nm mksh
424 will read and execute commands as if the
425 .Fl s
426 flag was passed iff the
427 .Ar file
428 argument is absent or
429 .Dq Li \- ;
430 otherwise, it sets $0 to
431 .Ar file
432 and reads commands from it.
433 Further arguments
434 .Ar arg1 ...
435 are assigned to positional parameters.
436 .Pp
437 The exit status of the shell is 127 if the
438 .Ar file
439 specified on the command line could not be opened,
440 or non-zero if a fatal error occurred during execution of the script.
441 Otherwise, the errorlevel is that of the last command executed,
442 0 if no command was executed.
395443 .Ss Startup files
396444 For the actual location of these files, see
397445 .Sx FILES .
13931441 .Sx Arithmetic expressions
13941442 for a description of an expression.
13951443 .Ss Parameters
1396 Parameters are shell variables; they can be assigned values and their values
1444 Parameters are shell variables; they can be assigned values, and their values
13971445 can be accessed using a parameter substitution.
13981446 A parameter name is either one
1399 of the special single punctuation or digit character parameters described
1400 below, or a letter followed by zero or more letters or digits
1401 .Po
1402 .Ql _
1403 counts as a letter
1404 .Pc .
1405 The latter form can be treated as arrays by appending an array index of the
1406 form
1407 .Op Ar expr
1408 where
1447 of the special single punctuation character or positional parameters described
1448 below, or a letter followed by zero or more letters, digits or underscores.
1449 The latter form can be accessed as array appending an index of the form
1450 .Li [\& Ns Ar expr Ns Li ]\&
1451 (in which
14091452 .Ar expr
1410 is an arithmetic expression.
1411 Array indices in
1412 .Nm
1413 are limited to the range 0 through 4294967295, inclusive.
1414 That is, they are a 32-bit unsigned integer.
1453 is an arithmetic expression).
1454 Array indices range from 0 to 4294967295
1455 .Pq 2\*(ha32\-1 ,
1456 inclusive, in
1457 .Nm .
14151458 .Pp
14161459 Parameter substitutions take the form
14171460 .Pf $ Ns Ar name ,
17551798 are evaluated as arithmetic expressions.
17561799 .Pp
17571800 .It Pf ${ Ns Ar name Ns @#}
1758 The hash (using the BAFH algorithm) of the expansion of
1801 The hash (using the BAFH1-0 algorithm) of the expansion of
17591802 .Ar name .
17601803 This is also used internally for the shell's hashtables.
17611804 .Pp
18281871 .It Ev 1 No .. Ev 9
18291872 The first nine positional parameters that were supplied to the shell, function,
18301873 or script sourced using the
1831 .Dq Li \&.
1832 built-in.
1874 .Dq Li .\&
1875 .Pq Dq dot
1876 builtin.
18331877 Further positional parameters may be accessed using
18341878 .Pf ${ Ar number Ns } .
18351879 .It Ev *
32433287 .It Ic Lbafh_add Op Ar string
32443288 .It Ic Lbafh_finish
32453289 .Pq Li dot.mkshrc No functions
3246 Implement the Better Avalance for the Jenkins Hash.
3290 Implement the Better Avalance for Jenkins Hash
3291 .Pq IV=1 .
32473292 This is the same hash
32483293 .Nm
32493294 currently uses internally.
44264471 ROT13-encrypts/-decrypts stdin to stdout.
44274472 .Pp
44284473 .It Xo
4429 .Ic set Op Fl +abCefhiklmnprsUuvXx
4474 .Ic set Op Fl +abCefhkmnpsUuvXx
44304475 .Op Fl +o Ar option
44314476 .Op Fl +A Ar name
44324477 .Op Fl \-
4433 .Op Ar arg ...
4434 .Xc
4478 .Op Ar argument ...
4479 .Xc
4480 .It Xo
4481 .Ic set Fl \-
4482 .Op Ar argument ...
4483 .Xc
4484 .It Ic set Fl +o
44354485 .Pq keeps assignments , special
44364486 The
44374487 .Ic set
44514501 .Fl + Ns Ar letter
44524502 syntax, where
44534503 .Ar letter
4454 is the option's single letter name (not all options have a single letter name).
4455 The following table lists short (if extant) and long names
4504 is the option's single letter name (not all options have both names).
4505 The following table lists short and long names
4506 .Pq if extant
44564507 along with a description of what each option does:
44574508 .Bl -tag -width 3n
44584509 .It Fl A Ar name
44594510 Sets the elements of the array parameter
44604511 .Ar name
44614512 to
4462 .Ar arg ...
4513 .Ar argument ...
44634514 .Pp
44644515 If
44654516 .Fl A
44924543 Only used with job control
44934544 .Pq Fl m .
44944545 .It Fl C \*(Ba Fl o Ic noclobber
4495 Prevent \*(Gt redirection from overwriting existing files.
4496 Instead, \*(Gt\*(Ba must be used to force an overwrite.
4546 Prevent \*(Gt redirection from overwriting existing files;
4547 .Ql \*(Gt\*(Ba
4548 must be used to force overwriting instead.
44974549 .Em Note:
44984550 This is not safe to use for creation of temporary files or
44994551 lockfiles due to a TOCTOU in a check allowing one to redirect output to
45014553 or other device files even in
45024554 .Ic noclobber
45034555 mode.
4556 .It Fl c
4557 Commands are read from an argument string.
4558 Can only be used when the shell is invoked.
45044559 .It Fl e \*(Ba Fl o Ic errexit
45054560 Exit (after executing the
45064561 .Dv ERR
45504605 the effective UID (EUID) or GID (EGID), respectively.
45514606 See above for a description of what this means.
45524607 .Pp
4553 If the shell is privileged, setting this flag after startup files
4554 have been processed let it go full setuid and/or setgid.
4555 Clearing this flag makes the shell drop privileges.
4556 Changing this flag resets the groups vector.
4608 If the shell is privileged, setting this flag after startup file
4609 processing let it go full setuid and/or setgid.
4610 Clearing the flag makes the shell drop privileges.
4611 Changing this flag resets the supplementary groups vector.
45574612 .It Fl r \*(Ba Fl o Ic restricted
45584613 The shell is a restricted shell.
45594614 This option can only be used when the shell is invoked.
45774632 and internal string handling functions.
45784633 This flag is disabled by default, but can be enabled by setting it on the
45794634 shell command line; is enabled automatically for interactive shells if
4580 requested at compile time, your system supports
4581 .Fn setlocale LC_CTYPE \&""
4582 and optionally
4583 .Fn nl_langinfo CODESET ,
4584 or the
4635 the POSIX locale uses the UTF-8 codeset or, lacking POSIX locales, the
45854636 .Ev LC_ALL ,
45864637 .Ev LC_CTYPE
45874638 or
45884639 .Ev LANG
4589 environment variables,
4590 and at least one of these returns something that matches
4591 .Dq UTF\-8
4640 environment variables either case-insensitively equal
4641 .Dq Li UTF\-8
45924642 or
4593 .Dq utf8
4594 case-insensitively; for direct builtin calls depending on the
4595 aforementioned environment variables.
4643 .Dq Li utf8
4644 or have that as codeset modifier.
45964645 .Pp
45974646 This build of the shell implements baroque locale tracking, that is,
45984647 .Ic set Fl +U
46574706 Do not kill running jobs with a
46584707 .Dv SIGHUP
46594708 signal when a login shell exits.
4660 Currently set by default, but this may
4661 change in the future to be compatible with
4662 .At
4663 .Nm ksh ,
4664 which
4665 doesn't have this option, but does send the
4666 .Dv SIGHUP
4667 signal.
4709 Currently enabled by default.
46684710 .It Fl o Ic nolog
46694711 No effect.
46704712 In the original Korn shell, this prevented function definitions from
47654807 .Pp
47664808 These options can also be used upon invocation of the shell.
47674809 The current set of
4768 options (with single letter names) can be found in the parameter
4810 options with single letter names can be found in the parameter
47694811 .Dq Li $\- .
47704812 .Ic set Fl o
47714813 with no option name will list all the options and whether each is on or off;
47754817 construct, which is an implementation detail; these commands are transient
47764818 .Pq only valid within the current shell session .
47774819 .Pp
4778 Remaining arguments, if any, are positional parameters and are assigned, in
4779 order, to the positional parameters (i.e. $1, $2, etc.).
4820 A lone
4821 .Dq Li \-
4822 clears both the
4823 .Fl v
4824 and
4825 .Fl x
4826 options (obsolete); it
4827 .Pq or a lone Dq Li +\&
4828 terminates option processing and is otherwise ignored.
4829 .Pp
4830 .No Remaining Ar argument Ns s ,
4831 if any, are assigned (in order, unless
4832 .Fl s
4833 is given) to
4834 .Ar name
4835 .Pq with Fl A
4836 or the positional parameters
4837 .Pq i.e.,\& $1, $2, etc .
4838 .No Use Fl \-
4839 if the first argument begins with plus or dash.
47804840 If options end with
47814841 .Dq Li \-\-
47824842 and there are no remaining arguments, all positional parameters are cleared.
4783 For unknown historical reasons, a lone
4784 .Dq Li \-
4785 option is treated specially\*(EMit clears both the
4786 .Fl v
4787 and
4788 .Fl x
4789 options.
47904843 If no options or arguments are given, the values of all parameters are printed
47914844 .Pq suitably quoted .
47924845 .Pp
59425995 builtin does not interpret backslashes and only supports the exact option
59435996 .Fl n ,
59445997 unless built with
5945 .Ev \-DMKSH_MIDNIGHTBSD01ASH_COMPAT .
5998 .Dv \-DMKSH_MIDNIGHTBSD01ASH_COMPAT .
59465999 .It
59476000 The substitution operations
59486001 .Sm off
59816034 eats a leading
59826035 .Fl \-
59836036 if built with
5984 .Ev \-DMKSH_MIDNIGHTBSD01ASH_COMPAT .
6037 .Dv \-DMKSH_MIDNIGHTBSD01ASH_COMPAT .
59856038 .El
59866039 .Ss Interactive input line editing
59876040 The shell supports three modes of reading command lines from a
72607313 .Nm mksh
72617314 currently uses OPTU-16 internally, which is the same as UTF-8 and CESU-8
72627315 with 0000..FFFD being valid codepoints; raw octets map to U+EF80..U+EFFF
7263 for releases before R60, U-00200080..U-002000FF for R60 onwards.
7316 for releases before R60, U-10000080..U-100000FF for R60 onwards.
72647317 .Em Future compatibility note :
72657318 there's work underway to use full 21-bit UTF-8 in mksh R60 or so.
72667319 .Sh BUGS
0 RCSID: $MirOS: src/bin/mksh/mksh.faq,v 1.28+locale-tracking 2021/10/03 23:38:13 tg Exp $
0 RCSID: $MirOS: src/bin/mksh/mksh.faq,v 1.32+locale-tracking 2022/01/25 06:07:32 tg Exp $
11 ToC: spelling
22 Title: How do you spell <tt>mksh</tt>? How do you pronounce it?
33
473473 the PUA; however, there is ambiguity if encountering those UTF-8-encoded, so
474474 it changed for R60.) The <tt>Arithmetic expressions</tt> and <tt>CAVEATS</tt>
475475 sections in mksh(1) contain more details about encoding and mapping.</p>
476 <p>As of R60, <tt>utf8-mode</tt> maps “raw octets” to U-00200080‥U-002000FF,
476 <p>As of R60, <tt>utf8-mode</tt> maps “raw octets” to U-10000080‥U-100000FF,
477477 which is outside the UCS and therefore collision-free. There’s work underway
478478 to make the shell support the full 21-bit UCS range for R60.</p>
479479 <p class="boxhead">The following POSIX sh-compatible code toggles the
483483 <div class="boxtext">
484484 <pre>
485485 case ${KSH_VERSION:-} in
486 *MIRBSD KSH*|*LEGACY KSH*)
486 *MIRBSD\ KSH*|*LEGACY\ KSH*)
487487 case ${LC_ALL:-${LC_CTYPE:-${LANG:-}}} in
488488 *[Uu][Tt][Ff]8*|*[Uu][Tt][Ff]-8*) set -U ;;
489489 *) set +U ;;
540540 … becomes…<br />
541541 <tt>[[ foo = *@(foo|bar)*baz* ]]</tt></p>
542542 ----
543 ToC: local-arrays
544 Title: How can I do local arrays?
545
546 <p class="boxhead">mksh supports function-local arrays with an “onion
547 model” in which you can basically create (and unset) a local variable
548 in a function, which may of course be array-typed:</p>
549 <div class="boxtext">
550 <pre>
551 function foo {
552 a[1]=x # modifies the outer array
553 echo ${a[*]}
554 local a # makes a local variable…
555 set -A a # … of type array…
556 a[0]=yz # modifies the inner array
557 echo ${a[*]}
558 unset a # removes the local variable
559 echo ${a[*]}
560 a[2]=! # modifies the unveiled outer again
561 echo ${a[*]}
562 }
563 set -A a -- 1 2 3 4 5
564 echo ${a[*]} # shows the outer array before…
565 foo
566 echo ${a[*]} # …and after the function ran
567 </pre>
568 </div><p class="boxfoot">This also works with <tt>a=(…)</tt> and
569 in POSIX-style functions <tt>foo() { …; }</tt> (in mksh, although
570 not in AT&amp;T ksh which uses a different scope model) and with
571 appending <tt>a+=(…)</tt> (and <tt>set -A a+ -- …</tt>), and even
572 no-truncation array assignments <tt>set +A a -- …</tt> behave in
573 a consistent manner.</p>
574 ----
543575 ToC: trim-vector
544576 Title: ${@?}: bad substitution
545577
552584 ToC: extensions-to-avoid
553585 Title: Are there any extensions to avoid?
554586
555 <p>GNU <tt>bash</tt> supports “<tt>&amp;&gt;</tt>” (and “|&amp;”) to redirect
556 both stdout and stderr in one go, but this breaks POSIX and Korn Shell syntax;
557 use POSIX redirections instead:</p>
587 <p>GNU <tt>bash</tt> supports “<tt>&amp;&gt;</tt>” (and “<tt>|&amp;</tt>”)
588 to redirect both stdout and stderr in one go, but this breaks POSIX
589 and Korn Shell syntax; use POSIX redirections instead:</p>
558590 <table border="1" cellpadding="3">
559591 <tr><td>GNU bash</td><td>
560592 <tt>foo |&amp; bar |&amp; baz &amp;&gt;log</tt>
2626 #include "sh.h"
2727
2828 #include <klibc/startup.h>
29 #include <errno.h>
30 #include <io.h>
31 #include <unistd.h>
3229 #include <process.h>
3330
34 __RCSID("$MirOS: src/bin/mksh/os2.c,v 1.12 2021/07/30 02:58:07 tg Exp $");
31 __RCSID("$MirOS: src/bin/mksh/os2.c,v 1.16 2022/01/06 22:35:02 tg Exp $");
3532
3633 struct a_s_arg {
3734 union {
6764 #define KLIBC_ARG_RESPONSE_EXCLUDE \
6865 (__KLIBC_ARG_DQUOTE | __KLIBC_ARG_WILDCARD | __KLIBC_ARG_SHELL)
6966
67 /* pre-initio() */
7068 static void
7169 response(int *argcp, const char ***argvp)
7270 {
105103 line = malloc(filesize + /* type */ 1 + /* NUL */ 1);
106104 if (!line) {
107105 exit_out_of_memory:
108 fputs("Out of memory while reading response file\n", stderr);
106 SHIKATANAI write(2,
107 SC("mksh: out of memory reading response file\n"));
109108 exit(255);
110109 }
111110
147146 free(line);
148147
149148 if (ferror(f)) {
150 fputs("Cannot read response file\n", stderr);
149 SHIKATANAI write(2,
150 SC("mksh: can't read response file\n"));
151151 exit(255);
152152 }
153153
162162 *argvp = new_argv;
163163 }
164164
165 /* pre-initio() */
165166 static void
166167 init_extlibpath(void)
167168 {
181182 }
182183 }
183184
185 /* pre-initio() */
184186 void
185187 os2_init(int *argcp, const char ***argvp)
186188 {
513515 add_temp(const char *name)
514516 {
515517 struct temp *tp;
516
517 tp = alloc(offsetof(struct temp, tffn[0]) + strlen(name) + 1, APERM);
518 memcpy(tp->tffn, name, strlen(name) + 1);
518 size_t len;
519
520 len = strlen(name);
521 tp = alloc(offsetof(struct temp, tffn[0]) + ++len, APERM);
522 memcpy(tp->tffn, name, len);
519523 tp->next = templist;
520524 templist = tp;
521525 }
+297
-184
sh.h less more
1010 /*-
1111 * Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
1212 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
13 * 2019, 2020, 2021
13 * 2019, 2020, 2021, 2022
1414 * mirabilos <m@mirbsd.org>
1515 *
1616 * Provided that these terms and disclaimer and all copyright notices
2929 * of said person’s immediate fault when using the work as intended.
3030 */
3131
32 #define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.978 2022/01/28 10:28:20 tg Exp $"
33
3234 #ifdef MKSH_USE_AUTOCONF_H
3335 /* things that “should” have been on the command line */
3436 #include "autoconf.h"
3537 #undef MKSH_USE_AUTOCONF_H
36 #endif
37
38 #ifdef __dietlibc__
39 /* XXX imake style */
40 #define _BSD_SOURCE /* live, BSD, live❣ */
4138 #endif
4239
4340 #if HAVE_SYS_PARAM_H
125122 #ifdef MIRBSD_BOOTFLOPPY
126123 #include <wchar.h>
127124 #endif
125 #include "mbsdint.h"
128126
129127 /* monkey-patch known-bad offsetof versions to quell a warning */
130128 #if (defined(__KLIBC__) || defined(__dietlibc__)) && \
203201 #define __SCCSID(x) __IDSTRING(sccsid,x)
204202 #endif
205203
206 #ifdef EXTERN
207 __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.954 2021/10/11 22:35:23 tg Exp $");
208 #endif
209 #define MKSH_VERSION "R59 2021/10/15"
210
211 /* arithmetic types: C implementation */
212 #if !HAVE_CAN_INTTYPES
213 #if !HAVE_CAN_UCBINTS
214 typedef signed int int32_t;
215 typedef unsigned int uint32_t;
216 #else
217 typedef u_int32_t uint32_t;
218 #endif
219 #endif
204 #define MKSH_VERSION "R59 2022/01/27"
220205
221206 /* shell types */
222207 typedef unsigned char kby; /* byte */
223 typedef unsigned int kui; /* wchar; kby or EOF; etc. */
208 typedef unsigned int kui; /* wchar; kby or EOF; ⊇k32; etc. */
209 /* main.c cta:int_32bit guaranteed */
210 typedef unsigned int k32; /* 32-bit arithmetic (hashes etc.) */
211 /* for use with/without 32-bit masking */
224212 typedef unsigned long kul; /* long, arithmetic */
225213 typedef signed long ksl; /* signed long, arithmetic */
226214
227 #define KBY(c) ((kby)(c)) /* byte, truncated if necessary */
228 #define KBI(c) ((kui)(kby)(c)) /* byte as u_int, truncated */
215 #define KBY(c) ((kby)(KUI(c) & 0xFFU)) /* byte, truncated if necessary */
216 #define KBI(c) ((kui)(KUI(c) & 0xFFU)) /* byte as u_int, truncated */
229217 #define KUI(u) ((kui)(u)) /* int as u_int, not truncated */
218 #define K32(u) ((k32)(KUI(u) & 0xFFFFFFFFU))
230219
231220 /* arithmetic types: shell arithmetics */
221
222 /* “cast” between unsigned / signed long */
223 #define KUL2SL(ul) mbiA_U2S(kul, ksl, LONG_MAX, ul)
224 #define KSL2UL(sl) mbiA_S2U(kul, ksl, sl)
225
226 /* convert between signed and sign variable plus magnitude */
227 #define KNEGUL2SL(n,ul) mbiA_VZM2S(kul, ksl, n, ul)
228 /* n = sl < 0; //mbiA_S2VZ(sl); */
229 #define KSL2NEGUL(sl) mbiA_S2M(kul, ksl, sl)
230
231 /* new arithmetics tbd, using mbiMA_* */
232
233 /* older arithmetics, to be replaced later */
232234 #ifdef MKSH_LEGACY_MODE
233235 /*
234236 * POSIX demands these to be the C environment's long type
241243 * integer wraparound, even across division and modulo, for
242244 * any shell code using them, is guaranteed.
243245 */
246 #if HAVE_CAN_INTTYPES
244247 typedef int32_t mksh_ari_t;
245248 typedef uint32_t mksh_uari_t;
246 #endif
249 #else
250 /* relies on compile-time asserts and CFLAGS to validate that */
251 typedef signed int mksh_ari_t;
252 typedef unsigned int mksh_uari_t;
253 #define INT32_MIN INT_MIN
254 #define INT32_MAX INT_MAX
255 #define UINT32_MAX UINT_MAX
256 #endif
257 #endif
258
259 /* new arithmetics in preparation */
247260
248261 /* boolean type (no <stdbool.h> deliberately) */
249262 typedef unsigned char mksh_bool;
290303 #undef PRINT /* LynxOS defines that somewhere */
291304 #undef flock /* SCO UnixWare defines that to flock64 but ENOENT */
292305
306 /* compiler shenanigans… */
307 #ifdef _FORTIFY_SOURCE
308 /* workaround via https://stackoverflow.com/a/64407070/2171120 */
309 #define SHIKATANAI (void)!
310 #else
311 #define SHIKATANAI (void)
312 #endif
313
293314 #ifndef MKSH_INCLUDES_ONLY
294
295 /* compile-time assertions */
296 #define cta(name,expr) struct cta_ ## name { char t[(expr) ? 1 : -1]; }
297
298 /* counts the value bits when given inttype_MAX as argument */
299 #define IMAX_BITS(m) ((m) / ((m) % 255 + 1) / 255 % 255 * 8 + 7 - \
300 86 / ((m) % 255 + 12))
301 /* taken from comp.lang.c by Hallvard B Furuseth */
302315
303316 /* EBCDIC fun */
304317
310323 # endif
311324 # if __CHARSET_LIB && defined(MKSH_EBCDIC)
312325 # error "Please compile without -E argument to Build.sh for ASCII!"
313 # endif
314 # if __CHARSET_LIB && !defined(_ENHANCED_ASCII_EXT)
315 /* go all-out on ASCII */
316 # define _ENHANCED_ASCII_EXT 0xFFFFFFFF
317326 # endif
318327 #endif
319328
382391 #endif
383392
384393 #ifndef SIZE_MAX
385 #ifdef SIZE_T_MAX
386 #define SIZE_MAX SIZE_T_MAX
387 #else
388394 #define SIZE_MAX ((size_t)-1)
389395 #endif
396
397 #ifndef PTRDIFF_MAX
398 #if (sizeof(size_t) == sizeof(ptrdiff_t)) && ((SIZE_MAX) == ((size_t)-1))
399 #define PTRDIFF_MAX ((ptrdiff_t)(SIZE_MAX >> 1))
400 #endif
401 #endif
402
403 /* limit maximum object size so we can express pointer differences w/o UB */
404 #if SIZE_MAX <= PTRDIFF_MAX
405 #define mksh_MAXSZ SIZE_MAX
406 #else
407 #define mksh_MAXSZ ((size_t)PTRDIFF_MAX)
390408 #endif
391409
392410 /* if this breaks, see sh.h,v 1.954 commit message and diff */
397415 #define KSH_ISVDIS(x,d) ((x) == _POSIX_VDISABLE ? (d) : KBI(x))
398416 #define KSH_DOVDIS(x) (x) = _POSIX_VDISABLE
399417
418 #ifndef S_ISFIFO
419 #define S_ISFIFO(m) ((m & 0170000) == 0010000)
420 #endif
400421 #ifndef S_ISCHR
401422 #define S_ISCHR(m) ((m & 0170000) == 0020000)
402423 #endif
469490 #define ksh_sigrestore(s,svp) ksh_sigset((s), *(svp), NULL)
470491 #endif
471492
493 #if HAVE_SIGDESCR_NP
494 #define ksh_sigmess(nr) sigdescr_np(nr)
495 #elif HAVE_SYS_SIGLIST
496 #if !HAVE_SYS_SIGLIST_DECL
497 extern const char * const sys_siglist[];
498 #endif
499 #define ksh_sigmess(nr) sys_siglist[nr]
500 #elif HAVE_STRSIGNAL
501 #define ksh_sigmess(nr) strsignal(nr)
502 #else
503 #define ksh_sigmess(nr) NULL
504 #endif
505 #define ksh_sigmessf(mess) (!(mess) || !*(mess))
506
472507 /* contract: masks the signal, may restart, not oneshot */
473508 void ksh_sigset(int, sig_t, ksh_sigsaved *);
474509
521556 extern int revoke(const char *);
522557 #endif
523558
559 #ifndef EOVERFLOW
560 #define EOVERFLOW ERANGE
561 #endif
562
524563 #if defined(DEBUG) || !HAVE_STRERROR
525564 #undef strerror
526565 #define strerror /* poisoned */ dontuse_strerror
527 #define cstrerror /* replaced */ cstrerror
528566 extern const char *cstrerror(int);
529567 #else
530568 #define cstrerror(errnum) ((const char *)strerror(errnum))
705743
706744 /* use this ipv strchr(s, 0) but no side effects in s! */
707745 #define strnul(s) ((s) + strlen((const void *)s))
746
747 /* inspired by jupp, where they are in lowercase though */
748 #define SC(s) (s), (sizeof(s) / sizeof(s[0]) - 1U)
749 #define SZ(s) (s), strlen(s)
708750
709751 #if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
710752 #define strdupx(d,s,ap) do { \
957999 /* note that i MUST NOT be zero */
9581000 #define LRETURN 1 /* return statement */
9591001 #define LEXIT 2 /* exit statement */
960 #define LERROR 3 /* errorf() called */
1002 #define LERROR 3 /* kerrf() called */
9611003 #define LERREXT 4 /* set -e caused */
9621004 #define LINTR 5 /* ^C noticed */
9631005 #define LBREAK 6 /* break statement */
10001042 #define kshppid rndsetupstate.kshppid_v
10011043
10021044 /* option processing */
1003 #define OF_CMDLINE 0x01 /* command line */
1004 #define OF_SET 0x02 /* set builtin */
1005 #define OF_SPECIAL 0x04 /* a special variable changing */
1006 #define OF_INTERNAL 0x08 /* set internally by shell */
1007 #define OF_FIRSTTIME 0x10 /* as early as possible, once */
1008 #define OF_ANY (OF_CMDLINE | OF_SET | OF_SPECIAL | OF_INTERNAL)
1045 #define OF_CMDLINE 0x01U /* command line */
1046 #define OF_SET 0x02U /* set builtin */
1047 #define OF_INTERNAL 0x04U /* set internally by shell */
1048 #define OF_FIRSTTIME 0x08U /* as early as possible, once */
1049 #define OF_ANY (OF_CMDLINE | OF_SET | OF_INTERNAL)
10091050
10101051 /* null value for variable; comparison pointer for unset */
10111052 EXTERN char null[] E_INIT("");
10301071
10311072 #ifndef HAVE_STRING_POOLING /* helpers for pooled strings */
10321073 #define T1space (Treal_sp2 + 5)
1033 #define Tcolsp (Tf_sD_ + 2)
10341074 #define TC_IFSWS (TinitIFS + 4)
10351075 EXTERN const char TinitIFS[] E_INIT("IFS= \t\n");
1036 EXTERN const char TFCEDIT_dollaru[] E_INIT("${FCEDIT:-/bin/ed} $_");
1076 EXTERN const char TFCEDIT_dollaru[] E_INIT("${FCEDIT:-/bin/ed} \"$_\"");
10371077 #define Tspdollaru (TFCEDIT_dollaru + 18)
10381078 EXTERN const char Tsgdot[] E_INIT("*=.");
10391079 EXTERN const char Taugo[] E_INIT("augo");
10451085 EXTERN const char Tbg[] E_INIT("bg");
10461086 EXTERN const char Tbad_buf[] E_INIT("%s: buf %zX len %zd");
10471087 EXTERN const char Tbad_flags[] E_INIT("%s: flags 0x%08X");
1048 EXTERN const char Tbad_sig_ss[] E_INIT("%s: bad signal '%s'");
1049 #define Tbad_sig_s (Tbad_sig_ss + 4)
1088 EXTERN const char Tbad_sig[] E_INIT("bad signal");
10501089 EXTERN const char Tsgbreak[] E_INIT("*=break");
10511090 #define Tbreak (Tsgbreak + 2)
10521091 EXTERN const char T__builtin[] E_INIT("-\\builtin");
10531092 #define T_builtin (T__builtin + 1)
10541093 #define Tbuiltin (T__builtin + 2)
1055 EXTERN const char Toomem[] E_INIT("can't allocate %zu data bytes");
10561094 EXTERN const char Tcant_cd[] E_INIT("restricted shell - can't cd");
10571095 EXTERN const char Tcant_filesub[] E_INIT("can't open $(<...) file");
10581096 #define Tcd (Tcant_cd + 25)
1059 EXTERN const char Tchvt2[] E_INIT("chvt: %s: %s");
1060 EXTERN const char Tchvt_failed[] E_INIT("chvt: %s failed");
1061 EXTERN const char Tcloexec_failed[] E_INIT("failed to %s close-on-exec flag for fd#%d: %s");
1097 EXTERN const char Tcloexec_failed[] E_INIT("failed to %s close-on-exec flag for fd#%d");
10621098 #define T_command (T_funny_command + 9)
10631099 #define Tcommand (T_funny_command + 10)
10641100 EXTERN const char Tsgcontinue[] E_INIT("*=continue");
10651101 #define Tcontinue (Tsgcontinue + 2)
10661102 EXTERN const char Tcreate[] E_INIT("create");
1103 EXTERN const char TchvtDone[] E_INIT("chvt: Done (%d)");
1104 #define TDone (TchvtDone + 6)
10671105 EXTERN const char TELIF_unexpected[] E_INIT("TELIF unexpected");
10681106 EXTERN const char TEXECSHELL[] E_INIT("EXECSHELL");
10691107 EXTERN const char TENV[] E_INIT("ENV");
10701108 EXTERN const char Tdsgexport[] E_INIT("^*=export");
10711109 #define Texport (Tdsgexport + 3)
1072 #ifdef __OS2__
1073 EXTERN const char Textproc[] E_INIT("extproc");
1074 #endif
10751110 EXTERN const char Tfalse[] E_INIT("false");
10761111 EXTERN const char Tfg[] E_INIT("fg");
10771112 EXTERN const char Tfg_badsubst[] E_INIT("fileglob: bad substitution");
10781113 #define Tfile (Tcant_filesub + 19)
1114 EXTERN const char Tyankfirst[] E_INIT("\nyank something first");
1115 #define Tfirst (Tyankfirst + 16)
10791116 EXTERN const char TFPATH[] E_INIT("FPATH");
10801117 EXTERN const char T_function[] E_INIT(" function");
10811118 #define Tfunction (T_function + 1)
10821119 EXTERN const char T_funny_command[] E_INIT("funny $()-command");
10831120 EXTERN const char Tgetopts[] E_INIT("getopts");
1121 #define Tgetrusage (Ttime_getrusage + 6)
1122 EXTERN const char Ttime_getrusage[] E_INIT("time: getrusage");
10841123 #define Thistory (Tnot_in_history + 7)
10851124 EXTERN const char Tintovfl[] E_INIT("integer overflow %zu %c %zu prevented");
10861125 EXTERN const char Tinvname[] E_INIT("%s: invalid %s name");
10881127 EXTERN const char Tjob_not_started[] E_INIT("job not started");
10891128 EXTERN const char Tmksh[] E_INIT("mksh");
10901129 #define Tname (Tinvname + 15)
1130 EXTERN const char Tnil[] E_INIT("(null)");
10911131 EXTERN const char Tno_args[] E_INIT("missing argument");
10921132 EXTERN const char Tno_OLDPWD[] E_INIT("no OLDPWD");
1093 EXTERN const char Tnot_ident[] E_INIT("is not an identifier");
1133 EXTERN const char Tnot_ident[] E_INIT("not an identifier");
10941134 EXTERN const char Tnot_in_history[] E_INIT("not in history");
1095 EXTERN const char Tnot_found_s[] E_INIT("%s not found");
1096 #define Tnot_found (Tnot_found_s + 3)
1135 #define Tnot_found (Tinacc_not_found + 16)
1136 #define Tsp_not_found (Tinacc_not_found + 15)
1137 EXTERN const char Tinacc_not_found[] E_INIT("inaccessible or not found");
10971138 #define Tnot_started (Tjob_not_started + 4)
10981139 #define TOLDPWD (Tno_OLDPWD + 3)
10991140 EXTERN const char Topen[] E_INIT("open");
11081149 #define Tread (Tshf_read + 4)
11091150 EXTERN const char Tdsgreadonly[] E_INIT("^*=readonly");
11101151 #define Treadonly (Tdsgreadonly + 3)
1152 EXTERN const char Tread_only[] E_INIT("read-only");
11111153 EXTERN const char Tredirection_dup[] E_INIT("can't finish (dup) redirection");
11121154 #define Tredirection (Tredirection_dup + 19)
11131155 #define Treal_sp1 (Treal_sp2 + 1)
11151157 EXTERN const char TREPLY[] E_INIT("REPLY");
11161158 EXTERN const char Treq_arg[] E_INIT("requires an argument");
11171159 EXTERN const char Tselect[] E_INIT("select");
1118 #define Tset (Tf_parm + 18)
1160 #define Tset (Tf_parm + 14)
11191161 #define Tset_po (T_set_po + 1)
11201162 EXTERN const char T_set_po[] E_INIT(" set +o");
11211163 EXTERN const char Tsghset[] E_INIT("*=#set");
11311173 EXTERN const char Tsynerr[] E_INIT("syntax error");
11321174 EXTERN const char Ttime[] E_INIT("time");
11331175 EXTERN const char Ttoo_many_args[] E_INIT("too many arguments");
1134 EXTERN const char Ttoo_many_files[] E_INIT("too many open files (%d -> %d): %s");
1176 EXTERN const char Ttoo_many_files[] E_INIT("too many open files (%d -> %d)");
11351177 EXTERN const char Ttrue[] E_INIT("true");
11361178 EXTERN const char Tdgtypeset[] E_INIT("^=typeset");
11371179 #define Ttypeset (Tdgtypeset + 2)
11481190 EXTERN const char Tf__S[] E_INIT(" %S");
11491191 #define Tf__d (Tunexpected_type + 22)
11501192 #define Tf__sN (Tf_s_s_sN + 5)
1193 EXTERN const char Tf_s_T[] E_INIT("%s %T");
11511194 #define Tf_T (Tf_s_T + 3)
11521195 EXTERN const char Tf_dN[] E_INIT("%d\n");
11531196 EXTERN const char Tf_s_[] E_INIT("%s ");
1154 EXTERN const char Tf_s_T[] E_INIT("%s %T");
11551197 EXTERN const char Tf_s_s_sN[] E_INIT("%s %s %s\n");
1156 #define Tf_s_s (Tf_sD_s_s + 4)
11571198 #define Tf__s_s (Tf_sD_s_s + 3)
1158 #define Tf_s_sD_s (Tf_cant_ss_s + 6)
1159 #define Tf_optdcs (Tf_optfoo + 4)
1160 EXTERN const char Tf_optfoo[] E_INIT("%s%s-%c: %s");
1161 EXTERN const char Tf_sD_[] E_INIT("%s: ");
1162 EXTERN const char Tf_parm[] E_INIT("%s: parameter not set");
1163 EXTERN const char Tf_coproc[] E_INIT("-p: %s");
1199 EXTERN const char Tf_s_sD_s[] E_INIT("%s %s: %s");
1200 EXTERN const char Tf_parm[] E_INIT("parameter not set");
11641201 EXTERN const char Tf_cant_s[] E_INIT("%s: can't %s");
1165 EXTERN const char Tf_cant_ss_s[] E_INIT("can't %s %s: %s");
11661202 EXTERN const char Tf_heredoc[] E_INIT("here document '%s' unclosed");
1167 #if HAVE_MKNOD
1168 EXTERN const char Tf_nonnum[] E_INIT("non-numeric %s %s '%s'");
1169 #endif
11701203 EXTERN const char Tf_S_[] E_INIT("%S ");
11711204 #define Tf_S (Tf__S + 1)
1172 #define Tf_lu (Tf_toolarge + 17)
1173 EXTERN const char Tf_toolarge[] E_INIT("%s %s too large: %lu");
1174 EXTERN const char Tf_ldfailed[] E_INIT("%s %s(%d, %ld) failed: %s");
1205 EXTERN const char Tf_sSQlu[] E_INIT("%s[%lu]");
1206 #define Tf_SQlu (Tf_sSQlu + 2)
1207 #define Tf_lu (Tf_toolarge + 14)
1208 EXTERN const char Tf_toolarge[] E_INIT("%s too large: %lu");
1209 EXTERN const char Tf_ldfailed[] E_INIT("%s tcsetpgrp(%d, %ld)");
11751210 EXTERN const char Tf_toomany[] E_INIT("too many %ss");
11761211 EXTERN const char Tf_sd[] E_INIT("%s %d");
1177 #define Tf_s (Tcloexec_failed + 43)
1212 #define Tf_s (Tf_temp + 24)
11781213 EXTERN const char Tft_end[] E_INIT("%;");
1179 EXTERN const char Tft_R[] E_INIT("%R");
1180 #define Tf_d (Tunexpected_type + 23)
1214 #define Tft_R (Tft_s_R + 3)
1215 EXTERN const char Tft_s_R[] E_INIT("%s %R");
1216 #define Tf_d (Tcloexec_failed + 39)
11811217 EXTERN const char Tf_sD_s_qs[] E_INIT("%s: %s '%s'");
1182 EXTERN const char Tf_ro[] E_INIT("read-only: %s");
1183 EXTERN const char Tf_temp[] E_INIT("can't %s temporary file %s: %s");
1184 EXTERN const char Tf_ssfaileds[] E_INIT("%s: %s failed: %s");
1185 EXTERN const char Tf_sD_sD_s[] E_INIT("%s: %s: %s");
1218 EXTERN const char Tf_temp[] E_INIT("can't %s temporary file %s");
1219 EXTERN const char Tf_ssfailed[] E_INIT("%s: %s failed");
11861220 EXTERN const char Tf__c_[] E_INIT("-%c ");
11871221 EXTERN const char Tf_sD_s_s[] E_INIT("%s: %s %s");
11881222 #define Tf_sN (Tf_s_s_sN + 6)
1189 #define Tf_sD_s (Tf_temp + 24)
1190 EXTERN const char T_devtty[] E_INIT("/dev/tty");
1223 #define Tf_sD_s (Tf_s_sD_s + 3)
11911224 #else /* helpers for string pooling */
11921225 #define T1space " "
1193 #define Tcolsp ": "
11941226 #define TC_IFSWS " \t\n"
11951227 #define TinitIFS "IFS= \t\n"
1196 #define TFCEDIT_dollaru "${FCEDIT:-/bin/ed} $_"
1197 #define Tspdollaru " $_"
1228 #define TFCEDIT_dollaru "${FCEDIT:-/bin/ed} \"$_\""
1229 #define Tspdollaru " \"$_\""
11981230 #define Tsgdot "*=."
11991231 #define Taugo "augo"
12001232 #define Tbracket "["
12051237 #define Tbg "bg"
12061238 #define Tbad_buf "%s: buf %zX len %zd"
12071239 #define Tbad_flags "%s: flags 0x%08X"
1208 #define Tbad_sig_ss "%s: bad signal '%s'"
1209 #define Tbad_sig_s "bad signal '%s'"
1240 #define Tbad_sig "bad signal"
12101241 #define Tsgbreak "*=break"
12111242 #define Tbreak "break"
12121243 #define T__builtin "-\\builtin"
12131244 #define T_builtin "\\builtin"
12141245 #define Tbuiltin "builtin"
1215 #define Toomem "can't allocate %zu data bytes"
12161246 #define Tcant_cd "restricted shell - can't cd"
12171247 #define Tcant_filesub "can't open $(<...) file"
12181248 #define Tcd "cd"
1219 #define Tchvt2 "chvt: %s: %s"
1220 #define Tchvt_failed "chvt: %s failed"
1221 #define Tcloexec_failed "failed to %s close-on-exec flag for fd#%d: %s"
1249 #define Tcloexec_failed "failed to %s close-on-exec flag for fd#%d"
12221250 #define T_command "-command"
12231251 #define Tcommand "command"
12241252 #define Tsgcontinue "*=continue"
12251253 #define Tcontinue "continue"
12261254 #define Tcreate "create"
1255 #define TchvtDone "chvt: Done (%d)"
1256 #define TDone "Done (%d)"
12271257 #define TELIF_unexpected "TELIF unexpected"
12281258 #define TEXECSHELL "EXECSHELL"
12291259 #define TENV "ENV"
12301260 #define Tdsgexport "^*=export"
12311261 #define Texport "export"
1232 #ifdef __OS2__
1233 #define Textproc "extproc"
1234 #endif
12351262 #define Tfalse "false"
12361263 #define Tfg "fg"
12371264 #define Tfg_badsubst "fileglob: bad substitution"
12381265 #define Tfile "file"
1266 #define Tyankfirst "\nyank something first"
1267 #define Tfirst "first"
12391268 #define TFPATH "FPATH"
12401269 #define T_function " function"
12411270 #define Tfunction "function"
12421271 #define T_funny_command "funny $()-command"
12431272 #define Tgetopts "getopts"
1273 #define Tgetrusage "getrusage"
1274 #define Ttime_getrusage "time: getrusage"
12441275 #define Thistory "history"
12451276 #define Tintovfl "integer overflow %zu %c %zu prevented"
12461277 #define Tinvname "%s: invalid %s name"
12481279 #define Tjob_not_started "job not started"
12491280 #define Tmksh "mksh"
12501281 #define Tname "name"
1282 #define Tnil "(null)"
12511283 #define Tno_args "missing argument"
12521284 #define Tno_OLDPWD "no OLDPWD"
1253 #define Tnot_ident "is not an identifier"
1285 #define Tnot_ident "not an identifier"
12541286 #define Tnot_in_history "not in history"
1255 #define Tnot_found_s "%s not found"
12561287 #define Tnot_found "not found"
1288 #define Tsp_not_found " not found"
1289 #define Tinacc_not_found "inaccessible or not found"
12571290 #define Tnot_started "not started"
12581291 #define TOLDPWD "OLDPWD"
12591292 #define Topen "open"
12681301 #define Tread "read"
12691302 #define Tdsgreadonly "^*=readonly"
12701303 #define Treadonly "readonly"
1304 #define Tread_only "read-only"
12711305 #define Tredirection_dup "can't finish (dup) redirection"
12721306 #define Tredirection "redirection"
12731307 #define Treal_sp1 "real "
12911325 #define Tsynerr "syntax error"
12921326 #define Ttime "time"
12931327 #define Ttoo_many_args "too many arguments"
1294 #define Ttoo_many_files "too many open files (%d -> %d): %s"
1328 #define Ttoo_many_files "too many open files (%d -> %d)"
12951329 #define Ttrue "true"
12961330 #define Tdgtypeset "^=typeset"
12971331 #define Ttypeset "typeset"
13081342 #define Tf__S " %S"
13091343 #define Tf__d " %d"
13101344 #define Tf__sN " %s\n"
1345 #define Tf_s_T "%s %T"
13111346 #define Tf_T "%T"
13121347 #define Tf_dN "%d\n"
13131348 #define Tf_s_ "%s "
1314 #define Tf_s_T "%s %T"
13151349 #define Tf_s_s_sN "%s %s %s\n"
1316 #define Tf_s_s "%s %s"
13171350 #define Tf__s_s " %s %s"
13181351 #define Tf_s_sD_s "%s %s: %s"
1319 #define Tf_optdcs "-%c: %s"
1320 #define Tf_optfoo "%s%s-%c: %s"
1321 #define Tf_sD_ "%s: "
1322 #define Tf_parm "%s: parameter not set"
1323 #define Tf_coproc "-p: %s"
1352 #define Tf_parm "parameter not set"
13241353 #define Tf_cant_s "%s: can't %s"
1325 #define Tf_cant_ss_s "can't %s %s: %s"
13261354 #define Tf_heredoc "here document '%s' unclosed"
1327 #if HAVE_MKNOD
1328 #define Tf_nonnum "non-numeric %s %s '%s'"
1329 #endif
13301355 #define Tf_S_ "%S "
13311356 #define Tf_S "%S"
1357 #define Tf_sSQlu "%s[%lu]"
1358 #define Tf_SQlu "[%lu]"
13321359 #define Tf_lu "%lu"
1333 #define Tf_toolarge "%s %s too large: %lu"
1334 #define Tf_ldfailed "%s %s(%d, %ld) failed: %s"
1360 #define Tf_toolarge "%s too large: %lu"
1361 #define Tf_ldfailed "%s tcsetpgrp(%d, %ld)"
13351362 #define Tf_toomany "too many %ss"
13361363 #define Tf_sd "%s %d"
13371364 #define Tf_s "%s"
13381365 #define Tft_end "%;"
13391366 #define Tft_R "%R"
1367 #define Tft_s_R "%s %R"
13401368 #define Tf_d "%d"
13411369 #define Tf_sD_s_qs "%s: %s '%s'"
1342 #define Tf_ro "read-only: %s"
1343 #define Tf_temp "can't %s temporary file %s: %s"
1344 #define Tf_ssfaileds "%s: %s failed: %s"
1345 #define Tf_sD_sD_s "%s: %s: %s"
1370 #define Tf_temp "can't %s temporary file %s"
1371 #define Tf_ssfailed "%s: %s failed"
13461372 #define Tf__c_ "-%c "
13471373 #define Tf_sD_s_s "%s: %s %s"
13481374 #define Tf_sN "%s\n"
13491375 #define Tf_sD_s "%s: %s"
1350 #define T_devtty "/dev/tty"
13511376 #endif /* end of string pooling */
1377
1378 #ifdef __OS2__
1379 EXTERN const char Textproc[] E_INIT("extproc");
1380 #endif
13521381
13531382 typedef kby Temp_type;
13541383 /* expanded heredoc */
13791408 #ifdef DF
13801409 #define shl_dbg (&shf_iob[3]) /* for DF() */
13811410 #endif
1411 EXTERN bool initio_done; /* shl_*out:true/1, shl_dbg:2 */
13821412 EXTERN bool shl_stdout_ok;
13831413
13841414 /*
14891519 /* out of space, but one for *@ would make sense, possibly others */
14901520
14911521 /* compile-time initialised, ASCII only */
1492 extern const uint32_t tpl_ctypes[128];
1522 extern const kui tpl_ctypes[128];
14931523 /* run-time, contains C_IFS as well, full 2⁸ octet range */
1494 EXTERN uint32_t ksh_ctypes[256];
1524 EXTERN kui ksh_ctypes[256];
14951525 /* first octet of $IFS, for concatenating "$*" */
14961526 EXTERN char ifs0;
14971527
15881618 !defined(__INTEL_COMPILER) && !defined(__SUNPRO_C)
15891619 extern kui eek_ord;
15901620 #define ORD(c) ((size_t)(c) > 0xFF ? eek_ord : KBI(c))
1591 #define ord(c) __builtin_choose_expr( \
1592 __builtin_types_compatible_p(__typeof__(c), char) || \
1593 __builtin_types_compatible_p(__typeof__(c), unsigned char), \
1594 KBI(c), ({ \
1595 size_t ord_c = (c); \
1596 \
1597 if (ord_c > (size_t)0xFFU) \
1598 internal_errorf("%s:%d:ord(%zX)", \
1599 __FILE__, __LINE__, ord_c); \
1600 (KBI(ord_c)); \
1621 #define ord(c) __builtin_choose_expr( \
1622 __builtin_types_compatible_p(__typeof__(c), char) || \
1623 __builtin_types_compatible_p(__typeof__(c), unsigned char), \
1624 KBI(c), ({ \
1625 size_t ord_c = (c); \
1626 \
1627 if (ord_c > (size_t)0xFFU) \
1628 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO, \
1629 "%s:%d:ord(%zX)", __FILE__, __LINE__, ord_c); \
1630 (KBI(ord_c)); \
16011631 }))
16021632 #else
16031633 #define ord(c) KBI(c)
16141644 #define rtt2asc(c) ebcdic_rtt_toascii[KBY(c)]
16151645 #define asc2rtt(c) ebcdic_rtt_fromascii[KBY(c)]
16161646 /* case-independent char comparison */
1617 #define ksh_eq(c,u,l) (ord(c) == ord(u) || ord(c) == ord(l))
1618 #else
1647 #define isCh(c,u,l) (ord(c) == ord(u) || ord(c) == ord(l))
1648 #else
1649 /* POSIX locale ordering */
16191650 #define asciibetical(c) ord(c)
1651 /* if inspecting numerical values (mapping on EBCDIC) */
16201652 #define rtt2asc(c) KBY(c)
16211653 #define asc2rtt(c) KBY(c)
1622 #define ksh_eq(c,u,l) ((ord(c) | 0x20U) == ord(l))
1623 #endif
1654 /* case-independent char comparison */
1655 #define isCh(c,u,l) ((ord(c) | 0x20U) == ord(l))
1656 #endif
1657 /* vs case-sensitive char comparison */
1658 #define isch(c,t) (ord(c) == ORD(t))
16241659 /* control character foo */
16251660 #ifdef MKSH_EBCDIC
16261661 #define ksh_isctrl(c) (ord(c) < 0x40U || ord(c) == 0xFFU)
16531688 /* Argument parsing for built-in commands and getopts command */
16541689
16551690 /* Values for Getopt.flags */
1656 #define GF_ERROR BIT(0) /* call errorf() if there is an error */
1691 #define GF_ERROR BIT(0) /* KWF_BIERR if there is an error */
16571692 #define GF_PLUSOPT BIT(1) /* allow +c as an option */
16581693 #define GF_NONAME BIT(2) /* don't print argv[0] in errors */
16591694
16811716
16821717 /* This for co-processes */
16831718
1684 /* something that won't (realisticly) wrap */
1685 typedef int Coproc_id;
1719 /* something that won't (realistically) wrap */
1720 typedef unsigned int Coproc_id;
16861721
16871722 struct coproc {
16881723 void *job; /* 0 or job of co-process using input pipe */
18261861 const char *fpath; /* temporary path to undef function */
18271862 } u;
18281863 union {
1864 k32 hval; /* hash(name) */
1865 k32 index; /* index for an array */
1866 } ua;
1867 union {
18291868 int field; /* field with for -L/-R/-Z */
18301869 int errnov; /* CEXEC/CTALIAS */
18311870 } u2;
1832 union {
1833 uint32_t hval; /* hash(name) */
1834 uint32_t index; /* index for an array */
1835 } ua;
18361871 /*
18371872 * command type (see below), base (if INTEGER),
18381873 * offset from val.s of value (if EXPORT)
18391874 */
18401875 int type;
18411876 /* flags (see below) */
1842 uint32_t flag;
1877 kui flag;
18431878
18441879 /* actually longer: name (variable length) */
18451880 char name[4];
24372472 #define notok2mul(max,val,c) (((val) != 0) && ((c) != 0) && \
24382473 (((max) / (c)) < (val)))
24392474 #define notok2add(max,val,c) ((val) > ((max) - (c)))
2440 #define notoktomul(val,cnst) notok2mul(SIZE_MAX, (val), (cnst))
2441 #define notoktoadd(val,cnst) notok2add(SIZE_MAX, (val), (cnst))
2475 #define notoktomul(val,cnst) notok2mul(mksh_MAXSZ, (val), (cnst))
2476 #define notoktoadd(val,cnst) notok2add(mksh_MAXSZ, (val), (cnst))
24422477 #define checkoktoadd(val,cnst) do { \
24432478 if (notoktoadd((val), (cnst))) \
2444 internal_errorf(Tintovfl, (size_t)(val), \
2445 '+', (size_t)(cnst)); \
2479 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO, \
2480 Tintovfl, (size_t)(val), '+', (size_t)(cnst)); \
24462481 } while (/* CONSTCOND */ 0)
24472482
24482483 /* lalloc.c */
24842519 int execute(struct op * volatile, volatile int, volatile int * volatile);
24852520 int c_builtin(const char **);
24862521 struct tbl *get_builtin(const char *);
2487 struct tbl *findfunc(const char *, uint32_t, bool);
2522 struct tbl *findfunc(const char *, k32, bool);
24882523 int define(const char *, struct op *);
24892524 const char *builtin(const char *, int (*)(const char **));
24902525 struct tbl *findcom(const char *, int);
26292664 int j_stopped_running(void);
26302665 /* lex.c */
26312666 int yylex(int);
2632 void yyerror(const char *, ...)
2633 MKSH_A_NORETURN
2634 MKSH_A_FORMAT(__printf__, 1, 2);
26352667 Source *pushs(int, Area *);
26362668 void set_prompt(int, Source *);
26372669 int pprompt(const char *, int);
26382670 /* main.c */
2671 kby kshname_islogin(const char **);
26392672 int include(const char *, int, const char **, bool);
26402673 int command(const char *, int);
26412674 int shell(Source * volatile, volatile int);
26452678 void quitenv(struct shf *);
26462679 void cleanup_parents_env(void);
26472680 void cleanup_proc_env(void);
2648 void errorf(const char *, ...)
2649 MKSH_A_NORETURN
2650 MKSH_A_FORMAT(__printf__, 1, 2);
2651 void errorfx(int, const char *, ...)
2652 MKSH_A_NORETURN
2653 MKSH_A_FORMAT(__printf__, 2, 3);
2654 void warningf(bool, const char *, ...)
2655 MKSH_A_FORMAT(__printf__, 2, 3);
2681 /* old {{{ */
26562682 void bi_errorf(const char *, ...)
26572683 MKSH_A_FORMAT(__printf__, 1, 2);
2658 void maybe_errorf(int *, int, const char *, ...)
2659 MKSH_A_FORMAT(__printf__, 3, 4);
2660 #define errorfz() errorf(NULL)
2661 #define errorfxz(rc) errorfx((rc), NULL)
2662 #define bi_errorfz() bi_errorf(NULL)
2663 void internal_errorf(const char *, ...)
2664 MKSH_A_NORETURN
2665 MKSH_A_FORMAT(__printf__, 1, 2);
2666 void internal_warningf(const char *, ...)
2667 MKSH_A_FORMAT(__printf__, 1, 2);
2668 void error_prefix(bool);
2684 /* old }}} */
26692685 void shellf(const char *, ...)
26702686 MKSH_A_FORMAT(__printf__, 1, 2);
26712687 void shprintf(const char *, ...)
26872703 void coproc_cleanup(int);
26882704 struct temp *maketemp(Area *, Temp_type, struct temp **);
26892705 void ktinit(Area *, struct table *, kby);
2690 struct tbl *ktscan(struct table *, const char *, uint32_t, struct tbl ***);
2706 struct tbl *ktscan(struct table *, const char *, k32, struct tbl ***);
26912707 /* table, name (key) to search for, hash(n) */
26922708 #define ktsearch(tp,s,h) ktscan((tp), (s), (h), NULL)
2693 struct tbl *ktenter(struct table *, const char *, uint32_t);
2709 struct tbl *ktenter(struct table *, const char *, k32);
26942710 #define ktdelete(p) do { p->flag = 0; } while (/* CONSTCOND */ 0)
26952711 void ktwalk(struct tstate *, struct table *);
26962712 struct tbl *ktnext(struct tstate *);
27022718 /* misc.c */
27032719 size_t option(const char *) MKSH_A_PURE;
27042720 char *getoptions(void);
2705 void change_flag(enum sh_flag, int, bool);
2721 void change_flag(enum sh_flag, unsigned int, bool);
27062722 void change_xtrace(unsigned char, bool);
2707 int parse_args(const char **, int, bool *);
2723 int parse_args(const char **, unsigned int, bool *);
27082724 int getn(const char *, int *);
27092725 int getpn(const char **, int *);
27102726 int gmatchx(const char *, const char *, bool);
27112727 bool has_globbing(const char *) MKSH_A_PURE;
27122728 int ascstrcmp(const void *, const void *) MKSH_A_PURE;
27132729 int ascpstrcmp(const void *, const void *) MKSH_A_PURE;
2730 void ksh_getopt_opterr(int, const char *, const char *);
27142731 void ksh_getopt_reset(Getopt *, int);
27152732 int ksh_getopt(const char **, Getopt *, const char *);
27162733 void print_value_quoted(struct shf *, const char *);
27662783 #define shf_putc shf_putc_i
27672784 #endif
27682785 int shf_putchar(int, struct shf *);
2769 ssize_t shf_puts(const char *, struct shf *);
2786 #ifdef MKSH_SHF_NO_INLINE
2787 #define shf_puts shf_putsv
2788 #else
2789 #define shf_puts(s,shf) ((s) ? shf_write((s), strlen(s), (shf)) : (ssize_t)-1)
2790 #endif
2791 ssize_t shf_putsv(const char *, struct shf *);
27702792 ssize_t shf_write(const char *, ssize_t, struct shf *);
27712793 ssize_t shf_fprintf(struct shf *, const char *, ...)
27722794 MKSH_A_FORMAT(__printf__, 2, 3);
27762798 char *shf_smprintf(const char *, ...)
27772799 MKSH_A_FORMAT(__printf__, 1, 2);
27782800 ssize_t shf_vfprintf(struct shf *, const char *, va_list)
2779 MKSH_A_FORMAT(__printf__, 2, 0);
2801 #ifdef MKSH_SHF_VFPRINTF_NO_GCC_FORMAT_ATTRIBUTE
2802 #define shf_vfprintf poisoned_shf_vfprintf
2803 #else
2804 MKSH_A_FORMAT(__printf__, 2, 0)
2805 #endif
2806 ;
27802807 void set_ifs(const char *);
2808 /* flags for numfmt below */
2809 #define FL_SGN 0x0000 /* signed decimal */
2810 #define FL_DEC 0x0001 /* unsigned decimal */
2811 #define FL_OCT 0x0002 /* unsigned octal */
2812 #define FL_HEX 0x0003 /* unsigned sedecimal */
2813 #define FM_TYPE 0x0003 /* mask: decimal/octal/hex */
2814 #define FL_UCASE 0x0004 /* use upper-case digits beyond 9 */
2815 #define FL_UPPER 0x000C /* use upper-case digits beyond 9 and 'X' */
2816 #define FL_PLUS 0x0010 /* FL_SGN force sign output */
2817 #define FL_BLANK 0x0020 /* FL_SGN output space unless sign present */
2818 #define FL_HASH 0x0040 /* FL_OCT force 0; FL_HEX force 0x/0X */
2819 /* internal flags to numfmt / shf_vfprintf */
2820 #define FL_NEG 0x0080 /* negative number, negated */
2821 #define FL_SHORT 0x0100 /* ‘h’ seen */
2822 #define FL_LONG 0x0200 /* ‘l’ seen */
2823 #define FL_SIZET 0x0400 /* ‘z’ seen */
2824 #define FM_SIZES 0x0700 /* mask: short/long/sizet */
2825 #define FL_NUMBER 0x0800 /* %[douxefg] a number was formatted */
2826 #define FL_RIGHT 0x1000 /* ‘-’ seen: right-pad, left-align */
2827 #define FL_ZERO 0x2000 /* ‘0’ seen: pad with leading zeros */
2828 #define FL_DOT 0x4000 /* ‘.’ seen: printf(3) precision specified */
2829 /*
2830 * %#o produces the longest output: '0' + w/3 + NUL
2831 * %#x produces '0x' + w/4 + NUL which is at least as long (w=8)
2832 * %+d produces sign + w/log₂(10) + NUL
2833 */
2834 #define NUMBUFSZ (1U + (mbiTYPE_UBITS(kul) + 2U) / 3U + /* NUL */ 1U)
2835 #define NUMBUFLEN(base,result) ((base) + NUMBUFSZ - (result) - 1U)
2836 char *kulfmt(kul number, kui flags, char *numbuf)
2837 MKSH_A_BOUNDED(__minbytes__, 3, NUMBUFSZ);
2838 char *kslfmt(ksl number, kui flags, char *numbuf)
2839 MKSH_A_BOUNDED(__minbytes__, 3, NUMBUFSZ);
27812840 /* syn.c */
27822841 void initkeywords(void);
27832842 struct op *compile(Source *, bool);
27842843 bool parse_usec(const char *, struct timeval *);
27852844 char *yyrecursive(int);
27862845 void yyrecursive_pop(bool);
2846 void yyerror(const char *, ...)
2847 MKSH_A_NORETURN
2848 MKSH_A_FORMAT(__printf__, 1, 2);
2849 /* shell error reporting */
2850 void bi_unwind(int);
2851 bool error_prefix(bool);
2852 #define KWF_BIERR (KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE | \
2853 KWF_BUILTIN | KWF_BIUNWIND)
2854 #define KWF_ERR(n) ((((unsigned int)(n)) & KWF_EXSTAT) | KWF_ERROR)
2855 #define KWF_EXSTAT 0x0000FFU /* (mask) errorlevel to use */
2856 #define KWF_VERRNO 0x000100U /* int vararg: use ipv errno */
2857 #define KWF_INTERNAL 0x000200U /* internal {error,warning} */
2858 #define KWF_WARNING 0x000000U /* (default) warning */
2859 #define KWF_ERROR 0x000400U /* error + consequences */
2860 #define KWF_PREFIX 0x000800U /* run error_prefix() */
2861 #define KWF_FILELINE 0x001000U /* error_prefix arg:=true */
2862 #define KWF_BUILTIN 0x002000U /* possibly show builtin_argv0 */
2863 #define KWF_MSGMASK 0x00C000U /* (mask) message to display */
2864 #define KWF_MSGFMT 0x000000U /* (default) printf-style variadic */
2865 #define KWF_ONEMSG 0x004000U /* only one string to show */
2866 #define KWF_TWOMSG 0x008000U /* two strings to show with colon */
2867 #define KWF_THREEMSG 0x00C000U /* three strings to colonise */
2868 #define KWF_NOERRNO 0x010000U /* omit showing strerror */
2869 #define KWF_BIUNWIND 0x020000U /* let kwarnf* tailcall bi_unwind(0) */
2870 void kwarnf(unsigned int, ...);
2871 #ifndef MKSH_SMALL
2872 void kwarnf0(unsigned int, const char *, ...)
2873 MKSH_A_FORMAT(__printf__, 2, 3);
2874 void kwarnf1(unsigned int, int, const char *, ...)
2875 MKSH_A_FORMAT(__printf__, 3, 4);
2876 #else
2877 #define kwarnf0 kwarnf /* with KWF_MSGFMT and !KWF_VERRNO */
2878 #define kwarnf1 kwarnf /* with KWF_MSGFMT and KWF_VERRNO */
2879 #endif
2880 void kerrf(unsigned int, ...)
2881 MKSH_A_NORETURN;
2882 #ifndef MKSH_SMALL
2883 void kerrf0(unsigned int, const char *, ...)
2884 MKSH_A_NORETURN
2885 MKSH_A_FORMAT(__printf__, 2, 3);
2886 void kerrf1(unsigned int, int, const char *, ...)
2887 MKSH_A_NORETURN
2888 MKSH_A_FORMAT(__printf__, 3, 4);
2889 #else
2890 #define kerrf0 kerrf /* with KWF_MSGFMT and !KWF_VERRNO */
2891 #define kerrf1 kerrf /* with KWF_MSGFMT and KWF_VERRNO */
2892 #endif
2893 void merrF(int *, unsigned int, ...);
2894 #define merrf(rv,va) do { \
2895 merrF va; \
2896 return (rv); \
2897 } while (/* CONSTCOND */ 0)
27872898 /* tree.c */
27882899 void fptreef(struct shf *, int, const char *, ...);
27892900 char *snptreef(char *, ssize_t, const char *, ...);
28122923 void newblock(void);
28132924 void popblock(void);
28142925 void initvar(void);
2815 struct block *varsearch(struct block *, struct tbl **, const char *, uint32_t);
2926 struct block *varsearch(struct block *, struct tbl **, const char *, k32);
28162927 struct tbl *global(const char *);
28172928 struct tbl *isglobal(const char *, bool);
28182929 struct tbl *local(const char *, bool);
28212932 struct tbl *setint_v(struct tbl *, struct tbl *, bool);
28222933 void setint(struct tbl *, mksh_ari_t);
28232934 void setint_n(struct tbl *, mksh_ari_t, int);
2824 struct tbl *typeset(const char *, uint32_t, uint32_t, int, int);
2935 struct tbl *typeset(const char *, kui, kui, int, int);
28252936 void unset(struct tbl *, int);
28262937 const char *skip_varname(const char *, bool) MKSH_A_PURE;
28272938 const char *skip_wdvarname(const char *, bool) MKSH_A_PURE;
28282939 int is_wdvarname(const char *, bool) MKSH_A_PURE;
28292940 int is_wdvarassign(const char *) MKSH_A_PURE;
2830 struct tbl *arraysearch(struct tbl *, uint32_t);
2941 struct tbl *arraysearch(struct tbl *, k32);
28312942 char **makenv(void);
28322943 void change_winsz(void);
28332944 size_t array_ref_len(const char *) MKSH_A_PURE;
28342945 struct tbl *arraybase(const char *);
28352946 mksh_uari_t set_array(const char *, bool, const char **);
2836 uint32_t hash(const void *) MKSH_A_PURE;
2837 uint32_t chvt_rndsetup(const void *, size_t) MKSH_A_PURE;
2838 mksh_ari_t rndget(void);
2947 k32 hash(const void *) MKSH_A_PURE;
2948 k32 chvt_rndsetup(const void *, size_t) MKSH_A_PURE;
2949 k32 rndget(void);
28392950 void rndset(unsigned long);
2840 void rndpush(const void *);
2951 void rndpush(const void *, size_t);
28412952 void record_match(const char *);
28422953
28432954 enum Test_op {
28812992 extern const struct t_op b_ops[];
28822993 /* ensure order with funcs.c */
28832994 #define Tda (u_ops[0].op_text)
2995 #define Tdc (u_ops[2].op_text)
28842996 #define Tdn (u_ops[12].op_text)
28852997 #define Tdo (u_ops[14].op_text)
2998 #define Tdp (u_ops[15].op_text)
28862999 #define Tdr (u_ops[16].op_text)
28873000 #define Tdu (u_ops[20].op_text) /* "-u" */
28883001 #define Tdx (u_ops[23].op_text)
+385
-278
shf.c less more
11
22 /*-
33 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
4 * 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2021
4 * 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2021,
5 * 2022
56 * mirabilos <m@mirbsd.org>
67 * Copyright (c) 2015
78 * Daniel Richard G. <skunk@iSKUNK.ORG>
2627
2728 #include "sh.h"
2829
29 __RCSID("$MirOS: src/bin/mksh/shf.c,v 1.120 2021/10/01 23:25:35 tg Exp $");
30 __RCSID("$MirOS: src/bin/mksh/shf.c,v 1.128 2022/01/06 22:35:04 tg Exp $");
3031
3132 /* flags to shf_emptybuf() */
3233 #define EB_READSW 0x01 /* about to switch to reading */
9192 }
9293
9394 /* helper function for shf_fdopen and shf_reopen */
95 /* pre-initio() *sflagsp=SHF_WR */
9496 static void
9597 shf_open_hlp(int fd, int *sflagsp, const char *where)
9698 {
120122 }
121123
122124 if (!(sflags & (SHF_RD | SHF_WR)))
123 internal_errorf(Tbad_flags, where, sflags);
125 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
126 Tbad_flags, where, sflags);
124127 }
125128
126129 /* Set up the shf structure for a file descriptor. Doesn't fail. */
130 /* pre-initio() sflags=SHF_WR */
127131 struct shf *
128132 shf_fdopen(int fd, int sflags, struct shf *shf)
129133 {
130134 ssize_t bsize =
131135 /* at most 512 */
132 sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
136 (sflags & SHF_UNBUF) ? ((sflags & SHF_RD) ? 1 : 0) : SHF_BSIZE;
133137
134138 shf_open_hlp(fd, &sflags, "shf_fdopen");
135139 if (shf) {
139143 } else
140144 shf->buf = NULL;
141145 } else {
142 shf = alloc(sizeof(struct shf) + bsize, ATEMP);
143 shf->buf = (unsigned char *)&shf[1];
146 unsigned char *cp;
147
148 cp = alloc(sizeof(struct shf) + bsize, ATEMP);
149 shf = (void *)cp;
150 shf->buf = cp + sizeof(struct shf);
144151 sflags |= SHF_ALLOCS;
145152 }
146153 shf->areap = ATEMP;
154161 shf->errnosv = 0;
155162 shf->bsize = bsize;
156163 if ((sflags & SHF_CLEXEC) && fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
157 internal_warningf(Tcloexec_failed, "set", fd,
158 cstrerror(errno));
164 kwarnf0(KWF_INTERNAL | KWF_WARNING, Tcloexec_failed, "set", fd);
159165 return (shf);
160166 }
161167
169175
170176 shf_open_hlp(fd, &sflags, "shf_reopen");
171177 if (!shf->buf || shf->bsize < bsize)
172 internal_errorf(Tbad_buf, "shf_reopen",
173 (size_t)shf->buf, shf->bsize);
178 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
179 Tbad_buf, "shf_reopen", (size_t)shf->buf, shf->bsize);
174180
175181 /* assumes shf->buf and shf->bsize already set up */
176182 shf->fd = fd;
182188 shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags;
183189 shf->errnosv = 0;
184190 if ((sflags & SHF_CLEXEC) && fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
185 internal_warningf(Tcloexec_failed, "set", fd,
186 cstrerror(errno));
191 kwarnf0(KWF_INTERNAL | KWF_WARNING, Tcloexec_failed, "set", fd);
187192 return (shf);
188193 }
189194
200205 shf_sopen(char *buf, ssize_t bsize, int sflags, struct shf *shf)
201206 {
202207 if (!((sflags & SHF_RD) ^ (sflags & SHF_WR)))
203 internal_errorf(Tbad_flags, "shf_sopen", sflags);
208 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
209 Tbad_flags, "shf_sopen", sflags);
204210
205211 if (!shf) {
206212 shf = alloc(sizeof(struct shf), ATEMP);
243249 shf_scheck_grow(ssize_t n, struct shf *shf)
244250 {
245251 if (!(shf->flags & SHF_WR))
246 internal_errorf(Tbad_flags, "shf_scheck", shf->flags);
252 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
253 Tbad_flags, "shf_scheck", shf->flags);
247254
248255 /* if n < 0 we lose in the macro already */
249256
331338 if (shf->flags & SHF_STRING)
332339 rv = (shf->flags & SHF_WR) ? -1 : 0;
333340 else if (shf->fd < 0)
334 internal_errorf(Tf_sD_s, "shf_flush", "no fd");
341 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_TWOMSG | KWF_NOERRNO,
342 "shf_flush", "no fd");
335343 else if (shf->flags & SHF_ERROR) {
336344 errno = shf->errnosv;
337345 rv = -1;
363371 int ret = 0;
364372
365373 if (!(shf->flags & SHF_STRING) && shf->fd < 0)
366 internal_errorf(Tf_sD_s, "shf_emptybuf", "no fd");
374 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_TWOMSG | KWF_NOERRNO,
375 "shf_emptybuf", "no fd");
367376
368377 if (shf->flags & SHF_ERROR) {
369378 errno = shf->errnosv;
451460 return (0);
452461
453462 if (shf->fd < 0)
454 internal_errorf(Tf_sD_s, "shf_fillbuf", "no fd");
463 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_TWOMSG | KWF_NOERRNO,
464 "shf_fillbuf", "no fd");
455465
456466 if (shf->flags & (SHF_EOF | SHF_ERROR)) {
457467 if (shf->flags & SHF_ERROR)
494504 ssize_t ncopy, orig_bsize = bsize;
495505
496506 if (!(shf->flags & SHF_RD))
497 internal_errorf(Tbad_flags, Tshf_read, shf->flags);
507 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
508 Tbad_flags, Tshf_read, shf->flags);
498509
499510 if (bsize <= 0)
500 internal_errorf(Tbad_buf, Tshf_read, (size_t)buf, bsize);
511 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
512 Tbad_buf, Tshf_read, (size_t)buf, bsize);
501513
502514 while (bsize > 0) {
503515 if (shf->rnleft == 0 &&
531543 char *orig_buf = buf;
532544
533545 if (!(shf->flags & SHF_RD))
534 internal_errorf(Tbad_flags, "shf_getse", shf->flags);
546 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
547 Tbad_flags, "shf_getse", shf->flags);
535548
536549 if (bsize <= 0)
537550 return (NULL);
552565 ncopy = end ? end - shf->rp + 1 : shf->rnleft;
553566 if (ncopy > bsize)
554567 ncopy = bsize;
555 memcpy(buf, (char *) shf->rp, ncopy);
568 memcpy(buf, shf->rp, ncopy);
556569 shf->rp += ncopy;
557570 shf->rnleft -= ncopy;
558571 buf += ncopy;
584597 shf_getchar(struct shf *shf)
585598 {
586599 if (!(shf->flags & SHF_RD))
587 internal_errorf(Tbad_flags, "shf_getchar", shf->flags);
600 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
601 Tbad_flags, "shf_getchar", shf->flags);
588602
589603 if (shf->rnleft == 0 && (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
590604 return (-1);
600614 shf_ungetc(int c, struct shf *shf)
601615 {
602616 if (!(shf->flags & SHF_RD))
603 internal_errorf(Tbad_flags, "shf_ungetc", shf->flags);
617 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
618 Tbad_flags, "shf_ungetc", shf->flags);
604619
605620 if ((shf->flags & SHF_ERROR) || c == -1 ||
606621 (shf->rp == shf->buf && shf->rnleft))
637652 shf_putchar(int c, struct shf *shf)
638653 {
639654 if (!(shf->flags & SHF_WR))
640 internal_errorf(Tbad_flags, "shf_putchar",shf->flags);
655 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
656 Tbad_flags, "shf_putchar", shf->flags);
641657
642658 if (c == -1)
643659 return (-1);
647663 ssize_t n;
648664
649665 if (shf->fd < 0)
650 internal_errorf(Tf_sD_s, "shf_putchar", "no fd");
666 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_TWOMSG | KWF_NOERRNO,
667 "shf_putchar", "no fd");
651668 if (shf->flags & SHF_ERROR) {
652669 errno = shf->errnosv;
653670 return (-1);
677694 * less if truncated, and -1 if the string could not be written.
678695 */
679696 ssize_t
680 shf_puts(const char *s, struct shf *shf)
697 shf_putsv(const char *s, struct shf *shf)
681698 {
682699 if (!s)
683700 return (-1);
695712 ssize_t n, ncopy, orig_nbytes = nbytes;
696713
697714 if (!(shf->flags & SHF_WR))
698 internal_errorf(Tbad_flags, Tshf_write, shf->flags);
715 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
716 Tbad_flags, Tshf_write, shf->flags);
699717
700718 if (nbytes < 0)
701 internal_errorf(Tbad_buf, Tshf_write, (size_t)buf, nbytes);
719 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
720 Tbad_buf, Tshf_write, (size_t)buf, nbytes);
702721
703722 /* don't buffer if buffer is empty and we're writing a large amount */
704723 if ((ncopy = shf->wnleft) &&
786805 ssize_t n;
787806
788807 if (!buf || bsize <= 0)
789 internal_errorf(Tbad_buf, "shf_snprintf", (size_t)buf, bsize);
808 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
809 Tbad_buf, "shf_snprintf", (size_t)buf, bsize);
790810
791811 shf_sopen(buf, bsize, SHF_WR, &shf);
792812 va_start(args, fmt);
811831 return (shf_sclose(&shf));
812832 }
813833
814 #define FL_HASH 0x001 /* '#' seen */
815 #define FL_PLUS 0x002 /* '+' seen */
816 #define FL_RIGHT 0x004 /* '-' seen */
817 #define FL_BLANK 0x008 /* ' ' seen */
818 #define FL_SHORT 0x010 /* 'h' seen */
819 #define FL_LONG 0x020 /* 'l' seen */
820 #define FL_ZERO 0x040 /* '0' seen */
821 #define FL_DOT 0x080 /* '.' seen */
822 #define FL_UPPER 0x100 /* format character was uppercase */
823 #define FL_NUMBER 0x200 /* a number was formatted %[douxefg] */
824 #define FL_SIZET 0x400 /* 'z' seen */
825 #define FM_SIZES 0x430 /* h/l/z mask */
834 /* pre-initio() */
835 char *
836 kslfmt(ksl number, kui flags, char *numbuf)
837 {
838 if (!IS(flags, FM_TYPE, FL_SGN)) {
839 /* uh-oh, unsigned? what? be bitwise faithful here */
840 union {
841 /*XXX hopefully not UB… */
842 ksl s;
843 kul u;
844 } v;
845
846 v.s = number;
847 return (kulfmt(v.u, flags, numbuf));
848 }
849 if (number < 0)
850 flags |= FL_NEG;
851 return (kulfmt(KSL2NEGUL(number), flags, numbuf));
852 }
853
854 /* pre-initio() */
855 char *
856 kulfmt(kul number, kui flags, char *numbuf)
857 {
858 char *cp;
859
860 cp = numbuf + NUMBUFSZ;
861 *--cp = '\0';
862 switch (flags & FM_TYPE) {
863 case FL_OCT:
864 do {
865 *--cp = digits_lc[number & 07UL];
866 number >>= 3;
867 } while (number);
868
869 if (HAS(flags, FL_HASH) && ord(*cp) != ORD('0'))
870 *--cp = '0';
871 break;
872 case FL_HEX: {
873 const char *digits;
874
875 digits = HAS(flags, FL_UCASE) ? digits_uc : digits_lc;
876 do {
877 *--cp = digits[number & 0xFUL];
878 number >>= 4;
879 } while (number);
880
881 if (HAS(flags, FL_HASH)) {
882 *--cp = IS(flags, FL_UPPER, FL_UPPER) ? 'X' : 'x';
883 *--cp = '0';
884 }
885 break;
886 }
887 default:
888 do {
889 *--cp = digits_lc[number % 10UL];
890 number /= 10UL;
891 } while (number);
892
893 if (!IS(flags, FM_TYPE, FL_DEC)) {
894 if (HAS(flags, FL_NEG))
895 *--cp = '-';
896 else if (HAS(flags, FL_PLUS))
897 *--cp = '+';
898 else if (HAS(flags, FL_BLANK))
899 *--cp = '-';
900 }
901 break;
902 }
903
904 return (cp);
905 }
826906
827907 ssize_t
828908 shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
829909 {
910 char numbuf[NUMBUFSZ];
830911 const char *s;
831 char c, *cp;
912 char c;
832913 int tmp = 0, flags;
833914 size_t field, precision, len;
834 unsigned long lnum;
835 /* %#o produces the longest output */
836 char numbuf[(8 * sizeof(long) + 2) / 3 + 1 + /* NUL */ 1];
837915 /* this stuff for dealing with the buffer */
838916 ssize_t nwritten = 0;
839917 /* for width determination */
9411019 switch (c) {
9421020 case 'd':
9431021 case 'i':
944 if (flags & FL_SIZET)
945 lnum = (long)VA(ssize_t);
946 else if (flags & FL_LONG)
947 lnum = VA(long);
948 else if (flags & FL_SHORT)
949 lnum = (long)(short)VA(int);
950 else
951 lnum = (long)VA(int);
1022 s = kslfmt(HAS(flags, FL_SIZET) ? (ksl)VA(ssize_t) :
1023 HAS(flags, FL_LONG) ? (ksl)VA(long) :
1024 HAS(flags, FL_SHORT) ? (ksl)(short)VA(int) :
1025 (ksl)VA(int), flags | FL_SGN, numbuf);
9521026 goto integral;
9531027
9541028 case 'o':
1029 flags |= FL_OCT;
1030 if (0)
1031 /* FALLTHROUGH */
9551032 case 'u':
1033 flags |= FL_DEC;
1034 if (0)
1035 /* FALLTHROUGH */
9561036 case 'x':
957 if (flags & FL_SIZET)
958 lnum = VA(size_t);
959 else if (flags & FL_LONG)
960 lnum = VA(unsigned long);
961 else if (flags & FL_SHORT)
962 lnum = (unsigned long)(unsigned short)VA(int);
963 else
964 lnum = (unsigned long)VA(unsigned int);
965
1037 flags |= FL_HEX;
1038
1039 s = kulfmt(HAS(flags, FL_SIZET) ? (kul)VA(size_t) :
1040 HAS(flags, FL_LONG) ? (kul)VA(unsigned long) :
1041 HAS(flags, FL_SHORT) ? (kul)(unsigned short)VA(int) :
1042 (kul)VA(unsigned int), flags, numbuf);
9661043 integral:
9671044 flags |= FL_NUMBER;
968 cp = numbuf + sizeof(numbuf);
969 *--cp = '\0';
970
971 switch (c) {
972 case 'd':
973 case 'i':
974 if (0 > (long)lnum) {
975 lnum = -(long)lnum;
976 tmp = 1;
977 } else
978 tmp = 0;
979 /* FALLTHROUGH */
980 case 'u':
981 do {
982 *--cp = digits_lc[lnum % 10];
983 lnum /= 10;
984 } while (lnum);
985
986 if (c != 'u') {
987 if (tmp)
988 *--cp = '-';
989 else if (flags & FL_PLUS)
990 *--cp = '+';
991 else if (flags & FL_BLANK)
992 *--cp = ' ';
993 }
994 break;
995
996 case 'o':
997 do {
998 *--cp = digits_lc[lnum & 0x7];
999 lnum >>= 3;
1000 } while (lnum);
1001
1002 if ((flags & FL_HASH) && *cp != '0')
1003 *--cp = '0';
1004 break;
1005
1006 case 'x': {
1007 const char *digits = (flags & FL_UPPER) ?
1008 digits_uc : digits_lc;
1009 do {
1010 *--cp = digits[lnum & 0xF];
1011 lnum >>= 4;
1012 } while (lnum);
1013
1014 if (flags & FL_HASH) {
1015 *--cp = (flags & FL_UPPER) ? 'X' : 'x';
1016 *--cp = '0';
1017 }
1018 }
1019 }
1020 len = numbuf + sizeof(numbuf) - 1 - (s = cp);
1045 len = NUMBUFLEN(numbuf, s);
10211046 if (flags & FL_DOT) {
10221047 if (precision > len) {
10231048 field = precision;
10301055
10311056 case 's':
10321057 if ((s = VA(const char *)) == NULL)
1033 s = "(null)";
1058 s = Tnil;
10341059 else if (flags & FL_HASH) {
10351060 print_value_quoted(shf, s);
10361061 continue;
10921117 s++;
10931118 nwritten++;
10941119 if (--precision &&
1095 ksh_eq(*s, 'X', 'x')) {
1120 isCh(*s, 'X', 'x')) {
10961121 shf_putc(*s, shf);
10971122 s++;
10981123 precision--;
11381163 }
11391164 #endif
11401165
1141 #ifdef DEBUG
1142 const char *
1143 cstrerror(int errnum)
1144 {
1145 #undef strerror
1146 return (strerror(errnum));
1147 #define strerror dontuse_strerror /* poisoned */
1148 }
1149 #elif !HAVE_STRERROR
1150
1151 #if HAVE_SYS_ERRLIST
1166 #if !HAVE_STRERROR
1167
1168 #if HAVE_STRERRORDESC_NP
1169 /* assume prototype, _GNU_SOURCE may be needed */
1170 #elif HAVE_SYS_ERRLIST
11521171 #if !HAVE_SYS_ERRLIST_DECL
11531172 extern const int sys_nerr;
11541173 extern const char * const sys_errlist[];
11551174 #endif
11561175 #endif
11571176
1177 /* pre-initio() */
11581178 const char *
11591179 cstrerror(int errnum)
11601180 {
1161 /* "Unknown error: " + sign + rough estimate + NUL */
1162 static char errbuf[15 + 1 + (8 * sizeof(int) + 2) / 3 + 1];
1163
1164 #if HAVE_SYS_ERRLIST
1181 #define unkerrstr "Unknown error: "
1182 #define unkerrlen (sizeof(unkerrstr) - 1U)
1183 static char errbuf[unkerrlen + NUMBUFSZ];
1184 #if HAVE_STRERRORDESC_NP
1185 const char *ccp;
1186 #endif
1187 char *cp;
1188
1189 #if HAVE_STRERRORDESC_NP
1190 if ((ccp = strerrordesc_np(errnum)))
1191 return (ccp);
1192 #elif HAVE_SYS_ERRLIST
11651193 if (errnum > 0 && errnum < sys_nerr && sys_errlist[errnum])
11661194 return (sys_errlist[errnum]);
11671195 #endif
11681196
1197 /* do not add ERANGE, might be EOVERFLOW */
11691198 switch (errnum) {
11701199 case 0:
11711200 return ("Undefined error: 0");
11771206 case ESRCH:
11781207 return ("No such process");
11791208 #endif
1180 #ifdef E2BIG
11811209 case E2BIG:
11821210 return ("Argument list too long");
1183 #endif
11841211 case ENOEXEC:
11851212 return ("Exec format error");
11861213 case EBADF:
11951222 return ("File exists");
11961223 case ENOTDIR:
11971224 return ("Not a directory");
1198 #ifdef EINVAL
11991225 case EINVAL:
12001226 return ("Invalid argument");
1201 #endif
12021227 #ifdef ELOOP
12031228 case ELOOP:
12041229 return ("Too many levels of symbolic links");
12051230 #endif
1231 case EOVERFLOW:
1232 return ("Value too large");
12061233 default:
1207 shf_snprintf(errbuf, sizeof(errbuf),
1208 "Unknown error: %d", errnum);
1209 return (errbuf);
1210 }
1234 cp = kslfmt(errnum, FL_SGN, errbuf + unkerrlen);
1235 cp -= unkerrlen;
1236 memcpy(cp, unkerrstr, unkerrlen);
1237 return (cp);
1238 }
1239 #undef unkerrlen
1240 #undef unkerrstr
1241 }
1242 #elif defined(DEBUG)
1243 /* pre-initio() */
1244 const char *
1245 cstrerror(int errnum)
1246 {
1247 #undef strerror
1248 return (strerror(errnum));
1249 #define strerror dontuse_strerror /* poisoned */
12111250 }
12121251 #endif
12131252
12141253 /* fast character classes */
1215 const uint32_t tpl_ctypes[128] = {
1254 const kui tpl_ctypes[128] = {
12161255 /* 0x00 */
12171256 CiNUL, CiCNTRL, CiCNTRL, CiCNTRL,
12181257 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
12631302 static int debug_ccls(void);
12641303 #endif
12651304
1305 /* pre-initio() */
12661306 static void
12671307 set_ccls(void)
12681308 {
12801320 #endif
12811321 }
12821322
1323 /* pre-initio() */
12831324 void
12841325 set_ifs(const char *s)
12851326 {
12941335 }
12951336
12961337 #if defined(MKSH_EBCDIC) || defined(MKSH_FAUX_EBCDIC)
1297 #if !HAVE_SETLOCALE_CTYPE
1338 #if !HAVE_SETLOCALE_LCALL && !defined(MKSH_FAUX_EBCDIC)
12981339 # error EBCDIC support requires use of the system locale
12991340 #endif
13001341 #include <locale.h>
1342
1343 static void ebcdic_initerr(const char *, size_t, int, int, int) MKSH_A_NORETURN;
13011344
13021345 /*
13031346 * Many headaches with EBCDIC:
13381381 * side, but as it's not really used anyway we decided to take the risk.
13391382 */
13401383
1384 /* pre-initio() */
13411385 void
13421386 ebcdic_init(void)
13431387 {
13501394 memset(ebcdic_rtt_fromascii, 0xFF, sizeof(ebcdic_rtt_fromascii));
13511395 setlocale(LC_ALL, "");
13521396 #ifdef MKSH_EBCDIC
1353 if (__etoa_l(ebcdic_rtt_toascii, 256) != 256) {
1354 write(2, "mksh: could not map EBCDIC to ASCII\n", 36);
1355 exit(255);
1356 }
1397 errno = ENOTDIR;
1398 if ((i = __etoa_l(ebcdic_rtt_toascii, 256)) != 256)
1399 ebcdic_initerr(SC("mksh: could not map EBCDIC to ASCII"),
1400 -1, i, errno);
13571401 #endif
13581402
13591403 memset(mapcache, 0, sizeof(mapcache));
13611405 while (i--) {
13621406 t = ebcdic_rtt_toascii[i];
13631407 /* ensure unique round-trip capable mapping */
1364 if (mapcache[t]) {
1365 write(2, "mksh: duplicate EBCDIC to ASCII mapping\n", 40);
1366 exit(255);
1367 }
1408 if (mapcache[t])
1409 ebcdic_initerr(SC("mksh: duplicate EBCDIC to ASCII mapping"),
1410 -2, i, ebcdic_rtt_fromascii[t]);
13681411 /*
13691412 * since there are 256 input octets, this also ensures
13701413 * the other mapping direction is completely filled
13881431 else
13891432 ebcdic_map[i] = (unsigned short)(0x100U | ord(i));
13901433 }
1391 if (ebcdic_rtt_toascii[0] || ebcdic_rtt_fromascii[0] || ebcdic_map[0]) {
1392 write(2, "mksh: NUL not at position 0\n", 28);
1393 exit(255);
1394 }
1434 if (ebcdic_rtt_toascii[0] || ebcdic_rtt_fromascii[0] || ebcdic_map[0])
1435 ebcdic_initerr(SC("mksh: NUL not at position 0"),
1436 ebcdic_rtt_toascii[0], ebcdic_rtt_fromascii[0],
1437 ebcdic_map[0]);
13951438 /* ensure control characters, i.e. 0x00‥0x3F and 0xFF, map sanely */
13961439 for (i = 0x00; i < 0x20; ++i)
13971440 if (!ksh_isctrl(asc2rtt(i)))
13991442 for (i = 0x7F; i < 0xA0; ++i)
14001443 if (!ksh_isctrl(asc2rtt(i))) {
14011444 ebcdic_ctrlmis:
1402 write(2, "mksh: control character mismapping\n", 35);
1403 exit(255);
1445 ebcdic_initerr(SC("mksh: control character mismapping"),
1446 -2, i, asc2rtt(i));
14041447 }
14051448 /* validate character literals used in the code */
1406 if (rtt2asc('\n') != 0x0AU || rtt2asc('\r') != 0x0DU ||
1407 rtt2asc(' ') != 0x20U ||
1408 rtt2asc('!') != 0x21U ||
1409 rtt2asc('"') != 0x22U ||
1410 rtt2asc('#') != 0x23U ||
1411 rtt2asc('$') != 0x24U ||
1412 rtt2asc('%') != 0x25U ||
1413 rtt2asc('&') != 0x26U ||
1414 rtt2asc('\'') != 0x27U ||
1415 rtt2asc('(') != 0x28U ||
1416 rtt2asc(')') != 0x29U ||
1417 rtt2asc('*') != 0x2AU ||
1418 rtt2asc('+') != 0x2BU ||
1419 rtt2asc(',') != 0x2CU ||
1420 rtt2asc('-') != 0x2DU ||
1421 rtt2asc('.') != 0x2EU ||
1422 rtt2asc('/') != 0x2FU ||
1423 rtt2asc('0') != 0x30U ||
1424 rtt2asc(':') != 0x3AU ||
1425 rtt2asc(';') != 0x3BU ||
1426 rtt2asc('<') != 0x3CU ||
1427 rtt2asc('=') != 0x3DU ||
1428 rtt2asc('>') != 0x3EU ||
1429 rtt2asc('?') != 0x3FU ||
1430 rtt2asc('@') != 0x40U ||
1431 rtt2asc('A') != 0x41U ||
1432 rtt2asc('B') != 0x42U ||
1433 rtt2asc('C') != 0x43U ||
1434 rtt2asc('D') != 0x44U ||
1435 rtt2asc('E') != 0x45U ||
1436 rtt2asc('F') != 0x46U ||
1437 rtt2asc('G') != 0x47U ||
1438 rtt2asc('H') != 0x48U ||
1439 rtt2asc('I') != 0x49U ||
1440 rtt2asc('N') != 0x4EU ||
1441 rtt2asc('O') != 0x4FU ||
1442 rtt2asc('P') != 0x50U ||
1443 rtt2asc('Q') != 0x51U ||
1444 rtt2asc('R') != 0x52U ||
1445 rtt2asc('S') != 0x53U ||
1446 rtt2asc('T') != 0x54U ||
1447 rtt2asc('U') != 0x55U ||
1448 rtt2asc('W') != 0x57U ||
1449 rtt2asc('X') != 0x58U ||
1450 rtt2asc('Y') != 0x59U ||
1451 rtt2asc('[') != 0x5BU ||
1452 rtt2asc('\\') != 0x5CU ||
1453 rtt2asc(']') != 0x5DU ||
1454 rtt2asc('^') != 0x5EU ||
1455 rtt2asc('_') != 0x5FU ||
1456 rtt2asc('`') != 0x60U ||
1457 rtt2asc('a') != 0x61U ||
1458 rtt2asc('b') != 0x62U ||
1459 rtt2asc('c') != 0x63U ||
1460 rtt2asc('d') != 0x64U ||
1461 rtt2asc('e') != 0x65U ||
1462 rtt2asc('f') != 0x66U ||
1463 rtt2asc('g') != 0x67U ||
1464 rtt2asc('h') != 0x68U ||
1465 rtt2asc('i') != 0x69U ||
1466 rtt2asc('j') != 0x6AU ||
1467 rtt2asc('k') != 0x6BU ||
1468 rtt2asc('l') != 0x6CU ||
1469 rtt2asc('n') != 0x6EU ||
1470 rtt2asc('p') != 0x70U ||
1471 rtt2asc('r') != 0x72U ||
1472 rtt2asc('s') != 0x73U ||
1473 rtt2asc('t') != 0x74U ||
1474 rtt2asc('u') != 0x75U ||
1475 rtt2asc('v') != 0x76U ||
1476 rtt2asc('w') != 0x77U ||
1477 rtt2asc('x') != 0x78U ||
1478 rtt2asc('y') != 0x79U ||
1479 rtt2asc('{') != 0x7BU ||
1480 rtt2asc('|') != 0x7CU ||
1481 rtt2asc('}') != 0x7DU ||
1482 rtt2asc('~') != 0x7EU) {
1483 write(2, "mksh: compiler vs. runtime codepage mismatch!\n", 46);
1449 #define litcheck(c,v) \
1450 if (rtt2asc(c) != v) \
1451 ebcdic_initerr(SC("mksh: compiler vs. runtime codepage mismatch"), \
1452 -3, c, rtt2asc(c))
1453 litcheck('\n', 0x0AU);
1454 litcheck('\r', 0x0DU);
1455 litcheck(' ', 0x20U);
1456 litcheck('!', 0x21U);
1457 litcheck('"', 0x22U);
1458 litcheck('#', 0x23U);
1459 litcheck('$', 0x24U);
1460 litcheck('%', 0x25U);
1461 litcheck('&', 0x26U);
1462 litcheck('\'', 0x27U);
1463 litcheck('(', 0x28U);
1464 litcheck(')', 0x29U);
1465 litcheck('*', 0x2AU);
1466 litcheck('+', 0x2BU);
1467 litcheck(',', 0x2CU);
1468 litcheck('-', 0x2DU);
1469 litcheck('.', 0x2EU);
1470 litcheck('/', 0x2FU);
1471 litcheck('0', 0x30U);
1472 litcheck(':', 0x3AU);
1473 litcheck(';', 0x3BU);
1474 litcheck('<', 0x3CU);
1475 litcheck('=', 0x3DU);
1476 litcheck('>', 0x3EU);
1477 litcheck('?', 0x3FU);
1478 litcheck('@', 0x40U);
1479 litcheck('A', 0x41U);
1480 litcheck('B', 0x42U);
1481 litcheck('C', 0x43U);
1482 litcheck('D', 0x44U);
1483 litcheck('E', 0x45U);
1484 litcheck('F', 0x46U);
1485 litcheck('G', 0x47U);
1486 litcheck('H', 0x48U);
1487 litcheck('I', 0x49U);
1488 litcheck('N', 0x4EU);
1489 litcheck('O', 0x4FU);
1490 litcheck('P', 0x50U);
1491 litcheck('Q', 0x51U);
1492 litcheck('R', 0x52U);
1493 litcheck('S', 0x53U);
1494 litcheck('T', 0x54U);
1495 litcheck('U', 0x55U);
1496 litcheck('W', 0x57U);
1497 litcheck('X', 0x58U);
1498 litcheck('Y', 0x59U);
1499 litcheck('[', 0x5BU);
1500 litcheck('\\', 0x5CU);
1501 litcheck(']', 0x5DU);
1502 litcheck('^', 0x5EU);
1503 litcheck('_', 0x5FU);
1504 litcheck('`', 0x60U);
1505 litcheck('a', 0x61U);
1506 litcheck('b', 0x62U);
1507 litcheck('c', 0x63U);
1508 litcheck('d', 0x64U);
1509 litcheck('e', 0x65U);
1510 litcheck('f', 0x66U);
1511 litcheck('g', 0x67U);
1512 litcheck('h', 0x68U);
1513 litcheck('i', 0x69U);
1514 litcheck('j', 0x6AU);
1515 litcheck('k', 0x6BU);
1516 litcheck('l', 0x6CU);
1517 litcheck('n', 0x6EU);
1518 litcheck('p', 0x70U);
1519 litcheck('r', 0x72U);
1520 litcheck('s', 0x73U);
1521 litcheck('t', 0x74U);
1522 litcheck('u', 0x75U);
1523 litcheck('v', 0x76U);
1524 litcheck('w', 0x77U);
1525 litcheck('x', 0x78U);
1526 litcheck('y', 0x79U);
1527 litcheck('{', 0x7BU);
1528 litcheck('|', 0x7CU);
1529 litcheck('}', 0x7DU);
1530 litcheck('~', 0x7EU);
1531 #undef litcheck
1532 /* validate sh.h control character literals */
1533 #define ctlcheck(n,c,v) \
1534 if (rtt2asc(c) != v) \
1535 ebcdic_initerr(SC("mksh: control character mismapping"), \
1536 -3, n, rtt2asc(c))
1537 ctlcheck('@', CTRL_AT, 0x00U);
1538 ctlcheck('A', CTRL_A, 0x01U);
1539 ctlcheck('B', CTRL_B, 0x02U);
1540 ctlcheck('C', CTRL_C, 0x03U);
1541 ctlcheck('D', CTRL_D, 0x04U);
1542 ctlcheck('E', CTRL_E, 0x05U);
1543 ctlcheck('F', CTRL_F, 0x06U);
1544 ctlcheck('G', CTRL_G, 0x07U);
1545 ctlcheck('H', CTRL_H, 0x08U);
1546 ctlcheck('I', CTRL_I, 0x09U);
1547 ctlcheck('J', CTRL_J, 0x0AU);
1548 ctlcheck('K', CTRL_K, 0x0BU);
1549 ctlcheck('L', CTRL_L, 0x0CU);
1550 ctlcheck('M', CTRL_M, 0x0DU);
1551 ctlcheck('N', CTRL_N, 0x0EU);
1552 ctlcheck('O', CTRL_O, 0x0FU);
1553 ctlcheck('P', CTRL_P, 0x10U);
1554 ctlcheck('Q', CTRL_Q, 0x11U);
1555 ctlcheck('R', CTRL_R, 0x12U);
1556 ctlcheck('S', CTRL_S, 0x13U);
1557 ctlcheck('T', CTRL_T, 0x14U);
1558 ctlcheck('U', CTRL_U, 0x15U);
1559 ctlcheck('V', CTRL_V, 0x16U);
1560 ctlcheck('W', CTRL_W, 0x17U);
1561 ctlcheck('X', CTRL_X, 0x18U);
1562 ctlcheck('Y', CTRL_Y, 0x19U);
1563 ctlcheck('Z', CTRL_Z, 0x1AU);
1564 ctlcheck('[', CTRL_BO, 0x1BU);
1565 ctlcheck('\\', CTRL_BK, 0x1CU);
1566 ctlcheck(']', CTRL_BC, 0x1DU);
1567 ctlcheck('^', CTRL_CA, 0x1EU);
1568 ctlcheck('_', CTRL_US, 0x1FU);
1569 ctlcheck('?', CTRL_QM, 0x7FU);
1570 #undef ctlcheck
1571 }
1572
1573 /* pre-initio() */
1574 static void
1575 ebcdic_initerr(const char *s, size_t n, int a, int b, int c)
1576 {
1577 char buf[NUMBUFSZ + 3];
1578 char *cp;
1579 const char *ccp;
1580
1581 SHIKATANAI write(2, s, n);
1582 /*
1583 * a>=0: a,b,c=hex
1584 * a=-1: b=sgn c=errno
1585 * a=-2: b=hex c=hex
1586 * a=-3: b=chr c=hex
1587 */
1588 if (a == -1) {
1589 ccp = cstrerror(c);
1590 cp = kslfmt(b, FL_SGN, buf + 1U);
1591 *--cp = '<';
1592 buf[NUMBUFSZ] = '>';
1593 buf[NUMBUFSZ + 1U] = ccp ? '<' : '(';
1594 SHIKATANAI write(2, cp, NUMBUFLEN(buf + 1U, cp) + 2U);
1595 if (ccp) {
1596 SHIKATANAI write(2, SZ(ccp));
1597 SHIKATANAI write(2, SC(">\n"));
1598 } else
1599 SHIKATANAI write(2, SC("unknown error)\n"));
14841600 exit(255);
14851601 }
1486 /* validate sh.h control character literals */
1487 if (rtt2asc(CTRL_AT) != 0x00U ||
1488 rtt2asc(CTRL_A) != 0x01U ||
1489 rtt2asc(CTRL_B) != 0x02U ||
1490 rtt2asc(CTRL_C) != 0x03U ||
1491 rtt2asc(CTRL_D) != 0x04U ||
1492 rtt2asc(CTRL_E) != 0x05U ||
1493 rtt2asc(CTRL_F) != 0x06U ||
1494 rtt2asc(CTRL_G) != 0x07U ||
1495 rtt2asc(CTRL_H) != 0x08U ||
1496 rtt2asc(CTRL_I) != 0x09U ||
1497 rtt2asc(CTRL_J) != 0x0AU ||
1498 rtt2asc(CTRL_K) != 0x0BU ||
1499 rtt2asc(CTRL_L) != 0x0CU ||
1500 rtt2asc(CTRL_M) != 0x0DU ||
1501 rtt2asc(CTRL_N) != 0x0EU ||
1502 rtt2asc(CTRL_O) != 0x0FU ||
1503 rtt2asc(CTRL_P) != 0x10U ||
1504 rtt2asc(CTRL_Q) != 0x11U ||
1505 rtt2asc(CTRL_R) != 0x12U ||
1506 rtt2asc(CTRL_S) != 0x13U ||
1507 rtt2asc(CTRL_T) != 0x14U ||
1508 rtt2asc(CTRL_U) != 0x15U ||
1509 rtt2asc(CTRL_V) != 0x16U ||
1510 rtt2asc(CTRL_W) != 0x17U ||
1511 rtt2asc(CTRL_X) != 0x18U ||
1512 rtt2asc(CTRL_Y) != 0x19U ||
1513 rtt2asc(CTRL_Z) != 0x1AU ||
1514 rtt2asc(CTRL_BO) != 0x1BU ||
1515 rtt2asc(CTRL_BK) != 0x1CU ||
1516 rtt2asc(CTRL_BC) != 0x1DU ||
1517 rtt2asc(CTRL_CA) != 0x1EU ||
1518 rtt2asc(CTRL_US) != 0x1FU ||
1519 rtt2asc(CTRL_QM) != 0x7FU)
1520 goto ebcdic_ctrlmis;
1602 if (a == -3) {
1603 buf[0] = '<';
1604 buf[1] = b;
1605 buf[2] = '>';
1606 SHIKATANAI write(2, buf, 3);
1607 } else {
1608 if (a != -2) {
1609 cp = kslfmt(a, FL_HEX | FL_UCASE | FL_HASH, buf + 1);
1610 *--cp = '<';
1611 buf[NUMBUFSZ] = '>';
1612 SHIKATANAI write(2, cp, NUMBUFLEN(buf + 1U, cp) + 1U);
1613 }
1614 cp = kslfmt(b, FL_HEX | FL_UCASE | FL_HASH, buf + 1);
1615 *--cp = '<';
1616 buf[NUMBUFSZ] = '>';
1617 SHIKATANAI write(2, cp, NUMBUFLEN(buf + 1U, cp) + 1U);
1618 }
1619 cp = kslfmt(c, FL_HEX | FL_UCASE | FL_HASH, buf + 1);
1620 *--cp = '<';
1621 buf[NUMBUFSZ] = '>';
1622 buf[NUMBUFSZ + 1U] = '\n';
1623 SHIKATANAI write(2, cp, NUMBUFLEN(buf + 1U, cp) + 2U);
1624 exit(255);
15211625 }
15221626 #endif
15231627
15281632 * style, or anything really.
15291633 */
15301634
1635 /* pre-initio() */
15311636 static unsigned int
15321637 v(unsigned int c)
15331638 {
15541659
15551660 static struct ciname {
15561661 const char *name;
1557 uint32_t val;
1558 uint32_t bit;
1662 kui val;
1663 kui bit;
15591664 } ci[32], *cibit[32];
15601665
1666 /* pre-initio() */
15611667 static int
15621668 cicomp(const void *a_, const void *b_)
15631669 {
15661672 return (strcmp(a->name, b->name));
15671673 }
15681674
1675 /* pre-initio() */
15691676 static int
15701677 debug_ccls(void)
15711678 {
17101817 z += strlen(#x); \
17111818 } \
17121819 } while (/* CONSTCOND */ 0)
1713 printf("// shf.c {{{ begin\n/* fast character classes */\n");
1714 printf("const uint32_t tpl_ctypes[128] = {\n");
1820 printf("// shf.c begin {{{\n/* fast character classes */\n");
1821 printf("const kui tpl_ctypes[128] = {\n");
17151822 x = 0, y = 0; /* fsck GCC */
17161823 for (i = 0; i <= 0x7F; ++i) {
17171824 if (!(i & 0x0F)) {
17431850 }
17441851 }
17451852 #undef D
1746 printf("};\n// shf.c }}} end\n\n");
1853 printf("};\n// shf.c end }}}\n\n");
17471854
17481855 #define putrangef(len,cond,count) do { \
17491856 for (count = 0; count <= 0xFF; ++count) \
18481955 } while (/* CONSTCOND */ 0)
18491956 DD("??IFS", CiIFS, CiCNTRL);
18501957
1851 printf("// sh.h {{{ begin\n/*\n * fast character classes\n */\n\n");
1958 printf("// sh.h begin {{{\n/*\n * fast character classes\n */\n\n");
18521959 printf("/* internal types, do not reference */\n\n");
18531960
18541961 #define D(x) DD(#x, x, CiIFS)
18591966 printf("/* out of space, but one for *@ would make sense, possibly others */\n\n");
18601967
18611968 printf("/* compile-time initialised, ASCII only */\n"
1862 "extern const uint32_t tpl_ctypes[128];\n"
1969 "extern const kui tpl_ctypes[128];\n"
18631970 "/* run-time, contains C_IFS as well, full 2⁸ octet range */\n"
1864 "EXTERN uint32_t ksh_ctypes[256];\n"
1971 "EXTERN kui ksh_ctypes[256];\n"
18651972 "/* first octet of $IFS, for concatenating \"$*\" */\n"
18661973 "EXTERN char ifs0;\n"
18671974 "\n");
19802087 D(C_TAB, "ASCII horizontal tabulator");
19812088 D(C_UNDER, "underscore");
19822089
1983 printf("// sh.h }}} end\n");
2090 printf("// sh.h end }}}\n");
19842091 return (ksh_ctypes[0] == CiNUL);
19852092 }
19862093 #endif
+293
-11
syn.c less more
2121 * of said person's immediate fault when using the work as intended.
2222 */
2323
24 /* to avoid -Wmissing-format-attribute on vwarnf(), which is no candidate */
25 #define MKSH_SHF_VFPRINTF_NO_GCC_FORMAT_ATTRIBUTE
2426 #include "sh.h"
2527
26 __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.133 2021/10/10 21:36:54 tg Exp $");
28 __RCSID("$MirOS: src/bin/mksh/syn.c,v 1.141 2022/01/06 22:35:04 tg Exp $");
2729
2830 struct nesting_state {
2931 int start_token; /* token than began nesting (eg, FOR) */
6466 static int dbtestp_eval(Test_env *, Test_op, const char *,
6567 const char *, bool);
6668 static void dbtestp_error(Test_env *, int, const char *) MKSH_A_NORETURN;
69
70 static void vwarnf(unsigned int, int, const char *, va_list);
71 #ifndef MKSH_SMALL
72 static void vwarnf0(unsigned int, int, const char *, va_list)
73 MKSH_A_FORMAT(__printf__, 3, 0);
74 #else
75 #define vwarnf0 vwarnf
76 #endif
6777
6878 static struct op *outtree; /* yyparse output */
6979 static struct nesting_state nesting; /* \n changed to ; */
316326 ACCEPT;
317327 if (check_decl_utility) {
318328 struct tbl *tt = get_builtin(ident);
319 uint32_t flag;
329 kui flag;
320330
321331 flag = tt ? tt->flag : 0;
322332 if (flag & DECL_UTIL)
10531063 }
10541064
10551065 #if HAVE_SELECT
1056
1057 #ifndef EOVERFLOW
1058 #ifdef ERANGE
1059 #define EOVERFLOW ERANGE
1060 #else
1061 #define EOVERFLOW EINVAL
1062 #endif
1063 #endif
1064
10651066 bool
10661067 parse_usec(const char *s, struct timeval *tv)
10671068 {
11781179 if (popall)
11791180 goto popnext;
11801181 }
1182
1183 void
1184 yyerror(const char *fmt, ...)
1185 {
1186 va_list ap;
1187
1188 /* pop aliases and re-reads */
1189 while (source->type == SALIAS || source->type == SREREAD)
1190 source = source->next;
1191 /* zap pending input */
1192 source->str = null;
1193
1194 va_start(ap, fmt);
1195 vwarnf0(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE | KWF_NOERRNO,
1196 0, fmt, ap);
1197 va_end(ap);
1198 unwind(LERROR);
1199 }
1200
1201 /* used by error reporting functions to print "ksh: .kshrc[25]: " */
1202 bool
1203 error_prefix(bool fileline)
1204 {
1205 bool kshname_shown = false;
1206
1207 /* Avoid foo: foo[2]: ... */
1208 if (!fileline || !source || !source->file ||
1209 strcmp(source->file, kshname) != 0) {
1210 kshname_shown = true;
1211 shf_puts(kshname + (isch(*kshname, '-') ? 1 : 0), shl_out);
1212 shf_putc_i(':', shl_out);
1213 shf_putc_i(' ', shl_out);
1214 }
1215 if (fileline && source && source->file != NULL) {
1216 shf_fprintf(shl_out, "%s[%d]: ", source->file, source->errline ?
1217 source->errline : source->line);
1218 source->errline = 0;
1219 }
1220 return (kshname_shown);
1221 }
1222
1223 /* error reporting functions */
1224
1225 static void
1226 vwarnf(unsigned int flags, int verrno, const char *fmt, va_list ap)
1227 {
1228 int rept = 0;
1229 bool show_builtin_argv0 = false;
1230
1231 if (HAS(flags, KWF_ERROR)) {
1232 if (HAS(flags, KWF_INTERNAL))
1233 shf_write(SC("internal error: "), shl_out);
1234 else
1235 shf_write(SC("E: "), shl_out);
1236 /* additional things to do on error */
1237 exstat = flags & KWF_EXSTAT;
1238 if (HAS(flags, KWF_INTERNAL) && trap_exstat != -1)
1239 trap_exstat = exstat;
1240 /* debugging: note that stdout not valid */
1241 shl_stdout_ok = false;
1242 } else {
1243 if (HAS(flags, KWF_INTERNAL))
1244 shf_write(SC("internal warning: "), shl_out);
1245 else
1246 shf_write(SC("W: "), shl_out);
1247 }
1248 if (HAS(flags, KWF_BUILTIN) &&
1249 /* not set when main() calls parse_args() */
1250 builtin_argv0 && builtin_argv0 != kshname)
1251 show_builtin_argv0 = true;
1252 if (HAS(flags, KWF_PREFIX) && error_prefix(HAS(flags, KWF_FILELINE)) &&
1253 show_builtin_argv0) {
1254 const char *kshbasename;
1255
1256 kshname_islogin(&kshbasename);
1257 show_builtin_argv0 = strcmp(builtin_argv0, kshbasename) != 0;
1258 }
1259 if (show_builtin_argv0) {
1260 shf_puts(builtin_argv0, shl_out);
1261 shf_putc_i(':', shl_out);
1262 shf_putc_i(' ', shl_out);
1263 }
1264 switch (flags & KWF_MSGMASK) {
1265 default:
1266 #undef shf_vfprintf
1267 shf_vfprintf(shl_out, fmt, ap);
1268 #define shf_vfprintf poisoned_shf_vfprintf
1269 break;
1270 case KWF_THREEMSG:
1271 rept = 2;
1272 if (0)
1273 /* FALLTHROUGH */
1274 case KWF_TWOMSG:
1275 rept = 1;
1276 /* FALLTHROUGH */
1277 case KWF_ONEMSG:
1278 while (/* CONSTCOND */ 1) {
1279 shf_puts(fmt ? fmt : Tnil, shl_out);
1280 if (!rept--)
1281 break;
1282 shf_putc_i(':', shl_out);
1283 shf_putc_i(' ', shl_out);
1284 fmt = va_arg(ap, const char *);
1285 }
1286 break;
1287 }
1288 if (!HAS(flags, KWF_NOERRNO)) {
1289 /* compare shf.c */
1290 #if !HAVE_STRERROR
1291 shf_putc_i(':', shl_out);
1292 shf_putc_i(' ', shl_out);
1293 shf_putsv(cstrerror(verrno), shl_out);
1294 #else
1295 /* may be nil */
1296 shf_fprintf(shl_out, ": %s", cstrerror(verrno));
1297 #endif
1298 }
1299 shf_putc_i('\n', shl_out);
1300 shf_flush(shl_out);
1301 }
1302
1303 #ifndef MKSH_SMALL
1304 static void
1305 vwarnf0(unsigned int flags, int verrno, const char *fmt, va_list ap)
1306 {
1307 return (vwarnf(flags, verrno, fmt, ap));
1308 }
1309 #endif
1310
1311 void
1312 kwarnf(unsigned int flags, ...)
1313 {
1314 const char *fmt;
1315 va_list ap;
1316 int verrno;
1317
1318 verrno = errno;
1319
1320 va_start(ap, flags);
1321 if (HAS(flags, KWF_VERRNO))
1322 verrno = va_arg(ap, int);
1323 fmt = va_arg(ap, const char *);
1324 vwarnf(flags, verrno, fmt, ap);
1325 va_end(ap);
1326 if (HAS(flags, KWF_BIUNWIND))
1327 bi_unwind(0);
1328 }
1329
1330 #ifndef MKSH_SMALL
1331 void
1332 kwarnf0(unsigned int flags, const char *fmt, ...)
1333 {
1334 va_list ap;
1335 int verrno;
1336
1337 verrno = errno;
1338
1339 va_start(ap, fmt);
1340 vwarnf0(flags, verrno, fmt, ap);
1341 va_end(ap);
1342 if (HAS(flags, KWF_BIUNWIND))
1343 bi_unwind(0);
1344 }
1345
1346 void
1347 kwarnf1(unsigned int flags, int verrno, const char *fmt, ...)
1348 {
1349 va_list ap;
1350
1351 va_start(ap, fmt);
1352 vwarnf0(flags, verrno, fmt, ap);
1353 va_end(ap);
1354 if (HAS(flags, KWF_BIUNWIND))
1355 bi_unwind(0);
1356 }
1357 #endif
1358
1359 /* presented by lack of portable variadic macros in early C */
1360
1361 void
1362 kerrf(unsigned int flags, ...)
1363 {
1364 const char *fmt;
1365 va_list ap;
1366 int verrno;
1367
1368 verrno = errno;
1369
1370 va_start(ap, flags);
1371 if (HAS(flags, KWF_VERRNO))
1372 verrno = va_arg(ap, int);
1373 fmt = va_arg(ap, const char *);
1374 vwarnf(flags, verrno, fmt, ap);
1375 va_end(ap);
1376 unwind(LERROR);
1377 }
1378
1379 #ifndef MKSH_SMALL
1380 void
1381 kerrf0(unsigned int flags, const char *fmt, ...)
1382 {
1383 va_list ap;
1384 int verrno;
1385
1386 verrno = errno;
1387
1388 va_start(ap, fmt);
1389 vwarnf0(flags, verrno, fmt, ap);
1390 va_end(ap);
1391 unwind(LERROR);
1392 }
1393
1394 #if 0 /* not used */
1395 void
1396 kerrf1(unsigned int flags, int verrno, const char *fmt, ...)
1397 {
1398 va_list ap;
1399
1400 va_start(ap, fmt);
1401 vwarnf0(flags, verrno, fmt, ap);
1402 va_end(ap);
1403 unwind(LERROR);
1404 }
1405 #endif
1406 #endif
1407
1408 /* maybe error, maybe builtin error; use merrf() macro */
1409 void
1410 merrF(int *ep, unsigned int flags, ...)
1411 {
1412 const char *fmt;
1413 va_list ap;
1414 int verrno;
1415
1416 verrno = errno;
1417
1418 if (ep)
1419 flags |= KWF_BUILTIN;
1420
1421 va_start(ap, flags);
1422 if (HAS(flags, KWF_VERRNO))
1423 verrno = va_arg(ap, int);
1424 fmt = va_arg(ap, const char *);
1425 vwarnf(flags, verrno, fmt, ap);
1426 va_end(ap);
1427
1428 if (ep) {
1429 *ep = exstat;
1430 bi_unwind(0);
1431 } else
1432 unwind(LERROR);
1433 }
1434
1435 /* transform warning into bi_errorf */
1436 void
1437 bi_unwind(int rc)
1438 {
1439 if (rc)
1440 exstat = rc;
1441 /* debugging: note that stdout not valid */
1442 shl_stdout_ok = false;
1443
1444 /* POSIX special builtins cause non-interactive shells to exit */
1445 if (builtin_spec) {
1446 builtin_argv0 = NULL;
1447 /* may not want to use LERROR here */
1448 unwind(LERROR);
1449 }
1450 }
1451
1452 /*XXX old */
1453 void
1454 bi_errorf(const char *fmt, ...)
1455 {
1456 va_list ap;
1457
1458 va_start(ap, fmt);
1459 vwarnf0(/*XXX*/ KWF_BIERR | KWF_NOERRNO, /*XXX*/ 0, fmt, ap);
1460 va_end(ap);
1461 bi_unwind(0);
1462 }
2222
2323 #include "sh.h"
2424
25 __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.111 2021/10/16 02:20:02 tg Exp $");
25 __RCSID("$MirOS: src/bin/mksh/tree.c,v 1.112 2021/11/12 05:06:03 tg Exp $");
2626
2727 #define INDENT 8
2828
183183 fptreef(shf, indent, "%Nesac ");
184184 break;
185185 case TELIF:
186 internal_errorf(TELIF_unexpected);
186 kerrf(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_ONEMSG | KWF_NOERRNO,
187 TELIF_unexpected);
187188 /* FALLTHROUGH */
188189 case TIF:
189190 i = 2;
284285 shf_putc('\n', &ptree_heredoc);
285286 shf_puts(iop->heredoc, &ptree_heredoc);
286287 /* iop->delim is set before iop->heredoc */
287 shf_puts(evalstr(iop->delim, 0), &ptree_heredoc);
288 shf_putsv(evalstr(iop->delim, 0), &ptree_heredoc);
288289 }
289290 ioheredelim:
290291 /* delim is NULL during syntax error printing */
480481 switch ((c = ord(*fmt++))) {
481482 case ORD('s'):
482483 /* string */
483 shf_puts(va_arg(va, char *), shf);
484 shf_putsv(va_arg(va, char *), shf);
484485 break;
485486 case ORD('S'):
486487 /* word */
668669 nest--;
669670 break;
670671 default:
671 internal_warningf(
672 kwarnf0(KWF_INTERNAL | KWF_WARNING | KWF_NOERRNO,
672673 "wdscan: unknown char 0x%X (carrying on)",
673 (unsigned char)wp[-1]);
674 KBI(wp[-1]));
674675 }
675676 }
676677
12491250 ++nesting;
12501251 shf_puts("{tree:" /*}*/, shf);
12511252 if (t == NULL) {
1252 name = "(null)";
1253 name = Tnil;
12531254 goto out;
12541255 }
12551256 dumpioact(shf, t);
22 /*-
33 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
44 * 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
5 * 2019, 2020
5 * 2019, 2020, 2021
66 * mirabilos <m@mirbsd.org>
77 *
88 * Provided that these terms and disclaimer and all copyright notices
2323
2424 #include "sh.h"
2525
26 __RCSID("$MirOS: src/bin/mksh/ulimit.c,v 1.3 2020/07/24 21:08:26 tg Exp $");
26 __RCSID("$MirOS: src/bin/mksh/ulimit.c,v 1.4 2021/11/12 05:06:03 tg Exp $");
2727
2828 #define SOFT 0x1
2929 #define HARD 0x2
231231 /* silently accept */
232232 return 0;
233233 #endif
234 internal_warningf("ulimit: %c", what);
234 kwarnf0(KWF_INTERNAL | KWF_WARNING | KWF_NOERRNO, "ulimit: %c", what);
235235 return (1);
236236 found:
237237 if (wp[builtin_opt.optind]) {
309309 #else
310310 if (l->writable == false) {
311311 /* check.t:ulimit-2 fails if we return 1 and/or do:
312 bi_errorf(Tf_ro, l->name);
312 bi_errorf(Tread_only ": %s", l->name);
313313 */
314314 return (0);
315315 }
+178
-129
var.c less more
22 /*-
33 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
44 * 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
5 * 2019, 2021
5 * 2019, 2021, 2022
66 * mirabilos <m@mirbsd.org>
77 *
88 * Provided that these terms and disclaimer and all copyright notices
3535 #include <sys/ptem.h>
3636 #endif
3737
38 __RCSID("$MirOS: src/bin/mksh/var.c,v 1.252 2021/09/30 03:20:12 tg Exp $");
38 __RCSID("$MirOS: src/bin/mksh/var.c,v 1.264 2022/01/28 10:28:22 tg Exp $");
3939
4040 /*-
4141 * Variables
4848 */
4949
5050 static struct table specials;
51 static uint32_t lcg_state = 5381, qh_state = 4711;
51 static k32 lcg_state = 5381U, qh_state = 4711U;
5252 /* may only be set by typeset() just before call to array_index_calc() */
5353 static enum namerefflag innermost_refflag = SRF_NOP;
5454
6060 mksh_uari_t u;
6161 } mksh_ari_u;
6262
63 static void c_typeset_vardump(struct tbl *, uint32_t, int, int, bool, bool);
64 static void c_typeset_vardump_recursive(struct block *, uint32_t, int, bool,
63 static void c_typeset_vardump(struct tbl *, kui, int, int, bool, bool);
64 static void c_typeset_vardump_recursive(struct block *, kui, int, bool,
6565 bool);
6666 static char *formatstr(struct tbl *, const char *);
6767 static void exportprep(struct tbl *, const char *, size_t);
7272 static void unsetspec(struct tbl *, bool);
7373 static int getint(struct tbl *, mksh_ari_u *, bool);
7474 static int getnum(const char *, mksh_ari_u *, bool, bool);
75 static const char *array_index_calc(const char *, bool *, uint32_t *);
76 static struct tbl *vtypeset(int *, const char *, uint32_t, uint32_t, int, int);
75 static const char *array_index_calc(const char *, bool *, k32 *);
76 static struct tbl *vtypeset(int *, const char *, kui, kui, int, int);
7777
7878 /*
7979 * create a new block for function calls and simple commands
8080 * assume caller has allocated and set up e->loc
8181 */
82 /* pre-initio() */
8283 void
8384 newblock(void)
8485 {
165166
166167 /* common code for several functions below and c_typeset() */
167168 struct block *
168 varsearch(struct block *l, struct tbl **vpp, const char *vn, uint32_t h)
169 varsearch(struct block *l, struct tbl **vpp, const char *vn, k32 h)
169170 {
170171 register struct tbl *vp;
171172
186187
187188 /*
188189 * Used to calculate an array index for global()/local(). Sets *arrayp
189 * to true if this is an array, sets *valp to the array index, returns
190 * to true if this is an array, sets *idxp to the array index, returns
190191 * the basename of the array. May only be called from global()/local()
191192 * and must be their first callee.
192193 */
193194 static const char *
194 array_index_calc(const char *n, bool *arrayp, uint32_t *valp)
195 array_index_calc(const char *n, bool *arrayp, k32 *idxp)
195196 {
196197 const char *p;
197198 size_t len;
200201 *arrayp = false;
201202 redo_from_ref:
202203 p = skip_varname(n, false);
204 if ((size_t)(p - n) > (size_t)(INT_MAX - X_EXTRA))
205 kerrf(KWF_ERR(255) | KWF_PREFIX | KWF_FILELINE | KWF_ONEMSG |
206 KWF_NOERRNO, "parameter name too long");
203207 if (innermost_refflag == SRF_NOP && (p != n) && ctype(n[0], C_ALPHX)) {
204208 struct tbl *vp;
205209 char *vn;
223227
224228 if (p != n && ord(*p) == ORD('[') && (len = array_ref_len(p))) {
225229 char *sub, *tmp;
226 mksh_ari_t rval;
230 mksh_ari_u rval;
227231 size_t tmplen = p - n;
228232
229233 /* calculate the value of the subscript */
233237 memcpy(tmp, p + 1, len);
234238 tmp[len] = '\0';
235239 sub = substitute(tmp, 0);
236 evaluate(sub, &rval, KSH_UNWIND_ERROR, true);
237 *valp = (uint32_t)rval;
240 evaluate(sub, &rval.i, KSH_UNWIND_ERROR, true);
241 *idxp = K32(rval.u);
238242 afree(sub, ATEMP);
239243 memcpy(tmp, n, tmplen);
240244 tmp[tmplen] = '\0';
262266 struct block *l = e->loc;
263267 int c;
264268 bool array;
265 uint32_t h, val;
269 k32 h;
270 k32 idx;
266271
267272 /*
268273 * check to see if this is an array;
269274 * dereference namerefs; must come first
270275 */
271 vn = array_index_calc(n, &array, &val);
276 vn = array_index_calc(n, &array, &idx);
272277 h = hash(vn);
273278 c = (unsigned char)vn[0];
274279 if (!ctype(c, C_ALPHX)) {
275280 if (array)
276 errorf(Tbadsubst);
281 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
282 KWF_ONEMSG | KWF_NOERRNO, Tbadsubst);
277283 vp = vtemp;
278284 vp->flag = DEFINED;
279285 vp->type = 0;
329335 docreate = false;
330336 if (vp != NULL) {
331337 if (array)
332 vp = arraysearch(vp, val);
338 vp = arraysearch(vp, idx);
333339 if (docreate) {
334340 vp->flag |= DEFINED;
335341 if (special(vn))
353359 union mksh_cchack vname;
354360 struct block *l = e->loc;
355361 bool array;
356 uint32_t h, val;
362 k32 h;
363 k32 idx;
357364
358365 /*
359366 * check to see if this is an array;
360367 * dereference namerefs; must come first
361368 */
362 vn = array_index_calc(n, &array, &val);
369 vn = array_index_calc(n, &array, &idx);
363370 h = hash(vn);
364371 if (!ctype(*vn, C_ALPHX)) {
365372 vp = vtemp;
383390 }
384391 }
385392 if (array)
386 vp = arraysearch(vp, val);
393 vp = arraysearch(vp, idx);
387394 vp->flag |= DEFINED;
388395 if (special(vn))
389396 vp->flag |= SPECIAL;
472479
473480 error_ok &= ~0x4;
474481 if ((vq->flag & RDONLY) && !no_ro_check) {
475 warningf(true, Tf_ro, vq->name);
482 kwarnf((error_ok ? KWF_WARNING : KWF_ERR(2)) | KWF_PREFIX |
483 KWF_FILELINE | KWF_TWOMSG | KWF_NOERRNO,
484 Tread_only, vq->name);
476485 if (!error_ok)
477 errorfxz(2);
486 unwind(LERROR);
478487 return (0);
479488 }
480489 if (!(vq->flag&INTEGER)) {
486495 #ifndef MKSH_SMALL
487496 /* debugging */
488497 if (s >= vq->val.s && s < (vq->val.s + cursz)) {
489 internal_errorf(
498 kerrf0(KWF_INTERNAL | KWF_ERR(0xFF) | KWF_NOERRNO,
490499 "setstr: %s=%s: assigning to self",
491500 vq->name, s);
492501 }
542551 if (vp->flag & SPECIAL)
543552 getspec(vp);
544553 /* XXX is it possible for ISSET to be set and val.s to be NULL? */
545 if (!(vp->flag & ISSET) || (!(vp->flag & INTEGER) && vp->val.s == NULL))
554 if (!(vp->flag & ISSET) || (!(vp->flag & INTEGER) && vp->val.s == NULL)) {
555 errno = EINVAL;
546556 return (-1);
557 }
547558 if (vp->flag & INTEGER) {
548559 nump->i = vp->val.i;
549560 return (vp->type);
572583 }
573584
574585 if (c == '0' && arith) {
575 if (ksh_eq(s[0], 'X', 'x')) {
586 if (isCh(s[0], 'X', 'x')) {
576587 /* interpret as hexadecimal */
577588 base = 16;
578589 ++s;
589600 do {
590601 if (c == '#') {
591602 /* ksh-style base determination */
592 if (have_base || num < 1)
603 if (have_base || num < 1) {
604 errno = EINVAL;
593605 return (-1);
606 }
594607 if ((base = num) == 1) {
595608 /* mksh-specific extension */
596609 unsigned int wc;
610623 c = ksh_numuc(c) + 10;
611624 else if (ctype(c, C_LOWER))
612625 c = ksh_numlc(c) + 10;
613 else
626 else {
627 errno = EINVAL;
614628 return (-1);
615 if (c >= base)
629 }
630 if (c >= base) {
631 errno = EINVAL;
616632 return (-1);
633 }
617634 /* handle overflow as truncation */
618635 num = num * base + c;
619636 } while ((c = (unsigned char)*s++));
664681 static char *
665682 formatstr(struct tbl *vp, const char *s)
666683 {
667 int olen, nlen;
668684 char *p, *q;
669 size_t psiz;
670
671 olen = (int)utf_mbswidth(s);
672
673 if (vp->flag & (RJUST|LJUST)) {
685
686 if (vp->flag & (RJUST | LJUST)) {
687 int slen, nlen;
688 size_t psiz;
689
690 psiz = utf_mbswidth(s);
691 if (psiz > (size_t)INT_MAX) {
692 errno = EOVERFLOW;
693 kerrf0(KWF_ERR(0xFF) | KWF_PREFIX | KWF_FILELINE,
694 "string width %zu", psiz);
695 }
696 slen = (int)psiz;
674697 if (!vp->u2.field)
675698 /* default field width */
676 vp->u2.field = olen;
699 vp->u2.field = slen;
677700 nlen = vp->u2.field;
678 } else
679 nlen = olen;
680
681 p = alloc((psiz = nlen * /* MB_LEN_MAX */ 3 + 1), ATEMP);
682 if (vp->flag & (RJUST|LJUST)) {
683 int slen = olen;
701
702 p = alloc2(nlen + 1, /* MB_LEN_MAX */ 4, ATEMP);
703 psiz = ((size_t)nlen + 1U) * 4U;
684704
685705 if (vp->flag & RJUST) {
686706 const char *qq;
728748 vp->u2.field, vp->u2.field, s);
729749 }
730750 } else
731 memcpy(p, s, strlen(s) + 1);
751 strdupx(p, s, ATEMP);
732752
733753 if (vp->flag & UCASEV_AL) {
734754 for (q = p; *q; q++)
766786 * UCASEV_AL), and optionally set its value if an assignment.
767787 */
768788 struct tbl *
769 typeset(const char *var, uint32_t set, uint32_t clr, int field, int base)
789 typeset(const char *var, kui set, kui clr, int field, int base)
770790 {
771791 return (vtypeset(NULL, var, set, clr, field, base));
772792 }
773793 static struct tbl *
774 vtypeset(int *ep, const char *var, uint32_t set, uint32_t clr,
794 vtypeset(int *ep, const char *var, kui set, kui clr,
775795 int field, int base)
776796 {
777797 struct tbl *vp;
802822 }
803823 if (ord(*val) == ORD('[')) {
804824 if (new_refflag != SRF_NOP)
805 return (maybe_errorf(ep, 1, Tf_sD_s, var,
806 "reference variable can't be an array"), NULL);
825 merrf(NULL, (ep, KWF_ERR(1) | KWF_PREFIX |
826 KWF_FILELINE | KWF_TWOMSG | KWF_NOERRNO,
827 var, "reference variable can't be an array"));
807828 len = array_ref_len(val);
808829 if (len < 3)
809830 return (NULL);
861882
862883 /* bail out on 'nameref foo+=bar' */
863884 if (vappend)
864 return (maybe_errorf(ep, 1,
865 "appending not allowed for nameref"), NULL);
885 merrf(NULL, (ep, KWF_ERR(1) | KWF_PREFIX |
886 KWF_FILELINE | KWF_ONEMSG | KWF_NOERRNO,
887 "appending not allowed for nameref"));
866888 /* find value if variable already exists */
867889 if ((qval = val) == NULL) {
868890 varsearch(e->loc, &vp, tvar, hash(tvar));
888910 goto nameref_rhs_checked;
889911 }
890912 nameref_empty:
891 return (maybe_errorf(ep, 1, Tf_sD_s, var,
892 "empty nameref target"), NULL);
913 merrf(NULL, (ep, KWF_ERR(1) | KWF_PREFIX |
914 KWF_FILELINE | KWF_TWOMSG | KWF_NOERRNO,
915 var, "empty nameref target"));
893916 }
894917 len = (ord(*ccp) == ORD('[')) ? array_ref_len(ccp) : 0;
895918 if (ccp[len]) {
898921 * junk after it" and "invalid array"; in the
899922 * latter case, len is also 0 and points to '['
900923 */
901 return (maybe_errorf(ep, 1, Tf_sD_s, qval,
902 "nameref target not a valid parameter name"), NULL);
924 merrf(NULL, (ep, KWF_ERR(1) | KWF_PREFIX |
925 KWF_FILELINE | KWF_TWOMSG | KWF_NOERRNO,
926 qval, "nameref target not a valid parameter name"));
903927 }
904928 nameref_rhs_checked:
905929 /* prevent nameref loops */
906930 while (qval) {
907931 if (!strcmp(qval, tvar))
908 return (maybe_errorf(ep, 1, Tf_sD_s, qval,
909 "expression recurses on parameter"), NULL);
932 merrf(NULL, (ep, KWF_ERR(1) | KWF_PREFIX |
933 KWF_FILELINE | KWF_TWOMSG | KWF_NOERRNO,
934 qval, "expression recurses on parameter"));
910935 varsearch(e->loc, &vp, qval, hash(qval));
911936 qval = NULL;
912937 if (vp && ((vp->flag & (ARRAY | ASSOC)) == ASSOC))
917942 /* prevent typeset from creating a local PATH/ENV/SHELL */
918943 if (Flag(FRESTRICTED) && (strcmp(tvar, TPATH) == 0 ||
919944 strcmp(tvar, TENV) == 0 || strcmp(tvar, TSHELL) == 0))
920 return (maybe_errorf(ep, 1, Tf_sD_s,
921 tvar, "restricted"), NULL);
945 merrf(NULL, (ep, KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
946 KWF_TWOMSG | KWF_NOERRNO, tvar, "restricted"));
922947
923948 innermost_refflag = new_refflag;
924949 vp = (set & LOCAL) ? local(tvar, tobool(set & LOCAL_COPY)) :
952977 vpbase = (vp->flag & ARRAY) ? arraybase(tvar) : vp;
953978
954979 /*
955 * only allow export and readonly flag to be set; AT&T ksh
980 * only allow export and read-only flag to be set; AT&T ksh
956981 * allows any attribute to be changed which means it can be
957982 * truncated or modified (-L/-R/-Z/-i)
958983 */
959984 if ((vpbase->flag & RDONLY) &&
960985 (val || clr || (set & ~(EXPORT | RDONLY))))
961 return (maybe_errorf(ep, 2, Tf_ro, tvar), NULL);
986 merrf(NULL, (ep, KWF_ERR(2) | KWF_PREFIX | KWF_FILELINE |
987 KWF_TWOMSG | KWF_NOERRNO, Tread_only, tvar));
962988 if (tvar != tvarbuf)
963989 afree(tvar, ATEMP);
964990
10391065 }
10401066 }
10411067 if (!ok)
1042 return (maybe_errorf(ep, 1, NULL), NULL);
1068 merrf(NULL, (ep, KWF_ERR(1) | KWF_PREFIX |
1069 KWF_FILELINE | KWF_ONEMSG | KWF_NOERRNO,
1070 "failed to set string value"));
10431071 }
10441072
10451073 if (vappend) {
10641092 if (base > 0)
10651093 vp->type = base;
10661094 } else {
1067 /* setstr can't fail (readonly check already done) */
1095 /* setstr can't fail (read-only check already done) */
10681096 setstr(vp, val, KSH_RETURN_ERROR | 0x4);
10691097 vp->flag |= (set & IMPORT);
10701098 }
12241252 (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) {
12251253 struct block *l2;
12261254 struct tbl *vp2;
1227 uint32_t h = hash(vp->name);
1255 k32 h = hash(vp->name);
12281256
12291257 /* unexport any redefined instances */
12301258 for (l2 = l->next; l2 != NULL; l2 = l2->next) {
13321360
13331361 vp->flag &= ~SPECIAL;
13341362 mksh_TIME(tv);
1335 shf_snprintf(buf, sizeof(buf), "%u.%06u",
1336 (unsigned)tv.tv_sec, (unsigned)tv.tv_usec);
1337 setstr(vp, buf, KSH_RETURN_ERROR | 0x4);
1363 if (vp->flag & INTEGER)
1364 setint(vp, (mksh_ari_t)tv.tv_sec);
1365 else {
1366 shf_snprintf(buf, sizeof(buf), "%u.%06u",
1367 (unsigned)tv.tv_sec, (unsigned)tv.tv_usec);
1368 setstr(vp, buf, KSH_RETURN_ERROR | 0x4);
1369 }
13381370 vp->flag |= SPECIAL;
13391371 return;
13401372 }
14571489 if (getint(vp, &num, false) == -1) {
14581490 s = str_val(vp);
14591491 if (st != V_RANDOM)
1460 errorf(Tf_sD_sD_s, vp->name, Tbadnum, s);
1492 kerrf(KWF_ERR(1) | KWF_PREFIX | KWF_FILELINE |
1493 KWF_THREEMSG | KWF_NOERRNO,
1494 vp->name, Tbadnum, s);
14611495 num.u = hash(s);
14621496 }
14631497 vp->flag |= SPECIAL;
15891623 * vp, indexed by val.
15901624 */
15911625 struct tbl *
1592 arraysearch(struct tbl *vp, uint32_t val)
1626 arraysearch(struct tbl *vp, k32 idx)
15931627 {
15941628 struct tbl *prev, *curr, *news;
15951629 size_t len;
15961630
15971631 vp->flag = (vp->flag | (ARRAY | DEFINED)) & ~ASSOC;
15981632 /* the table entry is always [0] */
1599 if (val == 0)
1633 if (idx == 0)
16001634 return (vp);
16011635 prev = vp;
16021636 curr = vp->u.array;
1603 while (curr && curr->ua.index < val) {
1637 while (curr && curr->ua.index < idx) {
16041638 prev = curr;
16051639 curr = curr->u.array;
16061640 }
1607 if (curr && curr->ua.index == val) {
1641 if (curr && curr->ua.index == idx) {
16081642 if (curr->flag&ISSET)
16091643 return (curr);
16101644 news = curr;
16121646 news = NULL;
16131647 if (!news) {
16141648 len = strlen(vp->name);
1615 checkoktoadd(len, 1 + offsetof(struct tbl, name[0]));
1649 /* no need to checkoktoadd, it comes from a vp->name */
16161650 news = alloc(offsetof(struct tbl, name[0]) + ++len, vp->areap);
16171651 memcpy(news->name, vp->name, len);
16181652 }
16201654 news->type = vp->type;
16211655 news->areap = vp->areap;
16221656 news->u2.field = vp->u2.field;
1623 news->ua.index = val;
1657 news->ua.index = idx;
16241658
16251659 if (curr != news) {
16261660 /* not reusing old array entry */
16961730
16971731 /* Note: AT&T ksh allows set -A but not set +A of a read-only var */
16981732 if ((vp->flag&RDONLY))
1699 errorfx(2, Tf_ro, ccp);
1733 kerrf(KWF_ERR(2) | KWF_PREFIX | KWF_FILELINE | KWF_TWOMSG |
1734 KWF_NOERRNO, Tread_only, ccp);
17001735 /* This code is quite non-optimal */
17011736 if (reset) {
17021737 /* trash existing values and attributes */
17471782 }
17481783 #endif
17491784
1750 vq = arraysearch(vp, j);
1785 vq = arraysearch(vp, K32(j));
17511786 /* would be nice to deal with errors here... (see above) */
17521787 setstr(vq, ccp, KSH_RETURN_ERROR);
17531788 i++;
17601795 void
17611796 change_winsz(void)
17621797 {
1763 struct timeval tv;
1764
1765 mksh_TIME(tv);
1766 BAFHUpdateMem_mem(qh_state, &tv, sizeof(tv));
1767
1798 struct {
1799 struct timeval tv;
17681800 #ifdef TIOCGWINSZ
1769 /* check if window size has changed */
1770 if (tty_init_fd() < 2) {
17711801 struct winsize ws;
1772
1773 if (ioctl(tty_fd, TIOCGWINSZ, &ws) >= 0) {
1774 if (ws.ws_col)
1775 x_cols = ws.ws_col;
1776 if (ws.ws_row)
1777 x_lins = ws.ws_row;
1802 int tif;
1803 int ioc;
1804 int eno;
1805 #endif
1806 } z;
1807
1808 memset(&z, 0, sizeof(z));
1809 mksh_TIME(z.tv);
1810
1811 #ifdef TIOCGWINSZ
1812 if ((z.tif = tty_init_fd()) < 2) {
1813 /* check if window size has changed */
1814 z.ioc = ioctl(tty_fd, TIOCGWINSZ, &z.ws);
1815 z.eno = errno;
1816 if (z.ioc >= 0) {
1817 if (z.ws.ws_col)
1818 x_cols = z.ws.ws_col;
1819 if (z.ws.ws_row)
1820 x_lins = z.ws.ws_row;
17781821 }
17791822 }
17801823 #endif
17851828 if (x_lins < MIN_LINS)
17861829 x_lins = 24;
17871830
1831 rndpush(&z, sizeof(z));
17881832 #ifdef SIGWINCH
17891833 got_winch = 0;
17901834 #endif
17911835 }
17921836
1793 uint32_t
1837 k32
17941838 hash(const void *s)
17951839 {
1796 register uint32_t h;
1840 register k32 h;
17971841
17981842 BAFHInit(h);
1799 BAFHUpdateStr_reg(h, s);
1800 BAFHFinish_reg(h);
1843 BAFHUpdateStr(h, s);
1844 BAFHFinish(h);
18011845 return (h);
18021846 }
18031847
1804 uint32_t
1848 k32
18051849 chvt_rndsetup(const void *bp, size_t sz)
18061850 {
1807 register uint32_t h;
1851 register k32 h;
18081852
18091853 /* use LCG as seed but try to get them to deviate immediately */
18101854 h = lcg_state;
18111855 (void)rndget();
1812 BAFHFinish_reg(h);
1856 BAFHFinish(h);
18131857 /* variation through pid, ppid, and the works */
1814 BAFHUpdateMem_reg(h, &rndsetupstate, sizeof(rndsetupstate));
1858 BAFHUpdateMem(h, &rndsetupstate, sizeof(rndsetupstate));
18151859 /* some variation, some possibly entropy, depending on OE */
1816 BAFHUpdateMem_reg(h, bp, sz);
1860 BAFHUpdateMem(h, bp, sz);
18171861 /* mix them all up */
1818 BAFHFinish_reg(h);
1862 BAFHFinish(h);
18191863
18201864 return (h);
18211865 }
18221866
1823 mksh_ari_t
1867 k32
18241868 rndget(void)
18251869 {
1870 register k32 v = lcg_state;
1871
18261872 /*
18271873 * this is the same Linear Congruential PRNG as Borland
18281874 * C/C++ allegedly uses in its built-in rand() function
18291875 */
1830 return (((lcg_state = 22695477 * lcg_state + 1) >> 16) & 0x7FFF);
1876 v = K32(22695477U * v + 1U);
1877 lcg_state = v;
1878 return ((k32)(v >> 16) & 0x7FFFU);
18311879 }
18321880
18331881 void
18341882 rndset(unsigned long v)
18351883 {
1836 register uint32_t h;
1884 register k32 h;
18371885 #if defined(arc4random_pushb_fast) || defined(MKSH_A4PB)
1838 register uint32_t t;
1886 register k32 t;
18391887 #endif
18401888 struct {
18411889 struct timeval tv;
18421890 void *sp;
1843 uint32_t qh;
1891 k32 qh;
18441892 pid_t pp;
1845 short r;
1893 unsigned short r;
18461894 } z;
18471895
18481896 /* clear the allocated space, for valgrind and to avoid UB */
18491897 memset(&z, 0, sizeof(z));
18501898
18511899 h = lcg_state;
1852 BAFHFinish_reg(h);
1853 BAFHUpdateMem_reg(h, &v, sizeof(v));
1900 BAFHFinish(h);
1901 BAFHUpdateMem(h, &v, sizeof(v));
18541902
18551903 mksh_TIME(z.tv);
1856 z.sp = &lcg_state;
1904 z.sp = &z;
18571905 z.pp = procpid;
1858 z.r = (short)rndget();
1906 z.r = rndget();
18591907
18601908 #if defined(arc4random_pushb_fast) || defined(MKSH_A4PB)
1861 t = qh_state;
1862 BAFHFinish_reg(t);
1863 z.qh = (t & 0xFFFF8000) | rndget();
1864 lcg_state = (t << 15) | rndget();
1909 z.qh = (qh_state & 0xFFFF8000U) | rndget();
1910 lcg_state = K32(qh_state << 15) | rndget();
18651911 /*
18661912 * either we have very chap entropy get and push available,
18671913 * with malloc() pulling in this code already anyway, or the
18681914 * user requested us to use the old functions
18691915 */
18701916 t = h;
1871 BAFHUpdateMem_reg(t, &lcg_state, sizeof(lcg_state));
1872 BAFHFinish_reg(t);
1917 BAFHUpdateMem(t, &lcg_state, sizeof(lcg_state));
1918 BAFHFinish(t);
18731919 lcg_state = t;
18741920 #if defined(arc4random_pushb_fast)
18751921 arc4random_pushb_fast(&lcg_state, sizeof(lcg_state));
18771923 #else
18781924 lcg_state = arc4random_pushb(&lcg_state, sizeof(lcg_state));
18791925 #endif
1880 BAFHUpdateMem_reg(h, &lcg_state, sizeof(lcg_state));
1926 BAFHUpdateMem(h, &lcg_state, sizeof(lcg_state));
18811927 #else
18821928 z.qh = qh_state;
18831929 #endif
18841930
1885 BAFHUpdateMem_reg(h, &z, sizeof(z));
1886 BAFHFinish_reg(h);
1931 BAFHUpdateMem(h, &z, sizeof(z));
1932 BAFHFinish(h);
18871933 lcg_state = h;
18881934 }
18891935
18901936 void
1891 rndpush(const void *s)
1892 {
1893 register uint32_t h = qh_state;
1894
1895 BAFHUpdateStr_reg(h, s);
1896 BAFHUpdateOctet_reg(h, 0);
1937 rndpush(const void *s, size_t n)
1938 {
1939 register k32 h = qh_state;
1940
1941 BAFHUpdateMem(h, s, n);
1942 BAFHFinish(h);
18971943 qh_state = h;
18981944 }
18991945
19141960 c_typeset(const char **wp)
19151961 {
19161962 struct tbl *vp, **p;
1917 uint32_t fset = 0, fclr = 0, flag;
1963 kui fset = 0, fclr = 0, flag;
19181964 int thing = 0, field = 0, base = 0, i;
19191965 struct block *l;
19201966 const char *opts;
20422088 }
20432089
20442090 if (fieldstr && !getn(fieldstr, &field)) {
2045 bi_errorf(Tf_sD_s, Tbadnum, fieldstr);
2091 kwarnf(KWF_BIERR | KWF_TWOMSG, Tbadnum, fieldstr);
20462092 return (1);
20472093 }
20482094 if (basestr) {
20492095 if (!getn(basestr, &base)) {
2050 bi_errorf(Tf_sD_s, "bad integer base", basestr);
2096 kwarnf(KWF_BIERR | KWF_TWOMSG,
2097 "bad integer base", basestr);
20512098 return (1);
20522099 }
20532100 if (base < 1 || base > 36)
20642111
20652112 if (func && (((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT)) ||
20662113 new_refflag != SRF_NOP)) {
2067 bi_errorf("only -t, -u and -x options may be used with -f");
2114 kwarnf(KWF_BIERR | KWF_ONEMSG | KWF_NOERRNO,
2115 "only -t, -u and -x options may be used with -f");
20682116 return (1);
20692117 }
20702118 if (wp[builtin_opt.optind]) {
21332181 field, base)) {
21342182 if (x)
21352183 return (x);
2136 bi_errorf(Tf_sD_s, wp[i], Tnot_ident);
2184 kwarnf(KWF_BIERR | KWF_TWOMSG | KWF_NOERRNO,
2185 wp[i], Tnot_ident);
21372186 return (1);
21382187 }
21392188 }
21702219 }
21712220
21722221 static void
2173 c_typeset_vardump_recursive(struct block *l, uint32_t flag, int thing,
2222 c_typeset_vardump_recursive(struct block *l, kui flag, int thing,
21742223 bool pflag, bool istset)
21752224 {
21762225 struct tbl **blockvars, *vp;
21842233 }
21852234
21862235 static void
2187 c_typeset_vardump(struct tbl *vp, uint32_t flag, int thing, int any_set,
2236 c_typeset_vardump(struct tbl *vp, kui flag, int thing, int any_set,
21882237 bool pflag, bool istset)
21892238 {
21902239 struct tbl *tvp;
22732322 }
22742323 shf_puts(vp->name, shl_stdout);
22752324 if (any_set)
2276 shprintf("[%lu]", arrayindex(vp));
2325 shprintf(Tf_SQlu, arrayindex(vp));
22772326 if ((!thing && !flag && pflag) ||
22782327 (thing == '-' && (vp->flag & ISSET))) {
22792328 shf_putc('=', shl_stdout);